v0.16.0
Loading...
Searching...
No Matches
EshelbianContact.cpp
Go to the documentation of this file.
1/**
2 * @file EshelbianContact.cpp
3 * @brief
4 * @date 2023-05-13
5 *
6 * @copyright Copyright (c) 2023
7 *
8 */
9
10#define SINGULARITY
11#include <MoFEM.hpp>
12using namespace MoFEM;
13
15
17
18namespace ContactOps {
19
22using BoundaryEleOp = BoundaryEle::UserDataOperator;
24
27
28double cn_contact = 1;
31double scale = 1;
32
33double airplane_ray_distance = 1; // thi is point from which plane send ray.
34 // This is multiple of elem radius.
35
36} // namespace ContactOps
37
38#ifdef ENABLE_PYTHON_BINDING
39#include <boost/python.hpp>
40#include <boost/python/def.hpp>
41#include <boost/python/numpy.hpp>
42namespace bp = boost::python;
43namespace np = boost::python::numpy;
44#endif
45
46#include <ContactOps.hpp>
47
48#include <EshelbianContact.hpp>
49
50extern "C" {
51void tricircumcenter3d_tp(double a[3], double b[3], double c[3],
52 double circumcenter[3], double *xi, double *eta);
53}
54
55namespace EshelbianPlasticity {
56
57#ifdef ENABLE_PYTHON_BINDING
58struct ContactSDFPython : public ContactOps::SDFPython {
59 using ContactOps::SDFPython::SDFPython;
60};
61#else
63#endif
64
65boost::shared_ptr<ContactSDFPython> setupContactSdf() {
66 boost::shared_ptr<ContactSDFPython> sdf_python_ptr;
67
68#ifdef ENABLE_PYTHON_BINDING
69
70 auto file_exists = [](std::string myfile) {
71 std::ifstream file(myfile.c_str());
72 if (file) {
73 return true;
74 }
75 return false;
76 };
77
78 char sdf_file_name[255] = "sdf.py";
79 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-sdf_file",
80 sdf_file_name, 255, PETSC_NULLPTR);
81
82 if (file_exists(sdf_file_name)) {
83 MOFEM_LOG("EP", Sev::inform) << sdf_file_name << " file found";
84 sdf_python_ptr = boost::make_shared<ContactSDFPython>();
85 CHKERR sdf_python_ptr->sdfInit(sdf_file_name);
86 ContactOps::sdfPythonWeakPtr = sdf_python_ptr;
87 MOFEM_LOG("EP", Sev::inform) << "SdfPython initialized";
88 } else {
89 MOFEM_LOG("EP", Sev::warning) << sdf_file_name << " file NOT found";
90 }
91
92#endif // ENABLE_PYTHON_BINDING
93
94 return sdf_python_ptr;
95};
96
98 : public PostProcBrokenMeshInMoabBase<FaceElementForcesAndSourcesCore> {
99
102
104 boost::shared_ptr<moab::Core> core_mesh_ptr, int max_order,
105 std::map<int, Range> &&body_map);
107 if (treeSurfPtr) {
108 treeSurfPtr->delete_tree(rootSetSurf);
109 }
110 }
113 inline boost::shared_ptr<OrientedBoxTreeTool> &getTreeSurfPtr() {
114 return treeSurfPtr;
115 }
116 inline auto getRootSetSurf() { return rootSetSurf; }
117 int getMaxLevel() const { return refElementsMap.at(MBTRI)->defMaxLevel; }
118
119 friend struct OpMoveNode;
120 friend struct OpTreeSearch;
121
122 struct FaceData {
123 int gaussPtNb; //< integration points number
124 std::array<double, 3> slavePoint;
125 std::array<double, 3> masterPoint;
126 std::array<double, 3> rayPoint;
127 std::array<double, 3> unitRay;
128 double eleRadius;
129
130 // std::vector<int> dofsSlaveIds;
131 // std::vector<double> dofsSlaveCoeff;
132 // std::vector<double> baseSlaveFuncs;
133
134 std::array<double, 9> masterPointNodes;
135 std::array<double, 9> masterTractionNodes;
136 std::array<double, 9> slavePointNodes;
137 std::array<double, 9> slaveTractionNodes;
138
139 FaceData() = default;
140 };
141
142 using MapFaceData = std::map<EntityHandle, std::vector<FaceData>>;
143
144 inline auto findFaceDataVecPtr(EntityHandle fe_ent) {
145 auto &map_face_data = shadowDataMap;
146 auto it = map_face_data.find(fe_ent);
147 if (it == map_face_data.end()) {
148 return (std::vector<FaceData> *)nullptr;
149 }
150 return &(it->second);
151 }
152
153 inline auto getFaceDataPtr(std::vector<FaceData>::iterator &it, int gg,
154 std::vector<FaceData> *vec_ptr) {
155 FaceData *face_data_ptr = nullptr;
156 if (it != vec_ptr->end()) {
157 if (it->gaussPtNb == gg) {
158 face_data_ptr = &(*it);
159 ++it;
160 }
161 }
162 return face_data_ptr;
163 }
164
165protected:
167 boost::shared_ptr<OrientedBoxTreeTool> treeSurfPtr;
169
171 // Tag thCoeff;
172 // Tag thIds;
173 // Tag thBases;
178
180
181 std::map<int, Range> bodyMap;
182
183 const int maxOrder;
184};
185
186auto checkSdf(EntityHandle fe_ent, std::map<int, Range> &sdf_map_range) {
187 for (auto &m_sdf : sdf_map_range) {
188 if (m_sdf.second.find(fe_ent) != m_sdf.second.end())
189 return m_sdf.first;
190 }
191 return -1;
192}
193
194template <typename OP_PTR>
195auto getSdf(OP_PTR op_ptr, MatrixDouble &contact_disp, int block_id,
196 bool eval_hessian) {
197
198 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
199
200 auto ts_time = op_ptr->getTStime();
201 auto ts_time_step = op_ptr->getTStimeStep();
204 ts_time_step = EshelbianCore::physicalDt;
205 }
206
207 auto m_spatial_coords = ContactOps::get_spatial_coords(
208 op_ptr->getFTensor1CoordsAtGaussPts(),
209 getFTensor1FromMat<3>(contact_disp), nb_gauss_pts);
210 auto m_normals_at_pts = ContactOps::get_normalize_normals(
211 op_ptr->getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
213 ts_time_step, ts_time, nb_gauss_pts, m_spatial_coords, m_normals_at_pts,
214 block_id);
216 ts_time_step, ts_time, nb_gauss_pts, m_spatial_coords, m_normals_at_pts,
217 block_id);
218
219#ifndef NDEBUG
220 if (v_sdf.size() != nb_gauss_pts)
222 "Wrong number of integration pts");
223 if (m_grad_sdf.size1() != nb_gauss_pts)
225 "Wrong number of integration pts");
226 if (m_grad_sdf.size2() != 3)
227 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Should be size of 3");
228#endif // NDEBUG
229
230 if (eval_hessian) {
232 ts_time_step, ts_time, nb_gauss_pts, m_spatial_coords, m_normals_at_pts,
233 block_id);
234 return std::make_tuple(block_id, m_normals_at_pts, v_sdf, m_grad_sdf,
235 m_hess_sdf);
236 } else {
237
238 return std::make_tuple(block_id, m_normals_at_pts, v_sdf, m_grad_sdf,
239 MatrixDouble(6, nb_gauss_pts, 0.));
240 }
241};
242
243/**
244 * @brief Calculate points data on contact surfaces
245 *
246 * @tparam T1
247 * @param unit_ray
248 * @param point
249 * @param elem_point_nodes
250 * @param elem_traction_nodes
251 * @param t_spatial_coords
252 * @return auto
253 */
254template <typename T1>
256
257 std::array<double, 3> &unit_ray, std::array<double, 3> &point,
258
259 std::array<double, 9> &elem_point_nodes,
260 std::array<double, 9> &elem_traction_nodes,
261
262 FTensor::Tensor1<T1, 3> &t_spatial_coords) {
263 FTensor::Index<'i', 3> i;
264
265 auto t_unit_ray = getFTensor1FromPtr<3>(unit_ray.data());
266 auto t_point = getFTensor1FromPtr<3>(point.data());
267
268 auto get_normal = [](auto &ele_coords) {
270 Tools::getTriNormal(ele_coords.data(), &t_normal(0));
271 return t_normal;
272 };
273
274 auto t_normal = get_normal(elem_point_nodes);
275 t_normal(i) /= t_normal.l2();
276
277 auto sn = t_normal(i) * t_point(i);
278 auto nm = t_normal(i) * t_spatial_coords(i);
279 auto nr = t_normal(i) * t_unit_ray(i);
280
281 auto gamma = (sn - nm) / nr;
282
283 FTensor::Tensor1<T1, 3> t_point_current;
284 t_point_current(i) = t_spatial_coords(i) + gamma * t_unit_ray(i);
285
286 auto get_local_point_shape_functions = [&](auto &&t_elem_coords,
287 auto &t_point) {
288 std::array<T1, 2> loc_coords;
291 &t_elem_coords(0, 0), &t_point(0), 1, loc_coords.data()),
292 "get local coords");
293 return FTensor::Tensor1<T1, 3>{N_MBTRI0(loc_coords[0], loc_coords[1]),
294 N_MBTRI1(loc_coords[0], loc_coords[1]),
295 N_MBTRI2(loc_coords[0], loc_coords[1])};
296 };
297
298 auto eval_position = [&](auto &&t_field, auto &t_shape_fun) {
299 FTensor::Index<'i', 3> i;
300 FTensor::Index<'j', 3> j;
301 FTensor::Tensor1<T1, 3> t_point_out;
302 t_point_out(i) = t_shape_fun(j) * t_field(j, i);
303 return t_point_out;
304 };
305
306 auto t_shape_fun = get_local_point_shape_functions(
307 getFTensor2FromPtr<3, 3>(elem_point_nodes.data()), t_point_current);
308 auto t_slave_point_updated = eval_position(
309 getFTensor2FromPtr<3, 3>(elem_point_nodes.data()), t_shape_fun);
310 auto t_traction_updated = eval_position(
311 getFTensor2FromPtr<3, 3>(elem_traction_nodes.data()), t_shape_fun);
312
313 return std::make_tuple(t_slave_point_updated, t_traction_updated, t_normal);
314};
315
316template <typename T1>
318
319 ContactTree::FaceData *face_data_ptr,
320 FTensor::Tensor1<T1, 3> &t_spatial_coords
321
322) {
323
324 return multiPoint(face_data_ptr->unitRay, face_data_ptr->masterPoint,
325 face_data_ptr->masterPointNodes,
326 face_data_ptr->masterTractionNodes, t_spatial_coords);
327};
328
329template <typename T1>
331
332 ContactTree::FaceData *face_data_ptr,
333 FTensor::Tensor1<T1, 3> &t_spatial_coords
334
335) {
336
337 return multiPoint(face_data_ptr->unitRay, face_data_ptr->slavePoint,
338 face_data_ptr->slavePointNodes,
339 face_data_ptr->slaveTractionNodes, t_spatial_coords);
340};
341
342/**
343 * Evaluate gap and tractions between master and slave points
344 */
345template <typename T1>
347 FTensor::Tensor1<T1, 3> &t_spatial_coords) {
348
349 auto [t_slave_point_current, t_slave_traction_current, t_slave_normal] =
350 multiSlavePoint(face_data_ptr, t_spatial_coords);
351 auto [t_master_point_current, t_master_traction_current, t_master_normal] =
352 multiMasterPoint(face_data_ptr, t_spatial_coords);
353
354 FTensor::Index<'i', 3> i;
355
357 t_normal(i) = t_master_normal(i) - t_slave_normal(i);
358 t_normal.normalize();
359
360 auto gap = t_normal(i) * (t_slave_point_current(i) - t_spatial_coords(i));
361 auto tn_master = t_master_traction_current(i) * t_normal(i);
362 auto tn_slave = t_slave_traction_current(i) * t_normal(i);
363 auto tn = std::max(-tn_master, tn_slave);
364
365 return std::make_tuple(gap, tn_master, tn_slave,
366 ContactOps::constrain(gap, tn),
367 t_master_traction_current, t_slave_traction_current);
368};
369
371
372/** Caluclate rhs term for contact
373 */
374template <typename T1, typename T2, typename T3>
376
377 ContactTree::FaceData *face_data_ptr, FTensor::Tensor1<T1, 3> &t_coords,
378 FTensor::Tensor1<T2, 3> &t_spatial_coords,
380 bool debug = false
381
382) {
383 FTensor::Index<'i', 3> i;
384 FTensor::Index<'j', 3> j;
385
387 t_u(i) = t_spatial_coords(i) - t_coords(i);
388
390
391 switch (type) {
393
394 auto [t_slave_point_current, t_slave_traction_current, t_slave_normal] =
395 multiSlavePoint(face_data_ptr, t_spatial_coords);
396 auto [t_master_point_current, t_master_traction_current, t_master_normal] =
397 multiMasterPoint(face_data_ptr, t_spatial_coords);
398
399 // average normal surface
401 t_normal(i) = t_master_normal(i) - t_slave_normal(i);
402 t_normal.normalize();
403
404 // get projection operators
406 t_P(i, j) = t_normal(i) * t_normal(j);
408 t_Q(i, j) = kronecker_delta(i, j) - t_P(i, j);
409
410 constexpr double beta = 0.5;
411
412 auto zeta = 1e-8 * face_data_ptr->eleRadius;
415
416 // this is regularised std::min(d,s)
417 auto f_min_gap = [zeta](auto d, auto s) {
418 return 0.5 * (d + s - std::sqrt((d - s) * (d - s) + zeta));
419 };
420 // this derivative of regularised std::min(d,s)
421 auto f_diff_min_gap = [zeta](auto d, auto s) {
422 return 0.5 * (1 - (d - s) / std::sqrt((d - s) * (d - s) + zeta));
423 };
424
425 // add penalty on penetration side
426 auto f_barrier = [alpha1, alpha2, f_min_gap, f_diff_min_gap](auto g,
427 auto tn) {
428 auto d = alpha1 * g;
429 auto b1 =
430 0.5 * (tn + f_min_gap(d, tn) + f_diff_min_gap(d, tn) * (d - tn));
431 auto b2 = alpha2 * f_min_gap(g, 0) * g;
432 return b1 - b2;
433 };
434
435 FTensor::Tensor1<T2, 3> t_gap_vec;
436 t_gap_vec(i) = beta * t_spatial_coords(i) +
437 (1 - beta) * t_slave_point_current(i) - t_spatial_coords(i);
439 t_traction_vec(i) =
440 -beta * t_master_traction(i) + (beta - 1) * t_slave_traction_current(i);
441
442 auto t_gap = t_normal(i) * t_gap_vec(i);
443 auto t_tn = t_normal(i) * t_traction_vec(i);
444 auto barrier = f_barrier(t_gap, t_tn);
445
447 // add penalty on penetration side
448 t_traction_bar(i) = t_normal(i) * barrier;
449
450 t_rhs(i) =
451
452 t_Q(i, j) * t_master_traction(j) +
453
454 t_P(i, j) * (t_master_traction(j) - t_traction_bar(j));
455
456 if (debug) {
457 auto is_nan_or_inf = [](double value) -> bool {
458 return std::isnan(value) || std::isinf(value);
459 };
460
461 double v = std::complex<double>(t_rhs(i) * t_rhs(i)).real();
462 if (is_nan_or_inf(v)) {
463 MOFEM_LOG_CHANNEL("SELF");
464 MOFEM_LOG("SELF", Sev::error) << "t_rhs " << t_rhs;
465 CHK_MOAB_THROW(MOFEM_DATA_INCONSISTENCY, "rhs is nan or inf");
466 }
467 }
468
469 } break;
472 break;
473 }
474
475 return t_rhs;
476};
477
480 const std::string row_field_name,
481 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
482 boost::shared_ptr<ContactTree> contact_tree_ptr,
483 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr = nullptr);
484
486
487private:
488 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
489 boost::shared_ptr<ContactTree> contactTreePtr;
490 boost::shared_ptr<std::map<int, Range>> sdfMapRangePtr;
491};
492
494 const std::string row_field_name,
495 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
496 boost::shared_ptr<ContactTree> contact_tree_ptr,
497 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr)
498 : ContactOps::AssemblyBoundaryEleOp(row_field_name, row_field_name,
499 ContactOps::BoundaryEleOp::OPROW),
500 commonDataPtr(common_data_ptr), contactTreePtr(contact_tree_ptr),
501 sdfMapRangePtr(sdf_map_range_ptr) {
502 CHK_THROW_MESSAGE(PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn",
504 PETSC_NULLPTR),
505 "get cn failed");
508 PetscOptionsGetScalar(PETSC_NULLPTR, "", "-alpha_contact_const",
509 &ContactOps::alpha_contact_const, PETSC_NULLPTR),
510 "get alpha contact failed");
512 PETSC_NULLPTR, "", "-alpha_contact_quadratic",
514 "get alpha contact failed");
516 PetscOptionsGetScalar(PETSC_NULLPTR, "", "-airplane_ray_distance",
517 &ContactOps::airplane_ray_distance, PETSC_NULLPTR),
518 "get alpha contact failed");
519
520 MOFEM_LOG("EP", Sev::inform) << "cn " << ContactOps::cn_contact;
521 MOFEM_LOG("EP", Sev::inform)
522 << "alpha_contact_const " << ContactOps::alpha_contact_const;
523 MOFEM_LOG("EP", Sev::inform)
524 << "alpha_contact_quadratic " << ContactOps::alpha_contact_quadratic;
525 MOFEM_LOG("EP", Sev::inform)
526 << "airplane_ray_distance " << ContactOps::airplane_ray_distance;
527}
528
532
533 FTensor::Index<'i', 3> i;
534 FTensor::Index<'j', 3> j;
535 FTensor::Index<'k', 3> k;
536 FTensor::Index<'l', 3> l;
537
538 const size_t nb_gauss_pts = getGaussPts().size2();
539
540#ifndef NDEBUG
541 if (commonDataPtr->contactDisp.size1() != nb_gauss_pts) {
542 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
543 "Wrong number of integration pts %ld != %ld",
544 commonDataPtr->contactDisp.size1(), nb_gauss_pts);
545 }
546#endif // !NDEBUG
547
548 auto &nf = locF;
549 locF.clear();
550
551 auto t_w = getFTensor0IntegrationWeight();
552 auto t_coords = getFTensor1CoordsAtGaussPts();
553 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
554 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
555
556 // placeholder to pass boundary block id to python. default SDF is set on
557 // block = -1, one can choose different block by making block "CONTACT_SDF",
558 // then specific SDF can be set to that block.
559 auto [block_id, m_normals_at_pts, v_sdf, m_grad_sdf, m_hess_sdf] =
560 getSdf(this, commonDataPtr->contactDisp,
561 checkSdf(getFEEntityHandle(), *sdfMapRangePtr), false);
562
563 auto t_sdf_v = getFTensor0FromVec(v_sdf);
564 auto t_grad_sdf_v = getFTensor1FromMat<3>(m_grad_sdf);
565 auto t_normalize_normal = getFTensor1FromMat<3>(m_normals_at_pts);
566
567 auto next = [&]() {
568 ++t_w;
569 ++t_coords;
570 ++t_disp;
571 ++t_traction;
572 ++t_normalize_normal;
573 ++t_sdf_v;
574 ++t_grad_sdf_v;
575 };
576
577 auto face_data_vec_ptr =
578 contactTreePtr->findFaceDataVecPtr(getFEEntityHandle());
579 auto face_gauss_pts_it = face_data_vec_ptr->begin();
580
581 auto nb_base_functions = data.getN().size2();
582 auto t_base = data.getFTensor0N();
583 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
584
586 auto face_data_ptr = contactTreePtr->getFaceDataPtr(face_gauss_pts_it, gg,
587 face_data_vec_ptr);
588
589 auto check_face_contact = [&]() {
590 if (checkSdf(getFEEntityHandle(), *sdfMapRangePtr) != -1)
591 return false;
592
593 if (face_data_ptr) {
594 return true;
595 }
596 return false;
597 };
598
599#ifdef ENABLE_PYTHON_BINDING
600 double c = 0.;
601 if (ContactOps::sdfPythonWeakPtr.lock()) {
602 auto tn = t_traction(i) * t_grad_sdf_v(i);
603 c = ContactOps::constrain(t_sdf_v, tn);
604 }
605#else
606 constexpr double c = 0;
607#endif
608
609 if (!c && check_face_contact()) {
610 FTensor::Tensor1<double, 3> t_spatial_coords;
611 t_spatial_coords(i) = t_coords(i) + t_disp(i);
612 auto t_rhs_tmp = multiPointRhs(face_data_ptr, t_coords, t_spatial_coords,
613 t_traction, MultiPointRhsType::U, true);
614 t_rhs(i) = t_rhs_tmp(i);
615
616 } else {
617
618#ifdef ENABLE_PYTHON_BINDING
619 auto inv_cn = 1. / ContactOps::cn_contact;
620
621 if (ContactOps::sdfPythonWeakPtr.lock()) {
623 t_cP(i, j) = (c * t_grad_sdf_v(i)) * t_grad_sdf_v(j);
624 t_cQ(i, j) = kronecker_delta(i, j) - t_cP(i, j);
625 t_rhs(i) = t_cQ(i, j) * t_traction(j) +
626 (c * inv_cn * t_sdf_v) * t_grad_sdf_v(i);
627 } else {
628 t_rhs(i) = t_traction(i);
629 }
630#else
631 t_rhs(i) = t_traction(i);
632#endif
633 }
634
635 auto t_nf = getFTensor1FromPtr<3>(&nf[0]);
636 const double alpha = t_w * getMeasure();
637
638 size_t bb = 0;
639 for (; bb != nbRows / 3; ++bb) {
640 const double beta = alpha * t_base;
641 t_nf(i) -= beta * t_rhs(i);
642 ++t_nf;
643 ++t_base;
644 }
645 for (; bb < nb_base_functions; ++bb)
646 ++t_base;
647
648 next();
649 }
650
652}
653
654template <AssemblyType A, IntegrationType I> struct OpConstrainBoundaryHDivRhs;
655
656template <AssemblyType A>
658 : public FormsIntegrators<FaceUserDataOperator>::Assembly<A>::OpBrokenBase {
659
662
664 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
665 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
666 boost::shared_ptr<ContactTree> contact_tree_ptr);
667
668 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
669
670private:
671 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
672 boost::shared_ptr<ContactTree> contactTreePtr;
673};
674
675template <AssemblyType A>
678 boost::shared_ptr<std::vector<BrokenBaseSideData>>
679 broken_base_side_data,
680 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
681 boost::shared_ptr<ContactTree> contact_tree_ptr)
682 : OP(broken_base_side_data), commonDataPtr(common_data_ptr),
683 contactTreePtr(contact_tree_ptr) {}
684
685template <AssemblyType A>
689
694
695 const size_t nb_gauss_pts = OP::getGaussPts().size2();
696
697#ifndef NDEBUG
698 if (commonDataPtr->contactDisp.size1() != nb_gauss_pts) {
699 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
700 "Wrong number of integration pts %ld != %ld",
701 commonDataPtr->contactDisp.size1(), nb_gauss_pts);
702 }
703#endif // !NDEBUG
704
705 auto &nf = OP::locF;
706 OP::locF.clear();
707
708 auto t_w = OP::getFTensor0IntegrationWeight();
709 auto t_material_normal = OP::getFTensor1NormalsAtGaussPts();
710 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
711
712 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
713 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
714
715 auto next = [&]() {
716 ++t_w;
717 ++t_disp;
718 ++t_traction;
719 ++t_coords;
720 ++t_material_normal;
721 };
722
723 auto face_data_vec_ptr =
724 contactTreePtr->findFaceDataVecPtr(OP::getFEEntityHandle());
725 auto face_gauss_pts_it = face_data_vec_ptr->begin();
726
727 auto nb_base_functions = data.getN().size2() / 3;
728 auto t_base = data.getFTensor1N<3>();
729 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
730
731 auto t_nf = getFTensor1FromPtr<3>(&nf[0]);
732 const double alpha = t_w / 2.;
733
734 size_t bb = 0;
735 for (; bb != OP::nbRows / 3; ++bb) {
736 const double beta = alpha * t_base(i) * t_material_normal(i);
737 t_nf(i) += beta * t_disp(i);
738 ++t_nf;
739 ++t_base;
740 }
741 for (; bb < nb_base_functions; ++bb)
742 ++t_base;
743
744 next();
745 }
746
748}
749
751
753 const std::string row_field_name, const std::string col_field_name,
754 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
755 boost::shared_ptr<ContactTree> contact_tree_ptr,
756 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr = nullptr);
757
760
761private:
762 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
763 boost::shared_ptr<ContactTree> contactTreePtr;
764 boost::shared_ptr<std::map<int, Range>> sdfMapRangePtr;
765};
766
768 const std::string row_field_name, const std::string col_field_name,
769 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
770 boost::shared_ptr<ContactTree> contact_tree_ptr,
771 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr)
772 : ContactOps::AssemblyBoundaryEleOp(row_field_name, col_field_name,
773 ContactOps::BoundaryEleOp::OPROWCOL),
774 commonDataPtr(common_data_ptr), contactTreePtr(contact_tree_ptr),
775 sdfMapRangePtr(sdf_map_range_ptr) {
776
777 sYmm = false;
778}
779
782 EntitiesFieldData::EntData &col_data) {
784
785 using namespace ContactOps;
786
787 FTensor::Index<'i', 3> i;
788 FTensor::Index<'j', 3> j;
789 FTensor::Index<'k', 3> k;
790
791 auto nb_rows = row_data.getIndices().size();
792 auto nb_cols = col_data.getIndices().size();
793
794 auto &locMat = AssemblyBoundaryEleOp::locMat;
795 locMat.resize(nb_rows, nb_cols, false);
796 locMat.clear();
797
798 if (nb_cols && nb_rows) {
799
800 auto nb_gauss_pts = getGaussPts().size2();
801 auto t_w = getFTensor0IntegrationWeight();
802 auto t_coords = getFTensor1CoordsAtGaussPts();
803 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
804 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
805
806 // placeholder to pass boundary block id to python
807 auto [block_id, m_normals_at_pts, v_sdf, m_grad_sdf, m_hess_sdf] =
808 getSdf(this, commonDataPtr->contactDisp,
809 checkSdf(getFEEntityHandle(), *sdfMapRangePtr), true);
810
811 auto t_sdf_v = getFTensor0FromVec(v_sdf);
812 auto t_grad_sdf_v = getFTensor1FromMat<3>(m_grad_sdf);
813 auto t_hess_sdf_v = getFTensor2SymmetricFromMat<3>(m_hess_sdf);
814 auto t_normalized_normal = getFTensor1FromMat<3>(m_normals_at_pts);
815
816 auto next = [&]() {
817 ++t_w;
818 ++t_coords;
819 ++t_disp;
820 ++t_traction;
821 ++t_sdf_v;
822 ++t_grad_sdf_v;
823 ++t_hess_sdf_v;
824 ++t_normalized_normal;
825 };
826
827 auto face_data_vec_ptr =
828 contactTreePtr->findFaceDataVecPtr(getFEEntityHandle());
829 auto face_gauss_pts_it = face_data_vec_ptr->begin();
830
831 auto t_row_base = row_data.getFTensor0N();
832 auto nb_face_functions = row_data.getN().size2() / 3;
833 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
834
835 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
836
837 auto face_data_ptr = contactTreePtr->getFaceDataPtr(face_gauss_pts_it, gg,
838 face_data_vec_ptr);
839
840 auto check_face_contact = [&]() {
841 if (checkSdf(getFEEntityHandle(), *sdfMapRangePtr) != -1)
842 return false;
843
844 if (face_data_ptr) {
845 return true;
846 }
847 return false;
848 };
849
851
852#ifdef ENABLE_PYTHON_BINDING
853 double c = 0.;
854 if (ContactOps::sdfPythonWeakPtr.lock()) {
855 auto tn = t_traction(i) * t_grad_sdf_v(i);
856 c = ContactOps::constrain(t_sdf_v, tn);
857 }
858#else
859 constexpr double c = 0;
860#endif
861
862 if (!c && check_face_contact()) {
863 FTensor::Tensor1<double, 3> t_spatial_coords;
864 t_spatial_coords(i) = t_coords(i) + t_disp(i);
865 constexpr double eps = std::numeric_limits<float>::epsilon();
866 for (auto ii = 0; ii < 3; ++ii) {
867 FTensor::Tensor1<std::complex<double>, 3> t_spatial_coords_cx{
868 t_spatial_coords(0), t_spatial_coords(1), t_spatial_coords(2)};
869 t_spatial_coords_cx(ii) += eps * 1i;
870 auto t_rhs_tmp =
871 multiPointRhs(face_data_ptr, t_coords, t_spatial_coords_cx,
872 t_traction, MultiPointRhsType::U);
873 for (int jj = 0; jj != 3; ++jj) {
874 auto v = t_rhs_tmp(jj).imag();
875 t_res_dU(jj, ii) = v / eps;
876 }
877 }
878
879 } else {
880
881#ifdef ENABLE_PYTHON_BINDING
882
883 if (ContactOps::sdfPythonWeakPtr.lock()) {
884 auto inv_cn = 1. / ContactOps::cn_contact;
885 t_res_dU(i, j) =
886
887 (-c) * (t_hess_sdf_v(i, j) * t_grad_sdf_v(k) * t_traction(k) +
888 t_grad_sdf_v(i) * t_hess_sdf_v(k, j) * t_traction(k))
889
890 + (c * inv_cn) * (t_sdf_v * t_hess_sdf_v(i, j) +
891
892 t_grad_sdf_v(j) * t_grad_sdf_v(i));
893 } else {
894 t_res_dU(i, j) = 0;
895 }
896#else
897 t_res_dU(i, j) = 0;
898#endif
899 }
900
901 auto alpha = t_w * getMeasure();
902
903 size_t rr = 0;
904 for (; rr != nb_rows / 3; ++rr) {
905
906 auto t_mat = getFTensor2FromArray<3, 3, 3>(locMat, 3 * rr);
907 auto t_col_base = col_data.getFTensor0N(gg, 0);
908
909 for (size_t cc = 0; cc != nb_cols / 3; ++cc) {
910 auto beta = alpha * t_row_base * t_col_base;
911 t_mat(i, j) -= beta * t_res_dU(i, j);
912 ++t_col_base;
913 ++t_mat;
914 }
915
916 ++t_row_base;
917 }
918 for (; rr < nb_face_functions; ++rr)
919 ++t_row_base;
920
921 next();
922 }
923 }
924
926}
927
928template <AssemblyType A, IntegrationType I> struct OpConstrainBoundaryL2Lhs_dP;
929
930template <AssemblyType A>
932 : public FormsIntegrators<FaceUserDataOperator>::Assembly<A>::OpBrokenBase {
933
936
938 std::string row_field_name,
939 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
940 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
941 boost::shared_ptr<ContactTree> contact_tree_ptr,
942 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr = nullptr);
943
944 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
946
947private:
948 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
949 boost::shared_ptr<ContactTree> contactTreePtr;
950 boost::shared_ptr<std::map<int, Range>> sdfMapRangePtr;
951};
952
953template <AssemblyType A>
956 std::string row_field_name,
957 boost::shared_ptr<std::vector<BrokenBaseSideData>>
958 broken_base_side_data,
959 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
960 boost::shared_ptr<ContactTree> contact_tree_ptr,
961 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr)
962 : OP(row_field_name, broken_base_side_data, false, false),
963 commonDataPtr(common_data_ptr), contactTreePtr(contact_tree_ptr),
964 sdfMapRangePtr(sdf_map_range_ptr) {
965 OP::sYmm = false;
966}
967
968template <AssemblyType A>
972 EntitiesFieldData::EntData &col_data) {
974
975 using namespace ContactOps;
976
977 FTensor::Index<'i', 3> i;
978 FTensor::Index<'j', 3> j;
979 FTensor::Index<'k', 3> k;
980
981 auto nb_rows = row_data.getIndices().size();
982 auto nb_cols = col_data.getIndices().size();
983
984 auto &locMat = AssemblyBoundaryEleOp::locMat;
985 locMat.resize(nb_rows, nb_cols, false);
986 locMat.clear();
987
988 if (nb_cols && nb_rows) {
989
990 const size_t nb_gauss_pts = OP::getGaussPts().size2();
991
992 auto t_w = OP::getFTensor0IntegrationWeight();
993 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
994 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
995 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
996 auto t_material_normal = OP::getFTensor1NormalsAtGaussPts();
997
998 // placeholder to pass boundary block id to python
999 auto [block_id, m_normals_at_pts, v_sdf, m_grad_sdf, m_hess_sdf] =
1000 getSdf(this, commonDataPtr->contactDisp,
1001 checkSdf(OP::getFEEntityHandle(), *sdfMapRangePtr), false);
1002
1003 auto t_sdf_v = getFTensor0FromVec(v_sdf);
1004 auto t_grad_sdf_v = getFTensor1FromMat<3>(m_grad_sdf);
1005
1006 auto next = [&]() {
1007 ++t_w;
1008 ++t_disp;
1009 ++t_traction;
1010 ++t_coords;
1011 ++t_material_normal;
1012 ++t_sdf_v;
1013 ++t_grad_sdf_v;
1014 };
1015
1016 auto face_data_vec_ptr =
1017 contactTreePtr->findFaceDataVecPtr(OP::getFEEntityHandle());
1018 auto face_gauss_pts_it = face_data_vec_ptr->begin();
1019
1020 auto t_row_base = row_data.getFTensor0N();
1021 auto nb_face_functions = row_data.getN().size2();
1022
1023 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
1024
1025 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1026
1027 auto face_data_ptr = contactTreePtr->getFaceDataPtr(face_gauss_pts_it, gg,
1028 face_data_vec_ptr);
1029
1030 auto check_face_contact = [&]() {
1031 if (checkSdf(OP::getFEEntityHandle(), *sdfMapRangePtr) != -1)
1032 return false;
1033
1034 if (face_data_ptr) {
1035 return true;
1036 }
1037 return false;
1038 };
1039
1041
1042#ifdef ENABLE_PYTHON_BINDING
1043 double c = 0.;
1044 if (ContactOps::sdfPythonWeakPtr.lock()) {
1045 auto tn = t_traction(i) * t_grad_sdf_v(i);
1046 c = ContactOps::constrain(t_sdf_v, tn);
1047 }
1048#else
1049 constexpr double c = 0;
1050#endif
1051
1052 if (!c && check_face_contact()) {
1053 FTensor::Tensor1<double, 3> t_spatial_coords;
1054 t_spatial_coords(i) = t_coords(i) + t_disp(i);
1055 constexpr double eps = std::numeric_limits<float>::epsilon();
1056 for (auto ii = 0; ii != 3; ++ii) {
1057 FTensor::Tensor1<std::complex<double>, 3> t_traction_cx{
1058 t_traction(0), t_traction(1), t_traction(2)};
1059 t_traction_cx(ii) += eps * 1i;
1060 auto t_rhs_tmp =
1061 multiPointRhs(face_data_ptr, t_coords, t_spatial_coords,
1062 t_traction_cx, MultiPointRhsType::U);
1063 for (int jj = 0; jj != 3; ++jj) {
1064 auto v = t_rhs_tmp(jj).imag();
1065 t_res_dP(jj, ii) = v / eps;
1066 }
1067 }
1068 } else {
1069
1070#ifdef ENABLE_PYTHON_BINDING
1071 if (ContactOps::sdfPythonWeakPtr.lock()) {
1073 t_cP(i, j) = (c * t_grad_sdf_v(i)) * t_grad_sdf_v(j);
1074 t_cQ(i, j) = kronecker_delta(i, j) - t_cP(i, j);
1075 t_res_dP(i, j) = t_cQ(i, j);
1076 } else {
1077 t_res_dP(i, j) = t_kd(i, j);
1078 }
1079#else
1080 t_res_dP(i, j) = t_kd(i, j);
1081#endif
1082 }
1083
1084 const double alpha = t_w / 2.;
1085 size_t rr = 0;
1086 for (; rr != nb_rows / 3; ++rr) {
1087
1088 auto t_mat = getFTensor2FromArray<3, 3, 3>(locMat, 3 * rr);
1089 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1090
1091 for (size_t cc = 0; cc != nb_cols / 3; ++cc) {
1092 auto col_base = t_col_base(i) * t_material_normal(i);
1093 const double beta = alpha * t_row_base * col_base;
1094 t_mat(i, j) -= beta * t_res_dP(i, j);
1095 ++t_col_base;
1096 ++t_mat;
1097 }
1098
1099 ++t_row_base;
1100 }
1101 for (; rr < nb_face_functions; ++rr)
1102 ++t_row_base;
1103
1104 next();
1105 }
1106 }
1107
1109}
1110
1111template <AssemblyType A, IntegrationType I>
1113
1114template <AssemblyType A>
1116 : public FormsIntegrators<FaceUserDataOperator>::Assembly<A>::OpBrokenBase {
1117
1120
1122 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
1123 std::string col_field_name,
1124 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
1125 boost::shared_ptr<ContactTree> contact_tree_ptr);
1126
1127 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
1128 EntitiesFieldData::EntData &col_data);
1129
1130private:
1131 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
1132 boost::shared_ptr<ContactTree> contactTreePtr;
1133};
1134
1135template <AssemblyType A>
1138 boost::shared_ptr<std::vector<BrokenBaseSideData>>
1139 broken_base_side_data,
1140 std::string col_field_name,
1141 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
1142 boost::shared_ptr<ContactTree> contact_tree_ptr)
1143 : OP(col_field_name, broken_base_side_data, true, true),
1144 commonDataPtr(common_data_ptr), contactTreePtr(contact_tree_ptr) {
1145 OP::sYmm = false;
1146}
1147
1148template <AssemblyType A>
1152 EntitiesFieldData::EntData &row_data) {
1154
1155 // Note: col_data and row_data are swapped in this function, we going to
1156 // transpose locMat at the end
1157
1158 using namespace ContactOps;
1159
1163
1164 auto nb_rows = row_data.getIndices().size();
1165 auto nb_cols = col_data.getIndices().size();
1166
1167 auto &locMat = AssemblyBoundaryEleOp::locMat;
1168 locMat.resize(nb_rows, nb_cols, false);
1169 locMat.clear();
1170
1171 if (nb_cols && nb_rows) {
1172
1173 const size_t nb_gauss_pts = OP::getGaussPts().size2();
1174
1175 auto t_w = OP::getFTensor0IntegrationWeight();
1176 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
1177 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
1178 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1179 auto t_material_normal = OP::getFTensor1NormalsAtGaussPts();
1180
1181 auto next = [&]() {
1182 ++t_w;
1183 ++t_disp;
1184 ++t_traction;
1185 ++t_coords;
1186 ++t_material_normal;
1187 };
1188
1189 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
1190
1191 auto face_data_vec_ptr =
1192 contactTreePtr->findFaceDataVecPtr(OP::getFEEntityHandle());
1193 auto face_gauss_pts_it = face_data_vec_ptr->begin();
1194
1195 auto t_row_base = row_data.getFTensor1N<3>();
1196 auto nb_face_functions = row_data.getN().size2() / 3;
1197 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1198
1199 const auto alpha = t_w / 2.;
1200
1201 size_t rr = 0;
1202 for (; rr != nb_rows / 3; ++rr) {
1203
1204 auto row_base = alpha * (t_row_base(i) * t_material_normal(i));
1205
1206 auto t_mat = getFTensor2FromArray<3, 3, 3>(locMat, 3 * rr);
1207 auto t_col_base = col_data.getFTensor0N(gg, 0);
1208
1209 for (size_t cc = 0; cc != nb_cols / 3; ++cc) {
1210 const auto beta = row_base * t_col_base;
1211 t_mat(i, j) += beta * t_kd(i, j);
1212 ++t_col_base;
1213 ++t_mat;
1214 }
1215
1216 ++t_row_base;
1217 }
1218 for (; rr < nb_face_functions; ++rr)
1219 ++t_row_base;
1220
1221 next();
1222 }
1223 }
1224
1225 locMat = trans(locMat);
1226
1228}
1229
1231 boost::shared_ptr<moab::Core> core_mesh_ptr,
1232 int max_order, std::map<int, Range> &&body_map)
1233 : Base(m_field, core_mesh_ptr, "contact"), maxOrder(max_order),
1234 bodyMap(body_map) {
1235
1236 auto ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBTRI>>();
1237 ref_ele_ptr->hoNodes =
1238 PETSC_FALSE; ///< So far only linear geometry is implemented for contact
1239
1240 CHK_THROW_MESSAGE(ref_ele_ptr->getOptions(optionsPrefix), "getOptions");
1241 CHK_THROW_MESSAGE(ref_ele_ptr->generateReferenceElementMesh(),
1242 "Error when generating reference element");
1243
1244 MOFEM_LOG("EP", Sev::inform) << "Contact hoNodes " << ref_ele_ptr->hoNodes
1245 ? "true"
1246 : "false";
1247 MOFEM_LOG("EP", Sev::inform)
1248 << "Contact maxOrder " << ref_ele_ptr->defMaxLevel;
1249
1250 refElementsMap[MBTRI] = ref_ele_ptr;
1251
1252 int def_ele_id = -1;
1253 CHKERR getPostProcMesh().tag_get_handle("ELE_ID", 1, MB_TYPE_INTEGER, thEleId,
1254 MB_TAG_CREAT | MB_TAG_DENSE,
1255 &def_ele_id);
1256 CHKERR getPostProcMesh().tag_get_handle("BODY_ID", 1, MB_TYPE_INTEGER,
1257 thBodyId, MB_TAG_CREAT | MB_TAG_DENSE,
1258 &def_ele_id);
1259
1260 // std::vector<int> def_ids(3 * nb_bases, 0);
1261 // CHKERR getPostProcMesh().tag_get_handle("IDS", 3 * nb_bases,
1262 // MB_TYPE_INTEGER,
1263 // thIds, MB_TAG_CREAT | MB_TAG_DENSE,
1264 // &*def_ids.begin());
1265 // std::vector<double> def_coeffs(3 * nb_bases, 0);
1266 // CHKERR getPostProcMesh().tag_get_handle("COEFF", 3 * nb_bases,
1267 // MB_TYPE_DOUBLE,
1268 // thCoeff, MB_TAG_CREAT |
1269 // MB_TAG_DENSE,
1270 // &*def_coeffs.begin());
1271 // std::vector<double> def_basses(nb_bases, 0);
1272 // CHKERR getPostProcMesh().tag_get_handle("BASES", nb_bases, MB_TYPE_DOUBLE,
1273 // thBases, MB_TAG_CREAT |
1274 // MB_TAG_DENSE,
1275 // &*def_basses.begin());
1276
1277 std::array<double, 3> def_small_x{0., 0., 0.};
1278 CHKERR getPostProcMesh().tag_get_handle("x", 3, MB_TYPE_DOUBLE, thSmallX,
1279 MB_TAG_CREAT | MB_TAG_DENSE,
1280 def_small_x.data());
1281 CHKERR getPostProcMesh().tag_get_handle("X", 3, MB_TYPE_DOUBLE, thLargeX,
1282 MB_TAG_CREAT | MB_TAG_DENSE,
1283 def_small_x.data());
1284
1285 std::array<double, 3> def_tractions{0., 0., 0.};
1286 CHKERR getPostProcMesh().tag_get_handle(
1287 "TRACTION", 3, MB_TYPE_DOUBLE, thTraction, MB_TAG_CREAT | MB_TAG_DENSE,
1288 &*def_tractions.begin());
1289}
1290
1296
1299
1301 shadowDataMap.clear();
1302
1303 PetscBarrier(nullptr);
1304
1305 auto pcomm_post_proc_mesh = this->getPostProcMeshPcommPtr();
1306 if (pcomm_post_proc_mesh == nullptr)
1307 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY, "PComm not allocated");
1308
1309 auto brodacts = [&](auto &brodacts_ents) {
1311 Range recived_ents;
1312 for (auto rr = 0; rr != mField.get_comm_size(); ++rr) {
1313 pcomm_post_proc_mesh->broadcast_entities(
1314 rr, rr == mField.get_comm_rank() ? brodacts_ents : recived_ents,
1315 false, true);
1316 }
1318 };
1319
1320 Range brodacts_ents;
1321 CHKERR getPostProcMesh().get_entities_by_dimension(0, 2, brodacts_ents, true);
1322 CHKERR brodacts(brodacts_ents);
1323
1324 Range ents;
1325 CHKERR getPostProcMesh().get_entities_by_dimension(0, 2, ents, true);
1326 CHKERR buildTree(ents);
1327
1328#ifndef NDEBUG
1329 CHKERR writeFile("debug_tree.h5m");
1330#endif // NDEBUG
1331
1333}
1334
1337 // MOFEM_LOG("SELF", Sev::inform) << ents << endl;
1338 if (treeSurfPtr) {
1339 treeSurfPtr->delete_tree(rootSetSurf);
1340 }
1341 treeSurfPtr = boost::shared_ptr<OrientedBoxTreeTool>(
1342 new OrientedBoxTreeTool(&getPostProcMesh(), "ROOTSETSURF", true));
1343 CHKERR treeSurfPtr->build(ents, rootSetSurf);
1344 // CHKERR treeSurfPtr->stats(rootSetSurf, std::cerr);
1346}
1347
1349
1351
1352 OpMoveNode(boost::shared_ptr<ContactTree> contact_tree_ptr,
1353 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
1354 boost::shared_ptr<MatrixDouble> u_h1_ptr);
1355 MoFEMErrorCode doWork(int side, EntityType type,
1357
1358protected:
1359 boost::weak_ptr<ContactTree> contactTreePtr;
1360 boost::shared_ptr<MatrixDouble> uH1Ptr;
1361 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
1362};
1363
1365 boost::shared_ptr<ContactTree> contact_tree_ptr,
1366 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
1367 boost::shared_ptr<MatrixDouble> u_h1_ptr)
1368 : UOP(NOSPACE, UOP::OPSPACE), contactTreePtr(contact_tree_ptr),
1369 uH1Ptr(u_h1_ptr), commonDataPtr(common_data_ptr) {}
1370
1374
1375 if (auto contact_tree_ptr = contactTreePtr.lock()) {
1376
1377 auto get_body_id = [&](auto fe_ent) {
1378 for (auto &m : contact_tree_ptr->bodyMap) {
1379 if (m.second.find(fe_ent) != m.second.end()) {
1380 return m.first;
1381 }
1382 }
1383 return -1;
1384 };
1385
1386 auto &moab_post_proc_mesh = contact_tree_ptr->getPostProcMesh();
1387 auto &post_proc_ents = contact_tree_ptr->getPostProcElements();
1388
1389 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1390 auto fe_id = id_from_handle(fe_ent);
1391 auto body_id = get_body_id(fe_ent);
1392 auto &map_gauss_pts = contact_tree_ptr->getMapGaussPts();
1393
1394 CHKERR moab_post_proc_mesh.tag_clear_data(contact_tree_ptr->thEleId,
1395 post_proc_ents, &fe_id);
1396 CHKERR moab_post_proc_mesh.tag_clear_data(contact_tree_ptr->thBodyId,
1397 post_proc_ents, &body_id);
1398
1399 auto nb_gauss_pts = getGaussPts().size2();
1400 auto t_u_h1 = getFTensor1FromMat<3>(*uH1Ptr);
1401 auto t_u_l2 = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
1402 auto t_coords = getFTensor1CoordsAtGaussPts();
1403
1404 MatrixDouble x_h1(nb_gauss_pts, 3);
1405 auto t_x_h1 = getFTensor1FromPtr<3>(&x_h1(0, 0));
1406 MatrixDouble x_l2(nb_gauss_pts, 3);
1407 auto t_x_l2 = getFTensor1FromPtr<3>(&x_l2(0, 0));
1408 MatrixDouble tractions = trans(commonDataPtr->contactTraction);
1409 MatrixDouble coords = getCoordsAtGaussPts();
1410
1411 FTensor::Index<'i', 3> i;
1412
1413 // VectorDouble bases(nb_bases, 0);
1414 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
1415 t_x_h1(i) = t_coords(i) + t_u_h1(i);
1416 t_x_l2(i) = t_coords(i) + t_u_l2(i);
1417
1418 ++t_coords;
1419 ++t_u_h1;
1420 ++t_u_l2;
1421 ++t_x_h1;
1422 ++t_x_l2;
1423 }
1424
1425 CHKERR moab_post_proc_mesh.set_coords(
1426 &*map_gauss_pts.begin(), map_gauss_pts.size(), &*x_h1.data().begin());
1427 CHKERR moab_post_proc_mesh.tag_set_data(
1428 contact_tree_ptr->thSmallX, &*map_gauss_pts.begin(),
1429 map_gauss_pts.size(), &*x_h1.data().begin());
1430 CHKERR moab_post_proc_mesh.tag_set_data(
1431 contact_tree_ptr->thLargeX, &*map_gauss_pts.begin(),
1432 map_gauss_pts.size(), &*coords.data().begin());
1433 CHKERR moab_post_proc_mesh.tag_set_data(
1434 contact_tree_ptr->thTraction, &*map_gauss_pts.begin(),
1435 map_gauss_pts.size(), &*tractions.data().begin());
1436
1437 } else {
1438 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1439 "ContactTree pointer expired in OpMoveNode");
1440 }
1441
1443}
1444
1446
1448
1449 OpTreeSearch(boost::shared_ptr<ContactTree> contact_tree_ptr,
1450 boost::shared_ptr<MatrixDouble> u_h1_ptr,
1451 boost::shared_ptr<MatrixDouble> traction_ptr, Range r,
1452
1453 moab::Interface *post_proc_mesh_ptr,
1454 std::vector<EntityHandle> *map_gauss_pts_ptr
1455
1456 );
1457 MoFEMErrorCode doWork(int side, EntityType type,
1459
1460protected:
1461 boost::shared_ptr<ContactTree> contactTreePtr;
1462 boost::shared_ptr<MatrixDouble> uH1Ptr;
1463 boost::shared_ptr<MatrixDouble> tractionPtr;
1464 moab::Interface *postProcMeshPtr = nullptr;
1465 std::vector<EntityHandle> *mapGaussPtsPtr = nullptr;
1466
1468};
1469
1470OpTreeSearch::OpTreeSearch(boost::shared_ptr<ContactTree> contact_tree_ptr,
1471 boost::shared_ptr<MatrixDouble> u_h1_ptr,
1472 boost::shared_ptr<MatrixDouble> traction_ptr,
1473 Range r,
1474
1475 moab::Interface *post_proc_mesh_ptr,
1476 std::vector<EntityHandle> *map_gauss_pts_ptr
1477
1478 )
1479 : UOP(NOSPACE, UOP::OPSPACE), contactTreePtr(contact_tree_ptr),
1480 uH1Ptr(u_h1_ptr), tractionPtr(traction_ptr),
1481 postProcMeshPtr(post_proc_mesh_ptr), mapGaussPtsPtr(map_gauss_pts_ptr),
1482 contactRange(r) {}
1483
1487
1488 auto &m_field = getPtrFE()->mField;
1489 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1490 auto fe_id = id_from_handle(fe_ent);
1491
1492 if (contactRange.find(fe_ent) == contactRange.end())
1494
1495 FTensor::Index<'i', 3> i;
1496 FTensor::Index<'j', 3> j;
1497
1498 const auto nb_gauss_pts = getGaussPts().size2();
1499
1500 auto t_disp_h1 = getFTensor1FromMat<3>(*uH1Ptr);
1501 auto t_coords = getFTensor1CoordsAtGaussPts();
1502 auto t_traction = getFTensor1FromMat<3>(*tractionPtr);
1503
1504 auto next = [&]() {
1505 ++t_disp_h1;
1506 ++t_traction;
1507 ++t_coords;
1508 };
1509
1510 auto get_ele_centre = [i](auto t_ele_coords) {
1511 FTensor::Tensor1<double, 3> t_ele_center;
1512 t_ele_center(i) = 0;
1513 for (int nn = 0; nn != 3; nn++) {
1514 t_ele_center(i) += t_ele_coords(i);
1515 ++t_ele_coords;
1516 }
1517 t_ele_center(i) /= 3;
1518 return t_ele_center;
1519 };
1520
1521 auto get_ele_radius = [i](auto t_ele_center, auto t_ele_coords) {
1523 t_n0(i) = t_ele_center(i) - t_ele_coords(i);
1524 return t_n0.l2();
1525 };
1526
1527 auto get_face_conn = [this](auto face) {
1528 const EntityHandle *conn;
1529 int num_nodes;
1530 CHK_MOAB_THROW(contactTreePtr->getPostProcMesh().get_connectivity(
1531 face, conn, num_nodes, true),
1532 "get conn");
1533 if (num_nodes != 3) {
1534 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "face is not a triangle");
1535 }
1536 return conn;
1537 };
1538
1539 auto get_face_coords = [this](auto conn) {
1540 std::array<double, 9> coords;
1541 CHKERR contactTreePtr->getPostProcMesh().get_coords(conn, 3, coords.data());
1542 return coords;
1543 };
1544
1545 auto get_closet_face = [this](auto *point_ptr, auto r) {
1546 FTensor::Tensor1<double, 3> t_point_out;
1547 std::vector<EntityHandle> faces_out;
1549 contactTreePtr->getTreeSurfPtr()->sphere_intersect_triangles(
1550 point_ptr, r / 8, contactTreePtr->getRootSetSurf(), faces_out),
1551 "get closest faces");
1552 return faces_out;
1553 };
1554
1555 auto get_faces_out = [this](auto *point_ptr, auto *unit_ray_ptr, auto radius,
1556 auto eps) {
1557 std::vector<double> distances_out;
1558 std::vector<EntityHandle> faces_out;
1560
1561 contactTreePtr->getTreeSurfPtr()->ray_intersect_triangles(
1562 distances_out, faces_out, contactTreePtr->getRootSetSurf(), eps,
1563 point_ptr, unit_ray_ptr, &radius),
1564
1565 "get closest faces");
1566 return std::make_pair(faces_out, distances_out);
1567 };
1568
1569 auto get_normal = [](auto &ele_coords) {
1571 Tools::getTriNormal(ele_coords.data(), &t_normal(0));
1572 return t_normal;
1573 };
1574
1575 auto make_map = [&](auto &face_out, auto &face_dist, auto &t_ray_point,
1576 auto &t_unit_ray, auto &t_master_coord) {
1577 FTensor::Index<'i', 3> i;
1578 FTensor::Index<'j', 3> j;
1579 std::map<double, EntityHandle> m;
1580 for (auto ii = 0; ii != face_out.size(); ++ii) {
1581 auto face_conn = get_face_conn(face_out[ii]);
1582 auto face_coords = get_face_coords(face_conn);
1583 auto t_face_normal = get_normal(face_coords);
1584 t_face_normal.normalize();
1586 t_x(i) = t_ray_point(i) + t_unit_ray(i) * face_dist[ii];
1588 t_chi(i, j) =
1589 t_x(i) * t_face_normal(j) - t_master_coord(i) * t_unit_ray(j);
1590 if (t_unit_ray(i) * t_face_normal(i) > std::cos(M_PI / 3)) {
1591 auto dot = std::sqrt(t_chi(i, j) * t_chi(i, j));
1592 m[dot] = face_out[ii];
1593 }
1594 }
1595 return m;
1596 };
1597
1598 auto get_tag_data = [this](auto tag, auto face, auto &vec) {
1600 int tag_length;
1601 CHKERR contactTreePtr->getPostProcMesh().tag_get_length(tag, tag_length);
1602 vec.resize(tag_length);
1603 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(tag, &face, 1,
1604 &*vec.begin());
1606 };
1607
1608 auto create_tag = [this](const std::string tag_name, const int size) {
1609 double def_VAL[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
1610 Tag th;
1611 if (postProcMeshPtr) {
1612 CHKERR postProcMeshPtr->tag_get_handle(
1613 tag_name.c_str(), size, MB_TYPE_DOUBLE, th,
1614 MB_TAG_CREAT | MB_TAG_SPARSE, def_VAL);
1615 CHKERR postProcMeshPtr->tag_clear_data(th, &*mapGaussPtsPtr->begin(),
1616 mapGaussPtsPtr->size(), def_VAL);
1617 }
1618 return th;
1619 };
1620
1621 auto set_float_precision = [](const double x) {
1622 if (std::abs(x) < std::numeric_limits<float>::epsilon())
1623 return 0.;
1624 else
1625 return x;
1626 };
1627
1628 // scalars
1629 auto save_scal_tag = [&](auto &th, auto v, const int gg) {
1631 if (postProcMeshPtr) {
1632 v = set_float_precision(v);
1633 CHKERR postProcMeshPtr->tag_set_data(th, &(*mapGaussPtsPtr)[gg], 1, &v);
1634 }
1636 };
1637
1638 // adjacencies
1639 auto get_fe_adjacencies = [this](auto fe_ent) {
1640 Range adj_faces;
1641 CHK_MOAB_THROW(getFaceFE()->mField.get_moab().get_adjacencies(
1642 &fe_ent, 1, 2, false, adj_faces, moab::Interface::UNION),
1643 "get adj");
1644 std::set<int> adj_ids;
1645 for (auto f : adj_faces) {
1646 adj_ids.insert(id_from_handle(f));
1647 }
1648 return adj_ids;
1649 };
1650
1651 auto get_face_id = [this](auto face) {
1652 int id;
1653 if (contactTreePtr->getPostProcMesh().tag_get_data(
1654 contactTreePtr->thEleId, &face, 1, &id) == MB_SUCCESS) {
1655 return id;
1656 }
1657 return -1;
1658 };
1659
1660 auto get_body_id = [this](auto face) {
1661 int id;
1662 if (contactTreePtr->getPostProcMesh().tag_get_data(
1663 contactTreePtr->thBodyId, &face, 1, &id) == MB_SUCCESS) {
1664 return id;
1665 }
1666 return -1;
1667 };
1668
1669 auto get_face_part = [this](auto face) {
1670 const moab::Core *core_mesh_ptr =
1671 dynamic_cast<const moab::Core *>(&contactTreePtr->getPostProcMesh());
1672 auto pcomm_post_proc_mesh =
1673 MeshPCommRegistry::getOrCreate(const_cast<moab::Core *>(core_mesh_ptr));
1674 int part;
1675 if (contactTreePtr->getPostProcMesh().tag_get_data(
1676 pcomm_post_proc_mesh->part_tag(), &face, 1, &part) == MB_SUCCESS) {
1677 return part;
1678 }
1679 return -1;
1680 };
1681
1682 auto check_face = [&](auto face, auto fe_id, auto part) {
1683 auto face_id = get_face_id(face);
1684 auto face_part = get_face_part(face);
1685 if (face_id == fe_id && face_part == part)
1686 return true;
1687 return false;
1688 };
1689
1690 // vectors
1691 VectorDouble3 v(3);
1692 FTensor::Tensor1<FTensor::PackPtr<double *, 0>, 3> t_v(&v[0], &v[1], &v[2]);
1693 auto save_vec_tag = [&](auto &th, auto &t_d, const int gg) {
1695 if (postProcMeshPtr) {
1696 t_v(i) = t_d(i);
1697 for (auto &a : v.data())
1698 a = set_float_precision(a);
1699 CHKERR postProcMeshPtr->tag_set_data(th, &(*mapGaussPtsPtr)[gg], 1,
1700 &*v.data().begin());
1701 }
1703 };
1704
1705 Tag th_mark = create_tag("contact_mark", 1);
1706 Tag th_mark_slave = create_tag("contact_mark_slave", 1);
1707 Tag th_body_id = create_tag("contact_body_id", 1);
1708 Tag th_gap = create_tag("contact_gap", 1);
1709 Tag th_tn_master = create_tag("contact_tn_master", 1);
1710 Tag th_tn_slave = create_tag("contact_tn_slave", 1);
1711 Tag th_contact_traction = create_tag("contact_traction", 3);
1712 Tag th_contact_traction_master = create_tag("contact_traction_master", 3);
1713 Tag th_contact_traction_slave = create_tag("contact_traction_slave", 3);
1714 Tag th_c = create_tag("contact_c", 1);
1715 Tag th_normal = create_tag("contact_normal", 3);
1716 Tag th_dist = create_tag("contact_dip", 3);
1717
1718 auto t_ele_centre = get_ele_centre(getFTensor1Coords());
1719 auto ele_radius = get_ele_radius(t_ele_centre, getFTensor1Coords());
1720
1721 contactTreePtr->shadowDataMap.clear();
1722 auto &shadow_vec = contactTreePtr->shadowDataMap[fe_ent];
1723 shadow_vec.clear();
1724
1725 auto adj_fe_ids = get_fe_adjacencies(fe_ent);
1726
1727 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
1728
1729 FTensor::Tensor1<double, 3> t_spatial_coords;
1730 t_spatial_coords(i) = t_coords(i) + t_disp_h1(i);
1731
1732 if (postProcMeshPtr) {
1733 CHKERR save_vec_tag(th_contact_traction, t_traction, gg);
1734 }
1735
1736 auto faces_close = get_closet_face(&t_spatial_coords(0), ele_radius);
1737 for (auto face_close : faces_close) {
1738 if (check_face(face_close, fe_id, m_field.get_comm_rank())) {
1739
1740 auto body_id = get_body_id(face_close);
1741
1742 auto master_face_conn = get_face_conn(face_close);
1743 std::array<double, 9> master_coords;
1744 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(
1745 contactTreePtr->thSmallX, master_face_conn, 3,
1746 master_coords.data());
1747 std::array<double, 9> master_traction;
1748 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(
1749 contactTreePtr->thTraction, master_face_conn, 3,
1750 master_traction.data());
1751 auto t_normal_face_close = get_normal(master_coords);
1752 t_normal_face_close.normalize();
1753
1754 if (postProcMeshPtr) {
1755 double m = 1;
1756 CHKERR save_scal_tag(th_mark, m, gg);
1757 CHKERR save_scal_tag(th_body_id, static_cast<double>(body_id), gg);
1758 CHKERR save_vec_tag(th_normal, t_normal_face_close, gg);
1759 CHKERR save_vec_tag(th_contact_traction, t_traction, gg);
1760 }
1761
1762 FTensor::Tensor1<double, 3> t_unit_ray;
1763 t_unit_ray(i) = -t_normal_face_close(i);
1764 FTensor::Tensor1<double, 3> t_ray_point;
1765 t_ray_point(i) =
1766 t_spatial_coords(i) -
1767 t_unit_ray(i) * ContactOps::airplane_ray_distance * ele_radius;
1768
1769 constexpr double eps = 1e-3;
1770 auto [faces_out, faces_dist] =
1771 get_faces_out(&t_ray_point(0), &t_unit_ray(0),
1772 2 * ContactOps::airplane_ray_distance * ele_radius,
1773 eps * ele_radius);
1774
1775 auto m = make_map(faces_out, faces_dist, t_ray_point, t_unit_ray,
1776 t_spatial_coords);
1777 for (auto m_it = m.begin(); m_it != m.end(); ++m_it) {
1778 auto face = m_it->second;
1779 if (face != face_close) {
1780
1781 if (
1782
1783 (adj_fe_ids.find(get_face_id(face)) == adj_fe_ids.end() ||
1784 get_face_part(face) != m_field.get_comm_rank())
1785
1786 ) {
1787
1788 shadow_vec.push_back(ContactTree::FaceData());
1789 shadow_vec.back().gaussPtNb = gg;
1790
1791 auto slave_face_conn = get_face_conn(face);
1792 std::array<double, 9> slave_coords;
1793 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(
1794 contactTreePtr->thSmallX, slave_face_conn, 3,
1795 slave_coords.data());
1796 auto t_normal_face = get_normal(slave_coords);
1797 std::array<double, 9> slave_tractions;
1798 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(
1799 contactTreePtr->thTraction, slave_face_conn, 3,
1800 slave_tractions.data());
1801
1802 auto t_master_point =
1803 getFTensor1FromPtr<3>(shadow_vec.back().masterPoint.data());
1804 auto t_slave_point =
1805 getFTensor1FromPtr<3>(shadow_vec.back().slavePoint.data());
1806 auto t_ray_point_data =
1807 getFTensor1FromPtr<3>(shadow_vec.back().rayPoint.data());
1808 auto t_unit_ray_data =
1809 getFTensor1FromPtr<3>(shadow_vec.back().unitRay.data());
1810
1811 t_slave_point(i) = t_ray_point(i) + m_it->first * t_unit_ray(i);
1812
1813 auto eval_position = [&](auto &&t_elem_coords, auto &&t_point) {
1814 std::array<double, 2> loc_coords;
1817 &t_elem_coords(0, 0), &t_point(0), 1,
1818 loc_coords.data()),
1819 "get local coords");
1820 FTensor::Tensor1<double, 3> t_shape_fun;
1821 CHK_THROW_MESSAGE(Tools::shapeFunMBTRI<0>(&t_shape_fun(0),
1822 &loc_coords[0],
1823 &loc_coords[1], 1),
1824 "calc shape fun");
1825 FTensor::Index<'i', 3> i;
1826 FTensor::Index<'j', 3> j;
1827 FTensor::Tensor1<double, 3> t_point_out;
1828 t_point_out(i) = t_shape_fun(j) * t_elem_coords(j, i);
1829 return t_point_out;
1830 };
1831
1832 auto t_master_point_updated = eval_position(
1833 getFTensor2FromPtr<3, 3>(master_coords.data()),
1834 getFTensor1FromPtr<3>(shadow_vec.back().masterPoint.data()));
1835 t_master_point(i) = t_master_point_updated(i);
1836
1837 auto t_slave_point_updated = eval_position(
1838 getFTensor2FromPtr<3, 3>(slave_coords.data()),
1839 getFTensor1FromPtr<3>(shadow_vec.back().slavePoint.data()));
1840 t_slave_point(i) = t_slave_point_updated(i);
1841
1842 t_ray_point_data(i) = t_ray_point(i);
1843 t_unit_ray_data(i) = t_unit_ray(i);
1844
1845 std::copy(master_coords.begin(), master_coords.end(),
1846 shadow_vec.back().masterPointNodes.begin());
1847 std::copy(master_traction.begin(), master_traction.end(),
1848 shadow_vec.back().masterTractionNodes.begin());
1849 std::copy(slave_coords.begin(), slave_coords.end(),
1850 shadow_vec.back().slavePointNodes.begin());
1851 std::copy(slave_tractions.begin(), slave_tractions.end(),
1852 shadow_vec.back().slaveTractionNodes.begin());
1853
1854 shadow_vec.back().eleRadius = ele_radius;
1855
1856 // CHKERR get_tag_data(contactTreePtr->thIds, face,
1857 // shadow_vec.back().dofsSlaveIds);
1858 // CHKERR get_tag_data(contactTreePtr->thCoeff, face,
1859 // shadow_vec.back().dofsSlaveCoeff);
1860 // CHKERR get_tag_data(contactTreePtr->thBases, face,
1861 // shadow_vec.back().baseSlaveFuncs);
1862
1863 if (postProcMeshPtr) {
1864 auto [gap, tn_master, tn_slave, c, t_master_traction,
1865 t_slave_traction] =
1866 multiGetGap(&(shadow_vec.back()), t_spatial_coords);
1868 t_gap_vec(i) = t_slave_point(i) - t_spatial_coords(i);
1869 CHKERR save_scal_tag(th_gap, gap, gg);
1870 CHKERR save_scal_tag(th_tn_master, tn_master, gg);
1871 CHKERR save_scal_tag(th_tn_slave, tn_slave, gg);
1872 CHKERR save_scal_tag(th_c, c, gg);
1873 double m = 1;
1874 CHKERR save_scal_tag(th_mark_slave, m, gg);
1875 CHKERR save_vec_tag(th_dist, t_gap_vec, gg);
1876 CHKERR save_vec_tag(th_contact_traction_master,
1877 t_master_traction, gg);
1878 CHKERR save_vec_tag(th_contact_traction_slave, t_slave_traction,
1879 gg);
1880 }
1881
1882 break;
1883 }
1884 }
1885 }
1886 break;
1887 }
1888 }
1889 next();
1890 }
1891
1893}
1894
1896 const std::string block_name, int dim) {
1897 Range r;
1898
1899 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
1900 auto bcs = mesh_mng->getCubitMeshsetPtr(
1901
1902 std::regex((boost::format("%s(.*)") % block_name).str())
1903
1904 );
1905
1906 for (auto bc : bcs) {
1907 Range faces;
1908 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
1909 faces, true),
1910 "get meshset ents");
1911 r.merge(faces);
1912 }
1913
1914 return r;
1915};
1916
1917boost::shared_ptr<ForcesAndSourcesCore>
1919
1920 auto &m_field = ep.mField;
1921
1922 boost::shared_ptr<ContactTree> fe_contact_tree;
1923
1924 auto impl = [&]() {
1926
1927 /** Contact requires that body is marked */
1928 auto get_body_range = [&](auto name, int dim, auto sev) {
1929 std::map<int, Range> map;
1930
1931 for (auto m_ptr :
1932 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
1933 std::regex(
1934
1935 (boost::format("%s(.*)") % name).str()
1936
1937 ))
1938
1939 ) {
1940 Range ents;
1941 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(
1942 m_field.get_moab(), dim, ents, true),
1943 "by dim");
1944 map[m_ptr->getMeshsetId()] = ents;
1945 MOFEM_LOG("EPSYNC", sev) << "Meshset: " << m_ptr->getMeshsetId() << " "
1946 << ents.size() << " entities";
1947 }
1948
1949 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), sev);
1950 return map;
1951 };
1952
1953 auto get_map_skin = [&](auto &&map) {
1954 ParallelComm *pcomm =
1955 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
1956
1957 Skinner skin(&m_field.get_moab());
1958 for (auto &m : map) {
1959 Range skin_faces;
1960 CHKERR skin.find_skin(0, m.second, false, skin_faces);
1961 CHK_MOAB_THROW(pcomm->filter_pstatus(
1962 skin_faces, PSTATUS_SHARED | PSTATUS_MULTISHARED,
1963 PSTATUS_NOT, -1, nullptr),
1964 "filter");
1965 m.second.swap(skin_faces);
1966 }
1967 return map;
1968 };
1969
1970 /* The above code is written in C++ and it appears to be defining and using
1971 various operations on boundary elements and side elements. */
1973 using BoundaryEleOp = BoundaryEle::UserDataOperator;
1974
1975 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1976
1977 auto calcs_side_traction = [&](auto &pip) {
1979 using EleOnSide =
1981 using SideEleOp = EleOnSide::UserDataOperator;
1982 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
1983 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
1984 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
1985 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
1986 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
1987 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
1989 op_loop_domain_side->getOpPtrVector().push_back(
1991 ep.piolaStress, contact_common_data_ptr->contactTractionPtr(),
1992 boost::make_shared<double>(1.0)));
1993 pip.push_back(op_loop_domain_side);
1995 };
1996
1997 auto add_contact_three = [&]() {
1999 auto tree_moab_ptr = boost::make_shared<moab::Core>();
2000 fe_contact_tree = boost::make_shared<ContactTree>(
2001 m_field, tree_moab_ptr, ep.spaceOrder,
2002 get_body_range("CONTACT", SPACE_DIM - 1, Sev::inform));
2003 fe_contact_tree->getOpPtrVector().push_back(
2005 ep.contactDisp, contact_common_data_ptr->contactDispPtr()));
2006 CHKERR calcs_side_traction(fe_contact_tree->getOpPtrVector());
2007 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2008 fe_contact_tree->getOpPtrVector().push_back(
2010 fe_contact_tree->getOpPtrVector().push_back(
2011 new OpMoveNode(fe_contact_tree, contact_common_data_ptr, u_h1_ptr));
2013 };
2014
2015 CHKERR add_contact_three();
2016
2018 };
2019
2020 CHK_THROW_MESSAGE(impl(), "createContactDetectionFiniteElement");
2021
2022 struct exclude_sdf {
2023 exclude_sdf(Range &&r) : map(r) {}
2024 bool operator()(FEMethod *fe_method_ptr) {
2025 auto ent = fe_method_ptr->getFEEntityHandle();
2026 if (map.find(ent) != map.end()) {
2027 return false;
2028 }
2029 return true;
2030 }
2031
2032 private:
2033 Range map;
2034 };
2035
2036 fe_contact_tree->exeTestHook =
2037 exclude_sdf(get_range_from_block(m_field, "CONTACT_SDF", SPACE_DIM - 1));
2038
2039 return fe_contact_tree;
2040};
2041
2042static auto get_body_range(MoFEM::Interface &m_field, const std::string name,
2043 int dim) {
2044 std::map<int, Range> map;
2045
2046 for (auto m_ptr :
2047 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2048
2049 (boost::format("%s(.*)") % name).str()
2050
2051 ))
2052
2053 ) {
2054 Range ents;
2055 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(m_field.get_moab(),
2056 dim, ents, true),
2057 "by dim");
2058 map[m_ptr->getMeshsetId()] = ents;
2059 }
2060
2061 return map;
2062};
2063
2065 EshelbianCore &ep, boost::shared_ptr<ForcesAndSourcesCore> fe_ptr,
2066 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
2068
2069 auto contact_tree_ptr = boost::dynamic_pointer_cast<ContactTree>(fe_ptr);
2070
2071 auto &m_field = ep.mField;
2072
2073 using BoundaryEle =
2075 using EleOnSide =
2077 using SideEleOp = EleOnSide::UserDataOperator;
2078 using BdyEleOp = BoundaryEle::UserDataOperator;
2079
2080 // First: Iterate over skeleton FEs adjacent to Domain FEs
2081 // Note: BoundaryEle, i.e. uses skeleton interation rule
2082 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
2083 m_field, ep.contactElement, SPACE_DIM - 1, Sev::noisy);
2084
2085 auto rule_contact = [](int, int, int o) { return -1; };
2087
2088 auto set_rule_contact = [refine](
2089
2090 ForcesAndSourcesCore *fe_raw_ptr, int order_row,
2091 int order_col, int order_data
2092
2093 ) {
2095 auto rule = 2 * order_data;
2096 fe_raw_ptr->gaussPts = Tools::refineTriangleIntegrationPts(rule, refine);
2098 };
2099
2100 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2101 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2102 CHKERR
2103 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2104 op_loop_skeleton_side->getOpPtrVector(), {L2}, ep.materialH1Positions,
2105 ep.frontAdjEdges);
2106
2107 // Second: Iterate over domain FEs adjacent to skelton, particularly
2108 // one domain element.
2109 auto broken_data_ptr = boost::make_shared<std::vector<BrokenBaseSideData>>();
2110
2111 // Data storing contact fields
2112 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
2113
2114 auto add_ops_domain_side = [&](auto &pip) {
2116 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
2117 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
2118 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
2119 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2120 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
2121 CHKERR
2122 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2123 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2125 op_loop_domain_side->getOpPtrVector().push_back(
2127 broken_data_ptr));
2128 op_loop_domain_side->getOpPtrVector().push_back(
2130 ep.piolaStress, contact_common_data_ptr->contactTractionPtr()));
2131 pip.push_back(op_loop_domain_side);
2133 };
2134
2135 auto add_ops_contact_rhs = [&](auto &pip) {
2137 // get body id and SDF range
2138 auto contact_sfd_map_range_ptr = boost::make_shared<std::map<int, Range>>(
2139 get_body_range(m_field, "CONTACT_SDF", SPACE_DIM - 1));
2140
2141 pip.push_back(new OpCalculateVectorFieldValues<3>(
2142 ep.contactDisp, contact_common_data_ptr->contactDispPtr()));
2143 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2144 pip.push_back(
2146 pip.push_back(new OpTreeSearch(
2147 contact_tree_ptr, u_h1_ptr,
2148 contact_common_data_ptr->contactTractionPtr(),
2149 get_range_from_block(m_field, "CONTACT", SPACE_DIM - 1), nullptr,
2150 nullptr));
2152 ep.contactDisp, contact_common_data_ptr, contact_tree_ptr,
2153 contact_sfd_map_range_ptr));
2155 broken_data_ptr, contact_common_data_ptr, contact_tree_ptr));
2156
2158 };
2159
2160 // push ops to face/side pipeline
2161 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2162 CHKERR add_ops_contact_rhs(op_loop_skeleton_side->getOpPtrVector());
2163
2164 // Add skeleton to domain pipeline
2165 pip.push_back(op_loop_skeleton_side);
2166
2168};
2169
2171 EshelbianCore &ep, boost::shared_ptr<ForcesAndSourcesCore> fe_ptr,
2172 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
2174
2175 auto contact_tree_ptr = boost::dynamic_pointer_cast<ContactTree>(fe_ptr);
2176 auto &m_field = ep.mField;
2177
2178 using BoundaryEle =
2180 using EleOnSide =
2182 using SideEleOp = EleOnSide::UserDataOperator;
2183 using BdyEleOp = BoundaryEle::UserDataOperator;
2184
2185 // First: Iterate over skeleton FEs adjacent to Domain FEs
2186 // Note: BoundaryEle, i.e. uses skeleton interation rule
2187 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
2188 m_field, ep.contactElement, SPACE_DIM - 1, Sev::noisy);
2189
2190 auto rule_contact = [](int, int, int o) { return -1; };
2192
2193 auto set_rule_contact = [refine](
2194
2195 ForcesAndSourcesCore *fe_raw_ptr, int order_row,
2196 int order_col, int order_data
2197
2198 ) {
2200 auto rule = 2 * order_data;
2201 fe_raw_ptr->gaussPts = Tools::refineTriangleIntegrationPts(rule, refine);
2203 };
2204
2205 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2206 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2207 CHKERR
2208 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2209 op_loop_skeleton_side->getOpPtrVector(), {L2}, ep.materialH1Positions,
2210 ep.frontAdjEdges);
2211
2212 // Second: Iterate over domain FEs adjacent to skelton, particularly
2213 // one domain element.
2214 auto broken_data_ptr = boost::make_shared<std::vector<BrokenBaseSideData>>();
2215
2216 // Data storing contact fields
2217 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
2218
2219 auto add_ops_domain_side = [&](auto &pip) {
2221 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
2222 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
2223 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
2224 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2225 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
2226 CHKERR
2227 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2228 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2230 op_loop_domain_side->getOpPtrVector().push_back(
2232 broken_data_ptr));
2233 op_loop_domain_side->getOpPtrVector().push_back(
2235 ep.piolaStress, contact_common_data_ptr->contactTractionPtr()));
2236 pip.push_back(op_loop_domain_side);
2238 };
2239
2240 auto add_ops_contact_lhs = [&](auto &pip) {
2242 pip.push_back(new OpCalculateVectorFieldValues<3>(
2243 ep.contactDisp, contact_common_data_ptr->contactDispPtr()));
2244 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2245 pip.push_back(
2247 pip.push_back(new OpTreeSearch(
2248 contact_tree_ptr, u_h1_ptr,
2249 contact_common_data_ptr->contactTractionPtr(),
2250 get_range_from_block(m_field, "CONTACT", SPACE_DIM - 1), nullptr,
2251 nullptr));
2252
2253 // get body id and SDF range
2254 auto contact_sfd_map_range_ptr = boost::make_shared<std::map<int, Range>>(
2255 get_body_range(m_field, "CONTACT_SDF", SPACE_DIM - 1));
2256
2258 ep.contactDisp, ep.contactDisp, contact_common_data_ptr,
2259 contact_tree_ptr, contact_sfd_map_range_ptr));
2260 pip.push_back(
2262 ep.contactDisp, broken_data_ptr, contact_common_data_ptr,
2263 contact_tree_ptr, contact_sfd_map_range_ptr));
2264 pip.push_back(
2266 broken_data_ptr, ep.contactDisp, contact_common_data_ptr,
2267 contact_tree_ptr));
2268
2270 };
2271
2272 // push ops to face/side pipeline
2273 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2274 CHKERR add_ops_contact_lhs(op_loop_skeleton_side->getOpPtrVector());
2275
2276 // Add skeleton to domain pipeline
2277 pip.push_back(op_loop_skeleton_side);
2278
2280};
2281
2284 boost::shared_ptr<ForcesAndSourcesCore> fe_ptr,
2285 boost::shared_ptr<MatrixDouble> u_h1_ptr,
2286 boost::shared_ptr<MatrixDouble> contact_traction_ptr,
2287 Range r, moab::Interface *post_proc_mesh_ptr,
2288 std::vector<EntityHandle> *map_gauss_pts_ptr) {
2289
2290 auto &m_field = ep.mField;
2291 auto contact_tree_ptr = boost::dynamic_pointer_cast<ContactTree>(fe_ptr);
2292 return new OpTreeSearch(
2293 contact_tree_ptr, u_h1_ptr, contact_traction_ptr,
2294 get_range_from_block(m_field, "CONTACT", SPACE_DIM - 1),
2295 post_proc_mesh_ptr, map_gauss_pts_ptr);
2296}
2297
2298} // namespace EshelbianPlasticity
Implementation of tonsorial bubble base div(v) = 0.
Eshelbian plasticity interface.
std::string type
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define FTENSOR_INDEX(DIM, I)
constexpr double a
static const double eps
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
Kronecker Delta class.
Tensor1< T, Tensor_Dim > normalize()
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ NOSPACE
Definition definitions.h:83
#define MYPCOMM_INDEX
default communicator number PCOMM
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
static const bool debug
#define N_MBTRI1(x, y)
triangle shape function
Definition fem_tools.h:47
#define N_MBTRI0(x, y)
triangle shape function
Definition fem_tools.h:46
#define N_MBTRI2(x, y)
triangle shape function
Definition fem_tools.h:48
static const double face_coords[4][9]
constexpr auto t_kd
double eta
IntegrationType
Form integrator integration types.
@ GAUSS
Gaussian quadrature integration.
MoFEMErrorCode writeFile(const std::string file_name)
wrote results in (MOAB) format, use "file_name.h5m"
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
auto get_normalize_normals(FTensor::Tensor1< T1, DIM1 > &&t_normal_at_pts, size_t nb_gauss_pts)
double cn_contact
Definition contact.cpp:97
double alpha_contact_quadratic
FormsIntegrators< BoundaryEleOp >::Assembly< A >::OpBase AssemblyBoundaryEleOp
MatrixDouble grad_surface_distance_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_spatial_coords, MatrixDouble &m_normals_at_pts, int block_id)
MatrixDouble hess_surface_distance_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_spatial_coords, MatrixDouble &m_normals_at_pts, int block_id)
PostProcEleByDim< SPACE_DIM >::SideEle SideEle
double alpha_contact_const
double airplane_ray_distance
auto get_spatial_coords(FTensor::Tensor1< T1, DIM1 > &&t_coords, FTensor::Tensor1< T2, DIM2 > &&t_disp, size_t nb_gauss_pts)
double constrain(double sdf, double tn)
constrain function
VectorDouble surface_distance_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_spatial_coords, MatrixDouble &m_normals_at_pts, int block_id)
boost::shared_ptr< ContactSDFPython > setupContactSdf()
Read SDF file and setup contact SDF.
static auto get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
auto checkSdf(EntityHandle fe_ent, std::map< int, Range > &sdf_map_range)
ForcesAndSourcesCore::UserDataOperator * getOpContactDetection(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > contact_tree_ptr, boost::shared_ptr< MatrixDouble > u_h1_ptr, boost::shared_ptr< MatrixDouble > contact_traction_ptr, Range r, moab::Interface *post_proc_mesh_ptr, std::vector< EntityHandle > *map_gauss_pts_ptr)
Push operator for contact detection.
boost::shared_ptr< ForcesAndSourcesCore > createContactDetectionFiniteElement(EshelbianCore &ep)
Create a Contact Tree finite element.
auto multiMasterPoint(ContactTree::FaceData *face_data_ptr, FTensor::Tensor1< T1, 3 > &t_spatial_coords)
auto multiGetGap(ContactTree::FaceData *face_data_ptr, FTensor::Tensor1< T1, 3 > &t_spatial_coords)
auto multiPointRhs(ContactTree::FaceData *face_data_ptr, FTensor::Tensor1< T1, 3 > &t_coords, FTensor::Tensor1< T2, 3 > &t_spatial_coords, FTensor::Tensor1< T3, 3 > &t_master_traction, MultiPointRhsType type, bool debug=false)
MoFEMErrorCode pushContactOpsRhs(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > contact_tree_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
Push contact operations to the right-hand side.
auto multiSlavePoint(ContactTree::FaceData *face_data_ptr, FTensor::Tensor1< T1, 3 > &t_spatial_coords)
auto multiPoint(std::array< double, 3 > &unit_ray, std::array< double, 3 > &point, std::array< double, 9 > &elem_point_nodes, std::array< double, 9 > &elem_traction_nodes, FTensor::Tensor1< T1, 3 > &t_spatial_coords)
Calculate points data on contact surfaces.
MoFEMErrorCode pushContactOpsLhs(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > contact_tree_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
Push contact operations to the left-hand side.
static auto get_body_range(MoFEM::Interface &m_field, const std::string name, int dim)
auto getSdf(OP_PTR op_ptr, MatrixDouble &contact_disp, int block_id, bool eval_hessian)
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::FaceSideEle EleOnSide
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
VectorBoundedArray< double, 3 > VectorDouble3
Definition Types.hpp:92
UBlasMatrix< double > MatrixDouble
Definition Types.hpp:77
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto id_from_handle(const EntityHandle h)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
void tricircumcenter3d_tp(double a[3], double b[3], double c[3], double circumcenter[3], double *xi, double *eta)
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
constexpr AssemblyType A
constexpr double g
FTensor::Index< 'm', 3 > m
boost::shared_ptr< Range > frontAdjEdges
MoFEM::Interface & mField
const std::string materialH1Positions
const std::string elementVolumeName
static double physicalDt
const std::string spatialH1Disp
const std::string piolaStress
static PetscBool physicalTimeFlg
static double currentPhysicalTime
const std::string contactDisp
const std::string contactElement
boost::shared_ptr< OrientedBoxTreeTool > & getTreeSurfPtr()
std::map< EntityHandle, std::vector< FaceData > > MapFaceData
boost::shared_ptr< OrientedBoxTreeTool > treeSurfPtr
auto findFaceDataVecPtr(EntityHandle fe_ent)
auto getFaceDataPtr(std::vector< FaceData >::iterator &it, int gg, std::vector< FaceData > *vec_ptr)
MoFEMErrorCode buildTree(Range &ents)
MoFEMErrorCode preProcess()
Pre-processing function executed at loop initialization.
MoFEMErrorCode postProcess()
Post-processing function executed at loop completion.
ContactTree(MoFEM::Interface &m_field, boost::shared_ptr< moab::Core > core_mesh_ptr, int max_order, std::map< int, Range > &&body_map)
int getMaxLevel() const
Determine refinement level based on fields approx ordre.
boost::shared_ptr< std::map< int, Range > > sdfMapRangePtr
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data, EntitiesFieldData::EntData &col_data)
OpConstrainBoundaryL2Lhs_dU(const std::string row_field_name, const std::string col_field_name, boost::shared_ptr< ContactOps::CommonData > common_data_ptr, boost::shared_ptr< ContactTree > contact_tree_ptr, boost::shared_ptr< std::map< int, Range > > sdf_map_range_ptr=nullptr)
boost::shared_ptr< ContactOps::CommonData > commonDataPtr
boost::shared_ptr< std::map< int, Range > > sdfMapRangePtr
boost::shared_ptr< ContactOps::CommonData > commonDataPtr
boost::shared_ptr< ContactTree > contactTreePtr
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data)
OpConstrainBoundaryL2Rhs(const std::string row_field_name, boost::shared_ptr< ContactOps::CommonData > common_data_ptr, boost::shared_ptr< ContactTree > contact_tree_ptr, boost::shared_ptr< std::map< int, Range > > sdf_map_range_ptr=nullptr)
boost::shared_ptr< ContactOps::CommonData > commonDataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
boost::weak_ptr< ContactTree > contactTreePtr
FaceElementForcesAndSourcesCore::UserDataOperator UOP
boost::shared_ptr< MatrixDouble > uH1Ptr
OpMoveNode(boost::shared_ptr< ContactTree > contact_tree_ptr, boost::shared_ptr< ContactOps::CommonData > common_data_ptr, boost::shared_ptr< MatrixDouble > u_h1_ptr)
boost::shared_ptr< ContactTree > contactTreePtr
std::vector< EntityHandle > * mapGaussPtsPtr
boost::shared_ptr< MatrixDouble > uH1Ptr
OpTreeSearch(boost::shared_ptr< ContactTree > contact_tree_ptr, boost::shared_ptr< MatrixDouble > u_h1_ptr, boost::shared_ptr< MatrixDouble > traction_ptr, Range r, moab::Interface *post_proc_mesh_ptr, std::vector< EntityHandle > *map_gauss_pts_ptr)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
boost::shared_ptr< MatrixDouble > tractionPtr
FaceElementForcesAndSourcesCore::UserDataOperator UOP
virtual int get_comm_size() const =0
virtual moab::Interface & get_moab()=0
virtual int get_comm_rank() const =0
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
auto getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
Structure for user loop methods on finite elements.
EntityHandle getFEEntityHandle() const
Get the entity handle of the current finite element.
Base face element used to integrate on skeleton.
structure to get information from mofem into EntitiesFieldData
MatrixDouble gaussPts
Matrix of integration points.
static auto getOrCreate(moab::Core *core_mesh_ptr)
Interface for managing meshsets containing materials and boundary conditions.
Operator for broken loop side.
Calculate trace of vector (Hdiv/Hcurl) space.
Specialization for MatrixDouble vector field values calculation.
Element used to execute operators on side of the element.
Template struct for dimension-specific finite element types.
MoFEMErrorCode postProcess()
Post-processing function executed at loop completion.
static RefineTrianglesReturn refineTriangle(int nb_levels)
create uniform triangle mesh of refined elements
Definition Tools.cpp:724
static MatrixDouble refineTriangleIntegrationPts(MatrixDouble pts, RefineTrianglesReturn refined)
generate integration points for refined triangle mesh for last level
Definition Tools.cpp:791
static MoFEMErrorCode getLocalCoordinatesOnReferenceThreeNodeTri(const double *elem_coords, const double *glob_coords, const int nb_nodes, double *local_coords)
Get the local coordinates on reference three node tri object.
Definition Tools.cpp:188
static MoFEMErrorCode getTriNormal(const double *coords, double *normal, double *d_normal=nullptr)
Get the Tri Normal objectGet triangle normal.
Definition Tools.cpp:353
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
BoundaryEle::UserDataOperator BdyEleOp
double zeta
Viscous hardening.
Definition plastic.cpp:131