LightSim2Grid 0.12.0__cp313-cp313-win_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. lightsim2grid/__init__.py +57 -0
  2. lightsim2grid/_utils/__init__.py +136 -0
  3. lightsim2grid/compilation_options/__init__.py +37 -0
  4. lightsim2grid/contingencyAnalysis.py +425 -0
  5. lightsim2grid/elements/__init__.py +38 -0
  6. lightsim2grid/gridmodel/__init__.py +26 -0
  7. lightsim2grid/gridmodel/compare_gridmodel.py +323 -0
  8. lightsim2grid/gridmodel/from_pandapower/__init__.py +11 -0
  9. lightsim2grid/gridmodel/from_pandapower/_aux_add_dc_line.py +82 -0
  10. lightsim2grid/gridmodel/from_pandapower/_aux_add_gen.py +35 -0
  11. lightsim2grid/gridmodel/from_pandapower/_aux_add_line.py +73 -0
  12. lightsim2grid/gridmodel/from_pandapower/_aux_add_load.py +42 -0
  13. lightsim2grid/gridmodel/from_pandapower/_aux_add_sgen.py +85 -0
  14. lightsim2grid/gridmodel/from_pandapower/_aux_add_shunt.py +41 -0
  15. lightsim2grid/gridmodel/from_pandapower/_aux_add_slack.py +131 -0
  16. lightsim2grid/gridmodel/from_pandapower/_aux_add_storage.py +38 -0
  17. lightsim2grid/gridmodel/from_pandapower/_aux_add_trafo.py +149 -0
  18. lightsim2grid/gridmodel/from_pandapower/_aux_check_legit.py +59 -0
  19. lightsim2grid/gridmodel/from_pandapower/_my_const.py +15 -0
  20. lightsim2grid/gridmodel/from_pandapower/_pp_bus_to_ls_bus.py +16 -0
  21. lightsim2grid/gridmodel/from_pandapower/initGridModel.py +174 -0
  22. lightsim2grid/gridmodel/from_pypowsybl/__init__.py +11 -0
  23. lightsim2grid/gridmodel/from_pypowsybl/_aux_handle_slack.py +62 -0
  24. lightsim2grid/gridmodel/from_pypowsybl/_from_pypowsybl.py +552 -0
  25. lightsim2grid/lightSimBackend.py +2119 -0
  26. lightsim2grid/newtonpf/__init__.py +11 -0
  27. lightsim2grid/pandapower_compat/__init__.py +12 -0
  28. lightsim2grid/pandapower_compat/dcpf/__init__.py +11 -0
  29. lightsim2grid/pandapower_compat/dcpf/_dcpf.py +65 -0
  30. lightsim2grid/pandapower_compat/newtonpf/__init__.py +11 -0
  31. lightsim2grid/pandapower_compat/newtonpf/_newtonpf.py +351 -0
  32. lightsim2grid/physical_law_checker.py +126 -0
  33. lightsim2grid/rewards/__init__.py +11 -0
  34. lightsim2grid/rewards/n1ContingencyReward.py +190 -0
  35. lightsim2grid/securityAnalysis.py +31 -0
  36. lightsim2grid/solver/__init__.py +75 -0
  37. lightsim2grid/timeSerie.py +284 -0
  38. lightsim2grid-0.12.0.dist-info/METADATA +382 -0
  39. lightsim2grid-0.12.0.dist-info/RECORD +45 -0
  40. lightsim2grid-0.12.0.dist-info/WHEEL +5 -0
  41. lightsim2grid-0.12.0.dist-info/licenses/AUTHORS.txt +9 -0
  42. lightsim2grid-0.12.0.dist-info/licenses/LICENSE +373 -0
  43. lightsim2grid-0.12.0.dist-info/licenses/LICENSE.md +373 -0
  44. lightsim2grid-0.12.0.dist-info/top_level.txt +2 -0
  45. lightsim2grid_cpp.cp313-win_arm64.pyd +0 -0
