v0.16.0
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]
 
 Contact (MoFEM::Interface &m_field)
 
MoFEMErrorCode runProblem ()
 

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]
 
MoFEMErrorCode setupProblem ()
 
MoFEMErrorCode createCommonData ()
 
MoFEMErrorCode bC ()
 
MoFEMErrorCode OPs ()
 
MoFEMErrorCode tsSolve ()
 
MoFEMErrorCode checkResults ()
 

Private Attributes

MoFEM::InterfacemField
 
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
 
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
 
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
 
boost::shared_ptr< MFrontInterfacemfrontInterfacePtr
 
boost::shared_ptr< MonitormonitorPtr
 
boost::shared_ptr< GenericElementInterfacemfrontInterface
 

Detailed Description

Definition at line 120 of file contact.cpp.

Constructor & Destructor Documentation

◆ Contact() [1/2]

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

Definition at line 122 of file contact.cpp.

123 : mField(m_field), mfrontInterfacePtr(nullptr) {}
boost::shared_ptr< MFrontInterface > mfrontInterfacePtr
Definition contact.cpp:141
MoFEM::Interface & mField
Definition contact.cpp:128

◆ Contact() [2/2]

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

Definition at line 128 of file contact.cpp.

128: mField(m_field) {}

Member Function Documentation

◆ bC() [1/2]

MoFEMErrorCode Contact::bC ( )
private

[Create common data]

[Boundary condition]

Definition at line 457 of file contact.cpp.

457 {
459 auto bc_mng = mField.getInterface<BcManager>();
461
462 for (auto f : {"U", "SIGMA"}) {
463 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
464 "REMOVE_X", f, 0, 0);
465 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
466 "REMOVE_Y", f, 1, 1);
467 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
468 "REMOVE_Z", f, 2, 2);
469 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
470 "REMOVE_ALL", f, 0, 3);
471 }
472
473 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "FIX_X",
474 "SIGMA", 0, 0, false, true);
475 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "FIX_Y",
476 "SIGMA", 1, 1, false, true);
477 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "FIX_Z",
478 "SIGMA", 2, 2, false, true);
479 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "FIX_ALL",
480 "SIGMA", 0, 3, false, true);
481 CHKERR bc_mng->removeBlockDOFsOnEntities(
482 simple->getProblemName(), "NO_CONTACT", "SIGMA", 0, 3, false, true);
483
484 // Note remove has to be always before push. Then node marking will be
485 // corrupted.
486 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
487 simple->getProblemName(), "U");
488
490}
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.

◆ bC() [2/2]

MoFEMErrorCode Contact::bC ( )
private

◆ checkResults() [1/2]

MoFEMErrorCode Contact::checkResults ( )
private

[Solve]

[Check]

Definition at line 874 of file contact.cpp.

874 {
876 if (atom_test && !mField.get_comm_rank()) {
877 const double *t_ptr;
878 CHKERR VecGetArrayRead(ContactOps::CommonData::totalTraction, &t_ptr);
879 double hertz_force;
880 double fem_force;
881 double analytical_active_area = 1.0;
882 double norm = 1e-5;
883 double tol_force = 1e-3;
884 double tol_norm = 7.5; // change when analytical functions are updated
885 double tol_area = 3e-2;
886 double fem_active_area = t_ptr[3];
887
888 switch (atom_test) {
889 case 1: // plane stress
890 hertz_force = 3.927;
891 fem_force = t_ptr[1];
892 break;
893
894 case 2: // plane strain
895 hertz_force = 4.675;
896 fem_force = t_ptr[1];
897 norm = monitorPtr->getErrorNorm(1);
898 break;
899
900 case 3: // Hertz 3D
901 hertz_force = 3.968;
902 tol_force = 2e-3;
903 fem_force = t_ptr[2];
904 analytical_active_area = M_PI / 4;
905 tol_area = 0.2;
906 break;
907
908 case 4: // axisymmetric
909 tol_force = 5e-3;
910 tol_area = 0.2;
911 // analytical_active_area = M_PI;
912
913 case 5: // axisymmetric
914 hertz_force = 15.873;
915 tol_force = 5e-3;
916 fem_force = t_ptr[1];
917 norm = monitorPtr->getErrorNorm(1);
918 analytical_active_area = M_PI;
919 break;
920
921 case 6: // wavy 2d
922 hertz_force = 0.374;
923 fem_force = t_ptr[1];
924 break;
925
926 case 7: // wavy 3d
927 hertz_force = 0.5289;
928 fem_force = t_ptr[2];
929 break;
930
931 default:
932 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
933 "atom test %d does not exist", atom_test);
934 }
935 if (fabs(fem_force - hertz_force) / hertz_force > tol_force) {
936 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
937 "atom test %d failed: Wrong FORCE output: %3.4e != %3.4e",
938 atom_test, fem_force, hertz_force);
939 }
940 if (norm > tol_norm) {
941 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
942 "atom test %d failed: Wrong NORM output: %3.4e > %3.4e",
943 atom_test, norm, tol_norm);
944 }
945 if (fabs(fem_active_area - analytical_active_area) > tol_area) {
946 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
947 "atom test %d failed: AREA computed %3.4e but should be %3.4e",
948 atom_test, fem_active_area, analytical_active_area);
949 }
950 CHKERR VecRestoreArrayRead(ContactOps::CommonData::totalTraction, &t_ptr);
951 }
952
954
956}
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_INVALID_DATA
Definition definitions.h:36
static SmartPetscObj< Vec > totalTraction
boost::shared_ptr< Monitor > monitorPtr
Definition contact.cpp:142
virtual int get_comm_rank() const =0
int atom_test
Definition contact.cpp:96

◆ checkResults() [2/2]

MoFEMErrorCode Contact::checkResults ( )
private

◆ createCommonData() [1/2]

MoFEMErrorCode Contact::createCommonData ( )
private

[Set up problem]

[Create common data]

Definition at line 310 of file contact.cpp.

310 {
312
313 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-large_strain",
314 &is_large_strain, PETSC_NULLPTR);
315 PetscBool use_mfront = PETSC_FALSE;
316 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-use_mfront", &use_mfront,
317 PETSC_NULLPTR);
318 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_axisymmetric",
319 &is_axisymmetric, PETSC_NULLPTR);
320 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
321 PETSC_NULLPTR);
322
323 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-scale", &scale,
324 PETSC_NULLPTR);
325 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-young_modulus",
326 &young_modulus, PETSC_NULLPTR);
327 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-poisson_ratio",
328 &poisson_ratio, PETSC_NULLPTR);
329 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-rho", &rho, PETSC_NULLPTR);
330 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn", &cn_contact,
331 PETSC_NULLPTR);
332 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-spring_stiffness",
333 &spring_stiffness, PETSC_NULLPTR);
334 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-vis_spring_stiffness",
335 &vis_spring_stiffness, PETSC_NULLPTR);
336 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-alpha_damping",
337 &alpha_damping, PETSC_NULLPTR);
338
339 if (!use_mfront) {
340 if (!is_large_strain) {
341 MOFEM_LOG("CONTACT", Sev::inform)
342 << "Selected material model: Hooke (small strain)";
343 } else {
344 MOFEM_LOG("CONTACT", Sev::inform)
345 << "Selected material model: Hencky (finite strain)";
346 }
347 MOFEM_LOG("CONTACT", Sev::inform) << "Young modulus " << young_modulus;
348 MOFEM_LOG("CONTACT", Sev::inform) << "Poisson_ratio " << poisson_ratio;
349 } else {
350 MOFEM_LOG("CONTACT", Sev::inform) << "Using MFront for material model";
351 }
352
353 MOFEM_LOG("CONTACT", Sev::inform) << "Density " << rho;
354 MOFEM_LOG("CONTACT", Sev::inform) << "cn_contact " << cn_contact;
355 MOFEM_LOG("CONTACT", Sev::inform) << "Spring stiffness " << spring_stiffness;
356 MOFEM_LOG("CONTACT", Sev::inform)
357 << "Vis spring_stiffness " << vis_spring_stiffness;
358
359 MOFEM_LOG("CONTACT", Sev::inform) << "alpha_damping " << alpha_damping;
360
361 PetscBool use_scale = PETSC_FALSE;
362 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-use_scale", &use_scale,
363 PETSC_NULLPTR);
364 if (use_scale) {
366 }
367
368 MOFEM_LOG("CONTACT", Sev::inform) << "Scale " << scale;
369
370 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_quasi_static",
371 &is_quasi_static, PETSC_NULLPTR);
372 MOFEM_LOG("CONTACT", Sev::inform)
373 << "Is quasi-static: " << (is_quasi_static ? "true" : "false");
374
375#ifdef ENABLE_PYTHON_BINDING
376 auto file_exists = [](std::string myfile) {
377 std::ifstream file(myfile.c_str());
378 if (file) {
379 return true;
380 }
381 return false;
382 };
383 char sdf_file_name[255] = "sdf.py";
384 PetscBool has_sdf_file_option = PETSC_FALSE;
385 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-sdf_file",
386 sdf_file_name,
387 255,
388 &has_sdf_file_option);
389 if (!has_sdf_file_option) {
390 auto *json_config = mField.getInterface<JsonConfigManager>();
391 const auto contact_surface_script =
392 json_config->getPythonScriptByKey("contact_surface");
393 if (!contact_surface_script.empty()) {
394 std::strcpy(sdf_file_name, contact_surface_script.c_str());
395 MOFEM_LOG("CONTACT", Sev::inform)
396 << "Using Python script 'contact_surface' from JSON config: "
397 << sdf_file_name;
398 }
399 }
400
401 if (file_exists(sdf_file_name)) {
402 MOFEM_LOG("CONTACT", Sev::inform) << sdf_file_name << " file found";
403 sdfPythonPtr = boost::make_shared<SDFPython>();
404 CHKERR sdfPythonPtr->sdfInit(sdf_file_name);
405 sdfPythonWeakPtr = sdfPythonPtr;
406 } else {
407 MOFEM_LOG("CONTACT", Sev::warning) << sdf_file_name << " file NOT found";
408 }
409#endif
410
411 if (is_axisymmetric) {
412 if (SPACE_DIM == 3) {
413 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
414 "Use executable contact_2d with axisymmetric model");
415 } else {
416 if (!use_mfront) {
417 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
418 "Axisymmetric model is only available with MFront (set "
419 "use_mfront to 1)");
420 } else {
421 MOFEM_LOG("CONTACT", Sev::inform) << "Using axisymmetric model";
422 }
423 }
424 } else {
425 if (SPACE_DIM == 2) {
426 MOFEM_LOG("CONTACT", Sev::inform) << "Using plane strain model";
427 }
428 }
429
430 if (use_mfront) {
431 if (SPACE_DIM == 3) {
433 } else if (SPACE_DIM == 2) {
434 if (is_axisymmetric) {
436 } else {
438 }
439 }
440 CHKERR mfrontInterfacePtr->getCommandLineParameters();
441 }
442
444 auto dm = simple->getDM();
445 monitorPtr = boost::make_shared<Monitor>(dm, scale, mfrontInterfacePtr,
447
448 if (mfrontInterfacePtr) {
449 mfrontInterfacePtr->setMonitor(monitorPtr);
450 }
451
453}
@ 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:97
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
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)
std::string getPythonScriptByKey(const std::string &key) const
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
double young_modulus
Definition contact.cpp:84
constexpr AssemblyType AT
Definition contact.cpp:36
double spring_stiffness
Definition contact.cpp:87
PetscBool is_large_strain
Definition contact.cpp:94
double rho
Definition contact.cpp:86
PetscBool is_quasi_static
[Operators used for contact]
Definition contact.cpp:78
double alpha_damping
Definition contact.cpp:89
constexpr int SPACE_DIM
Definition contact.cpp:55
double poisson_ratio
Definition contact.cpp:85
double vis_spring_stiffness
Definition contact.cpp:88
PetscBool is_axisymmetric
Definition contact.cpp:93

