17 boost::ptr_deque<MoFEM::ForcesAndSourcesCore::UserDataOperator> &
25 CHKERR PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"Mortar Config",
"none");
29 "approximation order of spatial positions in contact interface",
"", 1,
31 CHKERR PetscOptionsInt(
"-ho_levels_num",
"number of higher order levels",
"",
33 CHKERR PetscOptionsInt(
"-order_lambda",
34 "approximation order of Lagrange multipliers",
"", 1,
37 CHKERR PetscOptionsBool(
"-is_partitioned",
38 "set if mesh is partitioned (this result that each "
39 "process keeps only part of the mes",
42 CHKERR PetscOptionsReal(
"-cn_value",
"default regularisation cn value",
"",
45 CHKERR PetscOptionsReal(
"-post_proc_gap_tol",
46 "gap tolerance for post processing",
"", 0.,
49 CHKERR PetscOptionsBool(
"-is_newton_cotes",
50 "set if Newton-Cotes quadrature rules are used",
"",
52 CHKERR PetscOptionsBool(
"-convect",
"set to convect integration pts",
"",
54 CHKERR PetscOptionsBool(
"-print_contact_state",
55 "output number of active gp at every iteration",
"",
57 CHKERR PetscOptionsBool(
"-alm_flag",
"if set use ALM, if not use C-function",
58 "", PETSC_FALSE, &
almFlag, PETSC_NULL);
59 CHKERR PetscOptionsBool(
"-debug",
"output debug files",
"", PETSC_FALSE,
63 CHKERR PetscOptionsInt(
"-order",
"approximation order of spatial positions",
64 "", 1, &
order, PETSC_NULL);
67 ierr = PetscOptionsEnd();
85 <<
"Meshset_level0 " << meshset_level0.size();
92 slaveTris.merge(contact_surface_pair.first);
100 contact_surface_pair.second, contact_surface_pair.first,
106 "Partitioned mesh is not supported with mortar contact");
109 CHKERR moab.create_meshset(MESHSET_SET, meshset_slave_master_prisms);
111 moab.add_entities(meshset_slave_master_prisms,
contactPrisms);
113 meshset_slave_master_prisms, 3,
bitLevels.back());
116 CHKERR moab.write_mesh(
"slave_master_prisms.vtk",
117 &meshset_slave_master_prisms, 1);
119 Range tris_from_prism;
122 contactPrisms, 2,
true, tris_from_prism, moab::Interface::UNION);
124 tris_from_prism = tris_from_prism.subset_by_type(MBTRI);
161 "set appropriate position field order, "
162 "setPositionFieldOrder(int order)");
181 auto set_contact_order = [&]() {
183 Range contact_tris, contact_edges;
185 moab::Interface::UNION);
186 contact_tris = contact_tris.subset_by_type(MBTRI);
187 CHKERR moab.get_adjacencies(contact_tris, 1,
false, contact_edges,
188 moab::Interface::UNION);
190 ho_ents.merge(contact_tris);
191 ho_ents.merge(contact_edges);
193 Range ents, verts, tets;
194 CHKERR moab.get_connectivity(ho_ents, verts,
true);
195 CHKERR moab.get_adjacencies(verts, 3,
false, tets,
196 moab::Interface::UNION);
197 tets = tets.subset_by_type(MBTET);
198 for (
auto d : {1, 2}) {
199 CHKERR moab.get_adjacencies(tets,
d,
false, ents,
200 moab::Interface::UNION);
202 ho_ents = unite(ho_ents, ents);
203 ho_ents = unite(ho_ents, tets);
212 CHKERR set_contact_order();
248 simple->getOtherFiniteElements().push_back(
"CONTACT_ELEM");
249 simple->getOtherFiniteElements().push_back(
"CONTACT_POST_PROC");
254 template <
typename T,
bool RHS>
260 "DM not defined, addElementsToDM(dm) first");
264 auto make_contact_element = [&]() {
265 return boost::make_shared<MortarContactProblem::MortarContactElement>(
269 auto make_convective_master_element = [&]() {
270 return boost::make_shared<
275 auto make_convective_slave_element = [&]() {
276 return boost::make_shared<
281 auto make_contact_common_data = [&]() {
282 return boost::make_shared<MortarContactProblem::CommonDataMortarContact>(
286 auto get_contact_rhs = [&](
auto make_element,
bool is_alm =
false,
287 bool is_displacements =
false) {
288 auto fe_rhs_simple_contact = make_element();
289 auto common_data_mortar_contact = make_contact_common_data();
291 fe_rhs_simple_contact->contactStateVec =
292 common_data_mortar_contact->gaussPtsStateVec;
294 fe_rhs_simple_contact->getOpPtrVector().push_back(
297 fe_rhs_simple_contact, common_data_mortar_contact,
positionField,
298 "LAGMULT", is_alm,
false,
"", is_displacements);
299 fe_rhs_simple_contact->getOpPtrVector().push_back(
301 return fe_rhs_simple_contact;
304 auto get_master_traction_rhs = [&](
auto make_element,
bool is_alm =
false,
305 bool is_displacements =
false) {
306 auto fe_rhs_simple_contact = make_element();
307 fe_rhs_simple_contact->getOpPtrVector().push_back(
309 auto common_data_mortar_contact = make_contact_common_data();
311 fe_rhs_simple_contact, common_data_mortar_contact,
positionField,
312 "LAGMULT", is_alm,
false,
"", is_displacements);
313 fe_rhs_simple_contact->getOpPtrVector().push_back(
315 return fe_rhs_simple_contact;
318 auto get_master_traction_lhs = [&](
auto make_element,
bool is_alm =
false,
319 bool is_displacements =
false) {
320 auto fe_lhs_simple_contact = make_element();
321 auto common_data_mortar_contact = make_contact_common_data();
322 fe_lhs_simple_contact->getOpPtrVector().push_back(
325 fe_lhs_simple_contact, common_data_mortar_contact,
positionField,
326 "LAGMULT", is_alm,
false,
"", is_displacements);
327 fe_lhs_simple_contact->getOpPtrVector().push_back(
329 return fe_lhs_simple_contact;
332 auto get_master_help_traction_lhs = [&](
auto make_element,
334 bool is_displacements =
false) {
335 auto fe_lhs_simple_contact = make_element();
336 auto common_data_mortar_contact = make_contact_common_data();
337 fe_lhs_simple_contact->getOpPtrVector().push_back(
340 fe_lhs_simple_contact, common_data_mortar_contact,
positionField,
341 "LAGMULT", is_alm,
false,
"", is_displacements);
342 fe_lhs_simple_contact->getOpPtrVector().push_back(
344 return fe_lhs_simple_contact;
347 auto get_contact_lhs = [&](
auto make_element,
bool is_alm =
false,
348 bool is_displacements =
false) {
349 auto fe_lhs_simple_contact = make_element();
350 auto common_data_mortar_contact = make_contact_common_data();
351 fe_lhs_simple_contact->getOpPtrVector().push_back(
354 fe_lhs_simple_contact, common_data_mortar_contact,
positionField,
355 "LAGMULT", is_alm,
false,
"", is_displacements);
356 fe_lhs_simple_contact->getOpPtrVector().push_back(
358 return fe_lhs_simple_contact;
361 auto get_contact_help_lhs = [&](
auto make_element,
bool is_alm =
false,
362 bool is_displacements =
false) {
363 auto fe_lhs_simple_contact = make_element();
364 auto common_data_mortar_contact = make_contact_common_data();
365 fe_lhs_simple_contact->getOpPtrVector().push_back(
368 fe_lhs_simple_contact, common_data_mortar_contact,
positionField,
369 "LAGMULT", is_alm,
false,
"", is_displacements);
370 fe_lhs_simple_contact->getOpPtrVector().push_back(
372 return fe_lhs_simple_contact;
375 auto set_solver_pipelines = [&](PetscErrorCode (*
function)(
376 DM,
const std::string,
377 boost::shared_ptr<MoFEM::FEMethod>,
378 boost::shared_ptr<MoFEM::BasicMethod>,
379 boost::shared_ptr<MoFEM::BasicMethod>),
380 PetscErrorCode (*jacobian)(
381 DM,
const std::string,
382 boost::shared_ptr<MoFEM::FEMethod>,
383 boost::shared_ptr<MoFEM::BasicMethod>,
384 boost::shared_ptr<MoFEM::BasicMethod>)) {
390 CHKERR function(this->
dM,
"CONTACT_ELEM",
391 get_contact_rhs(make_convective_master_element,
almFlag,
393 PETSC_NULL, PETSC_NULL);
394 CHKERR function(this->
dM,
"CONTACT_ELEM",
395 get_master_traction_rhs(make_convective_slave_element,
397 PETSC_NULL, PETSC_NULL);
401 CHKERR jacobian(this->
dM,
"CONTACT_ELEM",
402 get_contact_help_lhs(make_convective_master_element,
404 PETSC_NULL, PETSC_NULL);
407 this->
dM,
"CONTACT_ELEM",
408 get_master_help_traction_lhs(make_convective_slave_element),
409 PETSC_NULL, PETSC_NULL);
416 this->
dM,
"CONTACT_ELEM",
418 PETSC_NULL, PETSC_NULL);
419 CHKERR function(this->
dM,
"CONTACT_ELEM",
420 get_master_traction_rhs(make_contact_element,
almFlag,
422 PETSC_NULL, PETSC_NULL);
426 CHKERR jacobian(this->
dM,
"CONTACT_ELEM",
427 get_contact_lhs(make_contact_element,
almFlag,
429 PETSC_NULL, PETSC_NULL);
430 CHKERR jacobian(this->
dM,
"CONTACT_ELEM",
431 get_master_traction_lhs(make_contact_element,
almFlag,
433 PETSC_NULL, PETSC_NULL);
441 if constexpr (std::is_same_v<T, SNES>) {
445 }
else if (std::is_same_v<T, TS>) {
462 "This TS is not yet implemented for contact");
467 static_assert(!std::is_same_v<T, KSP>,
468 "this solver has not been implemented for contact yet");
490 MortarContactInterface::setupSolverFunction<TS>(
const TSType type) {
497 MortarContactInterface::setupSolverFunction<SNES>(
const TSType type) {
504 MortarContactInterface::setupSolverJacobian<SNES>(
const TSType type) {
511 MortarContactInterface::setupSolverJacobian<TS>(
const TSType type) {
519 CHKERR this->setupSolverFunction<SNES>();
524 CHKERR this->setupSolverJacobian<SNES>();
547 "you need to setup the solver first to use postProcessContactState");
552 auto get_contact_data = [&](
auto vec, std::array<double, 2> &data) {
554 CHKERR VecAssemblyBegin(vec);
555 CHKERR VecAssemblyEnd(vec);
557 CHKERR VecGetArrayRead(vec, &array);
562 CHKERR VecRestoreArrayRead(vec, &array);
570 MOFEM_LOG_C(
"WORLD", Sev::verbose,
"Active gauss pts: %d out of %d",
575 <<
"Computing contact area only on the post process surface";
577 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Using gap tolerance %3.3f",
580 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Active contact area: %3.3f out of %3.3f",
584 auto out_file_name =
"out_contact_integ_pts_" + to_string(step) +
".h5m";
587 "PARALLEL=WRITE_PART");
611 auto out_file_name =
"out_contact_" + to_string(step) +
".h5m";
632 std::map<std::string, Range> slave_surface_map, master_surface_map;
634 auto fill_surface_map = [&](
auto &surface_map, std::string surface_name) {
638 if (it->getName().compare(0, surface_name.size(), surface_name) == 0) {
642 std::string key = it->getName().substr(surface_name.size());
643 auto res = surface_map.insert(std::pair<std::string, Range>(key, tris));
646 "Contact surface name %s used more than once",
647 it->getName().c_str());
655 CHKERR fill_surface_map(slave_surface_map,
"MORTAR_SLAVE");
656 CHKERR fill_surface_map(master_surface_map,
"MORTAR_MASTER");
658 for (
const auto &[key, slave_range] : slave_surface_map) {
659 auto master_search = master_surface_map.find(key);
660 if (master_search != master_surface_map.end()) {
662 std::pair<Range, Range>(slave_range, master_search->second));
663 master_surface_map.erase(master_search);
667 "Cannot find pairing contact surface MORTAR_MASTER%s for existing "
668 "surface MORTAR_SLAVE%s",
669 key.c_str(), key.c_str());
673 if (!master_surface_map.empty()) {
674 std::string key = master_surface_map.begin()->first;
676 "Cannot find pairing contact surface MORTAR_SLAVE%s for existing "
677 "surface MORTAR_MASTER%s",
678 key.c_str(), key.c_str());
687 std::string surface_name =
"MORTAR_POST_PROC";
690 if (it->getName().compare(0, surface_name.size(), surface_name) == 0) {