Skip to content

feat(meshing): purposeful adapt/redistribution naming — node_redistribution + engine-less adapt()#372

Merged
lmoresi merged 7 commits into
developmentfrom
feature/purposeful-adapt-naming
Jul 16, 2026
Merged

feat(meshing): purposeful adapt/redistribution naming — node_redistribution + engine-less adapt()#372
lmoresi merged 7 commits into
developmentfrom
feature/purposeful-adapt-naming

Conversation

@lmoresi

@lmoresi lmoresi commented Jul 16, 2026

Copy link
Copy Markdown
Member

Stacked on #371 (chore/retire-superseded-movers) — the redistribution entry point depends on the pruned dispatch. Re-target to development after #371 merges (or merge in order 371 → this).

Ruling

Maintainer naming ruling, 2026-07-16: user-facing names state the capability; algorithm names (NVB, MMPDE) live in internals and docstrings. Quote on the architecture: the mesh-controlled method "will be how we allow meshes to control how they can be modified".

What this adds

Item Detail
uw.meshing.node_redistribution(mesh, metric, ...) New user entry (exported, in __all__); thin dispatch to the mesh-controlled method
Mesh.redistribute_nodes(metric, **kwargs) New method; base implementation: 2D simplex (triangle) meshes → the MMPDE mover via the existing smooth_mesh_interior machinery; quad/hex, 3D simplex, constrained manifolds → honest NotImplementedError stating what exists and what doesn't (each guard message names the 2D-simplex support and points at mesh.adapt for topology change)
Engine-less mesh.adapt() mesh.adapt(metric, max_levels=...) works without engine=. Default engine is NVB on 2D meshes; engine= remains accepted, documented as an advanced/internal selector. Verified at post-#369 base: the default was still "sbr", so this is a real change, not docs-only
smooth_mesh_interior Stays (it is the machinery, not a wrong name); docstring points users at node_redistribution; no deprecation warning
Retirement message The retired-mover ValueError from #371 now names node_redistribution as the replacement

Decision surfaced for review

NVB is 2D-only this pass, so a blanket NVB default would have made every engine-less 3D adapt() raise where SBR previously worked. The default is therefore dimension-aware: engine=None resolves to "nvb" when cdim == 2, "sbr" otherwise (commented at the resolution site). Explicit engine= is always honoured. If the ruling intended a hard NVB default even in 3D, say so and I'll change it.

