v0.16.3
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | List of all members
SetUpSchurImpl Struct Reference
Inheritance diagram for SetUpSchurImpl:
[legend]
Collaboration diagram for SetUpSchurImpl:
[legend]

Public Member Functions

 SetUpSchurImpl (MoFEM::Interface &m_field)
 
virtual ~SetUpSchurImpl ()=default
 
MoFEMErrorCode setUp (SmartPetscObj< KSP >)
 
 SetUpSchurImpl (MoFEM::Interface &m_field, SmartPetscObj< DM > sub_dm, SmartPetscObj< IS > field_split_is, SmartPetscObj< AO > ao_up)
 
virtual ~SetUpSchurImpl ()
 
MoFEMErrorCode setUp (TS solver)
 
MoFEMErrorCode preProc ()
 
MoFEMErrorCode postProc ()
 
 SetUpSchurImpl (MoFEM::Interface &m_field)
 
virtual ~SetUpSchurImpl ()
 
MoFEMErrorCode setUp (SmartPetscObj< TS > solver)
 
 SetUpSchurImpl (MoFEM::Interface &m_field)
 
virtual ~SetUpSchurImpl ()
 
MoFEMErrorCode setUp (SmartPetscObj< TS > solver)
 
 SetUpSchurImpl (MoFEM::Interface &m_field)
 
virtual ~SetUpSchurImpl ()=default
 
MoFEMErrorCode setUp (SmartPetscObj< KSP > solver)
 

Private Member Functions

MoFEMErrorCode createSubDM ()
 
MoFEMErrorCode setOperator ()
 
MoFEMErrorCode setPC (PC pc)
 
MoFEMErrorCode setDiagonalPC (PC pc)
 
MoFEMErrorCode setOperator ()
 
MoFEMErrorCode setPC (PC pc)
 
SmartPetscObj< DM > createSubDM ()
 
MoFEMErrorCode setEntities ()
 
MoFEMErrorCode createSubDM ()
 
MoFEMErrorCode setOperator ()
 
MoFEMErrorCode setPC (PC pc)
 
MoFEMErrorCode setDiagonalPC (PC pc)
 

Private Attributes

MoFEM::Interface & mField
 
SmartPetscObj< Mat > S
 
SmartPetscObj< DM > subDM
 field split sub dm
 
SmartPetscObj< IS > fieldSplitIS
 IS for split Schur block.
 
SmartPetscObj< AO > aoSchur
 
SmartPetscObj< DM > schurDM
 
SmartPetscObj< DM > blockDM
 
Range volEnts
 
Range subEnts
 

Additional Inherited Members

- Static Public Member Functions inherited from SetUpSchur
static boost::shared_ptr< SetUpSchur > createSetUpSchur (MoFEM::Interface &m_field)
 
static boost::shared_ptr< SetUpSchur > createSetUpSchur (MoFEM::Interface &m_field, SmartPetscObj< DM > sub_dm, SmartPetscObj< IS > field_split_it, SmartPetscObj< AO > ao_map)
 Create data structure for handling Schur complement.
 
static boost::shared_ptr< SetUpSchur > createSetUpSchur (MoFEM::Interface &m_field)
 
static boost::shared_ptr< SetUpSchur > createSetUpSchur (MoFEM::Interface &m_field)
 
static boost::shared_ptr< SetUpSchur > createSetUpSchur (MoFEM::Interface &m_field)
 
- Protected Member Functions inherited from SetUpSchur
 SetUpSchur ()=default
 
virtual ~SetUpSchur ()=default
 
 SetUpSchur ()=default
 
 SetUpSchur ()=default
 
 SetUpSchur ()=default
 
 SetUpSchur ()=default
 

Detailed Description

Examples
mofem/atom_tests/test_broken_space.cpp, mofem/tutorials/adv-0_plasticity/plastic.cpp, and mofem/tutorials/vec-10_elasticity_schur/schur_elastic.cpp.

Definition at line 552 of file test_broken_space.cpp.

Constructor & Destructor Documentation

◆ SetUpSchurImpl() [1/5]

SetUpSchurImpl::SetUpSchurImpl ( MoFEM::Interface &  m_field)
inline

Definition at line 554 of file test_broken_space.cpp.

554: SetUpSchur(), mField(m_field) {}
MoFEM::Interface & mField
SetUpSchur()=default

◆ ~SetUpSchurImpl() [1/5]

virtual SetUpSchurImpl::~SetUpSchurImpl ( )
virtualdefault

◆ SetUpSchurImpl() [2/5]

SetUpSchurImpl::SetUpSchurImpl ( MoFEM::Interface &  m_field,
SmartPetscObj< DM >  sub_dm,
SmartPetscObj< IS >  field_split_is,
SmartPetscObj< AO >  ao_up 
)
inline

Definition at line 1675 of file plastic.cpp.

1677 : SetUpSchur(), mField(m_field), subDM(sub_dm),
1678 fieldSplitIS(field_split_is), aoSchur(ao_up) {
1679 if (S) {
1681 "Is expected that schur matrix is not "
1682 "allocated. This is "
1683 "possible only is if PC is set up twice");
1684 }
1685 }
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
SmartPetscObj< DM > subDM
field split sub dm
Definition plastic.cpp:1696
SmartPetscObj< Mat > S
SmartPetscObj< AO > aoSchur
Definition plastic.cpp:1698
SmartPetscObj< IS > fieldSplitIS
IS for split Schur block.
Definition plastic.cpp:1697

