diff --git a/src/diag_counters.f90 b/src/diag_counters.f90 index db66ac71..cfc4561e 100644 --- a/src/diag_counters.f90 +++ b/src/diag_counters.f90 @@ -22,7 +22,8 @@ module diag_counters EVT_WARNING_MAXIT_REJECT_100, EVT_WARNING_MAXIT_REJECT_1E4, & EVT_WARNING_MAXIT_REJECT_LARGE, EVT_WARNING_MAXIT_NONFINITE, & EVT_RETRY_EXHAUSTED, EVT_WARNING_AXIS_CROSSING_ACCEPT, & - EVT_TOROIDAL_REGULARIZATION, EVT_AXIS_FO_BRIDGE, N_EVENT + EVT_TOROIDAL_REGULARIZATION, EVT_AXIS_FO_BRIDGE, & + EVT_RECOVERY_STORM, N_EVENT public :: diag_counters_init, count_event, diag_counters_total, & diag_counters_reset, event_name @@ -52,7 +53,8 @@ module diag_counters integer, parameter :: EVT_WARNING_AXIS_CROSSING_ACCEPT = 21 integer, parameter :: EVT_TOROIDAL_REGULARIZATION = 22 integer, parameter :: EVT_AXIS_FO_BRIDGE = 23 - integer, parameter :: N_EVENT = 23 + integer, parameter :: EVT_RECOVERY_STORM = 24 + integer, parameter :: N_EVENT = 24 ! Whole cache lines per thread column keep neighbouring threads from sharing ! a line. The event id indexes within a column; STRIDE >= N_EVENT. @@ -147,6 +149,8 @@ function event_name(id) result(name) name = 'toroidal_regularization' case (EVT_AXIS_FO_BRIDGE) name = 'axis_fo_bridge' + case (EVT_RECOVERY_STORM) + name = 'recovery_storm' case default name = 'unknown' end select diff --git a/src/params.f90 b/src/params.f90 index 72e32b0d..a104f77a 100644 --- a/src/params.f90 +++ b/src/params.f90 @@ -56,6 +56,10 @@ module params integer, parameter :: ORBIT_EXIT_NUMERICAL_LINEAR = 103 integer, parameter :: ORBIT_EXIT_NUMERICAL_EVENT = 104 integer, parameter :: ORBIT_EXIT_NUMERICAL_FULL_ORBIT = 105 + ! A marker whose trajectory was silently corrupted by a storm of symplectic + ! recovery events. It is not a physical loss and is not counted as confined; + ! the trajectory is no longer trustworthy, so the marker is flagged for audit. + integer, parameter :: ORBIT_EXIT_RECOVERY_STORM = 106 real(dp) :: contr_pp = -1d0 integer :: ibins logical :: generate_start_only = .False. @@ -146,6 +150,12 @@ module params !> microstep. A second consecutive failure is terminal rather than freezing !> the remainder of the orbit at one phase-space point. integer, parameter :: max_consecutive_warning_holds = 1 + !> Per-marker threshold: if a marker accumulates more than this many recovery + !> events during the full trace, it is flagged as a recovery storm exit (106). + integer :: recovery_storm_threshold = 1000 + !> Run-level warning bound: if the ensemble-mean recovery events per + !> microstep exceeds this value, a warning suggesting a larger npoiper2 + real(dp) :: recovery_rate_warning_per_step = 1.0e1_dp character(1000) :: field_input = '' character(1000) :: coord_input = '' @@ -199,7 +209,8 @@ module params spectre_ncon_ode_relerr, & output_results_netcdf, & output_error, output_orbits_macrostep, & ! callback - macrostep_time_grid, checkpoint_interval, restart + macrostep_time_grid, checkpoint_interval, restart, & + recovery_storm_threshold, recovery_rate_warning_per_step integer(int8), allocatable :: wall_hit(:) real(dp), allocatable :: wall_hit_cart(:, :)