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(MoFEM::Interface &m_field) {
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 PetscBool has_sdf_file_option = PETSC_FALSE;
80 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-sdf_file",
81 sdf_file_name, 255, &has_sdf_file_option);
82 std::string sdf_file = sdf_file_name;
83 if (!has_sdf_file_option) {
84 const auto contact_surface_script =
85 m_field.getInterface<JsonConfigManager>()->getPythonScriptByKey(
86 "contact_surface");
87 if (!contact_surface_script.empty()) {
88 sdf_file = contact_surface_script;
89 MOFEM_LOG("EP", Sev::inform)
90 << "Using Python script 'contact_surface' from JSON config: "
91 << sdf_file;
92 }
93 }
94
95 if (file_exists(sdf_file)) {
96 MOFEM_LOG("EP", Sev::inform) << sdf_file << " file found";
97 sdf_python_ptr = boost::make_shared<ContactSDFPython>();
98 CHKERR sdf_python_ptr->sdfInit(sdf_file);
99 ContactOps::sdfPythonWeakPtr = sdf_python_ptr;
100 MOFEM_LOG("EP", Sev::inform) << "SdfPython initialized";
101 } else {
102 MOFEM_LOG("EP", Sev::warning) << sdf_file << " file NOT found";
103 }
104
105#endif // ENABLE_PYTHON_BINDING
106
107 return sdf_python_ptr;
108};
109
111 : public PostProcBrokenMeshInMoabBase<FaceElementForcesAndSourcesCore> {
112
114 using Base::refElementsMap;
115
117 boost::shared_ptr<moab::Core> core_mesh_ptr, int max_order,
118 std::map<int, Range> &&body_map);
120 if (treeSurfPtr) {
121 treeSurfPtr->delete_tree(rootSetSurf);
122 }
123 }
126 inline boost::shared_ptr<OrientedBoxTreeTool> &getTreeSurfPtr() {
127 return treeSurfPtr;
128 }
129 inline auto getRootSetSurf() { return rootSetSurf; }
130 int getMaxLevel() const { return refElementsMap.at(MBTRI)->defMaxLevel; }
131
132 friend struct OpMoveNode;
133 friend struct OpTreeSearch;
134
135 struct FaceData {
136 int gaussPtNb; //< integration points number
137 std::array<double, 3> slavePoint;
138 std::array<double, 3> masterPoint;
139 std::array<double, 3> rayPoint;
140 std::array<double, 3> unitRay;
141 double eleRadius;
142
143 // std::vector<int> dofsSlaveIds;
144 // std::vector<double> dofsSlaveCoeff;
145 // std::vector<double> baseSlaveFuncs;
146
147 std::array<double, 9> masterPointNodes;
148 std::array<double, 9> masterTractionNodes;
149 std::array<double, 9> slavePointNodes;
150 std::array<double, 9> slaveTractionNodes;
151
152 FaceData() = default;
153 };
154
155 using MapFaceData = std::map<EntityHandle, std::vector<FaceData>>;
156
157 inline auto findFaceDataVecPtr(EntityHandle fe_ent) {
158 auto &map_face_data = shadowDataMap;
159 auto it = map_face_data.find(fe_ent);
160 if (it == map_face_data.end()) {
161 return (std::vector<FaceData> *)nullptr;
162 }
163 return &(it->second);
164 }
165
166 inline auto getFaceDataPtr(std::vector<FaceData>::iterator &it, int gg,
167 std::vector<FaceData> *vec_ptr) {
168 FaceData *face_data_ptr = nullptr;
169 if (it != vec_ptr->end()) {
170 if (it->gaussPtNb == gg) {
171 face_data_ptr = &(*it);
172 ++it;
173 }
174 }
175 return face_data_ptr;
176 }
177
178protected:
180 boost::shared_ptr<OrientedBoxTreeTool> treeSurfPtr;
181 EntityHandle rootSetSurf;
182
184 // Tag thCoeff;
185 // Tag thIds;
186 // Tag thBases;
191
193
194 std::map<int, Range> bodyMap;
195
196 const int maxOrder;
197};
198
199auto checkSdf(EntityHandle fe_ent, std::map<int, Range> &sdf_map_range) {
200 for (auto &m_sdf : sdf_map_range) {
201 if (m_sdf.second.find(fe_ent) != m_sdf.second.end())
202 return m_sdf.first;
203 }
204 return -1;
205}
206
207template <typename OP_PTR>
208auto getSdf(OP_PTR op_ptr, MatrixDouble &contact_disp, int block_id,
209 bool eval_hessian) {
210
211 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
212
213 auto ts_time = op_ptr->getTStime();
214 auto ts_time_step = op_ptr->getTStimeStep();
217 ts_time_step = EshelbianCore::physicalDt;
218 }
219
220 auto m_spatial_coords = ContactOps::get_spatial_coords(
221 op_ptr->getFTensor1CoordsAtGaussPts(),
222 getFTensor1FromMat<3>(contact_disp), nb_gauss_pts);
223 auto m_normals_at_pts = ContactOps::get_normalize_normals(
224 op_ptr->getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
226 ts_time_step, ts_time, nb_gauss_pts, m_spatial_coords, m_normals_at_pts,
227 block_id);
229 ts_time_step, ts_time, nb_gauss_pts, m_spatial_coords, m_normals_at_pts,
230 block_id);
231
232#ifndef NDEBUG
233 if (v_sdf.size() != nb_gauss_pts)
235 "Wrong number of integration pts");
236 if (m_grad_sdf.size1() != nb_gauss_pts)
238 "Wrong number of integration pts");
239 if (m_grad_sdf.size2() != 3)
240 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Should be size of 3");
241#endif // NDEBUG
242
243 if (eval_hessian) {
245 ts_time_step, ts_time, nb_gauss_pts, m_spatial_coords, m_normals_at_pts,
246 block_id);
247 return std::make_tuple(block_id, m_normals_at_pts, v_sdf, m_grad_sdf,
248 m_hess_sdf);
249 } else {
250
251 return std::make_tuple(block_id, m_normals_at_pts, v_sdf, m_grad_sdf,
252 MatrixDouble(6, nb_gauss_pts, 0.));
253 }
254};
255
256/**
257 * @brief Calculate points data on contact surfaces
258 *
259 * @tparam T1
260 * @param unit_ray
261 * @param point
262 * @param elem_point_nodes
263 * @param elem_traction_nodes
264 * @param t_spatial_coords
265 * @return auto
266 */
267template <typename T1>
269
270 std::array<double, 3> &unit_ray, std::array<double, 3> &point,
271
272 std::array<double, 9> &elem_point_nodes,
273 std::array<double, 9> &elem_traction_nodes,
274
275 FTensor::Tensor1<T1, 3> &t_spatial_coords) {
276 FTensor::Index<'i', 3> i;
277
278 auto t_unit_ray = getFTensor1FromPtr<3>(unit_ray.data());
279 auto t_point = getFTensor1FromPtr<3>(point.data());
280
281 auto get_normal = [](auto &ele_coords) {
283 Tools::getTriNormal(ele_coords.data(), &t_normal(0));
284 return t_normal;
285 };
286
287 auto t_normal = get_normal(elem_point_nodes);
288 t_normal(i) /= t_normal.l2();
289
290 auto sn = t_normal(i) * t_point(i);
291 auto nm = t_normal(i) * t_spatial_coords(i);
292 auto nr = t_normal(i) * t_unit_ray(i);
293
294 auto gamma = (sn - nm) / nr;
295
296 FTensor::Tensor1<T1, 3> t_point_current;
297 t_point_current(i) = t_spatial_coords(i) + gamma * t_unit_ray(i);
298
299 auto get_local_point_shape_functions = [&](auto &&t_elem_coords,
300 auto &t_point) {
301 std::array<T1, 2> loc_coords;
304 &t_elem_coords(0, 0), &t_point(0), 1, loc_coords.data()),
305 "get local coords");
306 return FTensor::Tensor1<T1, 3>{N_MBTRI0(loc_coords[0], loc_coords[1]),
307 N_MBTRI1(loc_coords[0], loc_coords[1]),
308 N_MBTRI2(loc_coords[0], loc_coords[1])};
309 };
310
311 auto eval_position = [&](auto &&t_field, auto &t_shape_fun) {
312 FTensor::Index<'i', 3> i;
313 FTensor::Index<'j', 3> j;
314 FTensor::Tensor1<T1, 3> t_point_out;
315 t_point_out(i) = t_shape_fun(j) * t_field(j, i);
316 return t_point_out;
317 };
318
319 auto t_shape_fun = get_local_point_shape_functions(
320 getFTensor2FromPtr<3, 3>(elem_point_nodes.data()), t_point_current);
321 auto t_slave_point_updated = eval_position(
322 getFTensor2FromPtr<3, 3>(elem_point_nodes.data()), t_shape_fun);
323 auto t_traction_updated = eval_position(
324 getFTensor2FromPtr<3, 3>(elem_traction_nodes.data()), t_shape_fun);
325
326 return std::make_tuple(t_slave_point_updated, t_traction_updated, t_normal);
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->masterPoint,
338 face_data_ptr->masterPointNodes,
339 face_data_ptr->masterTractionNodes, t_spatial_coords);
340};
341
342template <typename T1>
344
345 ContactTree::FaceData *face_data_ptr,
346 FTensor::Tensor1<T1, 3> &t_spatial_coords
347
348) {
349
350 return multiPoint(face_data_ptr->unitRay, face_data_ptr->slavePoint,
351 face_data_ptr->slavePointNodes,
352 face_data_ptr->slaveTractionNodes, t_spatial_coords);
353};
354
355/**
356 * Evaluate gap and tractions between master and slave points
357 */
358template <typename T1>
360 FTensor::Tensor1<T1, 3> &t_spatial_coords) {
361
362 auto [t_slave_point_current, t_slave_traction_current, t_slave_normal] =
363 multiSlavePoint(face_data_ptr, t_spatial_coords);
364 auto [t_master_point_current, t_master_traction_current, t_master_normal] =
365 multiMasterPoint(face_data_ptr, t_spatial_coords);
366
367 FTensor::Index<'i', 3> i;
368
370 t_normal(i) = t_master_normal(i) - t_slave_normal(i);
371 t_normal.normalize();
372
373 auto gap = t_normal(i) * (t_slave_point_current(i) - t_spatial_coords(i));
374 auto tn_master = t_master_traction_current(i) * t_normal(i);
375 auto tn_slave = t_slave_traction_current(i) * t_normal(i);
376 auto tn = std::max(-tn_master, tn_slave);
377
378 return std::make_tuple(gap, tn_master, tn_slave,
379 ContactOps::constrain(gap, tn),
380 t_master_traction_current, t_slave_traction_current);
381};
382
384
385/** Caluclate rhs term for contact
386 */
387template <typename T1, typename T2, typename T3>
389
390 ContactTree::FaceData *face_data_ptr, FTensor::Tensor1<T1, 3> &t_coords,
391 FTensor::Tensor1<T2, 3> &t_spatial_coords,
393 bool debug = false
394
395) {
396 FTensor::Index<'i', 3> i;
397 FTensor::Index<'j', 3> j;
398
400 t_u(i) = t_spatial_coords(i) - t_coords(i);
401
403
404 switch (type) {
406
407 auto [t_slave_point_current, t_slave_traction_current, t_slave_normal] =
408 multiSlavePoint(face_data_ptr, t_spatial_coords);
409 auto [t_master_point_current, t_master_traction_current, t_master_normal] =
410 multiMasterPoint(face_data_ptr, t_spatial_coords);
411
412 // average normal surface
414 t_normal(i) = t_master_normal(i) - t_slave_normal(i);
415 t_normal.normalize();
416
417 // get projection operators
419 t_P(i, j) = t_normal(i) * t_normal(j);
421 t_Q(i, j) = kronecker_delta(i, j) - t_P(i, j);
422
423 constexpr double beta = 0.5;
424
425 auto zeta = 1e-8 * face_data_ptr->eleRadius;
428
429 // this is regularised std::min(d,s)
430 auto f_min_gap = [zeta](auto d, auto s) {
431 return 0.5 * (d + s - std::sqrt((d - s) * (d - s) + zeta));
432 };
433 // this derivative of regularised std::min(d,s)
434 auto f_diff_min_gap = [zeta](auto d, auto s) {
435 return 0.5 * (1 - (d - s) / std::sqrt((d - s) * (d - s) + zeta));
436 };
437
438 // add penalty on penetration side
439 auto f_barrier = [alpha1, alpha2, f_min_gap, f_diff_min_gap](auto g,
440 auto tn) {
441 auto d = alpha1 * g;
442 auto b1 =
443 0.5 * (tn + f_min_gap(d, tn) + f_diff_min_gap(d, tn) * (d - tn));
444 auto b2 = alpha2 * f_min_gap(g, 0) * g;
445 return b1 - b2;
446 };
447
448 FTensor::Tensor1<T2, 3> t_gap_vec;
449 t_gap_vec(i) = beta * t_spatial_coords(i) +
450 (1 - beta) * t_slave_point_current(i) - t_spatial_coords(i);
452 t_traction_vec(i) =
453 -beta * t_master_traction(i) + (beta - 1) * t_slave_traction_current(i);
454
455 auto t_gap = t_normal(i) * t_gap_vec(i);
456 auto t_tn = t_normal(i) * t_traction_vec(i);
457 auto barrier = f_barrier(t_gap, t_tn);
458
460 // add penalty on penetration side
461 t_traction_bar(i) = t_normal(i) * barrier;
462
463 t_rhs(i) =
464
465 t_Q(i, j) * t_master_traction(j) +
466
467 t_P(i, j) * (t_master_traction(j) - t_traction_bar(j));
468
469 if (debug) {
470 auto is_nan_or_inf = [](double value) -> bool {
471 return std::isnan(value) || std::isinf(value);
472 };
473
474 double v = std::complex<double>(t_rhs(i) * t_rhs(i)).real();
475 if (is_nan_or_inf(v)) {
476 MOFEM_LOG_CHANNEL("SELF");
477 MOFEM_LOG("SELF", Sev::error) << "t_rhs " << t_rhs;
478 CHK_MOAB_THROW(MOFEM_DATA_INCONSISTENCY, "rhs is nan or inf");
479 }
480 }
481
482 } break;
485 break;
486 }
487
488 return t_rhs;
489};
490
493 const std::string row_field_name,
494 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
495 boost::shared_ptr<ContactTree> contact_tree_ptr,
496 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr = nullptr);
497
499
500private:
501 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
502 boost::shared_ptr<ContactTree> contactTreePtr;
503 boost::shared_ptr<std::map<int, Range>> sdfMapRangePtr;
504};
505
507 const std::string row_field_name,
508 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
509 boost::shared_ptr<ContactTree> contact_tree_ptr,
510 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr)
511 : ContactOps::AssemblyBoundaryEleOp(row_field_name, row_field_name,
512 ContactOps::BoundaryEleOp::OPROW),
513 commonDataPtr(common_data_ptr), contactTreePtr(contact_tree_ptr),
514 sdfMapRangePtr(sdf_map_range_ptr) {
515 CHK_THROW_MESSAGE(PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn",
517 PETSC_NULLPTR),
518 "get cn failed");
521 PetscOptionsGetScalar(PETSC_NULLPTR, "", "-alpha_contact_const",
522 &ContactOps::alpha_contact_const, PETSC_NULLPTR),
523 "get alpha contact failed");
525 PETSC_NULLPTR, "", "-alpha_contact_quadratic",
527 "get alpha contact failed");
529 PetscOptionsGetScalar(PETSC_NULLPTR, "", "-airplane_ray_distance",
530 &ContactOps::airplane_ray_distance, PETSC_NULLPTR),
531 "get alpha contact failed");
532
533 MOFEM_LOG("EP", Sev::inform) << "cn " << ContactOps::cn_contact;
534 MOFEM_LOG("EP", Sev::inform)
535 << "alpha_contact_const " << ContactOps::alpha_contact_const;
536 MOFEM_LOG("EP", Sev::inform)
537 << "alpha_contact_quadratic " << ContactOps::alpha_contact_quadratic;
538 MOFEM_LOG("EP", Sev::inform)
539 << "airplane_ray_distance " << ContactOps::airplane_ray_distance;
540}
541
545
546 FTensor::Index<'i', 3> i;
547 FTensor::Index<'j', 3> j;
548 FTensor::Index<'k', 3> k;
549 FTensor::Index<'l', 3> l;
550
551 const size_t nb_gauss_pts = getGaussPts().size2();
552
553#ifndef NDEBUG
554 if (commonDataPtr->contactDisp.size1() != nb_gauss_pts) {
555 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
556 "Wrong number of integration pts %ld != %ld",
557 commonDataPtr->contactDisp.size1(), nb_gauss_pts);
558 }
559#endif // !NDEBUG
560
561 auto &nf = locF;
562 locF.clear();
563
564 auto t_w = getFTensor0IntegrationWeight();
565 auto t_coords = getFTensor1CoordsAtGaussPts();
566 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
567 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
568
569 // placeholder to pass boundary block id to python. default SDF is set on
570 // block = -1, one can choose different block by making block "CONTACT_SDF",
571 // then specific SDF can be set to that block.
572 auto [block_id, m_normals_at_pts, v_sdf, m_grad_sdf, m_hess_sdf] =
573 getSdf(this, commonDataPtr->contactDisp,
574 checkSdf(getFEEntityHandle(), *sdfMapRangePtr), false);
575
576 auto t_sdf_v = getFTensor0FromVec(v_sdf);
577 auto t_grad_sdf_v = getFTensor1FromMat<3>(m_grad_sdf);
578 auto t_normalize_normal = getFTensor1FromMat<3>(m_normals_at_pts);
579
580 auto next = [&]() {
581 ++t_w;
582 ++t_coords;
583 ++t_disp;
584 ++t_traction;
585 ++t_normalize_normal;
586 ++t_sdf_v;
587 ++t_grad_sdf_v;
588 };
589
590 auto face_data_vec_ptr =
591 contactTreePtr->findFaceDataVecPtr(getFEEntityHandle());
592 auto face_gauss_pts_it = face_data_vec_ptr->begin();
593
594 auto nb_base_functions = data.getN().size2();
595 auto t_base = data.getFTensor0N();
596 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
597
599 auto face_data_ptr = contactTreePtr->getFaceDataPtr(face_gauss_pts_it, gg,
600 face_data_vec_ptr);
601
602 auto check_face_contact = [&]() {
603 if (checkSdf(getFEEntityHandle(), *sdfMapRangePtr) != -1)
604 return false;
605
606 if (face_data_ptr) {
607 return true;
608 }
609 return false;
610 };
611
612#ifdef ENABLE_PYTHON_BINDING
613 double c = 0.;
614 if (ContactOps::sdfPythonWeakPtr.lock()) {
615 auto tn = t_traction(i) * t_grad_sdf_v(i);
616 c = ContactOps::constrain(t_sdf_v, tn);
617 }
618#else
619 constexpr double c = 0;
620#endif
621
622 if (!c && check_face_contact()) {
623 FTensor::Tensor1<double, 3> t_spatial_coords;
624 t_spatial_coords(i) = t_coords(i) + t_disp(i);
625 auto t_rhs_tmp = multiPointRhs(face_data_ptr, t_coords, t_spatial_coords,
626 t_traction, MultiPointRhsType::U, true);
627 t_rhs(i) = t_rhs_tmp(i);
628
629 } else {
630
631#ifdef ENABLE_PYTHON_BINDING
632 auto inv_cn = 1. / ContactOps::cn_contact;
633
634 if (ContactOps::sdfPythonWeakPtr.lock()) {
636 t_cP(i, j) = (c * t_grad_sdf_v(i)) * t_grad_sdf_v(j);
637 t_cQ(i, j) = kronecker_delta(i, j) - t_cP(i, j);
638 t_rhs(i) = t_cQ(i, j) * t_traction(j) +
639 (c * inv_cn * t_sdf_v) * t_grad_sdf_v(i);
640 } else {
641 t_rhs(i) = t_traction(i);
642 }
643#else
644 t_rhs(i) = t_traction(i);
645#endif
646 }
647
648 auto t_nf = getFTensor1FromPtr<3>(&nf[0]);
649 const double alpha = t_w * getMeasure();
650
651 size_t bb = 0;
652 for (; bb != nbRows / 3; ++bb) {
653 const double beta = alpha * t_base;
654 t_nf(i) -= beta * t_rhs(i);
655 ++t_nf;
656 ++t_base;
657 }
658 for (; bb < nb_base_functions; ++bb)
659 ++t_base;
660
661 next();
662 }
663
665}
666
667template <AssemblyType A, IntegrationType I> struct OpConstrainBoundaryHDivRhs;
668
669template <AssemblyType A>
671 : public FormsIntegrators<FaceUserDataOperator>::Assembly<A>::OpBrokenBase {
672
675
677 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
678 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
679 boost::shared_ptr<ContactTree> contact_tree_ptr);
680
681 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
682
683private:
684 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
685 boost::shared_ptr<ContactTree> contactTreePtr;
686};
687
688template <AssemblyType A>
691 boost::shared_ptr<std::vector<BrokenBaseSideData>>
692 broken_base_side_data,
693 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
694 boost::shared_ptr<ContactTree> contact_tree_ptr)
695 : OP(broken_base_side_data), commonDataPtr(common_data_ptr),
696 contactTreePtr(contact_tree_ptr) {}
697
698template <AssemblyType A>
702
707
708 const size_t nb_gauss_pts = OP::getGaussPts().size2();
709
710#ifndef NDEBUG
711 if (commonDataPtr->contactDisp.size1() != nb_gauss_pts) {
712 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
713 "Wrong number of integration pts %ld != %ld",
714 commonDataPtr->contactDisp.size1(), nb_gauss_pts);
715 }
716#endif // !NDEBUG
717
718 auto &nf = OP::locF;
719 OP::locF.clear();
720
721 auto t_w = OP::getFTensor0IntegrationWeight();
722 auto t_material_normal = OP::getFTensor1NormalsAtGaussPts();
723 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
724
725 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
726 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
727
728 auto next = [&]() {
729 ++t_w;
730 ++t_disp;
731 ++t_traction;
732 ++t_coords;
733 ++t_material_normal;
734 };
735
736 auto face_data_vec_ptr =
737 contactTreePtr->findFaceDataVecPtr(OP::getFEEntityHandle());
738 auto face_gauss_pts_it = face_data_vec_ptr->begin();
739
740 auto nb_base_functions = data.getN().size2() / 3;
741 auto t_base = data.getFTensor1N<3>();
742 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
743
744 auto t_nf = getFTensor1FromPtr<3>(&nf[0]);
745 const double alpha = t_w / 2.;
746
747 size_t bb = 0;
748 for (; bb != OP::nbRows / 3; ++bb) {
749 const double beta = alpha * t_base(i) * t_material_normal(i);
750 t_nf(i) += beta * t_disp(i);
751 ++t_nf;
752 ++t_base;
753 }
754 for (; bb < nb_base_functions; ++bb)
755 ++t_base;
756
757 next();
758 }
759
761}
762
764
766 const std::string row_field_name, const std::string col_field_name,
767 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
768 boost::shared_ptr<ContactTree> contact_tree_ptr,
769 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr = nullptr);
770
773
774private:
775 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
776 boost::shared_ptr<ContactTree> contactTreePtr;
777 boost::shared_ptr<std::map<int, Range>> sdfMapRangePtr;
778};
779
781 const std::string row_field_name, const std::string col_field_name,
782 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
783 boost::shared_ptr<ContactTree> contact_tree_ptr,
784 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr)
785 : ContactOps::AssemblyBoundaryEleOp(row_field_name, col_field_name,
786 ContactOps::BoundaryEleOp::OPROWCOL),
787 commonDataPtr(common_data_ptr), contactTreePtr(contact_tree_ptr),
788 sdfMapRangePtr(sdf_map_range_ptr) {
789
790 sYmm = false;
791}
792
795 EntitiesFieldData::EntData &col_data) {
797
798 using namespace ContactOps;
799
800 FTensor::Index<'i', 3> i;
801 FTensor::Index<'j', 3> j;
802 FTensor::Index<'k', 3> k;
803
804 auto nb_rows = row_data.getIndices().size();
805 auto nb_cols = col_data.getIndices().size();
806
807 auto &locMat = AssemblyBoundaryEleOp::locMat;
808 locMat.resize(nb_rows, nb_cols, false);
809 locMat.clear();
810
811 if (nb_cols && nb_rows) {
812
813 auto nb_gauss_pts = getGaussPts().size2();
814 auto t_w = getFTensor0IntegrationWeight();
815 auto t_coords = getFTensor1CoordsAtGaussPts();
816 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
817 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
818
819 // placeholder to pass boundary block id to python
820 auto [block_id, m_normals_at_pts, v_sdf, m_grad_sdf, m_hess_sdf] =
821 getSdf(this, commonDataPtr->contactDisp,
822 checkSdf(getFEEntityHandle(), *sdfMapRangePtr), true);
823
824 auto t_sdf_v = getFTensor0FromVec(v_sdf);
825 auto t_grad_sdf_v = getFTensor1FromMat<3>(m_grad_sdf);
826 auto t_hess_sdf_v = getFTensor2SymmetricFromMat<3>(m_hess_sdf);
827 auto t_normalized_normal = getFTensor1FromMat<3>(m_normals_at_pts);
828
829 auto next = [&]() {
830 ++t_w;
831 ++t_coords;
832 ++t_disp;
833 ++t_traction;
834 ++t_sdf_v;
835 ++t_grad_sdf_v;
836 ++t_hess_sdf_v;
837 ++t_normalized_normal;
838 };
839
840 auto face_data_vec_ptr =
841 contactTreePtr->findFaceDataVecPtr(getFEEntityHandle());
842 auto face_gauss_pts_it = face_data_vec_ptr->begin();
843
844 auto t_row_base = row_data.getFTensor0N();
845 auto nb_face_functions = row_data.getN().size2() / 3;
846 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
847
848 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
849
850 auto face_data_ptr = contactTreePtr->getFaceDataPtr(face_gauss_pts_it, gg,
851 face_data_vec_ptr);
852
853 auto check_face_contact = [&]() {
854 if (checkSdf(getFEEntityHandle(), *sdfMapRangePtr) != -1)
855 return false;
856
857 if (face_data_ptr) {
858 return true;
859 }
860 return false;
861 };
862
864
865#ifdef ENABLE_PYTHON_BINDING
866 double c = 0.;
867 if (ContactOps::sdfPythonWeakPtr.lock()) {
868 auto tn = t_traction(i) * t_grad_sdf_v(i);
869 c = ContactOps::constrain(t_sdf_v, tn);
870 }
871#else
872 constexpr double c = 0;
873#endif
874
875 if (!c && check_face_contact()) {
876 FTensor::Tensor1<double, 3> t_spatial_coords;
877 t_spatial_coords(i) = t_coords(i) + t_disp(i);
878 constexpr double eps = std::numeric_limits<float>::epsilon();
879 for (auto ii = 0; ii < 3; ++ii) {
880 FTensor::Tensor1<std::complex<double>, 3> t_spatial_coords_cx{
881 t_spatial_coords(0), t_spatial_coords(1), t_spatial_coords(2)};
882 t_spatial_coords_cx(ii) += eps * 1i;
883 auto t_rhs_tmp =
884 multiPointRhs(face_data_ptr, t_coords, t_spatial_coords_cx,
885 t_traction, MultiPointRhsType::U);
886 for (int jj = 0; jj != 3; ++jj) {
887 auto v = t_rhs_tmp(jj).imag();
888 t_res_dU(jj, ii) = v / eps;
889 }
890 }
891
892 } else {
893
894#ifdef ENABLE_PYTHON_BINDING
895
896 if (ContactOps::sdfPythonWeakPtr.lock()) {
897 auto inv_cn = 1. / ContactOps::cn_contact;
898 t_res_dU(i, j) =
899
900 (-c) * (t_hess_sdf_v(i, j) * t_grad_sdf_v(k) * t_traction(k) +
901 t_grad_sdf_v(i) * t_hess_sdf_v(k, j) * t_traction(k))
902
903 + (c * inv_cn) * (t_sdf_v * t_hess_sdf_v(i, j) +
904
905 t_grad_sdf_v(j) * t_grad_sdf_v(i));
906 } else {
907 t_res_dU(i, j) = 0;
908 }
909#else
910 t_res_dU(i, j) = 0;
911#endif
912 }
913
914 auto alpha = t_w * getMeasure();
915
916 size_t rr = 0;
917 for (; rr != nb_rows / 3; ++rr) {
918
919 auto t_mat = getFTensor2FromArray<3, 3, 3>(locMat, 3 * rr);
920 auto t_col_base = col_data.getFTensor0N(gg, 0);
921
922 for (size_t cc = 0; cc != nb_cols / 3; ++cc) {
923 auto beta = alpha * t_row_base * t_col_base;
924 t_mat(i, j) -= beta * t_res_dU(i, j);
925 ++t_col_base;
926 ++t_mat;
927 }
928
929 ++t_row_base;
930 }
931 for (; rr < nb_face_functions; ++rr)
932 ++t_row_base;
933
934 next();
935 }
936 }
937
939}
940
941template <AssemblyType A, IntegrationType I> struct OpConstrainBoundaryL2Lhs_dP;
942
943template <AssemblyType A>
945 : public FormsIntegrators<FaceUserDataOperator>::Assembly<A>::OpBrokenBase {
946
949
951 std::string row_field_name,
952 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
953 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
954 boost::shared_ptr<ContactTree> contact_tree_ptr,
955 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr = nullptr);
956
957 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
959
960private:
961 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
962 boost::shared_ptr<ContactTree> contactTreePtr;
963 boost::shared_ptr<std::map<int, Range>> sdfMapRangePtr;
964};
965
966template <AssemblyType A>
969 std::string row_field_name,
970 boost::shared_ptr<std::vector<BrokenBaseSideData>>
971 broken_base_side_data,
972 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
973 boost::shared_ptr<ContactTree> contact_tree_ptr,
974 boost::shared_ptr<std::map<int, Range>> sdf_map_range_ptr)
975 : OP(row_field_name, broken_base_side_data, false, false),
976 commonDataPtr(common_data_ptr), contactTreePtr(contact_tree_ptr),
977 sdfMapRangePtr(sdf_map_range_ptr) {
978 OP::sYmm = false;
979}
980
981template <AssemblyType A>
985 EntitiesFieldData::EntData &col_data) {
987
988 using namespace ContactOps;
989
990 FTensor::Index<'i', 3> i;
991 FTensor::Index<'j', 3> j;
992 FTensor::Index<'k', 3> k;
993
994 auto nb_rows = row_data.getIndices().size();
995 auto nb_cols = col_data.getIndices().size();
996
997 auto &locMat = AssemblyBoundaryEleOp::locMat;
998 locMat.resize(nb_rows, nb_cols, false);
999 locMat.clear();
1000
1001 if (nb_cols && nb_rows) {
1002
1003 const size_t nb_gauss_pts = OP::getGaussPts().size2();
1004
1005 auto t_w = OP::getFTensor0IntegrationWeight();
1006 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
1007 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
1008 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1009 auto t_material_normal = OP::getFTensor1NormalsAtGaussPts();
1010
1011 // placeholder to pass boundary block id to python
1012 auto [block_id, m_normals_at_pts, v_sdf, m_grad_sdf, m_hess_sdf] =
1013 getSdf(this, commonDataPtr->contactDisp,
1014 checkSdf(OP::getFEEntityHandle(), *sdfMapRangePtr), false);
1015
1016 auto t_sdf_v = getFTensor0FromVec(v_sdf);
1017 auto t_grad_sdf_v = getFTensor1FromMat<3>(m_grad_sdf);
1018
1019 auto next = [&]() {
1020 ++t_w;
1021 ++t_disp;
1022 ++t_traction;
1023 ++t_coords;
1024 ++t_material_normal;
1025 ++t_sdf_v;
1026 ++t_grad_sdf_v;
1027 };
1028
1029 auto face_data_vec_ptr =
1030 contactTreePtr->findFaceDataVecPtr(OP::getFEEntityHandle());
1031 auto face_gauss_pts_it = face_data_vec_ptr->begin();
1032
1033 auto t_row_base = row_data.getFTensor0N();
1034 auto nb_face_functions = row_data.getN().size2();
1035
1036 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
1037
1038 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1039
1040 auto face_data_ptr = contactTreePtr->getFaceDataPtr(face_gauss_pts_it, gg,
1041 face_data_vec_ptr);
1042
1043 auto check_face_contact = [&]() {
1044 if (checkSdf(OP::getFEEntityHandle(), *sdfMapRangePtr) != -1)
1045 return false;
1046
1047 if (face_data_ptr) {
1048 return true;
1049 }
1050 return false;
1051 };
1052
1054
1055#ifdef ENABLE_PYTHON_BINDING
1056 double c = 0.;
1057 if (ContactOps::sdfPythonWeakPtr.lock()) {
1058 auto tn = t_traction(i) * t_grad_sdf_v(i);
1059 c = ContactOps::constrain(t_sdf_v, tn);
1060 }
1061#else
1062 constexpr double c = 0;
1063#endif
1064
1065 if (!c && check_face_contact()) {
1066 FTensor::Tensor1<double, 3> t_spatial_coords;
1067 t_spatial_coords(i) = t_coords(i) + t_disp(i);
1068 constexpr double eps = std::numeric_limits<float>::epsilon();
1069 for (auto ii = 0; ii != 3; ++ii) {
1070 FTensor::Tensor1<std::complex<double>, 3> t_traction_cx{
1071 t_traction(0), t_traction(1), t_traction(2)};
1072 t_traction_cx(ii) += eps * 1i;
1073 auto t_rhs_tmp =
1074 multiPointRhs(face_data_ptr, t_coords, t_spatial_coords,
1075 t_traction_cx, MultiPointRhsType::U);
1076 for (int jj = 0; jj != 3; ++jj) {
1077 auto v = t_rhs_tmp(jj).imag();
1078 t_res_dP(jj, ii) = v / eps;
1079 }
1080 }
1081 } else {
1082
1083#ifdef ENABLE_PYTHON_BINDING
1084 if (ContactOps::sdfPythonWeakPtr.lock()) {
1086 t_cP(i, j) = (c * t_grad_sdf_v(i)) * t_grad_sdf_v(j);
1087 t_cQ(i, j) = kronecker_delta(i, j) - t_cP(i, j);
1088 t_res_dP(i, j) = t_cQ(i, j);
1089 } else {
1090 t_res_dP(i, j) = t_kd(i, j);
1091 }
1092#else
1093 t_res_dP(i, j) = t_kd(i, j);
1094#endif
1095 }
1096
1097 const double alpha = t_w / 2.;
1098 size_t rr = 0;
1099 for (; rr != nb_rows / 3; ++rr) {
1100
1101 auto t_mat = getFTensor2FromArray<3, 3, 3>(locMat, 3 * rr);
1102 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1103
1104 for (size_t cc = 0; cc != nb_cols / 3; ++cc) {
1105 auto col_base = t_col_base(i) * t_material_normal(i);
1106 const double beta = alpha * t_row_base * col_base;
1107 t_mat(i, j) -= beta * t_res_dP(i, j);
1108 ++t_col_base;
1109 ++t_mat;
1110 }
1111
1112 ++t_row_base;
1113 }
1114 for (; rr < nb_face_functions; ++rr)
1115 ++t_row_base;
1116
1117 next();
1118 }
1119 }
1120
1122}
1123
1124template <AssemblyType A, IntegrationType I>
1126
1127template <AssemblyType A>
1129 : public FormsIntegrators<FaceUserDataOperator>::Assembly<A>::OpBrokenBase {
1130
1133
1135 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
1136 std::string col_field_name,
1137 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
1138 boost::shared_ptr<ContactTree> contact_tree_ptr);
1139
1140 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
1141 EntitiesFieldData::EntData &col_data);
1142
1143private:
1144 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
1145 boost::shared_ptr<ContactTree> contactTreePtr;
1146};
1147
1148template <AssemblyType A>
1151 boost::shared_ptr<std::vector<BrokenBaseSideData>>
1152 broken_base_side_data,
1153 std::string col_field_name,
1154 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
1155 boost::shared_ptr<ContactTree> contact_tree_ptr)
1156 : OP(col_field_name, broken_base_side_data, true, true),
1157 commonDataPtr(common_data_ptr), contactTreePtr(contact_tree_ptr) {
1158 OP::sYmm = false;
1159}
1160
1161template <AssemblyType A>
1165 EntitiesFieldData::EntData &row_data) {
1167
1168 // Note: col_data and row_data are swapped in this function, we going to
1169 // transpose locMat at the end
1170
1171 using namespace ContactOps;
1172
1176
1177 auto nb_rows = row_data.getIndices().size();
1178 auto nb_cols = col_data.getIndices().size();
1179
1180 auto &locMat = AssemblyBoundaryEleOp::locMat;
1181 locMat.resize(nb_rows, nb_cols, false);
1182 locMat.clear();
1183
1184 if (nb_cols && nb_rows) {
1185
1186 const size_t nb_gauss_pts = OP::getGaussPts().size2();
1187
1188 auto t_w = OP::getFTensor0IntegrationWeight();
1189 auto t_disp = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
1190 auto t_traction = getFTensor1FromMat<3>(commonDataPtr->contactTraction);
1191 auto t_coords = OP::getFTensor1CoordsAtGaussPts();
1192 auto t_material_normal = OP::getFTensor1NormalsAtGaussPts();
1193
1194 auto next = [&]() {
1195 ++t_w;
1196 ++t_disp;
1197 ++t_traction;
1198 ++t_coords;
1199 ++t_material_normal;
1200 };
1201
1202 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
1203
1204 auto face_data_vec_ptr =
1205 contactTreePtr->findFaceDataVecPtr(OP::getFEEntityHandle());
1206 auto face_gauss_pts_it = face_data_vec_ptr->begin();
1207
1208 auto t_row_base = row_data.getFTensor1N<3>();
1209 auto nb_face_functions = row_data.getN().size2() / 3;
1210 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1211
1212 const auto alpha = t_w / 2.;
1213
1214 size_t rr = 0;
1215 for (; rr != nb_rows / 3; ++rr) {
1216
1217 auto row_base = alpha * (t_row_base(i) * t_material_normal(i));
1218
1219 auto t_mat = getFTensor2FromArray<3, 3, 3>(locMat, 3 * rr);
1220 auto t_col_base = col_data.getFTensor0N(gg, 0);
1221
1222 for (size_t cc = 0; cc != nb_cols / 3; ++cc) {
1223 const auto beta = row_base * t_col_base;
1224 t_mat(i, j) += beta * t_kd(i, j);
1225 ++t_col_base;
1226 ++t_mat;
1227 }
1228
1229 ++t_row_base;
1230 }
1231 for (; rr < nb_face_functions; ++rr)
1232 ++t_row_base;
1233
1234 next();
1235 }
1236 }
1237
1238 locMat = trans(locMat);
1239
1241}
1242
1244 boost::shared_ptr<moab::Core> core_mesh_ptr,
1245 int max_order, std::map<int, Range> &&body_map)
1246 : Base(m_field, core_mesh_ptr, "contact"), maxOrder(max_order),
1247 bodyMap(body_map) {
1248
1249 auto ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBTRI>>();
1250 ref_ele_ptr->hoNodes =
1251 PETSC_FALSE; ///< So far only linear geometry is implemented for contact
1252
1253 CHK_THROW_MESSAGE(ref_ele_ptr->getOptions(optionsPrefix), "getOptions");
1254 CHK_THROW_MESSAGE(ref_ele_ptr->generateReferenceElementMesh(),
1255 "Error when generating reference element");
1256
1257 MOFEM_LOG("EP", Sev::inform) << "Contact hoNodes " << ref_ele_ptr->hoNodes
1258 ? "true"
1259 : "false";
1260 MOFEM_LOG("EP", Sev::inform)
1261 << "Contact maxOrder " << ref_ele_ptr->defMaxLevel;
1262
1263 refElementsMap[MBTRI] = ref_ele_ptr;
1264
1265 int def_ele_id = -1;
1266 CHKERR getPostProcMesh().tag_get_handle("ELE_ID", 1, MB_TYPE_INTEGER, thEleId,
1267 MB_TAG_CREAT | MB_TAG_DENSE,
1268 &def_ele_id);
1269 CHKERR getPostProcMesh().tag_get_handle("BODY_ID", 1, MB_TYPE_INTEGER,
1270 thBodyId, MB_TAG_CREAT | MB_TAG_DENSE,
1271 &def_ele_id);
1272
1273 // std::vector<int> def_ids(3 * nb_bases, 0);
1274 // CHKERR getPostProcMesh().tag_get_handle("IDS", 3 * nb_bases,
1275 // MB_TYPE_INTEGER,
1276 // thIds, MB_TAG_CREAT | MB_TAG_DENSE,
1277 // &*def_ids.begin());
1278 // std::vector<double> def_coeffs(3 * nb_bases, 0);
1279 // CHKERR getPostProcMesh().tag_get_handle("COEFF", 3 * nb_bases,
1280 // MB_TYPE_DOUBLE,
1281 // thCoeff, MB_TAG_CREAT |
1282 // MB_TAG_DENSE,
1283 // &*def_coeffs.begin());
1284 // std::vector<double> def_basses(nb_bases, 0);
1285 // CHKERR getPostProcMesh().tag_get_handle("BASES", nb_bases, MB_TYPE_DOUBLE,
1286 // thBases, MB_TAG_CREAT |
1287 // MB_TAG_DENSE,
1288 // &*def_basses.begin());
1289
1290 std::array<double, 3> def_small_x{0., 0., 0.};
1291 CHKERR getPostProcMesh().tag_get_handle("x", 3, MB_TYPE_DOUBLE, thSmallX,
1292 MB_TAG_CREAT | MB_TAG_DENSE,
1293 def_small_x.data());
1294 CHKERR getPostProcMesh().tag_get_handle("X", 3, MB_TYPE_DOUBLE, thLargeX,
1295 MB_TAG_CREAT | MB_TAG_DENSE,
1296 def_small_x.data());
1297
1298 std::array<double, 3> def_tractions{0., 0., 0.};
1299 CHKERR getPostProcMesh().tag_get_handle(
1300 "TRACTION", 3, MB_TYPE_DOUBLE, thTraction, MB_TAG_CREAT | MB_TAG_DENSE,
1301 &*def_tractions.begin());
1302}
1303
1309
1312
1313 CHKERR Base::postProcess();
1314 shadowDataMap.clear();
1315
1316 PetscBarrier(nullptr);
1317
1318 auto pcomm_post_proc_mesh = this->getPostProcMeshPcommPtr();
1319 if (pcomm_post_proc_mesh == nullptr)
1320 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY, "PComm not allocated");
1321
1322 auto brodacts = [&](auto &brodacts_ents) {
1324 Range recived_ents;
1325 for (auto rr = 0; rr != mField.get_comm_size(); ++rr) {
1326 pcomm_post_proc_mesh->broadcast_entities(
1327 rr, rr == mField.get_comm_rank() ? brodacts_ents : recived_ents,
1328 false, true);
1329 }
1331 };
1332
1333 Range brodacts_ents;
1334 CHKERR getPostProcMesh().get_entities_by_dimension(0, 2, brodacts_ents, true);
1335 CHKERR brodacts(brodacts_ents);
1336
1337 Range ents;
1338 CHKERR getPostProcMesh().get_entities_by_dimension(0, 2, ents, true);
1339 CHKERR buildTree(ents);
1340
1341#ifndef NDEBUG
1342 CHKERR writeFile("debug_tree.h5m");
1343#endif // NDEBUG
1344
1346}
1347
1350 // MOFEM_LOG("SELF", Sev::inform) << ents << endl;
1351 if (treeSurfPtr) {
1352 treeSurfPtr->delete_tree(rootSetSurf);
1353 }
1354 treeSurfPtr = boost::shared_ptr<OrientedBoxTreeTool>(
1355 new OrientedBoxTreeTool(&getPostProcMesh(), "ROOTSETSURF", true));
1356 CHKERR treeSurfPtr->build(ents, rootSetSurf);
1357 // CHKERR treeSurfPtr->stats(rootSetSurf, std::cerr);
1359}
1360
1362
1364
1365 OpMoveNode(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 MoFEMErrorCode doWork(int side, EntityType type,
1370
1371protected:
1372 boost::weak_ptr<ContactTree> contactTreePtr;
1373 boost::shared_ptr<MatrixDouble> uH1Ptr;
1374 boost::shared_ptr<ContactOps::CommonData> commonDataPtr;
1375};
1376
1378 boost::shared_ptr<ContactTree> contact_tree_ptr,
1379 boost::shared_ptr<ContactOps::CommonData> common_data_ptr,
1380 boost::shared_ptr<MatrixDouble> u_h1_ptr)
1381 : UOP(NOSPACE, UOP::OPSPACE), contactTreePtr(contact_tree_ptr),
1382 uH1Ptr(u_h1_ptr), commonDataPtr(common_data_ptr) {}
1383
1387
1388 if (auto contact_tree_ptr = contactTreePtr.lock()) {
1389
1390 auto get_body_id = [&](auto fe_ent) {
1391 for (auto &m : contact_tree_ptr->bodyMap) {
1392 if (m.second.find(fe_ent) != m.second.end()) {
1393 return m.first;
1394 }
1395 }
1396 return -1;
1397 };
1398
1399 auto &moab_post_proc_mesh = contact_tree_ptr->getPostProcMesh();
1400 auto &post_proc_ents = contact_tree_ptr->getPostProcElements();
1401
1402 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1403 auto fe_id = id_from_handle(fe_ent);
1404 auto body_id = get_body_id(fe_ent);
1405 auto &map_gauss_pts = contact_tree_ptr->getMapGaussPts();
1406
1407 CHKERR moab_post_proc_mesh.tag_clear_data(contact_tree_ptr->thEleId,
1408 post_proc_ents, &fe_id);
1409 CHKERR moab_post_proc_mesh.tag_clear_data(contact_tree_ptr->thBodyId,
1410 post_proc_ents, &body_id);
1411
1412 auto nb_gauss_pts = getGaussPts().size2();
1413 auto t_u_h1 = getFTensor1FromMat<3>(*uH1Ptr);
1414 auto t_u_l2 = getFTensor1FromMat<3>(commonDataPtr->contactDisp);
1415 auto t_coords = getFTensor1CoordsAtGaussPts();
1416
1417 MatrixDouble x_h1(nb_gauss_pts, 3);
1418 auto t_x_h1 = getFTensor1FromPtr<3>(&x_h1(0, 0));
1419 MatrixDouble x_l2(nb_gauss_pts, 3);
1420 auto t_x_l2 = getFTensor1FromPtr<3>(&x_l2(0, 0));
1421 MatrixDouble tractions = trans(commonDataPtr->contactTraction);
1422 MatrixDouble coords = getCoordsAtGaussPts();
1423
1424 FTensor::Index<'i', 3> i;
1425
1426 // VectorDouble bases(nb_bases, 0);
1427 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
1428 t_x_h1(i) = t_coords(i) + t_u_h1(i);
1429 t_x_l2(i) = t_coords(i) + t_u_l2(i);
1430
1431 ++t_coords;
1432 ++t_u_h1;
1433 ++t_u_l2;
1434 ++t_x_h1;
1435 ++t_x_l2;
1436 }
1437
1438 CHKERR moab_post_proc_mesh.set_coords(
1439 &*map_gauss_pts.begin(), map_gauss_pts.size(), &*x_h1.data().begin());
1440 CHKERR moab_post_proc_mesh.tag_set_data(
1441 contact_tree_ptr->thSmallX, &*map_gauss_pts.begin(),
1442 map_gauss_pts.size(), &*x_h1.data().begin());
1443 CHKERR moab_post_proc_mesh.tag_set_data(
1444 contact_tree_ptr->thLargeX, &*map_gauss_pts.begin(),
1445 map_gauss_pts.size(), &*coords.data().begin());
1446 CHKERR moab_post_proc_mesh.tag_set_data(
1447 contact_tree_ptr->thTraction, &*map_gauss_pts.begin(),
1448 map_gauss_pts.size(), &*tractions.data().begin());
1449
1450 } else {
1451 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1452 "ContactTree pointer expired in OpMoveNode");
1453 }
1454
1456}
1457
1459
1461
1462 OpTreeSearch(boost::shared_ptr<ContactTree> contact_tree_ptr,
1463 boost::shared_ptr<MatrixDouble> u_h1_ptr,
1464 boost::shared_ptr<MatrixDouble> traction_ptr, Range r,
1465
1466 moab::Interface *post_proc_mesh_ptr,
1467 std::vector<EntityHandle> *map_gauss_pts_ptr
1468
1469 );
1470 MoFEMErrorCode doWork(int side, EntityType type,
1472
1473protected:
1474 boost::shared_ptr<ContactTree> contactTreePtr;
1475 boost::shared_ptr<MatrixDouble> uH1Ptr;
1476 boost::shared_ptr<MatrixDouble> tractionPtr;
1477 moab::Interface *postProcMeshPtr = nullptr;
1478 std::vector<EntityHandle> *mapGaussPtsPtr = nullptr;
1479
1481};
1482
1483OpTreeSearch::OpTreeSearch(boost::shared_ptr<ContactTree> contact_tree_ptr,
1484 boost::shared_ptr<MatrixDouble> u_h1_ptr,
1485 boost::shared_ptr<MatrixDouble> traction_ptr,
1486 Range r,
1487
1488 moab::Interface *post_proc_mesh_ptr,
1489 std::vector<EntityHandle> *map_gauss_pts_ptr
1490
1491 )
1492 : UOP(NOSPACE, UOP::OPSPACE), contactTreePtr(contact_tree_ptr),
1493 uH1Ptr(u_h1_ptr), tractionPtr(traction_ptr),
1494 postProcMeshPtr(post_proc_mesh_ptr), mapGaussPtsPtr(map_gauss_pts_ptr),
1495 contactRange(r) {}
1496
1500
1501 auto &m_field = getPtrFE()->mField;
1502 auto fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1503 auto fe_id = id_from_handle(fe_ent);
1504
1505 if (contactRange.find(fe_ent) == contactRange.end())
1507
1508 FTensor::Index<'i', 3> i;
1509 FTensor::Index<'j', 3> j;
1510
1511 const auto nb_gauss_pts = getGaussPts().size2();
1512
1513 auto t_disp_h1 = getFTensor1FromMat<3>(*uH1Ptr);
1514 auto t_coords = getFTensor1CoordsAtGaussPts();
1515 auto t_traction = getFTensor1FromMat<3>(*tractionPtr);
1516
1517 auto next = [&]() {
1518 ++t_disp_h1;
1519 ++t_traction;
1520 ++t_coords;
1521 };
1522
1523 auto get_ele_centre = [i](auto t_ele_coords) {
1524 FTensor::Tensor1<double, 3> t_ele_center;
1525 t_ele_center(i) = 0;
1526 for (int nn = 0; nn != 3; nn++) {
1527 t_ele_center(i) += t_ele_coords(i);
1528 ++t_ele_coords;
1529 }
1530 t_ele_center(i) /= 3;
1531 return t_ele_center;
1532 };
1533
1534 auto get_ele_radius = [i](auto t_ele_center, auto t_ele_coords) {
1536 t_n0(i) = t_ele_center(i) - t_ele_coords(i);
1537 return t_n0.l2();
1538 };
1539
1540 auto get_face_conn = [this](auto face) {
1541 const EntityHandle *conn;
1542 int num_nodes;
1543 CHK_MOAB_THROW(contactTreePtr->getPostProcMesh().get_connectivity(
1544 face, conn, num_nodes, true),
1545 "get conn");
1546 if (num_nodes != 3) {
1547 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "face is not a triangle");
1548 }
1549 return conn;
1550 };
1551
1552 auto get_face_coords = [this](auto conn) {
1553 std::array<double, 9> coords;
1554 CHKERR contactTreePtr->getPostProcMesh().get_coords(conn, 3, coords.data());
1555 return coords;
1556 };
1557
1558 auto get_closet_face = [this](auto *point_ptr, auto r) {
1559 FTensor::Tensor1<double, 3> t_point_out;
1560 std::vector<EntityHandle> faces_out;
1562 contactTreePtr->getTreeSurfPtr()->sphere_intersect_triangles(
1563 point_ptr, r / 8, contactTreePtr->getRootSetSurf(), faces_out),
1564 "get closest faces");
1565 return faces_out;
1566 };
1567
1568 auto get_faces_out = [this](auto *point_ptr, auto *unit_ray_ptr, auto radius,
1569 auto eps) {
1570 std::vector<double> distances_out;
1571 std::vector<EntityHandle> faces_out;
1573
1574 contactTreePtr->getTreeSurfPtr()->ray_intersect_triangles(
1575 distances_out, faces_out, contactTreePtr->getRootSetSurf(), eps,
1576 point_ptr, unit_ray_ptr, &radius),
1577
1578 "get closest faces");
1579 return std::make_pair(faces_out, distances_out);
1580 };
1581
1582 auto get_normal = [](auto &ele_coords) {
1584 Tools::getTriNormal(ele_coords.data(), &t_normal(0));
1585 return t_normal;
1586 };
1587
1588 auto make_map = [&](auto &face_out, auto &face_dist, auto &t_ray_point,
1589 auto &t_unit_ray, auto &t_master_coord) {
1590 FTensor::Index<'i', 3> i;
1591 FTensor::Index<'j', 3> j;
1592 std::map<double, EntityHandle> m;
1593 for (auto ii = 0; ii != face_out.size(); ++ii) {
1594 auto face_conn = get_face_conn(face_out[ii]);
1595 auto face_coords = get_face_coords(face_conn);
1596 auto t_face_normal = get_normal(face_coords);
1597 t_face_normal.normalize();
1599 t_x(i) = t_ray_point(i) + t_unit_ray(i) * face_dist[ii];
1601 t_chi(i, j) =
1602 t_x(i) * t_face_normal(j) - t_master_coord(i) * t_unit_ray(j);
1603 if (t_unit_ray(i) * t_face_normal(i) > std::cos(M_PI / 3)) {
1604 auto dot = std::sqrt(t_chi(i, j) * t_chi(i, j));
1605 m[dot] = face_out[ii];
1606 }
1607 }
1608 return m;
1609 };
1610
1611 auto get_tag_data = [this](auto tag, auto face, auto &vec) {
1613 int tag_length;
1614 CHKERR contactTreePtr->getPostProcMesh().tag_get_length(tag, tag_length);
1615 vec.resize(tag_length);
1616 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(tag, &face, 1,
1617 &*vec.begin());
1619 };
1620
1621 auto create_tag = [this](const std::string tag_name, const int size) {
1622 double def_VAL[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
1623 Tag th;
1624 if (postProcMeshPtr) {
1625 CHKERR postProcMeshPtr->tag_get_handle(
1626 tag_name.c_str(), size, MB_TYPE_DOUBLE, th,
1627 MB_TAG_CREAT | MB_TAG_SPARSE, def_VAL);
1628 CHKERR postProcMeshPtr->tag_clear_data(th, &*mapGaussPtsPtr->begin(),
1629 mapGaussPtsPtr->size(), def_VAL);
1630 }
1631 return th;
1632 };
1633
1634 auto set_float_precision = [](const double x) {
1635 if (std::abs(x) < std::numeric_limits<float>::epsilon())
1636 return 0.;
1637 else
1638 return x;
1639 };
1640
1641 // scalars
1642 auto save_scal_tag = [&](auto &th, auto v, const int gg) {
1644 if (postProcMeshPtr) {
1645 v = set_float_precision(v);
1646 CHKERR postProcMeshPtr->tag_set_data(th, &(*mapGaussPtsPtr)[gg], 1, &v);
1647 }
1649 };
1650
1651 // adjacencies
1652 auto get_fe_adjacencies = [this](auto fe_ent) {
1653 Range adj_faces;
1654 CHK_MOAB_THROW(getFaceFE()->mField.get_moab().get_adjacencies(
1655 &fe_ent, 1, 2, false, adj_faces, moab::Interface::UNION),
1656 "get adj");
1657 std::set<int> adj_ids;
1658 for (auto f : adj_faces) {
1659 adj_ids.insert(id_from_handle(f));
1660 }
1661 return adj_ids;
1662 };
1663
1664 auto get_face_id = [this](auto face) {
1665 int id;
1666 if (contactTreePtr->getPostProcMesh().tag_get_data(
1667 contactTreePtr->thEleId, &face, 1, &id) == MB_SUCCESS) {
1668 return id;
1669 }
1670 return -1;
1671 };
1672
1673 auto get_body_id = [this](auto face) {
1674 int id;
1675 if (contactTreePtr->getPostProcMesh().tag_get_data(
1676 contactTreePtr->thBodyId, &face, 1, &id) == MB_SUCCESS) {
1677 return id;
1678 }
1679 return -1;
1680 };
1681
1682 auto get_face_part = [this](auto face) {
1683 const moab::Core *core_mesh_ptr =
1684 dynamic_cast<const moab::Core *>(&contactTreePtr->getPostProcMesh());
1685 auto pcomm_post_proc_mesh =
1686 MeshPCommRegistry::getOrCreate(const_cast<moab::Core *>(core_mesh_ptr));
1687 int part;
1688 if (contactTreePtr->getPostProcMesh().tag_get_data(
1689 pcomm_post_proc_mesh->part_tag(), &face, 1, &part) == MB_SUCCESS) {
1690 return part;
1691 }
1692 return -1;
1693 };
1694
1695 auto check_face = [&](auto face, auto fe_id, auto part) {
1696 auto face_id = get_face_id(face);
1697 auto face_part = get_face_part(face);
1698 if (face_id == fe_id && face_part == part)
1699 return true;
1700 return false;
1701 };
1702
1703 // vectors
1704 VectorDouble3 v(3);
1705 FTensor::Tensor1<FTensor::PackPtr<double *, 0>, 3> t_v(&v[0], &v[1], &v[2]);
1706 auto save_vec_tag = [&](auto &th, auto &t_d, const int gg) {
1708 if (postProcMeshPtr) {
1709 t_v(i) = t_d(i);
1710 for (auto &a : v.data())
1711 a = set_float_precision(a);
1712 CHKERR postProcMeshPtr->tag_set_data(th, &(*mapGaussPtsPtr)[gg], 1,
1713 &*v.data().begin());
1714 }
1716 };
1717
1718 Tag th_mark = create_tag("contact_mark", 1);
1719 Tag th_mark_slave = create_tag("contact_mark_slave", 1);
1720 Tag th_body_id = create_tag("contact_body_id", 1);
1721 Tag th_gap = create_tag("contact_gap", 1);
1722 Tag th_tn_master = create_tag("contact_tn_master", 1);
1723 Tag th_tn_slave = create_tag("contact_tn_slave", 1);
1724 Tag th_contact_traction = create_tag("contact_traction", 3);
1725 Tag th_contact_traction_master = create_tag("contact_traction_master", 3);
1726 Tag th_contact_traction_slave = create_tag("contact_traction_slave", 3);
1727 Tag th_c = create_tag("contact_c", 1);
1728 Tag th_normal = create_tag("contact_normal", 3);
1729 Tag th_dist = create_tag("contact_dip", 3);
1730
1731 auto t_ele_centre = get_ele_centre(getFTensor1Coords());
1732 auto ele_radius = get_ele_radius(t_ele_centre, getFTensor1Coords());
1733
1734 contactTreePtr->shadowDataMap.clear();
1735 auto &shadow_vec = contactTreePtr->shadowDataMap[fe_ent];
1736 shadow_vec.clear();
1737
1738 auto adj_fe_ids = get_fe_adjacencies(fe_ent);
1739
1740 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
1741
1742 FTensor::Tensor1<double, 3> t_spatial_coords;
1743 t_spatial_coords(i) = t_coords(i) + t_disp_h1(i);
1744
1745 if (postProcMeshPtr) {
1746 CHKERR save_vec_tag(th_contact_traction, t_traction, gg);
1747 }
1748
1749 auto faces_close = get_closet_face(&t_spatial_coords(0), ele_radius);
1750 for (auto face_close : faces_close) {
1751 if (check_face(face_close, fe_id, m_field.get_comm_rank())) {
1752
1753 auto body_id = get_body_id(face_close);
1754
1755 auto master_face_conn = get_face_conn(face_close);
1756 std::array<double, 9> master_coords;
1757 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(
1758 contactTreePtr->thSmallX, master_face_conn, 3,
1759 master_coords.data());
1760 std::array<double, 9> master_traction;
1761 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(
1762 contactTreePtr->thTraction, master_face_conn, 3,
1763 master_traction.data());
1764 auto t_normal_face_close = get_normal(master_coords);
1765 t_normal_face_close.normalize();
1766
1767 if (postProcMeshPtr) {
1768 double m = 1;
1769 CHKERR save_scal_tag(th_mark, m, gg);
1770 CHKERR save_scal_tag(th_body_id, static_cast<double>(body_id), gg);
1771 CHKERR save_vec_tag(th_normal, t_normal_face_close, gg);
1772 CHKERR save_vec_tag(th_contact_traction, t_traction, gg);
1773 }
1774
1775 FTensor::Tensor1<double, 3> t_unit_ray;
1776 t_unit_ray(i) = -t_normal_face_close(i);
1777 FTensor::Tensor1<double, 3> t_ray_point;
1778 t_ray_point(i) =
1779 t_spatial_coords(i) -
1780 t_unit_ray(i) * ContactOps::airplane_ray_distance * ele_radius;
1781
1782 constexpr double eps = 1e-3;
1783 auto [faces_out, faces_dist] =
1784 get_faces_out(&t_ray_point(0), &t_unit_ray(0),
1785 2 * ContactOps::airplane_ray_distance * ele_radius,
1786 eps * ele_radius);
1787
1788 auto m = make_map(faces_out, faces_dist, t_ray_point, t_unit_ray,
1789 t_spatial_coords);
1790 for (auto m_it = m.begin(); m_it != m.end(); ++m_it) {
1791 auto face = m_it->second;
1792 if (face != face_close) {
1793
1794 if (
1795
1796 (adj_fe_ids.find(get_face_id(face)) == adj_fe_ids.end() ||
1797 get_face_part(face) != m_field.get_comm_rank())
1798
1799 ) {
1800
1801 shadow_vec.push_back(ContactTree::FaceData());
1802 shadow_vec.back().gaussPtNb = gg;
1803
1804 auto slave_face_conn = get_face_conn(face);
1805 std::array<double, 9> slave_coords;
1806 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(
1807 contactTreePtr->thSmallX, slave_face_conn, 3,
1808 slave_coords.data());
1809 auto t_normal_face = get_normal(slave_coords);
1810 std::array<double, 9> slave_tractions;
1811 CHKERR contactTreePtr->getPostProcMesh().tag_get_data(
1812 contactTreePtr->thTraction, slave_face_conn, 3,
1813 slave_tractions.data());
1814
1815 auto t_master_point =
1816 getFTensor1FromPtr<3>(shadow_vec.back().masterPoint.data());
1817 auto t_slave_point =
1818 getFTensor1FromPtr<3>(shadow_vec.back().slavePoint.data());
1819 auto t_ray_point_data =
1820 getFTensor1FromPtr<3>(shadow_vec.back().rayPoint.data());
1821 auto t_unit_ray_data =
1822 getFTensor1FromPtr<3>(shadow_vec.back().unitRay.data());
1823
1824 t_slave_point(i) = t_ray_point(i) + m_it->first * t_unit_ray(i);
1825
1826 auto eval_position = [&](auto &&t_elem_coords, auto &&t_point) {
1827 std::array<double, 2> loc_coords;
1830 &t_elem_coords(0, 0), &t_point(0), 1,
1831 loc_coords.data()),
1832 "get local coords");
1833 FTensor::Tensor1<double, 3> t_shape_fun;
1834 CHK_THROW_MESSAGE(Tools::shapeFunMBTRI<0>(&t_shape_fun(0),
1835 &loc_coords[0],
1836 &loc_coords[1], 1),
1837 "calc shape fun");
1838 FTensor::Index<'i', 3> i;
1839 FTensor::Index<'j', 3> j;
1840 FTensor::Tensor1<double, 3> t_point_out;
1841 t_point_out(i) = t_shape_fun(j) * t_elem_coords(j, i);
1842 return t_point_out;
1843 };
1844
1845 auto t_master_point_updated = eval_position(
1846 getFTensor2FromPtr<3, 3>(master_coords.data()),
1847 getFTensor1FromPtr<3>(shadow_vec.back().masterPoint.data()));
1848 t_master_point(i) = t_master_point_updated(i);
1849
1850 auto t_slave_point_updated = eval_position(
1851 getFTensor2FromPtr<3, 3>(slave_coords.data()),
1852 getFTensor1FromPtr<3>(shadow_vec.back().slavePoint.data()));
1853 t_slave_point(i) = t_slave_point_updated(i);
1854
1855 t_ray_point_data(i) = t_ray_point(i);
1856 t_unit_ray_data(i) = t_unit_ray(i);
1857
1858 std::copy(master_coords.begin(), master_coords.end(),
1859 shadow_vec.back().masterPointNodes.begin());
1860 std::copy(master_traction.begin(), master_traction.end(),
1861 shadow_vec.back().masterTractionNodes.begin());
1862 std::copy(slave_coords.begin(), slave_coords.end(),
1863 shadow_vec.back().slavePointNodes.begin());
1864 std::copy(slave_tractions.begin(), slave_tractions.end(),
1865 shadow_vec.back().slaveTractionNodes.begin());
1866
1867 shadow_vec.back().eleRadius = ele_radius;
1868
1869 // CHKERR get_tag_data(contactTreePtr->thIds, face,
1870 // shadow_vec.back().dofsSlaveIds);
1871 // CHKERR get_tag_data(contactTreePtr->thCoeff, face,
1872 // shadow_vec.back().dofsSlaveCoeff);
1873 // CHKERR get_tag_data(contactTreePtr->thBases, face,
1874 // shadow_vec.back().baseSlaveFuncs);
1875
1876 if (postProcMeshPtr) {
1877 auto [gap, tn_master, tn_slave, c, t_master_traction,
1878 t_slave_traction] =
1879 multiGetGap(&(shadow_vec.back()), t_spatial_coords);
1881 t_gap_vec(i) = t_slave_point(i) - t_spatial_coords(i);
1882 CHKERR save_scal_tag(th_gap, gap, gg);
1883 CHKERR save_scal_tag(th_tn_master, tn_master, gg);
1884 CHKERR save_scal_tag(th_tn_slave, tn_slave, gg);
1885 CHKERR save_scal_tag(th_c, c, gg);
1886 double m = 1;
1887 CHKERR save_scal_tag(th_mark_slave, m, gg);
1888 CHKERR save_vec_tag(th_dist, t_gap_vec, gg);
1889 CHKERR save_vec_tag(th_contact_traction_master,
1890 t_master_traction, gg);
1891 CHKERR save_vec_tag(th_contact_traction_slave, t_slave_traction,
1892 gg);
1893 }
1894
1895 break;
1896 }
1897 }
1898 }
1899 break;
1900 }
1901 }
1902 next();
1903 }
1904
1906}
1907
1909 const std::string block_name, int dim) {
1910 Range r;
1911
1912 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
1913 auto bcs = mesh_mng->getCubitMeshsetPtr(
1914
1915 std::regex((boost::format("%s(.*)") % block_name).str())
1916
1917 );
1918
1919 for (auto bc : bcs) {
1920 Range faces;
1921 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
1922 faces, true),
1923 "get meshset ents");
1924 r.merge(faces);
1925 }
1926
1927 return r;
1928};
1929
1930boost::shared_ptr<ForcesAndSourcesCore>
1932
1933 auto &m_field = ep.mField;
1934
1935 boost::shared_ptr<ContactTree> fe_contact_tree;
1936
1937 auto impl = [&]() {
1939
1940 /** Contact requires that body is marked */
1941 auto get_body_range = [&](auto name, int dim, auto sev) {
1942 std::map<int, Range> map;
1943
1944 for (auto m_ptr :
1945 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
1946 std::regex(
1947
1948 (boost::format("%s(.*)") % name).str()
1949
1950 ))
1951
1952 ) {
1953 Range ents;
1954 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(
1955 m_field.get_moab(), dim, ents, true),
1956 "by dim");
1957 map[m_ptr->getMeshsetId()] = ents;
1958 MOFEM_LOG("EPSYNC", sev) << "Meshset: " << m_ptr->getMeshsetId() << " "
1959 << ents.size() << " entities";
1960 }
1961
1962 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), sev);
1963 return map;
1964 };
1965
1966 auto get_map_skin = [&](auto &&map) {
1967 ParallelComm *pcomm =
1968 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
1969
1970 Skinner skin(&m_field.get_moab());
1971 for (auto &m : map) {
1972 Range skin_faces;
1973 CHKERR skin.find_skin(0, m.second, false, skin_faces);
1974 CHK_MOAB_THROW(pcomm->filter_pstatus(
1975 skin_faces, PSTATUS_SHARED | PSTATUS_MULTISHARED,
1976 PSTATUS_NOT, -1, nullptr),
1977 "filter");
1978 m.second.swap(skin_faces);
1979 }
1980 return map;
1981 };
1982
1983 /* The above code is written in C++ and it appears to be defining and using
1984 various operations on boundary elements and side elements. */
1986 using BoundaryEleOp = BoundaryEle::UserDataOperator;
1987
1988 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1989
1990 auto calcs_side_traction = [&](auto &pip) {
1992 using EleOnSide =
1994 using SideEleOp = EleOnSide::UserDataOperator;
1995 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
1996 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
1997 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
1998 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
1999 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2000 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2002 op_loop_domain_side->getOpPtrVector().push_back(
2004 ep.piolaStress, contact_common_data_ptr->contactTractionPtr(),
2005 boost::make_shared<double>(1.0)));
2006 pip.push_back(op_loop_domain_side);
2008 };
2009
2010 auto add_contact_three = [&]() {
2012 auto tree_moab_ptr = boost::make_shared<moab::Core>();
2013 fe_contact_tree = boost::make_shared<ContactTree>(
2014 m_field, tree_moab_ptr, ep.spaceOrder,
2015 get_body_range("CONTACT", SPACE_DIM - 1, Sev::inform));
2016 fe_contact_tree->getOpPtrVector().push_back(
2018 ep.contactDisp, contact_common_data_ptr->contactDispPtr()));
2019 CHKERR calcs_side_traction(fe_contact_tree->getOpPtrVector());
2020 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2021 fe_contact_tree->getOpPtrVector().push_back(
2023 fe_contact_tree->getOpPtrVector().push_back(
2024 new OpMoveNode(fe_contact_tree, contact_common_data_ptr, u_h1_ptr));
2026 };
2027
2028 CHKERR add_contact_three();
2029
2031 };
2032
2033 CHK_THROW_MESSAGE(impl(), "createContactDetectionFiniteElement");
2034
2035 struct exclude_sdf {
2036 exclude_sdf(Range &&r) : map(r) {}
2037 bool operator()(FEMethod *fe_method_ptr) {
2038 auto ent = fe_method_ptr->getFEEntityHandle();
2039 if (map.find(ent) != map.end()) {
2040 return false;
2041 }
2042 return true;
2043 }
2044
2045 private:
2046 Range map;
2047 };
2048
2049 fe_contact_tree->exeTestHook =
2050 exclude_sdf(get_range_from_block(m_field, "CONTACT_SDF", SPACE_DIM - 1));
2051
2052 return fe_contact_tree;
2053};
2054
2055static auto get_body_range(MoFEM::Interface &m_field, const std::string name,
2056 int dim) {
2057 std::map<int, Range> map;
2058
2059 for (auto m_ptr :
2060 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2061
2062 (boost::format("%s(.*)") % name).str()
2063
2064 ))
2065
2066 ) {
2067 Range ents;
2068 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(m_field.get_moab(),
2069 dim, ents, true),
2070 "by dim");
2071 map[m_ptr->getMeshsetId()] = ents;
2072 }
2073
2074 return map;
2075};
2076
2078 EshelbianCore &ep, boost::shared_ptr<ForcesAndSourcesCore> fe_ptr,
2079 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
2081
2082 auto contact_tree_ptr = boost::dynamic_pointer_cast<ContactTree>(fe_ptr);
2083
2084 auto &m_field = ep.mField;
2085
2086 using BoundaryEle =
2088 using EleOnSide =
2090 using SideEleOp = EleOnSide::UserDataOperator;
2091 using BdyEleOp = BoundaryEle::UserDataOperator;
2092
2093 // First: Iterate over skeleton FEs adjacent to Domain FEs
2094 // Note: BoundaryEle, i.e. uses skeleton interation rule
2095 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
2096 m_field, ep.contactElement, SPACE_DIM - 1, Sev::noisy);
2097
2098 auto rule_contact = [](int, int, int o) { return -1; };
2100
2101 auto set_rule_contact = [refine](
2102
2103 ForcesAndSourcesCore *fe_raw_ptr, int order_row,
2104 int order_col, int order_data
2105
2106 ) {
2108 auto rule = 2 * order_data;
2109 fe_raw_ptr->gaussPts = Tools::refineTriangleIntegrationPts(rule, refine);
2111 };
2112
2113 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2114 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2115 CHKERR
2116 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2117 op_loop_skeleton_side->getOpPtrVector(), {L2}, ep.materialH1Positions,
2118 ep.frontAdjEdges);
2119
2120 // Second: Iterate over domain FEs adjacent to skelton, particularly
2121 // one domain element.
2122 auto broken_data_ptr = boost::make_shared<std::vector<BrokenBaseSideData>>();
2123
2124 // Data storing contact fields
2125 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
2126
2127 auto add_ops_domain_side = [&](auto &pip) {
2129 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
2130 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
2131 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
2132 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2133 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
2134 CHKERR
2135 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2136 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2138 op_loop_domain_side->getOpPtrVector().push_back(
2140 broken_data_ptr));
2141 op_loop_domain_side->getOpPtrVector().push_back(
2143 ep.piolaStress, contact_common_data_ptr->contactTractionPtr()));
2144 pip.push_back(op_loop_domain_side);
2146 };
2147
2148 auto add_ops_contact_rhs = [&](auto &pip) {
2150 // get body id and SDF range
2151 auto contact_sfd_map_range_ptr = boost::make_shared<std::map<int, Range>>(
2152 get_body_range(m_field, "CONTACT_SDF", SPACE_DIM - 1));
2153
2154 pip.push_back(new OpCalculateVectorFieldValues<3>(
2155 ep.contactDisp, contact_common_data_ptr->contactDispPtr()));
2156 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2157 pip.push_back(
2159 pip.push_back(new OpTreeSearch(
2160 contact_tree_ptr, u_h1_ptr,
2161 contact_common_data_ptr->contactTractionPtr(),
2162 get_range_from_block(m_field, "CONTACT", SPACE_DIM - 1), nullptr,
2163 nullptr));
2165 ep.contactDisp, contact_common_data_ptr, contact_tree_ptr,
2166 contact_sfd_map_range_ptr));
2168 broken_data_ptr, contact_common_data_ptr, contact_tree_ptr));
2169
2171 };
2172
2173 // push ops to face/side pipeline
2174 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2175 CHKERR add_ops_contact_rhs(op_loop_skeleton_side->getOpPtrVector());
2176
2177 // Add skeleton to domain pipeline
2178 pip.push_back(op_loop_skeleton_side);
2179
2181};
2182
2184 EshelbianCore &ep, boost::shared_ptr<ForcesAndSourcesCore> fe_ptr,
2185 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
2187
2188 auto contact_tree_ptr = boost::dynamic_pointer_cast<ContactTree>(fe_ptr);
2189 auto &m_field = ep.mField;
2190
2191 using BoundaryEle =
2193 using EleOnSide =
2195 using SideEleOp = EleOnSide::UserDataOperator;
2196 using BdyEleOp = BoundaryEle::UserDataOperator;
2197
2198 // First: Iterate over skeleton FEs adjacent to Domain FEs
2199 // Note: BoundaryEle, i.e. uses skeleton interation rule
2200 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
2201 m_field, ep.contactElement, SPACE_DIM - 1, Sev::noisy);
2202
2203 auto rule_contact = [](int, int, int o) { return -1; };
2205
2206 auto set_rule_contact = [refine](
2207
2208 ForcesAndSourcesCore *fe_raw_ptr, int order_row,
2209 int order_col, int order_data
2210
2211 ) {
2213 auto rule = 2 * order_data;
2214 fe_raw_ptr->gaussPts = Tools::refineTriangleIntegrationPts(rule, refine);
2216 };
2217
2218 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2219 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2220 CHKERR
2221 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2222 op_loop_skeleton_side->getOpPtrVector(), {L2}, ep.materialH1Positions,
2223 ep.frontAdjEdges);
2224
2225 // Second: Iterate over domain FEs adjacent to skelton, particularly
2226 // one domain element.
2227 auto broken_data_ptr = boost::make_shared<std::vector<BrokenBaseSideData>>();
2228
2229 // Data storing contact fields
2230 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
2231
2232 auto add_ops_domain_side = [&](auto &pip) {
2234 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
2235 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
2236 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
2237 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2238 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
2239 CHKERR
2240 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2241 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2243 op_loop_domain_side->getOpPtrVector().push_back(
2245 broken_data_ptr));
2246 op_loop_domain_side->getOpPtrVector().push_back(
2248 ep.piolaStress, contact_common_data_ptr->contactTractionPtr()));
2249 pip.push_back(op_loop_domain_side);
2251 };
2252
2253 auto add_ops_contact_lhs = [&](auto &pip) {
2255 pip.push_back(new OpCalculateVectorFieldValues<3>(
2256 ep.contactDisp, contact_common_data_ptr->contactDispPtr()));
2257 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2258 pip.push_back(
2260 pip.push_back(new OpTreeSearch(
2261 contact_tree_ptr, u_h1_ptr,
2262 contact_common_data_ptr->contactTractionPtr(),
2263 get_range_from_block(m_field, "CONTACT", SPACE_DIM - 1), nullptr,
2264 nullptr));
2265
2266 // get body id and SDF range
2267 auto contact_sfd_map_range_ptr = boost::make_shared<std::map<int, Range>>(
2268 get_body_range(m_field, "CONTACT_SDF", SPACE_DIM - 1));
2269
2271 ep.contactDisp, ep.contactDisp, contact_common_data_ptr,
2272 contact_tree_ptr, contact_sfd_map_range_ptr));
2273 pip.push_back(
2275 ep.contactDisp, broken_data_ptr, contact_common_data_ptr,
2276 contact_tree_ptr, contact_sfd_map_range_ptr));
2277 pip.push_back(
2279 broken_data_ptr, ep.contactDisp, contact_common_data_ptr,
2280 contact_tree_ptr));
2281
2283 };
2284
2285 // push ops to face/side pipeline
2286 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2287 CHKERR add_ops_contact_lhs(op_loop_skeleton_side->getOpPtrVector());
2288
2289 // Add skeleton to domain pipeline
2290 pip.push_back(op_loop_skeleton_side);
2291
2293};
2294
2297 boost::shared_ptr<ForcesAndSourcesCore> fe_ptr,
2298 boost::shared_ptr<MatrixDouble> u_h1_ptr,
2299 boost::shared_ptr<MatrixDouble> contact_traction_ptr,
2300 Range r, moab::Interface *post_proc_mesh_ptr,
2301 std::vector<EntityHandle> *map_gauss_pts_ptr) {
2302
2303 auto &m_field = ep.mField;
2304 auto contact_tree_ptr = boost::dynamic_pointer_cast<ContactTree>(fe_ptr);
2305 return new OpTreeSearch(
2306 contact_tree_ptr, u_h1_ptr, contact_traction_ptr,
2307 get_range_from_block(m_field, "CONTACT", SPACE_DIM - 1),
2308 post_proc_mesh_ptr, map_gauss_pts_ptr);
2309}
2310
2311} // 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.
#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)
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.
boost::shared_ptr< ContactSDFPython > setupContactSdf(MoFEM::Interface &m_field)
Read SDF file and setup contact SDF.
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 writeFile(const std::string file_name)
wrote results in (MOAB) format, use "file_name.h5m"
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