Skip to content

Load-balance, active-box windowing, block-structured AMR#1628

Open
sbryngelson wants to merge 396 commits into
MFlowCode:masterfrom
sbryngelson:up/mega
Open

Load-balance, active-box windowing, block-structured AMR#1628
sbryngelson wants to merge 396 commits into
MFlowCode:masterfrom
sbryngelson:up/mega

Conversation

@sbryngelson

@sbryngelson sbryngelson commented Jul 3, 2026

Copy link
Copy Markdown
Member

Summary

An opt-in, default-off family of performance features and the measurement infrastructure they rest on. With all flags at their defaults the only touched production path is s_mpi_decompose_computational_domain, refactored through the new m_box module (byte-identical; covered by the existing suite).

  • Load-balance infrastructurem_box (partition arithmetic), m_load_weight/load_weight_wrt (per-cell load-weight field + imbalance metric), m_sfc_partition/sfc_partition_wrt (Morton-SFC predicted-imbalance diagnostic), m_load_balance/load_balance (weighted static decomposition at init; AMR-fine-work-aware), m_rank_timing/rank_time_wrt (per-rank compute-time diagnostic).
  • Active-box windowingm_active_box/active_box: restricts reconstruction/Riemann/RK windows to a light-cone-grown box around non-ambient flow; strict-subset golden-tested.
  • Hybrid reconstruction/flux sensorshybrid_weno and hybrid_riemann (+hybrid_weno_eps, hybrid_smooth_flux): linear-optimal weights / central-or-Rusanov flux in smooth cells, full WENO/HLLC at flagged discontinuities (Jameson sensor, stencil-dilated, per-level under AMR).
  • Block-structured AMRm_amr + m_amr_registers: two-level 2:1 refined block hierarchy; conservative restriction and conservative-linear prolongation with physics-specific closures; per-stage flux registers with Berger–Colella refluxing; Berger–Rigoutsos multi-block dynamic regrid; optional dt/2 subcycling; multi-rank (single-owner blocks assigned by Morton-SFC work balancing at each regrid, with migration; blocks may span rank seams via P2P coarse↔fine gather/scatter; same-level seam halo; distributed registers); restart (both IO modes, regridded-layout persistence); AMR-aware post-processing (fine blocks visualizable as Silo overlay domains); GPU-resident fine level on both OpenACC and OpenMP offload.

Full algorithm and user documentation: docs/documentation/amr.md (support matrix enforced at runtime by the checker — unsupported combinations abort with named messages, never silently).

AMR physics support matrix (abridged; authoritative table in amr.md)

Supported and golden-tested: single- and multi-fluid (5-eq, mpp_lim) · 6-eq with per-block pressure relaxation · viscous (refluxed) · phase change (relax) · chemistry incl. species diffusion · Euler–Euler bubbles (polytropic/non-polytropic, mono/polydisperse, QBMM incl. non-polytropic with per-block pb/mv side-state; dynamic regrid + subcycle) · acoustic sources (coarse-grid support with regrid exclusion) · immersed boundaries (multi-body, static or prescribed-motion, incl. dynamic regrid with body-containment expansion and per-substage guards) · 2D axisymmetric (per-block WENO-coefficient recompute) · stretched grids (exact parent-bisection ghost coordinates + per-swap coefficient recompute) · hybrid WENO/Riemann sensors (per-level) · Lagrangian bubbles (cloud excluded from blocks; two-way coupling on the coarse grid; regrid clips around the moving cloud) · active_box (blocks contained in the growing window; agrees with plain AMR to ~1e-14) · IGR (restriction-only coupling: fine sigma solve seeded/Dirichlet-bounded by the coarse solve; documented truncation-order seam, exact free-stream) · 1D MHD/RMHD (div(B)=0 by construction in 1D; HLL and HLLD, incl. relativistic).

Gated with named aborts (documented rationale): surface tension (seam force imbalance is structural — three fixes attempted and diagnosed in amr.md) · 2D/3D MHD (attempted and measured: the c/f seam is a continuous O(1) div(B) source GLM cleaning cannot remove — needs constrained-transport-class B prolongation/reflux) · hyperelasticity · 3D cylindrical (global azimuthal filter) · force-driven IB (moving_ibm=2) · STL bodies · Riemann-extrapolation BCs (bc=-4) · amr_subcycle under IGR · stretched grids with Lagrangian/IB-regrid (uniform-spacing index conversions).

