v0.16.3
Loading...
Searching...
No Matches
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
Contact Struct Reference
Collaboration diagram for Contact:
[legend]

Classes

struct  ScaledTimeScale
 

Public Member Functions

 Contact (MoFEM::Interface &m_field)
 
MoFEMErrorCode runProblem ()
 [Run problem]
 

Private Member Functions

MoFEMErrorCode setupProblem ()
 [Run problem]
 
MoFEMErrorCode createCommonData ()
 [Set up problem]
 
MoFEMErrorCode bC ()
 [Create common data]
 
MoFEMErrorCode OPs ()
 [Boundary condition]
 
MoFEMErrorCode tsSolve ()
 
MoFEMErrorCode checkResults ()
 [Solve]
 

Private Attributes

MoFEM::Interface & mField
 
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
 
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
 
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
 
boost::shared_ptr< MFrontInterface > mfrontInterfacePtr
 
boost::shared_ptr< Monitor > monitorPtr
 

Detailed Description

Definition at line 119 of file contact.cpp.

Constructor & Destructor Documentation

◆ Contact()

Contact::Contact ( MoFEM::Interface &  m_field)
inline

Definition at line 121 of file contact.cpp.

122 : mField(m_field), mfrontInterfacePtr(nullptr) {}
boost::shared_ptr< MFrontInterface > mfrontInterfacePtr
Definition contact.cpp:140
MoFEM::Interface & mField
Definition contact.cpp:127

Member Function Documentation

◆ bC()

MoFEMErrorCode Contact::bC ( )
private

[Create common data]

[Boundary condition]

Definition at line 452 of file contact.cpp.

452 {
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}
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
Boundary condition manager for finite element problem setup.
Definition of the displacement bc data structure.
Definition BCData.hpp:72
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.

◆ checkResults()

MoFEMErrorCode Contact::checkResults ( )
private

[Solve]

[Check]

Definition at line 880 of file contact.cpp.

880 {
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}
int number
std::string name
FTensor::Index< 'i', SPACE_DIM > i
PetscBool testing
@ LAST_TOTAL_TRACTION_AND_AREA
constexpr double t
plate stiffness
Definition plate.cpp:58
static SmartPetscObj< Vec > totalTractionAndArea
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
std::function< MoFEMErrorCode()> TestHook

◆ createCommonData()

MoFEMErrorCode Contact::createCommonData ( )
private

[Set up problem]

[Create common data]

Definition at line 309 of file contact.cpp.

309 {
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}
double young_modulus
Definition contact.cpp:82
constexpr AssemblyType AT
Definition contact.cpp:34
double spring_stiffness
Definition contact.cpp:85
PetscBool is_large_strain
Definition contact.cpp:92
double rho
Definition contact.cpp:84
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
double scale
Definition contact.cpp:89
PetscBool is_axisymmetric
Definition contact.cpp:91
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MOFEM_LOG(channel, severity)
Log.
double cn_contact
Definition contact.cpp:95
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)
boost::shared_ptr< MFrontInterface > createMFrontInterface(MoFEM::Interface &m_field, ModelHypothesis mh, AssemblyType at)
create mfront interface
@ AXISYMMETRICAL
Axisymmetrical model hypothesis.
@ PLANESTRAIN
Plane strain model hypothesis.
@ TRIDIMENSIONAL
3D model hypothesis.
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
boost::shared_ptr< Monitor > monitorPtr
Definition contact.cpp:141
std::string getPythonScriptByKey(const std::string &key) const
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799

◆ OPs()

MoFEMErrorCode Contact::OPs ( )
private

[Boundary condition]

[Push operators to pip]

[Only used for dynamics]

[Only used for dynamics]

[Only used for dynamics]

[Only used for dynamics]

[Operators used for contact]

[Operators used for contact]

[Operators used for contact]

[Operators used for contact]

Definition at line 489 of file contact.cpp.

489 {
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}
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
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 order
Definition contact.cpp:78
int geom_order
Definition contact.cpp:81
@ H1
continuous field
Definition definitions.h:85
@ HDIV
field with continuous normal traction
Definition definitions.h:87
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesVector< 1, SPACE_DIM, SPACE_DIM > OpInertiaForce
@ GAUSS
Gaussian quadrature integration.
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)
static constexpr int approx_order
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
Definition seepage.cpp:56
Add operators pushing bases from local to physical configuration.
Approximate field values for given petsc vector.
Specialization for MatrixDouble vector field values calculation.
PipelineManager interface.

◆ runProblem()

MoFEMErrorCode Contact::runProblem ( )

[Run problem]

Definition at line 156 of file contact.cpp.

156 {
160 CHKERR bC();
161 CHKERR OPs();
162 CHKERR tsSolve();
165}
MoFEMErrorCode tsSolve()
Definition contact.cpp:727
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
MoFEMErrorCode bC()
[Create common data]
Definition contact.cpp:452

◆ setupProblem()

MoFEMErrorCode Contact::setupProblem ( )
private

[Run problem]

[Set up problem]

< blocs interation is collective, so that is set irrespective if there are entities in given rank or not in the block

Definition at line 169 of file contact.cpp.

169 {
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]
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
int sigma_order
Definition contact.cpp:80
int contact_order
Definition contact.cpp:79
constexpr FieldSpace CONTACT_SPACE
[Specialisation for assembly]
Definition contact.cpp:67
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 MYPCOMM_INDEX
default communicator number PCOMM
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.
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
FTensor::Index< 'm', 3 > m
Managing BitRefLevels.
virtual moab::Interface & get_moab()=0
Interface for managing meshsets containing materials and boundary conditions.
Projection of edge entities with one mid-node on hierarchical basis.

◆ tsSolve()

MoFEMErrorCode Contact::tsSolve ( )
private

Definition at line 727 of file contact.cpp.

727 {
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}
TestHook hook
@ ROW
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
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
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1250
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1207
double D
const double v
phase velocity of light in medium (cm/ns)
const FTensor::Tensor2< T, Dim, Dim > Vec
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
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
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1292
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
static auto createTotalTraction(MoFEM::Interface &m_field)
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
Definition contact.cpp:137
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
Definition contact.cpp:136
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
Definition contact.cpp:138
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
intrusive_ptr for managing petsc objects
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field)

Member Data Documentation

◆ mField

MoFEM::Interface& Contact::mField
private

Definition at line 127 of file contact.cpp.

◆ mfrontInterfacePtr

boost::shared_ptr<MFrontInterface> Contact::mfrontInterfacePtr
private

Definition at line 140 of file contact.cpp.

◆ monitorPtr

boost::shared_ptr<Monitor> Contact::monitorPtr
private

Definition at line 141 of file contact.cpp.

◆ uXScatter

std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter> > Contact::uXScatter
private

Definition at line 136 of file contact.cpp.

◆ uYScatter

std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter> > Contact::uYScatter
private

Definition at line 137 of file contact.cpp.

◆ uZScatter

std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter> > Contact::uZScatter
private

Definition at line 138 of file contact.cpp.


The documentation for this struct was generated from the following file: