149 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
150 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
151 PetscInt choice_base_value = AINSWORTH;
152 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL,
"-base", list_bases,
153 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
155 switch (choice_base_value) {
159 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
164 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
176 CHKERR PetscOptionsGetInt(PETSC_NULLPTR,
"",
"-order", &
order, PETSC_NULLPTR);
181 auto project_ho_geometry = [&]() {
182 Projection10NodeCoordsOnField ent_method(
mField,
"GEOMETRY");
185 CHKERR project_ho_geometry();
187 CHKERR PetscOptionsGetBool(PETSC_NULLPTR,
"",
"-use_adolc_material",
192 "ADOL-C support is not enabled. Please reconfigure with "
193 "-DWITH_ADOL_C=ON and recompile to use AdolC material model.");
197 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Use ADOL-C material model";
199 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Use Hencky material model";
202 auto tag_meshest = [&]() {
205 auto set_block = [&](
auto name,
int dim) {
206 std::map<int, Range> map;
207 auto set_tag_impl = [&](
auto name) {
210 auto bcs = mesh_mng->getCubitMeshsetPtr(
212 std::regex((boost::format(
"%s(.*)") % name).str())
215 std::map<int, int> ids_map;
217 for (
auto bc : bcs) {
218 int id = bc->getMeshsetId();
219 ids_map[id] = bit_id;
222 for (
auto bc : bcs) {
226 map[ids_map[bc->getMeshsetId()]] = r;
228 <<
"Block " << name <<
" id " << bc->getMeshsetId() <<
" : "
229 << ids_map[bc->getMeshsetId()] <<
" has " << r.size()
235 CHKERR set_tag_impl(name);
237 return std::make_pair(name, map);
240 auto set_skin = [&](
auto &&map) {
241 for (
auto &
m : map.second) {
245 <<
"Skin for block " << map.first <<
" id " <<
m.first <<
" has "
246 <<
m.second.size() <<
" entities";
251 auto set_tag = [&](
auto &&map) {
253 auto name = map.first;
254 int def_val[] = {-1};
256 name, 1, MB_TYPE_INTEGER, th,
257 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
259 for (
auto &
m : map.second) {
261 for (
auto ent :
m.second) {
266 if (current_id != -1) {
339 auto add_domain_ops_lhs = [&](
auto &pip) {
344 HenckyOps::opFactoryDomainLhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
345 mField, pip,
"U",
"MAT_ELASTIC", Sev::inform);
349 auto add_domain_ops_rhs = [&](
auto &pip) {
354 HenckyOps::opFactoryDomainRhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
355 mField, pip,
"U",
"MAT_ELASTIC", Sev::inform);
359 CHKERR add_domain_ops_lhs(pipeline_mng->getOpDomainLhsPipeline());
360 CHKERR add_domain_ops_rhs(pipeline_mng->getOpDomainRhsPipeline());
363 CHKERR add_domain_ops_rhs(pipeline_mng->getOpEvaluationPipeline());
364 auto &domain_reaction_fe = pipeline_mng->getEvaluationFE();
365 domain_reaction_fe->postProcessHook =
366 EssentialPreProcReaction<DisplacementCubitBcData>(
mField,
369 PetscBool post_proc_vol;
370 PetscBool post_proc_skin;
373 post_proc_vol = PETSC_TRUE;
374 post_proc_skin = PETSC_FALSE;
376 post_proc_vol = PETSC_FALSE;
377 post_proc_skin = PETSC_TRUE;
380 CHKERR PetscOptionsGetBool(PETSC_NULLPTR,
"",
"-post_proc_vol",
381 &post_proc_vol, PETSC_NULLPTR);
382 CHKERR PetscOptionsGetBool(PETSC_NULLPTR,
"",
"-post_proc_skin",
383 &post_proc_skin, PETSC_NULLPTR);
386 auto create_post_proc_fe = [&]() {
387 auto post_proc_ele_domain = [
this](
auto &pip_domain) {
390 auto common_ptr = commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
391 mField, pip_domain,
"U",
"MAT_ELASTIC", Sev::inform);
395 auto post_proc_map = [&](
auto &pip,
auto u_ptr,
auto common_ptr) {
398 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
400 pip->getOpPtrVector().push_back(
402 new OpPPMap(pip->getPostProcMesh(), pip->getMapGaussPts(), {},
404 {{
"GRAD", common_ptr->matGradPtr},
405 {
"FIRST_PIOLA", common_ptr->getMatFirstPiolaStress()}},
410 auto push_post_proc_bdy = [&](
auto &pip_bdy) {
411 if (post_proc_skin == PETSC_FALSE)
412 return boost::shared_ptr<PostProcEleBdy>();
414 auto domain_fe_name =
simple->getDomainFEName();
415 auto u_ptr = boost::make_shared<MatrixDouble>();
416 pip_bdy->getOpPtrVector().push_back(
417 new OpCalculateVectorFieldValues<SPACE_DIM>(
"U", u_ptr));
420 auto common_ptr = post_proc_ele_domain(op_loop_side->getOpPtrVector());
421 pip_bdy->getOpPtrVector().push_back(op_loop_side);
422 CHKERR post_proc_map(pip_bdy, u_ptr, common_ptr);
426 auto push_post_proc_domain = [&](
auto &pip_domain) {
427 if (post_proc_vol == PETSC_FALSE)
428 return boost::shared_ptr<PostProcEleDomain>();
430 auto u_ptr = boost::make_shared<MatrixDouble>();
431 pip_domain->getOpPtrVector().push_back(
432 new OpCalculateVectorFieldValues<SPACE_DIM>(
"U", u_ptr));
433 auto common_ptr = post_proc_ele_domain(pip_domain->getOpPtrVector());
435 CHKERR post_proc_map(pip_domain, u_ptr, common_ptr);
440 auto post_proc_fe_domain = boost::make_shared<PostProcEleDomain>(
mField);
441 auto post_proc_fe_bdy = boost::make_shared<PostProcEleBdy>(
mField);
443 return std::make_pair(push_post_proc_domain(post_proc_fe_domain),
444 push_post_proc_bdy(post_proc_fe_bdy));
447 auto post_proc_pair = create_post_proc_fe();
448 postProcDomainFe = post_proc_pair.first;
449 postProcBdyFe = post_proc_pair.second;
535#ifdef WITH_ADOL_C_UMAT
537 constexpr int umat_model_type =
539 auto umat_physical_equations_ptr =
544 CHKERR umat_physical_equations_ptr->getOptions(&
mField);
545 CHKERR umat_physical_equations_ptr->recordTape();
558 #ifdef WITH_ADOL_C_GENERIC_ELASTIC
560 auto generic_physical_equations_ptr =
568 generic_physical_equations_ptr->hookEvaluateVariable =
570 generic_physical_equations_ptr->hookEvaluateDerivatives =
572 generic_physical_equations_ptr->hookUpdateState =
575 CHKERR generic_physical_equations_ptr->getOptions(&
mField);
576 CHKERR generic_physical_equations_ptr->recordTape();
579 material_map[generic_physical_equations_ptr->tAg] =
580 generic_physical_equations_ptr;
585 #ifdef WITH_ADOL_C_SIMPLE_DAMAGE
587 auto generic_physical_equations_ptr =
591 "GenericElasticSimpleDamage"));
594 mField, boost::dynamic_pointer_cast<MatOps::GenericElastic>(
595 generic_physical_equations_ptr));
597 CHKERR generic_physical_equations_ptr->getOptions(&
mField);
598 CHKERR generic_physical_equations_ptr->recordTape();
601 material_map[generic_physical_equations_ptr->tAg] =
602 generic_physical_equations_ptr;
615 MatOps::createMatOpsPhysicalEquationsPtr<MatOps::HUHU, modelType>(
622 auto add_domain_ops_lhs = [&](
auto &pip) {
628 template opLhsFactory<PETSC, GAUSS, DomainEleOp>(
633 template opLhsFactory<PETSC, GAUSS, DomainEleOp>(
639 auto add_domain_ops_rhs = [&](
auto &pip) {
645 template opRhsFactory<PETSC, GAUSS, DomainEleOp>(
650 template opRhsFactory<PETSC, GAUSS, DomainEleOp>(
656 auto add_domain_ops_update = [&](
auto &pip) {
667 CHKERR add_domain_ops_lhs(pipeline_mng->getOpDomainLhsPipeline());
668 CHKERR add_domain_ops_rhs(pipeline_mng->getOpDomainRhsPipeline());
674 CHKERR add_domain_ops_rhs(pipeline_mng->getOpEvaluationPipeline());
675 auto &domain_reaction_fe = pipeline_mng->getEvaluationFE();
676 domain_reaction_fe->postProcessHook =
677 EssentialPreProcReaction<DisplacementCubitBcData>(
mField,
680 PetscBool post_proc_vol;
681 PetscBool post_proc_skin;
684 post_proc_vol = PETSC_TRUE;
685 post_proc_skin = PETSC_FALSE;
687 post_proc_vol = PETSC_FALSE;
688 post_proc_skin = PETSC_TRUE;
691 CHKERR PetscOptionsGetBool(PETSC_NULLPTR,
"",
"-post_proc_vol",
692 &post_proc_vol, PETSC_NULLPTR);
693 CHKERR PetscOptionsGetBool(PETSC_NULLPTR,
"",
"-post_proc_skin",
694 &post_proc_skin, PETSC_NULLPTR);
697 auto create_post_proc_fe = [&]() {
698 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
700 auto post_proc_ele_domain = [&](
auto &pip_domain) {
711 auto post_proc_map = [&](
auto &pip,
auto u_ptr) {
716 auto first_piola_ptr =
718 pip->getOpPtrVector().push_back(
new OpPPMap(
719 pip->getPostProcMesh(), pip->getMapGaussPts(), {}, {{
"U", u_ptr}},
720 {{
"GRAD", grad_ptr}, {
"FIRST_PIOLA", first_piola_ptr}}, {}));
725 auto push_post_proc_bdy = [&](
auto &pip_bdy) {
726 if (post_proc_skin == PETSC_FALSE)
727 return boost::shared_ptr<PostProcEleBdy>();
729 auto domain_fe_name =
simple->getDomainFEName();
730 auto u_ptr = boost::make_shared<MatrixDouble>();
731 pip_bdy->getOpPtrVector().push_back(
732 new OpCalculateVectorFieldValues<SPACE_DIM>(
"U", u_ptr));
735 CHKERR post_proc_ele_domain(op_loop_side->getOpPtrVector());
736 pip_bdy->getOpPtrVector().push_back(op_loop_side);
737 CHKERR post_proc_map(pip_bdy, u_ptr);
741 auto push_post_proc_domain = [&](
auto &pip_domain) {
742 if (post_proc_vol == PETSC_FALSE)
743 return boost::shared_ptr<PostProcEleDomain>();
744 auto u_ptr = boost::make_shared<MatrixDouble>();
745 pip_domain->getOpPtrVector().push_back(
746 new OpCalculateVectorFieldValues<SPACE_DIM>(
"U", u_ptr));
747 CHKERR post_proc_ele_domain(pip_domain->getOpPtrVector());
751 if (!state_tags.empty()) {
754 selected_state_tags.reserve(state_tags.size());
755 statev_tags.reserve(state_tags.size());
757 constexpr auto statev_prefix =
"UMAT_STATEV_";
758 constexpr auto statev_prefix_len =
sizeof(
"UMAT_STATEV_") - 1;
759 auto get_statev_index = [&](
const std::string &name) {
760 return std::stoi(name.substr(statev_prefix_len));
763 for (
const auto &state_tag : state_tags) {
764 const auto &name = state_tag.name;
766 if (name ==
"UMAT_DFGRD0" || name ==
"UMAT_STRESS") {
767 selected_state_tags.push_back(state_tag);
771 if (name.rfind(statev_prefix, 0) == 0) {
772 statev_tags.push_back(state_tag);
776 std::sort(statev_tags.begin(), statev_tags.end(),
777 [&](
const auto &lhs,
const auto &rhs) {
778 return get_statev_index(lhs.name) <
779 get_statev_index(rhs.name);
781 if (statev_tags.size() > 10)
782 statev_tags.resize(10);
783 selected_state_tags.insert(selected_state_tags.end(),
784 statev_tags.begin(), statev_tags.end());
786 if (selected_state_tags.empty())
791 CHKERR PetscOptionsGetInt(PETSC_NULLPTR,
"",
"-order", &state_order,
793 auto op_loop_this =
new OpLoopThis<DomainEle>(
796 pip_domain->getOpPtrVector().push_back(op_loop_this);
797 CHKERR addTagDGProjectionOps<SPACE_DIM, SPACE_DIM>(
799 op_loop_this->getThisFEPtr()->getOpPtrVector(),
800 pip_domain->getPostProcMesh(), pip_domain->getMapGaussPts(),
805 CHKERR post_proc_map(pip_domain, u_ptr);
810 auto post_proc_fe_domain = boost::make_shared<PostProcEleDomain>(
mField);
811 auto post_proc_fe_bdy = boost::make_shared<PostProcEleBdy>(
mField);
813 return std::make_pair(push_post_proc_domain(post_proc_fe_domain),
814 push_post_proc_bdy(post_proc_fe_bdy));
817 auto post_proc_pair = create_post_proc_fe();
818 postProcDomainFe = post_proc_pair.first;
819 postProcBdyFe = post_proc_pair.second;
823 "ADOL-C support is not enabled. Please reconfigure with "
824 "-DWITH_ADOL_C=ON and recompile to use AdolC material model.");
836 auto dm =
simple->getDM();
837 auto ts = pipeline_mng->createTSIM();
839 auto add_extra_finite_elements_to_solver_pipelines = [&]() {
842 auto pre_proc_ptr = boost::make_shared<FEMethod>();
843 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
844 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
846 auto time_scale = boost::make_shared<ExampleTimeScale>();
848 auto get_bc_hook_rhs = [
this, pre_proc_ptr, time_scale]() {
850 CHKERR EssentialPreProc<DisplacementCubitBcData>(
mField, pre_proc_ptr,
851 {time_scale},
false)();
855 pre_proc_ptr->preProcessHook = get_bc_hook_rhs;
857 auto get_post_proc_hook_rhs = [
this, post_proc_rhs_ptr]() {
859 CHKERR EssentialPreProcReaction<DisplacementCubitBcData>(
860 mField, post_proc_rhs_ptr,
nullptr, Sev::verbose)();
861 CHKERR EssentialPostProcRhs<DisplacementCubitBcData>(
862 mField, post_proc_rhs_ptr, 1.)();
865 auto get_post_proc_hook_lhs = [
this, post_proc_lhs_ptr]() {
867 CHKERR EssentialPostProcLhs<DisplacementCubitBcData>(
868 mField, post_proc_lhs_ptr, 1.)();
871 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
872 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs;
875 auto ts_ctx_ptr = getDMTsCtx(
simple->getDM());
876 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
877 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
878 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
879 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
885 CHKERR add_extra_finite_elements_to_solver_pipelines();
887 auto create_monitor_fe = [dm](
auto &&post_proc_fe) {
888 return boost::make_shared<Monitor>(dm.get(), post_proc_fe);
892 boost::shared_ptr<FEMethod> null_fe;
901 CHKERR DMMoFEMTSSetMonitor(dm, ts,
simple->getDomainFEName(), null_fe,
902 null_fe, monitor_ptr);
906 CHKERR TSSetMaxTime(ts, ftime);
907 CHKERR TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP);
909 auto B = createDMMatrix(dm);
910 CHKERR TSSetI2Jacobian(ts,
B,
B, PETSC_NULLPTR, PETSC_NULLPTR);
911 auto D = createDMVector(
simple->getDM());
913 CHKERR TSSetFromOptions(ts);
921 CHKERR TSGetTime(ts, &ftime);
923 PetscInt steps, snesfails, rejects, nonlinits, linits;
924 CHKERR TSGetStepNumber(ts, &steps);
925 CHKERR TSGetSNESFailures(ts, &snesfails);
926 CHKERR TSGetStepRejections(ts, &rejects);
927 CHKERR TSGetSNESIterations(ts, &nonlinits);
928 CHKERR TSGetKSPIterations(ts, &linits);
930 "steps %d (%d rejected, %d SNES fails), ftime %g, nonlinits "
932 steps, rejects, snesfails, ftime, nonlinits, linits);
943 auto dm =
simple->getDM();
945 auto T = createDMVector(
simple->getDM());
946 CHKERR DMoFEMMeshToLocalVector(
simple->getDM(), T, INSERT_VALUES,
949 CHKERR VecNorm(T, NORM_2, &nrm2);
950 MOFEM_LOG(
"EXAMPLE", Sev::inform) <<
"Solution norm " << nrm2;
952 auto post_proc_norm_fe = boost::make_shared<DomainEle>(
mField);
954 auto post_proc_norm_rule_hook = [](int, int,
int p) ->
int {
return 2 * p; };
955 post_proc_norm_fe->getRuleHook = post_proc_norm_rule_hook;
958 post_proc_norm_fe->getOpPtrVector(), {H1},
"GEOMETRY");
960 enum NORMS { U_NORM_L2 = 0, PIOLA_NORM, LAST_NORM };
964 CHKERR VecZeroEntries(norms_vec);
966 auto u_ptr = boost::make_shared<MatrixDouble>();
967 post_proc_norm_fe->getOpPtrVector().push_back(
968 new OpCalculateVectorFieldValues<SPACE_DIM>(
"U", u_ptr));
970 post_proc_norm_fe->getOpPtrVector().push_back(
971 new OpCalcNormL2Tensor1<SPACE_DIM>(u_ptr, norms_vec, U_NORM_L2));
980 post_proc_norm_fe->getOpPtrVector().push_back(
981 new OpCalcNormL2Tensor2<SPACE_DIM, SPACE_DIM>(m_P, norms_vec,
986 "ADOL-C support is not enabled. Please reconfigure with "
987 "-DWITH_ADOL_C=ON and recompile to use AdolC material model.");
990 auto common_ptr = commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
991 mField, post_proc_norm_fe->getOpPtrVector(),
"U",
"MAT_ELASTIC",
993 post_proc_norm_fe->getOpPtrVector().push_back(
994 new OpCalcNormL2Tensor2<SPACE_DIM, SPACE_DIM>(
995 common_ptr->getMatFirstPiolaStress(), norms_vec, PIOLA_NORM));
998 CHKERR DMoFEMLoopFiniteElements(dm,
simple->getDomainFEName(),
1001 CHKERR VecAssemblyBegin(norms_vec);
1002 CHKERR VecAssemblyEnd(norms_vec);
1006 const double *norms;
1007 CHKERR VecGetArrayRead(norms_vec, &norms);
1009 <<
"norm_u: " << std::scientific << std::sqrt(norms[U_NORM_L2]);
1011 <<
"norm_piola: " << std::scientific << std::sqrt(norms[PIOLA_NORM]);
1012 CHKERR VecRestoreArrayRead(norms_vec, &norms);
1035 constexpr double applied_F_zz = 0.99;
1037 t_P_expected(
i,
J) = 0.;
1038 auto set_linear_elastic_piola = [&](
const double strain_zz,
1039 const double d_strain_d_F_zz) {
1040 constexpr double E = 1.;
1041 constexpr double nu = 0.3;
1042 const double lambda =
E * nu / ((1. + nu) * (1. - 2. * nu));
1043 const double mu =
E / (2. * (1. + nu));
1044 for (
int d = 0; d !=
SPACE_DIM - 1; ++d)
1045 t_P_expected(d, d) =
lambda * strain_zz;
1047 (
lambda + 2. *
mu) * strain_zz * d_strain_d_F_zz;
1050 auto set_neohookean_piola = [&](
const double F_zz,
const double J) {
1051 constexpr double c10 = 1.;
1052 constexpr double K = 1.;
1053 double I1 = (
SPACE_DIM - 1) + F_zz * F_zz;
1056 const double J_to_minus_two_thirds = std::pow(
J, -2. / 3.);
1058 const double F_dd = d ==
SPACE_DIM - 1 ? F_zz : 1.;
1059 const double inv_F_dd = 1. / F_dd;
1060 t_P_expected(d, d) =
1061 2. * c10 * J_to_minus_two_thirds *
1062 (F_dd - (I1 / 3.) * inv_F_dd) +
1063 K *
J * (
J - 1.) * inv_F_dd;
1067 auto eval_piola_at_point = [&](boost::shared_ptr<MatrixDouble> &mat_p) {
1069 std::array<double, 3> field_eval_coords = {0.123, -0.087, 0.193};
1071 auto field_eval_data = field_eval_ptr->getData<
DomainEle>();
1073 simple->getDomainFEName());
1074 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1076 auto fe = field_eval_data->feMethodPtr;
1077 fe->getRuleHook = [](int, int, int) {
return -1; };
1079 auto &pipeline = fe->getOpPtrVector();
1084 auto common_ptr = commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
1085 mField, pipeline,
"U",
"MAT_ELASTIC", Sev::inform);
1086 mat_p = common_ptr->getMatFirstPiolaStress();
1094 "ADOL-C support is not enabled. Please reconfigure with "
1095 "-DWITH_ADOL_C=ON and recompile to use MatOps material model.");
1099 field_eval_coords.data(), 1e-12,
simple->getProblemName(),
1108 const double hencky_strain_zz = std::log(applied_F_zz);
1109 set_linear_elastic_piola(hencky_strain_zz, 1. / applied_F_zz);
1114 const double J = applied_F_zz;
1115 set_neohookean_piola(applied_F_zz,
J);
1120 const double small_strain_zz = applied_F_zz - 1.;
1121 set_linear_elastic_piola(small_strain_zz, 1.);
1126 "Wrong Piola stress test number.");
1130 boost::shared_ptr<MatrixDouble> mat_p;
1131 CHKERR eval_piola_at_point(mat_p);
1133 auto t_P = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*mat_p);
1134 t_P_diff(
i,
J) = t_P(
i,
J) - t_P_expected(
i,
J);
1135 const double p_err = std::sqrt(t_P_diff(
i,
J) * t_P_diff(
i,
J));
1139 <<
"Piola stress test " << test_nb <<
" P(" << r <<
", " <<
c
1140 <<
") actual " << std::scientific << t_P(r,
c) <<
" expected "
1141 << t_P_expected(r,
c) <<
" diff " << t_P_diff(r,
c);
1143 <<
"Piola stress test " << test_nb <<
" error " << std::scientific
1147 "Wrong Piola stress. Error %6.4e", p_err);