tests/test_0835_sbr_adapt_on_top.py (the SBR engine's own contract file, written under the old implicit default) now pins engine="sbr" on all 13 adapt() calls.

Tests (new: tests/test_0764_node_redistribution.py, level_1 tier_a, 7 tests)

  • 2D simplex: node_redistribution moves nodes, topology preserved, zero warnings (DeprecationWarning-as-error guard);
  • free function ≡ mesh method (bit-identical twin-mesh result);
  • StructuredQuadBoxNotImplementedError (match "2D simplex");
  • 3D simplex box → NotImplementedError;
  • namespace export contract;
  • engine-less adapt() returns a child (child.parent is base);
  • engine-less child is bit-identical to an explicit engine="nvb" child.

Docs

docs/advanced/mesh-adaptation.md, the adaptive-meshing and adapt-on-top-faults skills now teach the purposeful spellings first (algorithm names second, as implementation detail); CHANGELOG entry.

Gates (strictly serial; amr-dev env)

Gate Base (= #371 branch) This PR
pytest tests/ -m "level_1 and tier_a" 390 passed / 11 skipped / 1 xfailed 397 passed / 11 skipped / 1 xfailed (+7 = the new 0763 tests; nothing lost)
Adapt batch (0763, 0834, 0835, 0836, 0850) all green
np2 tests/test_0839_nvb_parallel_adapt.py 6 passed
Style-gate scanner green green (no allowlist change)
pixi run docs-build green (one pre-existing toc warning only)

Underworld development team with AI support from Claude Code

lmoresi added 2 commits July 15, 2026 23:11
…closes #346, #353)

Maintainer ruling 2026-07-16 (retirement: mmpde superseded spring/MA/OT
via the isotropic-metric equivalence; deletion sign-off given
2026-07-16).

Deleted: smoothing/{spring,monge_ampere,anisotropic}.py, meshing/
_ot_adapt.py, mesh.OT_adapt / OT_adapt_reset_reference (tombstone
raises RuntimeError), tests/test_0760_mesh_ot_adapt.py, the WC-13
spring-shim tests.

BEHAVIOUR CHANGE (sanctioned): smooth_mesh_interior's default method=
is now 'mmpde' (was 'spring'). Retired method spellings raise a clear
ValueError naming the replacement; strategy= now routes to mmpde
(fixes #353's TypeError); #346's latent spring MPI deadlock dies with
the file. follow_metric now drives the MMPDE mover (theta=0.5, pure
equidistribution weighting for its scalar-density contract).

Kept: the graph-Laplacian Jacobi smoother, the MMPDE mover, the Taubin
surface smoother, all metric builders (fault_comb_metric,
fault_metric_tensor, metric_density_from_gradient). Boundary-facet /
slip primitives moved from _ot_adapt.py to smoothing/graph.py.

Style-gate allowlist shrank by the deleted files' four entries;
scanner green with no stale entries.

Gates: serial 'level_1 and tier_a' 390 passed / 11 skipped / 1 xfailed;
smoothing batch green; np2 test_0855 to follow.

Underworld development team with AI support from Claude Code
…bution + engine-less adapt()

Maintainer naming ruling 2026-07-16: user-facing names state the
CAPABILITY; algorithm names (NVB, MMPDE) live in internals and docs.

- New user entry uw.meshing.node_redistribution(mesh, metric, ...),
  a thin dispatch through the new mesh-controlled method
  Mesh.redistribute_nodes(metric, **kwargs) — the architecture by
  which meshes control how they can be modified. Base implementation:
  2D simplex -> the MMPDE mover via smooth_mesh_interior; quad/hex,
  3D, manifolds -> honest NotImplementedError stating what exists.
  Exported from meshing/__init__ (+__all__). smooth_mesh_interior
  stays as the machinery (docstring points at the new entry; no
  deprecation warning — it is not a wrong name).
- mesh.adapt(metric, max_levels=...) needs no engine=: default engine
  is NVB on 2D meshes (NVB is 2D-only this pass, so 3D resolves to
  SBR — an engine-less 3D adapt keeps working); engine= stays as the
  advanced/internal selector. test_0835 (the SBR contract file) pins
  engine='sbr' explicitly.
- Retirement ValueError now points at node_redistribution.
- New contract tests tests/test_0763_node_redistribution.py (7 tests,
  level_1 tier_a). Docs + skills teach the purposeful spellings first.

Gates: serial 'level_1 and tier_a' 397 passed / 11 skipped / 1 xfailed
(PR 1 baseline 390/11/1 + the 7 new tests); np2 test_0839 6 passed;
scanner green; docs build green.

Underworld development team with AI support from Claude Code
lmoresi added 3 commits July 15, 2026 23:49
…afe follow_metric envelope bound

CI runs tests/test_07*/test_08* by file range without marker filtering,
which caught two unmarked tests (test_0762_bounding_surfaces,
test_0763_boundary_slip_correctness) importing the deleted
meshing._ot_adapt for the relocated slip helpers — repointed to
meshing.smoothing. The follow_metric envelope bound is widened to 1.5x
target: the MMPDE mover's achieved h_min is platform-dependent
(1.27x on macOS, 1.40x on Linux CI at refinement=2); the bound now
catches over-refinement and gross under-refinement, not platform
jitter.

Local CI-mirror batches green: tests/test_07* 314 passed / 2 skipped /
8 xfailed / 1 xpassed; tests/test_08* 408 passed / 10 skipped /
11 xfailed.

Underworld development team with AI support from Claude Code
…as taken by boundary_slip_correctness)

Underworld development team with AI support from Claude Code
@lmoresi
lmoresi changed the base branch from chore/retire-superseded-movers to development July 16, 2026 18:13
lmoresi added 2 commits July 16, 2026 08:14
…identical content plus this PR's edits

Underworld development team with AI support from Claude Code
…nt SBR fallback

Maintainer ruling 2026-07-17: an engine-less 3D adapt must say honestly
that default adaptive refinement is 2D-only (3D refinement is committed
future work), rather than silently selecting a different algorithm.
engine='sbr' remains the explicit 3D opt-in. Regression test added.

Underworld development team with AI support from Claude Code
Copilot AI review requested due to automatic review settings July 16, 2026 18:23

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.

@lmoresi
lmoresi merged commit bc6f644 into development Jul 16, 2026
2 checks passed
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