12 #ifndef EXECUTABLE_DIMENSION
13 #define EXECUTABLE_DIMENSION 3
22 using namespace MoFEM;
66 std::max(
static_cast<double>(std::numeric_limits<float>::min_exponent10),
80 auto r = [&](
auto tau) {
83 constexpr
double eps = 1e-12;
84 return std::max(
r(tau),
eps *
r(0));
90 template <
typename T,
int DIM>
97 if (
C1_k < std::numeric_limits<double>::epsilon()) {
101 t_alpha(
i,
j) =
C1_k * t_plastic_strain(
i,
j);
153 #include <boost/python.hpp>
154 #include <boost/python/def.hpp>
155 #include <boost/python/numpy.hpp>
156 namespace bp = boost::python;
157 namespace np = boost::python::numpy;
167 #endif // ADD_CONTACT
184 template <
int FE_DIM,
int PROBLEM_DIM,
int SPACE_DIM>
struct AddHOOps;
189 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
190 std::vector<FieldSpace> space, std::string geom_field_name);
196 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
197 std::vector<FieldSpace> space, std::string geom_field_name);
203 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
204 std::vector<FieldSpace> space, std::string geom_field_name);
210 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
211 std::vector<FieldSpace> space, std::string geom_field_name);
223 static inline std::array<double, 2> meshVolumeAndCount = {0, 0};
250 boost::shared_ptr<ContactOps::SDFPython> sdfPythonPtr;
252 #endif // ADD_CONTACT
258 CHKERR createCommonData();
262 PetscBool test_ops = PETSC_FALSE;
265 if (test_ops == PETSC_FALSE) {
280 CHKERR mField.get_moab().get_entities_by_dimension(0,
SPACE_DIM, domain_ents,
282 auto get_ents_by_dim = [&](
const auto dim) {
288 CHKERR mField.get_moab().get_connectivity(domain_ents, ents,
true);
290 CHKERR mField.get_moab().get_entities_by_dimension(0, dim, ents,
true);
295 auto get_base = [&]() {
296 auto domain_ents = get_ents_by_dim(
SPACE_DIM);
297 if (domain_ents.empty())
315 const auto base = get_base();
326 PetscBool order_edge = PETSC_FALSE;
329 PetscBool order_face = PETSC_FALSE;
332 PetscBool order_volume = PETSC_FALSE;
336 if (order_edge || order_face || order_volume) {
338 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Order edge " << order_edge
341 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Order face " << order_face
344 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Order volume " << order_volume
348 auto ents = get_ents_by_dim(0);
350 ents.merge(get_ents_by_dim(1));
352 ents.merge(get_ents_by_dim(2));
354 ents.merge(get_ents_by_dim(3));
372 CHKERR mField.get_moab().get_entities_by_dimension(0,
SPACE_DIM, body_ents);
373 Skinner skin(&mField.get_moab());
375 CHKERR skin.find_skin(0, body_ents,
false, skin_ents);
379 auto filter_blocks = [&](
auto skin) {
380 bool is_contact_block =
true;
385 (boost::format(
"%s(.*)") %
"CONTACT").str()
394 <<
"Find contact block set: " <<
m->getName();
395 auto meshset =
m->getMeshset();
396 Range contact_meshset_range;
397 CHKERR mField.get_moab().get_entities_by_dimension(
398 meshset,
SPACE_DIM - 1, contact_meshset_range,
true);
401 contact_meshset_range);
402 contact_range.merge(contact_meshset_range);
404 if (is_contact_block) {
406 <<
"Nb entities in contact surface: " << contact_range.size();
408 skin = intersect(skin, contact_range);
415 ParallelComm *pcomm =
417 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
418 PSTATUS_NOT, -1, &boundary_ents);
419 return boundary_ents;
430 auto project_ho_geometry = [&]() {
432 return mField.loop_dofs(
"GEOMETRY", ent_method);
434 PetscBool project_geometry = PETSC_TRUE;
436 &project_geometry, PETSC_NULL);
437 if (project_geometry) {
438 CHKERR project_ho_geometry();
441 auto get_volume = [&]() {
444 std::array<double, 2> volume_and_count;
445 op_ptr->doWorkRhsHook = [&](
DataOperator *base_op_ptr,
int side,
449 auto op_ptr =
static_cast<VolOp *
>(base_op_ptr);
450 volume_and_count[VOL] += op_ptr->
getMeasure();
451 volume_and_count[COUNT] += 1;
455 volume_and_count = {0, 0};
456 auto fe = boost::make_shared<DomainEle>(mField);
457 fe->getOpPtrVector().push_back(op_ptr);
459 auto dm =
simple->getDM();
463 std::array<double, 2> tot_volume_and_count;
464 MPI_Allreduce(volume_and_count.data(), tot_volume_and_count.data(),
465 volume_and_count.size(), MPI_DOUBLE, MPI_SUM,
467 return tot_volume_and_count;
470 meshVolumeAndCount = get_volume();
472 <<
"Mesh volume " << meshVolumeAndCount[VOL] <<
" nb. of elements "
473 << meshVolumeAndCount[COUNT];
483 auto get_command_line_parameters = [&]() {
510 PetscBool tau_order_is_set;
513 PetscBool ep_order_is_set;
526 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Hardening " <<
H;
527 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Viscous hardening " <<
visH;
528 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Saturation yield stress " <<
Qinf;
529 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Saturation exponent " <<
b_iso;
530 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Kinematic hardening " <<
C1_k;
535 if (tau_order_is_set == PETSC_FALSE)
537 if (ep_order_is_set == PETSC_FALSE)
540 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Approximation order " <<
order;
542 <<
"Ep approximation order " <<
ep_order;
544 <<
"Tau approximation order " <<
tau_order;
546 <<
"Geometry approximation order " <<
geom_order;
548 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Density " <<
rho;
551 PetscBool is_scale = PETSC_TRUE;
565 #endif // ADD_CONTACT
575 CHKERR get_command_line_parameters();
579 sdfPythonPtr = boost::make_shared<ContactOps::SDFPython>();
580 CHKERR sdfPythonPtr->sdfInit(
"sdf.py");
581 ContactOps::sdfPythonWeakPtr = sdfPythonPtr;
583 #endif // ADD_CONTACT
596 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_X",
598 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Y",
600 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Z",
602 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
603 "REMOVE_ALL",
"U", 0, 3);
606 for (
auto b : {
"FIX_X",
"REMOVE_X"})
607 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(), b,
608 "SIGMA", 0, 0,
false,
true);
609 for (
auto b : {
"FIX_Y",
"REMOVE_Y"})
610 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(), b,
611 "SIGMA", 1, 1,
false,
true);
612 for (
auto b : {
"FIX_Z",
"REMOVE_Z"})
613 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(), b,
614 "SIGMA", 2, 2,
false,
true);
615 for (
auto b : {
"FIX_ALL",
"REMOVE_ALL"})
616 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(), b,
617 "SIGMA", 0, 3,
false,
true);
618 CHKERR bc_mng->removeBlockDOFsOnEntities(
619 simple->getProblemName(),
"NO_CONTACT",
"SIGMA", 0, 3,
false,
true);
623 simple->getProblemName(),
"U");
625 auto &bc_map = bc_mng->getBcMapByBlockName();
626 for (
auto bc : bc_map)
627 MOFEM_LOG(
"PLASTICITY", Sev::verbose) <<
"Marker " << bc.first;
638 auto integration_rule_bc = [](
int,
int,
int ao) {
return 2 * ao; };
642 auto add_boundary_ops_lhs_mechanical = [&](
auto &pip) {
646 pip, {
HDIV},
"GEOMETRY");
651 pip, mField,
"U", Sev::inform);
656 ContactOps::opFactoryBoundaryLhs<SPACE_DIM, AT, GAUSS, BoundaryEleOp>(
659 ContactOps::opFactoryBoundaryToDomainLhs<SPACE_DIM, AT, IT, DomainEle>(
660 mField, pip,
simple->getDomainFEName(),
"SIGMA",
"U",
"GEOMETRY",
662 #endif // ADD_CONTACT
667 auto add_boundary_ops_rhs_mechanical = [&](
auto &pip) {
671 pip, {
HDIV},
"GEOMETRY");
676 pip, mField,
"U", {boost::make_shared<ScaledTimeScale>()}, Sev::inform);
679 CHKERR ContactOps::opFactoryBoundaryRhs<SPACE_DIM, AT, IT, BoundaryEleOp>(
681 #endif // ADD_CONTACT
686 auto add_domain_ops_lhs = [
this](
auto &pip) {
689 pip, {
H1,
HDIV},
"GEOMETRY");
698 auto get_inertia_and_mass_damping = [
this](
const double,
const double,
702 return (
rho /
scale) * fe_domain_lhs->ts_aa +
705 pip.push_back(
new OpMass(
"U",
"U", get_inertia_and_mass_damping));
708 CHKERR PlasticOps::opFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
709 mField,
"MAT_PLASTIC", pip,
"U",
"EP",
"TAU");
714 auto add_domain_ops_rhs = [
this](
auto &pip) {
718 pip, {
H1,
HDIV},
"GEOMETRY");
722 {boost::make_shared<ScaledTimeScale>(
"body_force_hist.txt")},
730 AT>::LinearForm<IT>::OpBaseTimesVector<1,
SPACE_DIM, 1>;
733 auto mat_acceleration = boost::make_shared<MatrixDouble>();
735 "U", mat_acceleration));
737 new OpInertiaForce(
"U", mat_acceleration, [](
double,
double,
double) {
741 auto mat_velocity = boost::make_shared<MatrixDouble>();
745 new OpInertiaForce(
"U", mat_velocity, [](
double,
double,
double) {
751 CHKERR PlasticOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
752 mField,
"MAT_PLASTIC", pip,
"U",
"EP",
"TAU");
755 CHKERR ContactOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
757 #endif // ADD_CONTACT
762 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
763 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
766 CHKERR add_boundary_ops_lhs_mechanical(pip_mng->getOpBoundaryLhsPipeline());
767 CHKERR add_boundary_ops_rhs_mechanical(pip_mng->getOpBoundaryRhsPipeline());
769 CHKERR pip_mng->setDomainRhsIntegrationRule(vol_rule);
770 CHKERR pip_mng->setDomainLhsIntegrationRule(vol_rule);
772 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_bc);
773 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_bc);
775 auto create_reaction_pipeline = [&](
auto &pip) {
778 pip, {
H1},
"GEOMETRY");
779 CHKERR PlasticOps::opFactoryDomainReactions<SPACE_DIM, AT, IT, DomainEleOp>(
780 mField,
"MAT_PLASTIC", pip,
"U",
"EP",
"TAU");
784 reactionFe = boost::make_shared<DomainEle>(mField);
785 reactionFe->getRuleHook = vol_rule;
786 CHKERR create_reaction_pipeline(reactionFe->getOpPtrVector());
787 reactionFe->postProcessHook =
806 static boost::shared_ptr<SetUpSchur> createSetUpSchur(
827 auto set_section_monitor = [&](
auto solver) {
830 CHKERR TSGetSNES(solver, &snes);
831 CHKERR SNESMonitorSet(snes,
834 (
void *)(snes_ctx_ptr.get()),
nullptr);
838 auto create_post_process_elements = [&]() {
839 auto push_vol_ops = [
this](
auto &pip) {
841 pip, {
H1,
HDIV},
"GEOMETRY");
843 auto [common_plastic_ptr, common_hencky_ptr] =
844 PlasticOps::createCommonPlasticOps<SPACE_DIM, IT, DomainEleOp>(
845 mField,
"MAT_PLASTIC", pip,
"U",
"EP",
"TAU", 1., Sev::inform);
847 if (common_hencky_ptr) {
848 if (common_plastic_ptr->mGradPtr != common_hencky_ptr->matGradPtr)
852 return std::make_pair(common_plastic_ptr, common_hencky_ptr);
855 auto push_vol_post_proc_ops = [
this](
auto &pp_fe,
auto &&p) {
858 auto &pip = pp_fe->getOpPtrVector();
860 auto [common_plastic_ptr, common_hencky_ptr] = p;
864 auto x_ptr = boost::make_shared<MatrixDouble>();
867 auto u_ptr = boost::make_shared<MatrixDouble>();
876 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
879 common_plastic_ptr->getPlasticSurfacePtr()},
880 {
"PLASTIC_MULTIPLIER",
881 common_plastic_ptr->getPlasticTauPtr()}},
883 {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}},
885 {{
"GRAD", common_hencky_ptr->matGradPtr},
886 {
"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()}},
888 {{
"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()},
889 {
"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
890 {
"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
902 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
905 common_plastic_ptr->getPlasticSurfacePtr()},
906 {
"PLASTIC_MULTIPLIER",
907 common_plastic_ptr->getPlasticTauPtr()}},
909 {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}},
913 {{
"STRAIN", common_plastic_ptr->mStrainPtr},
914 {
"STRESS", common_plastic_ptr->mStressPtr},
915 {
"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
916 {
"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
926 PetscBool post_proc_vol;
927 PetscBool post_proc_skin;
930 post_proc_vol = PETSC_TRUE;
931 post_proc_skin = PETSC_FALSE;
933 post_proc_vol = PETSC_FALSE;
934 post_proc_skin = PETSC_TRUE;
939 &post_proc_skin, PETSC_NULL);
941 auto vol_post_proc = [
this, push_vol_post_proc_ops, push_vol_ops,
943 if (post_proc_vol == PETSC_FALSE)
944 return boost::shared_ptr<PostProcEle>();
945 auto pp_fe = boost::make_shared<PostProcEle>(mField);
947 push_vol_post_proc_ops(pp_fe, push_vol_ops(pp_fe->getOpPtrVector())),
948 "push_vol_post_proc_ops");
952 auto skin_post_proc = [
this, push_vol_post_proc_ops, push_vol_ops,
954 if (post_proc_skin == PETSC_FALSE)
955 return boost::shared_ptr<SkinPostProcEle>();
958 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
961 pp_fe->getOpPtrVector().push_back(op_side);
963 pp_fe, push_vol_ops(op_side->getOpPtrVector())),
964 "push_vol_post_proc_ops");
968 return std::make_pair(vol_post_proc(), skin_post_proc());
971 auto scatter_create = [&](
auto D,
auto coeff) {
973 CHKERR is_manager->isCreateProblemFieldAndRank(
simple->getProblemName(),
974 ROW,
"U", coeff, coeff, is);
976 CHKERR ISGetLocalSize(is, &loc_size);
978 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &
v);
980 CHKERR VecScatterCreate(
D, is,
v, PETSC_NULL, &scatter);
985 boost::shared_ptr<SetPtsData> field_eval_data;
986 boost::shared_ptr<MatrixDouble> u_field_ptr;
988 std::array<double, SPACE_DIM> field_eval_coords;
991 field_eval_coords.data(), &coords_dim,
994 boost::shared_ptr<std::map<std::string, boost::shared_ptr<VectorDouble>>>
995 scalar_field_ptrs = boost::make_shared<
996 std::map<std::string, boost::shared_ptr<VectorDouble>>>();
997 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
998 vector_field_ptrs = boost::make_shared<
999 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
1000 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
1001 sym_tensor_field_ptrs = boost::make_shared<
1002 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
1003 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
1004 tensor_field_ptrs = boost::make_shared<
1005 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
1008 auto u_field_ptr = boost::make_shared<MatrixDouble>();
1013 field_eval_data,
simple->getDomainFEName());
1015 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1016 auto no_rule = [](
int,
int,
int) {
return -1; };
1017 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
1018 field_eval_fe_ptr->getRuleHook = no_rule;
1021 field_eval_fe_ptr->getOpPtrVector(), {H1, HDIV},
"GEOMETRY");
1023 auto [common_plastic_ptr, common_hencky_ptr] =
1024 PlasticOps::createCommonPlasticOps<SPACE_DIM, IT, DomainEleOp>(
1025 mField,
"MAT_PLASTIC", field_eval_fe_ptr->getOpPtrVector(),
"U",
1026 "EP",
"TAU", 1., Sev::inform);
1028 field_eval_fe_ptr->getOpPtrVector().push_back(
1031 if ((common_plastic_ptr) && (common_hencky_ptr) && (scalar_field_ptrs)) {
1033 scalar_field_ptrs->insert(
1034 {
"PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()});
1035 scalar_field_ptrs->insert(
1036 {
"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()});
1037 vector_field_ptrs->insert({
"U", u_field_ptr});
1038 sym_tensor_field_ptrs->insert(
1039 {
"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()});
1040 sym_tensor_field_ptrs->insert(
1041 {
"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()});
1042 sym_tensor_field_ptrs->insert(
1043 {
"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()});
1044 tensor_field_ptrs->insert({
"GRAD", common_hencky_ptr->matGradPtr});
1045 tensor_field_ptrs->insert(
1046 {
"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()});
1048 scalar_field_ptrs->insert(
1049 {
"PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()});
1050 scalar_field_ptrs->insert(
1051 {
"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()});
1052 vector_field_ptrs->insert({
"U", u_field_ptr});
1053 sym_tensor_field_ptrs->insert(
1054 {
"STRAIN", common_plastic_ptr->mStrainPtr});
1055 sym_tensor_field_ptrs->insert(
1056 {
"STRESS", common_plastic_ptr->mStressPtr});
1057 sym_tensor_field_ptrs->insert(
1058 {
"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()});
1059 sym_tensor_field_ptrs->insert(
1060 {
"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()});
1065 auto test_monitor_ptr = boost::make_shared<FEMethod>();
1067 auto set_time_monitor = [&](
auto dm,
auto solver) {
1070 dm, create_post_process_elements(), reactionFe, uXScatter, uYScatter,
1071 uZScatter, field_eval_coords, field_eval_data, scalar_field_ptrs,
1072 vector_field_ptrs, sym_tensor_field_ptrs, tensor_field_ptrs));
1073 boost::shared_ptr<ForcesAndSourcesCore>
null;
1075 test_monitor_ptr->postProcessHook = [&]() {
1078 if (
atom_test && fabs(test_monitor_ptr->ts_t - 0.5) < 1e-12 &&
1079 test_monitor_ptr->ts_step == 25) {
1081 if (scalar_field_ptrs->at(
"PLASTIC_MULTIPLIER")->size()) {
1084 MOFEM_LOG(
"PlasticSync", Sev::inform) <<
"Eval point tau: " << t_tau;
1086 if (
atom_test == 1 && fabs(t_tau - 0.688861) > 1e-5) {
1088 "atom test %d failed: wrong plastic multiplier value",
1093 if (vector_field_ptrs->at(
"U")->size1()) {
1096 getFTensor1FromMat<SPACE_DIM>(*vector_field_ptrs->at(
"U"));
1097 MOFEM_LOG(
"PlasticSync", Sev::inform) <<
"Eval point U: " << t_disp;
1099 if (
atom_test == 1 && fabs(t_disp(0) - 0.25 / 2.) > 1e-5 ||
1100 fabs(t_disp(1) + 0.0526736) > 1e-5 || fabs(t_disp(2)) > 1e-5) {
1102 "atom test %d failed: wrong displacement value",
1107 if (sym_tensor_field_ptrs->at(
"PLASTIC_STRAIN")->size1()) {
1108 auto t_plastic_strain = getFTensor2SymmetricFromMat<SPACE_DIM>(
1109 *sym_tensor_field_ptrs->at(
"PLASTIC_STRAIN"));
1111 <<
"Eval point EP: " << t_plastic_strain;
1114 fabs(t_plastic_strain(0, 0) - 0.221943) > 1e-5 ||
1115 fabs(t_plastic_strain(0, 1)) > 1e-5 ||
1116 fabs(t_plastic_strain(1, 1) + 0.110971) > 1e-5) {
1118 "atom test %d failed: wrong plastic strain value",
1123 if (tensor_field_ptrs->at(
"FIRST_PIOLA")->size1()) {
1124 auto t_piola_stress = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(
1125 *tensor_field_ptrs->at(
"FIRST_PIOLA"));
1127 <<
"Eval point Piola stress: " << t_piola_stress;
1129 if (
atom_test == 1 && fabs((t_piola_stress(0, 0) - 198.775) /
1130 t_piola_stress(0, 0)) > 1e-5 ||
1131 fabs(t_piola_stress(0, 1)) + fabs(t_piola_stress(1, 0)) +
1132 fabs(t_piola_stress(1, 1)) >
1135 "atom test %d failed: wrong Piola stress value",
1146 monitor_ptr,
null, test_monitor_ptr);
1151 auto set_schur_pc = [&](
auto solver,
1152 boost::shared_ptr<SetUpSchur> &schur_ptr) {
1155 auto name_prb =
simple->getProblemName();
1161 dm_sub =
createDM(mField.get_comm(),
"DMMOFEM");
1166 for (
auto f : {
"U"}) {
1178 dm_sub =
createDM(mField.get_comm(),
"DMMOFEM");
1184 for (
auto f : {
"SIGMA",
"EP",
"TAU"}) {
1189 for (
auto f : {
"EP",
"TAU"}) {
1208 auto get_nested_mat_data = [&](
auto schur_dm,
auto block_dm) {
1214 {simple->getDomainFEName(),
1230 {simple->getBoundaryFEName(),
1232 {{
"SIGMA",
"SIGMA"}, {
"U",
"SIGMA"}, {
"SIGMA",
"U"}
1242 {dm_schur, dm_block}, block_mat_data,
1244 {
"SIGMA",
"EP",
"TAU"}, {
nullptr,
nullptr,
nullptr}, true
1251 auto get_nested_mat_data = [&](
auto schur_dm,
auto block_dm) {
1252 auto block_mat_data =
1255 {{simple->getDomainFEName(),
1272 {dm_schur, dm_block}, block_mat_data,
1274 {
"EP",
"TAU"}, {
nullptr,
nullptr}, false
1281 auto nested_mat_data = get_nested_mat_data(dm_schur, dm_block);
1284 auto block_is =
getDMSubData(dm_block)->getSmartRowIs();
1285 auto ao_schur =
getDMSubData(dm_schur)->getSmartRowMap();
1291 CHKERR schur_ptr->setUp(solver);
1297 auto dm =
simple->getDM();
1300 uXScatter = scatter_create(
D, 0);
1301 uYScatter = scatter_create(
D, 1);
1303 uZScatter = scatter_create(
D, 2);
1305 auto create_solver = [pip_mng]() {
1307 return pip_mng->createTSIM();
1309 return pip_mng->createTSIM2();
1312 auto solver = create_solver();
1314 auto active_pre_lhs = []() {
1321 auto active_post_lhs = [&]() {
1323 auto get_iter = [&]() {
1328 "Can not get iter");
1332 auto iter = get_iter();
1335 std::array<int, 5> activity_data;
1336 std::fill(activity_data.begin(), activity_data.end(), 0);
1338 activity_data.data(), activity_data.size(), MPI_INT,
1339 MPI_SUM, mField.get_comm());
1341 int &active_points = activity_data[0];
1342 int &avtive_full_elems = activity_data[1];
1343 int &avtive_elems = activity_data[2];
1344 int &nb_points = activity_data[3];
1345 int &nb_elements = activity_data[4];
1349 double proc_nb_points =
1350 100 *
static_cast<double>(active_points) / nb_points;
1351 double proc_nb_active =
1352 100 *
static_cast<double>(avtive_elems) / nb_elements;
1353 double proc_nb_full_active = 100;
1355 proc_nb_full_active =
1356 100 *
static_cast<double>(avtive_full_elems) / avtive_elems;
1359 "Iter %d nb pts %d nb active pts %d (%3.3f\%) nb active "
1361 "(%3.3f\%) nb full active elems %d (%3.3f\%)",
1362 iter, nb_points, active_points, proc_nb_points,
1363 avtive_elems, proc_nb_active, avtive_full_elems,
1364 proc_nb_full_active, iter);
1371 auto add_active_dofs_elem = [&](
auto dm) {
1373 auto fe_pre_proc = boost::make_shared<FEMethod>();
1374 fe_pre_proc->preProcessHook = active_pre_lhs;
1375 auto fe_post_proc = boost::make_shared<FEMethod>();
1376 fe_post_proc->postProcessHook = active_post_lhs;
1378 ts_ctx_ptr->getPreProcessIJacobian().push_front(fe_pre_proc);
1379 ts_ctx_ptr->getPostProcessIJacobian().push_back(fe_post_proc);
1383 auto set_essential_bc = [&](
auto dm,
auto solver) {
1387 auto pre_proc_ptr = boost::make_shared<FEMethod>();
1388 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
1389 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
1392 auto disp_time_scale = boost::make_shared<TimeScale>();
1394 auto get_bc_hook_rhs = [
this, pre_proc_ptr, disp_time_scale]() {
1396 {disp_time_scale},
false);
1399 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
1401 auto get_post_proc_hook_rhs = [
this, post_proc_rhs_ptr]() {
1404 mField, post_proc_rhs_ptr,
nullptr, Sev::verbose)();
1406 mField, post_proc_rhs_ptr, 1.)();
1409 auto get_post_proc_hook_lhs = [
this, post_proc_lhs_ptr]() {
1411 mField, post_proc_lhs_ptr, 1.);
1413 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
1416 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
1417 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
1418 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
1419 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
1420 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
1426 CHKERR TSSetSolution(solver,
D);
1428 CHKERR TS2SetSolution(solver,
D, DD);
1431 CHKERR set_section_monitor(solver);
1432 CHKERR set_time_monitor(dm, solver);
1433 CHKERR TSSetFromOptions(solver);
1436 CHKERR add_active_dofs_elem(dm);
1437 boost::shared_ptr<SetUpSchur> schur_ptr;
1438 CHKERR set_schur_pc(solver, schur_ptr);
1439 CHKERR set_essential_bc(dm, solver);
1444 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
1445 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"TSSetUp";
1447 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"TSSetUp <= done";
1448 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"TSSolve";
1449 CHKERR TSSolve(solver, NULL);
1450 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"TSSolve <= done";
1467 constexpr
double eps = 1e-9;
1469 auto x = opt->setRandomFields(
simple->getDM(), {
1471 {
"U", {-1e-6, 1e-6}},
1473 {
"EP", {-1e-6, 1e-6}},
1479 auto dot_x_plastic_active =
1480 opt->setRandomFields(
simple->getDM(), {
1489 auto diff_x_plastic_active =
1490 opt->setRandomFields(
simple->getDM(), {
1500 auto dot_x_elastic =
1501 opt->setRandomFields(
simple->getDM(), {
1510 auto diff_x_elastic =
1511 opt->setRandomFields(
simple->getDM(), {
1521 auto test_domain_ops = [&](
auto fe_name,
auto lhs_pipeline,
auto rhs_pipeline,
1522 auto dot_x,
auto diff_x) {
1525 auto diff_res = opt->checkCentralFiniteDifference(
1526 simple->getDM(), fe_name, rhs_pipeline, lhs_pipeline, x, dot_x,
1532 CHKERR VecNorm(diff_res, NORM_2, &fnorm);
1534 "Test consistency of tangent matrix %3.4e", fnorm);
1536 constexpr
double err = 1e-5;
1539 "Norm of directional derivative too large err = %3.4e", fnorm);
1544 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Elastic active";
1545 CHKERR test_domain_ops(
simple->getDomainFEName(), pip->getDomainLhsFE(),
1546 pip->getDomainRhsFE(), dot_x_elastic, diff_x_elastic);
1548 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Plastic active";
1549 CHKERR test_domain_ops(
simple->getDomainFEName(), pip->getDomainLhsFE(),
1550 pip->getDomainRhsFE(), dot_x_plastic_active,
1551 diff_x_plastic_active);
1567 #endif // ADD_CONTACT
1570 const char param_file[] =
"param_file.petsc";
1574 auto core_log = logging::core::get();
1576 LogManager::createSink(LogManager::getStrmWorld(),
"PLASTICITY"));
1578 LogManager::createSink(LogManager::getStrmWorld(),
"TIMER"));
1579 LogManager::setLog(
"PLASTICITY");
1584 LogManager::createSink(LogManager::getStrmWorld(),
"CONTACT"));
1585 LogManager::setLog(
"CONTACT");
1587 #endif // ADD_CONTACT
1590 LogManager::createSink(LogManager::getStrmSync(),
"PlasticSync"));
1591 LogManager::setLog(
"PlasticSync");
1597 DMType dm_name =
"DMMOFEM";
1628 if (Py_FinalizeEx() < 0) {
1632 #endif // ADD_CONTACT
1645 "Is expected that schur matrix is not "
1646 "allocated. This is "
1647 "possible only is PC is set up twice");
1671 CHKERR TSGetSNES(solver, &snes);
1673 CHKERR SNESGetKSP(snes, &ksp);
1674 CHKERR KSPSetFromOptions(ksp);
1677 CHKERR KSPGetPC(ksp, &pc);
1678 PetscBool is_pcfs = PETSC_FALSE;
1679 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1683 "Is expected that schur matrix is not "
1684 "allocated. This is "
1685 "possible only is PC is set up twice");
1693 CHKERR TSGetDM(solver, &solver_dm);
1694 CHKERR DMSetMatType(solver_dm, MATSHELL);
1701 auto swap_assemble = [](TS ts, PetscReal
t,
Vec u,
Vec u_t, PetscReal
a,
1702 Mat
A, Mat B,
void *ctx) {
1705 CHKERR TSSetIJacobian(solver,
A,
P, swap_assemble, ts_ctx_ptr.get());
1707 auto swap_assemble = [](TS ts, PetscReal
t,
Vec u,
Vec u_t,
Vec utt,
1708 PetscReal
a, PetscReal aa, Mat
A, Mat B,
1712 CHKERR TSSetI2Jacobian(solver,
A,
P, swap_assemble, ts_ctx_ptr.get());
1716 auto set_ops = [&]() {
1722 pip_mng->getOpBoundaryLhsPipeline().push_front(
1726 {
"EP",
"TAU"}, {
nullptr,
nullptr},
aoSchur,
S,
false, false
1730 pip_mng->getOpDomainLhsPipeline().push_front(
1734 {
"EP",
"TAU"}, {
nullptr,
nullptr},
aoSchur,
S,
false, false
1739 double eps_stab = 1e-4;
1745 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
1748 pip_mng->getOpBoundaryLhsPipeline().push_front(
1750 pip_mng->getOpBoundaryLhsPipeline().push_back(
1751 new OpMassStab(
"SIGMA",
"SIGMA", [eps_stab](
double,
double,
double) {
1756 {
"SIGMA",
"EP",
"TAU"}, {
nullptr,
nullptr,
nullptr},
aoSchur,
S,
1761 pip_mng->getOpDomainLhsPipeline().push_front(
1765 {
"SIGMA",
"EP",
"TAU"}, {
nullptr,
nullptr,
nullptr},
aoSchur,
S,
1769 #endif // ADD_CONTACT
1773 auto set_assemble_elems = [&]() {
1775 auto schur_asmb_pre_proc = boost::make_shared<FEMethod>();
1776 schur_asmb_pre_proc->preProcessHook = [
this]() {
1779 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"Lhs Assemble Begin";
1782 auto schur_asmb_post_proc = boost::make_shared<FEMethod>();
1784 schur_asmb_post_proc->postProcessHook = [
this, schur_asmb_post_proc]() {
1786 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"Lhs Assemble End";
1789 CHKERR MatAssemblyBegin(
S, MAT_FINAL_ASSEMBLY);
1790 CHKERR MatAssemblyEnd(
S, MAT_FINAL_ASSEMBLY);
1797 ts_ctx_ptr->getPreProcessIJacobian().push_front(schur_asmb_pre_proc);
1798 ts_ctx_ptr->getPostProcessIJacobian().push_front(schur_asmb_post_proc);
1802 auto set_pc = [&]() {
1805 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER,
S);
1809 auto set_diagonal_pc = [&]() {
1812 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULL, &subksp);
1813 auto get_pc = [](
auto ksp) {
1815 CHKERR KSPGetPC(ksp, &pc_raw);
1820 CHKERR PetscFree(subksp);
1826 CHKERR set_assemble_elems();
1830 CHKERR set_diagonal_pc();
1833 pip_mng->getOpBoundaryLhsPipeline().push_front(
1835 pip_mng->getOpBoundaryLhsPipeline().push_back(
1838 pip_mng->getOpDomainLhsPipeline().push_back(
1847 boost::shared_ptr<SetUpSchur>
1851 return boost::shared_ptr<SetUpSchur>(
1858 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1859 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1866 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1867 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1873 template <
int FE_DIM,
int PROBLEM_DIM,
int SPACE_DIM>
1875 scaleL2(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1876 std::string geom_field_name) {
1879 auto jac_ptr = boost::make_shared<MatrixDouble>();
1880 auto det_ptr = boost::make_shared<VectorDouble>();
1882 geom_field_name, jac_ptr));
1885 auto scale_ptr = boost::make_shared<double>(1.);
1889 auto op_scale =
new OP(
NOSPACE, OP::OPSPACE);
1890 op_scale->doWorkRhsHook = [scale_ptr, det_ptr,
1893 *scale_ptr =
scale / det_ptr->size();
1897 pipeline.push_back(op_scale);
1909 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1910 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1912 constexpr
bool scale_l2 =
false;
1914 CHKERR scaleL2<3, 3, 3>(pipeline, geom_field_name);
1917 nullptr,
nullptr,
nullptr);
1922 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1923 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1925 constexpr
bool scale_l2 =
false;
1927 CHKERR scaleL2<2, 2, 2>(pipeline, geom_field_name);
1930 nullptr,
nullptr,
nullptr);