|
| 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