@@ -0,0 +1,57 @@
1
+ # Copyright (c) 2020-2024, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0.
4
+ # If a copy of the Mozilla Public License, version 2.0 was not distributed with this file,
5
+ # you can obtain one at http://mozilla.org/MPL/2.0/.
6
+ # SPDX-License-Identifier: MPL-2.0
7
+ # This file is part of LightSim2grid, LightSim2grid implements a c++ backend targeting the Grid2Op platform.
8
+
9
+ __version__ = "0.12.0"
10
+
11
+ __all__ = [
12
+ "newtonpf",
13
+ "SolverType",
14
+ "ErrorType",
15
+ "solver",
16
+ "compilation_options"]
17
+
18
+ # import directly from c++ module
19
+ from lightsim2grid.solver import SolverType
20
+ from lightsim2grid.solver import ErrorType
21
+
22
+ try:
23
+ from lightsim2grid.lightSimBackend import LightSimBackend # noqa: F401
24
+ __all__.append("LightSimBackend")
25
+ except ImportError as exc_: # noqa: F841
26
+ # grid2op is not installed, the Backend will not be available
27
+ pass
28
+
29
+ try:
30
+ from lightsim2grid.physical_law_checker import PhysicalLawChecker # noqa: F401
31
+ __all__.append("PhysicalLawChecker")
32
+ except ImportError as exc_: # noqa: F841
33
+ # grid2op is not installed, the PhysicalLawChecker will not be available
34
+ pass
35
+
36
+ try:
37
+ from lightsim2grid.timeSerie import TimeSerie # noqa: F401
38
+ __all__.append("TimeSerie")
39
+ __all__.append("timeSerie")
40
+ except ImportError as exc_: # noqa: F841
41
+ # grid2op is not installed, the TimeSeries module will not be available
42
+ pass
43
+
44
+ try:
45
+ from lightsim2grid.contingencyAnalysis import ContingencyAnalysis # noqa: F401
46
+ __all__.append("contingencyAnalysis")
47
+ __all__.append("ContingencyAnalysis")
48
+ except ImportError as exc_: # noqa: F841
49
+ # grid2op is not installed, the SecurtiyAnalysis module will not be available
50
+ pass
51
+
52
+ try:
53
+ from lightsim2grid.rewards import N1ContingencyReward # noqa: F401
54
+ __all__.append("rewards")
55
+ except ImportError as exc_: # noqa: F841
56
+ # grid2op is not installed, the SecurtiyAnalysis module will not be available
57
+ pass
@@ -0,0 +1,136 @@
1
+ # this class is defined to avoid circular references when using grid2op -> pandapower -> lightsim2grid -> grid2op
2
+ # this module is lazily imported by the LightSimBackend and should not be used anywhere else,
3
+ # as the name states
4
+
5
+ import warnings
6
+
7
+ try:
8
+ import grid2op
9
+ from grid2op.Backend import PandaPowerBackend
10
+ class _DoNotUseAnywherePandaPowerBackend(PandaPowerBackend):
11
+ """used to duplicate the class attributes of PandaPowerBackend"""
12
+ shunts_data_available = True
13
+
14
+ if not hasattr(PandaPowerBackend, "_clear_grid_dependant_class_attributes"):
15
+ # not available in python 3.7
16
+ warnings.warn("This is a compatibility mode, please avoid using it and migrate to python >=3.10 ideally.")
17
+ def f(cls):
18
+ cls._INIT_GRID_CLS = None # do not modify that, this is handled by grid2op automatically
19
+ cls._PATH_GRID_CLASSES = None # especially do not modify that
20
+
21
+ cls.glop_version = grid2op.__version__
22
+
23
+ cls.SUB_COL = 0
24
+ cls.LOA_COL = 1
25
+ cls.GEN_COL = 2
26
+ cls.LOR_COL = 3
27
+ cls.LEX_COL = 4
28
+ cls.STORAGE_COL = 5
29
+
30
+ cls.attr_list_vect = None
31
+ cls.attr_list_set = {}
32
+ cls.attr_list_json = []
33
+ cls.attr_nan_list_set = set()
34
+
35
+ # class been init
36
+ cls._IS_INIT = False
37
+
38
+ # name of the objects
39
+ cls.env_name = "unknown"
40
+ cls.name_load = None
41
+ cls.name_gen = None
42
+ cls.name_line = None
43
+ cls.name_sub = None
44
+ cls.name_storage = None
45
+
46
+ cls.n_gen = -1
47
+ cls.n_load = -1
48
+ cls.n_line = -1
49
+ cls.n_sub = -1
50
+ cls.n_storage = -1
51
+
52
+ cls.sub_info = None
53
+ cls.dim_topo = -1
54
+
55
+ # to which substation is connected each element
56
+ cls.load_to_subid = None
57
+ cls.gen_to_subid = None
58
+ cls.line_or_to_subid = None
59
+ cls.line_ex_to_subid = None
60
+ cls.storage_to_subid = None
61
+
62
+ # which index has this element in the substation vector
63
+ cls.load_to_sub_pos = None
64
+ cls.gen_to_sub_pos = None
65
+ cls.line_or_to_sub_pos = None
66
+ cls.line_ex_to_sub_pos = None
67
+ cls.storage_to_sub_pos = None
68
+
69
+ # which index has this element in the topology vector
70
+ cls.load_pos_topo_vect = None
71
+ cls.gen_pos_topo_vect = None
72
+ cls.line_or_pos_topo_vect = None
73
+ cls.line_ex_pos_topo_vect = None
74
+ cls.storage_pos_topo_vect = None
75
+
76
+ # "convenient" way to retrieve information of the grid
77
+ cls.grid_objects_types = None
78
+ # to which substation each element of the topovect is connected
79
+ cls._topo_vect_to_sub = None
80
+
81
+ # list of attribute to convert it from/to a vector
82
+ cls._vectorized = None
83
+
84
+ # redispatch data, not available in all environment
85
+ cls.redispatching_unit_commitment_availble = False
86
+ cls.gen_type = None
87
+ cls.gen_pmin = None
88
+ cls.gen_pmax = None
89
+ cls.gen_redispatchable = None
90
+ cls.gen_max_ramp_up = None
91
+ cls.gen_max_ramp_down = None
92
+ cls.gen_min_uptime = None
93
+ cls.gen_min_downtime = None
94
+ cls.gen_cost_per_MW = None # marginal cost (in currency / (power.step) and not in $/(MW.h) it would be $ / (MW.5mins) )
95
+ cls.gen_startup_cost = None # start cost (in currency)
96
+ cls.gen_shutdown_cost = None # shutdown cost (in currency)
97
+ cls.gen_renewable = None
98
+
99
+ # storage unit static data
100
+ cls.storage_type = None
101
+ cls.storage_Emax = None
102
+ cls.storage_Emin = None
103
+ cls.storage_max_p_prod = None
104
+ cls.storage_max_p_absorb = None
105
+ cls.storage_marginal_cost = None
106
+ cls.storage_loss = None
107
+ cls.storage_charging_efficiency = None
108
+ cls.storage_discharging_efficiency = None
109
+
110
+ # grid layout
111
+ cls.grid_layout = None
112
+
113
+ # shunt data, not available in every backend
114
+ cls.n_shunt = None
115
+ cls.name_shunt = None
116
+ cls.shunt_to_subid = None
117
+
118
+ # alarm / alert
119
+ cls.assistant_warning_type = None
120
+
121
+ # alarms
122
+ cls.dim_alarms = 0
123
+ cls.alarms_area_names = []
124
+ cls.alarms_lines_area = {}
125
+ cls.alarms_area_lines = []
126
+
127
+ # alerts
128
+ cls.dim_alerts = 0
129
+ cls.alertable_line_names = []
130
+ cls.alertable_line_ids = []
131
+ setattr(_DoNotUseAnywherePandaPowerBackend, "_clear_grid_dependant_class_attributes", classmethod(f))
132
+
133
+
134
+ except ImportError as exc_:
135
+ # grid2op is not installed, we do not use it.
136
+ pass
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2024, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0.
4
+ # If a copy of the Mozilla Public License, version 2.0 was not distributed with this file,
5
+ # you can obtain one at http://mozilla.org/MPL/2.0/.
6
+ # SPDX-License-Identifier: MPL-2.0
7
+ # This file is part of LightSim2grid, LightSim2grid implements a c++ backend targeting the Grid2Op platform.
8
+
9
+ __all__ = ["klu_solver_available",
10
+ "nicslu_solver_available",
11
+ "cktso_solver_available",
12
+ "compiled_march_native",
13
+ "compiled_o3_optim",
14
+ "version",
15
+ "lightsim2grid_lib"]
16
+
17
+ from lightsim2grid_cpp import klu_solver_available
18
+ from lightsim2grid_cpp import nicslu_solver_available
19
+ from lightsim2grid_cpp import cktso_solver_available
20
+ from lightsim2grid_cpp import compiled_march_native
21
+ from lightsim2grid_cpp import compiled_o3_optim
22
+ from lightsim2grid_cpp import version
23
+ from lightsim2grid_cpp import __file__ as lightsim2grid_lib
24
+
25
+ try:
26
+ from lightsim2grid_cpp import nicslu_lib
27
+ __all__.append("nicslu_lib")
28
+ except ImportError :
29
+ # NICSLU linear solver is not available
30
+ pass
31
+
32
+ try:
33
+ from lightsim2grid_cpp import cktso_lib
34
+ __all__.append("cktso_lib")
35
+ except ImportError :
36
+ # CKTSO linear solver is not available
37
+ pass
@@ -0,0 +1,425 @@
1
+ # Copyright (c) 2020, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0.
4
+ # If a copy of the Mozilla Public License, version 2.0 was not distributed with this file,
5
+ # you can obtain one at http://mozilla.org/MPL/2.0/.
6
+ # SPDX-License-Identifier: MPL-2.0
7
+ # This file is part of LightSim2grid, LightSim2grid implements a c++ backend targeting the Grid2Op platform.
8
+
9
+ __all__ = ["ContingencyAnalysisCPP"]
10
+
11
+ import copy
12
+ import numpy as np
13
+ from collections.abc import Iterable
14
+
15
+ from lightsim2grid.solver import SolverType
16
+ from lightsim2grid_cpp import ContingencyAnalysisCPP
17
+
18
+ try:
19
+ from lightsim2grid.lightSimBackend import LightSimBackend
20
+ __all__.append("ContingencyAnalysis")
21
+ GRID2OP_INSTALLED = True
22
+ except ImportError as exc_:
23
+ # grid2op is not installed
24
+ GRID2OP_INSTALLED = False
25
+
26
+
27
+ class __ContingencyAnalysis(object):
28
+ """
29
+ This class allows to perform a "security analysis" from a given grid state.
30
+
31
+ For now, you cannot change the grid state, and it only computes the security analysis with
32
+ current flows at origin of powerlines.
33
+
34
+ Feel free to post a feature request if you want to extend it.
35
+
36
+ This class is used in 4 phases:
37
+
38
+ 0) you create it from a grid2op environment (the grid topology will not be modified from this environment)
39
+ 1) you add some contingencies to simulate
40
+ 2) you start the simulation
41
+ 3) you read back the results
42
+
43
+
44
+ Examples
45
+ --------
46
+ An example is given here
47
+
48
+ .. code-block:: python
49
+
50
+ import grid2op
51
+ from lightsim2grid import SecurityAnalysis
52
+ from lightsim2grid import LightSimBackend
53
+ env_name = ...
54
+ env = grid2op.make(env_name, backend=LightSimBackend())
55
+
56
+ 0) you create
57
+ security_analysis = SecurityAnalysis(env)
58
+
59
+ 1) you add some contingencies to simulate
60
+ security_analysis.add_multiple_contingencies(...) # or security_analysis.add_single_contingency(...)
61
+
62
+ 2) you start the simulation (done automatically)
63
+ 3) you read back the results
64
+ res_p, res_a, res_v = security_analysis.get_flows()
65
+
66
+ # in this results, then
67
+ # res_a[row_id] will be the flows, on all powerline corresponding to the `row_id` contingency.
68
+ # you can retrieve it with `security_analysis.contingency_order[row_id]`
69
+
70
+ Notes
71
+ ------
72
+
73
+ Sometimes, the behaviour might differ from grid2op. For example, if simulating a contingency
74
+ leads to a non connected grid, then this function will return "Nan" for the flows and 0. for
75
+ the voltages.
76
+
77
+ In grid2op, it would be, in this case, 0. for the flows and 0. for the voltages.
78
+
79
+ """
80
+ STR_TYPES = (str, np.str_) # np.str deprecated in numpy 1.20 and earlier versions not supported anyway
81
+
82
+ def __init__(self, grid2op_env):
83
+ if not GRID2OP_INSTALLED:
84
+ raise RuntimeError("Impossible to use the python wrapper `ContingencyAnalysis` "
85
+ "when grid2op is not installed. Please fall back to the "
86
+ "c++ version (available in python) with:\n"
87
+ "\tfrom lightsim2grid.contingencyAnalysis import ContingencyAnalysisCPP\n"
88
+ "and refer to the appropriate documentation.")
89
+ from grid2op.Environment import Environment
90
+ self.__is_closed = False
91
+ if isinstance(grid2op_env, Environment):
92
+ if not isinstance(grid2op_env.backend, LightSimBackend):
93
+ raise RuntimeError("This class only works with LightSimBackend")
94
+ self._ls_backend = grid2op_env.backend.copy()
95
+ elif isinstance(grid2op_env, LightSimBackend):
96
+ if hasattr(grid2op_env, "_is_loaded") and not grid2op_env._is_loaded:
97
+ raise RuntimeError("Impossible to init a `ContingencyAnalysis` "
98
+ "with a backend that has not been initialized.")
99
+ self._ls_backend = grid2op_env.copy()
100
+ else:
101
+ raise RuntimeError("`ContingencyAnalysis` can only be created "
102
+ "with a grid2op `Environment` or a `LightSimBackend`")
103
+ self.computer = ContingencyAnalysisCPP(self._ls_backend._grid)
104
+ self._contingency_order = {} # key: contingency (as tuple), value: order in which it is entered
105
+ self._all_contingencies = []
106
+ self.__computed = False
107
+ self._vs = None
108
+ self._ampss = None
109
+ self._mws = None
110
+
111
+ self.available_solvers = self.computer.available_solvers()
112
+ if SolverType.KLU in self.available_solvers:
113
+ # use the faster KLU if available
114
+ self.computer.change_solver(SolverType.KLU)
115
+
116
+ @property
117
+ def all_contingencies(self):
118
+ return copy.deepcopy(self._all_contingencies)
119
+
120
+ @all_contingencies.setter
121
+ def all_contingencies(self, val):
122
+ raise RuntimeError("Impossible to add new topologies like this. Please use `add_single_contingency` "
123
+ "or `add_multiple_contingencies`.")
124
+
125
+ # TODO implement that !
126
+ def __update_grid(self, backend_act):
127
+ raise NotImplementedError("TODO !")
128
+ self.clear(with_contlist=False)
129
+ self._ls_backend.apply_action(backend_act)
130
+ # run the powerflow
131
+ self._ls_backend.runpf()
132
+ # update the computer
133
+ # self.computer = ContingencyAnalysisCPP(self._ls_backend._grid)
134
+ # self.computer.update_grid(...) # not implemented
135
+
136
+ def clear(self, with_contlist=True):
137
+ """
138
+ Clear the list of contingencies to simulate
139
+ """
140
+
141
+ if self.__is_closed:
142
+ raise RuntimeError("This is closed, you cannot use it.")
143
+
144
+ self.__computed = False
145
+ self._vs = None
146
+ self._ampss = None
147
+ self._mws = None
148
+ if with_contlist:
149
+ self.computer.clear()
150
+ self._contingency_order = {}
151
+ self._all_contingencies = []
152
+ else:
153
+ self.computer.clear_results_only()
154
+
155
+ def _single_cont_to_li_int(self, single_cont):
156
+ li_disc = []
157
+ if isinstance(single_cont, int):
158
+ single_cont = [single_cont]
159
+
160
+ for stuff in single_cont:
161
+ if isinstance(stuff, type(self).STR_TYPES):
162
+ stuff = (type(self._ls_backend).name_line == stuff).nonzero()
163
+ stuff = stuff[0]
164
+ if stuff.size == 0:
165
+ # name is not found
166
+ raise RuntimeError(f"Impossible to find a powerline named \"{stuff}\" in the environment")
167
+ stuff = int(stuff[0])
168
+ else:
169
+ stuff = int(stuff)
170
+ li_disc.append(stuff)
171
+ return li_disc
172
+
173
+ def add_single_contingency(self, *args):
174
+ """
175
+ This function allows to add a single contingency specified by either the powerlines names
176
+ (which should match env.name_line) or by their ID.
177
+
178
+ The contingency added can be a "n-1" which will simulate a single powerline disconnection
179
+ or a "n-k" which will simulate the disconnection of multiple powerlines.
180
+
181
+ It does not accept any keword arguments.
182
+
183
+ Examples
184
+ --------
185
+
186
+ .. code-block:: python
187
+
188
+ import grid2op
189
+ from lightsim2grid import SecurityAnalysis
190
+ from lightsim2grid import LightSimBackend
191
+ env_name = ...
192
+ env = grid2op.make(env_name, backend=LightSimBackend())
193
+
194
+ security_anlysis = SecurityAnalysis(env)
195
+ # the single (n-1) contingency "disconnect powerline 0" is added
196
+ security_anlysis.add_single_contingency(0)
197
+
198
+ # add the single (n-1) contingency "disconnect line 1
199
+ security_anlysis.add_single_contingency(env.name_line[1])
200
+
201
+ # add a single contingency that disconnect powerline 2 and 3 at the same time
202
+ security_anlysis.add_single_contingency(env.name_line[2], 3)
203
+
204
+ Notes
205
+ -----
206
+ If it raises an error for a given contingency, the object might be not properly initialized.
207
+ In this case, we recommend you to clear it (using the `clear()` method and to attempt to
208
+ add contingencies again.)
209
+
210
+ """
211
+ if self.__is_closed:
212
+ raise RuntimeError("This is closed, you cannot use it.")
213
+
214
+ li_disc = self._single_cont_to_li_int(args)
215
+ li_disc_tup = tuple(li_disc)
216
+ if li_disc_tup not in self._contingency_order:
217
+ # this is really the first time this contingency is seen
218
+ try:
219
+ self.computer.add_nk(li_disc)
220
+ my_id = len(self._contingency_order)
221
+ self._contingency_order[li_disc_tup] = my_id
222
+ self._all_contingencies.append(li_disc_tup)
223
+ except Exception as exc_:
224
+ raise RuntimeError(f"Impossible to add the contingency {args}. The most likely cause "
225
+ f"is that you try to disconnect a powerline that is not present "
226
+ f"on the grid") from exc_
227
+
228
+ def add_multiple_contingencies(self, *args):
229
+ """
230
+ This function will add multiple contingencies at the same time.
231
+
232
+ This code is equivalent to:
233
+
234
+ .. code-block:: python
235
+
236
+ for single_cont in args:
237
+ self.add_single_contingency(single_cont)
238
+
239
+ It does not accept any keword arguments.
240
+
241
+ Examples
242
+ --------
243
+
244
+ .. code-block:: python
245
+
246
+ import grid2op
247
+ from lightsim2grid import SecurityAnalysis
248
+ from lightsim2grid import LightSimBackend
249
+ env_name = ...
250
+ env = grid2op.make(env_name, backend=LightSimBackend())
251
+
252
+ security_anlysis = SecurityAnalysis(env)
253
+
254
+ # add a single contingency that disconnect powerline 2 and 3 at the same time
255
+ security_anlysis.add_single_contingency(env.name_line[2], 3)
256
+
257
+ # add a multiple contingencies the first one disconnect powerline 2 and
258
+ # and the second one disconnect powerline 3
259
+ security_anlysis.add_multiple_contingencies(env.name_line[2], 3)
260
+ """
261
+ if self.__is_closed:
262
+ raise RuntimeError("This is closed, you cannot use it.")
263
+
264
+ for single_cont in args:
265
+ if isinstance(single_cont, Iterable) and not isinstance(single_cont, type(self).STR_TYPES):
266
+ # this is a contingency consisting in cutting multiple powerlines
267
+ self.add_single_contingency(*single_cont)
268
+ else:
269
+ # this is likely an int or a string representing a contingency
270
+ self.add_single_contingency(single_cont)
271
+
272
+ def add_all_n1_contingencies(self):
273
+ """
274
+ This method registers as the contingencies that will be computed all the contingencies that disconnects 1 powerline
275
+
276
+ This is equivalent to:
277
+
278
+ .. code-block:: python
279
+
280
+ for single_cont_id in range(env.n_line):
281
+ self.add_single_contingency(single_cont_id)
282
+ """
283
+ if self.__is_closed:
284
+ raise RuntimeError("This is closed, you cannot use it.")
285
+
286
+ for single_cont_id in range(type(self._ls_backend).n_line):
287
+ self.add_single_contingency(single_cont_id)
288
+
289
+ def get_flows(self, *args):
290
+ """
291
+ Retrieve the flows after each contingencies has been simulated.
292
+
293
+ Each row of the resulting flow matrix will correspond to a contingency simulated in the arguments.
294
+
295
+ You can require only the result on some contingencies with the `args` argument, but in each case, all the results will
296
+ be computed. If you don't specify anything, the results will be returned for all contingencies (which we recommend to do)
297
+
298
+ Examples
299
+ --------
300
+
301
+ .. code-block:: python
302
+
303
+ import grid2op
304
+ from lightsim2grid import SecurityAnalysis
305
+ from lightsim2grid import LightSimBackend
306
+ env_name = ...
307
+ env = grid2op.make(env_name, backend=LightSimBackend())
308
+
309
+ security_analysis = SecurityAnalysis(env)
310
+ security_analysis.add_multiple_contingencies(...) # or security_analysis.add_single_contingency(...)
311
+ res_p, res_a, res_v = security_analysis.get_flows()
312
+
313
+ # in this results, then
314
+ # res_a[row_id] will be the flows, on all powerline corresponding to the `row_id` contingency.
315
+ # you can retrieve it with `security_analysis.contingency_order[row_id]`
316
+ """
317
+ if self.__is_closed:
318
+ raise RuntimeError("This is closed, you cannot use it.")
319
+
320
+ all_defaults = self.computer.my_defaults()
321
+ if len(args) == 0:
322
+ # default: i consider all contingencies
323
+ orders_ = np.zeros(len(all_defaults), dtype=int)
324
+ for id_cpp, cont_ in enumerate(all_defaults):
325
+ tup_ = tuple(cont_)
326
+ orders_[self._contingency_order[tup_]] = id_cpp
327
+ else:
328
+ # a list of interesting contingencies has been provided
329
+ orders_ = np.zeros(len(args), dtype=int)
330
+ all_defaults = [tuple(cont) for cont in all_defaults]
331
+ for id_me, cont_ in enumerate(args):
332
+ cont_li = self._single_cont_to_li_int(cont_)
333
+ tup_ = tuple(cont_li)
334
+ if tup_ not in self._contingency_order:
335
+ raise RuntimeError(f"Contingency {cont_} is not simulated by this class. Have you called "
336
+ f"`add_single_contingency` or `add_multiple_contingencies` ?")
337
+ id_cpp = all_defaults.index(tup_)
338
+ orders_[id_me] = id_cpp
339
+
340
+ if not self.__computed:
341
+ self.compute_V()
342
+ self.compute_A()
343
+ self.compute_P()
344
+
345
+ return self._mws[orders_], self._ampss[orders_], self._vs[orders_]
346
+
347
+ def compute_V(self):
348
+ """
349
+ This function allows to retrieve the complex voltage at each bus of the grid for each contingency.
350
+
351
+ .. warning:: Order of the results
352
+
353
+ The order in which the results are returned is NOT necessarily the order in which the contingencies have
354
+ been entered. Please use `get_flows()` method for easier reading back of the results
355
+
356
+ """
357
+ if self.__is_closed:
358
+ raise RuntimeError("This is closed, you cannot use it.")
359
+ if self._ls_backend._debug_Vdc is not None:
360
+ v_init = self._ls_backend._debug_Vdc.copy()
361
+ else:
362
+ v_init = self._ls_backend.V.copy()
363
+ self.computer.compute(v_init,
364
+ self._ls_backend.max_it,
365
+ self._ls_backend.tol)
366
+ self._vs = self.computer.get_voltages().copy()
367
+ self.__computed = True
368
+ return self._vs
369
+
370
+ def compute_A(self):
371
+ """
372
+ This function returns the current flows (in Amps, A) at the origin / high voltage side
373
+
374
+ .. warning:: Order of the results
375
+
376
+ The order in which the results are returned is NOT necessarily the order in which the contingencies have
377
+ been entered. Please use `get_flows()` method for easier reading back of the results !
378
+
379
+ """
380
+ if self.__is_closed:
381
+ raise RuntimeError("This is closed, you cannot use it.")
382
+
383
+ if not self.__computed:
384
+ raise RuntimeError("This function can only be used if compute_V has been sucessfully called")
385
+ self.computer.compute_flows()
386
+ self._ampss = 1e3 * self.computer.get_flows()
387
+ return self._ampss
388
+
389
+ def compute_P(self):
390
+ """
391
+ This function returns the active power flows (in MW) at the origin / high voltage side
392
+
393
+ .. warning:: Order of the results
394
+
395
+ The order in which the results are returned is NOT necessarily the order in which the contingencies have
396
+ been entered. Please use `get_flows()` method for easier reading back of the results !
397
+
398
+ """
399
+ if self.__is_closed:
400
+ raise RuntimeError("This is closed, you cannot use it.")
401
+
402
+ if not self.__computed:
403
+ raise RuntimeError("This function can only be used if compute_V has been sucessfully called")
404
+ self.computer.compute_power_flows()
405
+ self._mws = self.computer.get_power_flows().copy()
406
+ return self._mws
407
+
408
+ def close(self):
409
+ """permanently close the object"""
410
+ if self.__is_closed:
411
+ return
412
+ self.clear()
413
+ self.computer.close()
414
+ self._ls_backend.close()
415
+ self.__is_closed = True
416
+
417
+ def change_solver(self, solver_type):
418
+ if self.__is_closed:
419
+ raise RuntimeError("This is closed, you cannot use it.")
420
+ self.computer.change_solver(solver_type)
421
+ self.clear()
422
+
423
+
424
+ if GRID2OP_INSTALLED:
425
+ ContingencyAnalysis = __ContingencyAnalysis
@@ -0,0 +1,38 @@
1
+ # Copyright (c) 2020, RTE (https://www.rte-france.com)
2
+ # See AUTHORS.txt
3
+ # This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0.
4
+ # If a copy of the Mozilla Public License, version 2.0 was not distributed with this file,
5
+ # you can obtain one at http://mozilla.org/MPL/2.0/.
6
+ # SPDX-License-Identifier: MPL-2.0
7
+ # This file is part of LightSim2grid, LightSim2grid implements a c++ backend targeting the Grid2Op platform.
8
+
9
+ __all__ = ["GeneratorContainer",
10
+ "GenInfo",
11
+ "SGenContainer",
12
+ "SGenInfo",
13
+ "LoadContainer",
14
+ "LoadInfo",
15
+ "ShuntContainer",
16
+ "ShuntInfo",
17
+ "TrafoContainer",
18
+ "TrafoInfo",
19
+ "LineContainer",
20
+ "LineInfo",
21
+ "DCLineContainer",
22
+ "DCLineInfo",
23
+ ]
24
+
25
+ from lightsim2grid_cpp import GeneratorContainer
26
+ from lightsim2grid_cpp import GenInfo
27
+ from lightsim2grid_cpp import SGenContainer
28
+ from lightsim2grid_cpp import SGenInfo
29
+ from lightsim2grid_cpp import LoadContainer
30
+ from lightsim2grid_cpp import LoadInfo
31
+ from lightsim2grid_cpp import ShuntContainer
32
+ from lightsim2grid_cpp import ShuntInfo
33
+ from lightsim2grid_cpp import TrafoContainer
34
+ from lightsim2grid_cpp import TrafoInfo
35
+ from lightsim2grid_cpp import LineContainer
36
+ from lightsim2grid_cpp import LineInfo
37
+ from lightsim2grid_cpp import DCLineContainer
38
+ from lightsim2grid_cpp import DCLineInfo