Validation evidence

  • Conservation: reflux-exact (~1e-15 defects) across single/multi-fluid, viscous, bubbles, chemistry, phase change, through subcycled + regridding advances.
  • Free-stream preservation: exact (0.0) with subcycling + regrid armed, including 3D, IGR, and Lagrangian configs.
  • Decomposition exactness: np=1 == np=2 element-exact with blocks spanning rank seams (fields byte-identical incl. chemistry species).
  • Methodology: every feature validated by AMR-vs-no-AMR reference comparison with a control experiment calibrating the expected error scale, plus mechanism evidence from run logs (regrid counts, box coordinates, ghost-point counts) — a golden that does not mechanically exercise its path is treated as no coverage. Liveness goldens for the hybrid sensors are deliberately sized so a silently dead sensor fails them (~5e-4 signal vs 5e-5 tolerance) — they caught a real dead-sensor bug on Cray GPU during CI hardening.
  • GPU: full test suite with post-process on 2×V100 — OpenACC 644/644 executed pass, OpenMP offload 643/644 (one slurm launch flake). Speed spot-check (800² 2D blast, 2 ranks): AMR + dynamic regrid costs +3% wall over no-AMR at these sizes; ACC ≈ 12% faster than OMP; acc/omp solutions bitwise identical.
  • CI: one fully green 85-lane matrix on record (all GitHub-hosted lanes: gnu/intel × debug/no-debug/reldebug × double/single/mixed, macos, and the NVHPC 23.11–26.3 compat matrix). Fixes landed during hardening were each reproduced locally in the exact failing configuration first (intel FP drift, single-precision tolerance classification, gfortran bounds-check OOB, OpenACC present-table mapping ×3).

Known issues (all non-gating or in progress)

  • Frontier/Cray, in progress: two device-mapping issues in the IB machinery under CCE (plain-IBM descriptor corruption on gpu-omp; a present-table crash in the AMR-IB swap on gpu-acc). Being fixed with direct Cray iteration; the CCE bench/case-opt lane failures share the same root.
  • NVHPC 24.1/24.3 compat lanes (informational, continue-on-error): an intermittent post-detected NaN on the two Lagrangian+AMR goldens. Exhaustively unreproducible off GitHub's runners — the exact failing stack (NVHPC 24.3 SDK, -tp=px -Kieee, HPC-X MPI, and the CI docker image itself under apptainer) passes elsewhere, as do native/zen2 builds; 24.5+ green. Documented at the golden definitions.
  • Accuracy postures documented rather than hidden: multi-fluid alpha-sum deviation bounded ~5.7e-3 at historical block faces during shock crossing (non-growing); viscous prolongation-ghost seam ~1e-6 np-dependence; IGR seam conservation is truncation-order (no reflux capture from the fused IGR kernels — exact-conservation capture is noted future work).

Review guide

The commit history is arc-ordered (active-box → load-weight → SFC → weighted decomposition → rank timing → hybrid → m_box → AMR rungs → physics envelope → CI/GPU hardening); reviewing by arc is much easier than by file. The AMR arc builds stepwise: static hierarchy → restriction/prolongation → fine advance → refluxing → regrid → subcycling → multi-rank → GPU → each physics rung with its own validation. Commit messages carry the validation evidence for their change (measured defects, golden UUIDs, repro details for CI fixes).

All parameters ship default-off with case_validator entries, runtime checker gates, and case.md/amr.md documentation.

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.

Pull request overview

This PR introduces an opt-in (“default-off”) family of performance/diagnostic features (load-weight and SFC partition diagnostics, weighted init-time decomposition, rank timing), plus major simulation capabilities (active-box RHS windowing and block-structured AMR) and corresponding post-processing support and documentation/validation updates.

Changes:

  • Adds new runtime parameters and toolchain metadata/validation hooks for the experimental performance/AMR feature family.
  • Extends the simulation code with new modules for active-box restriction, load-weight diagnostics, SFC partition reporting, rank timing, and AMR integration points (including restart/output plumbing).
  • Updates post_process to read/write AMR fine-block overlays and adds/updates golden metadata plus documentation/indexing.

Reviewed changes