◆ ~SetUpSchurImpl() [2/5]

virtual SetUpSchurImpl::~SetUpSchurImpl ( )
inlinevirtual

Definition at line 1686 of file plastic.cpp.

1686{ S.reset(); }

◆ SetUpSchurImpl() [3/5]

SetUpSchurImpl::SetUpSchurImpl ( MoFEM::Interface &  m_field)
inline

Definition at line 1013 of file contact.cpp.

1013: SetUpSchur(), mField(m_field) {}

◆ ~SetUpSchurImpl() [3/5]

virtual SetUpSchurImpl::~SetUpSchurImpl ( )
inlinevirtual

Definition at line 1015 of file contact.cpp.

1015{}

◆ SetUpSchurImpl() [4/5]

SetUpSchurImpl::SetUpSchurImpl ( MoFEM::Interface &  m_field)
inline

Definition at line 996 of file incompressible_elasticity.cpp.

996: SetUpSchur(), mField(m_field) {}

◆ ~SetUpSchurImpl() [4/5]

virtual SetUpSchurImpl::~SetUpSchurImpl ( )
inlinevirtual

Definition at line 997 of file incompressible_elasticity.cpp.

997{ S.reset(); }

◆ SetUpSchurImpl() [5/5]

SetUpSchurImpl::SetUpSchurImpl ( MoFEM::Interface &  m_field)
inline

Definition at line 180 of file schur_elastic.cpp.

180 : SetUpSchur(), mField(m_field) {
181 if (S) {
184 "Is expected that schur matrix is not allocated. This is "
185 "possible only is if PC is set up twice");
186 }
187 }

◆ ~SetUpSchurImpl() [5/5]

virtual SetUpSchurImpl::~SetUpSchurImpl ( )
virtualdefault

Member Function Documentation

◆ createSubDM() [1/3]

MoFEMErrorCode SetUpSchurImpl::createSubDM ( )
private
Examples
mofem/tutorials/vec-10_elasticity_schur/schur_elastic.cpp.

Definition at line 1107 of file contact.cpp.

1107 {
1109 auto simple = mField.getInterface<Simple>();
1110
1111 auto create_dm = [&](const char *name, const char *field_name, auto dm_type) {
1112 auto dm = createDM(mField.get_comm(), dm_type);
1113 auto create_dm_imp = [&]() {
1115 CHKERR DMMoFEMCreateSubDM(dm, simple->getDM(), name);
1116 CHKERR DMMoFEMSetSquareProblem(dm, PETSC_TRUE);
1117 CHKERR DMMoFEMAddElement(dm, simple->getDomainFEName());
1120 CHKERR DMSetUp(dm);
1122 };
1124 create_dm_imp(),
1125 "Error in creating schurDM. It is possible that schurDM is "
1126 "already created");
1127 return dm;
1128 };
1129
1130 // Note: here we can make block with bubbles of "U" and "SIGMA" fields. See
1131 // vec-0_elasticity where bubbles are added.
1132
1133 schurDM = create_dm("SCHUR", "U", "DMMOFEM_MG");
1134 blockDM = create_dm("BLOCK", "SIGMA", "DMMOFEM");
1135
1136 if constexpr (AT == AssemblyType::BLOCK_SCHUR) {
1137
1138 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
1139 auto block_mat_data = createBlockMatStructure(
1140 simple->getDM(),
1141
1142 {{
1143
1144 simple->getDomainFEName(),
1145
1146 {
1147
1148 {"U", "U"}, {"SIGMA", "U"}, {"U", "SIGMA"}, {"SIGMA", "SIGMA"}
1149
1150 }}}
1151
1152 );
1153
1155
1156 {schur_dm, block_dm}, block_mat_data,
1157
1158 {"SIGMA"}, {nullptr}, true
1159
1160 );
1161 };
1162
1163 auto nested_mat_data = get_nested_mat_data(schurDM, blockDM);
1164 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
1165
1166 } else {
1167 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1168 "Only BLOCK_SCHUR is implemented");
1169 }
1170
1172}
std::string name
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
Definition DMMoFEM.cpp:244
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:517
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:479
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:267
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:309
boost::shared_ptr< BlockStructure > createBlockMatStructure(DM dm, SchurFEOpsFEandFields schur_fe_op_vec)
Create block matrix structure.
Definition Schur.cpp:2415
boost::shared_ptr< NestSchurData > createSchurNestedMatrixStruture(std::pair< SmartPetscObj< DM >, SmartPetscObj< DM > > dms, boost::shared_ptr< BlockStructure > block_mat_data_ptr, std::vector< std::string > fields_names, std::vector< boost::shared_ptr< Range > > field_ents, bool add_preconditioner_block)
Create structure of nested matrix [A11 A10; A01 A00].
Definition Schur.cpp:3667
MoFEMErrorCode DMMoFEMSetNestSchurData(DM dm, boost::shared_ptr< NestSchurData >)
Definition DMMoFEM.cpp:1584
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
constexpr auto field_name
virtual MPI_Comm & get_comm() const =0
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
SmartPetscObj< DM > schurDM
Definition contact.cpp:1028
SmartPetscObj< DM > blockDM
Definition contact.cpp:1029
constexpr AssemblyType AT