◆ createCommonData() [2/2]

MoFEMErrorCode Contact::createCommonData ( )
private

◆ OPs() [1/2]

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 494 of file contact.cpp.

494 {
497 auto *pip_mng = mField.getInterface<PipelineManager>();
498 auto time_scale = boost::make_shared<ScaledTimeScale>();
499 auto body_force_time_scale =
500 boost::make_shared<ScaledTimeScale>("body_force_hist.txt");
501
502 auto integration_rule_vol = [](int, int, int approx_order) {
503 return 2 * approx_order + geom_order - 1;
504 };
505 auto integration_rule_boundary = [](int, int, int approx_order) {
506 return 2 * approx_order + geom_order - 1;
507 };
508
509 auto add_domain_base_ops = [&](auto &pip) {
512 "GEOMETRY");
514 };
515
516 auto add_domain_ops_lhs = [&](auto &pip) {
518
519 //! [Only used for dynamics]
522 //! [Only used for dynamics]
523 if (is_quasi_static == PETSC_FALSE) {
524
525 auto *pip_mng = mField.getInterface<PipelineManager>();
526 auto fe_domain_lhs = pip_mng->getDomainLhsFE();
527
528 auto get_inertia_and_mass_damping =
529 [this, fe_domain_lhs](const double, const double, const double) {
530 return (rho * scale) * fe_domain_lhs->ts_aa +
531 (alpha_damping * scale) * fe_domain_lhs->ts_a;
532 };
533 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
534 } else {
535
536 auto *pip_mng = mField.getInterface<PipelineManager>();
537 auto fe_domain_lhs = pip_mng->getDomainLhsFE();
538
539 auto get_inertia_and_mass_damping =
540 [this, fe_domain_lhs](const double, const double, const double) {
541 return (alpha_damping * scale) * fe_domain_lhs->ts_a;
542 };
543 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
544 }
545
546 if (!mfrontInterfacePtr) {
547 if (!is_large_strain) {
548 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
549 mField, pip, "U", "MAT_ELASTIC", Sev::verbose, scale);
550 } else {
551 CHKERR HenckyOps::opFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
552 mField, pip, "U", "MAT_ELASTIC", Sev::verbose, scale);
553 }
554 } else {
555 CHKERR mfrontInterfacePtr->opFactoryDomainLhs(pip, "U");
556 }
557
559 };
560
561 auto add_domain_ops_rhs = [&](auto &pip) {
563
565 pip, mField, "U", {body_force_time_scale}, Sev::inform);
566
567 //! [Only used for dynamics]
570 //! [Only used for dynamics]
571
572 // only in case of dynamics
573 if (is_quasi_static == PETSC_FALSE) {
574 auto mat_acceleration = boost::make_shared<MatrixDouble>();
576 "U", mat_acceleration));
577 pip.push_back(
578 new OpInertiaForce("U", mat_acceleration, [](double, double, double) {
579 return rho * scale;
580 }));
581 }
582
583 // only in case of viscosity
584 if (alpha_damping > 0) {
585 auto mat_velocity = boost::make_shared<MatrixDouble>();
586 pip.push_back(
587 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", mat_velocity));
588 pip.push_back(
589 new OpInertiaForce("U", mat_velocity, [](double, double, double) {
590 return alpha_damping * scale;
591 }));
592 }
593
594 if (!mfrontInterfacePtr) {
595 if (!is_large_strain) {
596 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
597 mField, pip, "U", "MAT_ELASTIC", Sev::inform, 1, scale);
598 } else {
599 CHKERR HenckyOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
600 mField, pip, "U", "MAT_ELASTIC", Sev::inform, scale);
601 }
602 } else {
603 CHKERR mfrontInterfacePtr->opFactoryDomainRhs(pip, "U");
604 }
605
606 CHKERR ContactOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
607 pip, "SIGMA", "U", is_axisymmetric);
608
610 };
611
612 auto add_boundary_base_ops = [&](auto &pip) {
615 "GEOMETRY");
616 // We have to integrate on curved face geometry, thus integration weight
617 // have to adjusted.
618 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
620 };
621
622 auto add_boundary_ops_lhs = [&](auto &pip) {
624
625 //! [Operators used for contact]
628 //! [Operators used for contact]
629
630 // Add Natural BCs to LHS
632 pip, mField, "U", Sev::inform);
633
634 if (spring_stiffness > 0 || vis_spring_stiffness > 0) {
635
636 auto *pip_mng = mField.getInterface<PipelineManager>();
637 auto fe_boundary_lhs = pip_mng->getBoundaryLhsFE();
638
639 pip.push_back(new OpSpringLhs(
640 "U", "U",
641
642 [this, fe_boundary_lhs](double, double, double) {
643 return spring_stiffness * scale +
644 (vis_spring_stiffness * scale) * fe_boundary_lhs->ts_a;
645 }
646
647 ));
648 }
649
650 CHKERR
651 ContactOps::opFactoryBoundaryLhs<SPACE_DIM, AT, GAUSS, BoundaryEleOp>(
652 pip, "SIGMA", "U", is_axisymmetric);
654 DomainEle>(
655 mField, pip, simple->getDomainFEName(), "SIGMA", "U", "GEOMETRY",
656 integration_rule_vol, is_axisymmetric);
657
659 };
660
661 auto add_boundary_ops_rhs = [&](auto &pip) {
663
664 //! [Operators used for contact]
667 //! [Operators used for contact]
668
669 // Add Natural BCs to RHS
671 pip, mField, "U", {time_scale}, Sev::inform);
672
673 if (spring_stiffness > 0 || vis_spring_stiffness > 0) {
674 auto u_disp = boost::make_shared<MatrixDouble>();
675 auto dot_u_disp = boost::make_shared<MatrixDouble>();
676 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_disp));
677 pip.push_back(
678 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", dot_u_disp));
679 pip.push_back(
680 new OpSpringRhs("U", u_disp, [this](double, double, double) {
681 return spring_stiffness * scale;
682 }));
683 pip.push_back(
684 new OpSpringRhs("U", dot_u_disp, [this](double, double, double) {
686 }));
687 }
688
689 CHKERR
690 ContactOps::opFactoryBoundaryRhs<SPACE_DIM, AT, GAUSS, BoundaryEleOp>(
691 pip, "SIGMA", "U", is_axisymmetric);
692
694 };
695
696 CHKERR add_domain_base_ops(pip_mng->getOpDomainLhsPipeline());
697 CHKERR add_domain_base_ops(pip_mng->getOpDomainRhsPipeline());
698 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
699 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
700
701 CHKERR add_boundary_base_ops(pip_mng->getOpBoundaryLhsPipeline());
702 CHKERR add_boundary_base_ops(pip_mng->getOpBoundaryRhsPipeline());
703 CHKERR add_boundary_ops_lhs(pip_mng->getOpBoundaryLhsPipeline());
704 CHKERR add_boundary_ops_rhs(pip_mng->getOpBoundaryRhsPipeline());
705
706 if (mfrontInterfacePtr) {
707 CHKERR mfrontInterfacePtr->setUpdateInternalVariablesOperators(
708 integration_rule_vol, "U");
709 CHKERR mfrontInterfacePtr->setPostProcessOperators(
710 integration_rule_vol, simple->getDomainFEName(), "U", order);
711 }
712
713 CHKERR pip_mng->setDomainRhsIntegrationRule(integration_rule_vol);
714 CHKERR pip_mng->setDomainLhsIntegrationRule(integration_rule_vol);
715 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_boundary);
716 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_boundary);
717
719}
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
@ 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.
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
FormsIntegrators< BoundaryEleOp >::Assembly< AT >::BiLinearForm< IT >::OpMass< 1, SPACE_DIM > OpSpringLhs
[Operators used for contact]
Definition contact.cpp:73
int order
Definition contact.cpp:80
int geom_order
Definition contact.cpp:83
FormsIntegrators< BoundaryEleOp >::Assembly< AT >::LinearForm< IT >::OpBaseTimesVector< 1, SPACE_DIM, 1 > OpSpringRhs
Definition contact.cpp:75

