Uh oh!
There was an error while loading. Please reload this page.
Rotated and block constraints are exclusive; remove four dead label lookups - #590
Conversation
…p dead label lookups Two independent fixes in the same boundary-condition code. #464. add_rotated_freeslip_bc, add_fault_bc and add_constraint_bc could all be called on the same solver and nothing checked. The rotated driver builds its own index-set fieldsplit over velocity and pressure and build_rotation addresses them by field number, so a block constraint's multiplier DOFs are in neither index set and the preconditioner is built over a strict subset of the operator's rows. The two impose the same wall-normal condition by different means, so _reject_mixed_constraint_mechanisms refuses the combination at whichever call comes second, naming both. test_0062 covers both orderings and, as controls, that several rotated boundaries and several block constraints are each still allowed. With the guard neutered the solver accepts one rotated boundary condition and one multiplier together and says nothing, which is what the issue reports. #506. bc_is = bc_label.getStratumIS(value) was assigned at four sites in petsc_generic_snes_solvers.pyx and read at none; bc_label at those sites existed only to produce it. A stratum IS beside a collective DS registration invites a rank-local skip, which is why the issue asks for it to go. Closes#464, #506. Underworld development team with AI support from Claude Code
lmoresi
commented
Aug 16, 2026
Adversarial reviewReviewed at 1. The guard is registration-time only, so it can be bypassed. It fires from 2. 3. Removing the dead lookups changes nothing observable, which is also the Checked and clean: nothing in Underworld development team with AI support from Claude Code |
The registration checks only cover what goes through the solver's own methods, and fault_contact writes _fault_contact_faults directly rather than through add_fault_bc. The dispatch is where both lists are read together, so it carries the check as well: registration gives the better message, the dispatch gives the guarantee. It runs as the first statement of solve(), before any setup touches either list, so an unsupported pair costs nothing before it is refused. Underworld development team with AI support from Claude Code
lmoresi
commented
Aug 16, 2026
Finding 1 above is addressed at Findings 2 and 3 stand as written. Underworld development team with AI support from Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Closes#464. Closes#506.
Two independent fixes in the same boundary-condition code, both small and both
in
petsc_generic_snes_solvers.pyx.#464 — the two constraint mechanisms are now exclusive
add_rotated_freeslip_bc,add_fault_bcandadd_constraint_bccould all becalled on one solver and nothing checked.
The rotated driver builds its own index-set fieldsplit over exactly two fields
(
rotated_bc._solve_rotated_iterative), andbuild_rotationaddresses velocityand pressure by field number. A block constraint registers a multiplier field of
its own; those DOFs are in neither index set, so the preconditioner is built over
a strict subset of the operator's rows with nothing said about it. Both
mechanisms impose the same wall-normal condition, so the combination is a
configuration error rather than a case to support — supporting it would need a
third split for the multipliers and a
build_rotationthat knows about them._reject_mixed_constraint_mechanismsonSNES_Stokes_SaddlePtrefuses whichevercall comes second, naming what is already registered and what was refused. The
fault path is covered too, since
add_fault_bcreaches the same rotated driver.The same check runs as the first statement of
solve(). The registration checksonly cover what goes through the solver's own methods, and
fault_contactwrites_fault_contact_faultsdirectly rather than throughadd_fault_bc; the dispatchis where both lists are read together. Registration gives the better message — it
knows which call was refused — and the dispatch gives the guarantee. Running it
first means an unsupported pair costs nothing before it is refused.
tests/test_0062_rotated_constraint_exclusivity.pycovers both orderings, andboth single-mechanism controls: several rotated boundaries on one solver, and
several block constraints on one solver, are each still allowed. Without those a
guard that refused everything would pass.
The negative control is what shows there was something to fix. Neutering
_reject_mixed_constraint_mechanismsand repeating the first case:#506 — four dead label lookups
bc_iswas assigned at four sites and read at none;bc_labelat those sitesexisted only to produce it. Nine lines removed. The issue's reason for wanting
them gone is that a stratum IS sitting beside a collective DS registration
invites a rank-local skip —
getStratumISreturns nothing on a rank that holdsno part of the stratum, and the obvious next edit is to
continueon that.Verified
./uw test: 1498 passed, 32 skipped, 2 xfailed — the branch baselineplus the five new tests.
test_0641_wave_c_api_shims.pyuses each on a different solver.Underworld development team with AI support from Claude Code