Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
074a660
smoother: volumetric-spring + Monge-Ampere metric redistribution
lmoresi May 17, 2026
f435101
smoother: metric-redistribution + Monge-Ampere diagnostics
lmoresi May 17, 2026
3e5233c
smoother: MA ~10x faster via factor-once-reuse direct sub-solves
lmoresi May 17, 2026
6f622b2
smoother: Phase-0 study — reject Newton/cofactor MA linearisation
lmoresi May 17, 2026
4e1c5f7
smoother: phi_degree=2 default (~2x cheaper, grading-identical); GAMG…
lmoresi May 17, 2026
f9aeb6e
smoother: P1×GAMG scaling check — P1 does not rescue GAMG; flag direc…
lmoresi May 17, 2026
663811e
smoother: add ma_show_grids.py — render MA-redistributed Annulus grids
lmoresi May 17, 2026
9e21ec2
smoother: document d/n anisotropy-blindness — rim radial over-collapse
lmoresi May 17, 2026
708df94
smoother: hi-res grid renderer — rim over-collapse is resolution-inde…
lmoresi May 17, 2026
7d9635e
smoother: localised features — GAMG robust + heavy-tailed monitor is …
lmoresi May 17, 2026
3b5da1b
smoother: polar metric + boundary slip — settled negative
lmoresi May 17, 2026
c1bf8ab
smoother: angular-OT target vs anisotropic scalar — (2) is a structur…
lmoresi May 17, 2026
62a6912
smoother: (3) metric-tensor construction from grad(rho) — verified
lmoresi May 17, 2026
3ba57fe
docs: add next-phase kickoff brief for the anisotropic mover (3)
lmoresi May 17, 2026
7091c6a
smoother: (3) anisotropic tensor mover — implementation + smoke
lmoresi May 17, 2026
f08e8ca
smoother: (3) mover — fixed-D damped MMPDE, robust defaults, validated
lmoresi May 18, 2026
e21201f
smoother: (3) mover — angular + non-separable validation
lmoresi May 18, 2026
988ecbf
docs: (3) anisotropic mover — implemented & validated
lmoresi May 18, 2026
05e9460
smoother: (3) blob target-metric vs realised diagnostic
lmoresi May 18, 2026
d8c48fc
smoother: (3) demo — Ra=1e5 annulus convection refined on ∇T
lmoresi May 18, 2026
5f97643
docs: (3) mover — Architecture / limitations / unexplored corners
lmoresi May 18, 2026
20da9f6
smoother: (3) mover — GAMG-parity + cost-per-step harness
lmoresi May 18, 2026
656785e
docs: (3) mover — GAMG validated + cost-per-step + 3D scope
lmoresi May 18, 2026
6320cdd
smoother: (3) demo — res-32 convection warm-started from res-16
lmoresi May 18, 2026
96f20bc
smoother: API lock-in for the anisotropic adaptation
lmoresi May 18, 2026
1ee8993
docs: node-snuggling adaptation alongside mesh.adapt
lmoresi May 18, 2026
896140f
smoother: adaptive-convection harness + next-phase kickoff brief
lmoresi May 18, 2026
4e8bc1d
harness: local-FE remap correction (interp) + Nu sign fix
lmoresi May 18, 2026
b312acd
saturation experiment, dynamic-adapt fixes, proper Nusselt
lmoresi May 18, 2026
65bf0e8
docs: complete mathematical formulation for mesh adaptation
lmoresi May 18, 2026
90df754
fix: amp is a no-op for the anisotropic mover (correct docs)
lmoresi May 18, 2026
ac9a849
sat: a16y — genuinely-stronger metric via the real levers + beta pass…
lmoresi May 18, 2026
494ac79
meshing+solvers: adapt strategies, gradient-side metric smoothing, an…
lmoresi May 21, 2026
900b4d8
scripts: stagnant-lid drivers and saturation harness updates
lmoresi May 21, 2026
d500c52
meshing: uw.meshing.follow_metric() — two-knob cell-size-envelope API
lmoresi May 21, 2026
6767261
meshing: per-cell Lagrangian rest-size spring fixes follow_metric ove…
lmoresi May 21, 2026
5de7cad
meshing: spring uses min-edge/max-edge per cell, sliver-aware in both…
lmoresi May 21, 2026
2129af6
mover: kill near-degenerate slivers — cap restore_w + area-floor back…
lmoresi May 21, 2026
0c31803
follow_metric: built-in Jacobi polish pass to clean residual slivers
lmoresi May 21, 2026
74766f4
follow_metric: adaptive Jacobi polish keyed to cell shape quality
lmoresi May 21, 2026
cc8572e
meshing+harness: spring + adaptive polish + dt-mult + perturbation IC…
lmoresi May 23, 2026
959c67d
meshing: OT-improvement step (_winslow_equidistribute) + MA fixes
lmoresi May 23, 2026
1d99d4e
scripts: OT-interleave + multi-res + level-isolation probes
lmoresi May 23, 2026
4b57d15
scripts: blob-then-sharp OT sweep — incremental OT validated
lmoresi May 23, 2026
17b98a5
meshing: land mesh.OT_adapt() — optimal-transport mesh adaptation
lmoresi May 25, 2026
d4e1cbf
solvers: guard + cache the constant nullspace (Copilot review, PR #209)
lmoresi May 25, 2026
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
85 changes: 85 additions & 0 deletions docs/advanced/mesh-adaptation.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,28 @@ for each edge vector $\mathbf{e}$. Edges that are too long get subdivided; regio
**Key insight**: Higher metric values produce finer mesh. If you want 10× refinement, the metric values should be ~100× larger (since $M \propto 1/h^2$).
```

### Two families of mesh adaptation

UW3 offers **two complementary** ways to put resolution where it is
needed:

| | `mesh.adapt(...)` (this page) | `smooth_mesh_interior(method="anisotropic")` |
|---|---|---|
| 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* |
| Topology | New mesh, **variables reset** (must transfer) | **Unchanged** — variables, DOFs, partition preserved |
| Grading reach | Strong (can add nodes → ~10×) | Capped by the node count (~1.5–2×) |
| Cell shape | Isotropic (`M = h⁻²I`) | **Anisotropic** — cells aligned to the feature |
| Cost | Re-mesh + full variable transfer | A few cheap SPD elliptic solves (no re-mesh) |
| Parallel | MMG re-partition | O(N), GAMG-parallelisable, no transfer |

Use `mesh.adapt` when you need a genuinely finer mesh (more
elements) and can afford to rebuild the problem. Use the
**node-snuggling** redistribution when you want to *reshape* the
existing mesh toward a feature every timestep cheaply, keeping the
topology (and all fields) intact — see the **Node redistribution**
section below.

---

## Metric Creation Functions
Expand Down Expand Up @@ -353,6 +375,69 @@ For the mathematically inclined, see the [Developer Design Document](../develope

---

## Node redistribution — the snuggling mover

When you want to concentrate resolution on an evolving feature
**every timestep** without re-meshing — keeping the topology and
all field data intact — use the anisotropic metric mover instead
of `mesh.adapt`:

```python
import underworld3 as uw
from underworld3.meshing import (
smooth_mesh_interior, metric_density_from_gradient)

# ... mesh + a temperature field T after some solve ...

# Relative target DENSITY from |∇T| (the fixed-node-budget
# analogue of metric_from_gradient: same percentile-window idea,
# but ρ is a *density*, not an absolute h — there is no node
# budget to spend on an absolute size).
rho = metric_density_from_gradient(mesh, T, amp=8.0)

# Move the nodes to that metric (topology / DOFs / variables
# all preserved — no transfer needed).
smooth_mesh_interior(
mesh, metric=rho, method="anisotropic",
method_kwargs=dict(aniso_cap=2.0, relax=0.2, n_outer=12))
```

`metric_density_from_gradient` builds
$\rho = 1 + \mathrm{amp}\cdot t$, $t = \mathrm{clip}\big((|\nabla
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
*changes* (boundary layers, fronts, plume edges), and is
isotropic-coarse at a smooth *peak* ($\nabla\rho=0$) — it
deliberately de-refines a feature's core. For core resolution a
curvature (Hessian) metric is the (future) tool. It also does
**not** beat the fixed node-count cap — for a *separable* feature
the explicit 1-D OT is exact and cheaper; the mover earns its keep
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
{doc}`/developer/design/mesh-adaptation-formulation`; operational
detail in {doc}`/developer/subsystems/mesh-metric-redistribution`;
the dated R&D log in
`docs/developer/design/ma-newton-cofactor-exploration.md`.

---

## References

1. MMG Platform: https://www.mmgtools.org/
Expand Down
888 changes: 888 additions & 0 deletions docs/developer/design/ma-newton-cofactor-exploration.md

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading