fix(mmpde): per-cell collapse floor — mover was a silent no-op on graded meshes (#419)#420
fix(mmpde): per-cell collapse floor — mover was a silent no-op on graded meshes (#419)#420lmoresi wants to merge 1 commit into
Conversation
…ded meshes (#419) The MMPDE line-search accept test used a single ABSOLUTE collapse floor, `area_floor_frac x median cell volume`, with the median taken as a `_global_mean` of per-rank medians. Two defects followed. Any graded mesh disabled the mover outright. Anything out of `mesh.adapt` has finest cells orders of magnitude below the median, so those cells start already under the floor; every trial step failed the test, the line search backtracked to `scale=0`, and the mover returned having moved nothing — with no warning: mmpde outer 1/8: I=1.991126e+00 dI=+0.00e+00 scale=0.000 max|dx|=0.00e+00 And the behaviour depended on the partition, since a mean of per-rank medians is not the global median: the same mesh moved at np=1 and stood completely still at np=2. Floor each cell against its OWN starting volume instead — no cell may shrink below `area_floor_frac` of what it started as. Scale-free, grading-free, partition-independent, and still a strict no-fold certificate (a positive ratio certifies positive volume). The kwarg keeps its name and default; only its reference changes. This affected `redistribute_nodes` / `node_redistribution` generally, not just new code. Found while building shape relaxation on the mover. Underworld development team with AI support from Claude Code
Adversarial review (author, pre-review)Trying to break my own fix. Four things a reviewer should push on. 1. 2. It caps how much redistribution one call can do. A cell cannot shrink below 1% of its entry volume in this call, no matter what the metric asks. Repeated calls compose fine, but a single 3. Degenerate input cells. 4. The test does not actually reproduce the original parallel failure. The sharpest form of this bug was partition-dependent: np=1 moved, np=2 did not. My test is serial and only asserts "a graded mesh moves". It would catch a reintroduced median-based floor, but it would not catch a re-introduction of a partition-dependent reduction. A proper regression would compare Also not fixed here: the mover still emits no warning when the line search backtracks to What I am confident about: the no-fold guarantee is preserved (a positive volume ratio certifies positive volume), the reduction is partition-independent by construction, and the empty-rank path is handled ( |
Closes #419.
The bug
The MMPDE line-search accept test used a single absolute collapse floor derived from the median cell volume:
1. It disabled the mover on any graded mesh. The floor is 1% of the median cell volume. Anything out of
mesh.adapthas finest cells orders of magnitude below the median, so they start already under the floor. Every trial step was rejected, the line search backtracked toscale=0, and the mover returned having moved nothing — silently:2. It was partition-dependent. A
_global_meanof per-rank medians is not the global median, so which cells fell foul of the floor depended on how cells were spread across ranks. The same mesh moved at np=1 and stood completely still at np=2.This affected
redistribute_nodes/node_redistributiongenerally, not just new code.The fix
Floor each cell against its own starting volume: no cell may shrink below
area_floor_fracof what it started as. Scale-free, grading-free, partition-independent, and still a strict no-fold certificate — a positive ratio certifies positive volume.area_floor_frackeeps its name and default; only its reference changes.Tests
New
tests/test_0751_mmpde_graded_area_floor.py(level_1, tier_a):test_mover_moves_on_a_graded_mesh— asserts the mesh is genuinely graded first, so the test cannot pass without exercising the floor, then asserts the mover actually moves.test_collapse_guard_still_rejects_folding— the guard must still do its job: no cell folds, and none collapses below the documented fraction of its own start.54 existing tests pass across the mover,
follow_metric, graded adapt and mesh smoothing.Reviewer notes
min(initial=np.inf)in_min_area_fracis deliberate: a rank owning no cells must contribute the identity for the global MIN rather than raising on an empty reduction.area_floor_frac=0.01now means something stricter in the fine region than it used to (1% of a small cell, not 1% of the median), so a previously-accepted step that shrank a fine cell hard will now be backtracked. That is the intended reading, but it is a behaviour change for well-graded meshes that were already moving.scale=0for any other reason. A silent no-op is hard to diagnose — probably worth a follow-up warning.Underworld development team with AI support from Claude Code