Copilot reviewed 82 out of 94 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
toolchain/mfc/params/descriptions.py Adds user-facing descriptions for new experimental/performance parameters.
toolchain/mfc/params/definitions.py Registers new parameters (AMR, hybrid sensors, load-balance diagnostics) and target applicability.
toolchain/mfc/lint_docs.py Treats new validator checks as non-physics doc checks.
tests/F980C769/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/ECABA006/golden-metadata.txt Adds golden metadata for active-box test coverage.
tests/DD4CD8F3/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/CC4213FD/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/BD21A5C0/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/BCBA6E74/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/ACE05393/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/987D9025/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/852CCB81/golden-metadata.txt Adds golden metadata for AMR-related golden tests.
tests/65C375B4/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/4DADE04B/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/454C565F/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/3A474BEE/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/2FC423D3/golden-metadata.txt Adds golden metadata for a new/updated test.
tests/13945217/golden-metadata.txt Adds golden metadata for moving-IB under AMR test coverage.
src/simulation/m_viscous.fpp Clamps FD coefficient indexing to avoid ghost-region coefficient OOB in IB drag gradient evaluation.
src/simulation/m_time_steppers.fpp Integrates active-box bounds into RK update loops and interleaves AMR fine-stage/subcycle operations.
src/simulation/m_start_up.fpp Wires up new modules (rank timing, active-box, load-weight, SFC partition, AMR) into init/timestep/finalize and restart I/O.
src/simulation/m_sfc_partition.fpp Adds analysis-only SFC tiling + weighted partition prediction and reporting.
src/simulation/m_rank_timing.fpp Adds per-rank wall-time imbalance measurement helpers and reporting.
src/simulation/m_load_weight.fpp Adds per-cell load-weight field construction and rank-level imbalance reporting.
src/simulation/m_hypoelastic.fpp Refactors FD coefficient setup into a callable update routine (supporting AMR grid swaps).
src/simulation/m_global_parameters.fpp Adds AMR working-state mirrors and slot selection helper plus defaults for new parameters.
src/simulation/m_data_output.fpp Adds output/report hooks for load-weight, SFC partition, and rank-time diagnostics.
src/simulation/m_checker.fpp Adds input validation/prohibits for active-box, hybrid sensors, load-balance, and AMR configurations.
src/simulation/m_active_box.fpp Adds active-box initialization/growth and debug envelope checking.
src/simulation/m_acoustic_src.fpp Adds AMR-aware handling of acoustic source support (bounding boxes and overlap abort).
src/post_process/m_start_up.fpp Calls AMR fine-data reader and AMR overlay writer when amr is enabled.
src/post_process/m_global_parameters.fpp Adds default-off amr flag for post_process overlay behavior.
src/post_process/m_data_output.fpp Implements AMR fine-block overlay mesh/variables output (Silo/binary) and multimesh registration.
src/common/m_phase_change.fpp Exposes per-cell Newton iteration count and threads it through relaxation to support load-weighting.
src/common/m_global_parameters_common.fpp Adjusts start_idx lifecycle/allocation and makes load_weight_wrt visible to GPU macros.
src/common/m_derived_types.fpp Introduces a simple t_box type used by new partitioning infrastructure.
src/common/m_box.fpp Adds box/partition arithmetic helpers (equal/weighted splits, box-from-splits).
src/common/m_boundary_common.fpp Skips BC buffer population during AMR fine advance to rely on coarse-driven ghost fill.
docs/module_categories.json Registers new modules under documentation categories.
docs/documentation/readme.md Adds AMR section link to the documentation index.
.typos.toml Adds project-specific abbreviations to the spelling allowlist.

Comment thread src/common/m_phase_change.fpp Outdated
D = ((gs_min(lp) - 1.0_wp)*cvs(lp))/((gs_min(vp) - 1.0_wp)*cvs(vp))

