Skip to content

Commit f004f19

Browse files
committed
fix(sim): resolve nvhpc OMP-offload ICE in s_compute_dt (firstprivate acoustic_substepping)
1 parent 6ebe172 commit f004f19

2 files changed

Lines changed: 30 additions & 22 deletions

File tree

src/simulation/m_sim_helpers.fpp

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module m_sim_helpers
1414

1515
implicit none
1616

17-
private; public :: s_compute_enthalpy, s_compute_stability_from_dt, s_compute_dt_from_cfl
17+
private; public :: s_compute_enthalpy, s_compute_stability_from_dt, s_compute_dt_from_cfl, f_compute_multidim_cfl_terms
1818

1919
contains
2020

@@ -218,19 +218,17 @@ contains
218218
end subroutine s_compute_stability_from_dt
219219

220220
!> Computes dt for a specified CFL number. When acoustic_substepping is true, icfl_dt is the per-dimension advective CFL limit
221-
!! (dropping the sound speed c), and acou_dt_sf (if present) is filled with the per-cell acoustic CFL dt limit min_i
222-
!! dx_i/(|u_i|+c) -- the SAME quantity that sets dt in the .not. acoustic_substepping path. The caller reduces acou_dt_sf with a
223-
!! global MIN and divides the (already globally reduced) advective dt by cfl_target*acou_dt_min to get the substep count,
224-
!! guaranteeing the acoustic microstep CFL (|u_i|+c)*dtau/dx_i <= cfl_target everywhere (see s_compute_dt).
225-
subroutine s_compute_dt_from_cfl(vel, c, max_dt, rho, Re_l, j, k, l, acou_dt_sf, acoustic_sub)
221+
!! (dropping the sound speed c); the caller (s_compute_dt) separately fills acou_dt_sf with the per-cell acoustic CFL dt limit
222+
!! min_i dx_i/(|u_i|+c) inline (keeping a single 3-D array, max_dt, in this routine's signature). Only the scalar acoustic_sub
223+
!! selects the advective-vs-acoustic inviscid speed here.
224+
subroutine s_compute_dt_from_cfl(vel, c, max_dt, rho, Re_l, j, k, l, acoustic_sub)
226225
227226
$:GPU_ROUTINE(parallelism='[seq]')
228227
real(wp), dimension(num_vels), intent(in) :: vel
229228
real(wp), intent(in) :: c, rho
230229
real(wp), dimension(0:m,0:n,0:p), intent(inout) :: max_dt
231230
real(wp), dimension(2), intent(in) :: Re_l
232231
integer, intent(in) :: j, k, l
233-
real(wp), dimension(0:m,0:n,0:p), intent(inout) :: acou_dt_sf
234232
! Passed by value (not read from the module) so this `acc routine seq` does not require the
235233
! acoustic_substepping module variable to be in `acc declare create` (nvfortran W-1054 -> nvlink undefined ref).
236234
logical, intent(in) :: acoustic_sub
@@ -250,17 +248,6 @@ contains
250248
adv_speed = sum(abs(vel(1:num_vels)))
251249
icfl_dt = cfl_target*(dx(j)/max(adv_speed, sgm_eps))
252250
end if
253-
if (acoustic_sub) then
254-
! Per-cell acoustic CFL dt limit min_i dx_i/(|u_i|+c). The caller reduces this with a GLOBAL MIN
255-
! (NOT a per-cell ratio with the advective dt -- that would blow up at near-stagnation cells, where
256-
! adv_dt is huge but the cell does not limit dt). Using independently reduced minima of the advective
257-
! and acoustic dt limits is what makes n_substeps the correct field-wide microstep count.
258-
if (p > 0 .or. n > 0) then
259-
acou_dt_sf(j, k, l) = f_compute_multidim_cfl_terms(vel, c, j, k, l)
260-
else
261-
acou_dt_sf(j, k, l) = dx(j)/(abs(vel(1)) + c)
262-
end if
263-
end if
264251
else
265252
if (p > 0 .or. n > 0) then
266253
! 2D/3D cases

src/simulation/m_time_steppers.fpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,9 @@ contains
406406

407407
if (cfl_dt) then
408408
@:ALLOCATE(max_dt(0:m, 0:n, 0:p))
409-
! acou_dt_sf is always allocated under cfl_dt (it is a required, non-optional arg of
410-
! s_compute_dt_from_cfl so that routine generates valid GPU device code; written only when
411-
! acoustic_substepping). nvfortran `acc routine seq` cannot handle optional arguments.
409+
! acou_dt_sf is always allocated under cfl_dt; it is written directly in s_compute_dt's GPU loop
410+
! (only when acoustic_substepping) and reduced afterwards, rather than being passed into the
411+
! s_compute_dt_from_cfl device routine.
412412
@:ALLOCATE(acou_dt_sf(0:m, 0:n, 0:p))
413413
end if
414414
@@ -764,13 +764,20 @@ contains
764764
real(wp) :: dt_local
765765
real(wp) :: acou_dt_local !< Local min acoustic CFL dt limit (acoustic substepping)
766766
real(wp) :: acou_dt_min !< Global min acoustic CFL dt limit (acoustic substepping)
767+
logical :: acou_sub !< Firstprivate copy of acoustic_substepping for the device loop
767768
integer :: j, k, l !< Generic loop iterators
768769
integer :: fl !< Fluid loop iterator
769770
770771
if (.not. igr) then
771772
call s_convert_conservative_to_primitive_variables(q_cons_ts(1)%vf, q_T_sf, q_prim_vf, idwint)
772773
end if
773774
775+
! Capture acoustic_substepping into a firstprivate local. The module logical is deliberately NOT in
776+
! `acc declare create` (see s_compute_dt_from_cfl: avoids nvfortran W-1054 -> nvlink undefined ref), so
777+
! referencing it directly inside the device loop segfaults nvhpc OMP-offload codegen (fort2). A loop-local
778+
! scalar is firstprivate-captured at region entry and is device-safe under both OpenACC and OpenMP.
779+
acou_sub = acoustic_substepping
780+
774781
$:GPU_PARALLEL_LOOP(collapse=3, private='[vel, alpha, Re, rho, vel_sum, pres, gamma, pi_inf, c, H, qv, fl]')
775782
do l = 0, p
776783
do k = 0, n
@@ -796,7 +803,21 @@ contains
796803
Re(1) = 1._wp/max(Re(1), sgm_eps)
797804
end if
798805
799-
call s_compute_dt_from_cfl(vel, c, max_dt, rho, Re, j, k, l, acou_dt_sf, acoustic_substepping)
806+
call s_compute_dt_from_cfl(vel, c, max_dt, rho, Re, j, k, l, acou_sub)
807+
808+
if (acou_sub) then
809+
! Per-cell acoustic CFL dt limit min_i dx_i/(|u_i|+c), the SAME quantity that sets dt in the
810+
! .not. acoustic_substepping path. Computed inline (not inside s_compute_dt_from_cfl) so
811+
! acou_dt_sf stays out of that device routine's signature, keeping the per-step macro-step
812+
! limit (max_dt) the only 3-D array it touches. Reduced with a GLOBAL MIN below (not a
813+
! per-cell ratio with adv_dt, which would blow up at near-stagnation cells); the separately
814+
! reduced advective/acoustic minima give the correct field-wide microstep count.
815+
if (p > 0 .or. n > 0) then
816+
acou_dt_sf(j, k, l) = f_compute_multidim_cfl_terms(vel, c, j, k, l)
817+
else
818+
acou_dt_sf(j, k, l) = dx(j)/(abs(vel(1)) + c)
819+
end if
820+
end if
800821
end do
801822
end do
802823
end do

0 commit comments

Comments
 (0)