Stokes_Constrained.multiplier_schur_pc is a documented public property. It is read — at one site it swaps the multiplier block's Pmat term to the 1/μ Schur mass:
hh_pc = self._pp_G0 if self._multiplier_schur_pc else self._hh_G0[k]
PetscDSSetJacobianPreconditioner(ds.ds, fid, fid, ext.fns_jacobian[i_jac[hh_pc]], NULL, NULL, NULL)
So it is not dead code. But we could not construct a case where it changes anything.
Measured
Annulus, Stokes_Constrained with add_constraint_bc on both arcs (2 multipliers present, so the loop above is reached), snes_type=ksponly:
| configuration |
flag=False → flag=True |
| constant viscosity |
|u|, |p|, outer KSP its all identical |
| η contrast 1e4 |
identical — including the solve failing identically both ways (DIVERGED_LINEAR_SOLVE, 100 KSP its) |
| η contrast 1e6 |
identical, 4 KSP its both |
assembled |Pmat| (η contrast 1e3) |
identical to 12 digits |
The flag reads back correctly (True/False round-trip), so it is recorded.
Also notable in the same runs: |Pmat| equalled |J| exactly in both settings, despite Pmat being a distinct matrix.
Why this is filed as verify-or-remove rather than as a bug
The negative could be honest — two good Schur preconditioners can both converge in four iterations on a problem this easy, and we may simply not have found the discriminating case. The comment at the call site says the point is to reuse pressure's already-compiled 1/μ term "so there is NO extra JIT term", which suggests the motivation was compile cost rather than convergence.
But per the "identical cells are a common defect, never 'this variable does not matter'" rule that found #477, four identical rows across two decades of viscosity contrast is not evidence the flag works.
So: either produce the case where it earns its keep — and add it as a test, so the next audit does not re-open this — or remove the property. A public flag nobody can demonstrate an effect for is the same class as #477 and solver.strategy: accepted, recorded, and invisible if it is doing nothing.
Context worth knowing for whoever picks this up: Stokes_Constrained deliberately rejects saddle_preconditioner ("the Schur preconditioner is built automatically (selfp + the 1/viscosity mass from constitutive_model.K)"), so that class owns its Schur preconditioner by design. multiplier_schur_pc is the one hook left into it.
Found by the property-inertness pass of the solver configuration audit — docs/reviews/2026-07/solver-configuration-reachability-audit.md, Phase 3 (#485). Repro: ~/+Simulations/solver_reachability_audit/property_inertness_fair.py.
Underworld development team with AI support from Claude Code
Stokes_Constrained.multiplier_schur_pcis a documented public property. It is read — at one site it swaps the multiplier block's Pmat term to the 1/μ Schur mass:So it is not dead code. But we could not construct a case where it changes anything.
Measured
Annulus,
Stokes_Constrainedwithadd_constraint_bcon both arcs (2 multipliers present, so the loop above is reached),snes_type=ksponly:flag=False→flag=True|u|,|p|, outer KSP its all identical|Pmat|(η contrast 1e3)The flag reads back correctly (
True/Falseround-trip), so it is recorded.Also notable in the same runs:
|Pmat|equalled|J|exactly in both settings, despitePmatbeing a distinct matrix.Why this is filed as verify-or-remove rather than as a bug
The negative could be honest — two good Schur preconditioners can both converge in four iterations on a problem this easy, and we may simply not have found the discriminating case. The comment at the call site says the point is to reuse pressure's already-compiled 1/μ term "so there is NO extra JIT term", which suggests the motivation was compile cost rather than convergence.
But per the "identical cells are a common defect, never 'this variable does not matter'" rule that found #477, four identical rows across two decades of viscosity contrast is not evidence the flag works.
So: either produce the case where it earns its keep — and add it as a test, so the next audit does not re-open this — or remove the property. A public flag nobody can demonstrate an effect for is the same class as #477 and
solver.strategy: accepted, recorded, and invisible if it is doing nothing.Context worth knowing for whoever picks this up:
Stokes_Constraineddeliberately rejectssaddle_preconditioner("the Schur preconditioner is built automatically (selfp + the 1/viscosity mass fromconstitutive_model.K)"), so that class owns its Schur preconditioner by design.multiplier_schur_pcis the one hook left into it.Found by the property-inertness pass of the solver configuration audit —
docs/reviews/2026-07/solver-configuration-reachability-audit.md, Phase 3 (#485). Repro:~/+Simulations/solver_reachability_audit/property_inertness_fair.py.Underworld development team with AI support from Claude Code