Skip to content

MHD conservation across AMR seams ​

IDGroupMilestoneBackendsFigureRegression
MV-11Ideal MHDM2 (#41, P7a)CPU, FNLyes—

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 B=(0.8,0.5,−0.3). The perturbation drives the induction, so the flux register carries the B and ψ rows at every seam. Nothing crosses the periodic boundary, so every volume integral of the conservative state must stay constant to round-off when the Berger–Colella reflux is on.

Four legs:

  1. GLM without damping (glm_alpha = 0), reflux on: all 9 integrals (ρ, ρu, E, each component of B, ψ) within 10−13; ψ starts at zero, so its drift is relative to the largest initial integral;
  2. the same, reflux off: the negative control must drift by at least 10−10, so the seams are exercised;
  3. GLM with damping (glm_alpha = 0.18), reflux on: the 8 physical integrals within 10−13; ∫ψ is reported, not bounded;
  4. no divergence control (none, nv=8), reflux on: the 8 integrals within 10−13.

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 B or ψ rows, a wrong seam flux of the MHD or GLM kernels, a vacuous test (the negative control), and a seam layout that registers fewer faces than the six of the octant.

Models and numerics ​

ItemChoiceCode
Equationsideal MHD, γ=cp/cv=1.4 (the V3 input's); none (nv=8) or mixed GLM (nv=9)models
SpaceWENO5 (weno-u-5) flux splitting on characteristic variablescompute_residuals_weno, adam_flume_cpu_object.F90; mhd_face_split_fluxes, mhd_glm_face_split_fluxes, adam_flume_mhd_library.F90
CleaningGLM, ch=3, glm_damping_length = 1, glm_alpha = 0 or 0.18, glm_ch_check = warning; or nonemodels; add_glm_damping, adam_flume_cpu_mhd_glm_kernels.F90
TimeSSP Runge–Kutta, 3 stages (runge-kutta-ssp-33), CFL 0.5adam_rk_object.F90
AMRgeometric box marker, one more level on the octant; 2:1 ghost restriction and interpolationmark_by_geometry, adam_flume_common_object.F90; interp_seam_ghost, adam_field_object.F90; boundary conditions
RefluxBerger–Colella, stage fluxes weighted by the SSP coefficients, every conservative rowaccumulate_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
Integralsvolume integrals of the conservative variables, every stepcompute_conservation, adam_flume_cpu_object.F90
Boundariesperiodic on all six facesboundary conditions
FNL backendthe same kernels on the deviceadam_flume_fnl_object.F90

Initial and boundary conditions ​

ItemValue
Base inputconservation/amr-periodic.ini (V3), turned into MHD by mhd/zero-field/make_input.py
Domain[0,1]3
Gridoctree, one uniform level (8 blocks of 83 cells), the octant [0,0.5]3 refined once more: 15 blocks, 6 coarse–fine faces, ngc = 3
Ranks2
Initial conditionuniform: (ρ,u,v,w,p)=(1,1,1,1,1), B=(0.8,0.5,−0.3), ψ=0, seeded density/pressure perturbation s=0.01
Boundariesperiodic on all six faces
Final time20 steps (t=0.0347)
Legdivergence_controlglm_alpharefluxBound
glm-refluxglm0onall 9 integrals ≤10−13
glm-norefluxglm0offmax drift ≥10−10 (negative control)
glm-damped-refluxglm0.18onthe 8 physical integrals ≤10−13; ψ reported
none-refluxnone—onthe 8 integrals ≤10−13

Input files ​

FileRole
src/tests/flume/verification/conservation/amr-periodic.inithe V3 base input
src/tests/flume/verification/mhd/zero-field/make_input.pyderives 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.shruns 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.pythe 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-conservation

Results ​

MV-11: the drift of the MHD integrals across 2:1 seams

One panel per CPU leg (GLM with reflux, damped GLM with reflux, GLM without reflux, no cleaning with reflux): |I(t)−I(0)|/|I(0)| of every volume integral against the step (ψ absolute), floored at 10−17.

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 |I(0)|; ψ relative to the largest initial integral, ∫E=4.490):

LegBoundCPUFNL
glm-reflux, 8 physical integrals10−130 (constant to the printed digit)≤3.7⋅10−16 (Bz)
glm-reflux, ψ10−133.8⋅10−209.5⋅10−20
glm-noreflux, max over the integrals≥10−101.69⋅10−5 (ρu); 1.5⋅10−6 to 1.7⋅10−5 over the 9the same to 3 digits
glm-damped-reflux, 8 physical integrals10−13≤2.2⋅10−16≤3.7⋅10−16
glm-damped-reflux, ψ (reported)—6.0⋅10−11 (|∫ψ|=2.70⋅10−10)the same
none-reflux, 8 integrals10−130≤3.7⋅10−16
registered coarse–fine faces, every leg, both ranks666

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 B and ψ rows.
  • With damping, ∫ψ is not conserved: the source −kψ couples the Runge–Kutta stages. The seam-flux mismatch of stage s reaches ψn+1 through the later stages' damping, so it enters with weight bs(1−O(kΔt)) while the register corrects bs; the remainder is O(kΔt) of the uncorrected leak. Measured at M2-P7a (check.sh header): |∫ψ|=2.7⋅10−11, 2.7⋅10−10, 1.3⋅10−9 for glm_alpha 0.018, 0.18, 0.9, linear in the rate; without the seams it stays at 10−21. The kept damped histories give 2.70⋅10−10 at 0.18, as recorded.
  • The check.sh header records the M2-P7a CPU drift with reflux as ≤4.7⋅10−14 (Bz the largest) and 7⋅10−6 to 1.7⋅10−5 without. The kept CPU histories show exact constancy with reflux and 1.5⋅10−6 (Bx) to 1.7⋅10−5 without; the 7⋅10−6 lower end matches E (7.07⋅10−6), not the B 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 (∫Bz=−0.29999999999999993 against −0.29999999999999999): the two backends do not compute the integrals with the same arithmetic.