@@ -226,7 +226,16 @@ def foo(manager):
226226
227227 Number of consecutive timesteps each powerline has been on overflow.
228228
229- _nb_timestep_overflow_allowed: ``numpy.ndarray``, dtype: int
229+ _protection_counter: `numpy.ndarray``, dtype: int
230+ .. warning:: /!\\ \\ Internal, do not use unless you know what you are doing /!\\ \\
231+
232+ Current state of the delayed protection. It is exacly :attr:`BaseEnv._timestep_overflow` unless
233+ :attr:`grid2op.Parameters.Parameters.SOFT_OVERFLOW_THRESHOLD` != 1.
234+
235+ If the soft overflow threshold is different than 1, it counts the number of steps
236+ since the soft overflow threshold is "activated" (flow > limits * soft_overflow_threshold)
237+
238+ _nb_ts_max_protection_counter: ``numpy.ndarray``, dtype: int
230239 .. warning:: /!\\ \\ Internal, do not use unless you know what you are doing /!\\ \\
231240
232241 Number of consecutive timestep each powerline can be on overflow. It is usually read from
@@ -454,7 +463,8 @@ def __init__(
454463 self ._parameters .NO_OVERFLOW_DISCONNECTION
455464 )
456465 self ._timestep_overflow : np .ndarray = None
457- self ._nb_timestep_overflow_allowed : np .ndarray = None
466+ self ._protection_counter : np .ndarray = None
467+ self ._nb_ts_max_protection_counter : np .ndarray = None
458468 self ._hard_overflow_threshold : np .ndarray = None
459469
460470 # store actions "cooldown"
@@ -767,8 +777,9 @@ def _custom_deepcopy_for_copy(self, new_obj, dict_=None):
767777 # if True, then it will not disconnect lines above their thermal limits
768778 new_obj ._no_overflow_disconnection = self ._no_overflow_disconnection
769779 new_obj ._timestep_overflow = copy .deepcopy (self ._timestep_overflow )
770- new_obj ._nb_timestep_overflow_allowed = copy .deepcopy (
771- self ._nb_timestep_overflow_allowed
780+ new_obj ._protection_counter = copy .deepcopy (self ._protection_counter )
781+ new_obj ._nb_ts_max_protection_counter = copy .deepcopy (
782+ self ._nb_ts_max_protection_counter
772783 )
773784 new_obj ._hard_overflow_threshold = copy .deepcopy (self ._hard_overflow_threshold )
774785
@@ -1417,7 +1428,7 @@ def _has_been_initialized(self):
14171428 self ._times_before_topology_actionable = np .zeros (
14181429 shape = (bk_type .n_sub ,), dtype = dt_int
14191430 )
1420- self ._nb_timestep_overflow_allowed = np .full (
1431+ self ._nb_ts_max_protection_counter = np .full (
14211432 shape = (bk_type .n_line ,),
14221433 fill_value = self ._parameters .NB_TIMESTEP_OVERFLOW_ALLOWED ,
14231434 dtype = dt_int ,
@@ -1428,6 +1439,7 @@ def _has_been_initialized(self):
14281439 dtype = dt_float ,
14291440 )
14301441 self ._timestep_overflow = np .zeros (shape = (bk_type .n_line ,), dtype = dt_int )
1442+ self ._protection_counter = np .zeros (shape = (bk_type .n_line ,), dtype = dt_int )
14311443
14321444 # update the parameters
14331445 self .__new_param = self ._parameters # small hack to have it working as expected
@@ -1531,7 +1543,7 @@ def _update_parameters(self):
15311543 )
15321544 self ._nb_ts_reco = self ._parameters .NB_TIMESTEP_RECONNECTION
15331545
1534- self ._nb_timestep_overflow_allowed [
1546+ self ._nb_ts_max_protection_counter [
15351547 :
15361548 ] = self ._parameters .NB_TIMESTEP_OVERFLOW_ALLOWED
15371549 self ._hard_overflow_threshold [:] = self ._parameters .HARD_OVERFLOW_THRESHOLD
@@ -3267,6 +3279,7 @@ def _aux_register_env_converged(self,
32673279 # update the thermal limit, for DLR for example
32683280 self .backend .update_thermal_limit (self )
32693281 overflow_lines = self .backend .get_line_overflow ()
3282+ current_flows = self .backend .get_line_flow ()
32703283 # save the current topology as "last" topology (for connected powerlines)
32713284 # and update the state of the disconnected powerline due to cascading failure
32723285 self ._backend_action .update_state (disc_lines )
@@ -3285,6 +3298,11 @@ def _aux_register_env_converged(self,
32853298
32863299 # set to 0 the number of timestep for lines that are not on overflow
32873300 self ._timestep_overflow [~ overflow_lines ] = 0
3301+
3302+ # update protection counter
3303+ engaged_protection = current_flows > self .backend .get_thermal_limit () * self ._parameters .SOFT_OVERFLOW_THRESHOLD
3304+ self ._protection_counter [engaged_protection ] += 1
3305+ self ._protection_counter [~ engaged_protection ] = 0
32883306
32893307 # build the topological action "cooldown"
32903308 aff_lines , aff_subs = action .get_topological_impact (_read_from_cache = True )
@@ -3835,7 +3853,8 @@ def _reset_vectors_and_timings(self):
38353853 """
38363854 self ._no_overflow_disconnection = self ._parameters .NO_OVERFLOW_DISCONNECTION
38373855 self ._timestep_overflow [:] = 0
3838- self ._nb_timestep_overflow_allowed [
3856+ self ._protection_counter [:] = 0
3857+ self ._nb_ts_max_protection_counter [
38393858 :
38403859 ] = self ._parameters .NB_TIMESTEP_OVERFLOW_ALLOWED
38413860
@@ -3990,7 +4009,8 @@ def close(self):
39904009 "_forbid_dispatch_off" ,
39914010 "_no_overflow_disconnection" ,
39924011 "_timestep_overflow" ,
3993- "_nb_timestep_overflow_allowed" ,
4012+ "_protection_counter" ,
4013+ "_nb_ts_max_protection_counter" ,
39944014 "_hard_overflow_threshold" ,
39954015 "_times_before_line_status_actionable" ,
39964016 "_max_timestep_line_status_deactivated" ,
@@ -4615,7 +4635,7 @@ def __del__(self):
46154635 if hasattr (self , "_BaseEnv__closed" ) and not self .__closed :
46164636 self .close ()
46174637
4618- def _update_vector_with_timestep (self , horizon , is_overflow ):
4638+ def _update_vector_with_timestep (self , horizon , is_overflow , protection_triggered ):
46194639 """
46204640 INTERNAL
46214641
@@ -4671,9 +4691,10 @@ def _update_vector_with_timestep(self, horizon, is_overflow):
46714691 # this is tricky here because I have no model to predict the future...
46724692 # As i cannot do better, I simply do "if I am in overflow now, i will be later"
46734693 self ._timestep_overflow [is_overflow ] += (horizon - 1 )
4694+ self ._protection_counter [protection_triggered ] += (horizon - 1 )
46744695 return still_in_maintenance , reconnected , first_ts_maintenance
46754696
4676- def _reset_to_orig_state (self , obs ):
4697+ def _reset_to_orig_state (self , obs : BaseObservation ):
46774698 """
46784699 INTERNAL
46794700
@@ -4736,6 +4757,7 @@ def _reset_to_orig_state(self, obs):
47364757
47374758 # soft overflow
47384759 self ._timestep_overflow [:] = obs .timestep_overflow
4760+ self ._protection_counter [:] = obs .timestep_protection_engaged
47394761
47404762 def forecasts (self ):
47414763 # ensure that the "env.chronics_handler.forecasts" is called at most once per step
0 commit comments