13 using namespace MoFEM;
39 I>::OpGradSymTensorGrad<BASE_DIM, SPACE_DIM, SPACE_DIM, 0>;
43 I>::OpGradTimesSymTensor<BASE_DIM, SPACE_DIM, SPACE_DIM>;
109 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
110 std::string
field_name, std::string block_name,
111 boost::shared_ptr<MatrixDouble> mat_D_Ptr,
Sev sev);
115 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
116 std::string
field_name, std::string block_name,
117 boost::shared_ptr<MatrixDouble> mat_D_Ptr,
Sev sev) {
121 OpMatBlocks(std::string
field_name, boost::shared_ptr<MatrixDouble>
m,
124 std::vector<const CubitMeshSets *> meshset_vec_ptr)
128 std::fill(&(doEntities[MBEDGE]), &(doEntities[MBMAXTYPE]),
false);
130 "Can not get data from block");
137 for (
auto &b : blockData) {
139 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
140 CHKERR getMatDPtr(matDPtr, b.bulkModulusK, b.shearModulusG);
145 CHKERR getMatDPtr(matDPtr, bulkModulusKDefault, shearModulusGDefault);
150 boost::shared_ptr<MatrixDouble> matDPtr;
154 double shearModulusG;
158 double bulkModulusKDefault;
159 double shearModulusGDefault;
160 std::vector<BlockData> blockData;
164 std::vector<const CubitMeshSets *> meshset_vec_ptr,
168 for (
auto m : meshset_vec_ptr) {
170 std::vector<double> block_data;
171 CHKERR m->getAttributes(block_data);
172 if (block_data.size() < 2) {
174 "Expected that block has two attributes");
176 auto get_block_ents = [&]() {
179 m_field.
get_moab().get_entities_by_handle(
m->meshset, ents,
true);
198 MoFEMErrorCode getMatDPtr(boost::shared_ptr<MatrixDouble> mat_D_ptr,
202 auto set_material_stiffness = [&]() {
213 auto t_D = getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*mat_D_ptr);
222 set_material_stiffness();
227 pipeline.push_back(
new OpMatBlocks(
233 (boost::format(
"%s(.*)") % block_name).str()
247 CHKERR boundaryCondition();
271 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
272 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
273 PetscInt choice_base_value = AINSWORTH;
275 LASBASETOPT, &choice_base_value, PETSC_NULL);
278 switch (choice_base_value) {
282 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
287 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
306 auto project_ho_geometry = [&]() {
308 return mField.loop_dofs(
"GEOMETRY", ent_method);
310 CHKERR project_ho_geometry();
317 fieldEvalCoords.data(), &coords_dim,
321 vectorFieldPtr = boost::make_shared<MatrixDouble>();
327 fieldEvalData,
simple->getDomainFEName());
330 fieldEvalData,
simple->getDomainFEName());
333 fieldEvalData->setEvalPoints(fieldEvalCoords.data(), 1);
334 auto no_rule = [](
int,
int,
int) {
return -1; };
335 auto field_eval_fe_ptr = fieldEvalData->feMethodPtr.lock();
336 field_eval_fe_ptr->getRuleHook = no_rule;
338 field_eval_fe_ptr->getOpPtrVector().push_back(
353 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_X",
355 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Y",
357 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Z",
359 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
360 "REMOVE_ALL",
"U", 0, 3);
362 simple->getProblemName(),
"U");
365 CHKERR bc_mng->addBlockDOFsToMPCs(
simple->getProblemName(),
"U");
389 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
390 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
394 pip->getOpDomainLhsPipeline(), {H1},
"GEOMETRY");
396 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
398 pip->getOpBoundaryRhsPipeline(), {NOSPACE},
"GEOMETRY");
400 pip->getOpBoundaryLhsPipeline(), {NOSPACE},
"GEOMETRY");
403 auto mat_D_ptr = boost::make_shared<MatrixDouble>();
407 mat_D_ptr, Sev::verbose);
408 pip->getOpDomainLhsPipeline().push_back(
new OpK(
"U",
"U", mat_D_ptr));
412 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
413 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
414 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
415 pip->getOpDomainRhsPipeline().push_back(
419 mat_D_ptr, Sev::inform);
420 pip->getOpDomainRhsPipeline().push_back(
422 pip->getOpDomainRhsPipeline().push_back(
424 mat_strain_ptr, mat_stress_ptr, mat_D_ptr));
426 pip->getOpDomainRhsPipeline().push_back(
428 [](
double,
double,
double) constexpr {
return -1; }));
433 pip->getOpDomainRhsPipeline(), mField,
"U", Sev::inform);
439 pip->getOpBoundaryRhsPipeline(), mField,
"U", -1, Sev::inform);
442 pip->getOpBoundaryLhsPipeline(), mField,
"U", Sev::verbose);
449 static boost::shared_ptr<SetUpSchur>
462 auto solver = pip->createKSP();
463 CHKERR KSPSetFromOptions(solver);
465 auto dm =
simple->getDM();
469 auto set_essential_bc = [&]() {
474 auto pre_proc_rhs = boost::make_shared<FEMethod>();
475 auto post_proc_rhs = boost::make_shared<FEMethod>();
476 auto post_proc_lhs = boost::make_shared<FEMethod>();
478 auto get_pre_proc_hook = [&]() {
482 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
484 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
488 post_proc_rhs, 1.)();
493 auto get_post_proc_hook_lhs = [
this, post_proc_lhs]() {
497 post_proc_lhs, 1.)();
502 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
503 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
505 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
506 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
507 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
511 auto setup_and_solve = [&]() {
513 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
514 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp";
516 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp <= Done";
517 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve";
519 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve <= Done";
526 CHKERR set_essential_bc();
530 CHKERR schur_ptr->setUp(solver);
536 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
537 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
543 fieldEvalCoords.data(), 1e-12,
simple->getProblemName(),
544 simple->getDomainFEName(), fieldEvalData, mField.get_comm_rank(),
548 fieldEvalCoords.data(), 1e-12,
simple->getProblemName(),
549 simple->getDomainFEName(), fieldEvalData, mField.get_comm_rank(),
553 if (vectorFieldPtr->size1()) {
554 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vectorFieldPtr);
557 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1);
560 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1)
561 << " U_Z: " << t_disp(2);
576 auto det_ptr = boost::make_shared<VectorDouble>();
577 auto jac_ptr = boost::make_shared<MatrixDouble>();
578 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
580 pip->getDomainRhsFE().reset();
581 pip->getDomainLhsFE().reset();
582 pip->getBoundaryRhsFE().reset();
583 pip->getBoundaryLhsFE().reset();
587 auto post_proc_mesh = boost::make_shared<moab::Core>();
588 auto post_proc_begin = boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
589 mField, post_proc_mesh);
590 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
591 mField, post_proc_mesh);
594 auto calculate_stress_ops = [&](
auto &pip) {
596 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
597 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
598 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
601 auto mat_D_ptr = boost::make_shared<MatrixDouble>();
606 mat_strain_ptr, mat_stress_ptr, mat_D_ptr));
607 auto u_ptr = boost::make_shared<MatrixDouble>();
609 auto x_ptr = boost::make_shared<MatrixDouble>();
612 return boost::make_tuple(u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr);
615 auto post_proc_domain = [&](
auto post_proc_mesh) {
617 boost::make_shared<PostProcEleDomain>(mField, post_proc_mesh);
620 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
621 calculate_stress_ops(post_proc_fe->getOpPtrVector());
623 post_proc_fe->getOpPtrVector().push_back(
627 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
631 {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}},
635 {{
"STRAIN", mat_strain_ptr}, {
"STRESS", mat_stress_ptr}}
643 auto post_proc_boundary = [&](
auto post_proc_mesh) {
645 boost::make_shared<PostProcEleBdy>(mField, post_proc_mesh);
647 post_proc_fe->getOpPtrVector(), {},
"GEOMETRY");
651 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
652 calculate_stress_ops(op_loop_side->getOpPtrVector());
653 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
654 auto mat_traction_ptr = boost::make_shared<MatrixDouble>();
655 post_proc_fe->getOpPtrVector().push_back(
661 post_proc_fe->getOpPtrVector().push_back(
665 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
669 {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}, {
"T", mat_traction_ptr}},
673 {{
"STRAIN", mat_strain_ptr}, {
"STRESS", mat_stress_ptr}}
681 PetscBool post_proc_skin_only = PETSC_FALSE;
683 post_proc_skin_only = PETSC_TRUE;
685 &post_proc_skin_only, PETSC_NULL);
687 if (post_proc_skin_only == PETSC_FALSE) {
688 pip->getDomainRhsFE() = post_proc_domain(post_proc_mesh);
690 pip->getBoundaryRhsFE() = post_proc_boundary(post_proc_mesh);
694 post_proc_begin->getFEMethod());
695 CHKERR pip->loopFiniteElements();
697 post_proc_end->getFEMethod());
699 CHKERR post_proc_end->writeFile(
"out_elastic.h5m");
710 pip->getDomainRhsFE().reset();
711 pip->getDomainLhsFE().reset();
712 pip->getBoundaryRhsFE().reset();
713 pip->getBoundaryLhsFE().reset();
720 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
722 pip->getOpBoundaryRhsPipeline(), {},
"GEOMETRY");
724 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
725 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
726 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
728 pip->getOpDomainRhsPipeline().push_back(
731 pip->getOpDomainRhsPipeline().push_back(
734 auto mat_D_ptr = boost::make_shared<MatrixDouble>();
736 mat_D_ptr, Sev::verbose);
737 pip->getOpDomainRhsPipeline().push_back(
739 mat_strain_ptr, mat_stress_ptr, mat_D_ptr));
741 pip->getOpDomainRhsPipeline().push_back(
744 pip->getOpBoundaryRhsPipeline().push_back(
746 mat_strain_ptr, mat_stress_ptr, mat_D_ptr));
748 pip->getOpDomainRhsPipeline(), mField,
"U", Sev::verbose);
750 pip->getOpBoundaryRhsPipeline(), mField,
"U", -1, Sev::verbose);
752 auto dm =
simple->getDM();
754 CHKERR VecSetDM(res, PETSC_NULL);
756 pip->getDomainRhsFE()->f = res;
757 pip->getBoundaryRhsFE()->f = res;
759 CHKERR VecZeroEntries(res);
762 CHKERR pip->loopFiniteElements();
765 CHKERR VecGhostUpdateBegin(res, ADD_VALUES, SCATTER_REVERSE);
766 CHKERR VecGhostUpdateEnd(res, ADD_VALUES, SCATTER_REVERSE);
767 CHKERR VecAssemblyBegin(res);
768 CHKERR VecAssemblyEnd(res);
770 auto zero_residual_at_constrains = [&]() {
772 auto fe_post_proc_ptr = boost::make_shared<FEMethod>();
773 auto get_post_proc_hook_rhs = [&]() {
776 mField, fe_post_proc_ptr, res)();
778 mField, fe_post_proc_ptr, 0, res)();
782 fe_post_proc_ptr->postProcessHook = get_post_proc_hook_rhs;
787 CHKERR zero_residual_at_constrains();
790 CHKERR VecNorm(res, NORM_2, &nrm2);
792 MOFEM_LOG_C(
"WORLD", Sev::inform,
"residual = %3.4e\n", nrm2);
794 PetscBool test = PETSC_FALSE;
796 if (test == PETSC_TRUE) {
798 auto post_proc_residual = [&](
auto dm,
auto f_res,
auto out_name) {
801 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(mField);
803 auto u_vec = boost::make_shared<MatrixDouble>();
804 post_proc_fe->getOpPtrVector().push_back(
806 post_proc_fe->getOpPtrVector().push_back(
810 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
822 post_proc_fe->writeFile(out_name);
826 CHKERR post_proc_residual(
simple->getDM(), res,
"res.h5m");
828 constexpr
double eps = 1e-8;
831 "Residual is not zero");
838 static char help[] =
"...\n\n";
840 int main(
int argc,
char *argv[]) {
843 const char param_file[] =
"param_file.petsc";
846 auto core_log = logging::core::get();
858 DMType dm_name =
"DMMOFEM";
860 DMType dm_name_mg =
"DMMOFEM_MG";
890 "Is expected that schur matrix is not allocated. This is "
891 "possible only is PC is set up twice");
920 CHKERR KSPGetPC(solver, &pc);
921 PetscBool is_pcfs = PETSC_FALSE;
922 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
927 "Is expected that schur matrix is not allocated. This is "
928 "possible only is PC is set up twice");
935 CHKERR MatSetDM(S, PETSC_NULL);
937 CHKERR MatSetOption(S, MAT_SYMMETRIC, PETSC_TRUE);
945 CHKERR KSPGetDM(solver, &solver_dm);
946 CHKERR DMSetMatType(solver_dm, MATSHELL);
963 CHKERR mField.get_moab().get_entities_by_dimension(
simple->getMeshset(),
965 CHKERR mField.get_moab().get_entities_by_handle(
simple->getMeshset(),
967 subEnts = subtract(subEnts, volEnts);
975 auto create_dm = [&](
const char *name,
auto &ents,
auto dm_type) {
976 auto dm =
createDM(mField.get_comm(), dm_type);
977 auto create_dm_imp = [&]() {
982 auto sub_ents_ptr = boost::make_shared<Range>(ents);
989 "Error in creating schurDM. It is possible that schurDM is "
994 schurDM = create_dm(
"SCHUR", subEnts,
"DMMOFEM_MG");
995 blockDM = create_dm(
"BLOCK", volEnts,
"DMMOFEM");
999 auto get_nested_mat_data = [&]() {
1000 auto block_mat_data =
1005 simple->getDomainFEName(),
1015 {schurDM, blockDM}, block_mat_data,
1017 {
"U"}, {boost::make_shared<Range>(volEnts)}
1022 auto nested_mat_data = get_nested_mat_data();
1040 {
"U"}, {boost::make_shared<Range>(
volEnts)}, ao_up,
S,
true,
true));
1044 {
"U"}, {boost::make_shared<Range>(
volEnts)}, ao_up,
S,
true,
true));
1046 auto pre_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
1047 auto post_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
1049 pre_proc_schur_lhs_ptr->preProcessHook = [
this]() {
1054 MOFEM_LOG(
"TIMER", Sev::inform) <<
"Lhs Assemble Begin";
1058 post_proc_schur_lhs_ptr->postProcessHook = [
this, post_proc_schur_lhs_ptr,
1061 CHKERR MatAssemblyBegin(
S, MAT_FINAL_ASSEMBLY);
1062 CHKERR MatAssemblyEnd(
S, MAT_FINAL_ASSEMBLY);
1064 mField, post_proc_schur_lhs_ptr, 1,
S, ao_up)();
1065 MOFEM_LOG(
"TIMER", Sev::inform) <<
"Lhs Assemble End";
1070 ksp_ctx_ptr->getPreProcSetOperators().push_front(pre_proc_schur_lhs_ptr);
1071 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_schur_lhs_ptr);
1082 CHKERR PCFieldSplitSetIS(pc, NULL, vol_is);
1083 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER,
S);
1090 auto get_pc = [](
auto ksp) {
1092 CHKERR KSPGetPC(ksp, &pc_raw);
1103 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULL, &subksp);
1106 auto set_pc_p_mg = [](
auto dm,
auto pc,
auto S) {
1109 PetscBool same = PETSC_FALSE;
1110 PetscObjectTypeCompare((PetscObject)pc, PCMG, &same);
1114 CHKERR PCSetFromOptions(pc);
1121 CHKERR PetscFree(subksp);
1126 boost::shared_ptr<SetUpSchur>
1128 return boost::shared_ptr<SetUpSchur>(
new SetUpSchurImpl(m_field));