Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load and Generation Shedding #655

Merged
merged 49 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
96e1ca5
Add: AllowShedding attribute to GridObjects
DEUCE1957 Nov 4, 2024
75cf5a7
Debug: GridObject AllowShedding conversion
DEUCE1957 Nov 4, 2024
55e8c41
Add: Exception if shedding is not supported by Backend
DEUCE1957 Nov 4, 2024
51eb97e
Refact: Remove bool return from set_shedding() method
DEUCE1957 Nov 4, 2024
623d04b
Test: Add Entry for Allow_Shedding
DEUCE1957 Nov 4, 2024
ccbd1db
Refact: Remove Allow_Shedding from dict repr of GridObject
DEUCE1957 Nov 4, 2024
9c0078e
Add: Unit Tests
DEUCE1957 Nov 5, 2024
90c96d8
Refact: Use DEFAULT constants for n_busbar and allow_shedding
DEUCE1957 Nov 6, 2024
50b7c0f
Add: Can/Cannot Handle Interface for Load/Gen detachment
DEUCE1957 Nov 6, 2024
54ef719
Refact: Remove Set_Shedding
DEUCE1957 Nov 6, 2024
d9da4bf
Add: Backend-Agnostic Detachment Check
DEUCE1957 Nov 6, 2024
e66fd03
Add: ClassAttribute integration for AllowDetachment
DEUCE1957 Nov 6, 2024
6aa67c0
Debug: Use _get_topo_vect inside Backend check for Detachment
DEUCE1957 Nov 8, 2024
aebfaa1
Test: Update Backend Tests to expect _run_pf_with_diverging to catch …
DEUCE1957 Nov 8, 2024
486cffa
Debug: Try to fix Test_Issue_125
DEUCE1957 Nov 8, 2024
f16ba3c
Merge remote-tracking branch 'deuce1957/dev_shedding' into dev_shedding
BDonnot Nov 19, 2024
938709a
Add: 'detachment_is_allowed' in GridObj and Environment
DEUCE1957 Nov 23, 2024
4112dfe
Debug: assert 'detachment_is_allowed' in GridObject
DEUCE1957 Nov 23, 2024
7b6dabc
Test: Update strings for detachment
DEUCE1957 Nov 24, 2024
0666b39
Debug: Fix nested f-string in GridObjects
DEUCE1957 Nov 24, 2024
7cdf6c2
Debug: Add post-powerflow check for load / gen disconnect
DEUCE1957 Nov 24, 2024
bb23193
Debug: Add convergence check to post-powerflow check
DEUCE1957 Nov 24, 2024
c4d2c5c
Merge remote-tracking branch 'deuce1957/dev_shedding' into dev_shedding
BDonnot Nov 25, 2024
62f5428
fixing conflicts
BDonnot Nov 25, 2024
6e08212
forbid args in env creation, fix bug on CI, refacto the 'make' call
BDonnot Nov 25, 2024
4cf73c6
fixes to make tests pass
BDonnot Nov 25, 2024
dbba375
fix issue 125
BDonnot Nov 25, 2024
09d1a65
still working on making tests pass with new more concise implementation
BDonnot Nov 25, 2024
d6bf9a8
should fix all issues, need to make the AAA test suite better now
BDonnot Nov 26, 2024
8b70407
fixing broken tests (hopefully) and improve AAA backend test suite fo…
BDonnot Nov 26, 2024
2e81300
remove a pdb...
BDonnot Nov 26, 2024
3e25e95
Debug: Fix check in PandaPower Backend that prevents large-scale load…
DEUCE1957 Nov 27, 2024
d2d71ba
Debug: Use load dataframe instead of res_load for in_service check
DEUCE1957 Nov 27, 2024
809dfe4
Debug: Temporarily Rollback HotFix to PandaPowerBackend
DEUCE1957 Nov 27, 2024
5350712
Merge pull request #1 from BDonnot/dev_shedding
DEUCE1957 Nov 27, 2024
d2117e9
Merge branch 'dev_1.11.0' of https://github.com/Grid2op/grid2op into …
DEUCE1957 Dec 2, 2024
edcc81c
Refact: Improve Code Smell
DEUCE1957 Dec 2, 2024
5ee9aee
Add: Bring back fix to PandaPowerBackend for isolated loads
DEUCE1957 Dec 2, 2024
9adc3a4
Refact: Simplify _check_kirchhoff
DEUCE1957 Dec 2, 2024
42535de
Debug: Fix missing param in kirchhoff static methods
DEUCE1957 Dec 2, 2024
9a6b696
Refact: Emulate obs._check_kirchhoff in Backend._check_kirchhoff
DEUCE1957 Dec 2, 2024
5851026
refactoring check_kirchhoff methods of Observation and Backend, shoul…
BDonnot Dec 4, 2024
70d9292
Merge: dev_1.11.0 into dev_shedding
DEUCE1957 Dec 5, 2024
7dcbfa4
Merge pull request #2 from BDonnot/dev_shedding
DEUCE1957 Dec 5, 2024
1bdce5d
adding a kwargs to set the initial time stamp of the observation
BDonnot Dec 12, 2024
aab2b8d
Merge pull request #673 from BDonnot/bd_dev
BDonnot Dec 12, 2024
812a2e8
Merge remote-tracking branch 'upstream/dev_1.11.0' into dev_shedding
BDonnot Dec 13, 2024
c29b619
fix some last issue before merging on dev_turnoff_gen_load
BDonnot Dec 13, 2024
73d14dd
Merge branch 'BDonnot-dev_shedding' into dev_shedding
DEUCE1957 Dec 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ Native multi agents support:
name is added. This behaviour can be turned off by passing `_add_cls_nm_bk=False`
when calling `grid2op.make(...)`. If you develop a new Backend, you can also
customize the added name by overloading the `get_class_added_name` class method.
- [BREAKING] it is now forbidden to create environment with arguments.
Only key-word arguments are allowed.
- [FIXED] issue https://github.com/Grid2op/grid2op/issues/657
- [FIXED] missing an import on the `MaskedEnvironment` class
- [FIXED] a bug when trying to set the load_p, load_q, gen_p, gen_v by names.
Expand All @@ -123,6 +125,7 @@ Native multi agents support:
environment data
- [FIXED] an issue preventing to set the thermal limit in the options
if the last simulated action lead to a game over
- [FIXED] logos now have the correct URL
- [ADDED] possibility to set the "thermal limits" when calling `env.reset(..., options={"thermal limit": xxx})`
- [ADDED] possibility to retrieve some structural information about elements with
with `gridobj.get_line_info(...)`, `gridobj.get_load_info(...)`, `gridobj.get_gen_info(...)`
Expand All @@ -131,6 +134,8 @@ Native multi agents support:
- [ADDED] a method to check the KCL (`obs.check_kirchhoff`) directly from the observation
(previously it was only possible to do it from the backend). This should
be used for testing purpose only
- [ADDED] possibility to set the initial time stamp of the observation in the `env.reset`
kwargs by using `env.reset(..., options={"init datetime": XXX})`
- [IMPROVED] possibility to set the injections values with names
to be consistent with other way to set the actions (*eg* set_bus)
- [IMPROVED] error messages when creating an action which changes the injections
Expand All @@ -148,13 +153,15 @@ Native multi agents support:
does not have shunt information but there are not shunts on the grid.
- [IMPROVED] consistency of `MultiMixEnv` in case of automatic_classes (only one
class is generated for all mixes)
- [IMRPOVED] handling of disconnected elements in the backend no more
raise error. The base `Backend` class does that.
- [IMPROVED] the `act.as_serializable_dict()` to be more 'backend agnostic'as
it nows tries to use the name of the elements in the json output
- [IMPROVED] the way shunt data are digested in the `BaseAction` class (it is now
possible to use the same things as for the other types of element)
- [IMPROVED] grid2op does not require the `chronics` folder when using the `FromHandlers`
class

[1.10.4] - 2024-10-15
-------------------------
- [FIXED] new pypi link (no change in code)
Expand Down
83 changes: 83 additions & 0 deletions getting_started/13_DetachmentOfLoadsAndGenerators.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 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 detachment is disabled in all environments, to provide the keyword argument allow_detachment when initializing the environment. The backend must be able to support this feature."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import grid2op\n",
"from grid2op.Parameters import Parameters\n",
"from grid2op.PlotGrid import PlotMatplot\n",
"from pathlib import Path\n",
"\n",
"# Setup Environment\n",
"data_path = Path.cwd() / \"grid2op\" / \"data\"\n",
"p = Parameters()\n",
"p.MAX_SUB_CHANGED = 5\n",
"env = grid2op.make(data_path / \"rte_case5_example\", param=p, allow_detachment=True)\n",
"\n",
"# Setup Plotter Utility\n",
"plotter = PlotMatplot(env.observation_space, load_name=True, gen_name=True, dpi=150)\n",
"print(f\"Loads: {env.n_load}, Generators: {env.n_gen}, Storage: {env.n_storage}, Allow Detachment: {env._allow_detachment}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Detach the loads at substation 3 and 4. Normally this would cause a game-over, but if allow_detachment is True, the powerflow will be run. Game over in these cases can only occur if the powerflow does not converge."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"load_lookup = {name:i for i,name in enumerate(env.name_load)}\n",
"gen_lookup = {name:i for i,name in enumerate(env.name_gen)}\n",
"act = env.action_space({\"set_bus\":[(env.load_pos_topo_vect[load_lookup[\"load_3_1\"]], -1),\n",
" (env.load_pos_topo_vect[load_lookup[\"load_4_2\"]], -1)]})\n",
"print(act)\n",
"env.set_id(\"00\")\n",
"init_obs = env.reset()\n",
"obs, reward, done, info = env.step(act)\n",
"plotter.plot_obs(obs, figure=plt.figure(figsize=(8,5)))\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "venv_test",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.7"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
58 changes: 35 additions & 23 deletions grid2op/Action/baseAction.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ def __init__(self, _names_chronics_to_backend: Optional[Dict[Literal["loads", "p
self._modif_alert = False

@classmethod
def process_shunt_satic_data(cls):
def process_shunt_static_data(cls):
if not cls.shunts_data_available:
# this is really important, otherwise things from grid2op base types will be affected
cls.attr_list_vect = copy.deepcopy(cls.attr_list_vect)
Expand All @@ -506,7 +506,7 @@ def process_shunt_satic_data(cls):
except ValueError:
pass
cls.attr_list_set = set(cls.attr_list_vect)
return super().process_shunt_satic_data()
return super().process_shunt_static_data()

def copy(self) -> "BaseAction":
# sometimes this method is used...
Expand Down Expand Up @@ -573,8 +573,8 @@ def __copy__(self) -> "BaseAction":
return res

@classmethod
def process_shunt_satic_data(cls):
return super().process_shunt_satic_data()
def process_shunt_static_data(cls):
return super().process_shunt_static_data()

def __deepcopy__(self, memodict={}) -> "BaseAction":
res = type(self)()
Expand Down Expand Up @@ -846,7 +846,7 @@ def process_grid2op_compat(cls):
# if there are only one busbar, the "set_bus" action can still be used
# to disconnect the element, this is why it's not removed
cls._aux_process_n_busbar_per_sub()

cls.attr_list_set = copy.deepcopy(cls.attr_list_set)
cls.attr_list_set = set(cls.attr_list_vect)

Expand Down Expand Up @@ -1099,7 +1099,7 @@ def __eq__(self, other) -> bool:
self._change_bus_vect == other._change_bus_vect
):
return False

# shunts are the same
if type(self).shunts_data_available:
if self.n_shunt != other.n_shunt:
Expand Down Expand Up @@ -2163,6 +2163,34 @@ def _reset_vect(self):
self._vectorized = None
self._subs_impacted = None
self._lines_impacted = None

@staticmethod
def _check_keys_exist(action_cls:GridObjects, act_dict):
"""
Checks whether an action has the same keys in its
action space as are present in the provided dictionary.

Args:
action_cls (GridObjects): A Grid2Op action
act_dict (str:Any): Dictionary representation of an action
"""
for kk in act_dict.keys():
if kk not in action_cls.authorized_keys:
if kk == "shunt" and not action_cls.shunts_data_available:
# no warnings are raised in this case because if a warning
# were raised it could crash some environment
# with shunt in "init_state.json" with a backend that does not
# handle shunt
continue
if kk == "set_storage" and action_cls.n_storage == 0:
# no warnings are raised in this case because if a warning
# were raised it could crash some environment
# with storage in "init_state.json" but if the backend did not
# handle storage units
continue
warnings.warn(
f"The key '{kk}' used to update an action will be ignored. Valid keys are {action_cls.authorized_keys}"
)

def update(self,
dict_: DICT_ACT_TYPING
Expand Down Expand Up @@ -2374,23 +2402,7 @@ def update(self,
cls = type(self)

if dict_ is not None:
for kk in dict_.keys():
if kk not in cls.authorized_keys:
if kk == "shunt" and not cls.shunts_data_available:
# no warnings are raised in this case because if a warning
# were raised it could crash some environment
# with shunt in "init_state.json" with a backend that does not
# handle shunt
continue
if kk == "set_storage" and cls.n_storage == 0:
# no warnings are raised in this case because if a warning
# were raised it could crash some environment
# with storage in "init_state.json" but if the backend did not
# handle storage units
continue
warn = 'The key "{}" used to update an action will be ignored. Valid keys are {}'
warn = warn.format(kk, cls.authorized_keys)
warnings.warn(warn)
BaseAction._check_keys_exist(cls, dict_)

if cls.shunts_data_available:
# do not digest shunt when backend does not support it
Expand Down
4 changes: 2 additions & 2 deletions grid2op/Agent/topologyGreedy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# SPDX-License-Identifier: MPL-2.0
# This file is part of Grid2Op, Grid2Op a testbed platform to model sequential decision making in power systems.

from typing import List
from typing import List, Optional
from grid2op.Observation import BaseObservation
from grid2op.Action import BaseAction, ActionSpace
from grid2op.Agent.greedyAgent import GreedyAgent
Expand All @@ -27,7 +27,7 @@ class TopologyGreedy(GreedyAgent):

def __init__(self, action_space: ActionSpace, simulated_time_step : int =1):
GreedyAgent.__init__(self, action_space, simulated_time_step=simulated_time_step)
self.tested_action : List[BaseAction]= None
self.tested_action : Optional[list[BaseAction]] = None

def _get_tested_action(self, observation: BaseObservation) -> List[BaseAction]:
if self.tested_action is None:
Expand Down
Loading