Appearance
The gravity force
| ID | Group | Milestone | Backends | Figure | Regression |
|---|---|---|---|---|---|
| GV-1, GV-2, GV-3, GV-6, GV-7 (G1) | External gravity | M7 (#73) | CPU, FNL | yes | — |
Case and scope
G1 adds the gravity sources: momentum
- free fall is exact (GV-1): a uniform gas in a periodic box falls freely,
, , unchanged. A momentum or energy source with a wrong weight fails it; - a closed box conserves its mass and total energy (GV-3): the gas falls onto the floor and sloshes; mass and
( ; since G2a the invariant , see below) stay constant while alone exchanges with . A cell-centred energy source would fail it; - scaling covariance (GV-6): the run with the scale-invariant WENO weights is the same run in other units, bit for bit, as #49 established without gravity;
- the positivity limiter keeps the run alive where the gas falls toward vacuum (
box2d-lim,box2d-stiff).
GV-2 reports the spurious flow of the unbalanced scheme on an atmosphere at rest, the baseline of the well-balanced mode; GV-7 compares the backends.
Models and numerics
| Item | Choice | Code |
|---|---|---|
| Equations | compressible Euler, ideal gas, box2d-mhd: ideal MHD with EGLM (glm_ch = 3, glm_alpha = 0.18, glm_damping_length = 1) | models, EGLM |
| Momentum source | add_gravity_sources, adam_flume_cpu_object.F90; add_gravity_sources_dev, adam_flume_fnl_kernels.F90 | |
| Energy source | G1: the face form | add_gravity_sources, compute_gravity_correction, adam_flume_cpu_object.F90 |
| Positivity limiter (option B) | positivity_limiter = cell (box2d-lim, box2d-stiff, box2d-mhd): the backbone takes | compute_positivity_factors, adam_flume_cpu_positivity_kernels_agnostic.INC; add_gravity_limited_correction, limit_positivity, adam_flume_cpu_object.F90; numerics |
| Input checks | a gravity component along a null direction and immersed solids are refused; the stiffness $ | \mathbf g |
| Space | WENO5 (weno-u-5) flux splitting on characteristic variables (weno); GV-6 with weights = si | compute_residuals_weno, adam_flume_cpu_object.F90; numerics |
| Time | SSP Runge–Kutta, 3 stages (runge-kutta-ssp-33), CFL 0.4 | adam_rk_object.F90 |
| Boundaries | periodic; wall-inviscid (mirrored ghosts); hydrostatic (GV-2) | set_boundary_conditions, adam_flume_cpu_object.F90; adam_flume_bc_object.F90; boundary conditions |
| FNL backend | the same kernels on the device | adam_flume_fnl_object.F90, adam_flume_fnl_kernels.F90 |
Initial and boundary conditions
Common to every leg: ngc = 4, null z (extrapolation), np 2, CFL 0.4, uniform state
| Leg | Case | State | x faces | y faces | Run |
|---|---|---|---|---|---|
| GV-1 | freefall2d | uniform | periodic | periodic | 50 steps |
| GV-3 | box2d | uniform | periodic | wall-inviscid | 200 steps |
| GV-3 | box2d-mhd | uniform, EGLM, | periodic | wall-inviscid | 200 steps |
| limiter | box2d-lim | periodic | wall-inviscid | 300 steps | |
| limiter | box2d-stiff | periodic | wall-inviscid | 200 steps | |
| GV-2 | iso2d with the force | isothermal atmosphere, | periodic | hydrostatic | to |
| GV-6 | box2d, weights = si | uniform | periodic | wall-inviscid | 100 steps, against its input rescaled: lengths by |
| GV-7 | box2d, box2d-mhd on FNL | as above | as above |
Checkpoints every 10 steps (GV-3 asserts every one of them).
Input files
| File | Role |
|---|---|
src/tests/flume/verification/gravity/make_atmosphere.py | writes each case (freefall2d, box2d, box2d-mhd, box2d-lim, box2d-stiff, iso2d; --cells, --cfl, --time-max, --weights, --steps) |
src/tests/flume/verification/gravity/check.sh | runs the legs (--legs LIST, e.g. gv1,gv3,limiter,gv2; the force legs unless --no-force; --scaling adds gv6 (GV-6); --agree TAG for GV-7, which needs the legs gv3, gv8, gv10, gv4c; --keep) |
src/tests/flume/verification/gravity/atmosphere_oracle.py | freefall (GV-1, energy (GV-3, --report-total for the limiter cases), rest (GV-2), agree (GV-7, |
src/tests/flume/verification/scaling/scaling.py | GV-6: rescale --j 2 --k -1 --m -2 and compare |
src/tests/flume/verification/make_doc_runs.sh (group gravity) | re-runs freefall2d, box2d, box2d-mhd with their checkpoints |
src/tests/flume/verification/make_doc_figures.py (fig_gravity_force) | draws the figure |
bash
cd src/tests/flume/verification/gravity
./check.sh --np 2 --cases iso2d --scaling --keep # CPU: G0 iso2d, the force legs, GV-6
FLUME_EXE=$PWD/../../../../../exe/adam_flume_fnl ./check.sh --np 2 --cases iso2d --keep \
--agree adam_flume_cpu # FNL, and GV-7 against the CPU runsResults

Left, GV-1 free fall; centre, the GV-3 energy budget over the whole run; right, box2d settled after 200 steps.
Drawn with the current scheme (G2a's fourth-order energy source). Left, GV-1: the momentum of the periodic box follows box2d) through the box2d after 200 steps: the uniform gas has settled into a stratification,
As measured at G1 (the face-form energy source; CPU, FNL the same by GV-7):
| Leg | Asserted | Bound | CPU | FNL |
|---|---|---|---|---|
| GV-1 | the same | |||
GV-3 box2d | mass and | mass | the same | |
GV-3 box2d-mhd | as above | the same | ||
box2d-lim | completes, mass conserved; | 74 304 faces limited, no inadmissible backbone, mass | the same | |
box2d-stiff | as above | 324 424 faces limited, 32 inadmissible backbones, mass | the same | |
| GV-2 | $\max | \mathbf u | /c$ at | — |
| GV-6 | weights = si against the rescaled input | bitwise | bitwise | bitwise |
| GV-7 | FNL against CPU, per field | — | box2d box2d-mhd |
GV-7 scales a vector component by its vector's largest component:
Re-measured with the fourth-order energy source of G2a (the current scheme; CPU and FNL):
| Leg | Asserted | Bound | CPU and FNL |
|---|---|---|---|
| GV-1 | as above | unchanged (uniform state: the correction is zero) | |
GV-3 box2d | mass and | mass | |
GV-3 box2d-mhd | mass and | ||
box2d-lim | completes, mass conserved; | 107 984 faces limited (the correction is a high-order cell source inside | |
box2d-stiff | as above | runs, mass | |
| GV-2 | reported | — | unchanged |
| GV-6, NV-5 | bitwise | bitwise | bitwise |
| GV-7 | FNL against CPU, per field |
Related cases: the order of the energy source (G2a, the correction and the invariant
Findings
- The total energy. With the face-form energy source the conserved total is
to round-off at every checkpoint, while alone moves by per cent. Since G2a the exactly conserved total at reflecting walls is , plus an wall-row term (energy order); GV-3 asserts and reports the plain sum. - The limiter and gravity (owner decision: option B). The first form put the face-form energy into the backbone. A cell beside a wall then gets half of the face form (the wall face carries no mass) while its momentum gains the whole
: the stage takes about out of its internal energy, which near vacuum is negative. box2d-limdied at step 128 andbox2d-stiffat step 1 (every backbone inadmissible), with and without the limiter. Option B gives the backbone the time-centred energy, which leaves its internal energy unchanged, and limits the face-form excess with ; both cases then run. The stiff case's 32 inadmissible backbones come from the fluxes, not from gravity. - In the limited cases
(since G2a ) is exact only where the limiter does not act; it is reported, not asserted. box2d-stiffis the stiff regime:is about 4.5 times the sound speed. No time-step bound is imposed for gravity; the regime is logged at the first step. - GV-2 is the unbalanced baseline of the well-balanced mode: the spurious Mach number of an atmosphere at rest falls with
but is not zero.