Appearance
MHD conservation across AMR seams
| ID | Group | Milestone | Backends | Figure | Regression |
|---|---|---|---|---|---|
| MV-11 | Ideal MHD | M2 (#41, P7a) | CPU, FNL | yes | — |
Case and scope
The V3 case of conservation across AMR seams (a triply periodic box, one refined octant, 6 coarse–fine faces, a uniform flow with a 1% seeded density/pressure perturbation) run through the MHD path with the uniform field
Four legs:
- GLM without damping (
glm_alpha = 0), reflux on: all 9 integrals (, , , each component of , ) within ; starts at zero, so its drift is relative to the largest initial integral; - the same, reflux off: the negative control must drift by at least
, so the seams are exercised; - GLM with damping (
glm_alpha = 0.18), reflux on: the 8 physical integrals within; is reported, not bounded; - no divergence control (
none,), reflux on: the 8 integrals within .
Every run must register the 6 coarse–fine faces (registered intra-realm AMR seam faces: +6 in the log).
What the case catches: a reflux register without the
Models and numerics
| Item | Choice | Code |
|---|---|---|
| Equations | ideal MHD, none ( | models |
| Space | WENO5 (weno-u-5) flux splitting on characteristic variables | compute_residuals_weno, adam_flume_cpu_object.F90; mhd_face_split_fluxes, mhd_glm_face_split_fluxes, adam_flume_mhd_library.F90 |
| Cleaning | GLM, glm_damping_length = 1, glm_alpha = 0 or glm_ch_check = warning; or none | models; add_glm_damping, adam_flume_cpu_mhd_glm_kernels.F90 |
| Time | SSP Runge–Kutta, 3 stages (runge-kutta-ssp-33), CFL 0.5 | adam_rk_object.F90 |
| AMR | geometric box marker, one more level on the octant; 2:1 ghost restriction and interpolation | mark_by_geometry, adam_flume_common_object.F90; interp_seam_ghost, adam_field_object.F90; boundary conditions |
| Reflux | Berger–Colella, stage fluxes weighted by the SSP coefficients, every conservative row | accumulate_seam_fluxes, adam_flume_cpu_object.F90; accumulate_coarse_flux, accumulate_fine_flux, adam_flux_register_object.F90; apply_reflux_corrections, adam_forest_object.F90; numerics |
| Integrals | volume integrals of the conservative variables, every step | compute_conservation, adam_flume_cpu_object.F90 |
| Boundaries | periodic on all six faces | boundary conditions |
| FNL backend | the same kernels on the device | adam_flume_fnl_object.F90 |
Initial and boundary conditions
| Item | Value |
|---|---|
| Base input | conservation/amr-periodic.ini (V3), turned into MHD by mhd/zero-field/make_input.py |
| Domain | |
| Grid | octree, one uniform level (8 blocks of ngc = 3 |
| Ranks | 2 |
| Initial condition | uniform: |
| Boundaries | periodic on all six faces |
| Final time | 20 steps ( |
| Leg | divergence_control | glm_alpha | reflux | Bound |
|---|---|---|---|---|
glm-reflux | glm | 0 | on | all 9 integrals |
glm-noreflux | glm | 0 | off | max drift |
glm-damped-reflux | glm | 0.18 | on | the 8 physical integrals |
none-reflux | none | — | on | the 8 integrals |
Input files
| File | Role |
|---|---|
src/tests/flume/verification/conservation/amr-periodic.ini | the V3 base input |
src/tests/flume/verification/mhd/zero-field/make_input.py | derives the MHD input (--divergence-control, --b 0.8 0.5 -0.3, --set mhd.glm_alpha=…, --set numerics.reflux=…) |
src/tests/flume/verification/mhd/conservation/check.sh | runs the four legs and checks the six registered faces (--np N, --legs LIST: mv11-glm for legs 1 and 2, mv11-damped, mv11-none; FLUME_EXE selects the backend) |
src/tests/flume/verification/conservation/conservation_oracle.py | the drifts (--conserved, --max-drift, --leaky, --min-drift, --exclude psi) |
src/tests/flume/verification/make_doc_figures.py (fig_mhd_conservation) | the figure, from the kept CPU conservation histories of mhd/conservation/ (--only mhd-conservation) |
bash
cd src/tests/flume/verification/mhd/conservation && ./check.sh # CPU
FLUME_EXE=$PWD/../../../../../../exe/adam_flume_fnl ./check.sh # FNL
cd ../.. && python3 make_doc_figures.py --out ../../../../docs/public/flume --only mhd-conservationResults

One panel per CPU leg (GLM with reflux, damped GLM with reflux, GLM without reflux, no cleaning with reflux):
Maximum drift over the 20 steps, computed from the kept conservation histories (mhd/conservation/work-adam_flume_{cpu,fnl}-np2-<leg>/amr-periodic-conservation_history.dat) with the oracle's definition (relative to
| Leg | Bound | CPU | FNL |
|---|---|---|---|
glm-reflux, 8 physical integrals | 0 (constant to the printed digit) | ||
glm-reflux, | |||
glm-noreflux, max over the integrals | the same to 3 digits | ||
glm-damped-reflux, 8 physical integrals | |||
glm-damped-reflux, | — | the same | |
none-reflux, 8 integrals | 0 | ||
| registered coarse–fine faces, every leg, both ranks | 6 | 6 | 6 |
Related cases: conservation across AMR seams is the Euler V3 base; zero field (MV-2) runs the same box with a uniform MHD state; GLM divergence cleaning checks the damping; the M6 integral-drift study near seams is integral drift.
Findings
- With reflux the MHD integrals are constant to round-off on both backends,
included: the register carries the and rows. - With damping,
is not conserved: the source couples the Runge–Kutta stages. The seam-flux mismatch of stage reaches through the later stages' damping, so it enters with weight while the register corrects ; the remainder is of the uncorrected leak. Measured at M2-P7a ( check.shheader):, , for glm_alpha0.018, 0.18, 0.9, linear in the rate; without the seams it stays at. The kept damped histories give at 0.18, as recorded. - The
check.shheader records the M2-P7a CPU drift with reflux as( the largest) and to without. The kept CPU histories show exact constancy with reflux and ( ) to without; the lower end matches ( ), not the integrals. - The bounds hold on FNL as well. The FNL drifts with reflux are one to two ulps, not zero, and the FNL step-0 integrals already differ from the CPU ones in the last digit (
against ): the two backends do not compute the integrals with the same arithmetic.