◆ createSubDM() [2/3]

SmartPetscObj< DM > SetUpSchurImpl::createSubDM ( )
private

◆ createSubDM() [3/3]

MoFEMErrorCode SetUpSchurImpl::createSubDM ( )
private

◆ postProc()

MoFEMErrorCode SetUpSchurImpl::postProc ( )

◆ preProc()

MoFEMErrorCode SetUpSchurImpl::preProc ( )

◆ setDiagonalPC() [1/2]

MoFEMErrorCode SetUpSchurImpl::setDiagonalPC ( PC  pc)
private
Examples
mofem/tutorials/vec-10_elasticity_schur/schur_elastic.cpp.

Definition at line 1257 of file contact.cpp.

1257 {
1259 KSP *subksp;
1260 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
1261 auto get_pc = [](auto ksp) {
1262 PC pc_raw;
1263 CHKERR KSPGetPC(ksp, &pc_raw);
1264 return SmartPetscObj<PC>(pc_raw, true); // bump reference
1265 };
1266 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
1267
1268 auto set_pc_p_mg = [](auto dm, auto pc, auto S) {
1270 CHKERR PCSetDM(pc, dm);
1271 PetscBool same = PETSC_FALSE;
1272 PetscObjectTypeCompare((PetscObject)pc, PCMG, &same);
1273 if (same) {
1275 pc, createPCMGSetUpViaApproxOrdersCtx(dm, S, true));
1276 CHKERR PCSetFromOptions(pc);
1277 }
1279 };
1280
1281 auto set_pc_ksp = [&](auto dm, auto pc, auto S) {
1283 PetscBool same = PETSC_FALSE;
1284 PetscObjectTypeCompare((PetscObject)pc, PCKSP, &same);
1285 if (same) {
1286 CHKERR PCSetFromOptions(pc);
1287 KSP inner_ksp;
1288 CHKERR PCKSPGetKSP(pc, &inner_ksp);
1289 CHKERR KSPSetFromOptions(inner_ksp);
1290 PC inner_pc;
1291 CHKERR KSPGetPC(inner_ksp, &inner_pc);
1292 CHKERR PCSetFromOptions(inner_pc);
1293 CHKERR set_pc_p_mg(dm, inner_pc, S);
1294 }
1296 };
1297
1298 CHKERR set_pc_ksp(schurDM, get_pc(subksp[1]), S);
1299 CHKERR set_pc_p_mg(schurDM, get_pc(subksp[1]), S);
1300
1301 CHKERR PetscFree(subksp);
1303}
SmartPetscObj< KSP > ksp
MoFEMErrorCode setSchurA00MatSolvePC(SmartPetscObj< PC > pc)
Set PC for A00 block.
Definition Schur.cpp:4238
boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > createPCMGSetUpViaApproxOrdersCtx(DM dm, Mat A, bool use_shell_mat)
createPCMGSetUpViaApproxOrdersCtx
MoFEMErrorCode PCMGSetUpViaApproxOrders(PC pc, boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > ctx, int verb)
Function build MG structure.
intrusive_ptr for managing petsc objects

◆ setDiagonalPC() [2/2]

MoFEMErrorCode SetUpSchurImpl::setDiagonalPC ( PC  pc)
private

◆ setEntities()

MoFEMErrorCode SetUpSchurImpl::setEntities ( )
private
Examples
mofem/tutorials/vec-10_elasticity_schur/schur_elastic.cpp.

Definition at line 253 of file schur_elastic.cpp.