#ifdef MFC_SIMULATION
if (relax .and. load_weight_wrt) then
Comment thread src/simulation/m_sfc_partition.fpp
Comment thread src/simulation/m_sfc_partition.fpp Outdated
Comment thread src/simulation/m_rank_timing.fpp
…es expand to fully contain each body plus margin (partial coverage is untested regime), overlapping expansions merge with size-cap and acoustic-conflict aborts, fine IB state rebuilds from geometry after every regrid; moving bodies stay gated; golden 7FC2F9F8 (verified: regrid fires, box contains body bbox, post-regrid rebuild runs; 3-golden IB battery clean)
…nd by exact parent-cell bisection (unified formula: boundary k belongs to parent isect_lo+floor(k/2), even=parent midpoint, odd=parent right edge) replacing the locally-uniform continuation; grid-uniformity aborts relaxed to arm the per-swap WENO coefficient recompute; golden F0DDE1B4 (stretched + dynamic regrid + restart, block parents span 2.08x spacing). Validated: 15-golden uniform battery bit-identical, stretched AMR-vs-reference errors match the uniform control (rho 7.3e-3 vs 7.1e-3 rel-L2; static, dynamic-regrid, and 2-rank), restriction integral error exactly 0; docs matrices updated incl. stale IB dynamic-regrid rows from f3814e5
…d-combination gates; the sensor arrays are coarse-idwbuff sized (fine extent guard keeps fine bounds inside) and the sensor recomputes from the live swapped idwbuff every RHS call, so each level evaluates its own sensor. Validated: AMR-vs-reference error scale matches the plain control to 3 digits on an acoustic case where the sensor is live (mixed verdicts, 56/72 central). Also found the existing hybrid goldens cannot detect a dead sensor (bitwise-identical to plain WENO by design at physical eps: only constant/eps-dominated cells go central and any convex weights reconstruct those identically - verified by forcing all-central, 2e-2 shift); added consequential-eps liveness goldens (eps 0.5 > shock phi ~0.3, dead sensor moves the answer ~5e-4): BA4340EA 60739A3E and AMR combos 053C5DDA DDC4BA8A
…e containment expansion reads the body's LIVE centroid (bbox helper factored from the expansion), the initial block gets the same body expansion when regridding is active, and a per-substage guard aborts if a moving body reaches its block boundary between regrids (consecutive contained positions keep every sub-time interpolate contained). Validated: 200-step tracking run (29 regrids, body rises 25 cells past its initial box, completion is the guard's own proof of following), guard-trip negative test aborts with the named message, error at/below the validated static-block control (rho L2 5.6e-3 vs 8.5e-3, identical body-surface Linf); Mach ~0.85 wakes legitimately exceed the per-rank box cap (named abort). Golden E72953D1 (Mach 0.25, 4 regrids)
…s - regrid suppresses tags and clips candidate boxes around the cloud's padded bbox (positions + mapCells smearing + stencil + drift margin, recomputed collectively per regrid), the fine advance skips the EL hooks (a bubble would map to wrong indices on the swapped grid), and a per-stage guard aborts if the cloud reaches an active block. FIX: EL volume fractions sum to the local liquid fraction (beta), not 1 - the multi-fluid sum-to-one prolongation closure corrupted the EL state (found by the free-stream battery: O(1) momentum injection at block edges in quiescent flow; exactly 0 after the exemption); EL is correspondingly exempt from the mpp_lim gate. Validated: free-stream through block exactly 0, guard-trip named abort, 800-step wave + two-way bubble at 1e-9 field consistency with the bubble trajectory identical; goldens 4B08E9B7 (static) BCE1BBAE (dynamic regrid); multi-fluid AMR battery still green (closure fires for non-EL)
…ing - the fine block runs its own fixed-iteration sigma solve seeded and Dirichlet-bounded by the converged coarse sigma (piecewise-constant parent injection over the full buffered range; per-iteration BC/halo populate skipped under amr_in_fine_advance; coarse jac/jac_old warm-start state bounced across the fine advance), fine RK update uses the IGR coefficient form (dt embedded in the rhs), flux-register capture/apply return early under igr (no face fluxes exposed by the fused IGR kernels - seam conservation is truncation-order, documented), amr_subcycle gated. Validated: free-stream through block EXACTLY preserved, AMR-vs-reference at resolution scale (rho 1.3e-4 rel-L2, static and dynamic regrid), transverse seam artifact 3e-4 absolute from the coarse/fine sigma jump (truncation-level, documented), conservation drift at the reference's own outflow scale. Goldens 6C20B752 (static) 660FFBFE (dynamic regrid)
…mr_cur)%pb_f/mv_f as assumed-shape actuals made nvfortran emit a component-section data clause that dies partially-present on device (CUDA illegal address; caught by the full-suite GPU runs on both acc and omp - CPU passes only because the fine/coarse lbounds coincide); the ghost fill now selects its slot target by integer and references the slot arrays directly inside the kernels (the proven pattern of backup/update/lerp/restrict), and the pb/mv prolongation is now a device kernel reading the device-current coarse side-state (the old host-side copy would read a stale host mirror at regrid time on GPU). CPU nonpoly battery bit-identical (4/4 goldens)
…P_SFs pattern - the previous fix removed the ghost-fill component-section clause but the fine s_compute_rhs call still passed raw amr_slots(amr_cur)%pb_f/mv_f/rhs_* 5D members as actuals (second CUDA illegal address on device); persistent slot state (pb/mv f, stor, ghost_a/b) is now type(pres_field) with %sf allocated + ACC_SETUP_SFs per slot (the exact pb_ts pattern the coarse solver passes through the same RHS interface on GPU), and the fine rhs scratch moves to shared module arrays amr_rhs_pb_f/amr_rhs_mv_f (slots advance sequentially; mirrors the coarse rhs_pb pattern). CPU nonpoly battery bit-identical (4/4)
…on stays host-side - the trace (NV_ACC_NOTIFY) pinned the remaining illegal address to the device prolong kernel referencing pb_ts(1)%sf across modules; ALL pbmv kernels (fill/backup/rk-update/lerp/restrict) now receive the slot and coarse arrays as assumed-shape dummies with %sf pointer-member actuals - the one device-proven pattern (the coarse pb chain and the fine q_cons machinery both pass everything as arguments) - and the prolongation reverts to the original host loops + device push (both call paths make the coarse host mirrors current first: init writes them on the host, regrid refreshes them from the device); also fixes mv_f missing %sf in the two regrid GPU_UPDATE lists after the pres_field conversion. CPU nonpoly battery bit-identical (4/4)
…t-in (honor_io_keys), not content-based - honoring any case's explicit parallel_io/prim_vars_wrt broke the 18 Example-derived goldens whose imported case.py sets those keys (goldens were generated under the clobber): every full CI test lane failed with line-count mismatches (first seen on intel-reldebug only because it finishes first; reproduced locally under nvfortran, exit 0 with 6 extra prim.*.dat pack entries). The two tests the exemption exists for (5EFB3277 MPI-IO AMR restart, 0253D658 load_balance) opt in via define_case_d(honor_io_keys=True); UUIDs and goldens unchanged. Validated: ibm_ellipse/ibm_stl/phasechange_bubble pass again and both opt-ins keep their coverage (5/5 with -a)
…-clip verification after body expansion/merge ran only under acoustic_source, so an expanded box could silently regrow over the cloud in ib+lagrangian configs (fail-closed check now covers both exclusions); (2) the per-stage cloud guard ran only on block-owner ranks, missing bubbles whose smearing support reaches a block across a rank seam (now every rank checks its local bubbles against the global block box); (3) the moving-body containment guard was skipped entirely on static blocks (now always on for moving bodies, margin 0 there since validated static configs sit tighter than the regrid margin); (4) the position-to-cell-index conversions (int((x-beg)/dx(0))) in the IB expansion/guard and cloud exclusion assume uniform spacing and dx(0) is rank-local on stretched grids (rank-inconsistent regrid boxes) - stretched+lagrangian and stretched+ib-dynamic-regrid now fail closed at init (checker+validator). Comment/docs truth pass: fill_fine_ghosts_pbmv doc described the reverted selector design, nonpoly QBMM rows still said regrid/subcycle gated (both supported), amr.md mandatory settings said WENO-only (IGR allowed), recompute-flag comments still axisym-only. New goldens close the stretched coverage gaps: 79B334C7 (2-rank stretched: first exercise of the start_idx offset terms where a wrong offset changes coordinates), B7704247 (2D stretch_y: first exercise of the y-direction bisection formula; 2 regrids, block spans 65% y-spacing variation). 20-golden battery green incl. all touched features
…1e-12 relative threshold sits below single-precision grid roundoff (~1e-7), classifying EVERY grid as stretched under --single; harmless when it only armed the WENO recompute (wasted work), but the new stretched-combo gate turned it into a spurious init abort for the Lagrangian+AMR goldens on the CI single lane (reproduced locally). 1e3*epsilon(1) ~ 1e-13 double / 1e-4 single, both above roundoff and far below real stretching ratios (1.1-2x). Single: EL pair + stretched golden pass; double: 8-golden battery green
…R - the IGR rhs kernels write over -1:m+1 in EVERY dim including collapsed ones (the coarse rhs_vf is allocated (-1:m+1,-1:n+1,-1:p+1) under igr), but the fine slot rhs used the buffered fine extents whose collapsed dims are 0:0 - an out-of-bounds write in every 2D IGR AMR fine stage, trapped by gfortran bounds checking on the CI reldebug lane (silent in no-debug builds: the stray writes landed outside the read range, goldens unaffected). Buffered extents already cover -1:+1 in active dims. Validated: both IGR AMR goldens pass under reldebug bounds checking and the no-debug battery is unchanged
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.68301% with 898 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.78%. Comparing base (30df8e5) to head (d815e1c).
⚠️ Report is 8 commits behind head on master.

