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