253 {
256 CHKERR mField.get_moab().get_entities_by_dimension(simple->getMeshset(),
258 CHKERR mField.get_moab().get_entities_by_handle(simple->getMeshset(),
259 subEnts);
260 subEnts = subtract(subEnts, volEnts);
262};
constexpr int SPACE_DIM
[Define dimension]
virtual moab::Interface & get_moab()=0

◆ setOperator() [1/3]

MoFEMErrorCode SetUpSchurImpl::setOperator ( )
private
Examples
mofem/tutorials/vec-10_elasticity_schur/schur_elastic.cpp.

Definition at line 1174 of file contact.cpp.

1174 {
1176
1177 double eps_stab = 1e-4;
1178 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-eps_stab", &eps_stab,
1179 PETSC_NULLPTR);
1180
1183 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
1184
1185 auto simple = mField.getInterface<Simple>();
1186 auto pip = mField.getInterface<PipelineManager>();
1187
1188 auto dm_is = getDMSubData(schurDM)->getSmartRowIs();
1189 auto ao_up = createAOMappingIS(dm_is, PETSC_NULLPTR);
1190
1191 // Boundary
1192 pip->getOpBoundaryLhsPipeline().push_front(createOpSchurAssembleBegin());
1193 pip->getOpBoundaryLhsPipeline().push_back(
1194 new OpMassStab("SIGMA", "SIGMA",
1195 [eps_stab](double, double, double) { return eps_stab; }));
1196 pip->getOpBoundaryLhsPipeline().push_back(
1197
1198 createOpSchurAssembleEnd({"SIGMA"}, {nullptr}, ao_up, S, false, false)
1199
1200 );
1201
1202 // Domain
1203 pip->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
1204 pip->getOpDomainLhsPipeline().push_back(
1205
1206 createOpSchurAssembleEnd({"SIGMA"}, {nullptr}, ao_up, S, false, false)
1207
1208 );
1209
1210 auto pre_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
1211 auto post_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
1212
1213 pre_proc_schur_lhs_ptr->preProcessHook = [this]() {
1215 CHKERR MatZeroEntries(S);
1216 MOFEM_LOG("CONTACT", Sev::verbose) << "Lhs Assemble Begin";
1218 };
1219
1220 post_proc_schur_lhs_ptr->postProcessHook = [this, ao_up,
1221 post_proc_schur_lhs_ptr]() {
1223 MOFEM_LOG("CONTACT", Sev::verbose) << "Lhs Assemble End";
1224 [[maybe_unused]] auto print_mat_norm = [this](auto a, std::string prefix) {
1226 double nrm;
1227 CHKERR MatNorm(a, NORM_FROBENIUS, &nrm);
1228 MOFEM_LOG("CONTACT", Sev::noisy) << prefix << " norm = " << nrm;
1230 };
1231 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
1232 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
1234 mField, post_proc_schur_lhs_ptr, 1, S, ao_up)();
1235#ifndef NDEBUG
1236 CHKERR print_mat_norm(S, "S");
1237#endif // NDEBUG
1238 MOFEM_LOG("CONTACT", Sev::verbose) << "Lhs Assemble Finish";
1240 };
1241
1242 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
1243 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_schur_lhs_ptr);
1244 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_schur_lhs_ptr);
1245
1247}
constexpr double a
@ BLOCK_PRECONDITIONER_SCHUR
Block preconditioner Schur assembly.
#define MOFEM_LOG(channel, severity)
Log.
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1292
OpSchurAssembleBase * createOpSchurAssembleEnd(std::vector< std::string > fields_name, std::vector< boost::shared_ptr< Range > > field_ents, SmartPetscObj< AO > ao, SmartPetscObj< Mat > schur, bool sym_schur, bool symm_op)
Construct a new Op Schur Assemble End object.
Definition Schur.cpp:4196
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
auto getDMSubData(DM dm)
Get sub problem data structure.
Definition DMMoFEM.hpp:1308
auto createAOMappingIS(IS isapp, IS ispetsc)
Creates an application mapping using two index sets.
OpSchurAssembleBase * createOpSchurAssembleBegin()
Definition Schur.cpp:4191
Class (Function) to enforce essential constrains on the left hand side diagonal.
Definition Essential.hpp:33
PipelineManager interface.

◆ setOperator() [2/3]

MoFEMErrorCode SetUpSchurImpl::setOperator ( )
private

◆ setOperator() [3/3]

MoFEMErrorCode SetUpSchurImpl::setOperator ( )
private

◆ setPC() [1/3]

MoFEMErrorCode SetUpSchurImpl::setPC ( PC  pc)
private
Examples
mofem/tutorials/vec-10_elasticity_schur/schur_elastic.cpp.

Definition at line 1249 of file contact.cpp.

1249 {
1251 auto block_is = getDMSubData(blockDM)->getSmartRowIs();
1252 CHKERR PCFieldSplitSetIS(pc, NULL, block_is);
1253 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
1255}

◆ setPC() [2/3]

MoFEMErrorCode SetUpSchurImpl::setPC ( PC  pc)
private

◆ setPC() [3/3]

MoFEMErrorCode SetUpSchurImpl::setPC ( PC  pc)
private

◆ setUp() [1/5]

MoFEMErrorCode SetUpSchurImpl::setUp ( SmartPetscObj< KSP >  solver)
virtual

Implements SetUpSchur.

◆ setUp() [2/5]

MoFEMErrorCode SetUpSchurImpl::setUp ( SmartPetscObj< KSP >  ksp)
virtual

Implements SetUpSchur.

Examples
mofem/atom_tests/test_broken_space.cpp, mofem/tutorials/adv-0_plasticity/plastic.cpp, and mofem/tutorials/vec-10_elasticity_schur/schur_elastic.cpp.

Definition at line 565 of file test_broken_space.cpp.