Files with missing lines Patch % Lines
src/simulation/m_amr_regrid.fpp 54.80% 176 Missing and 130 partials ⚠️
src/simulation/m_amr_registers.fpp 62.97% 81 Missing and 76 partials ⚠️
src/simulation/m_amr_restart.fpp 64.97% 45 Missing and 24 partials ⚠️
src/post_process/m_data_input.f90 62.04% 38 Missing and 14 partials ⚠️
src/simulation/m_load_balance.fpp 46.80% 42 Missing and 8 partials ⚠️
src/simulation/m_ibm.fpp 71.31% 19 Missing and 16 partials ⚠️
src/simulation/m_load_weight.fpp 21.05% 23 Missing and 7 partials ⚠️
src/simulation/m_sfc_partition.fpp 62.50% 23 Missing and 7 partials ⚠️
src/common/m_mpi_common.fpp 49.05% 14 Missing and 13 partials ⚠️
src/simulation/m_data_output.fpp 32.25% 16 Missing and 5 partials ⚠️
... and 13 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1628      +/-   ##
==========================================
+ Coverage   59.62%   60.78%   +1.16%     
==========================================
  Files          83       93      +10     
  Lines       21246    25629    +4383     
  Branches     3145     4180    +1035     
==========================================
+ Hits        12668    15579    +2911     
- Misses       6467     7330     +863     
- Partials     2111     2720     +609     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…e kernels referenced sw_idwbuff (and amr_isect_lo/start_idx) directly in loop bounds and bodies; those are host-only module state, so OpenACC's present lookup failed fatally (data in PRESENT clause not found: sw_idwbuff) on BOTH Cray-acc (Frontier) and nvfortran-acc (Phoenix) while OpenMP's implicit map(to) tolerated it - exactly why only acc lanes crashed on the IGR AMR goldens. Root-caused with NV_ACC_NOTIFY on a V100 (fault after the s_amr_copy_fine_fields launch, present-table dump names sw_idwbuff). Scalar hoisting is the established kernel idiom everywhere else in the file. CPU pair bit-identical
…ic golden get override_tol=1e-8 - the consequential-eps regime deliberately amplifies reconstruction differences, which also amplifies benign backend FP variation: intel -O3 drifts these five goldens 2e-12..3.3e-10 rel past the 1e-12 default tolerance (intel no-debug CI lane), while the signal the hybrid goldens exist to catch (a dead sensor) moves the answer ~5e-4, four orders above the new tolerance. override_tol bypasses the --single 1e8 relaxation, so the four hybrid goldens join the --single skip list (the acoustic one already matched an existing skip pattern). UUIDs and goldens unchanged; gnu double 5/5
…-gating CI quirk at the EL AMR golden definitions - the exact failing stack (NVHPC 24.3 SDK, -tp=px -Kieee, HPC-X MPI, and the CI docker image itself run via apptainer) passes on Phoenix, as do native and zen2-targeted builds; suspected runner-hardware interaction with old nvfortran codegen, lanes are continue-on-error, 24.5+ green. Comment-only; UUIDs unchanged
… - the first intel no-debug failure only reported the FIRST out-of-tolerance variable (3.3e-10 rel), undersizing the retune; the next matrix run showed the true intel -O3 drift reaches 3.1e-7 rel on the AMR+hybrid pair. 1e-6 keeps >2 orders of margin above the drift and >2 orders below the ~5e-4 dead-sensor signal these goldens exist to detect. Acoustic golden stays at 1e-8 (its 3.3e-10 drift held). Comparison-side only; goldens/UUIDs unchanged; gnu 5/5
…sor engages - hybrid_weno/hybrid_riemann/hybrid_weno_eps/hybrid_smooth_flux are read inside the WENO reconstruction and HLLC flux device kernels but were in no GPU_DECLARE, so on Cray they read undefined on-device and the sensor ran vacuously (all full-WENO); nvfortran tolerated the unmapped module scalars, CCE did not. Added them to the not-case-opt GPU_DECLARE(create) and the matching GPU_UPDATE(device) beside the wenojs peers. Same class as f5eea61, opposite direction (flags not bounds). Verified: the 4 consequential-eps hybrid liveness goldens (60739A3E/BA4340EA/053C5DDA/DDC4BA8A) fail->pass on Frontier Cray-acc
… ICFL monitor sees valid data - active_box narrows the cons->prim producer to the light-cone box, leaving the frozen ambient exterior primitives (converted velocity/pressure) uninitialized; the full-domain ICFL/vCFL stability monitor then reads that exterior and NaN'd (fatal MPI_Abort on Cray-cpu Release, silently finite on gfortran). The first active_box RHS now runs the full-domain conversion once (ab_prim_seeded) to seed the frozen exterior, then narrows as before - the exterior is never overwritten, so all full-domain consumers (ICFL, probes, IB) stay valid. Optimization preserved (one extra full conversion at startup). Verified: ECABA006 fail->pass on Frontier Cray-cpu
…s; drop the redundant copyins - ghost_points is GPU_DECLARE'd, so @:ALLOCATE establishes its mapping and the explicit GPU_ENTER_DATA(copyin) layered a second dynamic map on the declared entry (CCE-OMP corrupts its descriptor: lib-4425 at first coarse setup, ALL IBM tests on Frontier gpu-omp), and the fine-setup path's BARE deallocate/allocate leaked the present-table entry so a later allocation reusing the host address range failed partially-present on Cray-acc (AMR-IBM only: the collision needs a SECOND setup, i.e. regrid). Contents were always filled by device kernels, so the copyins uploaded nothing. The codebase already documents the bare-deallocate leak at the finalize site. CPU IB battery 5/5; targets the two open Frontier items (B, A-IB) - Cray verification pending on Frontier
…y decision theory - the harness reports only the FIRST variable past tolerance, so the three prior retunes (1e-12 default -> 1e-8 -> 1e-6) each just revealed the next quantile of the same deterministic deviation field: intel-CPU and Cray-acc produce IDENTICAL sensor-on results differing from the gnu-generated goldens by up to ~6e-6 (compiler FP-contraction behavior on legitimate results, not noise; nvfortran stays under 1e-6). 5e-5 sits an order below the ~5e-4 dead-sensor signal these liveness goldens exist to catch and 8x above the worst observed drift; if any platform ever exceeds 5e-5 the static-golden design itself stops discriminating and should be redesigned rather than retuned. gnu 5/5
…ctive window (init containment abort + regrid window-clamp: the windowed coarse RK update would silently drop reflux corrections at faces outside the window), and the fine advance swaps ab_active off (window bounds are coarse cell indices, meaningless on the swapped block grid; a contained block is all-active by definition). The combination is np=1 by active_box's own MPI gate, the window's monotone growth means containment established at init/regrid holds between them, and the frozen exterior is valid ambient data for ghost prolongation (its primitives seeded since f55ccb9). Validated: ab+AMR vs plain AMR agree to 9.8e-15 over 200 steps including the window self-disable transition (the active_box round-off spec, with the nonzero diff proving the windowing engaged), dynamic-regrid pair bitwise identical with 4 regrids each, containment abort negative-tested with the named message. Goldens 4364FA6B (static, window live all 10 steps) 8AEA60DD (dynamic regrid)
…nd quantified the failure: B and the GLM psi field ride the generic conservative machinery structurally (the fine advance, prolongation, reflux, and restriction all compile and run), but per-component prolongation/reflux is not divergence-preserving, and on a magnetized 2D Brio-Wu (Bx 0.75, By flip, HLL + hyper_cleaning) the coarse/fine seam acts as a CONTINUOUS O(1) monopole source that cleaning spreads but cannot remove: max|divB| 0.53 in the block interior and 0.36 far-field vs the no-AMR run's 1.4e-3 cleaning background, despite field L2 errors looking normal (1e-2 class). HLLD NaNs outright at step 158 - and separately, m_riemann_solver_hlld has NO GLM coupling at all, so hyper_cleaning+HLLD is silently inert everywhere (upstream latent gap, flagged to maintainers in the PR). Supporting MHD needs constrained-transport-class B prolongation/reflux (future work). Gates restored with the measured rationale in checker/validator/docs; upstream MHD battery green (B=0 and magnetized goldens unaffected)
…_bc -> consistent wrap-seam list), fixes cross-rank deadlock, bit-identical
…windows, halves noise-driven migration churn (bit-identical)
…), spike bit-identical 2D+3D [Option 2 foundation]
…p) + l0_slot_off (tile prefix), behavior-neutral [spike-only + AMR np1==np2 byte-identical]
…runs the device pack/unpack P2P path that CI must exercise on Cray/AMD-flang (no other test hits it)
…vf intent(in)->intent(inout) (passed to bidirectional s_l0_copy_block inout dummy; nvfortran allowed it, GNU/Intel reject)
…teger div-by-zero SIGFPE on test 33866935

