Skip to content

Commit 3ced333

Browse files
committed
Merge master into cont_damage_fix
Conflict in m_riemann_solver_hllc.fpp: this branch and master (MFlowCode#1823) each split the HLLC private list to stay under the 132-column limit, in different ways. Kept master's _hllc_s*/_hllc_e* lists (one source of truth, joined once) and added this branch's solid_partial_density_L/R to _hllc_e1 next to damage_L/damage_R -- the damage flux that uses them is inside the #:if HYPO block, so they belong to the hypoelastic-only list. Claude-Session: https://claude.ai/code/session_01G77jhrA4JPDz5TqJzt8ACC
2 parents 2f16756 + 5829daf commit 3ced333

14 files changed

Lines changed: 415 additions & 42 deletions

.github/scripts/submit-slurm-job.sh

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,29 @@ elif [ "$device" = "gpu" ]; then
126126
# Determine GPU partition
127127
gpu_partition="batch"
128128
if [ "$gpu_partition_dynamic" = "true" ]; then
129-
# Use pre-selected bench partition if available, otherwise query sinfo
130-
if [ -n "${BENCH_GPU_PARTITION:-}" ]; then
131-
gpu_partition="$BENCH_GPU_PARTITION"
132-
echo "Using pre-selected bench partition: $gpu_partition (PR/master consistency)"
129+
if [ "$job_type" = "bench" ]; then
130+
# Benchmarks compare PR against master, so both jobs must land on the
131+
# SAME GPU type or the comparison is meaningless. That rules out a
132+
# partition list (SLURM could place PR and master on different
133+
# hardware); instead a single partition is picked and pinned across
134+
# both jobs via BENCH_GPU_PARTITION. See run_parallel_benchmarks.sh.
135+
if [ -n "${BENCH_GPU_PARTITION:-}" ]; then
136+
gpu_partition="$BENCH_GPU_PARTITION"
137+
echo "Using pre-selected bench partition: $gpu_partition (PR/master consistency)"
138+
else
139+
source "${SCRIPT_DIR}/select-gpu-partition.sh"
140+
gpu_partition="$SELECTED_GPU_PARTITION"
141+
fi
133142
else
134-
source "${SCRIPT_DIR}/select-gpu-partition.sh"
135-
gpu_partition="$SELECTED_GPU_PARTITION"
143+
# Tests (and build+test) don't compare across hardware, so submit to a
144+
# partition LIST and let SLURM start on whichever frees first instead
145+
# of pinning one partition and queueing behind it. This restores the
146+
# multi-partition backfill that #1299 dropped when it unified test and
147+
# bench onto the single-partition bench selector. gpu-l40s (bad
148+
# hardware) and gpu-rtx6000 (too slow for the test time limit) are
149+
# intentionally omitted.
150+
gpu_partition="gpu-h200,gpu-h100,gpu-a100,gpu-v100"
151+
echo "Using GPU partition list for test job: $gpu_partition"
136152
fi
137153
fi
138154

src/common/m_derived_types.fpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -526,11 +526,12 @@ module m_derived_types
526526
!> Condensed-phase reactive-burn (programmed pressure detonation) parameters. The rate is
527527
!> dlambda/dt = k (1 - lambda) ((p - pign)/pref)^n, optionally scaled by exp(-ta/T) when ta > 0.
528528
type reactive_burn_parameters
529-
real(wp) :: k !< Rate coefficient [1/s]
530-
real(wp) :: pign !< Ignition pressure threshold [Pa]
531-
real(wp) :: pref !< Reference pressure for the pressure drive [Pa]
532-
real(wp) :: n !< Pressure-drive exponent
533-
real(wp) :: ta !< Activation temperature [K] (0 = pure pressure-driven; > 0 adds exp(-ta/T))
529+
real(wp) :: k !< Rate coefficient [1/s]
530+
real(wp) :: pign !< Ignition pressure threshold [Pa]
531+
real(wp) :: pref !< Reference pressure for the pressure drive [Pa]
532+
real(wp) :: n !< Pressure-drive exponent
533+
real(wp) :: ta !< Activation temperature [K] (0 = pure pressure-driven; > 0 adds exp(-ta/T))
534+
integer :: substeps !< Operator-split sub-steps per time step (0 = source added to the flow RHS)
534535
end type reactive_burn_parameters
535536
536537
!> Lagrangian bubble parameters

src/common/m_global_parameters_common.fpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ contains
339339
rburn%pref = dflt_real
340340
rburn%n = dflt_real
341341
rburn%ta = 0._wp
342+
rburn%substeps = 0
342343

343344
! Case-optimization params: under case-opt these are compile-time constants in sim (skip assignment); in pre/post
344345
! MFC_CASE_OPTIMIZATION is always False so the block always executes there.

src/simulation/m_reactive_burn.fpp

Lines changed: 117 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,45 @@
1515
module m_reactive_burn
1616

1717
use m_global_parameters
18-
use m_variables_conversion, only: f_sg_thermal
18+
use m_variables_conversion, only: f_sg_thermal, s_compute_mixture_coefficients, f_pressure
1919

2020
implicit none
2121

22-
private; public :: s_compute_reactive_burn
22+
private; public :: s_compute_reactive_burn, s_reactive_burn_substep
2323

2424
contains
2525

26+
!> Programmed-burn rate dlambda/dt for one cell state. Both the RHS source and the operator-split integrator call this, so the
27+
!! rate law is stated once.
28+
!! @param pres Mixture pressure
29+
!! @param lambda Reaction progress, i.e. the product volume fraction
30+
!! @param alpha_rho_react Reactant partial density, for the optional Arrhenius factor
31+
!! @param alpha_react Reactant volume fraction, for the optional Arrhenius factor
32+
!! @param rate dlambda/dt; zero below the ignition pressure and once the reactant is spent
33+
subroutine s_burn_rate(pres, lambda, alpha_rho_react, alpha_react, rate)
34+
35+
$:GPU_ROUTINE(function_name='s_burn_rate', parallelism='[seq]', cray_inline=True)
36+
37+
real(wp), intent(in) :: pres, lambda, alpha_rho_react, alpha_react
38+
real(wp), intent(out) :: rate
39+
real(wp) :: drive
40+
41+
! Pressure-driven programmed burn: fires only behind the shock (p > rburn%pign).
42+
drive = (pres - rburn%pign)/rburn%pref
43+
if (drive > 0._wp .and. lambda < 1._wp) then
44+
rate = rburn%k*(1._wp - lambda)*drive**rburn%n
45+
! Optional Arrhenius dependence on the reactant phasic temperature from the stiffened-gas
46+
! EOS. rburn%ta = 0, the default, leaves the pure pressure-driven rate unchanged.
47+
if (rburn%ta > 0._wp) then
48+
rate = rate*exp(-rburn%ta/f_sg_thermal(pres, alpha_rho_react/max(alpha_react, sgm_eps), isentrope_n(1), &
49+
& isentrope_B(1), cvs(1)))
50+
end if
51+
else
52+
rate = 0._wp
53+
end if
54+
55+
end subroutine s_burn_rate
56+
2657
!> Add the programmed-burn reaction source to the continuity and volume-fraction RHS.
2758
!! @param rhs_vf Right-hand-side accumulator (inout)
2859
!! @param q_cons_vf Conserved variables (partial densities live here)
@@ -34,9 +65,9 @@ contains
3465
type(scalar_field), dimension(sys_size), intent(in) :: q_cons_vf, q_prim_vf
3566
type(int_bounds_info), dimension(1:3), intent(in) :: bounds
3667
integer :: x, y, z
37-
real(wp) :: rho, pres, lambda, rate, mdot, drive, T_r
68+
real(wp) :: rho, pres, lambda, rate, mdot
3869

39-
$:GPU_PARALLEL_LOOP(collapse=3, private='[rho, pres, lambda, rate, mdot, drive, T_r]', copyin='[bounds]')
70+
$:GPU_PARALLEL_LOOP(collapse=3, private='[rho, pres, lambda, rate, mdot]', copyin='[bounds]')
4071
do z = bounds(3)%beg, bounds(3)%end
4172
do y = bounds(2)%beg, bounds(2)%end
4273
do x = bounds(1)%beg, bounds(1)%end
@@ -45,20 +76,9 @@ contains
4576
pres = q_prim_vf(eqn_idx%E)%sf(x, y, z)
4677
lambda = q_prim_vf(eqn_idx%adv%beg + 1)%sf(x, y, z) ! reaction progress = product volume fraction
4778

48-
! pressure-driven programmed burn: fires only behind the shock (p > rburn%pign)
49-
drive = (pres - rburn%pign)/rburn%pref
50-
if (drive > 0._wp .and. lambda < 1._wp) then
51-
rate = rburn%k*(1._wp - lambda)*drive**rburn%n ! dlambda/dt
52-
53-
! Optional Arrhenius temperature dependence: rate *= exp(-rburn%ta/T_r), with T_r the
54-
! reactant phasic temperature from the stiffened-gas EOS T = (p + pi_inf)/((Gamma-1) rho cv).
55-
! rburn%ta = 0 (default) leaves the pure pressure-driven rate unchanged.
56-
if (rburn%ta > 0._wp) then
57-
T_r = f_sg_thermal(pres, q_cons_vf(eqn_idx%cont%beg)%sf(x, y, z)/q_prim_vf(eqn_idx%adv%beg)%sf(x, y, &
58-
& z), isentrope_n(1), isentrope_B(1), cvs(1))
59-
rate = rate*exp(-rburn%ta/T_r)
60-
end if
61-
79+
call s_burn_rate(pres, lambda, q_cons_vf(eqn_idx%cont%beg)%sf(x, y, z), q_prim_vf(eqn_idx%adv%beg)%sf(x, y, &
80+
& z), rate)
81+
if (rate > 0._wp) then
6282
mdot = rho*rate ! mass reactant -> product
6383

6484
! continuity: reactant loses mass, product gains it
@@ -76,4 +96,83 @@ contains
7696

7797
end subroutine s_compute_reactive_burn
7898

99+
!> Operator-split alternative to s_compute_reactive_burn, used when rburn%substeps > 0. The flow is frozen and the burn ODE is
100+
!! integrated over one time step in equal sub-steps, so the reaction time scale is decoupled from the acoustic CFL. The mixture
101+
!! pressure is re-evaluated from the frozen internal energy each sub-step, which is what carries the rate's own feedback: the
102+
!! coefficients move as the reactant becomes product.
103+
!! @param q_cons_vf Conserved variables, updated in place
104+
!! @param dtime Time step to integrate across
105+
!! @param bounds Interior cell bounds
106+
subroutine s_reactive_burn_substep(q_cons_vf, dtime, bounds)
107+
108+
type(scalar_field), dimension(sys_size), intent(inout) :: q_cons_vf
109+
real(wp), intent(in) :: dtime
110+
type(int_bounds_info), dimension(1:3), intent(in) :: bounds
111+
integer :: x, y, z, i, sub
112+
real(wp) :: rho, pres, lambda, rate
113+
real(wp) :: dt_sub, e_int, gamma_mix, pi_inf_mix, qv_mix
114+
real(wp) :: rho_mix, dlambda, dmass
115+
116+
! Bounded by num_fluids_max, not num_fluids: under case optimization num_fluids is a compile-time
117+
! constant that can be 1, and the reactant/product indices below are literal. The validator holds
118+
! reactive_burn to two fluids, so only the first two entries are ever used.
119+
real(wp), dimension(num_fluids_max) :: alpha_rho, alpha
120+
121+
dt_sub = dtime/real(rburn%substeps, wp)
122+
123+
$:GPU_PARALLEL_LOOP(collapse=3, private='[alpha_rho, alpha, rho, pres, lambda, rate, e_int, gamma_mix, pi_inf_mix, &
124+
& qv_mix, rho_mix, dlambda, dmass, i, sub]', copyin='[bounds, dt_sub]')
125+
do z = bounds(3)%beg, bounds(3)%end
126+
do y = bounds(2)%beg, bounds(2)%end
127+
do x = bounds(1)%beg, bounds(1)%end
128+
$:GPU_LOOP(parallelism='[seq]')
129+
do i = 1, num_fluids
130+
alpha_rho(i) = q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(x, y, z)
131+
alpha(i) = q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(x, y, z)
132+
end do
133+
rho = alpha_rho(1) + alpha_rho(2)
134+
135+
! Internal energy per unit volume is what the burn conserves: it moves mass and volume
136+
! between the phases, and the qv difference surfaces as pressure through the mixture EOS.
137+
e_int = q_cons_vf(eqn_idx%E)%sf(x, y, z)
138+
$:GPU_LOOP(parallelism='[seq]')
139+
do i = eqn_idx%mom%beg, eqn_idx%mom%end
140+
e_int = e_int - 0.5_wp*q_cons_vf(i)%sf(x, y, z)**2/rho
141+
end do
142+
143+
$:GPU_LOOP(parallelism='[seq]')
144+
do sub = 1, rburn%substeps
145+
lambda = alpha(2)
146+
call s_compute_mixture_coefficients(alpha_rho, alpha, rho_mix, gamma_mix, pi_inf_mix, qv_mix)
147+
pres = f_pressure(e_int, gamma_mix, pi_inf_mix, qv_mix)
148+
call s_burn_rate(pres, lambda, alpha_rho(1), alpha(1), rate)
149+
if (rate <= 0._wp) exit
150+
! A sub-step longer than the reaction time would carry the progress variable past one.
151+
! Stop it there and hand over the reactant's remaining mass in the same sub-step: capping
152+
! the two independently strands mass at zero volume, and the EOS divides one by the other.
153+
if (rate*dt_sub >= 1._wp - lambda) then
154+
dlambda = 1._wp - lambda
155+
dmass = alpha_rho(1)
156+
else
157+
dlambda = rate*dt_sub
158+
dmass = min(rho*dlambda, alpha_rho(1))
159+
end if
160+
alpha(1) = alpha(1) - dlambda
161+
alpha(2) = alpha(2) + dlambda
162+
alpha_rho(1) = alpha_rho(1) - dmass
163+
alpha_rho(2) = alpha_rho(2) + dmass
164+
end do
165+
166+
$:GPU_LOOP(parallelism='[seq]')
167+
do i = 1, num_fluids
168+
q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(x, y, z) = alpha_rho(i)
169+
q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(x, y, z) = alpha(i)
170+
end do
171+
end do
172+
end do
173+
end do
174+
$:END_GPU_PARALLEL_LOOP()
175+
176+
end subroutine s_reactive_burn_substep
177+
79178
end module m_reactive_burn

src/simulation/m_rhs.fpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,9 @@ contains
869869
call nvtxEndRange
870870
end if
871871
872-
if (reactive_burn) then
872+
! With rburn%substeps > 0 the burn is integrated by operator splitting after the flow
873+
! update (s_reactive_burn_substep), not added to the flow RHS here.
874+
if (reactive_burn .and. rburn%substeps == 0) then
873875
call nvtxStartRange("RHS-REACTIVE-BURN")
874876
call s_compute_reactive_burn(rhs_vf, q_cons_qp%vf, q_prim_qp%vf, idwint)
875877
call nvtxEndRange

0 commit comments

Comments
 (0)