Repository navigation
Conversation
A field split has block solvers only after PCSetUp, and asking earlier is a PETSc error whose ~38-line banner is printed before the exception reaches Python, so `except` cannot hide it. Two paths reached it: - the viscoelastic Stokes solve checked the velocity preconditioner before solving (the #827 reproducer); - the custom-multigrid "still installed?" test, run before each solve, on a solver rebuilt by a consistent_jacobian change. Every notch run with a non-nested FMG tail printed it. fieldsplit_sub_ksps(pc) returns the blocks, or [] when there are none yet, with the banner silenced for that one call by a push/pop of the "return" handler (it still raises; it does not print). Both sites use it, and the viscoelastic check moves to after the solve, as on the plain path, so it now inspects a set-up split instead of always returning early. test_1077 fails on the unfixed code (two cases) and passes with the fix. Underworld development team with AI support from Claude Code
- Test the plain-path site: a consistent_jacobian change rebuilds the solver, the warm solve meets its tolerance with no linear solve, and the post-solve check asked the un-set-up split for its blocks. Fails unfixed (banner). - The helper is private (_fieldsplit_sub_ksps): _petsc_tools is star-imported into the uw namespace. - Docstring: how it works, with Parameters and Returns. - Review record. Behaviour change, by design: a viscoelastic solve on a mesh without a hierarchy now warns that the velocity block fell back to GAMG and records the fallback, as a plain solve already did. Before, its pre-solve check always returned early. Underworld development team with AI support from Claude Code
🔍 Architectural Review ChecklistThank you for submitting an architectural review! Reviewers should validate: Design & Architecture
Implementation
Testing & Validation
Documentation
Review Process: See CODE-REVIEW-PROCESS.md Approval: This PR merge = Review formally approved |
|
✅ Test Suite: success |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #827.
A field split has block solvers only after
PCSetUp. Asking an un-set-up split for them is a PETSc error, and PETSc prints its ~38-line "Object is in wrong state / Must call KSPSetUp() or PCSetUp() before calling PCFieldSplitGetSubKSP()" banner before the exception reaches Python, soexceptcould not hide it and healthy solves looked broken.Three paths reached it:
SNES_Stokes._check_velocity_preconditionerconsistent_jacobianchange rebuilt the solverconsistent_jacobianchange; every notch run with a non-nested gmsh FMG tail printed itcustom_mg._pcmg_still_installedChange.
_fieldsplit_sub_ksps(pc)inutilities/_petsc_tools.pyreturns the blocks, or[]when there are none yet, with the banner silenced for that one call: the"return"error handler still raises, it only stops the printing, and it is popped on every path. (The"ignore"handler that broke 23 tests in an earlier attempt turns errors into success; this does not.) Both sites use it, and the viscoelastic check moves to after the solve, as on the plain path.Behaviour change, by design. Before, the viscoelastic check always returned early, so a viscoelastic solve on a mesh without a hierarchy never reported that its velocity block was running GAMG. It now warns and records
velocity.fell_back_from_fmg, as a plain solve already did (once per process under the default warning filter).Tests.
tests/test_1077_quiet_unsetup_fieldsplit.pycaptures fd-level stderr. The three path tests fail on the unfixed code on the banner assertion and pass with the fix; a fourth checks the helper ([]before set-up, two blocks after). Related suites (multigrid, custom-MG hierarchy, rotated free-slip, MG option bundle, restore/continuation, viscoelastic): 77 passed, no banner. A real notch driver run with a gmsh tail: 1 banner before, 0 after.Adversarial review. Record in
docs/reviews/2026-10/subksp-banner-827-adversarial-review.md. Findings: the plain-path site was untested (fixed, test added); the helper leaked into theuwnamespace via a star import (fixed, now private); docstring (fixed); the viscoelastic warning is a behaviour change (kept, stated above). Failed attacks: handler stack restored on every path includingKeyboardInterrupt; np 2 and np 4 with no banner and no hang (set-up state followsPCSetUp, run on every rank);_pcmg_still_installedsemantics unchanged; the othergetFieldSplitSubKSPcall sites are all after asetUp, inside a solve, or already guarded; no import cycle.Not in this PR.
petsc_generic_snes_solvers.pyx(_discard_preconditioner_setup) carries an identical copy of the silencing pattern; left alone so the solver core is untouched in a bugfix. A follow-up can route it through the helper.stacklevel=3resolves tomemprobe.py, so every solve shares one warning location.test_0017_describe_and_render.py::test_every_family_describes_itself_at_the_class_levelfails whentest_1057_ddt_transport_plugin.pyran earlier in the same process. test_1057 defines a solver subclassTensorTransportwith no summary, and the description test enumerates every subclass.Checklist (UW3 Style Charter — docs/developer/UW3_STYLE_CHARTER.md)
level_*andtier_*markers (S8)maybe_/try_/do_) and no commented-out code (S3, S4).array/mesh.X.coords— nowith ....access(...), nomesh.data(S7)pixi.toml/pixi.lockor other dependency changes riding in an unrelated PRUnderworld development team with AI support from Claude Code