Fortran does not mandate .and. short-circuit: amdflang evaluates mod(t_step, l0_rebalance_interval) before the interval>0 guard, so at the default interval=0 it divides by zero -> SIGFPE (exit 136). gfortran/nvfortran order the divide after the guard and never trap. Nesting the mod inside if(l0_rebalance_interval>0 .and. t_step>0) makes the divide unreachable at interval=0; output is unchanged (the rebalance branch was never taken there). Verified np=2 on AFAR amdflang gfx90a GPU build: 33866935 passes, golden matches, divide now guard-dominated in the Release binary.
…init populates tile slots only when amr on (no double-allocate)
…R fine loops (neutral scaffolding for coexist)
…nt-3 tiles->L0 coupling); note deferred double-alloc/free
… + s_l0_tiles_finalize free-slot loop under .not.amr (audit CRIT-1 geometry corruption + CRIT-2 use-after-free; both guard-hidden today)
…x (no freg/child-creg for coarse tiles; neutral pure-AMR)
…rame creg + L0 rhs)

Task 4 of the np>1 coupling. Open the coarse-RHS gate in s_tvd_rk to run s_compute_rhs
on the L0 field when amr .and. l0_ntile>0 (not just l0_ntile==0): after the tiles->L0
scatter it fills L0's edge-BC + inter-rank halo (s_populate_variables_buffers), captures
the c/f-face creg in the fixed L0 frame, and produces the L0 rhs the fine reflux corrects.