565 {
568 auto pip_mng = mField.getInterface<PipelineManager>();
569
570 CHKERR KSPSetFromOptions(ksp);
571 PC pc;
572 CHKERR KSPGetPC(ksp, &pc);
573
574 PetscBool is_pcfs = PETSC_FALSE;
575 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
576 if (is_pcfs) {
577
578 MOFEM_LOG("AT", Sev::inform) << "Setup Schur pc";
579
580 auto create_sub_dm = [&]() {
582
583 auto create_dm = [&](
584
585 std::string problem_name,
586 std::vector<std::string> fe_names,
587 std::vector<std::string> fields,
588
589 auto dm_type
590
591 ) {
592 auto dm = createDM(mField.get_comm(), dm_type);
593 auto create_dm_imp = [&]() {
595 CHKERR DMMoFEMCreateSubDM(dm, simple->getDM(), problem_name.c_str());
596 CHKERR DMMoFEMSetSquareProblem(dm, PETSC_TRUE);
597 for (auto fe : fe_names) {
599 }
600 CHKERR DMMoFEMAddElement(dm, simple->getSkeletonFEName());
601 for (auto field : fields) {
602 CHKERR DMMoFEMAddSubFieldRow(dm, field);
603 CHKERR DMMoFEMAddSubFieldCol(dm, field);
604 }
605 CHKERR DMSetUp(dm);
607 };
609 create_dm_imp(),
610 "Error in creating schurDM. It is possible that schurDM is "
611 "already created");
612 return dm;
613 };
614
615 auto schur_dm = create_dm(
616
617 "SCHUR",
618
619 {simple->getDomainFEName(), simple->getSkeletonFEName()},
620
621 {"HYBRID"},
622
623 "DMMOFEM_MG");
624
625 auto block_dm = create_dm(
626
627 "BLOCK",
628
629 {simple->getDomainFEName(), simple->getSkeletonFEName()},
630
631 {"BROKEN", "U"},
632
633 "DMMOFEM");
634
635 return std::make_tuple(schur_dm, block_dm);
636 };
637
638 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
639 auto block_mat_data = createBlockMatStructure(
640 simple->getDM(),
641
642 {
643
644 {
645
646 simple->getDomainFEName(),
647
648 {
649
650 {"BROKEN", "BROKEN"},
651 {"U", "U"},
652 {"BROKEN", "U"},
653 {"U", "BROKEN"}
654
655 }
656
657 },
658
659 {
660
661 simple->getSkeletonFEName(),
662
663 {
664
665 {"BROKEN", "HYBRID"}, {"HYBRID", "BROKEN"}
666
667 }
668
669 }
670
671 }
672
673 );
674
676
677 {schur_dm, block_dm}, block_mat_data,
678
679 {"BROKEN", "U"}, {nullptr, nullptr}, true
680
681 );
682 };
683
684 auto set_ops = [&](auto schur_dm) {
686 auto dm_is = getDMSubData(schur_dm)->getSmartRowIs();
687 auto ao_up = createAOMappingIS(dm_is, PETSC_NULLPTR);
688
689 boost::shared_ptr<BlockStructure> block_data;
690 CHKERR DMMoFEMGetBlocMatData(simple->getDM(), block_data);
691
692 if (AT == BLOCK_SCHUR) {
693 pip_mng->getOpDomainLhsPipeline().push_front(
695 pip_mng->getOpDomainLhsPipeline().push_back(
696
697 createOpSchurAssembleEnd({"BROKEN", "U"}, {nullptr, nullptr}, ao_up,
698 S, true, true)
699
700 );
701 }
702
703 auto pre_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
704 auto post_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
705
706 pre_proc_schur_lhs_ptr->preProcessHook = [this]() {
708 CHKERR MatZeroEntries(S);
709 MOFEM_LOG("AT", Sev::verbose) << "Lhs Assemble Begin";
711 };
712
713 post_proc_schur_lhs_ptr->postProcessHook = [this, ao_up,
714 post_proc_schur_lhs_ptr]() {
716 MOFEM_LOG("AT", Sev::verbose) << "Lhs Assemble End";
717
718 if (AT == BLOCK_SCHUR) {
719 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
720 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
721 if (1) {
722 auto S_from_block = matDuplicate(S, MAT_SHARE_NONZERO_PATTERN);
723 // Create matrix from block mat
724 CHKERR assembleBlockMatSchur(mField, post_proc_schur_lhs_ptr->B,
725 S_from_block, {"BROKEN", "U"},
726 {nullptr, nullptr}, ao_up);
727 CHKERR MatAssemblyBegin(S_from_block, MAT_FINAL_ASSEMBLY);
728 CHKERR MatAssemblyEnd(S_from_block, MAT_FINAL_ASSEMBLY);
729 CHKERR MatAYPX(S_from_block, -1, S, DIFFERENT_NONZERO_PATTERN);
730 double norm;
731 CHKERR MatNorm(S_from_block, NORM_FROBENIUS, &norm);
732 MOFEM_LOG("AT", Sev::inform) << "Norm of difference: " << norm;
733 if (norm > 1e-6)
734 SETERRQ(
735 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
736 "Norm of difference between Schur and block matrix is larger "
737 "than accepted");
738 }
739 } else {
740 CHKERR assembleBlockMatSchur(mField, post_proc_schur_lhs_ptr->B, S,
741 {"BROKEN", "U"}, {nullptr, nullptr}, ao_up);
742 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
743 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
744 }
745
746 MOFEM_LOG("AT", Sev::verbose) << "Lhs Assemble Finish";
748 };
749
750 auto ksp_ctx_ptr = getDMKspCtx(simple->getDM());
751 ksp_ctx_ptr->getPreProcSetOperators().push_front(pre_proc_schur_lhs_ptr);
752 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_schur_lhs_ptr);
753
755 };
756
757 auto set_pc = [&](auto pc, auto block_dm) {
759 auto block_is = getDMSubData(block_dm)->getSmartRowIs();
760 CHKERR PCFieldSplitSetIS(pc, NULL, block_is);
761 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
763 };
764
765
766
767 auto [schur_dm, block_dm] = create_sub_dm();
768 if (AT == BLOCK_SCHUR || AT == BLOCK_MAT) {
769 auto nested_mat_data = get_nested_mat_data(schur_dm, block_dm);
770 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
771 }
772 S = createDMHybridisedL2Matrix(schur_dm);
773 CHKERR MatSetDM(S, PETSC_NULLPTR);
774
775 int bs = (SPACE_DIM == 2) ? NBEDGE_L2(hybrid_approx_order)
777 CHKERR MatSetBlockSize(S, bs);
778
779 CHKERR set_ops(schur_dm);
780 CHKERR set_pc(pc, block_dm);
781 DM solver_dm;
782 CHKERR KSPGetDM(ksp, &solver_dm);
783 if (AT == BLOCK_SCHUR || AT == BLOCK_MAT)
784 CHKERR DMSetMatType(solver_dm, MATSHELL);
785
786 auto get_pc = [](auto ksp) {
787 PC pc_raw;
788 CHKERR KSPGetPC(ksp, &pc_raw);
789 return pc_raw;
790 };
791
792 auto set_diagonal_pc = [&](auto pc) {
794
795 if (AT == BLOCK_SCHUR || AT == BLOCK_MAT) {
796 auto A = createDMBlockMat(simple->getDM());
797 auto P = createDMNestSchurMat(simple->getDM());
798 CHKERR PCSetOperators(pc, A, P);
799 }
800
801 KSP *subksp;
802 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
803 CHKERR setSchurA00MatSolvePC(SmartPetscObj<PC>(get_pc(subksp[0]), true));
804
805 CHKERR PetscFree(subksp);
807 };
808
809 auto set_mg_for_schur_complement = [&](auto pc, auto schur_dm, auto S) {
811
812 KSP *subksp;
813 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
814 auto subpc = get_pc(subksp[1]);
815
816 auto set_pc_p_mg = [](auto dm, auto pc, auto S) {
818 CHKERR PCSetDM(pc, dm);
819 PetscBool same = PETSC_FALSE;
820 PetscObjectTypeCompare((PetscObject)pc, PCMG, &same);
821 if (same) {
822 MOFEM_LOG("TIMER", Sev::inform) << "Set up MG";
824 pc, createPCMGSetUpViaApproxOrdersCtx(dm, S, true));
825 CHKERR PCSetFromOptions(pc);
826 }
828 };
829
830 PetscBool same = PETSC_FALSE;
831 PetscObjectTypeCompare((PetscObject)subpc, PCKSP, &same);
832 if (same) {
833 CHKERR PCSetFromOptions(subpc);
834 KSP inner_ksp;
835 CHKERR PCKSPGetKSP(subpc, &inner_ksp);
836 CHKERR KSPSetFromOptions(inner_ksp);
837 PC inner_pc;
838 CHKERR KSPGetPC(inner_ksp, &inner_pc);
839 CHKERR PCSetFromOptions(inner_pc);
840 CHKERR set_pc_p_mg(schur_dm, inner_pc, S);
841 }
842
843 CHKERR PetscFree(subksp);
845 };
846
847 CHKERR KSPSetUp(ksp);
848 if (AT == BLOCK_SCHUR || AT == BLOCK_MAT) {
849 CHKERR set_diagonal_pc(pc);
850 CHKERR set_mg_for_schur_complement(pc, schur_dm, S);
851 }
852
853 } else {
854 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
855 "PC is not set to PCFIELDSPLIT");
856 }
858}
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ BLOCK_MAT
Block matrix assembly.
@ BLOCK_SCHUR
Block Schur assembly.
#define NBFACETRI_L2(P)
Number of base functions on triangle for L2 space.
#define NBEDGE_L2(P)
Number of base functions on edge from L2 space.
MoFEMErrorCode DMMoFEMGetBlocMatData(DM dm, boost::shared_ptr< BlockStructure > &)
Get data for block mat.
Definition DMMoFEM.cpp:1564
auto getDMKspCtx(DM dm)
Get KSP context data structure used by DM.
Definition DMMoFEM.hpp:1264
auto createDMHybridisedL2Matrix(DM dm)
Get smart hybridised L2 matrix from DM.
Definition DMMoFEM.hpp:1220
SmartPetscObj< Mat > matDuplicate(Mat mat, MatDuplicateOption op)
auto createDMNestSchurMat(DM dm)
Definition DMMoFEM.hpp:1234
MoFEMErrorCode assembleBlockMatSchur(MoFEM::Interface &m_field, Mat B, Mat S, std::vector< std::string > fields_name, std::vector< boost::shared_ptr< Range > > field_ents, SmartPetscObj< AO > ao)
Assemble Schur complement S = A11 - A10 A00^{-1} A01 from block matrix.
Definition Schur.cpp:3107
auto createDMBlockMat(DM dm)
Definition DMMoFEM.hpp:1227
constexpr AssemblyType A
[Define dimension]
int hybrid_approx_order

◆ setUp() [3/5]

MoFEMErrorCode SetUpSchurImpl::setUp ( SmartPetscObj< TS >  solver)
virtual

Implements SetUpSchur.

Definition at line 1032 of file contact.cpp.

1032 {
1034 auto simple = mField.getInterface<Simple>();
1035 auto pip = mField.getInterface<PipelineManager>();
1036
1037 SNES snes;
1038 CHKERR TSGetSNES(solver, &snes);
1039 KSP ksp;
1040 CHKERR SNESGetKSP(snes, &ksp);
1041 CHKERR KSPSetFromOptions(ksp);
1042
1043 PC pc;
1044 CHKERR KSPGetPC(ksp, &pc);
1045
1046 PetscBool is_pcfs = PETSC_FALSE;
1047 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1048 if (is_pcfs) {
1049
1050 MOFEM_LOG("CONTACT", Sev::inform) << "Setup Schur pc";
1051
1052 if (S) {
1055 "It is expected that Schur matrix is not allocated. This is "
1056 "possible only if PC is set up twice");
1057 }
1058
1060
1061 // Add data to DM storage
1063 CHKERR MatSetBlockSize(S, SPACE_DIM);
1064 // CHKERR MatSetOption(S, MAT_SYMMETRIC, PETSC_TRUE);
1065
1066 // Set DM to use shell block matrix
1067 DM solver_dm;
1068 CHKERR TSGetDM(solver, &solver_dm);
1069 CHKERR DMSetMatType(solver_dm, MATSHELL);
1070
1071 auto ts_ctx_ptr = getDMTsCtx(solver_dm);
1072 auto A = createDMBlockMat(simple->getDM());
1073 auto P = createDMNestSchurMat(simple->getDM());
1074
1075 if (is_quasi_static == PETSC_TRUE) {
1076 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a,
1077 Mat A, Mat B, void *ctx) {
1078 return TsSetIJacobian(ts, t, u, u_t, a, B, A, ctx);
1079 };
1080 CHKERR TSSetIJacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1081 } else {
1082 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec utt,
1083 PetscReal a, PetscReal aa, Mat A, Mat B,
1084 void *ctx) {
1085 return TsSetI2Jacobian(ts, t, u, u_t, utt, a, aa, B, A, ctx);
1086 };
1087 CHKERR TSSetI2Jacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1088 }
1089 CHKERR KSPSetOperators(ksp, A, P);
1090
1092 CHKERR setPC(pc);
1093 CHKERR TSSetUp(solver);
1094 CHKERR KSPSetUp(ksp);
1096
1097 } else {
1098 MOFEM_LOG("CONTACT", Sev::inform) << "No Schur PC";
1099 pip->getOpBoundaryLhsPipeline().push_front(createOpSchurAssembleBegin());
1100 pip->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd({}, {}));
1101 pip->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
1102 pip->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd({}, {}));
1103 }
1105}
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1207
const FTensor::Tensor2< T, Dim, Dim > Vec
PetscErrorCode TsSetIJacobian(TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a, Mat A, Mat B, void *ctx)
Set function evaluating jacobian in TS solver.
Definition TsCtx.cpp:169
PetscErrorCode TsSetI2Jacobian(TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, PetscReal a, PetscReal aa, Mat A, Mat B, void *ctx)
Calculation Jacobian for second order PDE in time.
Definition TsCtx.cpp:519
PetscBool is_quasi_static
Definition plastic.cpp:144
constexpr double t
plate stiffness
Definition plate.cpp:58
MoFEMErrorCode createSubDM()
Definition contact.cpp:1107
MoFEMErrorCode setDiagonalPC(PC pc)
Definition contact.cpp:1257
MoFEMErrorCode setPC(PC pc)
Definition contact.cpp:1249
MoFEMErrorCode setOperator()
Definition contact.cpp:1174

