v0.16.3
Loading...
Searching...
No Matches
contact.cpp
Go to the documentation of this file.
1/**
2 * \file contact.cpp
3 * \CONTACT contact.cpp
4 *
5 * CONTACT of contact problem
6 *
7 * @copyright Copyright (c) 2023
8 */
9
10/* The above code is a preprocessor directive in C++ that checks if the macro
11"EXECUTABLE_DIMENSION" has been defined. If it has not been defined, it is set
12to 3" */
13#ifndef EXECUTABLE_DIMENSION
14 #define EXECUTABLE_DIMENSION 3
15#endif
16
17#ifndef SCHUR_ASSEMBLE
18 #define SCHUR_ASSEMBLE 0
19#endif
20
21#include <MoFEM.hpp>
22#include <MatrixFunction.hpp>
23
24using namespace MoFEM;
25
26#ifdef ENABLE_PYTHON_BINDING
27 #include <boost/python.hpp>
28 #include <boost/python/def.hpp>
29 #include <boost/python/numpy.hpp>
30namespace bp = boost::python;
31namespace np = boost::python::numpy;
32#endif
33
34constexpr AssemblyType AT =
35 (SCHUR_ASSEMBLE) ? AssemblyType::BLOCK_SCHUR
36 : AssemblyType::PETSC; //< selected assembly type
38 IntegrationType::GAUSS; //< selected integration type
39
40template <int DIM> struct ElementsAndOps;
41
43 static constexpr FieldSpace CONTACT_SPACE = HCURL;
44};
45
47 static constexpr FieldSpace CONTACT_SPACE = HDIV;
48};
49
52
53constexpr int SPACE_DIM =
54 EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
55
56/* The above code is defining an alias `EntData` for the type
57`EntitiesFieldData::EntData`. This is a C++ syntax for creating a new name for
58an existing type. */
61using DomainEleOp = DomainEle::UserDataOperator;
63using BoundaryEleOp = BoundaryEle::UserDataOperator;
65//! [Specialisation for assembly]
66
68
69//! [Operators used for contact]
73 IT>::OpBaseTimesVector<1, SPACE_DIM, SPACE_DIM>;
74//! [Operators used for contact]
75
76PetscBool is_quasi_static = PETSC_TRUE;
77
78int order = 2; //< Order of displacements in the domain
79int contact_order = 2; //< Order of displacements in contact elements
80int sigma_order = 1; //< Order of Lagrange multiplier in side elements
81int geom_order = 1;
82double young_modulus = 100;
83double poisson_ratio = 0.25;
84double rho = 0.0;
85double spring_stiffness = 0.0;
87double alpha_damping = 0;
88
89double scale = 1.;
90
91PetscBool is_axisymmetric = PETSC_FALSE; //< flag for Axisymmetric model
92PetscBool is_large_strain = PETSC_FALSE; //< flag for large strain
93
94namespace ContactOps {
95double cn_contact = 0.1;
96}; // namespace ContactOps
97
98#include <HenckyOps.hpp>
99#include <HookeOps.hpp>
100using namespace HenckyOps;
101using namespace HookeOps;
102#include <ContactOps.hpp>
103#include <PostProcContact.hpp>
104#include <TestingContact.hpp>
105#include <ContactNaturalBC.hpp>
106
116
117using namespace ContactOps;
118
119struct Contact {
120
122 : mField(m_field), mfrontInterfacePtr(nullptr) {}
123
125
126private:
128
135
136 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uXScatter;
137 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uYScatter;
138 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uZScatter;
139
140 boost::shared_ptr<MFrontInterface> mfrontInterfacePtr;
141 boost::shared_ptr<Monitor> monitorPtr;
142
143#ifdef ENABLE_PYTHON_BINDING
144 boost::shared_ptr<SDFPython> sdfPythonPtr;
145#endif
146
149 double getScale(const double time) {
150 return scale * MoFEM::TimeScale::getScale(time);
151 };
152 };
153};
154
155//! [Run problem]
166//! [Run problem]
167
168//! [Set up problem]
172
173 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
174 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-contact_order", &contact_order,
175 PETSC_NULLPTR);
176 sigma_order = std::max(order, contact_order) - 1;
177 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-sigma_order", &sigma_order,
178 PETSC_NULLPTR);
179 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-geom_order", &geom_order,
180 PETSC_NULLPTR);
181
182 MOFEM_LOG("CONTACT", Sev::inform) << "Order " << order;
183 MOFEM_LOG("CONTACT", Sev::inform) << "Contact order " << contact_order;
184 MOFEM_LOG("CONTACT", Sev::inform) << "Sigma order " << sigma_order;
185 MOFEM_LOG("CONTACT", Sev::inform) << "Geom order " << geom_order;
186
187 // Select base
188 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
189 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
190 PetscInt choice_base_value = AINSWORTH;
191 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL, "-base", list_bases,
192 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
193
195 switch (choice_base_value) {
196 case AINSWORTH:
198 MOFEM_LOG("CONTACT", Sev::inform)
199 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
200 break;
201 case DEMKOWICZ:
203 MOFEM_LOG("CONTACT", Sev::inform)
204 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
205 break;
206 default:
207 base = LASTBASE;
208 break;
209 }
210
211 // Note: For tets we have only H1 Ainsworth base, for Hex we have only H1
212 // Demkowicz base. We need to implement Demkowicz H1 base on tet.
213 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
214 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
215 CHKERR simple->addDomainField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
216 SPACE_DIM);
217 CHKERR simple->addBoundaryField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
218 SPACE_DIM);
219 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
220
221 CHKERR simple->setFieldOrder("U", order);
222 CHKERR simple->setFieldOrder("GEOMETRY", geom_order);
223
224 auto get_skin = [&]() {
225 Range body_ents;
226 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
227 Skinner skin(&mField.get_moab());
228 Range skin_ents;
229 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
230 return skin_ents;
231 };
232
233 auto filter_blocks = [&](auto skin) {
234 bool is_contact_block = false;
235 Range contact_range;
236 for (auto m :
237 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
238
239 (boost::format("%s(.*)") % "CONTACT").str()
240
241 ))
242
243 ) {
244 is_contact_block =
245 true; ///< blocs interation is collective, so that is set irrespective
246 ///< if there are entities in given rank or not in the block
247 MOFEM_LOG("CONTACT", Sev::inform)
248 << "Find contact block set: " << m->getName();
249 auto meshset = m->getMeshset();
250 Range contact_meshset_range;
251 CHKERR mField.get_moab().get_entities_by_dimension(
252 meshset, SPACE_DIM - 1, contact_meshset_range, true);
253
254 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
255 contact_meshset_range);
256 contact_range.merge(contact_meshset_range);
257 }
258 if (is_contact_block) {
259 MOFEM_LOG("SYNC", Sev::inform)
260 << "Nb entities in contact surface: " << contact_range.size();
262 skin = intersect(skin, contact_range);
263 }
264 return skin;
265 };
266
267 auto filter_true_skin = [&](auto skin) {
268 Range boundary_ents;
269 ParallelComm *pcomm =
270 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
271 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
272 PSTATUS_NOT, -1, &boundary_ents);
273 return boundary_ents;
274 };
275
276 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
277 CHKERR simple->setFieldOrder("SIGMA", 0);
278 CHKERR simple->setFieldOrder("SIGMA", sigma_order, &boundary_ents);
279
280 if (contact_order > order) {
281 Range ho_ents;
282
283 CHKERR mField.get_moab().get_adjacencies(boundary_ents, 1, false, ho_ents,
284 moab::Interface::UNION);
285
286 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(ho_ents);
287 CHKERR simple->setFieldOrder("U", contact_order, &ho_ents);
288 CHKERR mField.getInterface<CommInterface>()->synchroniseFieldEntities("U");
289 }
290
291 CHKERR simple->setUp();
292
293 auto project_ho_geometry = [&]() {
294 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
295 return mField.loop_dofs("GEOMETRY", ent_method);
296 };
297
298 PetscBool project_geometry = PETSC_TRUE;
299 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-project_geometry",
300 &project_geometry, PETSC_NULLPTR);
301 if (project_geometry) {
302 CHKERR project_ho_geometry();
303 }
304
306} //! [Set up problem]
307
308//! [Create common data]
311
312 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-large_strain",
313 &is_large_strain, PETSC_NULLPTR);
314 PetscBool use_mfront = PETSC_FALSE;
315 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-use_mfront", &use_mfront,
316 PETSC_NULLPTR);
317 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_axisymmetric",
318 &is_axisymmetric, PETSC_NULLPTR);
319
320 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-scale", &scale,
321 PETSC_NULLPTR);
322 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-young_modulus",
323 &young_modulus, PETSC_NULLPTR);
324 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-poisson_ratio",
325 &poisson_ratio, PETSC_NULLPTR);
326 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-rho", &rho, PETSC_NULLPTR);
327 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn", &cn_contact,
328 PETSC_NULLPTR);
329 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-spring_stiffness",
330 &spring_stiffness, PETSC_NULLPTR);
331 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-vis_spring_stiffness",
332 &vis_spring_stiffness, PETSC_NULLPTR);
333 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-alpha_damping",
334 &alpha_damping, PETSC_NULLPTR);
335
336 if (!use_mfront) {
337 if (!is_large_strain) {
338 MOFEM_LOG("CONTACT", Sev::inform)
339 << "Selected material model: Hooke (small strain)";
340 } else {
341 MOFEM_LOG("CONTACT", Sev::inform)
342 << "Selected material model: Hencky (finite strain)";
343 }
344 MOFEM_LOG("CONTACT", Sev::inform) << "Young modulus " << young_modulus;
345 MOFEM_LOG("CONTACT", Sev::inform) << "Poisson_ratio " << poisson_ratio;
346 } else {
347 MOFEM_LOG("CONTACT", Sev::inform) << "Using MFront for material model";
348 }
349
350 MOFEM_LOG("CONTACT", Sev::inform) << "Density " << rho;
351 MOFEM_LOG("CONTACT", Sev::inform) << "cn_contact " << cn_contact;
352 MOFEM_LOG("CONTACT", Sev::inform) << "Spring stiffness " << spring_stiffness;
353 MOFEM_LOG("CONTACT", Sev::inform)
354 << "Vis spring_stiffness " << vis_spring_stiffness;
355
356 MOFEM_LOG("CONTACT", Sev::inform) << "alpha_damping " << alpha_damping;
357
358 PetscBool use_scale = PETSC_FALSE;
359 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-use_scale", &use_scale,
360 PETSC_NULLPTR);
361 if (use_scale) {
363 }
364
365 MOFEM_LOG("CONTACT", Sev::inform) << "Scale " << scale;
366
367 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_quasi_static",
368 &is_quasi_static, PETSC_NULLPTR);
369 MOFEM_LOG("CONTACT", Sev::inform)
370 << "Is quasi-static: " << (is_quasi_static ? "true" : "false");
371
372#ifdef ENABLE_PYTHON_BINDING
373 auto file_exists = [](std::string myfile) {
374 std::ifstream file(myfile.c_str());
375 if (file) {
376 return true;
377 }
378 return false;
379 };
380 char sdf_file_name[255] = "sdf.py";
381 PetscBool has_sdf_file_option = PETSC_FALSE;
382 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-sdf_file",
383 sdf_file_name, 255, &has_sdf_file_option);
384 if (!has_sdf_file_option) {
385 auto *json_config = mField.getInterface<JsonConfigManager>();
386 const auto contact_surface_script =
387 json_config->getPythonScriptByKey("contact_surface");
388 if (!contact_surface_script.empty()) {
389 std::strcpy(sdf_file_name, contact_surface_script.c_str());
390 MOFEM_LOG("CONTACT", Sev::inform)
391 << "Using Python script 'contact_surface' from JSON config: "
392 << sdf_file_name;
393 }
394 }
395
396 if (file_exists(sdf_file_name)) {
397 MOFEM_LOG("CONTACT", Sev::inform) << sdf_file_name << " file found";
398 sdfPythonPtr = boost::make_shared<SDFPython>();
399 CHKERR sdfPythonPtr->sdfInit(sdf_file_name);
400 sdfPythonWeakPtr = sdfPythonPtr;
401 } else {
402 MOFEM_LOG("CONTACT", Sev::warning) << sdf_file_name << " file NOT found";
403 }
404#endif
405
406 if (is_axisymmetric) {
407 if (SPACE_DIM == 3) {
408 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
409 "Use executable contact_2d with axisymmetric model");
410 } else {
411 if (!use_mfront) {
412 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
413 "Axisymmetric model is only available with MFront (set "
414 "use_mfront to 1)");
415 } else {
416 MOFEM_LOG("CONTACT", Sev::inform) << "Using axisymmetric model";
417 }
418 }
419 } else {
420 if (SPACE_DIM == 2) {
421 MOFEM_LOG("CONTACT", Sev::inform) << "Using plane strain model";
422 }
423 }
424
425 if (use_mfront) {
426 if (SPACE_DIM == 3) {
428 } else if (SPACE_DIM == 2) {
429 if (is_axisymmetric) {
431 } else {
433 }
434 }
435 CHKERR mfrontInterfacePtr->getCommandLineParameters();
436 }
437
439 auto dm = simple->getDM();
440 monitorPtr = boost::make_shared<Monitor>(dm, scale, mfrontInterfacePtr,
442
443 if (mfrontInterfacePtr) {
444 mfrontInterfacePtr->setMonitor(monitorPtr);
445 }
446
448}
449//! [Create common data]
450
451//! [Boundary condition]
454 auto bc_mng = mField.getInterface<BcManager>();
456
457 for (auto f : {"U", "SIGMA"}) {
458 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
459 "REMOVE_X", f, 0, 0);
460 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
461 "REMOVE_Y", f, 1, 1);
462 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
463 "REMOVE_Z", f, 2, 2);
464 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
465 "REMOVE_ALL", f, 0, 3);
466 }
467
468 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "FIX_X",
469 "SIGMA", 0, 0, false, true);
470 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "FIX_Y",
471 "SIGMA", 1, 1, false, true);
472 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "FIX_Z",
473 "SIGMA", 2, 2, false, true);
474 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "FIX_ALL",
475 "SIGMA", 0, 3, false, true);
476 CHKERR bc_mng->removeBlockDOFsOnEntities(
477 simple->getProblemName(), "NO_CONTACT", "SIGMA", 0, 3, false, true);
478
479 // Note remove has to be always before push. Then node marking will be
480 // corrupted.
481 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
482 simple->getProblemName(), "U");
483
485}
486//! [Boundary condition]
487
488//! [Push operators to pip]
492 auto *pip_mng = mField.getInterface<PipelineManager>();
493 auto time_scale = boost::make_shared<ScaledTimeScale>();
494 auto body_force_time_scale =
495 boost::make_shared<ScaledTimeScale>("body_force_hist.txt");
496
497 auto integration_rule_vol = [](int, int, int approx_order) {
498 return 2 * approx_order + geom_order - 1;
499 };
500 auto integration_rule_boundary = [](int, int, int approx_order) {
501 return 2 * approx_order + geom_order - 1;
502 };
503
504 auto add_domain_base_ops = [&](auto &pip) {
507 "GEOMETRY");
509 };
510
511 auto add_domain_ops_lhs = [&](auto &pip) {
513
514 //! [Only used for dynamics]
517 //! [Only used for dynamics]
518 if (is_quasi_static == PETSC_FALSE) {
519
520 auto *pip_mng = mField.getInterface<PipelineManager>();
521 auto fe_domain_lhs = pip_mng->getDomainLhsFE();
522
523 auto get_inertia_and_mass_damping =
524 [this, fe_domain_lhs](const double, const double, const double) {
525 return (rho * scale) * fe_domain_lhs->ts_aa +
526 (alpha_damping * scale) * fe_domain_lhs->ts_a;
527 };
528 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
529 } else {
530
531 auto *pip_mng = mField.getInterface<PipelineManager>();
532 auto fe_domain_lhs = pip_mng->getDomainLhsFE();
533
534 auto get_inertia_and_mass_damping =
535 [this, fe_domain_lhs](const double, const double, const double) {
536 return (alpha_damping * scale) * fe_domain_lhs->ts_a;
537 };
538 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
539 }
540
541 if (!mfrontInterfacePtr) {
542 if (!is_large_strain) {
543 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
544 mField, pip, "U", "MAT_ELASTIC", Sev::verbose, scale);
545 } else {
546 CHKERR HenckyOps::opFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
547 mField, pip, "U", "MAT_ELASTIC", Sev::verbose, scale);
548 }
549 } else {
550 CHKERR mfrontInterfacePtr->opFactoryDomainLhs(pip, "U");
551 }
552
554 };
555
556 auto add_domain_ops_rhs = [&](auto &pip) {
558
560 pip, mField, "U", {body_force_time_scale}, Sev::inform);
561
562 //! [Only used for dynamics]
565 //! [Only used for dynamics]
566
567 // only in case of dynamics
568 if (is_quasi_static == PETSC_FALSE) {
569 auto mat_acceleration = boost::make_shared<MatrixDouble>();
571 "U", mat_acceleration));
572 pip.push_back(
573 new OpInertiaForce("U", mat_acceleration, [](double, double, double) {
574 return rho * scale;
575 }));
576 }
577
578 // only in case of viscosity
579 if (alpha_damping > 0) {
580 auto mat_velocity = boost::make_shared<MatrixDouble>();
581 pip.push_back(
582 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", mat_velocity));
583 pip.push_back(
584 new OpInertiaForce("U", mat_velocity, [](double, double, double) {
585 return alpha_damping * scale;
586 }));
587 }
588
589 if (!mfrontInterfacePtr) {
590 if (!is_large_strain) {
591 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
592 mField, pip, "U", "MAT_ELASTIC", Sev::inform, 1, scale);
593 } else {
594 CHKERR HenckyOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
595 mField, pip, "U", "MAT_ELASTIC", Sev::inform, scale);
596 }
597 } else {
598 CHKERR mfrontInterfacePtr->opFactoryDomainRhs(pip, "U");
599 }
600
601 CHKERR ContactOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
602 pip, "SIGMA", "U", is_axisymmetric);
603
605 };
606
607 auto add_boundary_base_ops = [&](auto &pip) {
610 "GEOMETRY");
611 // We have to integrate on curved face geometry, thus integration weight
612 // have to adjusted.
613 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
615 };
616
617 auto add_boundary_ops_lhs = [&](auto &pip) {
619
620 //! [Operators used for contact]
623 //! [Operators used for contact]
624
625 // Add Natural BCs to LHS
627 pip, mField, "U", Sev::inform);
628
629 if (spring_stiffness > 0 || vis_spring_stiffness > 0) {
630
631 auto *pip_mng = mField.getInterface<PipelineManager>();
632 auto fe_boundary_lhs = pip_mng->getBoundaryLhsFE();
633
634 pip.push_back(new OpSpringLhs(
635 "U", "U",
636
637 [this, fe_boundary_lhs](double, double, double) {
638 return spring_stiffness * scale +
639 (vis_spring_stiffness * scale) * fe_boundary_lhs->ts_a;
640 }
641
642 ));
643 }
644
645 CHKERR
646 ContactOps::opFactoryBoundaryLhs<SPACE_DIM, AT, GAUSS, BoundaryEleOp>(
647 pip, "SIGMA", "U", is_axisymmetric);
649 DomainEle>(
650 mField, pip, simple->getDomainFEName(), "SIGMA", "U", "GEOMETRY",
651 integration_rule_vol, is_axisymmetric);
652
654 };
655
656 auto add_boundary_ops_rhs = [&](auto &pip) {
658
659 //! [Operators used for contact]
662 //! [Operators used for contact]
663
664 // Add Natural BCs to RHS
666 pip, mField, "U", {time_scale}, Sev::inform);
667
668 if (spring_stiffness > 0 || vis_spring_stiffness > 0) {
669 auto u_disp = boost::make_shared<MatrixDouble>();
670 auto dot_u_disp = boost::make_shared<MatrixDouble>();
671 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_disp));
672 pip.push_back(
673 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", dot_u_disp));
674 pip.push_back(
675 new OpSpringRhs("U", u_disp, [this](double, double, double) {
676 return spring_stiffness * scale;
677 }));
678 pip.push_back(
679 new OpSpringRhs("U", dot_u_disp, [this](double, double, double) {
681 }));
682 }
683
684 CHKERR
685 ContactOps::opFactoryBoundaryRhs<SPACE_DIM, AT, GAUSS, BoundaryEleOp>(
686 pip, "SIGMA", "U", is_axisymmetric);
687
689 };
690
691 CHKERR add_domain_base_ops(pip_mng->getOpDomainLhsPipeline());
692 CHKERR add_domain_base_ops(pip_mng->getOpDomainRhsPipeline());
693 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
694 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
695
696 CHKERR add_boundary_base_ops(pip_mng->getOpBoundaryLhsPipeline());
697 CHKERR add_boundary_base_ops(pip_mng->getOpBoundaryRhsPipeline());
698 CHKERR add_boundary_ops_lhs(pip_mng->getOpBoundaryLhsPipeline());
699 CHKERR add_boundary_ops_rhs(pip_mng->getOpBoundaryRhsPipeline());
700
701 if (mfrontInterfacePtr) {
702 CHKERR mfrontInterfacePtr->setUpdateInternalVariablesOperators(
703 integration_rule_vol, "U");
704 CHKERR mfrontInterfacePtr->setPostProcessOperators(
705 integration_rule_vol, simple->getDomainFEName(), "U", order);
706 }
707
708 CHKERR pip_mng->setDomainRhsIntegrationRule(integration_rule_vol);
709 CHKERR pip_mng->setDomainLhsIntegrationRule(integration_rule_vol);
710 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_boundary);
711 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_boundary);
712
714}
715//! [Push operators to pip]
716
717//! [Solve]
718struct SetUpSchur {
719 static boost::shared_ptr<SetUpSchur>
722
723protected:
724 SetUpSchur() = default;
725};
726
729
732 ISManager *is_manager = mField.getInterface<ISManager>();
733
734 auto set_section_monitor = [&](auto solver) {
736 SNES snes;
737 CHKERR TSGetSNES(solver, &snes);
738 PetscViewerAndFormat *vf;
739 CHKERR PetscViewerAndFormatCreate(PETSC_VIEWER_STDOUT_WORLD,
740 PETSC_VIEWER_DEFAULT, &vf);
741 CHKERR SNESMonitorSet(
742 snes,
743 (MoFEMErrorCode (*)(SNES, PetscInt, PetscReal,
744 void *))SNESMonitorFields,
745 vf, (MoFEMErrorCode (*)(void **))PetscViewerAndFormatDestroy);
747 };
748
749 auto scatter_create = [&](auto D, auto coeff) {
751 CHKERR is_manager->isCreateProblemFieldAndRank(simple->getProblemName(),
752 ROW, "U", coeff, coeff, is);
753 int loc_size;
754 CHKERR ISGetLocalSize(is, &loc_size);
755 Vec v;
756 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &v);
757 VecScatter scatter;
758 CHKERR VecScatterCreate(D, is, v, PETSC_NULLPTR, &scatter);
759 return std::make_tuple(SmartPetscObj<Vec>(v),
761 };
762
763 auto set_time_monitor = [&](auto dm, auto solver) {
765 monitorPtr->setScatterVectors(uXScatter, uYScatter, uZScatter);
766 boost::shared_ptr<ForcesAndSourcesCore> null;
767 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(),
768 monitorPtr, null, null);
770 };
771
772 auto set_essential_bc = [&]() {
774 // This is low level pushing finite elements (pipelines) to solver
775 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
776 auto pre_proc_ptr = boost::make_shared<FEMethod>();
777 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
778 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
779
780 // Add boundary condition scaling
781 auto time_scale = boost::make_shared<TimeScale>();
782
783 auto get_bc_hook_rhs = [&]() {
785 {time_scale}, false);
786 return hook;
787 };
788 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
789
790 auto get_post_proc_hook_rhs = [&]() {
792 mField, post_proc_rhs_ptr, 1.);
793 };
794 auto get_post_proc_hook_lhs = [&]() {
796 mField, post_proc_lhs_ptr, 1.);
797 };
798 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs();
799
800 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
801 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
802 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
803 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
804 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
806 };
807
808 // Set up Schur preconditioner
809 auto set_schur_pc = [&](auto solver) {
810 boost::shared_ptr<SetUpSchur> schur_ptr;
811 if (AT == AssemblyType::BLOCK_SCHUR) {
812 // Set up Schur preconditioner
814 CHK_MOAB_THROW(schur_ptr->setUp(solver), "SetUpSchur::setUp");
815 }
816 return schur_ptr;
817 };
818
819 auto dm = simple->getDM();
820 auto D = createDMVector(dm);
821
823
824 uXScatter = scatter_create(D, 0);
825 uYScatter = scatter_create(D, 1);
826 if (SPACE_DIM == 3)
827 uZScatter = scatter_create(D, 2);
828
829 // Add extra finite elements to SNES solver pipelines to resolve essential
830 // boundary conditions
831 CHKERR set_essential_bc();
832
834
835 if (is_quasi_static == PETSC_TRUE) {
836 auto solver = pip_mng->createTSIM();
837 CHKERR TSSetFromOptions(solver);
838
839 auto B = createDMMatrix(dm);
840 CHKERR TSSetIJacobian(solver, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
841 auto schur_pc_ptr = set_schur_pc(solver);
842
843 auto D = createDMVector(dm);
844 CHKERR set_section_monitor(solver);
845 CHKERR set_time_monitor(dm, solver);
846 CHKERR TSSetSolution(solver, D);
847 CHKERR TSSetUp(solver);
848 CHKERR TSSolve(solver, NULL);
849 CHKERR testing->checkSolver(solver, "contact");
850 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
851 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
852 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
853 } else {
854 auto solver = pip_mng->createTSIM2();
855 CHKERR TSSetFromOptions(solver);
856
857 auto B = createDMMatrix(dm);
858 CHKERR TSSetI2Jacobian(solver, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
859 auto schur_pc_ptr = set_schur_pc(solver);
860
861 auto D = createDMVector(dm);
862 auto DD = vectorDuplicate(D);
863 CHKERR set_section_monitor(solver);
864 CHKERR set_time_monitor(dm, solver);
865 CHKERR TS2SetSolution(solver, D, DD);
866 CHKERR TSSetUp(solver);
867 CHKERR TSSolve(solver, NULL);
868 CHKERR testing->checkSolver(solver, "contact");
869 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
870 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
871 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
872 }
873
875}
876//! [Solve]
877
878//! [Check]
879
883 auto dm = mField.getInterface<Simple>()->getDM();
884
885 // totalTractionAndArea is a ghost vector fully owned by rank 0 (see
886 // ContactOps::CommonData::createTotalTraction); broadcast it so every rank
887 // runs the collective checks below with identical values.
888 double t[LAST_TOTAL_TRACTION_AND_AREA] = {0., 0., 0., 0., 0.};
889 if (!mField.get_comm_rank()) {
890 const double *t_ptr;
892 &t_ptr);
893 for (int i = 0; i != LAST_TOTAL_TRACTION_AND_AREA; ++i)
894 t[i] = t_ptr[i];
896 &t_ptr);
897 }
898 CHKERR MPI_Bcast(t, LAST_TOTAL_TRACTION_AND_AREA, MPI_DOUBLE, 0,
899 mField.get_comm());
900
901 auto add_case = [&](int number, const std::string &name, double hertz_force,
902 double fem_force, double tol_force,
903 double analytical_active_area, double tol_area,
904 TestingInterface::TestHook pressure_check = {}) {
905 return testing->addTestCommandLine(
906 "", number, name,
907 [testing, hertz_force, fem_force, tol_force, analytical_active_area,
908 tol_area, fem_active_area = t[AREA_ACTIVE], pressure_check]() {
910 CHKERR testing->checkValue<TestType::SCALAR>(
911 "Hertz contact force", fem_force, hertz_force, {0., tol_force});
912 CHKERR testing->checkValue<TestType::SCALAR>(
913 "contact active area", fem_active_area, analytical_active_area,
914 {tol_area, 0.});
915 if (pressure_check)
916 CHKERR pressure_check();
918 });
919 };
920
921 CHKERR add_case(1, "hertz plane stress", 3.927, t[TY], 1e-3, 1.0, 3e-2);
922 CHKERR add_case(2, "hertz plane strain", 4.675, t[TY], 1e-3, 1.0, 3e-2,
923 [dm, &m_field = mField]() {
925 m_field, 7.5,
926 "hertz plane strain pressure norm")(dm.get());
927 });
928 CHKERR add_case(3, "hertz 3d", 3.968, t[TZ], 2e-3, M_PI / 4, 0.2);
929 CHKERR add_case(4, "hertz axisymmetric flat", 15.873, t[TY], 5e-3, M_PI, 0.2);
930 CHKERR add_case(5, "hertz axisymmetric sphere", 15.873, t[TY], 5e-3, M_PI,
931 3e-2, [dm, &m_field = mField]() {
933 m_field, 7.5,
934 "hertz axisymmetric pressure norm")(dm.get());
935 });
936 CHKERR add_case(6, "wavy 2d", 0.374, t[TY], 1e-3, 1.0, 3e-2);
937 CHKERR add_case(7, "wavy 3d", 0.5289, t[TZ], 1e-3, 1.0, 3e-2);
938
939 CHKERR testing->runTests();
940
942
944}
945//! [Check]
946
947static char help[] = "...\n\n";
948
949int main(int argc, char *argv[]) {
950
951#ifdef ENABLE_PYTHON_BINDING
952 Py_Initialize();
953 np::initialize();
954#endif
955
956 // Initialisation of MoFEM/PETSc and MOAB data structures
957 const char param_file[] = "param_file.petsc";
958 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
959
960 // Add logging channel for CONTACT
961 auto core_log = logging::core::get();
962 core_log->add_sink(
964 LogManager::setLog("CONTACT");
965 MOFEM_LOG_TAG("CONTACT", "Indent");
966
967 try {
968
969 //! [Register MoFEM discrete manager in PETSc]
970 DMType dm_name = "DMMOFEM";
971 CHKERR DMRegister_MoFEM(dm_name);
972 DMType dm_name_mg = "DMMOFEM_MG";
974 //! [Register MoFEM discrete manager in PETSc
975
976 //! [Create MoAB]
977 moab::Core mb_instance; ///< mesh database
978 moab::Interface &moab = mb_instance; ///< mesh database interface
979 //! [Create MoAB]
980
981 //! [Create MoFEM]
982 MoFEM::Core core(moab); ///< finite element database
983 MoFEM::Interface &m_field = core; ///< finite element database interface
984 //! [Create MoFEM]
985
986 //! [Load mesh]
987 Simple *simple = m_field.getInterface<Simple>();
989 CHKERR simple->loadFile("");
990 CHKERR m_field.getInterface<MeshsetsManager>()->setMeshsetFromFile();
991 //! [Load mesh]
992
993 //! [CONTACT]
994 Contact ex(m_field);
995 CHKERR ex.runProblem();
996 //! [CONTACT]
997 }
999
1001
1002#ifdef ENABLE_PYTHON_BINDING
1003 if (Py_FinalizeEx() < 0) {
1004 exit(120);
1005 }
1006#endif
1007
1008 return 0;
1009}
1010
1011struct SetUpSchurImpl : public SetUpSchur {
1012
1014
1015 virtual ~SetUpSchurImpl() {}
1016
1018
1019private:
1022 MoFEMErrorCode setPC(PC pc);
1024
1026
1030};
1031
1034 auto simple = mField.getInterface<Simple>();
1035 auto pip = mField.getInterface<PipelineManager>();
1036
1037 SNES snes;
1038 CHKERR TSGetSNES(solver, &snes);
1039 KSP ksp;
1040 CHKERR SNESGetKSP(snes, &ksp);
1041 CHKERR KSPSetFromOptions(ksp);
1042
1043 PC pc;
1044 CHKERR KSPGetPC(ksp, &pc);
1045
1046 PetscBool is_pcfs = PETSC_FALSE;
1047 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1048 if (is_pcfs) {
1049
1050 MOFEM_LOG("CONTACT", Sev::inform) << "Setup Schur pc";
1051
1052 if (S) {
1055 "It is expected that Schur matrix is not allocated. This is "
1056 "possible only if PC is set up twice");
1057 }
1058
1060
1061 // Add data to DM storage
1063 CHKERR MatSetBlockSize(S, SPACE_DIM);
1064 // CHKERR MatSetOption(S, MAT_SYMMETRIC, PETSC_TRUE);
1065
1066 // Set DM to use shell block matrix
1067 DM solver_dm;
1068 CHKERR TSGetDM(solver, &solver_dm);
1069 CHKERR DMSetMatType(solver_dm, MATSHELL);
1070
1071 auto ts_ctx_ptr = getDMTsCtx(solver_dm);
1072 auto A = createDMBlockMat(simple->getDM());
1073 auto P = createDMNestSchurMat(simple->getDM());
1074
1075 if (is_quasi_static == PETSC_TRUE) {
1076 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a,
1077 Mat A, Mat B, void *ctx) {
1078 return TsSetIJacobian(ts, t, u, u_t, a, B, A, ctx);
1079 };
1080 CHKERR TSSetIJacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1081 } else {
1082 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec utt,
1083 PetscReal a, PetscReal aa, Mat A, Mat B,
1084 void *ctx) {
1085 return TsSetI2Jacobian(ts, t, u, u_t, utt, a, aa, B, A, ctx);
1086 };
1087 CHKERR TSSetI2Jacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1088 }
1089 CHKERR KSPSetOperators(ksp, A, P);
1090
1092 CHKERR setPC(pc);
1093 CHKERR TSSetUp(solver);
1094 CHKERR KSPSetUp(ksp);
1096
1097 } else {
1098 MOFEM_LOG("CONTACT", Sev::inform) << "No Schur PC";
1099 pip->getOpBoundaryLhsPipeline().push_front(createOpSchurAssembleBegin());
1100 pip->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd({}, {}));
1101 pip->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
1102 pip->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd({}, {}));
1103 }
1105}
1106
1109 auto simple = mField.getInterface<Simple>();
1110
1111 auto create_dm = [&](const char *name, const char *field_name, auto dm_type) {
1112 auto dm = createDM(mField.get_comm(), dm_type);
1113 auto create_dm_imp = [&]() {
1115 CHKERR DMMoFEMCreateSubDM(dm, simple->getDM(), name);
1116 CHKERR DMMoFEMSetSquareProblem(dm, PETSC_TRUE);
1117 CHKERR DMMoFEMAddElement(dm, simple->getDomainFEName());
1120 CHKERR DMSetUp(dm);
1122 };
1124 create_dm_imp(),
1125 "Error in creating schurDM. It is possible that schurDM is "
1126 "already created");
1127 return dm;
1128 };
1129
1130 // Note: here we can make block with bubbles of "U" and "SIGMA" fields. See
1131 // vec-0_elasticity where bubbles are added.
1132
1133 schurDM = create_dm("SCHUR", "U", "DMMOFEM_MG");
1134 blockDM = create_dm("BLOCK", "SIGMA", "DMMOFEM");
1135
1136 if constexpr (AT == AssemblyType::BLOCK_SCHUR) {
1137
1138 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
1139 auto block_mat_data = createBlockMatStructure(
1140 simple->getDM(),
1141
1142 {{
1143
1144 simple->getDomainFEName(),
1145
1146 {
1147
1148 {"U", "U"}, {"SIGMA", "U"}, {"U", "SIGMA"}, {"SIGMA", "SIGMA"}
1149
1150 }}}
1151
1152 );
1153
1155
1156 {schur_dm, block_dm}, block_mat_data,
1157
1158 {"SIGMA"}, {nullptr}, true
1159
1160 );
1161 };
1162
1163 auto nested_mat_data = get_nested_mat_data(schurDM, blockDM);
1164 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
1165
1166 } else {
1167 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1168 "Only BLOCK_SCHUR is implemented");
1169 }
1170
1172}
1173
1176
1177 double eps_stab = 1e-4;
1178 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-eps_stab", &eps_stab,
1179 PETSC_NULLPTR);
1180
1183 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
1184
1185 auto simple = mField.getInterface<Simple>();
1186 auto pip = mField.getInterface<PipelineManager>();
1187
1188 auto dm_is = getDMSubData(schurDM)->getSmartRowIs();
1189 auto ao_up = createAOMappingIS(dm_is, PETSC_NULLPTR);
1190
1191 // Boundary
1192 pip->getOpBoundaryLhsPipeline().push_front(createOpSchurAssembleBegin());
1193 pip->getOpBoundaryLhsPipeline().push_back(
1194 new OpMassStab("SIGMA", "SIGMA",
1195 [eps_stab](double, double, double) { return eps_stab; }));
1196 pip->getOpBoundaryLhsPipeline().push_back(
1197
1198 createOpSchurAssembleEnd({"SIGMA"}, {nullptr}, ao_up, S, false, false)
1199
1200 );
1201
1202 // Domain
1203 pip->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
1204 pip->getOpDomainLhsPipeline().push_back(
1205
1206 createOpSchurAssembleEnd({"SIGMA"}, {nullptr}, ao_up, S, false, false)
1207
1208 );
1209
1210 auto pre_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
1211 auto post_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
1212
1213 pre_proc_schur_lhs_ptr->preProcessHook = [this]() {
1215 CHKERR MatZeroEntries(S);
1216 MOFEM_LOG("CONTACT", Sev::verbose) << "Lhs Assemble Begin";
1218 };
1219
1220 post_proc_schur_lhs_ptr->postProcessHook = [this, ao_up,
1221 post_proc_schur_lhs_ptr]() {
1223 MOFEM_LOG("CONTACT", Sev::verbose) << "Lhs Assemble End";
1224 [[maybe_unused]] auto print_mat_norm = [this](auto a, std::string prefix) {
1226 double nrm;
1227 CHKERR MatNorm(a, NORM_FROBENIUS, &nrm);
1228 MOFEM_LOG("CONTACT", Sev::noisy) << prefix << " norm = " << nrm;
1230 };
1231 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
1232 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
1234 mField, post_proc_schur_lhs_ptr, 1, S, ao_up)();
1235#ifndef NDEBUG
1236 CHKERR print_mat_norm(S, "S");
1237#endif // NDEBUG
1238 MOFEM_LOG("CONTACT", Sev::verbose) << "Lhs Assemble Finish";
1240 };
1241
1242 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
1243 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_schur_lhs_ptr);
1244 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_schur_lhs_ptr);
1245
1247}
1248
1251 auto block_is = getDMSubData(blockDM)->getSmartRowIs();
1252 CHKERR PCFieldSplitSetIS(pc, NULL, block_is);
1253 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
1255}
1256
1259 KSP *subksp;
1260 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
1261 auto get_pc = [](auto ksp) {
1262 PC pc_raw;
1263 CHKERR KSPGetPC(ksp, &pc_raw);
1264 return SmartPetscObj<PC>(pc_raw, true); // bump reference
1265 };
1266 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
1267
1268 auto set_pc_p_mg = [](auto dm, auto pc, auto S) {
1270 CHKERR PCSetDM(pc, dm);
1271 PetscBool same = PETSC_FALSE;
1272 PetscObjectTypeCompare((PetscObject)pc, PCMG, &same);
1273 if (same) {
1275 pc, createPCMGSetUpViaApproxOrdersCtx(dm, S, true));
1276 CHKERR PCSetFromOptions(pc);
1277 }
1279 };
1280
1281 auto set_pc_ksp = [&](auto dm, auto pc, auto S) {
1283 PetscBool same = PETSC_FALSE;
1284 PetscObjectTypeCompare((PetscObject)pc, PCKSP, &same);
1285 if (same) {
1286 CHKERR PCSetFromOptions(pc);
1287 KSP inner_ksp;
1288 CHKERR PCKSPGetKSP(pc, &inner_ksp);
1289 CHKERR KSPSetFromOptions(inner_ksp);
1290 PC inner_pc;
1291 CHKERR KSPGetPC(inner_ksp, &inner_pc);
1292 CHKERR PCSetFromOptions(inner_pc);
1293 CHKERR set_pc_p_mg(dm, inner_pc, S);
1294 }
1296 };
1297
1298 CHKERR set_pc_ksp(schurDM, get_pc(subksp[1]), S);
1299 CHKERR set_pc_p_mg(schurDM, get_pc(subksp[1]), S);
1300
1301 CHKERR PetscFree(subksp);
1303}
1304
1305boost::shared_ptr<SetUpSchur>
1307 return boost::shared_ptr<SetUpSchur>(new SetUpSchurImpl(m_field));
1308}
SmartPetscObj< KSP > ksp
Implementation of Hookes operator Hookes for linear elastic problems in MoFEM.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
TestHook hook
int number
std::string name
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
constexpr double a
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
double young_modulus
Definition contact.cpp:82
int sigma_order
Definition contact.cpp:80
constexpr AssemblyType AT
Definition contact.cpp:34
constexpr IntegrationType IT
Definition contact.cpp:37
static char help[]
[Check]
Definition contact.cpp:947
#define SCHUR_ASSEMBLE
Definition contact.cpp:18
double spring_stiffness
Definition contact.cpp:85
PetscBool is_large_strain
Definition contact.cpp:92
double rho
Definition contact.cpp:84
#define EXECUTABLE_DIMENSION
Definition contact.cpp:14
PetscBool is_quasi_static
[Operators used for contact]
Definition contact.cpp:76
double alpha_damping
Definition contact.cpp:87
constexpr int SPACE_DIM
Definition contact.cpp:53
double poisson_ratio
Definition contact.cpp:83
double vis_spring_stiffness
Definition contact.cpp:86
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
Definition contact.cpp:60
double scale
Definition contact.cpp:89
FormsIntegrators< BoundaryEleOp >::Assembly< AT >::BiLinearForm< IT >::OpMass< 1, SPACE_DIM > OpSpringLhs
[Operators used for contact]
Definition contact.cpp:71
FormsIntegrators< BoundaryEleOp >::Assembly< AT >::LinearForm< IT >::OpBaseTimesVector< 1, SPACE_DIM, SPACE_DIM > OpSpringRhs
Definition contact.cpp:73
int contact_order
Definition contact.cpp:79
int order
Definition contact.cpp:78
PetscBool is_axisymmetric
Definition contact.cpp:91
int geom_order
Definition contact.cpp:81
constexpr FieldSpace CONTACT_SPACE
[Specialisation for assembly]
Definition contact.cpp:67
@ ROW
#define CATCH_ERRORS
Catch errors.
FieldApproximationBase
approximation base
Definition definitions.h:58
@ LASTBASE
Definition definitions.h:69
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
FieldSpace
approximation spaces
Definition definitions.h:82
@ H1
continuous field
Definition definitions.h:85
@ HCURL
field with continuous tangents
Definition definitions.h:86
@ HDIV
field with continuous normal traction
Definition definitions.h:87
#define MYPCOMM_INDEX
default communicator number PCOMM
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesVector< 1, SPACE_DIM, SPACE_DIM > OpInertiaForce
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
Definition DMMoFEM.cpp:244
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:517
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:479
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:267
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:543
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
MoFEMErrorCode DMRegister_MGViaApproxOrders(const char sname[])
Register DM for Multi-Grid via approximation orders.
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1250
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:309
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1207
IntegrationType
Form integrator integration types.
AssemblyType
[Storage and set boundary conditions]
@ GAUSS
Gaussian quadrature integration.
@ PETSC
Standard PETSc assembly.
@ BLOCK_PRECONDITIONER_SCHUR
Block preconditioner Schur assembly.
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
FTensor::Index< 'i', SPACE_DIM > i
PetscBool testing
double D
const double v
phase velocity of light in medium (cm/ns)
double cn_contact
Definition contact.cpp:95
@ LAST_TOTAL_TRACTION_AND_AREA
MoFEMErrorCode opFactoryBoundaryToDomainLhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string fe_domain_name, std::string sigma, std::string u, std::string geom, ForcesAndSourcesCore::RuleHookFun rule, bool is_axisymmetric=false)
[HenckyOps]
Definition HenckyOps.hpp:12
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode DMMoFEMTSSetMonitor(DM dm, TS ts, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
Set Monitor To TS solver.
Definition DMMoFEM.cpp:1075
PetscErrorCode TsSetIJacobian(TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a, Mat A, Mat B, void *ctx)
Set function evaluating jacobian in TS solver.
Definition TsCtx.cpp:169
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1292
OpSchurAssembleBase * createOpSchurAssembleEnd(std::vector< std::string > fields_name, std::vector< boost::shared_ptr< Range > > field_ents, SmartPetscObj< AO > ao, SmartPetscObj< Mat > schur, bool sym_schur, bool symm_op)
Construct a new Op Schur Assemble End object.
Definition Schur.cpp:4196
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode setSchurA00MatSolvePC(SmartPetscObj< PC > pc)
Set PC for A00 block.
Definition Schur.cpp:4238
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > createPCMGSetUpViaApproxOrdersCtx(DM dm, Mat A, bool use_shell_mat)
createPCMGSetUpViaApproxOrdersCtx
auto getDMSubData(DM dm)
Get sub problem data structure.
Definition DMMoFEM.hpp:1308
boost::shared_ptr< MFrontInterface > createMFrontInterface(MoFEM::Interface &m_field, ModelHypothesis mh, AssemblyType at)
create mfront interface
PetscErrorCode TsSetI2Jacobian(TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, PetscReal a, PetscReal aa, Mat A, Mat B, void *ctx)
Calculation Jacobian for second order PDE in time.
Definition TsCtx.cpp:519
MoFEMErrorCode PCMGSetUpViaApproxOrders(PC pc, boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > ctx, int verb)
Function build MG structure.
@ AXISYMMETRICAL
Axisymmetrical model hypothesis.
@ PLANESTRAIN
Plane strain model hypothesis.
@ TRIDIMENSIONAL
3D model hypothesis.
boost::shared_ptr< BlockStructure > createBlockMatStructure(DM dm, SchurFEOpsFEandFields schur_fe_op_vec)
Create block matrix structure.
Definition Schur.cpp:2415
boost::shared_ptr< NestSchurData > createSchurNestedMatrixStruture(std::pair< SmartPetscObj< DM >, SmartPetscObj< DM > > dms, boost::shared_ptr< BlockStructure > block_mat_data_ptr, std::vector< std::string > fields_names, std::vector< boost::shared_ptr< Range > > field_ents, bool add_preconditioner_block)
Create structure of nested matrix [A11 A10; A01 A00].
Definition Schur.cpp:3667
auto createAOMappingIS(IS isapp, IS ispetsc)
Creates an application mapping using two index sets.
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
MoFEMErrorCode DMMoFEMSetNestSchurData(DM dm, boost::shared_ptr< NestSchurData >)
Definition DMMoFEM.cpp:1584
auto createDMNestSchurMat(DM dm)
Definition DMMoFEM.hpp:1234
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
OpSchurAssembleBase * createOpSchurAssembleBegin()
Definition Schur.cpp:4191
auto createDMBlockMat(DM dm)
Definition DMMoFEM.hpp:1227
PetscBool is_quasi_static
Definition plastic.cpp:144
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:62
constexpr FieldSpace CONTACT_SPACE
Definition plastic.cpp:52
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
static constexpr int approx_order
constexpr int SPACE_DIM
[Define dimension]
constexpr AssemblyType A
[Define dimension]
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
Definition seepage.cpp:56
FTensor::Index< 'm', 3 > m
static SmartPetscObj< Vec > totalTractionAndArea
static auto createTotalTraction(MoFEM::Interface &m_field)
double getScale(const double time)
Get scaling at given time.
Definition contact.cpp:149
boost::shared_ptr< MFrontInterface > mfrontInterfacePtr
Definition contact.cpp:140
boost::shared_ptr< Monitor > monitorPtr
Definition contact.cpp:141
MoFEMErrorCode tsSolve()
Definition contact.cpp:727
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
Definition contact.cpp:137
MoFEMErrorCode runProblem()
[Run problem]
Definition contact.cpp:156
MoFEMErrorCode setupProblem()
[Run problem]
Definition contact.cpp:169
MoFEMErrorCode OPs()
[Boundary condition]
Definition contact.cpp:489
MoFEMErrorCode createCommonData()
[Set up problem]
Definition contact.cpp:309
MoFEMErrorCode checkResults()
[Solve]
Definition contact.cpp:880
MoFEM::Interface & mField
Definition contact.cpp:127
MoFEMErrorCode bC()
[Create common data]
Definition contact.cpp:452
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
Definition contact.cpp:136
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
Definition contact.cpp:138
Contact(MoFEM::Interface &m_field)
Definition contact.cpp:121
[Operators_definition]
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
Managing BitRefLevels.
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Core (interface) class.
Definition Core.hpp:83
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
Deprecated interface functions.
Definition of the displacement bc data structure.
Definition BCData.hpp:72
Data on single entity (This is passed as argument to DataOperator::doWork)
Class (Function) to enforce essential constrains on the left hand side diagonal.
Definition Essential.hpp:33
Class (Function) to enforce essential constrains on the right hand side diagonal.
Definition Essential.hpp:41
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
std::string getPythonScriptByKey(const std::string &key) const
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
Interface for managing meshsets containing materials and boundary conditions.
Assembly methods.
Definition Natural.hpp:65
Approximate field values for given petsc vector.
Specialization for MatrixDouble vector field values calculation.
Template struct for dimension-specific finite element types.
PipelineManager interface.
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
intrusive_ptr for managing petsc objects
std::function< MoFEMErrorCode()> TestHook
Force scale operator for reading two columns.
double getScale(const double time)
Get scaling at a given time.
TimeScale(std::string file_name="", bool error_if_file_not_given=false, ScalingFun def_scaling_fun=[](double time) { return time;})
TimeScale constructor.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
SmartPetscObj< Mat > S
MoFEMErrorCode createSubDM()
Definition contact.cpp:1107
MoFEMErrorCode setDiagonalPC(PC pc)
Definition contact.cpp:1257
SetUpSchurImpl(MoFEM::Interface &m_field)
Definition contact.cpp:1013
SmartPetscObj< DM > schurDM
Definition contact.cpp:1028
MoFEMErrorCode setUp(SmartPetscObj< KSP >)
SmartPetscObj< DM > blockDM
Definition contact.cpp:1029
virtual ~SetUpSchurImpl()
Definition contact.cpp:1015
MoFEMErrorCode setPC(PC pc)
Definition contact.cpp:1249
MoFEMErrorCode setOperator()
Definition contact.cpp:1174
MoFEM::Interface & mField
[Push operators to pipeline]
SetUpSchur()=default
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field)
virtual MoFEMErrorCode setUp(SmartPetscObj< TS > solver)=0
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field)
constexpr AssemblyType AT