46 std::pair<boost::shared_ptr<PostProcEle>,
47 boost::shared_ptr<SkinPostProcEle>>
52 std::array<double, SPACE_DIM> pass_field_eval_coords,
53 boost::shared_ptr<SetPtsData> pass_field_eval_data,
54 boost::shared_ptr<MatrixDouble> vec_field_ptr)
55 : dM(dm), uXScatter(ux_scatter), uYScatter(uy_scatter),
56 uZScatter(uz_scatter), fieldEvalCoords(pass_field_eval_coords),
57 fieldEvalData(pass_field_eval_data), vecFieldPtr(vec_field_ptr) {
58 postProcFe = pair_post_proc_fe.first;
59 skinPostProcFe = pair_post_proc_fe.second;
76 fieldEvalCoords.data(), 1e-12,
simple->getProblemName(),
77 simple->getDomainFEName(), fieldEvalData,
83 fieldEvalCoords.data(), 1e-12,
simple->getProblemName(),
84 simple->getDomainFEName(), fieldEvalData,
89 if (vecFieldPtr->size1()) {
90 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vecFieldPtr);
93 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1);
96 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1)
97 <<
" U_Z: " << t_disp(2);
102 auto make_vtk = [&]() {
107 CHKERR postProcFe->writeFile(
"out_incomp_elasticity" +
108 boost::lexical_cast<std::string>(ts_step) +
111 if (skinPostProcFe) {
114 CHKERR skinPostProcFe->writeFile(
115 "out_skin_incomp_elasticity_" +
116 boost::lexical_cast<std::string>(ts_step) +
".h5m");
121 auto print_max_min = [&](
auto &tuple,
const std::string msg) {
123 CHKERR VecScatterBegin(std::get<1>(tuple), ts_u, std::get<0>(tuple),
124 INSERT_VALUES, SCATTER_FORWARD);
125 CHKERR VecScatterEnd(std::get<1>(tuple), ts_u, std::get<0>(tuple),
126 INSERT_VALUES, SCATTER_FORWARD);
128 CHKERR VecMax(std::get<0>(tuple), PETSC_NULL, &max);
129 CHKERR VecMin(std::get<0>(tuple), PETSC_NULL, &min);
131 "%s time %3.4e min %3.4e max %3.4e", msg.c_str(), ts_t, min,
137 CHKERR print_max_min(uXScatter,
"Ux");
138 CHKERR print_max_min(uYScatter,
"Uy");
140 CHKERR print_max_min(uZScatter,
"Uz");
166 return MatSetValues<AssemblyTypeSelector<AT>>(
167 op_ptr->
getKSPA(), row_data, col_data,
m, ADD_VALUES);
189 return MatSetValues<AssemblyTypeSelector<AT>>(
190 op_ptr->
getKSPB(), row_data, col_data,
m, ADD_VALUES);
198 inline static double mu;
227 boost::shared_ptr<MatrixDouble> strain_ptr,
228 boost::shared_ptr<VectorDouble> pressure_ptr)
230 stressPtr(stress_ptr), strainPtr(strain_ptr),
231 pressurePtr(pressure_ptr) {}
244 const size_t nb_gauss_pts = getGaussPts().size2();
246 stressPtr->resize((DIM * (DIM + 1)) / 2, nb_gauss_pts);
247 auto t_stress = getFTensor2SymmetricFromMat<DIM>(*(stressPtr));
248 auto t_strain = getFTensor2SymmetricFromMat<DIM>(*(strainPtr));
251 const double l_mu = mU;
253 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
255 t_stress(
i,
j) = t_pressure *
t_kd(
i,
j) + 2. * l_mu * t_strain(
i,
j);
276 CHKERR createCommonData();
300 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
301 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
302 PetscInt choice_base_value = AINSWORTH;
304 LASBASETOPT, &choice_base_value, PETSC_NULL);
307 switch (choice_base_value) {
310 MOFEM_LOG(
"INCOMP_ELASTICITY", Sev::inform)
311 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
315 MOFEM_LOG(
"INCOMP_ELASTICITY", Sev::inform)
316 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
351 auto project_ho_geometry = [&]() {
353 return mField.loop_dofs(
"GEOMETRY", ent_method);
355 CHKERR project_ho_geometry();
364 auto get_options = [&]() {
371 MOFEM_LOG(
"INCOMP_ELASTICITY", Sev::inform)
373 MOFEM_LOG(
"INCOMP_ELASTICITY", Sev::inform)
377 const double lambda_denom =
397 auto time_scale = boost::make_shared<TimeScale>();
413 pipeline_mng->getOpBoundaryRhsPipeline(), {NOSPACE},
"GEOMETRY");
416 pipeline_mng->getOpBoundaryRhsPipeline(), mField,
"U", {time_scale},
417 "FORCE", Sev::inform);
421 pipeline_mng->getOpDomainRhsPipeline(), mField,
"U", {time_scale},
422 "BODY_FORCE", Sev::inform);
425 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_X",
427 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Y",
429 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Z",
432 simple->getProblemName(),
"U");
449 auto add_domain_base_ops = [&](
auto &pip) {
456 auto add_domain_ops_lhs = [&](
auto &pip) {
474 auto mat_D_ptr = boost::make_shared<MatrixDouble>();
484 auto t_mat = getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*mat_D_ptr);
489 [](
const double,
const double,
const double) constexpr {
return -1.; },
491 pip.push_back(
new OpGradSymTensorGrad(
"U",
"U", mat_D_ptr));
497 pip.push_back(
new OpMassPressure(
"P",
"P", get_lambda_reciprocal));
503 pip.push_back(
new OpMassPressureStab(
504 "P",
"P", [eps_stab](
double,
double,
double) {
return eps_stab; }));
509 auto add_domain_ops_rhs = [&](
auto &pip) {
520 AT>::LinearForm<GAUSS>::OpBaseTimesScalar<1>;
524 auto pressure_ptr = boost::make_shared<VectorDouble>();
527 auto div_u_ptr = boost::make_shared<VectorDouble>();
531 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
535 auto strain_ptr = boost::make_shared<MatrixDouble>();
545 pip.push_back(
new OpDomainGradTimesTensor(
"U", strain_ptr, get_four_mu));
547 pip.push_back(
new OpDivDeltaUTimesP(
"U", pressure_ptr, minus_one));
549 pip.push_back(
new OpBaseTimesScalarValues(
"P", div_u_ptr, minus_one));
555 pip.push_back(
new OpBaseTimesScalarValues(
"P", pressure_ptr,
556 get_lambda_reciprocal));
562 CHKERR add_domain_base_ops(pip_mng->getOpDomainLhsPipeline());
563 CHKERR add_domain_base_ops(pip_mng->getOpDomainRhsPipeline());
564 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
565 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
567 CHKERR pip_mng->setDomainRhsIntegrationRule(integration_rule_vol);
568 CHKERR pip_mng->setDomainLhsIntegrationRule(integration_rule_vol);
576 static boost::shared_ptr<SetUpSchur>
591 auto set_section_monitor = [&](
auto solver) {
594 CHKERR TSGetSNES(solver, &snes);
595 PetscViewerAndFormat *vf;
596 CHKERR PetscViewerAndFormatCreate(PETSC_VIEWER_STDOUT_WORLD,
597 PETSC_VIEWER_DEFAULT, &vf);
600 (
MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
void *))SNESMonitorFields,
605 auto scatter_create = [&](
auto D,
auto coeff) {
607 CHKERR is_manager->isCreateProblemFieldAndRank(
simple->getProblemName(),
608 ROW,
"U", coeff, coeff, is);
610 CHKERR ISGetLocalSize(is, &loc_size);
612 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &
v);
614 CHKERR VecScatterCreate(
D, is,
v, PETSC_NULL, &scatter);
619 auto create_post_process_elements = [&]() {
620 auto pp_fe = boost::make_shared<PostProcEle>(mField);
621 auto &pip = pp_fe->getOpPtrVector();
623 auto push_vol_ops = [
this](
auto &pip) {
631 auto push_vol_post_proc_ops = [
this](
auto &pp_fe,
auto &&p) {
634 auto &pip = pp_fe->getOpPtrVector();
638 auto x_ptr = boost::make_shared<MatrixDouble>();
641 auto u_ptr = boost::make_shared<MatrixDouble>();
644 auto pressure_ptr = boost::make_shared<VectorDouble>();
647 auto div_u_ptr = boost::make_shared<VectorDouble>();
651 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
655 auto strain_ptr = boost::make_shared<MatrixDouble>();
658 auto stress_ptr = boost::make_shared<MatrixDouble>();
660 mu, stress_ptr, strain_ptr, pressure_ptr));
666 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
668 {{
"P", pressure_ptr}},
670 {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}},
674 {{
"STRAIN", strain_ptr}, {
"STRESS", stress_ptr}}
683 auto vol_post_proc = [
this, push_vol_post_proc_ops, push_vol_ops]() {
684 PetscBool post_proc_vol = PETSC_FALSE;
686 &post_proc_vol, PETSC_NULL);
687 if (post_proc_vol == PETSC_FALSE)
688 return boost::shared_ptr<PostProcEle>();
689 auto pp_fe = boost::make_shared<PostProcEle>(mField);
691 push_vol_post_proc_ops(pp_fe, push_vol_ops(pp_fe->getOpPtrVector())),
692 "push_vol_post_proc_ops");
696 auto skin_post_proc = [
this, push_vol_post_proc_ops, push_vol_ops]() {
697 PetscBool post_proc_skin = PETSC_TRUE;
699 &post_proc_skin, PETSC_NULL);
700 if (post_proc_skin == PETSC_FALSE)
701 return boost::shared_ptr<SkinPostProcEle>();
704 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
707 pp_fe->getOpPtrVector().push_back(op_side);
709 pp_fe, push_vol_ops(op_side->getOpPtrVector())),
710 "push_vol_post_proc_ops");
714 return std::make_pair(vol_post_proc(), skin_post_proc());
717 boost::shared_ptr<SetPtsData> field_eval_data;
718 boost::shared_ptr<MatrixDouble> vector_field_ptr;
720 std::array<double, SPACE_DIM> field_eval_coords;
723 field_eval_coords.data(), &coords_dim,
727 vector_field_ptr = boost::make_shared<MatrixDouble>();
732 field_eval_data,
simple->getDomainFEName());
735 field_eval_data,
simple->getDomainFEName());
738 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
739 auto no_rule = [](
int,
int,
int) {
return -1; };
740 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
741 field_eval_fe_ptr->getRuleHook = no_rule;
742 field_eval_fe_ptr->getOpPtrVector().push_back(
746 auto set_time_monitor = [&](
auto dm,
auto solver) {
748 boost::shared_ptr<MonitorIncompressible> monitor_ptr(
750 create_post_process_elements(), uXScatter,
751 uYScatter, uZScatter, field_eval_coords,
752 field_eval_data, vector_field_ptr));
753 boost::shared_ptr<ForcesAndSourcesCore>
null;
755 monitor_ptr,
null,
null);
759 auto set_essential_bc = [&]() {
763 auto pre_proc_ptr = boost::make_shared<FEMethod>();
764 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
767 auto time_scale = boost::make_shared<TimeScale>();
770 mField, pre_proc_ptr, {time_scale},
false);
771 post_proc_rhs_ptr->postProcessHook =
774 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
775 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
776 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
780 auto set_schur_pc = [&](
auto solver) {
782 CHKERR TSGetSNES(solver, &snes);
784 CHKERR SNESGetKSP(snes, &ksp);
786 CHKERR KSPGetPC(ksp, &pc);
787 PetscBool is_pcfs = PETSC_FALSE;
788 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
789 boost::shared_ptr<SetUpSchur> schur_ptr;
798 auto pre_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
799 auto post_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
800 pre_proc_schur_lhs_ptr->preProcessHook = [pre_proc_schur_lhs_ptr]() {
802 MOFEM_LOG(
"INCOMP_ELASTICITY", Sev::verbose) <<
"Lhs Zero matrices";
803 CHKERR MatZeroEntries(pre_proc_schur_lhs_ptr->A);
804 CHKERR MatZeroEntries(pre_proc_schur_lhs_ptr->B);
807 post_proc_schur_lhs_ptr->postProcessHook = [
this,
808 post_proc_schur_lhs_ptr]() {
810 MOFEM_LOG(
"INCOMP_ELASTICITY", Sev::verbose) <<
"Lhs Assemble Begin";
811 *(post_proc_schur_lhs_ptr->matAssembleSwitch) =
false;
812 CHKERR MatAssemblyBegin(post_proc_schur_lhs_ptr->A, MAT_FINAL_ASSEMBLY);
813 CHKERR MatAssemblyEnd(post_proc_schur_lhs_ptr->A, MAT_FINAL_ASSEMBLY);
815 mField, post_proc_schur_lhs_ptr, 1.,
818 CHKERR MatAssemblyBegin(post_proc_schur_lhs_ptr->B, MAT_FINAL_ASSEMBLY);
819 CHKERR MatAssemblyEnd(post_proc_schur_lhs_ptr->B, MAT_FINAL_ASSEMBLY);
820 CHKERR MatAXPY(post_proc_schur_lhs_ptr->B, 1, post_proc_schur_lhs_ptr->A,
821 SAME_NONZERO_PATTERN);
822 MOFEM_LOG(
"INCOMP_ELASTICITY", Sev::verbose) <<
"Lhs Assemble End";
825 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_schur_lhs_ptr);
826 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_schur_lhs_ptr);
828 if (is_pcfs == PETSC_TRUE) {
831 CHK_MOAB_THROW(schur_ptr->setUp(solver),
"setup schur preconditioner");
833 auto set_pcfieldsplit_preconditioned_ts = [&](
auto solver) {
835 auto bc_mng = mField.getInterface<
BcManager>();
836 auto name_prb =
simple->getProblemName();
839 name_prb,
ROW,
"P", 0, 1, is_p);
840 CHKERR PCFieldSplitSetIS(pc, PETSC_NULL, is_p);
844 "set pcfieldsplit preconditioned");
846 return boost::make_tuple(schur_ptr,
A, B);
849 return boost::make_tuple(schur_ptr,
A, B);
852 auto dm =
simple->getDM();
855 uXScatter = scatter_create(
D, 0);
856 uYScatter = scatter_create(
D, 1);
858 uZScatter = scatter_create(
D, 2);
862 CHKERR set_essential_bc();
864 auto solver = pip_mng->createTSIM();
865 CHKERR TSSetFromOptions(solver);
867 CHKERR set_section_monitor(solver);
868 CHKERR set_time_monitor(dm, solver);
869 auto [schur_pc_ptr,
A, B] = set_schur_pc(solver);
871 CHKERR TSSetSolution(solver,
D);
873 CHKERR TSSolve(solver, NULL);
883 static char help[] =
"...\n\n";
885 int main(
int argc,
char *argv[]) {
888 const char param_file[] =
"param_file.petsc";
892 auto core_log = logging::core::get();
894 LogManager::createSink(LogManager::getStrmWorld(),
"INCOMP_ELASTICITY"));
895 LogManager::setLog(
"INCOMP_ELASTICITY");
901 DMType dm_name =
"DMMOFEM";
956 auto dm =
simple->getDM();
959 CHKERR TSGetSNES(solver, &snes);
961 CHKERR SNESGetKSP(snes, &ksp);
963 CHKERR KSPGetPC(ksp, &pc);
965 MOFEM_LOG(
"INCOMP_ELASTICITY", Sev::inform) <<
"Setup Schur pc";
969 "Is expected that schur matrix is not allocated. This is "
970 "possible only is PC is set up twice");
973 auto create_sub_dm = [&]() {
975 auto set_up = [&]() {
988 subDM = create_sub_dm();
996 pip->getOpDomainLhsPipeline().push_back(
999 auto pre_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
1000 auto post_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
1002 pre_proc_schur_lhs_ptr->preProcessHook = [
this]() {
1008 post_proc_schur_lhs_ptr->postProcessHook = [
this, ao_up,
1009 post_proc_schur_lhs_ptr]() {
1012 auto print_mat_norm = [
this](
auto a, std::string prefix) {
1015 CHKERR MatNorm(
a, NORM_FROBENIUS, &nrm);
1016 MOFEM_LOG(
"INCOMP_ELASTICITY", Sev::verbose)
1017 << prefix <<
" norm = " << nrm;
1021 CHKERR MatAssemblyBegin(
S, MAT_FINAL_ASSEMBLY);
1022 CHKERR MatAssemblyEnd(
S, MAT_FINAL_ASSEMBLY);
1024 mField, post_proc_schur_lhs_ptr, 1,
S, ao_up)();
1027 CHKERR print_mat_norm(
S,
"S");
1033 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_schur_lhs_ptr);
1034 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_schur_lhs_ptr);
1038 simple->getProblemName(),
ROW,
"P", 0, 1, is_p);
1039 CHKERR PCFieldSplitSetIS(pc, NULL, is_p);
1040 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER,
S);
1045 boost::shared_ptr<SetUpSchur>
1047 return boost::shared_ptr<SetUpSchur>(
new SetUpSchurImpl(m_field));