Also fix a latent Task-3 ordering bug it exposes: the stage-entry scatter ran at the very
first stage BEFORE the tiles were seeded from L0 (s_l0_copy_coarse_to_tiles), writing
uninitialized zero-density tile memory into L0 and destroying the IC (dormant while the L0
coarse RHS was skipped; an immediate corner NaN once it consumes the zeroed L0). Guard the
scatter on .not. l0_tiles_need_fill - tiles are not authoritative until the first seed, and
L0 already holds the IC, so there is nothing to refresh.

Neutral 4/4 --gpu mp (pure-AMR/pure-L0 unchanged). Coexist (l0_ntile=1 np=1) vs monolithic
now NaN-free, max abs delta 2.1e-7 (the reflux/restrict correction the tiles do not yet
receive; Task 5 copy-back drives it to <=1e-13).
…-identical refactor)

Task 5 scaffolding. Refactor s_amr_fine_stage_advance and s_l0_advance_stage each into an
RHS pass (backup + s_compute_rhs -> per-slot rhs) and an RK pass (s_amr_fine_rk_update),
with the original name kept as a fused wrapper that calls both back-to-back. The AMR fine
blocks and pure-L0 tiles keep calling the fused wrappers (unchanged order). The per-slot
rhs already bridges the two passes, so no new store is needed; s_amr_fine_rk_update uses
slot bounds (not swapped globals), so the RK pass runs safely on coarse globals.

This lets the coexist tile path interpose the reflux-delta copy-back between the two passes
(next commit). Neutral 4/4 --gpu mp; coexist oracle delta unchanged at 2.063e-7 (identical
to pre-split -> the split is byte-for-byte identical).
…st double-allocate root cause

Completes Task 5 of the np>1 plan; NP1-G and NP2-MIG now byte-identical to monolithic AMR.

ROOT-CAUSE FIX (coexist double-allocate). Under coexist, s_l0_tiles_init re-allocated three
arrays s_initialize_amr_module already allocated: amr_seambuf_x/y (fine-fine halo seam buffer),
the sw_* grid-swap bounce buffers, and amr_gxcb/gycb/gzcb (global cell boundaries). gfortran
errors on the double-allocate; amdflang (AFAR MFlowCode#23.2.0, no alloc check) SILENTLY re-allocates ->
a stale/mis-sized/leaked buffer -> fine-fine halo heap corruption at np>1 -> a c/f-reflux NaN,
invisible at np=1 (fine vs tile sizes coincide) and on GPU-release (no runtime check). This is
the audit coexist-double-allocate class; Task-0 hardening gated the shared block-metadata +
amr_decomp but missed these three. Fix: amr_seambuf grows to max(existing, tile need); sw_* is
.not.amr-gated; amr_g?cb dealloc-then-reallocs the value-consistent EXTENDED superset (the fine
geometry has already copied its coords into the slots by then). Free side is already if(allocated).

CROSS-RANK COPY-BACK (Task 5 B+C). Reflux: zero rhs_vf under coexist so s_amr_apply_reflux fills
the PURE Berger-Colella delta, then s_l0_add_reflux_to_tiles routes it additively L0-owner ->
tile compute-owner. Restrict: s_l0_restrict_to_tiles routes the fine-footprint covered cells
L0 -> tile (overwrite). Tile advance split into s_l0_advance_stage_rhs / _rk so the copy-back
interposes between the tile RHS and its RK update. All coexist-only; neutral for pure modes.

Gate (--gpu mp, AFAR MFlowCode#23.2.0): NP1-G (np=1, l0_ntile=1) and NP2-MIG (np=2, l0_ntile=2, covering
tile FORCE-MIGRATED) both byte-identical (0.0) to monolithic AMR. Found via a CPU --debug
gfortran build (alloc-check + -ffpe-trap backtrace).
Protect the np>1 L0/AMR coexist coupling in CI. Two goldens on amr_2d_base (static
single-level 2D planar Sod), byte-identical to the monolithic-AMR run (l0_ntile=0):
- 1F074C5D 'AMR + L0 tiles -> 2D -> coexist static single-level np=1' (l0_ntile=1, ppn=1):
  the degenerate single-tile local coupling; proves the reflux/restrict copy-back assembles.
- 8D466A94 'AMR + L0 tiles -> 2D -> coexist force-migrated np=2' (l0_ntile=2, l0_migrate_step=3,
  ppn=2): the distributed gate - the covering tile is force-migrated so its compute-owner !=
  its L0-storage owner, exercising the cross-rank L0-owner -> compute-owner reflux/restrict route.
These are the only tests exercising amr=T with l0_ntile>0; a coexist coupling regression fails
them. Generated on --gpu mp (AFAR MFlowCode#23.2.0).
…IMP-3)

At coexist init, s_amr_reconcile_slots (called by s_initialize_amr_module before
s_l0_tiles_init) iterated 1..amr_num_blocks, which includes the tile prefix [1..l0_slot_off].
The tile-prefix owner defaults to 0, so RANK 0 allocated those slots here with the FINE-block
mbuf* sizing; s_amr_alloc_slot is idempotent, so s_l0_build_tile_slot could not then resize
them to the tile geometry — a latent tile-undersizing landmine (out-of-bounds if a tile
exceeds the fine mbuf*), benign only while fine mbuf* >= tile (true in the current tests).
Skip the tile prefix in reconcile — those slots are owned/sized by s_l0_tiles_init. l0_slot_off
is 0 without tiles, so this is a no-op for pure AMR. Neutrality 4/4 and both coexist goldens
(NP1-G, NP2-MIG) unchanged on --gpu mp.
…dges)

The dimension-split tile face fills (s_l0_fill_edge_bc + s_amr_fine_fine_halo) set only the
single-ghost face slabs the RHS stencil reads, leaving the >=2-dim ghost cells (2D diagonal
corners, 3D ghost edges + corners) unset. The RHS never reads them, but the cons->prim convert
visits the whole buffered range, and an unset ghost (all void fractions 0 -> gamma 0) is a 0/0
invalid-FP op - a hard SIGFPE under -ffpe-trap and a stray (harmless, never-output) NaN otherwise.
Present in all L0-tiles configs, including the landed golden 33866935.

New s_l0_fill_ghost_corners fills each such cell from the nearest INTERIOR cell (indices clamped
to [0:m]/[0:n]/[0:p]) - a valid state, and never a face ghost, so the RHS-relevant ghosts are
untouched and output is bit-unchanged. Called per owned tile after the fine-fine halo in
s_l0_advance_stage_rhs (so both pure-L0 and coexist). No-op in 1D (no multi-dim ghost).

Verified: neutrality 4/4 + both coexist goldens (NP1-G, NP2-MIG) byte-EXACT on --gpu mp (output
unchanged); and 8D466A94 (coexist l0_ntile=2) + 33866935 (pure-L0 l0_ntile=1) pass on a CPU
--debug -ffpe-trap=invalid build with NO SIGFPE (the corner 0/0 is gone).
… O(1) computed decomposition (exascale prep #1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants