31 boost::shared_ptr<MFrontInterface> mfront_interface_ptr =
nullptr,
38 CHKERR DMoFEMGetInterfacePtr(
dM, &m_field_ptr);
40 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
42 struct OpScale :
public ForcesAndSourcesCore::UserDataOperator {
43 OpScale(boost::shared_ptr<MatrixDouble> m_ptr,
double s)
44 : ForcesAndSourcesCore::UserDataOperator(
NOSPACE, OPSPACE),
45 mPtr(m_ptr),
scale(s) {}
46 MoFEMErrorCode doWork(
int, EntityType, EntitiesFieldData::EntData &) {
52 boost::shared_ptr<MatrixDouble> mPtr;
56 auto push_domain_ops = [&](
auto &pip) {
58 pip, {
H1,
HDIV},
"GEOMETRY")),
59 "Apply base transform");
62 using CommonDataVariant =
63 std::variant<boost::shared_ptr<HookeOps::CommonData>,
64 boost::shared_ptr<HenckyOps::CommonData>>;
65 auto contact_stress_ptr = boost::make_shared<MatrixDouble>();
66 pip.push_back(
new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(
67 "SIGMA", contact_stress_ptr));
70 auto hooke_common_data_ptr =
71 HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
72 *m_field_ptr, pip,
"U",
"MAT_ELASTIC", Sev::inform,
scale);
74 pip.push_back(
new OpScale(contact_stress_ptr,
scale));
75 return std::make_tuple(CommonDataVariant(hooke_common_data_ptr),
78 auto hencky_common_data_ptr =
79 HenckyOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
80 *m_field_ptr, pip,
"U",
"MAT_ELASTIC", Sev::inform,
scale);
81 pip.push_back(
new OpScale(contact_stress_ptr,
scale));
82 return std::make_tuple(CommonDataVariant(hencky_common_data_ptr),
86 auto push_bdy_ops = [&](
auto &pip) {
88 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
89 pip.push_back(
new OpCalculateVectorFieldValues<SPACE_DIM>(
90 "U", common_data_ptr->contactDispPtr()));
91 pip.push_back(
new OpCalculateHVecTensorTrace<SPACE_DIM, BoundaryEleOp>(
92 "SIGMA", common_data_ptr->contactTractionPtr()));
93 pip.push_back(
new OpScale(common_data_ptr->contactTractionPtr(),
scale));
95 pip.push_back(
new typename C::template OpEvaluateSDF<SPACE_DIM, GAUSS>(
97 return common_data_ptr;
100 auto get_domain_pip = [&](
auto &pip)
101 -> boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> & {
103 auto op_loop_side =
new OpLoopSide<SideEle>(
104 *m_field_ptr,
"dFE",
SPACE_DIM, Sev::noisy,
106 ForcesAndSourcesCore::UserDataOperator::AdjCache>());
107 pip.push_back(op_loop_side);
108 return op_loop_side->getOpPtrVector();
114 auto get_post_proc_domain_fe = [&]() {
116 boost::make_shared<PostProcEleDomain>(*m_field_ptr,
postProcMesh);
117 auto &pip = post_proc_fe->getOpPtrVector();
119 auto [hencky_or_hooke_common_data_ptr, contact_stress_ptr] =
120 push_domain_ops(get_domain_pip(pip));
122 auto u_ptr = boost::make_shared<MatrixDouble>();
123 pip.push_back(
new OpCalculateVectorFieldValues<SPACE_DIM>(
"U", u_ptr));
124 auto X_ptr = boost::make_shared<MatrixDouble>();
126 new OpCalculateVectorFieldValues<SPACE_DIM>(
"GEOMETRY", X_ptr));
138 [&](
auto &common_data_ptr) {
139 if constexpr (std::is_same_v<
140 std::decay_t<
decltype(common_data_ptr)>,
141 boost::shared_ptr<HookeOps::CommonData>>) {
143 post_proc_fe->getPostProcMesh(),
144 post_proc_fe->getMapGaussPts(), {},
145 {{
"U", u_ptr}, {
"GEOMETRY", X_ptr}},
146 {{
"SIGMA", contact_stress_ptr},
147 {
"G", common_data_ptr->matGradPtr}},
148 {{
"STRESS", common_data_ptr->getMatCauchyStress()},
149 {
"STRAIN", common_data_ptr->getMatStrain()}}));
152 else if constexpr (std::is_same_v<
153 std::decay_t<
decltype(common_data_ptr)>,
154 boost::shared_ptr<HenckyOps::CommonData>>) {
157 post_proc_fe->getPostProcMesh(),
158 post_proc_fe->getMapGaussPts(), {},
159 {{
"U", u_ptr}, {
"GEOMETRY", X_ptr}},
160 {{
"SIGMA", contact_stress_ptr},
161 {
"G", common_data_ptr->matGradPtr},
162 {
"PK1", common_data_ptr->getMatFirstPiolaStress()}
165 {{
"HENCKY_STRAIN", common_data_ptr->getMatLogC()}}));
168 hencky_or_hooke_common_data_ptr);
173 pip, {
HDIV},
"GEOMETRY")),
175 auto common_data_ptr = push_bdy_ops(pip);
181 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
183 {{
"SDF", common_data_ptr->sdfPtr()},
184 {
"CONSTRAINT_CONTACT", common_data_ptr->constraintPtr()}},
188 {
"TRACTION_CONTACT", common_data_ptr->contactTractionPtr()},
189 {
"GRAD_SDF", common_data_ptr->gradSdfPtr()}
195 {{
"HESS_SDF", common_data_ptr->hessSdfPtr()}}
205 auto get_post_proc_bdy_fe = [&]() {
207 boost::make_shared<PostProcEleBdy>(*m_field_ptr, postProcMesh);
208 auto &pip = post_proc_fe->getOpPtrVector();
211 pip, {
HDIV},
"GEOMETRY")),
213 auto common_data_ptr = push_bdy_ops(pip);
216 auto op_loop_side =
new OpLoopSide<SideEle>(
217 *m_field_ptr,
"dFE",
SPACE_DIM, Sev::noisy,
219 ForcesAndSourcesCore::UserDataOperator::AdjCache>());
220 pip.push_back(op_loop_side);
222 auto [hencky_or_hooke_common_data_ptr, contact_stress_ptr] =
223 push_domain_ops(op_loop_side->getOpPtrVector());
225 auto X_ptr = boost::make_shared<MatrixDouble>();
227 new OpCalculateVectorFieldValues<SPACE_DIM>(
"GEOMETRY", X_ptr));
233 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
235 {{
"SDF", common_data_ptr->sdfPtr()},
236 {
"CONSTRAINT_CONTACT", common_data_ptr->constraintPtr()}},
238 {{
"U", common_data_ptr->contactDispPtr()},
240 {
"TRACTION_CONTACT", common_data_ptr->contactTractionPtr()},
241 {
"GRAD_SDF", common_data_ptr->gradSdfPtr()}
247 {{
"HESS_SDF", common_data_ptr->hessSdfPtr()}}
256 auto get_integrate_traction = [&]() {
257 auto integrate_traction = boost::make_shared<BoundaryEle>(*m_field_ptr);
259 (AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
260 integrate_traction->getOpPtrVector(), {HDIV},
"GEOMETRY")),
264 integrate_traction->getOpPtrVector().push_back(
265 new OpSetHOWeightsOnSubDim<SPACE_DIM>());
271 (opFactoryCalculateTraction<SPACE_DIM, GAUSS, BoundaryEleOp>(
273 "push operators to calculate traction");
275 return integrate_traction;
278 auto get_integrate_area = [&]() {
279 auto integrate_area = boost::make_shared<BoundaryEle>(*m_field_ptr);
282 (AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
283 integrate_area->getOpPtrVector(), {HDIV},
"GEOMETRY")),
287 integrate_area->getOpPtrVector().push_back(
288 new OpSetHOWeightsOnSubDim<SPACE_DIM>());
294 m_field_ptr->getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
295 std::regex((boost::format(
"%s(.*)") %
"CONTACT").str()))) {
296 auto meshset =
m->getMeshset();
297 Range contact_meshset_range;
298 CHKERR m_field_ptr->get_moab().get_entities_by_dimension(
299 meshset,
SPACE_DIM - 1, contact_meshset_range,
true);
301 CHKERR m_field_ptr->getInterface<CommInterface>()->synchroniseEntities(
302 contact_meshset_range);
303 contact_range.merge(contact_meshset_range);
306 auto contact_range_ptr = boost::make_shared<Range>(contact_range);
308 auto op_loop_side =
new OpLoopSide<SideEle>(
309 *m_field_ptr, m_field_ptr->getInterface<Simple>()->getDomainFEName(),
311 CHKERR AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
312 op_loop_side->getOpPtrVector(), {H1},
"GEOMETRY");
315 (opFactoryCalculateArea<SPACE_DIM, GAUSS, BoundaryEleOp>(
316 integrate_area->getOpPtrVector(), op_loop_side,
"SIGMA",
"U",
318 "push operators to calculate area");
320 return integrate_area;
323 postProcDomainFe = get_post_proc_domain_fe();
325 postProcBdyFe = get_post_proc_bdy_fe();
327 integrateTraction = get_integrate_traction();
328 integrateArea = get_integrate_area();
337 CHKERR DMoFEMGetInterfacePtr(dM, &m_field_ptr);
339 auto post_proc = [&]() {
342 if (!mfrontInterfacePtr) {
343 auto post_proc_begin =
344 boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(*m_field_ptr,
347 boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(*m_field_ptr,
350 CHKERR DMoFEMPreProcessFiniteElements(dM,
351 post_proc_begin->getFEMethod());
352 if (!postProcBdyFe) {
353 postProcDomainFe->copyTs(*
this);
354 CHKERR DMoFEMLoopFiniteElements(dM,
"bFE", postProcDomainFe);
356 postProcDomainFe->copyTs(*
this);
357 postProcBdyFe->copyTs(*
this);
358 CHKERR DMoFEMLoopFiniteElements(dM,
"dFE", postProcDomainFe);
359 CHKERR DMoFEMLoopFiniteElements(dM,
"bFE", postProcBdyFe);
361 CHKERR DMoFEMPostProcessFiniteElements(dM,
362 post_proc_end->getFEMethod());
364 CHKERR post_proc_end->writeFile(
365 "out_contact_" + boost::lexical_cast<std::string>(sTEP) +
".h5m");
367 CHKERR mfrontInterfacePtr->postProcess(
369 m_field_ptr->
getInterface<Simple>()->getDomainFEName());
375 auto calculate_force = [&] {
377 CHKERR VecZeroEntries(CommonData::totalTractionAndArea);
378 CHKERR DMoFEMLoopFiniteElements(dM,
"bFE", integrateTraction);
379 CHKERR VecAssemblyBegin(CommonData::totalTractionAndArea);
380 CHKERR VecAssemblyEnd(CommonData::totalTractionAndArea);
384 auto calculate_area = [&] {
386 integrateArea->copyTs(*
this);
387 CHKERR DMoFEMLoopFiniteElements(dM,
"bFE", integrateArea);
388 CHKERR VecAssemblyBegin(CommonData::totalTractionAndArea);
389 CHKERR VecAssemblyEnd(CommonData::totalTractionAndArea);
393 auto calculate_reactions = [&]() {
396 auto res = createDMVector(dM);
398 auto assemble_domain = [&]() {
400 auto fe_rhs = boost::make_shared<DomainEle>(*m_field_ptr);
401 auto &pip = fe_rhs->getOpPtrVector();
409 CHKERR AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(pip, {
H1},
412 ContactOps::opFactoryDomainRhs<SPACE_DIM, PETSC, IT, DomainEleOp>(
415 if (!mfrontInterfacePtr) {
417 HenckyOps::opFactoryDomainRhs<SPACE_DIM, PETSC, IT, DomainEleOp>(
418 *m_field_ptr, pip,
"U",
"MAT_ELASTIC", Sev::inform,
scale);
420 CHKERR mfrontInterfacePtr->opFactoryDomainRhs(pip,
"U");
422 CHKERR DMoFEMLoopFiniteElements(dM,
"dFE", fe_rhs);
424 CHKERR VecAssemblyBegin(res);
425 CHKERR VecAssemblyEnd(res);
426 CHKERR VecGhostUpdateBegin(res, ADD_VALUES, SCATTER_REVERSE);
427 CHKERR VecGhostUpdateEnd(res, ADD_VALUES, SCATTER_REVERSE);
432 auto assemble_boundary = [&]() {
434 auto fe_rhs = boost::make_shared<BoundaryEle>(*m_field_ptr);
435 auto &pip = fe_rhs->getOpPtrVector();
443 CHKERR AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(pip, {},
447 pip.push_back(
new OpSetHOWeightsOnSubDim<SPACE_DIM>());
449 auto u_disp = boost::make_shared<MatrixDouble>();
450 pip.push_back(
new OpCalculateVectorFieldValues<SPACE_DIM>(
"U", u_disp));
452 new OpSpringRhs(
"U", u_disp, [
this](
double,
double,
double) {
456 CHKERR DMoFEMLoopFiniteElements(dM,
"bFE", fe_rhs);
462 CHKERR assemble_boundary();
464 auto fe_post_proc_ptr = boost::make_shared<FEMethod>();
465 auto get_post_proc_hook_rhs = [
this, fe_post_proc_ptr, res,
468 CHKERR EssentialPreProcReaction<DisplacementCubitBcData>(
469 *m_field_ptr, fe_post_proc_ptr, res)();
472 fe_post_proc_ptr->postProcessHook = get_post_proc_hook_rhs;
473 CHKERR DMoFEMPostProcessFiniteElements(dM, fe_post_proc_ptr.get());
478 auto print_max_min = [&](
auto &tuple,
const std::string msg) {
480 CHKERR VecScatterBegin(std::get<1>(tuple), ts_u, std::get<0>(tuple),
481 INSERT_VALUES, SCATTER_FORWARD);
482 CHKERR VecScatterEnd(std::get<1>(tuple), ts_u, std::get<0>(tuple),
483 INSERT_VALUES, SCATTER_FORWARD);
485 CHKERR VecMax(std::get<0>(tuple), PETSC_NULLPTR, &max);
486 CHKERR VecMin(std::get<0>(tuple), PETSC_NULLPTR, &min);
487 MOFEM_LOG_C(
"CONTACT", Sev::inform,
"%s time %6.4e min %6.4e max %6.4e",
488 msg.c_str(), ts_t, min, max);
492 auto print_force_and_area = [&]() {
495 CHKERR DMoFEMGetInterfacePtr(dM, &m_field_ptr);
498 CHKERR VecGetArrayRead(CommonData::totalTractionAndArea, &t_ptr);
500 "Contact force: time %6.3e Fx: %6.6e Fy: %6.6e Fz: %6.6e",
501 ts_t, t_ptr[
TX], t_ptr[
TY], t_ptr[
TZ]);
503 "Contact area: time %6.3e Active: %6.6e Potential: %6.6e",
505 CHKERR VecRestoreArrayRead(CommonData::totalTractionAndArea, &t_ptr);
510 if (mfrontInterfacePtr) {
511 CHKERR mfrontInterfacePtr->updateInternalVariables(
512 dM, m_field_ptr->
getInterface<Simple>()->getDomainFEName());
516 CHKERR PetscOptionsGetInt(PETSC_NULLPTR,
"",
"-save_every", &se,
519 if (!(ts_step % se)) {
521 <<
"Write file at time " << ts_t <<
" write step " << sTEP;
527 CHKERR calculate_reactions();
529 CHKERR print_max_min(uXScatter,
"Ux");
530 CHKERR print_max_min(uYScatter,
"Uy");
532 CHKERR print_max_min(uZScatter,
"Uz");
533 CHKERR print_force_and_area();