Skip to content

Jeans modes under self-gravity ​

IDGroupMilestoneBackendsFigureRegression
SV-3, SV-4, SV-5Self-gravityM8 (#81), P3CPU, FNLyesselfgravity-jeans

Case and scope ​

P3 couples the FFT solver to the scheme: [gravity] self_gravity, one Poisson solve per Runge–Kutta stage, applied through the potential path of SV-1. A linear Jeans mode on a uniform gas obeys ω2=c2k2−4πGρ0: it oscillates for wavelengths below the Jeans length and grows above it.

What the case catches:

  • SV-3, the stable wave: a wrong factor 4πG, a wrong sign of the force, the mean not removed, or a solve that does not use each stage's own density; any of them shifts the frequency, and the L1 error against the exact wave leaves second order;
  • SV-4, the unstable mode: a wrong growth rate; a broken point symmetry (an exact symmetry of the equations); a leak in the conservation the design promises, exact in the semi-discrete form, so that only the time integration may drift: E+W must drift at the Runge–Kutta order, and the momentum must stay at round-off;
  • SV-5, scaling covariance: a wrong dimension of G in the [reference] layer.

Models and numerics ​

ItemChoiceCode
Equationscompressible Euler, ideal gas, γ=5/3, with self-gravitymodels
Gravityself_gravity = .true., Φ solved every Runge–Kutta stage from that stage's densitysolve_potential, set_potential, adam_flume_common_object.F90; compute_residuals_weno, adam_flume_cpu_object.F90; solve_potential_gpu, adam_flume_fnl_object.F90
Poisson solverFFT, periodic (SV-2): FFTW on CPU, cuFFT on FNLadam_poisson_fft_object.F90, adam_fnl_poisson_fft_object.F90
Potential sourcesthe face form of SV-1add_potential_sources, adam_flume_cpu_object.F90
SpaceWENO5 (weno-u-5) flux splitting on characteristic variables (weno)numerics
TimeSSP Runge–Kutta, 3 stages (runge-kutta-ssp-33), CFL 0.4 (collapse: 0.4, 0.2, 0.1)adam_rk_object.F90
Scaling (SV-5)[reference] converts G by u02/(ρ0L02)adam_flume_gravity_object.F90; models
Executablethe FFT build: exe/adam_flume_cpu_fft (mode flume-cpu-gnu-fft), exe/adam_flume_fnl_fft (mode flume-fnl-nvf-fft)fobos.d/flume.fobos

Initial and boundary conditions ​

ItemValue
Stateρ0=1, p0=3/5, γ=5/3 (sound speed c=1), at rest
Modesine-wave with wave_mode = jeans: k=2π(1,1) (wave_angle 45°, wavelength 1/2), k2=8π2; ρ=ρ0(1+Asin⁡θ), p=p0(1+γAsin⁡θ), the velocity of the mode
Gridthe unit square (2-D quadtree, 4×4 blocks, two uniform levels) or the unit cube (3-D octree, 2×2×2 blocks, one level), uniform, 4 ghosts; 4n (2-D) or 2n (3-D) cells per side for n cells per block side
Boundariesevery active face periodic (2-D: extrapolation on the null z faces)
Ranks2
LegGPhysicsGridAmplitude, end
SV-3, jeans2dπ/2: 4πGρ0=2π2stable, λ=λJ/2, ω=π6322, 642, 1282A=10−6; one period, t=2/6
SV-3, jeans3dπ/2the same wave in the x-y plane, z uniform163, 32310−6; t=2/6
SV-4, jeansu2d (linear)9π/2: 4πGρ0=18π2unstable, λ=1.5λJ, σ=π10; the box shifted to [1/8,9/8]2, so that the density's centre of symmetry is its corner642, a checkpoint every 5 steps10−6; t=0.5
SV-4, jeansc2d (collapse)9π/2as jeansu2d, into the nonlinear collapse (the peak density reaches 1.73)642, CFL 0.4, 0.2, 0.110−2; t=0.4
SV-5π/2, and its dimensional twinjeans2d in L0=4, u0=1/2, ρ0=1/16 with [reference], against the code-unit run32210−6; t=0.2

Input files ​

FileRole
src/tests/flume/verification/selfgravity/make_jeans.pywrites jeans2d, jeans3d, jeansu2d, jeansc2d (--cells, --cfl, --time-max, --it-save, --amplitude)
src/tests/flume/verification/selfgravity/jeans.shruns the legs sv3-2d, sv3-3d, sv4, sv5 (--np N, --legs LIST, --keep; FLUME_EXE selects the backend)
src/tests/flume/verification/selfgravity/jeans_oracle.pywave (SV-3), growth and symmetry (SV-4 linear), conservation (SV-4 collapse)
src/tests/flume/verification/scaling/reference.shSV-5: the dimensional twin against the code-unit run, bitwise (NV-5)
src/tests/flume/regression/selfgravity-jeans/input.inithe frozen jeansc2d at 322, 20 steps
src/tests/flume/verification/make_doc_runs.sh, group jeanssv3-2d-{8,16,32}, sv3-3d-{8,16}, sv4-linear, sv4-collapse-{0.4,0.2,0.1}
src/tests/flume/verification/make_doc_figures.py, fig_selfgravity_jeansdraws the figure (--only selfgravity-jeans)
bash
cd src/tests/flume/verification/selfgravity && ./jeans.sh --legs "sv3-2d sv3-3d sv4 sv5"        # CPU
FLUME_EXE=$PWD/../../../../../exe/adam_flume_fnl_fft ./jeans.sh --legs "sv3-2d sv3-3d sv4 sv5"  # FNL

Results ​

SV-3 and SV-4: the stable wave's errors against N, the unstable mode's growth, the collapse's energy drift and density

Top left: the stable wave's error falls as Δx2 in 2-D and 3-D. Top right: the unstable mode grows as eσt, the fit on the exact line. Bottom left: in the collapse E and W exchange 17 % (their curves coincide) while E+W drifts at the Runge–Kutta order, a factor 8 per halving of the CFL number. Bottom right: the collapsing density at t=0.4, peak 1.73.

The exact linear solution is ρ0(1+Asin⁡(θ−ωt)) (stable) and ρ0(1+Aeσtsin⁡θ) (unstable). The growth rate is the least-squares fit of log⁡a(t), a=2⟨(ρ/ρ0−1)sin⁡θ⟩, over the checkpoints in [0.1,0.5]. The symmetry is the point reflection about the box corner: ρ even, u odd.

LegAssertedBoundCPUFNL
SV-3, 2-D, N = 32, 64, 128L1 error of ρ over ρ0A: 2.14⋅10−3, 5.35⋅10−4, 1.34⋅10−4 (CPU = FNL to 4 digits); order of the finest pair≥1.82.00, 2.002.00, 2.00
SV-3, 3-D, N = 16, 328.49⋅10−3, 2.14⋅10−3; order≥1.81.991.99
SV-4, growth (N = 64, 27 checkpoints in [0.1,0.5])the fitted σ = 9.9275 against π10 = 9.9346, relative10−27.2⋅10−47.2⋅10−4
SV-4, mirror symmetrydefect over the mode amplitude at t=0.510−9ρ 4.8⋅10−11, u 3.7⋅10−11ρ 9.8⋅10−11, u 7.7⋅10−11
SV-4, collapse, CFL 0.4, 0.2, 0.1drift of E+W: 2.74⋅10−7, 3.45⋅10−8, 4.33⋅10−9; order in Δt≥2.52.99, 2.992.99, 2.99 (the same drifts)
SV-4, collapsethe largest |∫ρu|10−148.9⋅10−185.1⋅10−18
SV-5, scaling covariancethe dimensional run (with G converted) against the code-unit runbitwisebitwise (fields, histories, 14 conversions)bitwise with nvfortran 26.1 (WSL GPU); nvfortran 25.5 (A30) stops reading the converted input, as NV-5 does: a defect older than P3, #86

Related cases: the same modes across 2:1 seams are SV-10, under runtime AMR SV-11; the isolated analogue of the collapse is SV-8; the [reference] layer is scaling covariance (NV-5).

Findings ​

  • The coupling is second order, as P0 designed it (the 7-point Laplacian and the face form): the WENO-5 fluxes cannot lift it. The error after one period is 1.3⋅10−4 of the amplitude at N=128.
  • Only the time integration drifts. In the collapse E and W each change by 17 % of the total, yet E+W drifts by 3⋅10−7 at CFL 0.4, and the drift falls as Δt3, SSP-RK3's order: the semi-discrete scheme conserves E+W exactly, as the design predicted. Momentum stays at round-off.
  • The symmetry holds to round-off, not bitwise: the summation orders of WENO and of the FFT are not mirror invariant. The defect relative to the mode is 5⋅10−11 at the end; it is largest (7⋅10−10) early, when the amplitude is 10−6 and round-off is a larger fraction of it.
  • Cost. CPU (WSL, indicative): a Poisson solve of the 322 grid takes 0.2 ms; with self-gravity the 322 run takes 31 s against 29 s without (one solve per stage and one per history row). FNL (one A30 per rank): 1.3 ms per solve at 322, 4.4 ms at 1282, the density and the potential crossing the host each stage. A first version copied the whole device potential every stage, sized to the block capacity (23 270 blocks, 16 in use): 0.73 s per solve, whatever the grid. Only the active blocks cross now; the results are bitwise those of the first version.
  • CPU and FNL agree to the printed digits on every SV-3 and SV-4 measure; the symmetry defects differ (round-off of different summation orders), both within the bound by a factor 10.
  • SV-5 on nvfortran 25.5 fails to read the converted input, as NV-5 does (#86).
  • The regression case selfgravity-jeans freezes jeansc2d at 322 (4×4 blocks of 82) for 20 steps, not the verification's 642 collapse.