The MMPDE mover's line-search accept test uses a single ABSOLUTE collapse floor derived from the median cell volume:
a0_own_med = float(np.median(np.abs(signed_vol(coords, cells_own))))
a0_own_med = _global_mean(a0_own_med) # mean of PER-RANK medians
a_min_floor = float(area_floor_frac) * a0_own_med
...
if np.all(np.isfinite(trial)) and _min_area(trial) > a_min_floor:
Two defects.
-
It disables the mover on any graded mesh. The floor is 0.01 x median cell volume. 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 therefore fails the test, the line search backtracks to scale=0, and the mover returns having moved nothing — with no warning. Observed on a 5-level graded 2D box: mmpde outer 1/8: I=1.991126e+00 dI=+0.00e+00 scale=0.000 max|dx|=0.00e+00, then exit.
-
It is partition-dependent. _global_mean of per-rank medians is not the global median, so which cells fall foul of the floor depends on how cells are distributed across ranks. The same mesh moved at np=1 and stood completely still at np=2.
This affects redistribute_nodes / node_redistribution generally, not just new code — any strongly-graded mesh.
Fix: floor each cell against ITS OWN starting volume (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 since a positive ratio certifies positive volume.
Reproducer: 2D UnstructuredSimplexBox(cellSize=0.2, refinement=1), adapt(fault_metric, max_levels=5), then any redistribute_nodes(...); compare max|dx| at np=1 vs np=2.
Found while building shape relaxation on top of the mover.
The MMPDE mover's line-search accept test uses a single ABSOLUTE collapse floor derived from the median cell volume:
Two defects.
It disables the mover on any graded mesh. The floor is
0.01 x median cell volume. Anything out ofmesh.adapthas finest cells orders of magnitude below the median, so those cells start already under the floor. Every trial step therefore fails the test, the line search backtracks toscale=0, and the mover returns having moved nothing — with no warning. Observed on a 5-level graded 2D box:mmpde outer 1/8: I=1.991126e+00 dI=+0.00e+00 scale=0.000 max|dx|=0.00e+00, then exit.It is partition-dependent.
_global_meanof per-rank medians is not the global median, so which cells fall foul of the floor depends on how cells are distributed across ranks. The same mesh moved at np=1 and stood completely still at np=2.This affects
redistribute_nodes/node_redistributiongenerally, not just new code — any strongly-graded mesh.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 since a positive ratio certifies positive volume.Reproducer: 2D
UnstructuredSimplexBox(cellSize=0.2, refinement=1),adapt(fault_metric, max_levels=5), then anyredistribute_nodes(...); comparemax|dx|at np=1 vs np=2.Found while building shape relaxation on top of the mover.