187 KSP schur_complement_ksp;
191 IS velocity_is, pressure_is;
192 PetscInt rstart, rend;
194 std::vector<Mat> intermediate_Qs;
195 std::vector<Mat> intermediate_Ls;
200 Mat global_Q =
nullptr;
205 global_Q = cast_ref<const PetscMatrixBase<Number> &>(
206 cast_ref<StaticCondensation &>(sparse_mass_mat).get_condensed_mat())
209 global_Q = cast_ref<PetscMatrixBase<Number> &>(sparse_mass_mat).mat();
214 Mat global_L =
nullptr;
224 auto process_intermediate_mats = [
this](
auto & intermediate_mats,
auto parent_mat)
226 mooseAssert(parent_mat,
"This should be non-null");
231 Mat intermediate_mat;
232 LibmeshPetscCall(MatCreateSubMatrix(i == 0 ? parent_mat : intermediate_mats[i - 1],
237 intermediate_mats[i] = intermediate_mat;
239 return _index_sets.empty() ? parent_mat : intermediate_mats.back();
242 Mat our_parent_Q =
nullptr;
244 our_parent_Q = process_intermediate_mats(intermediate_Qs, global_Q);
245 Mat our_parent_L =
nullptr;
247 our_parent_L = process_intermediate_mats(intermediate_Ls, global_L);
251 LibmeshPetscCall(PCFieldSplitGetISByIndex(schur_pc, 0, &velocity_is));
254 LibmeshPetscCall(MatGetOwnershipRange(our_parent_Q, &rstart, &rend));
260 mooseAssert(our_parent_L,
"This should be non-null");
265 MatCreateSubMatrix(our_parent_L, velocity_is, velocity_is, MAT_INITIAL_MATRIX, &
_L));
269 MatCreateSubMatrix(our_parent_L, velocity_is, velocity_is, MAT_REUSE_MATRIX, &
_L));
273 LibmeshPetscCall(ISComplement(velocity_is, rstart, rend, &pressure_is));
275 auto create_q_scale_submat =
276 [our_parent_Q,
this, velocity_is, pressure_is](
const auto & mat_initialization)
282 mooseAssert(our_parent_Q,
"This should be non-null");
284 LibmeshPetscCall(MatCreateSubMatrix(
285 our_parent_Q, pressure_is, pressure_is, mat_initialization, &
_Q_scale));
292 mooseAssert(our_parent_Q,
"This should be non-null");
295 LibmeshPetscCall(MatCreateSubMatrix(
296 our_parent_Q, velocity_is, velocity_is, mat_initialization, &
_Q_scale));
302 create_q_scale_submat(MAT_INITIAL_MATRIX);
308 LibmeshPetscCall(MatDestroy(&
_Q_scale));
309 create_q_scale_submat(MAT_INITIAL_MATRIX);
313 create_q_scale_submat(MAT_REUSE_MATRIX);
317 LibmeshPetscCall(ISDestroy(&pressure_is));
320 for (
auto & mat : intermediate_Qs)
321 LibmeshPetscCall(MatDestroy(&mat));
322 for (
auto & mat : intermediate_Ls)
323 LibmeshPetscCall(MatDestroy(&mat));
327 LibmeshPetscCall(PCFieldSplitGetSubKSP(schur_pc, &num_splits, &subksp));
329 mooseError(
"The number of splits should be two");
332 schur_complement_ksp = subksp[1];
336 mooseAssert(
_Q_scale,
"This should be non-null");
340 LibmeshPetscCall(KSPGetOperators(schur_complement_ksp, &S,
nullptr));
344 MatSchurComplementGetSubMatrices(S,
nullptr,
nullptr,
nullptr,
nullptr, &A11));
345 LibmeshPetscCall(MatAXPY(
_Q_scale, 1, A11, DIFFERENT_NONZERO_PATTERN));
348 LibmeshPetscCall(PCFieldSplitSetSchurPre(schur_pc, PC_FIELDSPLIT_SCHUR_PRE_USER,
_Q_scale));
351 LibmeshPetscCall(KSPSetOperators(schur_complement_ksp, S,
_Q_scale));
356 LibmeshPetscCall(KSPGetPC(schur_complement_ksp, &lsc_pc));
358 LibmeshPetscCall(PetscObjectTypeCompare(PetscObject(lsc_pc), PCLSC, &is_lsc));
360 mooseError(
"Not an LSC PC. Please check the 'schur_fs_index' parameter");
363 LibmeshPetscCall(PCGetOperators(lsc_pc,
nullptr, &lsc_pc_pmat));
368 mooseAssert(
_L,
"This should be non-null");
371 LibmeshPetscCall(PetscObjectCompose((PetscObject)lsc_pc_pmat,
"LSC_L", (PetscObject)
_L));
373 mooseAssert(
_have_mass_matrix,
"This is to verify we will enter the next conditional");
377 mooseAssert(
_Q_scale,
"This should be non-null");
381 PetscObjectCompose((PetscObject)lsc_pc_pmat,
"LSC_Qscale", (PetscObject)
_Q_scale));
386 LibmeshPetscCall(PetscFree(subksp));
Context object attached to a field split PC via PCSetApplicationContext so that the static fieldSplit...
NavierStokesProblem * problem
The problem that owns the field split tree being set up.