Skip to content

Commit 27a7746

Browse files
committed
test(sim): 3D low-Mach GPU demonstrators (shock + smooth acoustic pulse)
1 parent 9211347 commit 27a7746

2 files changed

Lines changed: 273 additions & 0 deletions

File tree

  • examples
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env python3
2+
"""
3+
3D smooth low-Mach acoustic pulse (single fluid, periodic) — the SMOOTH-FLOW companion to
4+
examples/3D_shock_lowmach_gpu for the split-explicit low-Mach acoustic substep
5+
(acoustic_substepping) on V100/OpenACC.
6+
7+
Why this case exists
8+
--------------------
9+
A localized strong shock raises the local Mach number and limits the advective-dt speedup
10+
of the split scheme (it can be near break-even in shock-dominated cases). The big speedup
11+
lives in the SMOOTH low-Mach bulk, where the robust (full-HLLC) shock-capture tier never
12+
fires and the whole domain advances on the cheap centered/acoustic-substep path with an
13+
advective-CFL outer step (~c/u ~ 1/M larger than the acoustic-CFL step of full HLLC).
14+
15+
Setup: a single uniform low-Mach background (rho0=1, p0=1, mean flow u_bg = 0.1*c0 in x) on
16+
a periodic cube, with a tiny smooth Gaussian pressure pulse (dp = 1e-3 * p0, sigma = 0.05)
17+
added by hardcoded IC hcid=304. The perturbation is smooth and infinitesimal, so the shock
18+
sensor never trips: this is the large-speedup regime.
19+
20+
Toggle via MFC_SPLIT env var: MFC_SPLIT=T -> split, otherwise -> baseline full HLLC.
21+
"""
22+
23+
import json
24+
import math
25+
import os
26+
27+
split = os.environ.get("MFC_SPLIT", "F").upper()
28+
acoustic_substepping = "T" if split == "T" else "F"
29+
30+
gamma = 1.4
31+
p0, rho0 = 1.0, 1.0
32+
c0 = math.sqrt(gamma * p0 / rho0) # ~1.1832
33+
u_bg = 0.1 * c0 # background Mach 0.1
34+
35+
# Domain: small cube so the fixed sigma=0.05 pulse (set inside hcid=304) is well resolved.
36+
L = 0.5
37+
Nx = 47 # 48^3 = 110592 cells; small for fast GPU turnaround
38+
Ny = 47
39+
Nz = 47
40+
dx = L / (Nx + 1)
41+
42+
CFL = 0.4
43+
# Acoustic-CFL outer dt (baseline / initial guess); split mode grows dt to the advective CFL.
44+
dt_init = CFL * dx / (u_bg + c0)
45+
46+
T_stop = 0.6
47+
t_save = T_stop / 4.0
48+
49+
print(
50+
json.dumps(
51+
{
52+
"run_time_info": "T",
53+
"x_domain%beg": 0.0,
54+
"x_domain%end": L,
55+
"y_domain%beg": 0.0,
56+
"y_domain%end": L,
57+
"z_domain%beg": 0.0,
58+
"z_domain%end": L,
59+
"m": Nx,
60+
"n": Ny,
61+
"p": Nz,
62+
"dt": dt_init,
63+
"cfl_adap_dt": "T",
64+
"cfl_target": CFL,
65+
"t_step_start": 0,
66+
"n_start": 0,
67+
"t_stop": T_stop,
68+
"t_save": t_save,
69+
"num_patches": 1,
70+
"model_eqns": 2,
71+
"num_fluids": 1,
72+
"alt_soundspeed": "F",
73+
"mpp_lim": "F",
74+
"mixture_err": "F",
75+
"time_stepper": "rk3",
76+
"weno_order": 5,
77+
"weno_eps": 1.0e-6,
78+
"mp_weno": "F",
79+
"weno_avg": "F",
80+
"mapped_weno": "F",
81+
"null_weights": "F",
82+
"riemann_solver": "hllc",
83+
"wave_speeds": "direct",
84+
"avg_state": "arithmetic",
85+
"bc_x%beg": -1,
86+
"bc_x%end": -1,
87+
"bc_y%beg": -1,
88+
"bc_y%end": -1,
89+
"bc_z%beg": -1,
90+
"bc_z%end": -1,
91+
"acoustic_substepping": acoustic_substepping,
92+
"n_acoustic_substeps": 0,
93+
"acoustic_div_damp": 0.1,
94+
"format": "binary",
95+
"precision": "double",
96+
"prim_vars_wrt": "T",
97+
"cons_vars_wrt": "T",
98+
"parallel_io": "F",
99+
# Patch 1: uniform low-Mach background filling the periodic cube.
100+
# hcid=304 overlays a smooth Gaussian pressure pulse (dp=1e-3*pres, sigma=0.05)
101+
# centered at the patch centroid.
102+
"patch_icpp(1)%geometry": 9,
103+
"patch_icpp(1)%x_centroid": 0.5 * L,
104+
"patch_icpp(1)%y_centroid": 0.5 * L,
105+
"patch_icpp(1)%z_centroid": 0.5 * L,
106+
"patch_icpp(1)%length_x": L,
107+
"patch_icpp(1)%length_y": L,
108+
"patch_icpp(1)%length_z": L,
109+
"patch_icpp(1)%vel(1)": u_bg,
110+
"patch_icpp(1)%vel(2)": 0.0,
111+
"patch_icpp(1)%vel(3)": 0.0,
112+
"patch_icpp(1)%pres": p0,
113+
"patch_icpp(1)%alpha_rho(1)": rho0,
114+
"patch_icpp(1)%alpha(1)": 1.0,
115+
"patch_icpp(1)%hcid": 304,
116+
"fluid_pp(1)%gamma": 1.0 / (gamma - 1.0),
117+
"fluid_pp(1)%pi_inf": 0.0,
118+
}
119+
)
120+
)
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#!/usr/bin/env python3
2+
"""
3+
3D low-Mach background + localized shock driver (single fluid) — the V100/OpenACC GPU
4+
demonstrator for the split-explicit low-Mach two-tier acoustic substep
5+
(acoustic_substepping).
6+
7+
This is a GPU-turnaround variant of examples/3D_shock_periodic_lowmach: same periodic,
8+
single-fluid, transverse-shear, Sod-like-driver structure, but the BACKGROUND is made
9+
genuinely low-Mach (u_bg ~ 0.1*c_amb, total background Mach ~0.12) so the smooth bulk sits
10+
in the low-Mach regime where the split scheme's advective outer step is large. A localized
11+
high-pressure slab still launches a right-running shock, so the robust (full-HLLC) tier
12+
flags at the shock faces and the two-tier shock capture is exercised in 3D.
13+
14+
Demonstrates (compare MFC_SPLIT=T vs =F at identical resolution):
15+
- Stability: runs to completion with acoustic_substepping='T', no NaN, no dt collapse.
16+
- Correctness: split solution matches full-HLLC (L2/Linf of conserved fields); shock
17+
captured non-oscillatorily (no spurious overshoot).
18+
- Conservation: total mass, energy, and all three momenta to ~machine precision.
19+
- GPU performance: per-step "Time Avg" and total time split vs full-HLLC on the V100.
20+
21+
Toggle via MFC_SPLIT env var: MFC_SPLIT=T -> split, otherwise -> baseline full HLLC.
22+
"""
23+
24+
import json
25+
import math
26+
import os
27+
28+
split = os.environ.get("MFC_SPLIT", "F").upper()
29+
acoustic_substepping = "T" if split == "T" else "F"
30+
31+
gamma = 1.4
32+
33+
# Moderate (2:1) pressure driver vs ambient. A full 10:1 Sod jump pushes the local Mach to
34+
# order 1 (no longer "low-Mach") and is smeared markedly more by the substepped scheme than
35+
# by tiny-dt full HLLC; a moderate jump keeps the local Mach modest, still launches a genuine
36+
# shock that flags the robust (full-HLLC) tier, and keeps split and full in close agreement.
37+
p_drive, rho_drive = 1.0, 1.0
38+
p_amb, rho_amb = 0.5, 0.5
39+
40+
c_amb = math.sqrt(gamma * p_amb / rho_amb)
41+
# Genuinely low-Mach background: mean flow Mach ~0.1, modest transverse shear ~0.05.
42+
u_bg = 0.1 * c_amb
43+
# Transverse velocities JUMP across the driver interface (shear in BOTH y and z): keeps both
44+
# off-normal momentum slots nonzero and varying at the flagged x-faces, while staying low Mach.
45+
v_amb = 0.05 * c_amb
46+
v_drive = -0.05 * c_amb
47+
w_amb = -0.05 * c_amb
48+
w_drive = 0.05 * c_amb
49+
50+
L = 1.0
51+
Nx = 47 # 48 cells in x
52+
Ny = 47 # 48 cells in y
53+
Nz = 47 # 48 cells in z (48^3 = 110592 cells; small for fast GPU turnaround)
54+
dx = L / (Nx + 1)
55+
Ly = L * (Ny + 1) / (Nx + 1) # cubic cells (dy = dz = dx)
56+
Lz = L * (Nz + 1) / (Nx + 1)
57+
58+
# Outer-step CFL (env-overridable). With a strong embedded shock the split scheme's
59+
# advective-CFL outer step must stay modest for stability, so the demonstrator uses a
60+
# conservative CFL shared by both split and full-HLLC for an apples-to-apples comparison.
61+
CFL = float(os.environ.get("MFC_CFL", "0.4"))
62+
umag = math.sqrt(u_bg**2 + max(abs(v_amb), abs(v_drive)) ** 2 + max(abs(w_amb), abs(w_drive)) ** 2)
63+
dt_init = CFL * dx / (umag + math.sqrt(gamma * p_drive / rho_drive))
64+
65+
# Keep the run short enough that the shock stays localized (does not traverse the periodic
66+
# domain), so the split-vs-full pointwise comparison is clean (no wrap-around mixing).
67+
T_stop = 0.3
68+
t_save = T_stop / 6.0
69+
70+
print(
71+
json.dumps(
72+
{
73+
"run_time_info": "T",
74+
"x_domain%beg": 0.0,
75+
"x_domain%end": L,
76+
"y_domain%beg": 0.0,
77+
"y_domain%end": Ly,
78+
"z_domain%beg": 0.0,
79+
"z_domain%end": Lz,
80+
"m": Nx,
81+
"n": Ny,
82+
"p": Nz,
83+
"dt": dt_init,
84+
"cfl_adap_dt": "T",
85+
"cfl_target": CFL,
86+
"t_step_start": 0,
87+
"n_start": 0,
88+
"t_stop": T_stop,
89+
"t_save": t_save,
90+
"num_patches": 2,
91+
"model_eqns": 2,
92+
"num_fluids": 1,
93+
"alt_soundspeed": "F",
94+
"mpp_lim": "F",
95+
"mixture_err": "F",
96+
"time_stepper": "rk3",
97+
"weno_order": 5,
98+
"weno_eps": 1.0e-6,
99+
"mp_weno": "F",
100+
"weno_avg": "F",
101+
"mapped_weno": "F",
102+
"null_weights": "F",
103+
"riemann_solver": "hllc",
104+
"wave_speeds": "direct",
105+
"avg_state": "arithmetic",
106+
"bc_x%beg": -1,
107+
"bc_x%end": -1,
108+
"bc_y%beg": -1,
109+
"bc_y%end": -1,
110+
"bc_z%beg": -1,
111+
"bc_z%end": -1,
112+
"acoustic_substepping": acoustic_substepping,
113+
"n_acoustic_substeps": 0,
114+
"acoustic_div_damp": 0.1,
115+
"format": "binary",
116+
"precision": "double",
117+
"prim_vars_wrt": "T",
118+
"cons_vars_wrt": "T",
119+
"parallel_io": "F",
120+
# Patch 1: ambient filling the domain (transverse velocities v_amb, w_amb)
121+
"patch_icpp(1)%geometry": 9,
122+
"patch_icpp(1)%x_centroid": 0.5 * L,
123+
"patch_icpp(1)%y_centroid": 0.5 * Ly,
124+
"patch_icpp(1)%z_centroid": 0.5 * Lz,
125+
"patch_icpp(1)%length_x": L,
126+
"patch_icpp(1)%length_y": 2.0 * Ly,
127+
"patch_icpp(1)%length_z": 2.0 * Lz,
128+
"patch_icpp(1)%vel(1)": u_bg,
129+
"patch_icpp(1)%vel(2)": v_amb,
130+
"patch_icpp(1)%vel(3)": w_amb,
131+
"patch_icpp(1)%pres": p_amb,
132+
"patch_icpp(1)%alpha_rho(1)": rho_amb,
133+
"patch_icpp(1)%alpha(1)": 1.0,
134+
# Patch 2: high-pressure driver slab (0.15 < x < 0.35), transverse v_drive, w_drive
135+
"patch_icpp(2)%geometry": 9,
136+
"patch_icpp(2)%alter_patch(1)": "T",
137+
"patch_icpp(2)%x_centroid": 0.25 * L,
138+
"patch_icpp(2)%y_centroid": 0.5 * Ly,
139+
"patch_icpp(2)%z_centroid": 0.5 * Lz,
140+
"patch_icpp(2)%length_x": 0.2 * L,
141+
"patch_icpp(2)%length_y": 2.0 * Ly,
142+
"patch_icpp(2)%length_z": 2.0 * Lz,
143+
"patch_icpp(2)%vel(1)": u_bg,
144+
"patch_icpp(2)%vel(2)": v_drive,
145+
"patch_icpp(2)%vel(3)": w_drive,
146+
"patch_icpp(2)%pres": p_drive,
147+
"patch_icpp(2)%alpha_rho(1)": rho_drive,
148+
"patch_icpp(2)%alpha(1)": 1.0,
149+
"fluid_pp(1)%gamma": 1.0 / (gamma - 1.0),
150+
"fluid_pp(1)%pi_inf": 0.0,
151+
}
152+
)
153+
)

0 commit comments

Comments
 (0)