Skip to content

Commit 1ee119b

Browse files
committed
Pass scalars into the EOS device routines: Cray OpenACC misaddresses a device-array element passed by reference
1 parent c167a0a commit 1ee119b

9 files changed

Lines changed: 103 additions & 61 deletions

File tree

.claude/rules/common-pitfalls.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ covered in `docs/documentation/contributing.md`.
6060
QBMM/viscous and MHD HLLD, while both Lagrange bubble cases *complete* with out-of-tolerance
6161
answers. Measured 2026-08-29 on MI210. A compile-only check returns green, so any future attempt to
6262
drop these must run the tests, not just build.
63+
- Pass **scalars** into device routines, never an element of a device-resident array: a `declare create`
64+
module array (`blkmod1(k,l,q)`, `gammas(i)`), an attached field (`q_prim_vf%vf(i)%sf(j,k,l)`), or a
65+
dummy sized by a device global (`alpha_K(i)` with `dimension(num_fluids)`). Copy the element to a
66+
local first and receive outputs into a local. CCE OpenACC compiles it clean and, unless it inlines
67+
the callee, reads and writes the element at the wrong address: on PR #1811 a kernel wrote
68+
`blkmod1(:,:,:)` through such a call and every cell stayed 0 while the host got 1.4 from the same
69+
fields; every test through the path ended in `NaN(s) in timestep output` while CCE OpenMP, amdflang
70+
and nvfortran were bit-identical. A leaf callee that gets inlined hides the bug, which is why the
71+
parent PR passed. Expressions (`a/max(b, eps)`) are temporaries and are fine.
6372
- The same "call it from the loop body" rule covers `m_thermochem`: calling `get_species_*` from
6473
inside a `GPU_ROUTINE` rather than from the kernel gave CCE OpenMP a runtime
6574
`Memory access fault by GPU node-N ... Reason: Unknown` on the first step (exit 134), while every

src/common/m_variables_conversion.fpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ contains
752752
real(wp) :: rho
753753
real(wp) :: gamma
754754
real(wp) :: pi_inf
755+
real(wp) :: pres_i, alpha_i, alpha_rho_i, e_i
755756
real(wp) :: qv
756757
real(wp) :: dyn_pres
757758
real(wp) :: nbub, R3tmp
@@ -894,10 +895,11 @@ contains
894895
! Six-equation model (Saurel et al. JCP 2009): compute per-phase internal energies
895896
if (model_eqns == model_eqns_6eq) then
896897
do i = 1, num_fluids
897-
call s_phase_internal_energy(q_prim_vf(eqn_idx%E)%sf(j, k, l), &
898-
& q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l), &
899-
& q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(j, k, l), i, &
900-
& q_cons_vf(i + eqn_idx%int_en%beg - 1)%sf(j, k, l))
898+
pres_i = q_prim_vf(eqn_idx%E)%sf(j, k, l)
899+
alpha_i = q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l)
900+
alpha_rho_i = q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(j, k, l)
901+
call s_phase_internal_energy(pres_i, alpha_i, alpha_rho_i, i, e_i)
902+
q_cons_vf(i + eqn_idx%int_en%beg - 1)%sf(j, k, l) = e_i
901903
end do
902904
end if
903905

@@ -1241,7 +1243,7 @@ contains
12411243
#:endif
12421244
real(wp), intent(out) :: rho_K, gamma_K, pi_inf_K, qv_K
12431245
real(wp) :: gamma_i, pi_inf_i, dpi_i, dgamma_i
1244-
real(wp) :: rho_i
1246+
real(wp) :: rho_i, alpha_i, alpha_rho_i
12451247
integer :: i !< Loop iterator over fluids
12461248
12471249
! The bubbly closure is written for one carrier liquid, which keeps its own coefficients
@@ -1263,7 +1265,9 @@ contains
12631265
$:GPU_LOOP(parallelism='[seq]')
12641266
do i = 1, num_fluids
12651267
rho_K = rho_K + alpha_rho_K(i)
1266-
call s_phase_coefficients(alpha_rho_K(i), alpha_K(i), i, rho_i, gamma_i, pi_inf_i, dpi_i, dgamma_i)
1268+
alpha_rho_i = alpha_rho_K(i)
1269+
alpha_i = alpha_K(i)
1270+
call s_phase_coefficients(alpha_rho_i, alpha_i, i, rho_i, gamma_i, pi_inf_i, dpi_i, dgamma_i)
12671271
gamma_K = gamma_K + alpha_K(i)*gamma_i
12681272
pi_inf_K = pi_inf_K + alpha_K(i)*pi_inf_i
12691273
qv_K = qv_K + alpha_rho_K(i)*qvs(i)
@@ -1283,7 +1287,7 @@ contains
12831287
real(wp), dimension(num_fluids), intent(in) :: dalpha_rho_dt, dadv_dt, alpha_rho, adv
12841288
#:endif
12851289
real(wp), intent(out) :: drho_dt, dgamma_dt, dpi_inf_dt, dqv_dt
1286-
real(wp) :: rho_i, gamma_i, pi_inf_i, dpi_i, dgamma_i
1290+
real(wp) :: rho_i, gamma_i, pi_inf_i, dpi_i, dgamma_i, alpha_i, alpha_rho_i
12871291
integer :: i !< Loop iterator over fluids
12881292
12891293
dgamma_dt = 0._wp
@@ -1299,7 +1303,9 @@ contains
12991303
$:GPU_LOOP(parallelism='[seq]')
13001304
do i = 1, num_fluids
13011305
drho_dt = drho_dt + dalpha_rho_dt(i)
1302-
call s_phase_coefficients(alpha_rho(i), adv(i), i, rho_i, gamma_i, pi_inf_i, dpi_i, dgamma_i)
1306+
alpha_rho_i = alpha_rho(i)
1307+
alpha_i = adv(i)
1308+
call s_phase_coefficients(alpha_rho_i, alpha_i, i, rho_i, gamma_i, pi_inf_i, dpi_i, dgamma_i)
13031309
! d(alpha X(rho_i))/dt with rho_i = alpha_rho/alpha; the alpha in dX/dt cancels
13041310
dgamma_dt = dgamma_dt + dadv_dt(i)*gamma_i + dgamma_i*(dalpha_rho_dt(i) - rho_i*dadv_dt(i))
13051311
dpi_inf_dt = dpi_inf_dt + dadv_dt(i)*pi_inf_i + dpi_i*(dalpha_rho_dt(i) - rho_i*dadv_dt(i))
@@ -1599,11 +1605,12 @@ contains
15991605
real(wp), intent(in) :: rho, pres
16001606
integer, intent(in) :: i
16011607
real(wp), intent(out) :: T
1602-
real(wp) :: p_ref, e_ref, dp_drho, de_drho, G0, dG0, T_ref
1608+
real(wp) :: p_ref, e_ref, dp_drho, de_drho, G0, dG0, T0, T_ref
16031609
16041610
if (f_is_state_dependent(i)) then
16051611
call s_reference_curve(rho, i, p_ref, e_ref, dp_drho, de_drho, G0, dG0)
1606-
call s_rk4(ode_reference_temperature, i, 1._wp/rho0s(i), t0s(i), 1._wp/rho, T_ref)
1612+
T0 = t0s(i)
1613+
call s_rk4(ode_reference_temperature, i, 1._wp/rho0s(i), T0, 1._wp/rho, T_ref)
16071614
T = T_ref + (pres - p_ref)/(rho*G0*cvs(i))
16081615
else
16091616
T = (pres + isentrope_B(i))/((isentrope_n(i) - 1._wp)*cvs(i)*rho)
@@ -1758,7 +1765,7 @@ contains
17581765
real(wp), dimension(num_fluids), intent(in), optional :: alpha_rho
17591766
#:endif
17601767
real(wp) :: alf !< Subgrid void fraction; dilute by construction
1761-
real(wp) :: blkmod_q
1768+
real(wp) :: blkmod_q, alpha_q, alpha_rho_q, gamma_q, pi_inf_q
17621769
integer :: q
17631770
17641771
if (chemistry) then ! Reacting mixture sound speed
@@ -1772,7 +1779,9 @@ contains
17721779
c = 0._wp
17731780
$:GPU_LOOP(parallelism='[seq]')
17741781
do q = 1, num_fluids
1775-
call s_phase_bulk_modulus(pres, adv(q), alpha_rho(q), q, blkmod_q)
1782+
alpha_q = adv(q)
1783+
alpha_rho_q = alpha_rho(q)
1784+
call s_phase_bulk_modulus(pres, alpha_q, alpha_rho_q, q, blkmod_q)
17761785
if (alt_soundspeed) then
17771786
c = c + adv(q)/blkmod_q
17781787
else
@@ -1788,14 +1797,18 @@ contains
17881797
c = 0._wp
17891798
$:GPU_LOOP(parallelism='[seq]')
17901799
do q = 1, num_fluids
1791-
c = c + adv(q)/f_bulk_modulus(pres, gammas(q), pi_infs(q))
1800+
gamma_q = gammas(q)
1801+
pi_inf_q = pi_infs(q)
1802+
c = c + adv(q)/f_bulk_modulus(pres, gamma_q, pi_inf_q)
17921803
end do
17931804
c = 1._wp/(rho*c)
17941805
else if (model_eqns == model_eqns_6eq) then ! volume-weighted arithmetic mean
17951806
c = 0._wp
17961807
$:GPU_LOOP(parallelism='[seq]')
17971808
do q = 1, num_fluids
1798-
c = c + adv(q)*f_bulk_modulus(pres, gammas(q), pi_infs(q))
1809+
gamma_q = gammas(q)
1810+
pi_inf_q = pi_infs(q)
1811+
c = c + adv(q)*f_bulk_modulus(pres, gamma_q, pi_inf_q)
17991812
end do
18001813
c = c/rho
18011814
else ! the mixture coefficients already carry the mixing

src/simulation/m_acoustic_src.fpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ contains
136136
#:endif
137137
real(wp) :: myRho, pi_inf_mix, qv_dummy
138138
real(wp) :: sim_time, c, gamma_mix
139-
real(wp) :: blkmod_q
139+
real(wp) :: blkmod_q, pres_q, alpha_q, alpha_rho_q
140140
real(wp) :: frequency_local, gauss_sigma_time_local
141141
real(wp) :: mass_src_diff, mom_src_diff
142142
real(wp) :: source_temporal
@@ -206,9 +206,10 @@ contains
206206

207207
deallocate (phi_rn)
208208

209-
$:GPU_PARALLEL_LOOP(private='[myalpha, myalpha_rho, myRho, pi_inf_mix, qv_dummy, c, blkmod_q, gamma_mix, &
210-
& frequency_local, gauss_sigma_time_local, mass_src_diff, mom_src_diff, source_temporal, j, &
211-
& k, l, q]', copyin = '[sum_BB, freq_conv_flag, gauss_conv_flag, sim_time]')
209+
$:GPU_PARALLEL_LOOP(private='[myalpha, myalpha_rho, myRho, pi_inf_mix, qv_dummy, c, blkmod_q, pres_q, alpha_q, &
210+
& alpha_rho_q, gamma_mix, frequency_local, gauss_sigma_time_local, mass_src_diff, &
211+
& mom_src_diff, source_temporal, j, k, l, q]', copyin = '[sum_BB, freq_conv_flag, &
212+
& gauss_conv_flag, sim_time]')
212213
do i = 1, num_points
213214
j = source_spatials(ai)%coord(1, i)
214215
k = source_spatials(ai)%coord(2, i)
@@ -229,7 +230,10 @@ contains
229230
c = 0._wp
230231
$:GPU_LOOP(parallelism='[seq]')
231232
do q = 1, num_fluids
232-
call s_phase_bulk_modulus(q_prim_vf(eqn_idx%E)%sf(j, k, l), myalpha(q), myalpha_rho(q), q, blkmod_q)
233+
pres_q = q_prim_vf(eqn_idx%E)%sf(j, k, l)
234+
alpha_q = myalpha(q)
235+
alpha_rho_q = myalpha_rho(q)
236+
call s_phase_bulk_modulus(pres_q, alpha_q, alpha_rho_q, q, blkmod_q)
233237
c = c + myalpha(q)*blkmod_q
234238
end do
235239
c = c/myRho

src/simulation/m_hypoelastic.fpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -599,14 +599,14 @@ contains
599599
!! @param nc_iface_vel_y_hatR_vf hat_R-pass radial-direction interface velocities
600600
subroutine s_compute_hypoelastic_rhs_axisym_geom_dual_pass(q_prim_vf, rhs_vf, nc_iface_vel_y_vf, nc_iface_vel_y_hatR_vf)
601601

602-
type(scalar_field), dimension(sys_size), intent(in) :: q_prim_vf
602+
type(scalar_field), dimension(sys_size), intent(in) :: q_prim_vf
603603
type(scalar_field), dimension(sys_size), intent(inout) :: rhs_vf
604-
type(scalar_field), dimension(:), intent(in) :: nc_iface_vel_y_vf
605-
type(scalar_field), dimension(:), intent(in) :: nc_iface_vel_y_hatR_vf
606-
real(wp) :: rho_K, G_K, K_K, C_num, pres_K, blkmod1_K, blkmod2_K
607-
integer :: i, k, l, q
604+
type(scalar_field), dimension(:), intent(in) :: nc_iface_vel_y_vf
605+
type(scalar_field), dimension(:), intent(in) :: nc_iface_vel_y_hatR_vf
606+
real(wp) :: rho_K, G_K, K_K, C_num, pres_K, blkmod1_K, blkmod2_K, alpha_K, alpha_rho_K
607+
integer :: i, k, l, q
608608

609-
$:GPU_PARALLEL_LOOP(collapse=3, private='[rho_K, G_K, K_K, C_num, pres_K, blkmod1_K, blkmod2_K]')
609+
$:GPU_PARALLEL_LOOP(collapse=3, private='[rho_K, G_K, K_K, C_num, pres_K, blkmod1_K, blkmod2_K, alpha_K, alpha_rho_K]')
610610
do q = 0, p
611611
do l = 0, n
612612
do k = 0, m
@@ -627,10 +627,12 @@ contains
627627
! Same two-component K as the HLLD anchor state (see m_riemann_solver_hypo_hlld.fpp), including the
628628
! verysmall denominator regularization
629629
pres_K = q_prim_vf(eqn_idx%E)%sf(k, l, q)
630-
call s_phase_bulk_modulus(pres_K, q_prim_vf(eqn_idx%adv%beg)%sf(k, l, q), &
631-
& q_prim_vf(eqn_idx%cont%beg)%sf(k, l, q), 1, blkmod1_K)
632-
call s_phase_bulk_modulus(pres_K, q_prim_vf(eqn_idx%adv%end)%sf(k, l, q), &
633-
& q_prim_vf(eqn_idx%cont%end)%sf(k, l, q), 2, blkmod2_K)
630+
alpha_K = q_prim_vf(eqn_idx%adv%beg)%sf(k, l, q)
631+
alpha_rho_K = q_prim_vf(eqn_idx%cont%beg)%sf(k, l, q)
632+
call s_phase_bulk_modulus(pres_K, alpha_K, alpha_rho_K, 1, blkmod1_K)
633+
alpha_K = q_prim_vf(eqn_idx%adv%end)%sf(k, l, q)
634+
alpha_rho_K = q_prim_vf(eqn_idx%cont%end)%sf(k, l, q)
635+
call s_phase_bulk_modulus(pres_K, alpha_K, alpha_rho_K, 2, blkmod2_K)
634636
blkmod1_K = blkmod1_K + (4._wp/3._wp)*Gs_hypo(1)
635637
blkmod2_K = blkmod2_K + (4._wp/3._wp)*Gs_hypo(2)
636638
K_K = q_prim_vf(eqn_idx%adv%beg)%sf(k, l, q)*q_prim_vf(eqn_idx%adv%end)%sf(k, l, &

src/simulation/m_ibm.fpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ contains
171171
real(wp), dimension(nb*nnode) :: presb_IP, massv_IP
172172
real(wp), dimension(num_species) :: Ys_IP
173173
#:endif
174+
real(wp) :: alpha_q, alpha_rho_q, e_q
174175
real(wp) :: T_IP, mw_IP, e_IP !< Image-point temperature, mixture MW, and mass-specific internal energy (chemistry)
175176
real(wp) :: v_blow_eff !< Effective surface blowing speed (after any pressure-coupled burn-rate scaling)
176177
! Primitive variables at the image point associated with a ghost point, interpolated from surrounding fluid cells.
@@ -223,7 +224,7 @@ contains
223224
$:GPU_PARALLEL_LOOP(private='[i, physical_loc, dyn_pres, alpha_rho_IP, alpha_IP, pres_IP, vel_IP, vel_g, vel_norm_IP, &
224225
& r_IP, v_IP, pb_IP, mv_IP, nmom_IP, presb_IP, massv_IP, rho, gamma, pi_inf, Re_K, G_K, Gs, gp, &
225226
& innerp, norm, buf, radial_vector, rotation_velocity, j, k, l, q, qv_K, c_IP, nbub, patch_id, &
226-
& Ys_IP, T_IP, mw_IP, e_IP, v_blow_eff, vel_sum_g, E_ghost]')
227+
& Ys_IP, T_IP, mw_IP, e_IP, v_blow_eff, vel_sum_g, E_ghost, alpha_q, alpha_rho_q, e_q]')
227228
do i = 1, num_gps
228229
gp = ghost_points(i)
229230
j = gp%loc(1)
@@ -444,9 +445,10 @@ contains
444445
if (model_eqns == model_eqns_6eq) then
445446
$:GPU_LOOP(parallelism='[seq]')
446447
do q = eqn_idx%int_en%beg, eqn_idx%int_en%end
447-
call s_phase_internal_energy(pres_IP, alpha_IP(q - eqn_idx%int_en%beg + 1), &
448-
& alpha_rho_IP(q - eqn_idx%int_en%beg + 1), q - eqn_idx%int_en%beg + 1, &
449-
& q_cons_vf(q)%sf(j, k, l))
448+
alpha_q = alpha_IP(q - eqn_idx%int_en%beg + 1)
449+
alpha_rho_q = alpha_rho_IP(q - eqn_idx%int_en%beg + 1)
450+
call s_phase_internal_energy(pres_IP, alpha_q, alpha_rho_q, q - eqn_idx%int_en%beg + 1, e_q)
451+
q_cons_vf(q)%sf(j, k, l) = e_q
450452
end do
451453
end if
452454
end do