◆ OPs() [2/2]

MoFEMErrorCode Contact::OPs ( )
private

◆ runProblem() [1/2]

MoFEMErrorCode Contact::runProblem ( )

[Run problem]

Definition at line 157 of file contact.cpp.

157 {
161 CHKERR bC();
162 CHKERR OPs();
163 CHKERR tsSolve();
166}
MoFEMErrorCode tsSolve()
Definition contact.cpp:732
MoFEMErrorCode setupProblem()
[Run problem]
Definition contact.cpp:170
MoFEMErrorCode OPs()
[Boundary condition]
Definition contact.cpp:494
MoFEMErrorCode createCommonData()
[Set up problem]
Definition contact.cpp:310
MoFEMErrorCode checkResults()
[Solve]
Definition contact.cpp:874
MoFEMErrorCode bC()
[Create common data]
Definition contact.cpp:457

◆ runProblem() [2/2]

MoFEMErrorCode Contact::runProblem ( )

◆ setupProblem() [1/2]

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 170 of file contact.cpp.

170 {
173
174 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
175 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-contact_order", &contact_order,
176 PETSC_NULLPTR);
177 sigma_order = std::max(order, contact_order) - 1;
178 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-sigma_order", &sigma_order,
179 PETSC_NULLPTR);
180 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-geom_order", &geom_order,
181 PETSC_NULLPTR);
182
183 MOFEM_LOG("CONTACT", Sev::inform) << "Order " << order;
184 MOFEM_LOG("CONTACT", Sev::inform) << "Contact order " << contact_order;
185 MOFEM_LOG("CONTACT", Sev::inform) << "Sigma order " << sigma_order;
186 MOFEM_LOG("CONTACT", Sev::inform) << "Geom order " << geom_order;
187
188 // Select base
189 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
190 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
191 PetscInt choice_base_value = AINSWORTH;
192 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL, "-base", list_bases,
193 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
194
196 switch (choice_base_value) {
197 case AINSWORTH:
199 MOFEM_LOG("CONTACT", Sev::inform)
200 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
201 break;
202 case DEMKOWICZ:
204 MOFEM_LOG("CONTACT", Sev::inform)
205 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
206 break;
207 default:
208 base = LASTBASE;
209 break;
210 }
211
212 // Note: For tets we have only H1 Ainsworth base, for Hex we have only H1
213 // Demkowicz base. We need to implement Demkowicz H1 base on tet.
214 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
215 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
216 CHKERR simple->addDomainField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
217 SPACE_DIM);
218 CHKERR simple->addBoundaryField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
219 SPACE_DIM);
220 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
221
222 CHKERR simple->setFieldOrder("U", order);
223 CHKERR simple->setFieldOrder("GEOMETRY", geom_order);
224
225 auto get_skin = [&]() {
226 Range body_ents;
227 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
228 Skinner skin(&mField.get_moab());
229 Range skin_ents;
230 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
231 return skin_ents;
232 };
233
234 auto filter_blocks = [&](auto skin) {
235 bool is_contact_block = false;
236 Range contact_range;
237 for (auto m :
238 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
239
240 (boost::format("%s(.*)") % "CONTACT").str()
241
242 ))
243
244 ) {
245 is_contact_block =
246 true; ///< blocs interation is collective, so that is set irrespective
247 ///< if there are entities in given rank or not in the block
248 MOFEM_LOG("CONTACT", Sev::inform)
249 << "Find contact block set: " << m->getName();
250 auto meshset = m->getMeshset();
251 Range contact_meshset_range;
252 CHKERR mField.get_moab().get_entities_by_dimension(
253 meshset, SPACE_DIM - 1, contact_meshset_range, true);
254
255 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
256 contact_meshset_range);
257 contact_range.merge(contact_meshset_range);
258 }
259 if (is_contact_block) {
260 MOFEM_LOG("SYNC", Sev::inform)
261 << "Nb entities in contact surface: " << contact_range.size();
263 skin = intersect(skin, contact_range);
264 }
265 return skin;
266 };
267
268 auto filter_true_skin = [&](auto skin) {
269 Range boundary_ents;
270 ParallelComm *pcomm =
271 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
272 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
273 PSTATUS_NOT, -1, &boundary_ents);
274 return boundary_ents;
275 };
276
277 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
278 CHKERR simple->setFieldOrder("SIGMA", 0);
279 CHKERR simple->setFieldOrder("SIGMA", sigma_order, &boundary_ents);
280
281 if (contact_order > order) {
282 Range ho_ents;
283
284 CHKERR mField.get_moab().get_adjacencies(boundary_ents, 1, false, ho_ents,
285 moab::Interface::UNION);
286
287 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(ho_ents);
288 CHKERR simple->setFieldOrder("U", contact_order, &ho_ents);
289 CHKERR mField.getInterface<CommInterface>()->synchroniseFieldEntities("U");
290 }
291
292 CHKERR simple->setUp();
293
294 auto project_ho_geometry = [&]() {
295 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
296 return mField.loop_dofs("GEOMETRY", ent_method);
297 };
298
299 PetscBool project_geometry = PETSC_TRUE;
300 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-project_geometry",
301 &project_geometry, PETSC_NULLPTR);
302 if (project_geometry) {
303 CHKERR project_ho_geometry();
304 }
305
307} //! [Set up problem]
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
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 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
virtual MPI_Comm & get_comm() const =0
Interface for managing meshsets containing materials and boundary conditions.
Projection of edge entities with one mid-node on hierarchical basis.
int sigma_order
Definition contact.cpp:82
int contact_order
Definition contact.cpp:81
constexpr FieldSpace CONTACT_SPACE
[Specialisation for assembly]
Definition contact.cpp:69

