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