@@ -173,6 +173,10 @@ void PetscPreconditioner<T>::set_petsc_aux_data(PC & pc, System & sys, const uns
173173 PCType pc_type = nullptr ;
174174 LibmeshPetscCallA (comm , PCGetType (pc , & pc_type ));
175175
176+ // Get the nesting level of this PC's KSP
177+ PetscInt level ;
178+ LibmeshPetscCallA (comm , PCGetKSPNestLevel (pc , & level ));
179+
176180 // Check if hypre ams/ads, otherwise we quit with nothing to do
177181 if (pc_type && std ::string (pc_type ) == PCHYPRE )
178182 {
@@ -205,7 +209,7 @@ void PetscPreconditioner<T>::set_petsc_aux_data(PC & pc, System & sys, const uns
205209 set_hypre_ads_data (pc , sys , v );
206210 }
207211 }
208- else if (pc_type && std ::string (pc_type ) == PCFIELDSPLIT )
212+ else if (pc_type && std ::string (pc_type ) == PCFIELDSPLIT && ! level )
209213 {
210214 // Annoyingly, if using Schur complement preconditioning, we need to call PCSetUp()
211215 auto pmatrix = cast_ptr < PetscMatrixBase < T > * > (sys .request_matrix ("System Matrix" ));
@@ -219,11 +223,18 @@ void PetscPreconditioner<T>::set_petsc_aux_data(PC & pc, System & sys, const uns
219223 KSP * subksps ;
220224 LibmeshPetscCallA (comm , PCFieldSplitGetSubKSP (pc , & n_splits , & subksps ));
221225
226+ // We assume a one-to-one map between splits and variables
227+ if (sys .n_vars () != n_splits )
228+ return ;
229+
222230 // Get the sub PC context for each split and recursively call this function
223231 for (auto s : make_range (n_splits ))
224232 {
225233 PC subpc ;
226234 LibmeshPetscCallA (comm , KSPGetPC (subksps [s ], & subpc ));
235+ #if PETSC_VERSION_LESS_THAN (3 , 25 , 0 )
236+ LibmeshPetscCallA (comm , PCSetKSPNestLevel (subpc , level + 1 ));
237+ #endif
227238 set_petsc_aux_data (subpc , sys , s );
228239 }
229240
0 commit comments