24 SmartPetscObj<AO>
aoS;
26 boost::shared_ptr<std::vector<boost::weak_ptr<NumeredDofEntity>>>
28 boost::shared_ptr<std::vector<unsigned char>>
51 boost::shared_ptr<P_MultiGridData>
pMGPtr;
56 std::vector<boost::shared_ptr<Range>> dm_range_list{
nullptr,
nullptr};
57 return std::make_pair(schur_field_list, dm_range_list);
61 std::vector<std::string> a00_field_list{
74 std::vector<boost::shared_ptr<Range>> range_list_ptr(a00_field_list.size(),
76 return std::make_pair(a00_field_list, range_list_ptr);
83 auto create_schur_dm = [&](SmartPetscObj<DM> &dm_sub) {
95 for (
auto f : schur_field_list) {
96 MOFEM_LOG(
"EP", Sev::inform) <<
"Add schur field: " <<
f;
105 auto create_a00_dm = [&](SmartPetscObj<DM> &dm_sub) {
117 for (
auto f : a00_field_list) {
118 MOFEM_LOG(
"EP", Sev::inform) <<
"Add a00 field: " <<
f;
127 auto get_snes = [&](TS ts) {
129 CHKERR TSGetSNES(ts, &snes);
133 auto get_ksp = [&](SNES snes) {
135 CHKERR SNESGetKSP(snes, &ksp);
136 CHKERR KSPSetFromOptions(ksp);
140 auto get_pc = [&](KSP ksp) {
142 CHKERR KSPGetPC(ksp, &pc);
146 auto ksp = get_ksp(get_snes(ts));
147 auto pc = get_pc(ksp);
149 PetscBool is_pcfs = PETSC_FALSE;
150 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
153 MOFEM_LOG(
"EP", Sev::inform) <<
"SetUpSchurImpl::setUp: PCFIELDSPLIT";
155 SmartPetscObj<DM> schur_dm, a00_dm;
156 CHKERR create_schur_dm(schur_dm);
157 CHKERR create_a00_dm(a00_dm);
164 std::vector<std::pair<std::string, std::string>> mat_block_list = {
184 mat_block_list.push_back(
186 mat_block_list.push_back(
188 mat_block_list.push_back(
199 auto get_nested_mat_data = [&](
auto schur_dm,
auto block_dm) {
205 {vol_elem_name, mat_block_list},
234 {schur_dm, a00_dm}, block_mat_data,
245 auto nested_mat_data = get_nested_mat_data(schur_dm, a00_dm);
253 std::numeric_limits<double>::epsilon()) {
254 auto swap_assemble = [](TS ts, PetscReal
t,
Vec u,
Vec u_t,
Vec utt,
255 PetscReal
a, PetscReal aa, Mat
A, Mat B,
260 CHKERR TSSetI2Jacobian(ts,
m, p, swap_assemble, ts_ctx_ptr.get());
262 auto swap_assemble = [](TS ts, PetscReal
t,
Vec u,
Vec u_t, PetscReal
a,
263 Mat
A, Mat B,
void *ctx) {
267 CHKERR TSSetIJacobian(ts,
m, p, swap_assemble, ts_ctx_ptr.get());
269 CHKERR KSPSetOperators(ksp,
m, p);
271 auto set_assembly = [&]() {
281 auto set_assemble = [&]() {
283 auto schur_asmb_pre_proc_lhs = boost::make_shared<FEMethod>();
284 auto schur_asmb_pre_proc_rhs = boost::make_shared<FEMethod>();
286 schur_asmb_pre_proc_lhs->preProcessHook = [
this]() {
292 schur_asmb_pre_proc_rhs->preProcessHook =
293 [
this, schur_asmb_pre_proc_rhs]() {
295 auto prb_ptr = schur_asmb_pre_proc_rhs->problemPtr;
296 auto dofs_prb = prb_ptr->getNumeredRowDofsPtr();
301 ->getSideDofsOnBrokenSpaceEntities(
309 if (
auto dof_ptr = dof.lock()) {
310 auto idx = dof_ptr->getPetscLocalDofIdx();
311 (*piolaZeroDofsMarker)[idx] = 1;
318 schur_asmb_pre_proc_rhs->problemPtr->getName();
322 SmartPetscObj<IS> crack_hybrid_is;
324 ->isCreateProblemFieldAndRankLocal(
326 SPACE_DIM, crack_hybrid_is, &*crack_faces);
328 SmartPetscObj<IS> crack_piola_is;
334 CHKERR VecGetArray(schur_asmb_pre_proc_rhs->x, &a_x);
335 auto zero_by_is = [&](
auto is) {
337 const PetscInt *is_array;
339 CHKERR ISGetLocalSize(is, &is_size);
340 CHKERR ISGetIndices(is, &is_array);
341 for (
int i = 0;
i != is_size; ++
i) {
342 a_x[is_array[
i]] = 0;
344 CHKERR ISRestoreIndices(is, &is_array);
348 CHKERR zero_by_is(crack_hybrid_is);
349 CHKERR zero_by_is(crack_piola_is);
351 CHKERR VecRestoreArray(schur_asmb_pre_proc_rhs->x, &a_x);
354 ->setLocalGhostVector(problem_name,
COL,
355 schur_asmb_pre_proc_rhs->x,
356 INSERT_VALUES, SCATTER_REVERSE);
362 auto schur_asmb_post_proc_lhs = boost::make_shared<FEMethod>();
363 auto schur_asmb_post_proc_rhs = boost::make_shared<FEMethod>();
365 schur_asmb_post_proc_rhs->postProcessHook =
366 [
this, schur_asmb_post_proc_rhs]() {
369 CHKERR VecGhostUpdateBegin(schur_asmb_post_proc_rhs->f,
370 ADD_VALUES, SCATTER_REVERSE);
371 CHKERR VecGhostUpdateEnd(schur_asmb_post_proc_rhs->f, ADD_VALUES,
373 CHKERR VecAssemblyBegin(schur_asmb_post_proc_rhs->f);
374 CHKERR VecAssemblyEnd(schur_asmb_post_proc_rhs->f);
375 *(schur_asmb_post_proc_rhs->vecAssembleSwitch) =
false;
380 schur_asmb_post_proc_rhs->problemPtr->getName();
384 SmartPetscObj<IS> crack_hybrid_is;
386 ->isCreateProblemFieldAndRankLocal(
388 SPACE_DIM, crack_hybrid_is, &*crack_faces);
390 SmartPetscObj<IS> crack_piola_is;
396 CHKERR VecGetArray(schur_asmb_post_proc_rhs->f, &a_f);
397 auto zero_by_is = [&](
auto is) {
399 const PetscInt *is_array;
401 CHKERR ISGetLocalSize(is, &is_size);
402 CHKERR ISGetIndices(is, &is_array);
403 for (
int i = 0;
i != is_size; ++
i) {
404 a_f[is_array[
i]] = 0;
406 CHKERR ISRestoreIndices(is, &is_array);
410 CHKERR zero_by_is(crack_hybrid_is);
411 CHKERR zero_by_is(crack_piola_is);
413 CHKERR VecRestoreArray(schur_asmb_post_proc_rhs->f, &a_f);
420 schur_asmb_post_proc_lhs->postProcessHook =
421 [
this, schur_asmb_post_proc_lhs]() {
432 CHKERR MatAssemblyBegin(schur_asmb_post_proc_lhs->B,
434 CHKERR MatAssemblyEnd(schur_asmb_post_proc_lhs->B,
436 *(schur_asmb_post_proc_lhs->matAssembleSwitch) =
false;
438 SmartPetscObj<IS> crack_hybrid_is;
440 ->isCreateProblemFieldAndRank(
442 SPACE_DIM, crack_hybrid_is, &*crack_faces);
443 CHKERR MatZeroRowsColumnsIS(schur_asmb_post_proc_lhs->B,
444 crack_hybrid_is, 1, PETSC_NULL,
448 SmartPetscObj<IS> crack_piola_is;
452 CHKERR MatZeroRowsColumnsIS(schur_asmb_post_proc_lhs->B,
453 crack_piola_is, 1, PETSC_NULL,
459 schur_asmb_post_proc_lhs->B,
S,
460 a00_field_list, a00_range_list,
aoS);
465 CHKERR MatAssemblyBegin(
S, MAT_FINAL_ASSEMBLY);
466 CHKERR MatAssemblyEnd(
S, MAT_FINAL_ASSEMBLY);
468 SmartPetscObj<IS> crack_hybrid_is;
470 ->isCreateProblemFieldAndRank(
472 SPACE_DIM, crack_hybrid_is, &*crack_faces);
474 CHKERR MatZeroRowsColumnsIS(
S, crack_hybrid_is, 1, PETSC_NULL,
481 ts_ctx_ptr->getPreProcessIFunction().push_front(
482 schur_asmb_pre_proc_rhs);
483 ts_ctx_ptr->getPostProcessIFunction().push_back(
484 schur_asmb_post_proc_rhs);
485 ts_ctx_ptr->getPreProcessIJacobian().push_front(
486 schur_asmb_pre_proc_lhs);
487 ts_ctx_ptr->getPostProcessIJacobian().push_back(
488 schur_asmb_post_proc_lhs);
493 boost::make_shared<std::vector<boost::weak_ptr<NumeredDofEntity>>>();
500 auto set_pc = [&]() {
503 auto schur_is =
getDMSubData(schur_dm)->getSmartRowIs();
504 CHKERR PCFieldSplitSetIS(pc, NULL, a00_is);
505 CHKERR PCFieldSplitSetIS(pc, NULL, schur_is);
506 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER,
S);
510 auto set_diagonal_pc = [&]() {
513 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULL, &subksp);
514 auto get_pc = [](
auto ksp) {
516 CHKERR KSPGetPC(ksp, &pc_raw);
517 return SmartPetscObj<PC>(pc_raw,
true);
521 auto set_pc_p_mg = [&](
auto dm,
auto pc,
auto S) {
524 PetscBool same = PETSC_FALSE;
525 PetscObjectTypeCompare((PetscObject)pc, PCMG, &same);
527 auto smart_pc = SmartPetscObj<PC>(pc,
true);
528 pMGPtr = boost::make_shared<P_MultiGridData>(dm, smart_pc,
S);
530 PetscObjectTypeCompare((PetscObject)pc, PCKSP, &same);
533 <<
"SetUpSchurImpl::setUp: fieldsplit 1 PCKSP";
534 CHKERR PCSetFromOptions(pc);
536 CHKERR PCKSPGetKSP(pc, &ksp);
538 CHKERR KSPGetPC(ksp, &ksp_pc);
539 CHKERR PCSetFromOptions(ksp_pc);
540 PetscObjectTypeCompare((PetscObject)ksp_pc, PCMG, &same);
542 auto smart_pc = SmartPetscObj<PC>(ksp_pc,
true);
543 pMGPtr = boost::make_shared<P_MultiGridData>(dm, smart_pc,
S);
549 CHKERR set_pc_p_mg(schur_dm, get_pc(subksp[1]),
S);
562 MOFEM_LOG(
"EP", Sev::inform) <<
"SetUpSchurImpl::setUp: PCLU or other";
577 boost::shared_ptr<EshelbianCore::SetUpSchur>
580 return boost::shared_ptr<SetUpSchur>(