Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .claude/skills/adaptive-meshing/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ uw.meshing.smooth_mesh_interior(mesh, metric=M, method="mmpde",
slip_surfaces=True, skip_threshold=None) # tensor metric: do the skip check yourself
```

Pitfalls that make it "not work": `method="anisotropic"`/`"ot"` (shred/sliver — use
mmpde); injecting `relax`/`n_outer` (starves mmpde's CG); `strategy=` instead of
Pitfalls that make it "not work": `method="anisotropic"`/`"ot"`/`"spring"`/`"ma"`
(RETIRED 2026-07 — they now raise ValueError; mmpde is the default and only
metric mover); injecting `relax`/`n_outer` (starves mmpde's CG); `strategy=` instead of
`refinement=R` (under-grades); a scalar bump for a fault (refines a fat corridor,
leaves the centre coarse); signed `Surface.distance.sym` for `d` (bleeds along the
line extension — use a direct unsigned distance). Full rationale + the rest of the
Expand Down
35 changes: 14 additions & 21 deletions docs/advanced/mesh-adaptation.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ for each edge vector $\mathbf{e}$. Edges that are too long get subdivided; regio
UW3 offers **two complementary** ways to put resolution where it is
needed:

| | `mesh.remesh(...)` (this page) | `smooth_mesh_interior(method="anisotropic")` |
| | `mesh.remesh(...)` (this page) | `smooth_mesh_interior(method="mmpde")` |
|---|---|---|
| Mechanism | **Re-mesh** (MMG): insert/remove/retriangulate | **Redistribute** the existing nodes (move only) |
| Node budget | *Changes* — targets an **absolute** edge length `h` | **Fixed** — relative redistribution to a target *density* |
Expand Down Expand Up @@ -405,9 +405,10 @@ smooth_mesh_interior(mesh, metric=rho, method="mmpde",
```{tip}
**`method="mmpde"` is the default mover** (since this release): the
variational moving-mesh adaptation of Huang & Kamenski. It is
dimension-general (2D/3D), matrix-free (no PETSc solve — small
per-cell dense algebra plus a parallel `Vec` assembly), provably
non-folding, and — uniquely among the movers here — genuinely
matrix-free (no PETSc solve — small per-cell dense algebra plus a
parallel `Vec` assembly), provably non-folding, currently 2D
(triangle meshes; the method itself is dimension-general but the
3D discretization is not implemented), and genuinely
*clusters and aligns* to an **anisotropic tensor** metric. It is
both the most capable and the most straightforward to reason about,
which is why it is now the default. Pass a **scalar** density (as
Expand All @@ -417,13 +418,13 @@ above; it is promoted to the isotropic tensor `ρ·I`) or a `d×d`
long-along refinement. Full design + derivation:
{doc}`/developer/design/anisotropic-mmpde-mover`.

The earlier movers remain available via `method=`:
`"spring"` (fast volumetric equant-cell smoother), `"ma"`
(isotropic Monge–Ampère), `"ot"` (linear OT-improvement step),
`"anisotropic"` (decoupled-Winslow tensor smoother — reshapes but
does not cluster). Use them only when you specifically need their
behaviour; `"mmpde"` supersedes `"anisotropic"` for fault / front
refinement.
The earlier movers — `"spring"` (volumetric equant-cell smoother),
`"ma"` (isotropic Monge–Ampère), `"ot"` (linear OT-improvement
step) and `"anisotropic"` (decoupled-Winslow tensor smoother) —
were **retired in 2026-07**: `"mmpde"` with a scalar metric
reproduces their isotropic equidistribution, and with a tensor
metric it clusters and aligns where they could not. The retired
spellings now raise a `ValueError` pointing here.

Key `mmpde` knobs (via `method_kwargs`): `p` (functional exponent,
1.5–2), `theta` (Huang alignment/equidistribution balance, 1/3),
Expand All @@ -439,9 +440,6 @@ T| - g_{lo})/(g_{hi}-g_{lo}),0,1\big)$ with $g_{lo},g_{hi}$ the
lo/hi percentiles of $|\nabla T|$ — deliberately the same shape as
{py:func}`underworld3.adaptivity.metric_from_gradient`, so the
*intent* you express is identical whichever family you choose.
The mover then builds a gradient-derived **anisotropic tensor**
metric internally and solves an M-weighted Laplace (Winslow)
coordinate map.

```{important}
This is a **gradient** metric: it resolves where the field
Expand All @@ -455,13 +453,8 @@ on general non-separable features and on cell-alignment / quality
(it never produces slivers).
```

Key knobs (via `method_kwargs`): `aniso_cap` (max cell anisotropy
— the binding stability lever; ≈2 robust, ≳6 folds), `relax`
(damping), `n_outer` (composed damped steps), `linear_solver`
(`"direct"` MUMPS, or `"gamg"` for the parallel-scalable path —
validated bit-parity). The full mathematical derivation (OT /
Monge–Ampère, the metric-tensor / Winslow mover, dynamic field
handling, Nusselt) is in
The full mathematical derivation (including the retired OT /
Monge–Ampère and Winslow movers, kept as an R&D record) is in
{doc}`/developer/design/mesh-adaptation-formulation`; operational
detail in {doc}`/developer/subsystems/mesh-metric-redistribution`;
the dated R&D log in
Expand Down
4 changes: 2 additions & 2 deletions docs/advanced/multigrid-preconditioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ re-discretising on the coarse mesh. `pc_mg_galerkin = both` does this.

This is the key reason to prefer FMG when you adapt:

- The coordinate-deforming adaptation movers (Winslow / anisotropic /
`OT_adapt` / `follow_metric`) **preserve mesh topology**. The refinement
- The coordinate-deforming adaptation movers (the MMPDE mover /
`follow_metric`) **preserve mesh topology**. The refinement
hierarchy survives them, so geometric multigrid keeps working as the mesh
deforms — precisely where GAMG struggles with the resulting anisotropy.
- A **true remesh** (a topology change) collapses the hierarchy to a single
Expand Down
24 changes: 24 additions & 0 deletions docs/developer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@ This log tracks significant development work at a conceptual level, suitable for

## 2026 Q3 (July – September)

### Retired Interior Movers — MMPDE Is the Mover (July 2026)

**The superseded fixed-topology interior movers were retired** (maintainer
ruling 2026-07): the spring-equilibrium, Monge–Ampère, OT-improvement-step
and anisotropic-Winslow movers were deleted, together with `mesh.OT_adapt()`
(built on the OT step; closes #346, whose latent MPI deadlock dies with the
spring mover, and #353, whose `strategy=` TypeError dies with the dispatch).

- `smooth_mesh_interior(method=...)` now defaults to **`"mmpde"`** (was
`"spring"`) — a sanctioned behaviour change: with a scalar metric the
MMPDE mover reproduces the retired movers' isotropic equidistribution
(the isotropic-metric equivalence), and with a tensor metric it clusters
and aligns where they could not. Retired spellings raise a `ValueError`
naming the replacement.
- `follow_metric(...)` (the two-knob adapter) now drives the MMPDE mover;
`mesh.OT_adapt()` raises a `RuntimeError` tombstone pointing at
`follow_metric` / `smooth_mesh_interior` / `mesh.adapt`.
- The graph-Laplacian Jacobi smoother and the Taubin surface-field smoother
(`smooth_surface_field`) are separate, current tools and are unchanged.
- The boundary-facet / boundary-slip primitives shared with surviving code
moved from `meshing/_ot_adapt.py` into `meshing/smoothing/graph.py`;
the style-gate allowlist shrank by the deleted files' entries.


### July 2026 Quality Campaign — Audit, Style Charter, Remediation Waves (July 2026)

**A systematic post-development-burst quality campaign**: six adversarially
Expand Down
5 changes: 5 additions & 0 deletions docs/developer/design/ma-newton-cofactor-exploration.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Monge–Ampère mesh redistribution: Newton/cofactor linearisation

> **RETIRED movers note (2026-07):** the spring / Monge-Ampère / OT-step /
> anisotropic-Winslow interior movers this document discusses were retired
> (superseded by `method="mmpde"`, the default). Kept as the R&D record;
> the code lives in git history before the retirement commit.

> **Status**: exploration (Phase 0), `feature/winslow-mesh-smoother`,
> 2026-05-17. Companion to
> `docs/developer/subsystems/mesh-metric-redistribution.md` (the
Expand Down
5 changes: 5 additions & 0 deletions docs/developer/design/mesh-adaptation-formulation.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Mesh adaptation by metric-driven node redistribution — mathematical formulation

> **RETIRED movers note (2026-07):** the spring / Monge-Ampère / OT-step /
> anisotropic-Winslow interior movers this document discusses were retired
> (superseded by `method="mmpde"`, the default). Kept as the R&D record;
> the code lives in git history before the retirement commit.

**Status**: Reference (current, 2026-05) — the mathematical formulation for the implemented `smooth_mesh_interior` family (`meshing/smoothing.py`).

> **Scope.** This is the self-contained *mathematical* reference for the
Expand Down
7 changes: 6 additions & 1 deletion docs/developer/design/ot-adapt-api-proposal.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
---
title: "Mesh.OT_adapt() — public API proposal"
date: 2026-05-24
status: proposal
status: retired (2026-07 — OT_adapt removed; superseded by the MMPDE mover)
---

> **RETIRED movers note (2026-07):** the spring / Monge-Ampère / OT-step /
> anisotropic-Winslow interior movers this document discusses were retired
> (superseded by `method="mmpde"`, the default). Kept as the R&D record;
> the code lives in git history before the retirement commit.

# `mesh.OT_adapt()` — public API proposal

## Background
Expand Down
17 changes: 12 additions & 5 deletions docs/developer/subsystems/mesh-metric-redistribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,25 @@ which remeshes / changes topology).

> **Mathematics:** the full derivations (optimal-transport /
> Monge–Ampère, the volumetric spring, the anisotropic
> metric-tensor / Winslow mover, the gradient-metric construction,
> dynamic field handling, and the Nusselt diagnostic) are in
> metric-tensor / Winslow mover — all retired 2026-07 — the
> gradient-metric construction, dynamic field handling, and the
> Nusselt diagnostic) are in
> {doc}`/developer/design/mesh-adaptation-formulation`. This page is
> the operational guide.

