Skip to content

Commit b97ecf1

Browse files
committed
Stop the run when pressure relaxation produces a non-physical density
1 parent 2e0c334 commit b97ecf1

1 file changed

Lines changed: 26 additions & 12 deletions

File tree

src/simulation/m_pressure_relaxation.fpp

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module m_pressure_relaxation
1111

1212
use m_derived_types
1313
use m_global_parameters
14+
use m_mpi_proxy, only: s_mpi_abort
1415
use m_variables_conversion, only: s_convert_species_to_mixture_variables_kernel, f_pressure, s_phase_internal_energy, &
1516
& s_phase_coefficients, s_phase_density_on_isentrope, f_is_state_dependent
1617

@@ -37,26 +38,29 @@ contains
3738
real(wp), dimension(num_fluids) :: alpha_rho, alpha
3839
#:endif
3940
real(wp) :: rho, gamma, pi_inf, qv_mix
40-
integer :: hit_cap, hit_cap_sum
41+
integer :: hit_cap, hit_cap_sum, unusable, unusable_sum
4142
real(wp) :: resid, resid_max
4243

4344
! Formed here, not one call deeper: CCE OpenACC accepts a num_fluids-sized array passed to a device routine from a
4445
! parallel-loop body, and rejects the same call from inside another acc routine seq.
4546
hit_cap_sum = 0
47+
unusable_sum = 0
4648
resid_max = 0._wp
47-
$:GPU_PARALLEL_LOOP(private='[i, j, k, l, alpha_rho, alpha, rho, gamma, pi_inf, qv_mix, hit_cap, resid]', collapse=3, &
48-
& reduction='[[hit_cap_sum], [resid_max]]', reductionOp='[+, max]')
49+
$:GPU_PARALLEL_LOOP(private='[i, j, k, l, alpha_rho, alpha, rho, gamma, pi_inf, qv_mix, hit_cap, resid, unusable]', &
50+
& collapse=3, reduction='[[hit_cap_sum, unusable_sum], [resid_max]]', reductionOp='[+, max]')
4951
do l = 0, p
5052
do k = 0, n
5153
do j = 0, m
5254
if (mpp_lim) call s_correct_volume_fractions(q_cons_vf, j, k, l)
5355

5456
hit_cap = 0
5557
resid = 0._wp
58+
unusable = 0
5659
if (s_needs_pressure_relaxation(q_cons_vf, j, k, l)) then
57-
call s_equilibrate_pressure(q_cons_vf, j, k, l, hit_cap, resid)
60+
call s_equilibrate_pressure(q_cons_vf, j, k, l, hit_cap, resid, unusable)
5861
end if
5962
hit_cap_sum = hit_cap_sum + hit_cap
63+
unusable_sum = unusable_sum + unusable
6064
resid_max = max(resid_max, resid)
6165

6266
$:GPU_LOOP(parallelism='[seq]')
@@ -75,6 +79,12 @@ contains
7579
n_hit_cap = n_hit_cap + hit_cap_sum
7680
worst_residual = max(worst_residual, resid_max)
7781

82+
! Equilibration produced a density that is not a usable number. Continuing means advancing a cell that has
83+
! no physical state, which is the kind of quiet wrongness that only shows up as a bad answer much later.
84+
if (unusable_sum > 0) then
85+
call s_mpi_abort('Pressure relaxation produced a non-physical phasic density. Exiting.')
86+
end if
87+
7888
end subroutine s_pressure_relaxation_procedure
7989

8090
!> One line at the end of a run if the equilibration ever stopped on its iteration cap. Silence means every cell reached the
@@ -138,13 +148,13 @@ contains
138148
end subroutine s_correct_volume_fractions
139149

140150
!> Main pressure equilibration using Newton-Raphson
141-
subroutine s_equilibrate_pressure(q_cons_vf, j, k, l, hit_cap, resid)
151+
subroutine s_equilibrate_pressure(q_cons_vf, j, k, l, hit_cap, resid, unusable)
142152

143153
$:GPU_ROUTINE(parallelism='[seq]')
144154

145155
type(scalar_field), dimension(sys_size), intent(inout) :: q_cons_vf
146156
integer, intent(in) :: j, k, l
147-
integer, intent(out) :: hit_cap
157+
integer, intent(out) :: hit_cap, unusable
148158
real(wp), intent(out) :: resid
149159
real(wp) :: pres_relax, f_pres, df_pres
150160
#:if not MFC_CASE_OPTIMIZATION and USING_AMD
@@ -226,6 +236,7 @@ contains
226236
! Written as .not. (<=) so a NaN residual is reported as a miss, like a diverged one.
227237
hit_cap = 0
228238
resid = 0._wp
239+
unusable = 0
229240
if (.not. (abs(f_pres) <= TOLERANCE)) then
230241
hit_cap = 1
231242
! A NaN residual has to be mapped, not passed on: max() with a NaN keeps the other operand, so the
@@ -234,14 +245,17 @@ contains
234245
if (f_pres /= f_pres) resid = huge(1._wp)
235246
end if
236247

237-
! Update volume fractions. The Newton above often stops on the iteration cap rather than on the
238-
! tolerance, and the answer then depends on that cap, so an unconverged-but-physical density is still
239-
! used -- the alternative would move every six-equation result. What is refused is a density that is
240-
! not a usable number: rho_K_s <= 0 or NaN, which is how one bad cell became a NaN a few steps later.
241-
! The comparison is written as .not. (> 0) so a NaN takes the same path as a non-positive value.
248+
! An unconverged-but-physical density is still used: the Newton often stops on the iteration cap and the
249+
! answer then depends on that cap, so refusing it would move every six-equation result. A density that is
250+
! not a usable number is different -- the equilibration has failed, and the cell has no physical state to
251+
! continue from. Flag it and let the caller stop the run rather than quietly leaving the cell unrelaxed.
252+
! Written as .not. (> 0) so a NaN takes the same path as a non-positive value.
242253
$:GPU_LOOP(parallelism='[seq]')
243254
do i = 1, num_fluids
244-
if (q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l) > sgm_eps .and. .not. (rho_K_s(i) > 0._wp)) return
255+
if (q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(j, k, l) > sgm_eps .and. .not. (rho_K_s(i) > 0._wp)) then
256+
unusable = 1
257+
return
258+
end if
245259
end do
246260

247261
$:GPU_LOOP(parallelism='[seq]')

0 commit comments

Comments
 (0)