From 6fbe6063c42f449b54394c9377707c27afd4d488 Mon Sep 17 00:00:00 2001 From: Xavier Weiss Date: Wed, 6 Nov 2024 16:26:54 +0100 Subject: [PATCH] Add: Backend-Agnostic Detachment Check Signed-off-by: Xavier Weiss --- .../13_DetachmentOfLoadsAndGenerators.ipynb | 32 +++++++++++++++++-- grid2op/Backend/backend.py | 23 +++++++------ grid2op/Backend/pandaPowerBackend.py | 1 + 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/getting_started/13_DetachmentOfLoadsAndGenerators.ipynb b/getting_started/13_DetachmentOfLoadsAndGenerators.ipynb index c5522a1d..1d01ce17 100644 --- a/getting_started/13_DetachmentOfLoadsAndGenerators.ipynb +++ b/getting_started/13_DetachmentOfLoadsAndGenerators.ipynb @@ -4,8 +4,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Shedding\n", - "In emergency conditions, it may be possible / necessary for a grid operator to disconnect certain loads, generators, or other components in order to prevent a larger blackout. This notebook explores how this can be achieved in Grid2OP. \n", + "### Detachment of Loads and Generators\n", + "In emergency conditions, it may be possible / necessary for a grid operator to detach certain loads, generators, or other components in order to prevent a larger blackout. This notebook explores how this can be achieved in Grid2OP. \n", "\n", "By default shedding is disabled in all environments, to provide the keyword argument allow_detachment when initializing the environment." ] @@ -71,6 +71,34 @@ ")\n", "display(network.res_line.loc[:, [\"p_from_mw\", \"p_to_mw\", \"q_from_mvar\", \"q_to_mvar\"]])" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "env.backend.loads_info()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "env.backend.generators_info()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "topo_vect = env.backend.get_topo_vect()\n", + "topo_vect[env.backend.load_pos_topo_vect]" + ] } ], "metadata": { diff --git a/grid2op/Backend/backend.py b/grid2op/Backend/backend.py index d843edb8..87d76738 100644 --- a/grid2op/Backend/backend.py +++ b/grid2op/Backend/backend.py @@ -1080,16 +1080,21 @@ def _runpf_with_diverging_exception(self, is_dc : bool) -> Optional[Exception]: conv = False exc_me = None - # if not self.allow_detachment and (~self._grid.load["in_service"]).any(): - # # TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state - # raise pp.powerflow.LoadflowNotConverged("Disconnected load: for now grid2op cannot handle properly" - # " disconnected load. If you want to disconnect one, say it" - # " consumes 0. instead. Please check loads: " - # f"{(~self._grid.load['in_service'].values).nonzero()[0]}" - # ) try: - # load_p, load_q, load_v = self.loads_info() - # prod_p, prod_q, prod_v = self.generators_info() + # Check if loads/gens have been detached and if this is allowed, otherwise raise an error + # .. versionadded:: 1.11.0 + topo_vect = self.get_topo_vect() + + load_buses = topo_vect[self.load_pos_topo_vect] + if not self.allow_detachment and (load_buses == -1).any(): + raise Grid2OpException(f"One or more loads were detached before powerflow in Backend {type(self).__name__}" + "but this is not allowed or not supported (Game Over)") + + gen_buses = topo_vect[self.gen_pos_topo_vect] + if not self.allow_detachment and (gen_buses == -1).any(): + raise Grid2OpException(f"One or more generators were detached before powerflow in Backend {type(self).__name__}" + "but this is not allowed or not supported (Game Over)") + conv, exc_me = self.runpf(is_dc=is_dc) # run powerflow except Grid2OpException as exc_: exc_me = exc_ diff --git a/grid2op/Backend/pandaPowerBackend.py b/grid2op/Backend/pandaPowerBackend.py index 82477f25..9bf85f27 100644 --- a/grid2op/Backend/pandaPowerBackend.py +++ b/grid2op/Backend/pandaPowerBackend.py @@ -344,6 +344,7 @@ def load_grid(self, """ self.can_handle_more_than_2_busbar() + self.can_handle_detachment() full_path = self.make_complete_path(path, filename) with warnings.catch_warnings():