Skip to content

Free surface in 3D: spherical shell support, dimension-general surface machinery, and the 2D compatibility-floor fix - #469

Open
lmoresi wants to merge 4 commits into
developmentfrom
feature/free-surface-3d
Open

Free surface in 3D: spherical shell support, dimension-general surface machinery, and the 2D compatibility-floor fix#469
lmoresi wants to merge 4 commits into
developmentfrom
feature/free-surface-3d

Conversation

@lmoresi

@lmoresi lmoresi commented Jul 29, 2026

Copy link
Copy Markdown
Member

What this is

Workstream C first pass (Louis + Claude; @gthyagi for review): uw.systems.FreeSurface runs end to end on a 3D spherical shell, built by making the surface machinery dimension-general rather than porting it piecewise. On the way, the 2D strong-datum compatibility floor was fully resolved (three stacked causes, each measured before fixed).

The 2D fix (rides first, benefits everything)

Strong-datum consistent solves on a deforming ring stalled honestly at rel ~2e-3, residual 100% in the pressure rows (block-split evidence). Three causes, closed in order, each verified by rerunning the power-law acceptance:

  1. Trace-mass gauge — the demean weights become the P1 lumped boundary mass accumulated per owned DMPlex facet (necessary; measured not dominant).
  2. Directed flux strip (maintainer ruling) — the datum's mean volume flux through the deformed facet normals is stripped with the same FE surface integral the residual uses (Φ = ∮ũ_n(n̂·Γ)ds, S = ∮(n̂·Γ)ds, mesh.Gamma), so the constrained field carries exactly zero discrete net flux.
  3. Pressure-gauge quotient convergence — the constant-pressure mode is projected out of every increment by the inner KSP (it is the gauge of an enclosed domain) and is not exactly a left-nullvector on a deformed faceted boundary; the outer loop now measures the quotient-space residual, mirroring PETSc's projected residual for singular systems.

Result: every step of the power-law annulus acceptance converges (3, 3, then 1 warm-started increment per step; previously honest stalls).