◆ setupProblem() [2/2]

MoFEMErrorCode Contact::setupProblem ( )
private

◆ tsSolve() [1/2]

MoFEMErrorCode Contact::tsSolve ( )
private

Definition at line 732 of file contact.cpp.

732 {
734
737 ISManager *is_manager = mField.getInterface<ISManager>();
738
739 auto set_section_monitor = [&](auto solver) {
741 SNES snes;
742 CHKERR TSGetSNES(solver, &snes);
743 PetscViewerAndFormat *vf;
744 CHKERR PetscViewerAndFormatCreate(PETSC_VIEWER_STDOUT_WORLD,
745 PETSC_VIEWER_DEFAULT, &vf);
746 CHKERR SNESMonitorSet(
747 snes,
748 (MoFEMErrorCode (*)(SNES, PetscInt, PetscReal,
749 void *))SNESMonitorFields,
750 vf, (MoFEMErrorCode (*)(void **))PetscViewerAndFormatDestroy);
752 };
753
754 auto scatter_create = [&](auto D, auto coeff) {
756 CHKERR is_manager->isCreateProblemFieldAndRank(simple->getProblemName(),
757 ROW, "U", coeff, coeff, is);
758 int loc_size;
759 CHKERR ISGetLocalSize(is, &loc_size);
760 Vec v;
761 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &v);
762 VecScatter scatter;
763 CHKERR VecScatterCreate(D, is, v, PETSC_NULLPTR, &scatter);
764 return std::make_tuple(SmartPetscObj<Vec>(v),
766 };
767
768 auto set_time_monitor = [&](auto dm, auto solver) {
770 monitorPtr->setScatterVectors(uXScatter, uYScatter, uZScatter);
771 boost::shared_ptr<ForcesAndSourcesCore> null;
772 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(),
773 monitorPtr, null, null);
775 };
776
777 auto set_essential_bc = [&]() {
779 // This is low level pushing finite elements (pipelines) to solver
780 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
781 auto pre_proc_ptr = boost::make_shared<FEMethod>();
782 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
783 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
784
785 // Add boundary condition scaling
786 auto time_scale = boost::make_shared<TimeScale>();
787
788 auto get_bc_hook_rhs = [&]() {
790 {time_scale}, false);
791 return hook;
792 };
793 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
794
795 auto get_post_proc_hook_rhs = [&]() {
797 mField, post_proc_rhs_ptr, 1.);
798 };
799 auto get_post_proc_hook_lhs = [&]() {
801 mField, post_proc_lhs_ptr, 1.);
802 };
803 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs();
804
805 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
806 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
807 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
808 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
809 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
811 };
812
813 // Set up Schur preconditioner
814 auto set_schur_pc = [&](auto solver) {
815 boost::shared_ptr<SetUpSchur> schur_ptr;
816 if (AT == AssemblyType::BLOCK_SCHUR) {
817 // Set up Schur preconditioner
819 CHK_MOAB_THROW(schur_ptr->setUp(solver), "SetUpSchur::setUp");
820 }
821 return schur_ptr;
822 };
823
824 auto dm = simple->getDM();
825 auto D = createDMVector(dm);
826
828
829 uXScatter = scatter_create(D, 0);
830 uYScatter = scatter_create(D, 1);
831 if (SPACE_DIM == 3)
832 uZScatter = scatter_create(D, 2);
833
834 // Add extra finite elements to SNES solver pipelines to resolve essential
835 // boundary conditions
836 CHKERR set_essential_bc();
837
838 if (is_quasi_static == PETSC_TRUE) {
839 auto solver = pip_mng->createTSIM();
840 CHKERR TSSetFromOptions(solver);
841
842 auto B = createDMMatrix(dm);
843 CHKERR TSSetIJacobian(solver, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
844 auto schur_pc_ptr = set_schur_pc(solver);
845
846 auto D = createDMVector(dm);
847 CHKERR set_section_monitor(solver);
848 CHKERR set_time_monitor(dm, solver);
849 CHKERR TSSetSolution(solver, D);
850 CHKERR TSSetUp(solver);
851 CHKERR TSSolve(solver, NULL);
852 } else {
853 auto solver = pip_mng->createTSIM2();
854 CHKERR TSSetFromOptions(solver);
855
856 auto B = createDMMatrix(dm);
857 CHKERR TSSetI2Jacobian(solver, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
858 auto schur_pc_ptr = set_schur_pc(solver);
859
860 auto D = createDMVector(dm);
861 auto DD = vectorDuplicate(D);
862 CHKERR set_section_monitor(solver);
863 CHKERR set_time_monitor(dm, solver);
864 CHKERR TS2SetSolution(solver, D, DD);
865 CHKERR TSSetUp(solver);
866 CHKERR TSSolve(solver, NULL);
867 }
868
870}
@ ROW
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1194
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:1046
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1279
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
static auto createTotalTraction(MoFEM::Interface &m_field)
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
Definition contact.cpp:139
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
Definition contact.cpp:137
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
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)

◆ tsSolve() [2/2]

MoFEMErrorCode Contact::tsSolve ( )
private

Member Data Documentation

◆ mField

MoFEM::Interface & Contact::mField
private

Definition at line 128 of file contact.cpp.

◆ mfrontInterface

boost::shared_ptr<GenericElementInterface> Contact::mfrontInterface
private

Definition at line 146 of file contact.cpp.

◆ mfrontInterfacePtr

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

Definition at line 141 of file contact.cpp.

◆ monitorPtr

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

Definition at line 142 of file contact.cpp.

◆ uXScatter

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

Definition at line 137 of file contact.cpp.

◆ uYScatter

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

Definition at line 138 of file contact.cpp.

◆ uZScatter

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

Definition at line 139 of file contact.cpp.


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