Skip to content

refactor(pyx-safe): naming, docs, dead code in the solver layer (D-14..22, WA-05..09, WA-18)#366

Merged
lmoresi merged 15 commits into
developmentfrom
feature/pyx-safe
Jul 15, 2026
Merged

refactor(pyx-safe): naming, docs, dead code in the solver layer (D-14..22, WA-05..09, WA-18)#366
lmoresi merged 15 commits into
developmentfrom
feature/pyx-safe

Conversation

@lmoresi

@lmoresi lmoresi commented Jul 15, 2026

Copy link
Copy Markdown
Member

The last remediation group of the 2026-07 quality campaign that can run without the maintainer present: naming, comments/docstrings, dead code, and byte-identical dedents ONLY, in the Cython solver layer. The structural multi-solver unification (D2, rows D-23..D-28) remains OUT of scope per maintainer ruling and is untouched. Base: development @ 045eac0.

Per-row status

Row Status Notes
D-14 done _maybe_install_snes_update -> _attach_snes_update_hook — the exact name used on the unmerged feature/snes-update-callbacks tip (b82acea), so its rebase stays trivial. Rename only (2 sites); allowlist entry removed (see below).
D-15 done Explicit if u_Field is None: ... else: ... in SNES_Scalar.__init__; SNES_Vector auto-create switched from truthiness to is None (WC-10 verified the auto-create already existed). Behaviour-identical: the Unknowns.u setter ignores None (verified in source). The suspicious num_components=mesh.dim on the default SCALAR var is kept and flagged TODO(BUG).
D-16 done The Picard/else Stokes solve tails verified byte-identical with diff FIRST (14 lines each), then dedented to run once; the misleading # Now go back to the original plan comment replaced with one that states the control flow.
D-17 done F1 guard property message now says F1 (was a copy-paste of F0). Error-path only.
D-18 done One class-level _convergence_reasons = {code: (NAME, explanation)} (contents identical to the fuller of the two old copies); get_snes_diagnostics and _warn_on_divergence both format from it. No external consumers (grep).
D-19 done _nondimensional_time helper; the six copies verified verbatim (5 at one indent, 1 deeper) before extraction; nothing parameterized.
D-20 done dim -> cdim in the three scopes that bind mesh.cdim (add_nitsche_bc, SNES_Vector._setup_pointwise_functions — which bound both names to the same value — and SNES_MultiComponent._setup_pointwise_functions); no topological mesh.dim use exists inside any of them (verified). Stale line ~173 comment now refers to _setup_discretisation by name.
D-21 done Four editorial musings deleted or converted to TODO(DESIGN): (the Vector/Scalar-unification musing now points at the deferred D-23..D-28 rows).
D-22 done (D-doc only) snes_max_it = 50 clobber commented: hardcoded, silently overrides user petsc_options each solve; respecting the user setting is deferred to the benchmarked D2 sub-wave per ruling D18. No behaviour change.
WA-05 done Four raise("string") (a TypeError at raise time) -> TypeError/ValueError with messages verbatim: add_condition f_id (TypeError), c_type (ValueError), components fallback (TypeError), _get_dof_partition_by_field_id section_type (ValueError).
WA-06 done Both if True: # c_label and label_val != -1: constant guards deleted, bodies dedented (SNES_Vector + Stokes DS wiring).
WA-07 done Fossil commented-out blocks deleted; the clearDS/createDS "destroys field registrations" rationale KEPT (reworded to be self-contained) and the flux-like-BC one-line intent note KEPT, per the row. Comment-only.
WA-08 done xmlrpc.client.Boolean, sympify (only qualified sympy.sympify is used), TypeAlias, class_or_instance_method — each verified unreferenced, deleted.
WA-09 done Empty 'robust'/'fast' pass branches deleted; unknown strategy -> ValueError; the kaskade-vs-additive pc_mg_type divergence commented ("do not change without benchmarking"). No option VALUES changed. No internal/test code assigns .strategy (grep), so the ValueError has no reachable caller today.
WA-18 done Dead triple-quoted petsc_dm_get_periodicity block + its ## Todo ! header deleted from petsc_discretisation.pyx.
stray (#344 follow-up) done uw.pprint(0, msg) in petsc_dm_find_labeled_points_local passed 0 as a message (proc is keyword-only); dropped — same fix as the x8 in #344.

Mechanical verification (dedup/dedent commits)

Every dedup/dedent commit was verified beyond the test gates:

  • WA-06 — cythonized the pyx pre/post and diffed the generated C with line bookkeeping normalized (__PYX_ERR/lineno numbers, goto labels, comments stripped): remaining hunks are exclusively code-object first-line metadata shifted by the two deleted guard lines and constant-pool repacking. The generated function bodies are identical (Cython constant-folds if True:).
  • WA-07 — same stripped-C diff: only docstring-table identifiers that embed source line numbers (..._line_3057 -> ..._line_3033) plus metadata; bodies identical (comment-only change).
  • D-16 — stripped-C diff with every hunk mapped to its enclosing generated C function: all code-body changes fall inside SNES_Stokes_SaddlePt.solve (the duplicated call sequence collapsing to a single dedented copy, same operations in the same order).
  • D-18 — runtime probe on the built extension: get_snes_diagnostics output identical to the pre-change table for every reason code in -12..5; _warn_on_divergence identical except codes -9/-10/-11, which now print DIVERGED_DTOL / DIVERGED_JACOBIAN_DOMAIN / DIVERGED_TR_DELTA instead of UNKNOWN(...) — precisely the gap READ-72 flagged (code 0 remains unreachable there).
  • D-19 — runtime probe: _nondimensional_time equals the old inline logic for float, int, np.float64, Pint Quantity, and UWQuantity inputs.

Gates (identical pre/post; env rebuilt rm -rf build/ && ./uw build before every gated run; suites strictly serial)

Gate Base (045eac0) Tip
pytest -m "level_1 and tier_a" 376 passed, 12 skipped, 2 xfailed, 1 xpassed 376 passed, 12 skipped, 2 xfailed, 1 xpassed
Solver-facing serial batch (test_0641 + test_1010-1065 families, 30 files) 174 passed, 6 failed*, 2 xfailed 174 passed, 6 failed* (same six), 2 xfailed
mpirun -np 2 pytest --with-mpi (test_1017/1062/1064 parallel) 13 passed 13 passed
Style gate scripts/check_deprecated_patterns.py green (87 allowlisted) green (86 allowlisted)

* The six failures are pre-existing at base (confirmed by two independent base runs): test_1051_VE_shear_box (order2_converges, order2_better_than_order1, steady_state_approach) and test_1052_VEP_stability_regression (vep_yield_lock_fixed_dt, vep_snes_no_divergence_loading_through_yield, pure_ve_variable_dt_accuracy) — the known VE/VEP territory.

Allowlist ratchet — first shrink

D-14 removes the src/underworld3/cython/petsc_generic_snes_solvers.pyx:hedging-name entry from scripts/deprecated_pattern_allowlist.txt (87 -> 86 allowlisted hits); the scanner verified green with the entry gone.

Note for maintainers

bugfix/yield-homotopy (KEEP_ACTIVE) edits this file and will need a shallow rebase — all changes here are local (renames, comment/dead-code deletion, two small data-motion extractions); no reordering or signature changes. feature/snes-update-callbacks rebases trivially by construction (D-14 chose its name).

Underworld development team with AI support from Claude Code

lmoresi added 15 commits July 14, 2026 17:23
…update_hook (D-14)

Charter S3 bans hedging prefixes (maybe_/try_/do_). The name chosen is the
one already used on the unmerged feature/snes-update-callbacks tip
(b82acea), so that branch's rebase stays trivial. Rename only — the method
body, its docstring, and the single call site in _snes_solve_with_retries
are otherwise untouched.

Also removes the now-satisfied hedging-name allowlist entry for this file
from scripts/deprecated_pattern_allowlist.txt — the ratchet's first shrink
(87 -> 86 allowlisted hits; scanner verified green with the entry gone).

Underworld development team with AI support from Claude Code
Line 1 of the flagship solver file was 'from xmlrpc.client import Boolean'.
Also removes the unused 'sympify' (the one live use is the qualified
sympy.sympify), 'TypeAlias', and 'class_or_instance_method' imports —
each verified unreferenced in the file (READ-70).

Underworld development team with AI support from Claude Code
…ion error paths (WA-05)

raise('...') is itself a TypeError at raise time ('exceptions must derive
from BaseException'), swallowing the diagnostic. Each site now raises a
real exception with the message text kept verbatim (READ-21):

- add_condition f_id type check                     -> TypeError
- add_condition c_type value check                  -> ValueError
- add_condition components fallback                 -> TypeError
- _get_dof_partition_by_field_id section_type check -> ValueError

Error-path only; no reachable behaviour change for valid arguments.

Underworld development team with AI support from Claude Code
Copy-paste of the F0 base-class guard pointed developers at the wrong
term (READ-71). Error-path message only.

Underworld development team with AI support from Claude Code
…es (WA-06)

'if True: #  c_label and label_val != -1:' wrapped the natural-BC
DS-wiring blocks in SNES_Vector._setup_discretisation and
SNES_Stokes_SaddlePt's equivalent — a constant-literal guard adding a
spurious indent level and implying a condition that no longer exists
(READ-14). Cython constant-folds the guard, so this is byte-identical.

Mechanical verification: cythonized the file pre/post and diffed the
generated C with line-number bookkeeping normalized (__PYX_ERR/lineno,
goto labels, comments stripped). Remaining hunks are exclusively
code-object first-line metadata shifted by the two deleted lines and the
compressed constant-pool repacking; the generated function bodies are
identical.

Underworld development team with AI support from Claude Code
Comment-only deletions per LE-13 / READ-24 / LE-15 (git keeps the history):

- SNES_Vector.solve: 13-line dead rebuild path; dead clearDS()/createDS()
  code (its 'destroys field registrations' rationale KEPT, reworded to be
  self-contained)
- whole commented-out add_essential_p_bc method (Stokes)
- SNES_Scalar natural-BC flux-Jacobian sketch (the one-line
  'different user-interface for flux-like bcs' intent note KEPT)
- old f0/F1 Array-form constructions in Scalar/Vector/Stokes
  _setup_pointwise_functions; FP1 pu_G2/pu_G3 fossils (one-line intent
  note kept); Stokes __init__ zero-matrix fossils
- commented debug prints, 'with mesh.access' one-liners (7),
  bc_label/getStratumIS alternates, coarse_dm.createDS() one-liner,
  dead attribute assignments (# self.u = u_Field triplet,
  # self._constitutive_model = None x3)

Mechanical verification: cythonized pre/post; normalized diff contains
only docstring-table identifiers that embed source line numbers,
code-object first-line metadata, and constant-pool repacking — the
generated function bodies are identical (comment-only change).

Underworld development team with AI support from Claude Code
…nstructors (D-15)

SNES_Scalar.__init__ created a default unknown then unconditionally
re-assigned 'self.Unknowns.u = u_Field' — correct only because the
Unknowns.u setter silently ignores None (READ-22). Now an explicit
if/else. SNES_Vector's auto-create used truthiness ('if not u_Field:');
now the explicit 'is None' contract, with a comment noting the supplied
field is assigned earlier in the constructor (WC-10 confirmed the
auto-create already existed — this row is readability only).

The suspicious num_components=mesh.dim on the default SCALAR variable is
kept as-is (load-bearing until reviewed) and flagged with a TODO(BUG).

Underworld development team with AI support from Claude Code
… tail (D-16)

The picard and else branches of SNES_Stokes_SaddlePt.solve ended with a
byte-identical 14-line tail (verified with diff before the change); the
'# Now go back to the original plan' comment sat at the wrong indent,
misleading about control flow (READ-29). The common tail now runs once
after the optional Picard warmup — verbatim code motion — and the comment
states the actual control flow.

Mechanical verification: cythonized pre/post; mapped every C diff hunk to
its enclosing generated function — all code-body changes fall inside
SNES_Stokes_SaddlePt.solve (the duplicated call sequence collapsing to a
single copy at outer indentation, same operations in the same order);
remaining hunks are constant-pool/code-object line metadata.

Underworld development team with AI support from Claude Code
Comment-only (D-doc). The Stokes solve path pushes a hardcoded
snes_max_it=50 to petsc_options each solve, overriding user settings
(READ-30). The behaviour change (respect the user's option) was deferred
with the D2 benchmarked sub-wave per maintainer ruling D18; the comment
records that and points at the worklist rows.

Underworld development team with AI support from Claude Code
…both consumers (D-18)

Two divergent tables lived in SolverBaseClass (READ-72): the 16-entry
'NAME - explanation' local map in get_convergence_diagnostics and the
12-entry compact class map used by _warn_on_divergence (-9/-10/-11 and 0
missing). Now a single class-level table code -> (NAME, explanation),
contents identical to the fuller copy; get_convergence_diagnostics
formats 'NAME - explanation' from it and _warn_on_divergence uses the
NAME. No external consumers (verified by grep).

Only reachable output delta: _warn_on_divergence now names codes
-9/-10/-11 (DIVERGED_DTOL / DIVERGED_JACOBIAN_DOMAIN / DIVERGED_TR_DELTA)
instead of printing UNKNOWN(...) — the gap the review flagged. Code 0
remains unreachable there (early return for reason >= 0). Runtime probe
of both consumers across all reason codes runs post-build (recorded in
the PR).

Underworld development team with AI support from Claude Code
…m copies (D-19)

The Pint/UWQuantity -> float time conversion snippet was copy-pasted six
times across the solve/residual paths (READ-73); all six verified
verbatim (modulo indentation) before extraction. The helper body is the
snippet unchanged — nothing parameterized. Call sites now read
't_nd = self._nondimensional_time(time)'.

Runtime probe (post-build, recorded in the PR): helper output equals the
old inline logic for float, int, Pint Quantity, and UWQuantity inputs.

Underworld development team with AI support from Claude Code
… (D-20)

Three method scopes bound a local named 'dim' to the EMBEDDING dimension
mesh.cdim (READ-76): SNES_Vector.add_nitsche_bc,
SNES_Vector._setup_pointwise_functions (which bound both 'dim' and 'cdim'
to the same value), and SNES_MultiComponent._setup_pointwise_functions.
Purely lexical rename within those scopes (no topological mesh.dim use
exists inside any of them — verified); the duplicate binding is gone and
shape-check error messages now say cdim, which is the accurate term on
manifold meshes.

Also fixes the stale '...FE element construction at line ~173' comment to
refer to _setup_discretisation by name (Charter S4: no line-number
references).

Underworld development team with AI support from Claude Code
…s (D-21)

Charter S4 bans editorial musings in comments (READ-74):
- 'LM: this is probably not something we need...' above SNES_Vector ->
  TODO(DESIGN) pointing at the deferred unification rows D-23..D-28
- 'Why is this here - this is not generic at all ??' ->
  TODO(DESIGN) on _setup_history_terms placement
- 'F0, F1 should be f0 and F1... uf0, uF1 are redundant' ->
  TODO(DESIGN) on residual-term naming
- trailing 'probably just needs to boot the DM...' musing deleted

Comment-only.

Underworld development team with AI support from Claude Code
… the Stokes strategy setter (WA-09)

The strategy setter carried empty '(Reserved)' branches ('robust'/'fast'
-> pass) — speculative generality banned by Charter S5 (READ-23). The
names remain accepted (all three configure the identical bundle, now
stated in a comment); an unknown name raises ValueError instead of
silently configuring 'default'. No option VALUES changed anywhere.

Also comments the long-standing kaskade-vs-additive pc_mg_type divergence
between this setter and __init__'s velocity block: kept as-is, not to be
changed without benchmarking.

No internal or test code assigns .strategy (verified by grep), so the new
ValueError has no reachable caller today.

Underworld development team with AI support from Claude Code
…x stray pprint positional proc (WA-18 + #344 follow-up)

- Deletes the module-level triple-quoted string holding the never-runnable
  petsc_dm_get_periodicity sketch and its content-free '## Todo !'
  introduction (LE-16). Git keeps the code if DM periodicity reading is
  ever wanted.
- petsc_dm_find_labeled_points_local: uw.pprint(0, msg) passed 0 as a
  *message* (proc is keyword-only, default 0), printing a stray leading
  '0'. Same fix as applied x8 elsewhere in the #344 Copilot pass.

Underworld development team with AI support from Claude Code
Copilot AI review requested due to automatic review settings July 15, 2026 04:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants