Skip to content

MHD with a zero field ​

IDGroupMilestoneBackendsFigureRegression
MV-2Ideal MHDM2 (#41, P3)CPU, FNLnouniform-amr-mhd

Case and scope ​

The MHD face kernels (the 7×7 Roe–Balsara core at the face average, with the decoupled Bn or the GLM pair) replace the Euler ones whenever physical_model = mhd-ideal. With B=0 the MHD system is the Euler one plus inert fields, which gives exact expectations before any MHD-specific test (MV-4). Both variants, divergence_control = none and glm, run two legs:

  1. Sod along x, y, z through the MHD path: L1(ρ) against the exact Riemann solution within the M1 bound of V1; the y and z runs equal the x run bit for bit after the permutation of the axes; B (and ψ) stay exactly zero;
  2. a uniform MHD state (ρ, u, p and B all non-zero) on the periodic box of V3:
    • single level: the last checkpoint equals the step-0 state bit for bit (the MHD fluxes of equal states cancel);
    • with the 2:1 refined octant: equal to round-off, 10−14 relative.

What the case catches: an MHD kernel that does not reduce to Euler at B=0, a direction-dependent defect of the MHD eigensystem, a spurious source of B or ψ, and MHD fluxes of equal states that do not cancel, on a uniform grid and across 2:1 faces.

Models and numerics ​

ItemChoiceCode
Equationsideal MHD, γ=cp/cv=1.4 (the cp,cv of the Euler base inputs, kept by make_input.py)models
SpaceWENO5 (weno-u-5) flux splitting on characteristic variables; the 7×7 Roe–Balsara core at the arithmetic face averagecompute_residuals_weno, adam_flume_cpu_object.F90; mhd_face_average, mhd_eigenvectors, mhd_face_split_fluxes, mhd_glm_face_split_fluxes, adam_flume_mhd_library.F90; numerics
Cleaningnone, or GLM with ch=3, glm_alpha = 0.18, glm_damping_length = 1, glm_ch_check = warningmodels; add_glm_damping, adam_flume_cpu_mhd_glm_kernels.F90
TimeSSP Runge–Kutta, 3 stages, CFL 0.5adam_rk_object.F90
AMR (uniform, AMR leg)geometric box marker on the octant; 2:1 ghost restriction and interpolation; refluxmark_by_geometry, adam_flume_common_object.F90; interp_seam_ghost, adam_field_object.F90; boundary conditions
BoundariesSod: extrapolation; uniform: periodicboundary conditions, periodic
FNL backendthe same kernels on the deviceadam_flume_fnl_object.F90

Initial and boundary conditions ​

Every input is derived from a committed Euler input by make_input.py: physical_model = mhd-ideal, an [mhd] section, nv=8 (none) or 9 (glm), and bx, by, bz added to every region and inflow state.

LegBase inputGridStateBoundariesSteps
Sod x, y, zsod/sod-{x,y,z}.inias V1: 64 blocks of 50×4×4 cells along the active axis, one levelriemann-problem: (ρ,u,p)=(1,0,1) / (0.125,0,0.1), B=0extrapolationt=0.2 (174 steps none, 241 steps glm: the ch bound sets Δt)
uniform, singleconservation/amr-periodic.ini, markers_number = 0[0,1]3, octree level 1: 8 blocks of 83 cellsuniform, s=0: (ρ,u,v,w,p)=(1,0.3,−0.2,0.1,1), B=(0.8,0.5,−0.3)periodic10
uniform, AMRconservation/amr-periodic.inithe octant [0,0.5]3 refined once more: 15 blocks, 2:1 faces on every side of the octantthe sameperiodic10

Ranks: 2 in every leg.

Input files ​

FileRole
src/tests/flume/verification/mhd/zero-field/make_input.pyderives the MHD input from an Euler one (--divergence-control, --b, --set section.key=value)
src/tests/flume/verification/sod/sod-{x,y,z}.inithe Sod base inputs
src/tests/flume/verification/conservation/amr-periodic.inithe V3 base input of the uniform legs
src/tests/flume/verification/mhd/zero-field/check.shruns every leg (--np N, --legs LIST: mv2-sod, mv2-uniform; FLUME_EXE selects the backend)
src/tests/flume/verification/sod/sod_oracle.pyL1(ρ) against the exact solution (--l1-max 3.31e-03), the y/z against x bitwise check
src/tests/flume/verification/mhd/plumbing/mhd_plumbing_oracle.py--zero (B, ψ exactly zero), --steady (last checkpoint against step 0)
bash
cd src/tests/flume/verification/mhd/zero-field && ./check.sh         # CPU
FLUME_EXE=$PWD/../../../../../../exe/adam_flume_fnl ./check.sh       # FNL

Results ​

A contract leg: no figure. Work directories of both backends are kept (zero-field/work-adam_flume_{cpu,fnl}-np2-*) with logs and histories; the checkpoints are deleted after the oracles and the oracle lines are not kept, so the cell-level verdicts below rest on the check.sh run. The values quoted are read from the kept histories:

CheckBoundCPUFNL
Sod, L1(ρ), both variants3.31⋅10−3 (V1)not keptnot kept
Sod, y and z against xbitwisenot keptnot kept
Sod, B (and ψ) in the last checkpointexactly zeronot kept; ∫Bx,∫By,∫Bz (and ∫ψ) are 0 in every history row, and the glm div(B) history is 0 at every stepthe same
uniform, single level: last against step-0 checkpointbitwisenot kept; every volume integral constant to the printed digit, ∫ψ=0the same
uniform, 2:1 octant: last against step-0 checkpoint10−14 relativenot kept; integrals constant to the printed digit, max|∫ψ|=1.2⋅10−18integrals constant, max|∫ψ|=2.0⋅10−19

The regression case uniform-amr-mhd freezes the uniform AMR leg (GLM, 10 steps; regression/run.sh).

Related cases: MHD plumbing checks the time step, outputs and restart of the same model; Sod shock tube is the Euler reference; Ryu–Jones 2a (MV-4) is the first test with a non-zero field; conservation across AMR seams (V3) is the base of the uniform legs and MHD conservation (MV-11) its MHD counterpart.

Findings ​

  • The Sod legs are not bitwise against the Euler path: at B=0 the MHD eigenspaces are degenerate and WENO acts in a different characteristic basis, so the expectation is the V1 accuracy bound, not equality.
  • The uniform state across the 2:1 patch is exact only to round-off. The cause is the interface, not the MHD kernels: the coarse–fine ghost fill reproduces a constant only to round-off for general values, and the Euler path does the same (a uniform Euler state with u,v,w=0.8,0.5,−0.3 drifts by 1.3⋅10−15 on this grid, while the committed all-ones state happens to be exact; check.sh header).
  • The work directories *-none-uniform and *-glm-uniform (CPU, dated before the others) predate the single/AMR split; check.sh no longer writes them.