12 #ifndef EXECUTABLE_DIMENSION
13 #define EXECUTABLE_DIMENSION 3
22 using namespace MoFEM;
65 std::max(
static_cast<double>(std::numeric_limits<float>::min_exponent10),
79 auto r = [&](
auto tau) {
82 constexpr
double eps = 1e-12;
83 return std::max(
r(tau),
eps *
r(0));
89 template <
typename T,
int DIM>
96 if (
C1_k < std::numeric_limits<double>::epsilon()) {
100 t_alpha(
i,
j) =
C1_k * t_plastic_strain(
i,
j);
149 #include <boost/python.hpp>
150 #include <boost/python/def.hpp>
151 #include <boost/python/numpy.hpp>
152 namespace bp = boost::python;
153 namespace np = boost::python::numpy;
163 #endif // ADD_CONTACT
208 boost::shared_ptr<ContactOps::SDFPython> sdfPythonPtr;
210 #endif // ADD_CONTACT
216 CHKERR createCommonData();
220 PetscBool test_ops = PETSC_FALSE;
223 if (test_ops == PETSC_FALSE) {
238 CHKERR mField.get_moab().get_entities_by_dimension(0,
SPACE_DIM, domain_ents,
240 auto get_ents_by_dim = [&](
const auto dim) {
246 CHKERR mField.get_moab().get_connectivity(domain_ents, ents,
true);
248 CHKERR mField.get_moab().get_entities_by_dimension(0, dim, ents,
true);
253 auto get_base = [&]() {
254 auto domain_ents = get_ents_by_dim(
SPACE_DIM);
255 if (domain_ents.empty())
273 const auto base = get_base();
284 PetscBool order_edge = PETSC_FALSE;
287 PetscBool order_face = PETSC_FALSE;
290 PetscBool order_volume = PETSC_FALSE;
294 if (order_edge || order_face || order_volume) {
296 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Order edge " << order_edge
299 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Order face " << order_face
302 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Order volume " << order_volume
306 auto ents = get_ents_by_dim(0);
308 ents.merge(get_ents_by_dim(1));
310 ents.merge(get_ents_by_dim(2));
312 ents.merge(get_ents_by_dim(3));
328 auto get_skin = [&]() {
330 CHKERR mField.get_moab().get_entities_by_dimension(0,
SPACE_DIM, body_ents);
331 Skinner skin(&mField.get_moab());
333 CHKERR skin.find_skin(0, body_ents,
false, skin_ents);
337 auto filter_blocks = [&](
auto skin) {
338 bool is_contact_block =
true;
343 (boost::format(
"%s(.*)") %
"CONTACT").str()
352 <<
"Find contact block set: " <<
m->getName();
353 auto meshset =
m->getMeshset();
354 Range contact_meshset_range;
355 CHKERR mField.get_moab().get_entities_by_dimension(
356 meshset,
SPACE_DIM - 1, contact_meshset_range,
true);
359 contact_meshset_range);
360 contact_range.merge(contact_meshset_range);
362 if (is_contact_block) {
364 <<
"Nb entities in contact surface: " << contact_range.size();
366 skin = intersect(skin, contact_range);
371 auto filter_true_skin = [&](
auto skin) {
373 ParallelComm *pcomm =
375 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
376 PSTATUS_NOT, -1, &boundary_ents);
377 return boundary_ents;
380 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
388 auto project_ho_geometry = [&]() {
390 return mField.loop_dofs(
"GEOMETRY", ent_method);
392 PetscBool project_geometry = PETSC_TRUE;
394 &project_geometry, PETSC_NULL);
395 if (project_geometry) {
396 CHKERR project_ho_geometry();
407 auto get_command_line_parameters = [&]() {
432 PetscBool tau_order_is_set;
435 PetscBool ep_order_is_set;
448 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Hardening " <<
H;
449 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Viscous hardening " <<
visH;
450 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Saturation yield stress " <<
Qinf;
451 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Saturation exponent " <<
b_iso;
452 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Kinematic hardening " <<
C1_k;
457 if (tau_order_is_set == PETSC_FALSE)
459 if (ep_order_is_set == PETSC_FALSE)
462 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Approximation order " <<
order;
464 <<
"Ep approximation order " <<
ep_order;
466 <<
"Tau approximation order " <<
tau_order;
468 <<
"Geometry approximation order " <<
geom_order;
470 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Density " <<
rho;
473 PetscBool is_scale = PETSC_TRUE;
487 #endif // ADD_CONTACT
497 CHKERR get_command_line_parameters();
501 sdfPythonPtr = boost::make_shared<ContactOps::SDFPython>();
502 CHKERR sdfPythonPtr->sdfInit(
"sdf.py");
503 ContactOps::sdfPythonWeakPtr = sdfPythonPtr;
505 #endif // ADD_CONTACT
518 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_X",
520 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Y",
522 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Z",
524 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
525 "REMOVE_ALL",
"U", 0, 3);
528 for (
auto b : {
"FIX_X",
"REMOVE_X"})
529 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(), b,
530 "SIGMA", 0, 0,
false,
true);
531 for (
auto b : {
"FIX_Y",
"REMOVE_Y"})
532 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(), b,
533 "SIGMA", 1, 1,
false,
true);
534 for (
auto b : {
"FIX_Z",
"REMOVE_Z"})
535 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(), b,
536 "SIGMA", 2, 2,
false,
true);
537 for (
auto b : {
"FIX_ALL",
"REMOVE_ALL"})
538 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(), b,
539 "SIGMA", 0, 3,
false,
true);
540 CHKERR bc_mng->removeBlockDOFsOnEntities(
541 simple->getProblemName(),
"NO_CONTACT",
"SIGMA", 0, 3,
false,
true);
545 simple->getProblemName(),
"U");
547 auto &bc_map = bc_mng->getBcMapByBlockName();
548 for (
auto bc : bc_map)
549 MOFEM_LOG(
"PLASTICITY", Sev::verbose) <<
"Marker " << bc.first;
560 auto integration_rule_bc = [](
int,
int,
int ao) {
return 2 * ao; };
564 auto add_boundary_ops_lhs_mechanical = [&](
auto &pip) {
573 pip, mField,
"U", Sev::inform);
578 ContactOps::opFactoryBoundaryLhs<SPACE_DIM, AT, GAUSS, BoundaryEleOp>(
581 ContactOps::opFactoryBoundaryToDomainLhs<SPACE_DIM, AT, IT, DomainEle>(
582 mField, pip,
simple->getDomainFEName(),
"SIGMA",
"U",
"GEOMETRY",
584 #endif // ADD_CONTACT
589 auto add_boundary_ops_rhs_mechanical = [&](
auto &pip) {
598 pip, mField,
"U", {boost::make_shared<ScaledTimeScale>()}, Sev::inform);
601 CHKERR ContactOps::opFactoryBoundaryRhs<SPACE_DIM, AT, IT, BoundaryEleOp>(
603 #endif // ADD_CONTACT
608 auto add_domain_ops_lhs = [
this](
auto &pip) {
620 auto get_inertia_and_mass_damping = [
this](
const double,
const double,
624 return (
rho /
scale) * fe_domain_lhs->ts_aa +
627 pip.push_back(
new OpMass(
"U",
"U", get_inertia_and_mass_damping));
630 CHKERR PlasticOps::opFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
631 mField,
"MAT_PLASTIC", pip,
"U",
"EP",
"TAU");
636 auto add_domain_ops_rhs = [
this](
auto &pip) {
644 {boost::make_shared<ScaledTimeScale>(
"body_force_hist.txt")},
652 AT>::LinearForm<IT>::OpBaseTimesVector<1,
SPACE_DIM, 1>;
655 auto mat_acceleration = boost::make_shared<MatrixDouble>();
657 "U", mat_acceleration));
659 new OpInertiaForce(
"U", mat_acceleration, [](
double,
double,
double) {
663 auto mat_velocity = boost::make_shared<MatrixDouble>();
667 new OpInertiaForce(
"U", mat_velocity, [](
double,
double,
double) {
673 CHKERR PlasticOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
674 mField,
"MAT_PLASTIC", pip,
"U",
"EP",
"TAU");
677 CHKERR ContactOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
679 #endif // ADD_CONTACT
684 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
685 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
688 CHKERR add_boundary_ops_lhs_mechanical(pip_mng->getOpBoundaryLhsPipeline());
689 CHKERR add_boundary_ops_rhs_mechanical(pip_mng->getOpBoundaryRhsPipeline());
691 CHKERR pip_mng->setDomainRhsIntegrationRule(vol_rule);
692 CHKERR pip_mng->setDomainLhsIntegrationRule(vol_rule);
694 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_bc);
695 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_bc);
697 auto create_reaction_pipeline = [&](
auto &pip) {
701 CHKERR PlasticOps::opFactoryDomainReactions<SPACE_DIM, AT, IT, DomainEleOp>(
702 mField,
"MAT_PLASTIC", pip,
"U",
"EP",
"TAU");
706 reactionFe = boost::make_shared<DomainEle>(mField);
707 reactionFe->getRuleHook = vol_rule;
708 CHKERR create_reaction_pipeline(reactionFe->getOpPtrVector());
709 reactionFe->postProcessHook =
728 static boost::shared_ptr<SetUpSchur> createSetUpSchur(
749 auto set_section_monitor = [&](
auto solver) {
752 CHKERR TSGetSNES(solver, &snes);
753 CHKERR SNESMonitorSet(snes,
756 (
void *)(snes_ctx_ptr.get()),
nullptr);
760 auto create_post_process_elements = [&]() {
761 auto pp_fe = boost::make_shared<PostProcEle>(mField);
763 auto push_vol_ops = [
this](
auto &pip) {
767 auto [common_plastic_ptr, common_hencky_ptr] =
768 PlasticOps::createCommonPlasticOps<SPACE_DIM, IT, DomainEleOp>(
769 mField,
"MAT_PLASTIC", pip,
"U",
"EP",
"TAU", 1., Sev::inform);
771 if (common_hencky_ptr) {
772 if (common_plastic_ptr->mGradPtr != common_hencky_ptr->matGradPtr)
776 return std::make_pair(common_plastic_ptr, common_hencky_ptr);
779 auto push_vol_post_proc_ops = [
this](
auto &pp_fe,
auto &&p) {
782 auto &pip = pp_fe->getOpPtrVector();
784 auto [common_plastic_ptr, common_hencky_ptr] = p;
788 auto x_ptr = boost::make_shared<MatrixDouble>();
791 auto u_ptr = boost::make_shared<MatrixDouble>();
800 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
803 common_plastic_ptr->getPlasticSurfacePtr()},
804 {
"PLASTIC_MULTIPLIER",
805 common_plastic_ptr->getPlasticTauPtr()}},
807 {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}},
809 {{
"GRAD", common_hencky_ptr->matGradPtr},
810 {
"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()}},
812 {{
"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
813 {
"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
825 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
828 common_plastic_ptr->getPlasticSurfacePtr()},
829 {
"PLASTIC_MULTIPLIER",
830 common_plastic_ptr->getPlasticTauPtr()}},
832 {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}},
836 {{
"STRAIN", common_plastic_ptr->mStrainPtr},
837 {
"STRESS", common_plastic_ptr->mStressPtr},
838 {
"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
839 {
"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
849 auto vol_post_proc = [
this, push_vol_post_proc_ops, push_vol_ops]() {
850 PetscBool post_proc_vol = PETSC_FALSE;
852 &post_proc_vol, PETSC_NULL);
853 if (post_proc_vol == PETSC_FALSE)
854 return boost::shared_ptr<PostProcEle>();
855 auto pp_fe = boost::make_shared<PostProcEle>(mField);
857 push_vol_post_proc_ops(pp_fe, push_vol_ops(pp_fe->getOpPtrVector())),
858 "push_vol_post_proc_ops");
862 auto skin_post_proc = [
this, push_vol_post_proc_ops, push_vol_ops]() {
863 PetscBool post_proc_skin = PETSC_TRUE;
865 &post_proc_skin, PETSC_NULL);
866 if (post_proc_skin == PETSC_FALSE)
867 return boost::shared_ptr<SkinPostProcEle>();
870 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
873 pp_fe->getOpPtrVector().push_back(op_side);
875 pp_fe, push_vol_ops(op_side->getOpPtrVector())),
876 "push_vol_post_proc_ops");
880 return std::make_pair(vol_post_proc(), skin_post_proc());
883 auto scatter_create = [&](
auto D,
auto coeff) {
885 CHKERR is_manager->isCreateProblemFieldAndRank(
simple->getProblemName(),
886 ROW,
"U", coeff, coeff, is);
888 CHKERR ISGetLocalSize(is, &loc_size);
890 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &
v);
892 CHKERR VecScatterCreate(
D, is,
v, PETSC_NULL, &scatter);
897 auto set_time_monitor = [&](
auto dm,
auto solver) {
899 boost::shared_ptr<Monitor> monitor_ptr(
900 new Monitor(dm, create_post_process_elements(), reactionFe, uXScatter,
901 uYScatter, uZScatter));
902 boost::shared_ptr<ForcesAndSourcesCore>
null;
904 monitor_ptr,
null,
null);
908 auto set_schur_pc = [&](
auto solver,
909 boost::shared_ptr<SetUpSchur> &schur_ptr) {
912 auto name_prb =
simple->getProblemName();
918 dm_sub =
createDM(mField.get_comm(),
"DMMOFEM");
923 for (
auto f : {
"U"}) {
935 dm_sub =
createDM(mField.get_comm(),
"DMMOFEM");
941 for (
auto f : {
"SIGMA",
"EP",
"TAU"}) {
946 for (
auto f : {
"EP",
"TAU"}) {
965 auto get_nested_mat_data = [&](
auto schur_dm,
auto block_dm) {
971 {simple->getDomainFEName(),
987 {simple->getBoundaryFEName(),
989 {{
"SIGMA",
"SIGMA"}, {
"U",
"SIGMA"}, {
"SIGMA",
"U"}
999 {dm_schur, dm_block}, block_mat_data,
1001 {
"SIGMA",
"EP",
"TAU"}, {
nullptr,
nullptr,
nullptr}, true
1008 auto get_nested_mat_data = [&](
auto schur_dm,
auto block_dm) {
1009 auto block_mat_data =
1012 {{simple->getDomainFEName(),
1029 {dm_schur, dm_block}, block_mat_data,
1031 {
"EP",
"TAU"}, {
nullptr,
nullptr}, false
1038 auto nested_mat_data = get_nested_mat_data(dm_schur, dm_block);
1041 auto block_is =
getDMSubData(dm_block)->getSmartRowIs();
1042 auto ao_schur =
getDMSubData(dm_schur)->getSmartRowMap();
1048 CHKERR schur_ptr->setUp(solver);
1054 auto dm =
simple->getDM();
1057 uXScatter = scatter_create(
D, 0);
1058 uYScatter = scatter_create(
D, 1);
1060 uZScatter = scatter_create(
D, 2);
1062 auto create_solver = [pip_mng]() {
1064 return pip_mng->createTSIM();
1066 return pip_mng->createTSIM2();
1069 auto solver = create_solver();
1071 auto active_pre_lhs = []() {
1078 auto active_post_lhs = [&]() {
1080 auto get_iter = [&]() {
1085 "Can not get iter");
1089 auto iter = get_iter();
1092 std::array<int, 5> activity_data;
1093 std::fill(activity_data.begin(), activity_data.end(), 0);
1095 activity_data.data(), activity_data.size(), MPI_INT,
1096 MPI_SUM, mField.get_comm());
1098 int &active_points = activity_data[0];
1099 int &avtive_full_elems = activity_data[1];
1100 int &avtive_elems = activity_data[2];
1101 int &nb_points = activity_data[3];
1102 int &nb_elements = activity_data[4];
1106 double proc_nb_points =
1107 100 *
static_cast<double>(active_points) / nb_points;
1108 double proc_nb_active =
1109 100 *
static_cast<double>(avtive_elems) / nb_elements;
1110 double proc_nb_full_active = 100;
1112 proc_nb_full_active =
1113 100 *
static_cast<double>(avtive_full_elems) / avtive_elems;
1116 "Iter %d nb pts %d nb active pts %d (%3.3f\%) nb active "
1118 "(%3.3f\%) nb full active elems %d (%3.3f\%)",
1119 iter, nb_points, active_points, proc_nb_points,
1120 avtive_elems, proc_nb_active, avtive_full_elems,
1121 proc_nb_full_active, iter);
1128 auto add_active_dofs_elem = [&](
auto dm) {
1130 auto fe_pre_proc = boost::make_shared<FEMethod>();
1131 fe_pre_proc->preProcessHook = active_pre_lhs;
1132 auto fe_post_proc = boost::make_shared<FEMethod>();
1133 fe_post_proc->postProcessHook = active_post_lhs;
1135 ts_ctx_ptr->getPreProcessIJacobian().push_front(fe_pre_proc);
1136 ts_ctx_ptr->getPostProcessIJacobian().push_back(fe_post_proc);
1140 auto set_essential_bc = [&](
auto dm,
auto solver) {
1144 auto pre_proc_ptr = boost::make_shared<FEMethod>();
1145 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
1146 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
1149 auto disp_time_scale = boost::make_shared<TimeScale>();
1151 auto get_bc_hook_rhs = [
this, pre_proc_ptr, disp_time_scale]() {
1153 {disp_time_scale},
false);
1156 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
1158 auto get_post_proc_hook_rhs = [
this, post_proc_rhs_ptr]() {
1161 mField, post_proc_rhs_ptr,
nullptr, Sev::verbose)();
1163 mField, post_proc_rhs_ptr, 1.)();
1166 auto get_post_proc_hook_lhs = [
this, post_proc_lhs_ptr]() {
1168 mField, post_proc_lhs_ptr, 1.);
1170 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
1173 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
1174 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
1175 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
1176 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
1177 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
1183 CHKERR TSSetSolution(solver,
D);
1185 CHKERR TS2SetSolution(solver,
D, DD);
1188 CHKERR set_section_monitor(solver);
1189 CHKERR set_time_monitor(dm, solver);
1190 CHKERR TSSetFromOptions(solver);
1193 CHKERR add_active_dofs_elem(dm);
1194 boost::shared_ptr<SetUpSchur> schur_ptr;
1195 CHKERR set_schur_pc(solver, schur_ptr);
1196 CHKERR set_essential_bc(dm, solver);
1201 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
1202 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"TSSetUp";
1204 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"TSSetUp <= done";
1205 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"TSSolve";
1206 CHKERR TSSolve(solver, NULL);
1207 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"TSSolve <= done";
1224 constexpr
double eps = 1e-9;
1226 auto x = opt->setRandomFields(
simple->getDM(), {
1228 {
"U", {-1e-6, 1e-6}},
1230 {
"EP", {-1e-6, 1e-6}},
1236 auto dot_x_plastic_active =
1237 opt->setRandomFields(
simple->getDM(), {
1246 auto diff_x_plastic_active =
1247 opt->setRandomFields(
simple->getDM(), {
1257 auto dot_x_elastic =
1258 opt->setRandomFields(
simple->getDM(), {
1267 auto diff_x_elastic =
1268 opt->setRandomFields(
simple->getDM(), {
1278 auto test_domain_ops = [&](
auto fe_name,
auto lhs_pipeline,
auto rhs_pipeline,
1279 auto dot_x,
auto diff_x) {
1282 auto diff_res = opt->checkCentralFiniteDifference(
1283 simple->getDM(), fe_name, rhs_pipeline, lhs_pipeline, x, dot_x,
1289 CHKERR VecNorm(diff_res, NORM_2, &fnorm);
1291 "Test consistency of tangent matrix %3.4e", fnorm);
1293 constexpr
double err = 1e-5;
1296 "Norm of directional derivative too large err = %3.4e", fnorm);
1301 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Elastic active";
1302 CHKERR test_domain_ops(
simple->getDomainFEName(), pip->getDomainLhsFE(),
1303 pip->getDomainRhsFE(), dot_x_elastic, diff_x_elastic);
1305 MOFEM_LOG(
"PLASTICITY", Sev::inform) <<
"Plastic active";
1306 CHKERR test_domain_ops(
simple->getDomainFEName(), pip->getDomainLhsFE(),
1307 pip->getDomainRhsFE(), dot_x_plastic_active,
1308 diff_x_plastic_active);
1326 #endif // ADD_CONTACT
1329 const char param_file[] =
"param_file.petsc";
1333 auto core_log = logging::core::get();
1335 LogManager::createSink(LogManager::getStrmWorld(),
"PLASTICITY"));
1337 LogManager::createSink(LogManager::getStrmWorld(),
"TIMER"));
1338 LogManager::setLog(
"PLASTICITY");
1343 LogManager::createSink(LogManager::getStrmWorld(),
"CONTACT"));
1344 LogManager::setLog(
"CONTACT");
1346 #endif // ADD_CONTACT
1351 DMType dm_name =
"DMMOFEM";
1382 if (Py_FinalizeEx() < 0) {
1386 #endif // ADD_CONTACT
1399 "Is expected that schur matrix is not "
1400 "allocated. This is "
1401 "possible only is PC is set up twice");
1425 CHKERR TSGetSNES(solver, &snes);
1427 CHKERR SNESGetKSP(snes, &ksp);
1428 CHKERR KSPSetFromOptions(ksp);
1431 CHKERR KSPGetPC(ksp, &pc);
1432 PetscBool is_pcfs = PETSC_FALSE;
1433 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1437 "Is expected that schur matrix is not "
1438 "allocated. This is "
1439 "possible only is PC is set up twice");
1447 CHKERR TSGetDM(solver, &solver_dm);
1448 CHKERR DMSetMatType(solver_dm, MATSHELL);
1455 auto swap_assemble = [](TS ts, PetscReal
t,
Vec u,
Vec u_t, PetscReal
a,
1456 Mat
A, Mat B,
void *ctx) {
1459 CHKERR TSSetIJacobian(solver,
A,
P, swap_assemble, ts_ctx_ptr.get());
1461 auto swap_assemble = [](TS ts, PetscReal
t,
Vec u,
Vec u_t,
Vec utt,
1462 PetscReal
a, PetscReal aa, Mat
A, Mat B,
1466 CHKERR TSSetI2Jacobian(solver,
A,
P, swap_assemble, ts_ctx_ptr.get());
1470 auto set_ops = [&]() {
1476 pip_mng->getOpBoundaryLhsPipeline().push_front(
1480 {
"EP",
"TAU"}, {
nullptr,
nullptr},
aoSchur,
S,
false, false
1484 pip_mng->getOpDomainLhsPipeline().push_front(
1488 {
"EP",
"TAU"}, {
nullptr,
nullptr},
aoSchur,
S,
false, false
1493 double eps_stab = 1e-4;
1499 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
1502 pip_mng->getOpBoundaryLhsPipeline().push_front(
1504 pip_mng->getOpBoundaryLhsPipeline().push_back(
1505 new OpMassStab(
"SIGMA",
"SIGMA", [eps_stab](
double,
double,
double) {
1510 {
"SIGMA",
"EP",
"TAU"}, {
nullptr,
nullptr,
nullptr},
aoSchur,
S,
1515 pip_mng->getOpDomainLhsPipeline().push_front(
1519 {
"SIGMA",
"EP",
"TAU"}, {
nullptr,
nullptr,
nullptr},
aoSchur,
S,
1523 #endif // ADD_CONTACT
1527 auto set_assemble_elems = [&]() {
1529 auto schur_asmb_pre_proc = boost::make_shared<FEMethod>();
1530 schur_asmb_pre_proc->preProcessHook = [
this]() {
1533 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"Lhs Assemble Begin";
1536 auto schur_asmb_post_proc = boost::make_shared<FEMethod>();
1538 schur_asmb_post_proc->postProcessHook = [
this, schur_asmb_post_proc]() {
1540 MOFEM_LOG(
"TIMER", Sev::verbose) <<
"Lhs Assemble End";
1543 CHKERR MatAssemblyBegin(
S, MAT_FINAL_ASSEMBLY);
1544 CHKERR MatAssemblyEnd(
S, MAT_FINAL_ASSEMBLY);
1551 ts_ctx_ptr->getPreProcessIJacobian().push_front(schur_asmb_pre_proc);
1552 ts_ctx_ptr->getPostProcessIJacobian().push_front(schur_asmb_post_proc);
1556 auto set_pc = [&]() {
1559 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER,
S);
1563 auto set_diagonal_pc = [&]() {
1566 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULL, &subksp);
1567 auto get_pc = [](
auto ksp) {
1569 CHKERR KSPGetPC(ksp, &pc_raw);
1574 CHKERR PetscFree(subksp);
1580 CHKERR set_assemble_elems();
1584 CHKERR set_diagonal_pc();
1587 pip_mng->getOpBoundaryLhsPipeline().push_front(
1589 pip_mng->getOpBoundaryLhsPipeline().push_back(
1592 pip_mng->getOpDomainLhsPipeline().push_back(
1601 boost::shared_ptr<SetUpSchur>
1605 return boost::shared_ptr<SetUpSchur>(