◆ setUp() [4/5]

MoFEMErrorCode SetUpSchurImpl::setUp ( SmartPetscObj< TS >  solver)
virtual

Implements SetUpSchur.

◆ setUp() [5/5]

MoFEMErrorCode SetUpSchurImpl::setUp ( TS  solver)
virtual

Implements SetUpSchur.

Definition at line 1701 of file plastic.cpp.

1701 {
1703 auto simple = mField.getInterface<Simple>();
1704 auto pip_mng = mField.getInterface<PipelineManager>();
1705
1706 SNES snes;
1707 CHKERR TSGetSNES(solver, &snes);
1708 KSP ksp;
1709 CHKERR SNESGetKSP(snes, &ksp);
1710 CHKERR KSPSetFromOptions(ksp);
1711
1712 PC pc;
1713 CHKERR KSPGetPC(ksp, &pc);
1714 PetscBool is_pcfs = PETSC_FALSE;
1715 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1716 if (is_pcfs) {
1717 if (S) {
1719 "Is expected that schur matrix is not "
1720 "allocated. This is "
1721 "possible only is if PC is set up twice");
1722 }
1723
1725 CHKERR MatSetBlockSize(S, SPACE_DIM);
1726
1727 // Set DM to use shell block matrix
1728 DM solver_dm;
1729 CHKERR TSGetDM(solver, &solver_dm);
1730 CHKERR DMSetMatType(solver_dm, MATSHELL);
1731
1732 auto ts_ctx_ptr = getDMTsCtx(solver_dm);
1733 auto A = createDMBlockMat(simple->getDM());
1734 auto P = createDMNestSchurMat(simple->getDM());
1735
1736 if (is_quasi_static == PETSC_TRUE) {
1737 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a,
1738 Mat A, Mat B, void *ctx) {
1739 return TsSetIJacobian(ts, t, u, u_t, a, B, A, ctx);
1740 };
1741 CHKERR TSSetIJacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1742 } else {
1743 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec utt,
1744 PetscReal a, PetscReal aa, Mat A, Mat B,
1745 void *ctx) {
1746 return TsSetI2Jacobian(ts, t, u, u_t, utt, a, aa, B, A, ctx);
1747 };
1748 CHKERR TSSetI2Jacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1749 }
1750 CHKERR KSPSetOperators(ksp, A, P);
1751
1752 auto set_ops = [&]() {
1754 auto pip_mng = mField.getInterface<PipelineManager>();
1755
1756#ifndef ADD_CONTACT
1757 // Boundary
1758 pip_mng->getOpBoundaryLhsPipeline().push_front(
1760 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
1761
1762 {"EP", "TAU"}, {nullptr, nullptr}, aoSchur, S, false, false
1763
1764 ));
1765 // Domain
1766 pip_mng->getOpDomainLhsPipeline().push_front(
1768 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
1769
1770 {"EP", "TAU"}, {nullptr, nullptr}, aoSchur, S, false, false
1771
1772 ));
1773#else
1774
1775 double eps_stab = 1e-4;
1776 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-eps_stab", &eps_stab,
1777 PETSC_NULLPTR);
1778
1781 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
1782
1783 // Boundary
1784 pip_mng->getOpBoundaryLhsPipeline().push_front(
1786 pip_mng->getOpBoundaryLhsPipeline().push_back(
1787 new OpMassStab("SIGMA", "SIGMA", [eps_stab](double, double, double) {
1788 return eps_stab;
1789 }));
1790 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
1791
1792 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, aoSchur, S,
1793 false, false
1794
1795 ));
1796 // Domain
1797 pip_mng->getOpDomainLhsPipeline().push_front(
1799 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
1800
1801 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, aoSchur, S,
1802 false, false
1803
1804 ));
1805#endif // ADD_CONTACT
1807 };
1808
1809 auto set_assemble_elems = [&]() {
1811 auto schur_asmb_pre_proc = boost::make_shared<FEMethod>();
1812 schur_asmb_pre_proc->preProcessHook = [this]() {
1814 CHKERR MatZeroEntries(S);
1815 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble Begin";
1817 };
1818 auto schur_asmb_post_proc = boost::make_shared<FEMethod>();
1819 auto weak_schur_asmb_post_proc = boost::weak_ptr<FEMethod>(
1820 schur_asmb_post_proc); // fe method passed to lambda, have to be weak ptr to avoid circular shared ptr reference
1821
1822 schur_asmb_post_proc->postProcessHook = [this,
1823 weak_schur_asmb_post_proc]() {
1825 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble End";
1826
1827 // Apply essential constrains to Schur complement
1828 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
1829 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
1831 mField, weak_schur_asmb_post_proc.lock(), 1, S, aoSchur)();
1832
1834 };
1835 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
1836 ts_ctx_ptr->getPreProcessIJacobian().push_front(schur_asmb_pre_proc);
1837 ts_ctx_ptr->getPostProcessIJacobian().push_front(schur_asmb_post_proc);
1839 };
1840
1841 auto set_pc = [&]() {
1843 CHKERR PCFieldSplitSetIS(pc, NULL, fieldSplitIS);
1844 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
1846 };
1847
1848 auto set_diagonal_pc = [&]() {
1850 KSP *subksp;
1851 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
1852 auto get_pc = [](auto ksp) {
1853 PC pc_raw;
1854 CHKERR KSPGetPC(ksp, &pc_raw);
1855 return SmartPetscObj<PC>(pc_raw,
1856 true); // bump reference
1857 };
1858 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
1859 CHKERR PetscFree(subksp);
1861 };
1862
1863 CHKERR set_ops();
1864 CHKERR set_pc();
1865 CHKERR set_assemble_elems();
1866
1867 CHKERR TSSetUp(solver);
1868 CHKERR KSPSetUp(ksp);
1869 CHKERR set_diagonal_pc();
1870
1871 } else {
1872 pip_mng->getOpBoundaryLhsPipeline().push_front(
1874 pip_mng->getOpBoundaryLhsPipeline().push_back(
1875 createOpSchurAssembleEnd({}, {}));
1876 pip_mng->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
1877 pip_mng->getOpDomainLhsPipeline().push_back(
1878 createOpSchurAssembleEnd({}, {}));
1879 }
1880
1881 // fieldSplitIS.reset();
1882 // aoSchur.reset();
1884}

