185 KSP schur_complement_ksp;
189 IS velocity_is, pressure_is;
190 PetscInt rstart, rend;
192 std::vector<Mat> intermediate_Qs;
193 std::vector<Mat> intermediate_Ls;
198 Mat global_Q =
nullptr;
203 global_Q = cast_ref<const libMesh::PetscMatrixBase<Number> &>(
204 cast_ref<libMesh::StaticCondensation &>(sparse_mass_mat).get_condensed_mat())
207 global_Q = cast_ref<libMesh::PetscMatrixBase<Number> &>(sparse_mass_mat).mat();
212 Mat global_L =
nullptr;
223 auto process_intermediate_mats = [
this](
auto & intermediate_mats,
auto parent_mat)
225 mooseAssert(parent_mat,
"This should be non-null");
230 Mat intermediate_mat;
231 LibmeshPetscCall(MatCreateSubMatrix(i == 0 ? parent_mat : intermediate_mats[i - 1],
236 intermediate_mats[i] = intermediate_mat;
238 return _index_sets.empty() ? parent_mat : intermediate_mats.back();
241 Mat our_parent_Q =
nullptr;
243 our_parent_Q = process_intermediate_mats(intermediate_Qs, global_Q);
244 Mat our_parent_L =
nullptr;
246 our_parent_L = process_intermediate_mats(intermediate_Ls, global_L);
250 LibmeshPetscCall(PCFieldSplitGetISByIndex(schur_pc, 0, &velocity_is));
253 LibmeshPetscCall(MatGetOwnershipRange(our_parent_Q, &rstart, &rend));
259 mooseAssert(our_parent_L,
"This should be non-null");
264 MatCreateSubMatrix(our_parent_L, velocity_is, velocity_is, MAT_INITIAL_MATRIX, &
_L));
268 MatCreateSubMatrix(our_parent_L, velocity_is, velocity_is, MAT_REUSE_MATRIX, &
_L));
272 LibmeshPetscCall(ISComplement(velocity_is, rstart, rend, &pressure_is));
274 auto create_q_scale_submat =
275 [our_parent_Q,
this, velocity_is, pressure_is](
const auto & mat_initialization)
281 mooseAssert(our_parent_Q,
"This should be non-null");
283 LibmeshPetscCall(MatCreateSubMatrix(
284 our_parent_Q, pressure_is, pressure_is, mat_initialization, &
_Q_scale));
291 mooseAssert(our_parent_Q,
"This should be non-null");
294 LibmeshPetscCall(MatCreateSubMatrix(
295 our_parent_Q, velocity_is, velocity_is, mat_initialization, &
_Q_scale));
301 create_q_scale_submat(MAT_INITIAL_MATRIX);
307 LibmeshPetscCall(MatDestroy(&
_Q_scale));
308 create_q_scale_submat(MAT_INITIAL_MATRIX);
312 create_q_scale_submat(MAT_REUSE_MATRIX);
316 LibmeshPetscCall(ISDestroy(&pressure_is));
319 for (
auto & mat : intermediate_Qs)
320 LibmeshPetscCall(MatDestroy(&mat));
321 for (
auto & mat : intermediate_Ls)
322 LibmeshPetscCall(MatDestroy(&mat));
326 LibmeshPetscCall(PCFieldSplitGetSubKSP(schur_pc, &num_splits, &subksp));
328 mooseError(
"The number of splits should be two");
331 schur_complement_ksp = subksp[1];
335 mooseAssert(
_Q_scale,
"This should be non-null");
339 LibmeshPetscCall(KSPGetOperators(schur_complement_ksp, &S,
nullptr));
343 MatSchurComplementGetSubMatrices(S,
nullptr,
nullptr,
nullptr,
nullptr, &A11));
344 LibmeshPetscCall(MatAXPY(
_Q_scale, 1, A11, DIFFERENT_NONZERO_PATTERN));
347 LibmeshPetscCall(PCFieldSplitSetSchurPre(schur_pc, PC_FIELDSPLIT_SCHUR_PRE_USER,
_Q_scale));
350 LibmeshPetscCall(KSPSetOperators(schur_complement_ksp, S,
_Q_scale));
355 LibmeshPetscCall(KSPGetPC(schur_complement_ksp, &lsc_pc));
357 LibmeshPetscCall(PetscObjectTypeCompare(PetscObject(lsc_pc), PCLSC, &is_lsc));
359 mooseError(
"Not an LSC PC. Please check the 'schur_fs_index' parameter");
362 LibmeshPetscCall(PCGetOperators(lsc_pc,
nullptr, &lsc_pc_pmat));
367 mooseAssert(
_L,
"This should be non-null");
370 LibmeshPetscCall(PetscObjectCompose((PetscObject)lsc_pc_pmat,
"LSC_L", (PetscObject)
_L));
372 mooseAssert(
_have_mass_matrix,
"This is to verify we will enter the next conditional");
376 mooseAssert(
_Q_scale,
"This should be non-null");
380 PetscObjectCompose((PetscObject)lsc_pc_pmat,
"LSC_Qscale", (PetscObject)
_Q_scale));
385 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.