Evaluate multi-guard physical and numerical safety gates for step rejection and retry.
Evaluates multiple safety constraints over the trial timestep. If any limits are violated (e.g. NaN/Inf presence, chemistry increments, density vacuum floors, temperature excursions, or PCG linear solver convergence bounds), the trial step is rejected, triggering a temporal step reduction and retry.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(case_params_t), | intent(in) | :: | params |
Input case parameters and user namelist settings. |
||
| type(solver_stats_t), | intent(in) | :: | stats |
Cumulative solver and PCG convergence metrics. |
||
| real(kind=rk), | intent(in) | :: | max_dT_chem |
Maximum temperature increment during the chemistry advance [K]. |
||
| real(kind=rk), | intent(in) | :: | max_dY_chem |
Maximum temperature increment during the chemistry advance [K]. Maximum species mass fraction increment during the chemistry advance. |
||
| real(kind=rk), | intent(in) | :: | max_rel_drho_chem |
Maximum temperature increment during the chemistry advance [K]. Maximum species mass fraction increment during the chemistry advance. Maximum relative density change during the chemistry advance. |
||
| real(kind=rk), | intent(in) | :: | ke_before |
Kinetic energy of the domain before the trial timestep [J]. |
||
| real(kind=rk), | intent(in) | :: | ke_after |
Kinetic energy of the domain before the trial timestep [J]. Trial domain kinetic energy after the trial timestep [J]. |
||
| real(kind=rk), | intent(in) | :: | cfl_after |
Kinetic energy of the domain before the trial timestep [J]. Trial domain kinetic energy after the trial timestep [J]. Peak domain CFL value computed at the trial state. |
||
| type(flow_fields_t), | intent(in) | :: | fields |
Struct containing current flow fields (u, p). |
||
| type(energy_fields_t), | intent(in) | :: | energy |
Struct containing current thermodynamic/energy fields (T, h). |
||
| type(transport_properties_t), | intent(in) | :: | transport |
Struct containing current transport/thermo properties (rho, mu). |
||
| logical, | intent(out) | :: | reject |
Output logical indicating if the trial step must be rejected. |
||
| character(len=*), | intent(out) | :: | reason |
Output character string describing the first tripped safety gate. |
subroutine evaluate_step_rejection(params, stats, max_dT_chem, max_dY_chem, max_rel_drho_chem, & ke_before, ke_after, cfl_after, fields, energy, transport, & reject, reason) use, intrinsic :: ieee_arithmetic, only: ieee_is_nan type(case_params_t), intent(in) :: params type(solver_stats_t), intent(in) :: stats real(rk), intent(in) :: max_dT_chem, max_dY_chem, max_rel_drho_chem real(rk), intent(in) :: ke_before, ke_after, cfl_after type(flow_fields_t), intent(in) :: fields type(energy_fields_t), intent(in) :: energy type(transport_properties_t), intent(in) :: transport logical, intent(out) :: reject character(len=*), intent(out) :: reason real(rk) :: ke_growth, cfl_limit reject = .false. reason = 'accepted' if (.not. params%enable_step_rejection) return ! Option B.1: NaN and Infinity Sanitation if (params%reject_on_nan) then if (any(ieee_is_nan(fields%u)) .or. any(abs(fields%u) > 1.0e8_rk)) then reject = .true. reason = 'NaN or Inf detected in velocity field u' return end if if (any(ieee_is_nan(fields%p)) .or. any(abs(fields%p) > 1.0e12_rk)) then reject = .true. reason = 'NaN or Inf detected in pressure field p' return end if if (allocated(energy%T)) then if (any(ieee_is_nan(energy%T)) .or. any(energy%T > 1.0e5_rk)) then reject = .true. reason = 'NaN or Inf detected in temperature field T' return end if end if if (allocated(transport%rho)) then if (any(ieee_is_nan(transport%rho))) then reject = .true. reason = 'NaN detected in density field rho' return end if end if end if ! Option B.2: Chemistry Limits if (params%chemistry_max_dT_per_step > zero .and. max_dT_chem > params%chemistry_max_dT_per_step) then reject = .true. reason = 'chemistry dT exceeded committed limit' return end if if (params%chemistry_max_dY_per_step > zero .and. max_dY_chem > params%chemistry_max_dY_per_step) then reject = .true. reason = 'chemistry dY exceeded committed limit' return end if if (params%chemistry_max_rel_rho_change_per_step > zero .and. & max_rel_drho_chem > params%chemistry_max_rel_rho_change_per_step) then reject = .true. reason = 'chemistry density change exceeded committed limit' return end if ! Option B.3: CFL Overshoot if (params%max_cfl_overshoot_factor > zero) then cfl_limit = params%max_cfl * params%max_cfl_overshoot_factor if (cfl_after > cfl_limit) then reject = .true. reason = 'post-step CFL overshoot' return end if end if ! Option B.4: Kinetic Energy Growth if (params%max_KE_growth_per_step > zero .and. ke_before > params%ke_reject_floor) then ke_growth = ke_after / ke_before if (ke_growth > params%max_KE_growth_per_step) then reject = .true. reason = 'kinetic energy growth exceeded limit' return end if end if ! Option B.5: PCG Pressure Iterations Ceiling if (params%reject_on_pressure_max_iter .and. stats%pressure_iterations >= params%pressure_max_iter) then reject = .true. reason = 'pressure solve reached max iterations' return end if ! Option B.6: PCG Convergence Health Audit if (stats%pressure_residual > params%max_pressure_residual_limit .and. & stats%pressure_residual_abs > params%pressure_abs_tol) then reject = .true. reason = 'pressure solver residual exceeds stability tolerance' return end if ! Option B.7: Density Floor/Vacuum Guard if (allocated(transport%rho)) then if (minval(transport%rho) < params%rho * params%min_density_ratio_limit) then reject = .true. reason = 'density vacuum limit violated' return end if end if ! Option B.8: Temperature Floor and Ceiling Excursions if (allocated(energy%T)) then if (minval(energy%T) < params%min_temperature_limit) then reject = .true. reason = 'temperature fell below safety floor' return end if if (maxval(energy%T) > params%max_temperature_limit) then reject = .true. reason = 'temperature exceeded safety ceiling' return end if end if end subroutine evaluate_step_rejection