Member Data Documentation

◆ aoSchur

SmartPetscObj<AO> SetUpSchurImpl::aoSchur
private
Examples
mofem/tutorials/adv-0_plasticity/plastic.cpp.

Definition at line 1698 of file plastic.cpp.

◆ blockDM

SmartPetscObj< DM > SetUpSchurImpl::blockDM
private

◆ fieldSplitIS

SmartPetscObj<IS> SetUpSchurImpl::fieldSplitIS
private

IS for split Schur block.

Examples
mofem/tutorials/adv-0_plasticity/plastic.cpp.

Definition at line 1697 of file plastic.cpp.

◆ mField

MoFEM::Interface & SetUpSchurImpl::mField
private

◆ S

SmartPetscObj< Mat > SetUpSchurImpl::S
private

◆ schurDM

SmartPetscObj< DM > SetUpSchurImpl::schurDM
private

◆ subDM

SmartPetscObj< DM > SetUpSchurImpl::subDM
private

field split sub dm

Examples
mofem/tutorials/adv-0_plasticity/plastic.cpp.

Definition at line 1696 of file plastic.cpp.

◆ subEnts

Range SetUpSchurImpl::subEnts
private

◆ volEnts

Range SetUpSchurImpl::volEnts
private

The documentation for this struct was generated from the following files: