Integrate CitcomS predictor-corrector into unified Eulerian SUPG - #689
Integrate CitcomS predictor-corrector into unified Eulerian SUPG#689gthyagi wants to merge 21 commits into
Conversation
Use one public AdvDiffusionSUPG class and one F0/F1 assembly for implicit CN/BE/BDF and explicit CitcomS updates. Preserve the P1 positive lumped mass, gamma=0.5 two-correction update, directional tau and conservative timestep estimate, cached PETSc vectors and geometry. Replace the former implementation with compatibility imports; no duplicate solver remains. Register timestep-estimator and integrator snapshot state, omit unused CitcomS DDt history, retain explicit BDF selection and custom tau, and validate incompatible settings. Add frozen-source triangle/tetrahedron equivalence and in-memory/disk restart tests. Replace the MPI Gaussian cross-host golden value with a same-host serial reference without loosening the threshold. Validation: rebuilt Mac worktree; 25 unified/API tests passed, 13 residual tests passed, seven MPI tests passed per rank including the Gaussian regression, and nine expanded two-rank migration/snapshot tests passed per rank. Style gate and diff whitespace checks passed. Gadi coupled benchmarks and memory gate are still pending; this is not a production-acceptance claim. Underworld development team with AI support from OpenAI Codex.
Select backward Euler explicitly for quasi-steady manufactured and high-Peclet tests. Check the public generic tau expression instead of the removed P0 implementation detail. Compare spherical serial/MPI values on the same host and cached triangulation; keep manufactured convergence as the absolute accuracy gate. Apply the same near-machine-precision implicit replay tolerance as the unified snapshot tests. Syntax and whitespace checks pass; Gadi numerical validation remains pending.
The Gadi eight-rank migration gate failed before any timestep because the tiny triangle fixture leaves unsupported local simplex layouts on some ranks. Propagate layout errors to every rank before entering timestep reductions. Increase the equivalence fixture resolution and add a separate empty-partition rejection regression. Preserve numerical algorithms and tolerances. Rebuilt locally; Gadi validation pending.
Gadi preserved snapshot fields exactly but a rebuilt CN solve differed by 3.45e-10 with the default 1e-9 Krylov tolerance. Tighten only the restart-test KSP/SNES tolerances and retain the near-machine-precision replay assertion. Production solver defaults are unchanged.
Eight-rank PC2 migration and field replay now pass. The CN rate differed by 2.04e-12 because taking a timestep derivative divides field roundoff by dt=0.003. Propagate the unchanged 2e-14 field comparison bound through max(abs(delta T))/dt rather than using an unrelated fixed rate tolerance. Snapshot restoration remains exact and production settings are unchanged.
Exercise the explicit P1 gamma=0.5 two-correction path against smooth published pulse solutions on triangles/tetrahedra, the existing rotating-Gaussian oracle, and exact radial diffusion in a spherical shell. Keep SUPG active for advection and prescribe velocity without Stokes. Bound finite-domain tails, use common fixed timesteps for spatial refinement, check absolute errors and convergence, and optionally retain compact HDF5 diagnostics for same-host serial/MPI comparison. Verify the spherical equation symbolically. Solver implementation unchanged. Syntax checks pass; numerical Gadi validation is pending.
Refine the spherical diffusion pair from 1/4-1/8 to 1/8-1/16 without relaxing the 8 percent absolute L2 criterion. Add fixed-1/8 dt, dt/2 and dt/4 trajectories, restoring identical T/Tdot/startup state and comparing full FE fields. Record input Gmsh SHA256 and short mesh filenames for strict same-mesh serial/MPI comparison. Reuse a focused advance/measurement helper instead of duplicating the diagnostic code. Solver implementation unchanged. Syntax checks pass; bounded Gadi numerical follow-up pending.
|
@lmoresi This PR is ready for a focused review once the current CI run completes. Two decisions remain intentionally open:
The former 200-step RSS soak is now opt-in ( |
Keep test 1077's default cellsize 1/8, numerical setup, 5% analytical bound and 1e-8 serial/MPI comparison unchanged. Expose only the internal helper's mesh size for the requested eight-rank 1/4, 1/8 and 1/16 Mac investigation after an empty-partition mesh. All three resolutions completed after mesh fix 7e17bec. Same-host serial/MPI errors agreed within 8.47e-9 at 1/8 and 2.46e-9 at 1/16. Preserve and document the independent 1/4 discrepancy of 7.00e-7; it persists with tighter solves on identical mesh hashes. Do not relax the original gate.
Add tiny 2D triangle and 3D tetrahedron tests with independent analytical P1 element matrices and exact semidiscrete eigenmode references. Compare every UW3 T/Tdot update against a closed-form two-correction map without using a fine numerical solution, Stokes, or A1. Demonstrate that consistent residual mass with lumped correction mass and two fixed corrections approaches (2I-D^-1 M)D^-1 K, with first-order timestep differences. Separate the startup-rate error using exactly solved CN and genuinely lumped-residual controls, which establish why uniform scalar decay is insufficient. Document the limitation without changing CitcomS semantics, solver defaults, or prior tolerances. Four tests pass on Mac serial (17.46 s) and eight MPI ranks (32.91 s); matching mesh hashes and update discrepancies below 4e-14. Style gate and whitespace checks pass.
Exercise the actual shared Eulerian CN solver on the same tiny triangle/tetrahedron meshes and timestep sequence as the PC2 diagnosis. Check the exact CN amplification map and second-order error against independently assembled generalized eigenmodes. Two tests pass in serial (26.61 s) and on eight MPI ranks (13.69 s), with order 2.00 in both dimensions. Finest relative errors are approximately 5.4e-9 and 5.7e-9. No Stokes/A1 run, numerical-method changes, or relaxed error tolerances.
A tiny three-process restart regression exposed a missing _h_cell field: implicit SUPG previously created its generic-tau geometry field only during residual construction, while snapshots require the same fields registered before loading. Materialize this existing dependency at solver construction, only for automatic generic tau; do not relax snapshot schema checks or change the time integration. Add independent full/write/resume worker tests for PC2, CN and BDF2 on a 370-tetrahedron mesh with varying timesteps and velocity. Require exact restored fields/state, then compare step-12 continuation with uninterrupted runs. The CN case demonstrably failed before the four-line constructor fix. After rebuild: serial 3 passed in 48.95 s; eight-rank workers 3 passed in 58.98 s. PC2 continuation is exact; CN/BDF2 fields agree within 8e-16. Update the user guide with the fresh-interpreter workflow. No Stokes/A1 run or checkpoint tolerance relaxation.
Reduce timestep-control changes, FMG comparison norms, and adapted-mesh pulse maxima globally instead of assuming every partition contains the Gaussian peak. Make equality and finite-value failures collective before subsequent solver calls. Keep the existing 1e-3 change, 1e-6 relative error, and 0.9-1.01 peak thresholds. No equations or solver tolerances change. The prior rank-local failures stranded peers in later PETSc collectives. Validation: all 48 API/residual/migration/diffusion checks pass on eight Mac ranks in 152.40 s. The three modified API tests also pass in the final 12-test serial lifecycle sequence (98.14 s). Global FMG discrepancy is 3.04e-10 with amplitude 0.96026 on eight ranks.
…checks Exercise PC2, CN and BDF2 for 200 changing-velocity updates on tiny triangles and tetrahedra, without Stokes, checkpoint output, reaction diagnostics or forced GC. Record per-rank current RSS after warm-up and require stable solver/vector handles and PC2 workspaces. Keep preset per-rank bounds of 16 MiB growth and 0.05 MiB/step late slope, with collective temperature-finiteness checks. Delegate fresh-process restart execution caps and descendant cleanup to the existing MPI supervisor instead of duplicating process-group termination. Document actual UW3 CN second-order discrete diffusion validation and the distinction between small lifecycle regression and production-scale acceptance. Validation: final serial API/restart/memory sequence 12 passed in 98.14 s; final eight-rank restart 3 passed in 60.59 s; final eight-rank memory 6 passed per rank in 60.56 s. Maximum resumed field discrepancy 8.89e-16, PC2 exact. Repeated memory checks pass unchanged limits; no universal zero-leak or second-order PC2 claim. Style gate and git diff --check pass.
Run singleton fresh-process phases directly when the target branch predates the MPI supervisor merged in development by underworldcode#678. Keep MPI restart validation conditional on that supervisor so parallel descendants remain bounded and diagnosable. This lets the SUPG feature branch validate PC2, CN, and BDF2 restart state without importing the unrelated 691-line supervisor change into this review. Underworld development team with AI support from Claude Code.
Detect the same-layout checkpoint API added by upstream underworldcode#674 before asserting MPI disk replay. Older transport-branch checkouts continue to test serial disk restore and MPI in-memory restore; rebased development checkouts automatically exercise the full distributed disk path. This keeps the SUPG PR focused while making its dependency on the already-merged checkpoint fix explicit. Underworld development team with AI support from Claude Code.
Keep six fast Level 2 workspace-reuse checks for PC2, CN, and BDF2 on triangles and tetrahedra. They run eight updates and retain the deterministic object-identity, finite-field, and boundedness assertions. Reclassify the 200-update RSS and late-slope regression as an opt-in Level 3 slow test selected with UW_RUN_SUPG_MEMORY_SOAK=1. Preserve its warm-up, sampling, thresholds, and six-case matrix, and document both execution paths. Validation: default serial 6 passed/6 skipped in 16.47 s wall; default eight-rank 6 passed/6 skipped per rank in 35.03 s wall; representative opt-in PC2 triangle soak passed in 10.83 s wall. Deprecated-pattern and whitespace checks pass. Underworld development team with AI support from Claude Code.
b739d68 to
048ee09
Compare
|
Follow-up: the two generic mesh fixes have now been removed from this PR and submitted independently:
The #689 history was rewritten and force-pushed without either commit. A clean rebuild succeeded. Its broad serial SUPG suite then produced 73 passed, 9 expected skips, and one expected prerequisite failure: without #692, the existing high-Peclet SUPG error is The earlier request to decide whether the generic fixes should stay in #689 is therefore resolved. The remaining review question is only the intended public contract for fixed two-correction PC2 and its documented temporal-order limitation. |
Preserve the fixed two-correction CitcomS compatibility mode while adding an explicitly selected pc_converged integrator. Iterate the full Petrov-Galerkin rate residual at startup and each timestep, using the lumped mass only as a reusable correction preconditioner and failing clearly when configured tolerances are not reached. Persist correction controls in solver snapshots, expose convergence diagnostics, and extend workspace and fresh-process restart coverage. Add independent finite-element diffusion tests proving second-order convergence and exact trapezoidal-map agreement in 2D/3D serial and MPI without relying on the Zhong A1 model. Document the mathematical distinction from fixed PC2 and the current repeated-residual performance cost.
|
Marked ready for review without changing the requested target: The head is 17 commits ahead of that target and contains no unrelated target divergence. Generic mesh fixes remain in independent PRs #691 and #692 rather than being duplicated in this SUPG integration diff. The current red CI result is the known partition-dependent |
DMPlexIsSimplex returns false on an empty partition. Using that local value for coordinate FE construction mixed simplex and tensor bases across the same communicator, consuming different PETSc message tags. A subsequent mesh HDF5 labelsLoad then blocked in PetscSFSetUp_Basic/MPI_Waitall. Gather cell-family decisions from populated ranks before FE setup and use the same classification for element metadata. Preserve the constructor hint for an entirely empty mesh; do not change SUPG algorithms, solver tolerances or MPI providers. Add single-cell triangle/tet/quad/hex regressions that require empty ranks and subsequently load another mesh, checking P2 volume and boundary integrals. The triangle regression failed before the fix. The original SUPG migration/partition sequence plus all four regressions passed on eight Mac ranks: 15 tests in 26.05 s, 32.30 s including launcher, 2.74 GiB peak process-tree RSS. The pre-fix sequence hung and the mesh-only reproducer also hung. Gadi rerun remains pending.
…#687) Adapt only the mesh-size correction from lmoresi's 68e545f on feature/navier-stokes-supg; do not import Navier-Stokes or other branch changes. Cache _radii_own from current DM vertex coordinates and use it for mesh.cell_size(). Preserve the legacy kd-tree radius arrays and global timestep/mesh-motion consumers. Use coordinate-section offsets and the full vertex stratum so the own-cell RMS definition also handles hexahedra, which have eight vertices but six faces. Correct the field documentation and Nitsche mechanism tests for the new definition; retain physical solve tolerances and use the exact nearest-centroid <= own-centroid ordering instead of an arbitrary approximate-equality tolerance. Add a first-failing independent geometry/deformation regression for triangles, tetrahedra, quadrilaterals and hexahedra plus a regular-square analytical control. Before: four failures in serial and on eight ranks. After rebuild: 21 passed/one expected skip serial (22.90 s), 22 passed on eight ranks (40.45 s), covering Nitsche solves, radius accessors, frozen PC2 migration and memory/disk snapshots. Own-cell geometry error is zero in these tests; style and whitespace gates pass.
Rename the new per-cell geometric radius cache from _radii_own to _cell_radii so the name describes cell geometry rather than rank ownership. Update the focused Nitsche and deformation checks accordingly.\n\nAdd an enumerated parallel regression that gathers owned-cell centroid/radius pairs and compares the complete sorted table with a fresh single-rank run on the same cached Gmsh mesh. This directly guards the rank-count-independence claim at np=2, np=4 and np=8 instead of relying only on within-rank geometric identities.\n\nValidated locally with 9 focused serial tests and the new MPI test at 2, 4 and 8 ranks.
Remove the local_h=False workaround from the boundary-normal MPI regression now that Mesh.cell_size() is partition independent. The test again exercises the public local_h=True default and compares its Nitsche solve with a fresh serial process.\n\nRecord the user-visible consequence in the development changelog: the rank-local centroid kd-tree moved the default Nitsche velocity answer by 6.6e-3, while the cell-geometry replacement is identical cell by cell from one through eight ranks.\n\nValidated the focused Nitsche regression at 2, 4 and 8 Open MPI ranks (10.99 s, 7.31 s and 9.60 s respectively).
|
PR #689 now includes the complete commit stacks from #691 and #692 as explicit cherry-picks, without retargeting the PR or importing unrelated
Validation after rebuilding the combined branch:
The 8-rank batch includes |
|
@lmoresi The remaining current-development integration gate is now complete. I created a temporary merge of current
This exercises the exact same-layout field reload from #674 and MPI descendant supervision from #678 without duplicating either implementation in #689. The PR description and restart table now record this result. Upstream CI for the exact PR head is still running. The remaining maintainer decision is the public API contract: preserve fixed two-correction |
|
Final author-side gate update: upstream CI passed for the exact PR head. The PR is now clean and mergeable, and every author-action checklist item is complete. The requested maintainer decision on the public PC2 API remains pending review. |
Summary
This is a focused follow-up to #673. It adds the Zhong/CitcomS P1
predictor-corrector as an optional mode of the existing Eulerian SUPG solver,
rather than maintaining a second SUPG implementation.
After this change there is one public class,
uw.systems.AdvDiffusionSUPG, and one implementation insystems/advection_diffusion_eulerian.py. The formeradvdiff_supgmodule isonly a compatibility import. CN, backward Euler, BDF2/BDF3, and the CitcomS
predictor-corrector therefore share the same solver lifecycle, residual
assembly, PETSc configuration, snapshot registration, and documentation.
This PR deliberately targets
feature/eulerian-supg-transport, notdevelopment, so the predictor-corrector can be reviewed together with theEulerian transport implementation it extends.
Why
The Zhong et al. (2008) mantle-convection benchmark requires the CitcomS-style
temperature update, but adding it as an independent solver produced duplicated
SUPG assembly, state handling, caches, and documentation. It also made matched
CN/BDF/PC2 benchmark comparisons harder because nominally common behavior lived
in different classes.
The integration preserves the CitcomS numerical choices:
gamma=0.5;Tdotstate for restart and benchmark output.It does not replace the generic transient SUPG parameter or alter the existing
implicit CN/BDF equations.
Public numerical contract
time_integrator="citcoms"0.9 * min(dt_adv, dt_diff)T,Tdot, startup statetime_integrator="pc_converged"T,Tdot, startup state and correction controlsorder=1,theta=0.5T, history, timestep and estimator stateorder=1,theta=1.0T, history, timestep and estimator stateorder=2/3CitcomS mode does not allocate the unused implicit multistep history. Repeated
updates reuse the assembled simplex geometry and predictor-corrector work
vectors.
Bugs found during validation
DMPlexIsSimplexwas interpreted rank-locally, so populated and empty ranks built different coordinate finite elements and consumed different PETSc message tags_h_cell) was not registered before snapshot metadata restorationmesh.cell_size()used distance to the nearest centroid available on each rankThe complete commit stacks from #691 and #692 are included here as explicit
cherry-picks, while remaining available as independently reviewable generic-mesh
PRs. This makes #689 self-contained for the eight-rank empty-partition and
high-Peclet SUPG validation without importing unrelated
developmentcommits.The own-cell calculation from #692 adapts only the mesh-size part of
68e545fdfrom the Navier-Stokes SUPG work associated with #687.
Independent accuracy checks
The validation does not use a long coupled A1 run as its oracle. Prescribed
velocity and diffusion problems isolate transport on tiny triangle,
tetrahedron, and spherical-shell meshes.
4e-141.55e-14Important PC2 limitation
The fixed two-correction CitcomS mode measures temporal order approximately
1.01 for nonuniform diffusion on a fixed mesh. The result is reproduced on
tiny straight-sided triangles and tetrahedra without Stokes, spherical
geometry, checkpointing, or A1.
UW3 agrees with the independently assembled recurrence to roundoff. The loss of
second-order behavior comes from applying only two lumped-inverse corrections
to a residual assembled with the consistent mass matrix, together with the
lumped startup rate. A constant scalar decay does not reveal this because
consistent and lumped mass act identically on a constant field.
This PR therefore preserves the CitcomS-compatible fixed-correction algorithm
but does not claim general second-order PDE accuracy for it. The separately
selected CN path is verified second order. The distinct
time_integrator="pc_converged"option now provides thatsecond-order reference without silently changing the compatibility mode. It
uses lumped mass only as an iterative preconditioner and converges the full
consistent Petrov-Galerkin rate residual at startup and every timestep.
Non-convergence raises
RuntimeError.2.0001,2.00002.0001,2.00002.0001,2.00002.0001,2.0000<5.2e-14<5.2e-14rtol=1e-1248-8148-81The public default is
rtol=1e-10. Repeated residual assembly is currentlymore expensive than a reusable consistent-mass Krylov solve, so this remains
an accuracy/reference mode; fixed PC2 remains the Zhong production default.
Serial/MPI agreement from #692
The rotating-Gaussian comparison from #692, now included here, uses the same mesh
file, timestep sequence, and unchanged
1e-8serial/MPI threshold.7.00e-73.90e-118.47e-92.01e-112.46e-91.87e-12The 1/4 absolute spatial error remains above the existing 5% accuracy bound;
only its partition dependence is fixed. No accuracy tolerance was relaxed.
The own-cell geometry oracle was also checked before and after affine
deformation on triangles, tetrahedra, quadrilaterals, and hexahedra. All four
geometries failed the old implementation in serial and MPI and agree with the
independent vertex-coordinate calculation to the existing
1e-12toleranceafter the fix.
Restart and memory validation
Fresh-process tests write, exit, construct a new interpreter, restore, and
continue PC2, converged PC, CN, and BDF2 on a 370-tetrahedron unit cube. The uninterrupted run
is the oracle.
5.55e-16; BDF28.88e-16The default Level 2 regression runs PC2, converged PC, CN, and BDF2 on
triangles and tetrahedra for eight updates and checks stable PETSc/vector/workspace
identities, finite temperature, and physical bounds. The longer RSS test is
an opt-in Level 3 soak selected with
UW_RUN_SUPG_MEMORY_SOAK=1; it retainsthe 200 updates, excludes the first 40 from growth, and checks workspace
identity without forced garbage collection.
Acceptance is
<16 MiB/rankafter warm-up and<0.05 MiB/steplate slope.These are bounded regressions on small meshes, not proof of leak-free behavior
for every production mesh. No new memory-management workaround was required
after the shared implementation reused its workspaces. The table records the
completed full soak validation; routine CI executes only the fast lifecycle
test.
Validation on this review branch
amr-devworktree build: passed;git diff --check: passed;old-base supervisor failures; all three fresh-process methods passed in a
separate rerun after the compatibility gate (53s);
35.03s at eight ranks; and
and 17.58s, respectively.
After cherry-picking the complete #691/#692 stacks and rebuilding this exact
branch, the focused serial cell-size, Nitsche, and SUPG residual suite passed
24 tests in 23.39s. A combined eight-rank batch passed 7 tests per rank in
41.50s, including the empty-partition mesh sequence, cell-by-cell size
comparison, default-Nitsche path, and the SUPG partition-independence test that
failed in the previous upstream run. No numerical tolerance was weakened.
The target branch predates two changes already merged into
development:Tests detect those capabilities. On this old target, only MPI disk restart is
skipped and singleton restart runs directly with a timeout. A temporary merge of
current
upstream/developmentand the exact #689 head (f41bcd2f) was builtwithout source conflicts. Supervised fresh-process restart then passed for PC2,
converged PC, CN, and BDF2 on eight ranks: 4 passed in 94.59 s. This verifies
the full paths while keeping the 924 lines already reviewed in #674/#678 out of
this PR.
Detailed experiment records and raw-result summaries are maintained in the
benchmark documentation,
especially the SUPG unification, analytical PC2, diffusion-time, restart,
memory, MPI-stall, and #687 cell-size reports.
Scope boundaries
serial/MPI regressions.
Checklist
construction regression is included from Fix cell-family detection on empty MPI ranks #691.
selected converged-reference public contract; decision remains pending.
Underworld development team with AI support from Claude Code