src/simulation/m_pressure_relaxation.fpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ contains
123123
#:else
124124
real(wp), dimension(num_fluids) :: pres_K_init, rho_K_init, rho_K_s
125125
#:endif
126-
real(wp) :: gamma_K, pi_inf_K, dpi_K, dgamma_K, c2_K
126+
real(wp) :: gamma_K, pi_inf_K, dpi_K, dgamma_K, c2_K, alpha_i, alpha_rho_i, rho_i, p_i, rho_s_i
127127
integer, parameter :: MAX_ITER = 50
128128
! Pressure relaxation convergence tolerance
129129
real(wp), parameter :: TOLERANCE = 1.e-10_wp
@@ -137,9 +137,10 @@ contains
137137
! Phasic internal energy carries the formation energy: alpha_rho_k*qv_k must be
138138
! removed before inverting the stiffened-gas EOS, or a nonzero qv inflates the
139139
! phasic pressure by rho_k*qv_k/gamma_k (this is what breaks the reactive burn).
140-
call s_phase_coefficients(q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(j, k, l), &
141-
& q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l), i, rho_K_init(i), gamma_K, pi_inf_K, &
142-
& dpi_K, dgamma_K)
140+
alpha_rho_i = q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(j, k, l)
141+
alpha_i = q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l)
142+
call s_phase_coefficients(alpha_rho_i, alpha_i, i, rho_i, gamma_K, pi_inf_K, dpi_K, dgamma_K)
143+
rho_K_init(i) = rho_i
143144
pres_K_init(i) = ((q_cons_vf(i + eqn_idx%int_en%beg - 1)%sf(j, k, l) - q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(j, &
144145
& k, l)*qvs(i))/q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l) - pi_inf_K)/gamma_K
145146
if (.not. f_is_state_dependent(i)) then
@@ -174,7 +175,10 @@ contains
174175
$:GPU_LOOP(parallelism='[seq]')
175176
do i = 1, num_fluids
176177
if (q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l) > sgm_eps .and. any_state_dependent_eos) then
177-
call s_phase_density_on_isentrope(i, rho_K_init(i), pres_K_init(i), pres_relax, rho_K_s(i), c2_K)
178+
rho_i = rho_K_init(i)
179+
p_i = pres_K_init(i)
180+
call s_phase_density_on_isentrope(i, rho_i, p_i, pres_relax, rho_s_i, c2_K)
181+
rho_K_s(i) = rho_s_i
178182
f_pres = f_pres + q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(j, k, l)/rho_K_s(i)
179183
df_pres = df_pres - q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(j, k, l)/(rho_K_s(i)**2*c2_K)
180184
else if (q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l) > sgm_eps) then
@@ -207,7 +211,7 @@ contains
207211
type(scalar_field), dimension(sys_size), intent(inout) :: q_cons_vf
208212
integer, intent(in) :: j, k, l
209213
real(wp), intent(in) :: rho, gamma, pi_inf, qv_mix
210-
real(wp) :: dyn_pres, pres_relax
214+
real(wp) :: dyn_pres, pres_relax, alpha_i, alpha_rho_i, e_i
211215
integer :: i
212216

213217
dyn_pres = 0._wp
@@ -220,9 +224,10 @@ contains
220224

221225
$:GPU_LOOP(parallelism='[seq]')
222226
do i = 1, num_fluids
223-
call s_phase_internal_energy(pres_relax, q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l), &
224-
& q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(j, k, l), i, &
225-
& q_cons_vf(i + eqn_idx%int_en%beg - 1)%sf(j, k, l))
227+
alpha_i = q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l)
228+
alpha_rho_i = q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(j, k, l)
229+
call s_phase_internal_energy(pres_relax, alpha_i, alpha_rho_i, i, e_i)
230+
q_cons_vf(i + eqn_idx%int_en%beg - 1)%sf(j, k, l) = e_i
226231
end do
227232

228233
end subroutine s_correct_internal_energies

0 commit comments

Comments
 (0)