> **Retirement note (2026-07):** the `spring`, `ma`, `ot` and
> `anisotropic` movers described in the historical sections below
> were retired — superseded by `method="mmpde"` (the default),
> whose scalar-metric behaviour reproduces their isotropic
> equidistribution. The retired spellings raise a `ValueError`.
> Sections describing them are kept as the R&D record.

```python
import underworld3 as uw
from underworld3.meshing import smooth_mesh_interior

smooth_mesh_interior(mesh, metric=f, method="spring") # fast
smooth_mesh_interior(mesh, metric=f, method="ma") # robust
smooth_mesh_interior(mesh, metric=f, method="anisotropic") # cleanest, aligned
smooth_mesh_interior(mesh, metric=f) # mmpde (default)
smooth_mesh_interior(mesh, metric=M_tensor) # tensor metric: aligned
```

## When to use it
Expand Down
4 changes: 2 additions & 2 deletions docs/developer/subsystems/meshing.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ This section needs:

- [Metric-driven mesh redistribution](mesh-metric-redistribution.md)
— topology-preserving node redistribution toward a target
size/density field (`smooth_mesh_interior`; spring &
Monge–Ampère methods). Restores the grading of a deformed
size/density field (`smooth_mesh_interior`; the variational
MMPDE mover). Restores the grading of a deformed
adapted mesh or bunches nodes ~2× at a feature; contrast
`mesh.adapt()` which remeshes.

Expand Down
6 changes: 1 addition & 5 deletions scripts/deprecated_pattern_allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ src/underworld3/tests/test_adaptivity_metrics.py:access-context
src/underworld3/discretisation/discretisation_mesh.py:mesh-data

# --- hedging-name (Charter S3) ---------------------------------------------
# Four `_do_move()` local closures in the mesh-mover machinery.
# `_do_move()` local closures in the mesh-mover machinery (three sites).
src/underworld3/discretisation/discretisation_mesh.py:hedging-name
src/underworld3/meshing/_ot_adapt.py:hedging-name
src/underworld3/meshing/smoothing/api.py:hedging-name

# --- except-pass (Charter S4) ----------------------------------------------
Expand All @@ -46,9 +45,6 @@ src/underworld3/function/_function.pyx:except-pass
src/underworld3/function/expressions.py:except-pass
src/underworld3/function/quantities.py:except-pass
src/underworld3/function/unit_conversion.py:except-pass
src/underworld3/meshing/_ot_adapt.py:except-pass
src/underworld3/meshing/smoothing/anisotropic.py:except-pass
src/underworld3/meshing/smoothing/monge_ampere.py:except-pass
src/underworld3/meshing/surfaces.py:except-pass
src/underworld3/model.py:except-pass
src/underworld3/scaling/_scaling.py:except-pass
Expand Down
Loading
Loading