@@ -173,6 +173,12 @@ 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+ #if !PETSC_VERSION_LESS_THAN (3 , 20 , 0 )
177+ // Get the nesting level of this PC's KSP
178+ PetscInt level ;
179+ LibmeshPetscCallA (comm , PCGetKSPNestLevel (pc , & level ));
180+ #endif
181+
176182 // Check if hypre ams/ads, otherwise we quit with nothing to do
177183 if (pc_type && std ::string (pc_type ) == PCHYPRE )
178184 {
@@ -205,7 +211,8 @@ void PetscPreconditioner<T>::set_petsc_aux_data(PC & pc, System & sys, const uns
205211 set_hypre_ads_data (pc , sys , v );
206212 }
207213 }
208- else if (pc_type && std ::string (pc_type ) == PCFIELDSPLIT )
214+ #if !PETSC_VERSION_LESS_THAN (3 , 20 , 0 )
215+ else if (pc_type && std ::string (pc_type ) == PCFIELDSPLIT && !level )
209216 {
210217 // Annoyingly, if using Schur complement preconditioning, we need to call PCSetUp()
211218 auto pmatrix = cast_ptr < PetscMatrixBase < T > * > (sys .request_matrix ("System Matrix" ));
@@ -219,17 +226,23 @@ void PetscPreconditioner<T>::set_petsc_aux_data(PC & pc, System & sys, const uns
219226 KSP * subksps ;
220227 LibmeshPetscCallA (comm , PCFieldSplitGetSubKSP (pc , & n_splits , & subksps ));
221228
229+ // We assume a one-to-one map between splits and variables
230+ if (sys .n_vars () != n_splits )
231+ return ;
232+
222233 // Get the sub PC context for each split and recursively call this function
223234 for (auto s : make_range (n_splits ))
224235 {
225236 PC subpc ;
226237 LibmeshPetscCallA (comm , KSPGetPC (subksps [s ], & subpc ));
238+ LibmeshPetscCallA (comm , PCSetKSPNestLevel (subpc , level + 1 ));
227239 set_petsc_aux_data (subpc , sys , s );
228240 }
229241
230242 // Free the array of sub KSP contexts
231243 LibmeshPetscCallA (comm , PetscFree (subksps ));
232244 }
245+ #endif
233246}
234247
235248
0 commit comments