The 3D machinery

  • Surface mean/demean: reduction over owned-facet partial trace-mass weights — each facet counted exactly once globally, two scalar allreduces, no gather, no ordering. Same code is the 2D line gauge and the 3D area gauge.
  • σ_nn on the 3D P2 trace: new boundary_flux mass="p1" — P1-projected recovery (edge-midpoint loads folded exactly onto vertices via the P1⊂P2 interpolation transpose; sound P1 lumped triangle mass; midpoints read back as the P1 interpolant). Chosen over mass="consistent" because the P2 vertex-integral checkerboard (Fix 3D boundary reaction flux recovery #404 hold) sits exactly at the vertices the P1 h∞ field consumes. The manager translates its lumped default to p1 on 3D meshes.
  • 2D-only features refused per piece (ring Taubin filter, tangential transport) instead of the blanket dim != 2 guard; the ring's gather generalises via lexicographic coordinate keys for its remaining diagnostic uses.
  • Interior carrier reads the deform displacement by direct nodal row map (no on-node point evaluation — the uw.function.evaluate returns wrong values for P1 fields at points exactly on cell edges (3D) #432 3D exposure class — and no per-step global location).

Evidence (~/+Simulations/FreeSurface/spherical_fs/)

Spherical Y20 topographic relaxation (constant-density shell, background_buoyancy="analytic", resolved timestep): clean exponential decay at rate 6.1–8.2 vs the half-space Cathles reference 12.5 — an O(1) shell/fixed-base correction in the physically correct direction — with the equilibrium modal bias falling 16.3% → 2.2% of A0 over one resolution step (matching the 2D production-resolution figure of ~2.4%; the #431-class discrete recovery defect, resolution-convergent, not structural).

Tests: new test_1072 (3D capability, 17s); full 2D battery green throughout (test_1018 18/18, 1070, 1071 serial; 1070 + 1066 at np2 and np4 for the quadrature/datum tests).

Deliberately delegated to the review/benchmarking pass (maintainer decision)

This PR ships the capability with first-evidence physics; the detailed benchmarking is left open, and this is the note recording that decision:

Related: #457 (TI consistent tangent, found during workstream B) still limits Newton-rate claims for anisotropic rheology in any dimension.

An adversarial review follows as the first comment.

🤖 Generated with Claude Code

Underworld development team with AI support from Claude Code

lmoresi added 4 commits July 29, 2026 13:12
…ension-general)

_ring_weights becomes the P1 lumped boundary mass accumulated per OWNED facet
from the plex (edge length/2 in 2D; triangle area/3 in 3D - the same code is
the 3D area-weighted gauge), on live coordinates. Seam weights are assembled
by summing per-rank partial contributions (_ring_gather gains op="sum";
ghost facets excluded via the point SF so each facet counts exactly once
globally). The quadrature test's invariant changes to the meaningful one:
the gauge total equals the FE boundary measure of the deformed POLYGON
(BdIntegral), not the ideal-circle arc length.

Honest finding from the acceptance rerun: the deformed-ring compatibility
floor (rel ~2e-3, 100% pressure-row) SURVIVES this fix at unchanged levels -
the demean weighting was not the dominant term. Remaining suspect: the
nodal-normal (analytic radial) vs facet-normal mismatch on the deformed
polygon - the constraint fixes u.rhat at nodes while the discrete flux
functional integrates u.n_facet, and the mismatch involves the free
tangential velocity, so no nodal demean of the datum can zero it. Recorded
in the acceptance README; formulation question for review.

Tests: test_1070 serial (6+1) + np2 (7) + quadrature np4; surface metrics at
strong level throughout.

Underworld development team with AI support from Claude Code
… quotient convergence — deformed-ring floor resolved

The compatibility floor (strong-datum consistent solves stalling honestly at
rel ~2e-3 on the deformed ring, residual 100% in the pressure rows) had TWO
stacked causes beyond the demean weights, resolved here:

1. The datum's DIRECTED mean: the divergence rows enforce the flux through
   the deformed FACET normals while the constraint fixes u.n along the nodal
   (analytic) normal. The datum is now shifted by Phi/S with
   Phi = BdIntegral(u_n_target * (n_node . Gamma)) and
   S = BdIntegral(n_node . Gamma) — the same FE surface integral the residual
   uses (maintainer ruling: strip the mean volume-flux term, computed fully
   consistently), so the constrained field carries exactly zero discrete net
   flux. Strong-constraint path only; collective, rank-identical shift.

2. The outer residual is now measured in the pressure-gauge QUOTIENT space
   when the constant-pressure nullspace is active: the inner KSP projects the
   constant mode from every increment (the gauge of an enclosed domain), so
   the outer loop cannot reduce that component and must not measure it — on a
   deformed faceted boundary it is not exactly zero (free tangential DOFs
   carry flux through the node-vs-facet normal mismatch) and an unprojected
   norm floors against the constant offset, stalling the line search. Mirrors
   PETSc's own projected residual for singular systems. The sigma_nn reaction
   stash stays unprojected.

Measured: power-law annulus FS acceptance now CONVERGES at every step
(3, 3, then 1 Newton increment per warm-started step, no warnings) with
surface metrics at strong-datum level (err 1.1e-2 ~ isoviscous 7.9e-3,
penalty 0.49; net flux 7.4e-4).

Tests: test_1018 18/18; test_1070+1071 serial; test_1070+1066 np2 (9).

Underworld development team with AI support from Claude Code
…rface machinery + P1-projected sigma_nn recovery

The FreeSurface manager now runs on a 3D spherical shell end to end (first
smoke: two full solve/advance steps, physically sensible h_inf). The blanket
dim!=2 guard is replaced by per-piece capability checks; the two genuinely
2D-only features (tangential transport, ring Taubin filter) are refused
explicitly in 3D.

- Surface mean/demean: reduction over OWNED-facet partial trace-mass weights
  (each facet counted exactly once globally, two scalar allreduces) - no
  gather, no ordering, dimension-general. The ordered ring survives only for
  the 2D-only features; its gather/dedup machinery generalises to 3D via
  lexicographic rounded-coordinate keys (deterministic order + exact
  same-node grouping; the 2D s-ordering and seam handling are unchanged).
- Geometry helpers route through _radial (CYLINDRICAL2D or SPHERICAL):
  radial height/deform direction on shells, last-axis on boxes - already
  dimension-general otherwise.
- sigma_nn on a 3D P2 trace: new boundary_flux mass="p1" - P1-PROJECTED
  recovery: fold each edge-midpoint load onto its edge vertices (exact
  interpolation transpose, load-conserving), de-smear with the sound P1
  lumped triangle mass, read midpoints back as the P1 interpolant. Chosen
  over mass="consistent" because the P2 vertex-integral checkerboard (#404
  hold) sits exactly at the vertices the P1 h_inf field consumes. The
  manager translates its "lumped" default to "p1" on 3D meshes; 2D maps
  "p1" to the sound lumped line mass.
- The interior carrier reads the deform displacement by DIRECT nodal row map
  (built once; falls back to point evaluation only if the carrier nodes do
  not coincide with the mesh coordinate nodes) - removes the on-node
  point-evaluation exposure (#432 class) and a per-step global location.

Tests: 2D battery green (test_1018 + 1070 + 1071 serial = 25; 1070 + 1066
np2 = 9). 3D shell smoke in ~/+Simulations/FreeSurface/spherical_fs/.

Underworld development team with AI support from Claude Code
…e 3D free surface

test_1072: end-to-end shell loop (finite mean-free h_inf under the trace-mass
gauge, surface moves toward equilibrium, bounded) + explicit refusal of the
2D-only features. The quantitative benchmarking (analytic Y_lm shell rate,
bias convergence, low-Ra spherical convection, 3D parallel) is deliberately
delegated to the review pass - evidence and scripts in
~/+Simulations/FreeSurface/spherical_fs/.

Underworld development team with AI support from Claude Code
Copilot AI review requested due to automatic review settings July 29, 2026 06:19

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 commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Adversarial review (pre-review, per house practice)

Ordered by how much each should worry the reviewer.

1. The quotient-space convergence measure is doing load-bearing work. The 2D floor fix's third leg declares convergence while a physically-real (small) incompatibility remains in the pressure-gauge component. This is standard for projected singular systems, and the component is minimized by the directed flux strip — but nothing REPORTS its size per solve. A user whose deformed geometry develops a large gauge-mode residual would see "converged" with no hint. Worth a follow-up: log the projected component's magnitude when it exceeds, say, rtol·reference.

2. The P1-projected σ_nn recovery is validated by physics, not by an exact oracle. The fold-down is exact as a load transfer (interpolation transpose), but its recovery ACCURACY on curved 3D traces is only evidenced by the Y20 benchmark's behaviour (right direction, resolution-convergent bias matching the 2D figure). No manufactured-traction test exists for the 3D path the way the SolCx topography test pins 2D. The delegated benchmarking should include one.

3. 3D parallel is untested. All 3D evidence is serial. The surface-mean reduction and the lex-key gather are collective-by-construction, but the empty-boundary-rank path (a rank owning no piece of the surface) has never actually executed — annulus partitions at np2/np4 always give every rank boundary. A spherical shell at np4+ is the first genuine test, and it is explicitly in the delegated list.

4. The benchmark's fitted rate is not resolution-converged (8.2 at res 0.2, 6.1 at res 0.15, half-space reference 12.5): the O(1) shell correction claim is qualitative. The floor's clean 16%→2.2% convergence is the strong quantitative result; the rate needs the delegated study before any analytic comparison is asserted.

5. Smaller items. The 3D lex-key gather assumes the surface deforms only along the normal (ordering built once — same assumption as the 2D ring, inherited, documented). The mass="p1" mode returns midpoint values as P1 interpolants — correct for the P1 h∞ consumer, but a caller wanting genuine P2 pointwise recovery must use "consistent" and inherit the checkerboard risk; the error message says so. estimate_dt is CFL-based and can hop the entire relaxation in one L-stable step (correct but surprising — the benchmark README documents it; a rate-based dt suggestion is a possible ergonomic follow-up). The refused-in-3D features raise at construction, not import, so a 2D script switched to a 3D mesh fails at the right moment with a named alternative.

What is well-covered: the 2D regression surface (every prior test green throughout, serial and np2, including the re-derived quadrature invariant); the three-cause floor fix each verified by measurement rather than assertion; capability pinned by test_1072 at 17s.

Underworld development team with AI support from Claude Code

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