LightSimBackend
This is an implementation of a grid2op Backend that uses lightsim2grid simulator coded in c++.
The integration with grid2op is rather easy. You simply need to provide the key-word argument backend=LightSimBackend() when building your environment using the grid2op.make function and you can use it transparently.
Example
See the section Use with grid2op for more information and more examples.
For standard grid2op environment, you can use it like:
import grid2op
from lightsim2grid.LightSimBackend import LightSimBackend
from grid2op.Agent import RandomAgent
# create an environment
env_name = "rte_case14_realistic" # for example, other environments might be usable
env = grid2op.make(env_name,
backend=LightSimBackend() # this is the only change you have to make!
)
# create an agent
my_agent = RandomAgent(env.action_space)
# proceed as you would any open ai gym loop
nb_episode = 10
for _ in range(nb_episde):
# you perform in this case 10 different episodes
obs = env.reset()
reward = env.reward_range[0]
done = False
while not done:
# here you loop on the time steps: at each step your agent receive an observation
# takes an action
# and the environment computes the next observation that will be used at the next step.
act = agent.act(obs, reward, done)
obs, reward, done, info = env.step(act)
# the `LightSimBackend` will be used to carry out the powerflow computation instead
# of the default grid2op `PandaPowerBackend`
Detailed documentation
Classes:
|
This is a specialization of the grid2op Backend class to use the lightsim2grid solver, coded in c++, aiming at speeding up the computations. |
- class lightsim2grid.lightSimBackend.LightSimBackend(detailed_infos_for_cascading_failures=False)[source]
This is a specialization of the grid2op Backend class to use the lightsim2grid solver, coded in c++, aiming at speeding up the computations.
Methods:
apply_action
(backendAction)Specific implementation of the method to apply an action modifying a powergrid in the pandapower format.
This method is called by the environment.
close
()INTERNAL
copy
()INTERNAL
INTERNAL
INTERNAL
INTERNAL
- returns
line_or_theta (
numpy.ndarray
) -- For each orgin side of powerline, gives the voltage angle
INTERNAL
INTERNAL
INTERNAL
load_grid
([path, filename])INTERNAL
INTERNAL
reset
(grid_path[, grid_filename])INTERNAL
runpf
([is_dc])INTERNAL
set_solver_max_iter
(max_iter)Set the maximum number of iteration the solver is allowed to perform.
set_solver_type
(solver_type)Change the type of solver you want to use.
set_tol
(new_tol)Set the tolerance of the powerflow.
INTERNAL
INTERNAL
- apply_action(backendAction)[source]
Specific implementation of the method to apply an action modifying a powergrid in the pandapower format.
- assert_grid_correct_after_powerflow()[source]
This method is called by the environment. It ensure that the backend remains consistent even after a powerflow has be run with
Backend.runpf()
method.- Returns
None
- Raise
grid2op.Exceptions.EnvError
and possibly all of its derived class.
- close()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
This is called by env.close() do not attempt to use it otherwise.
This function is called when the environment is over. After calling this function, the backend might not behave properly, and in any case should not be used before another call to
Backend.load_grid()
is performed
- copy()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
Performs a deep copy of the backend.
In the default implementation we explicitly called the deepcopy operator on self._grid to make the error message more explicit in case there is a problem with this part.
The implementation is equivalent to:
return copy.deepcopy(self)
- Returns
An instance of Backend equal to
self
, but deep copied.- Return type
Backend
- generators_info()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
Prefer using
grid2op.Observation.BaseObservation.prod_p
,grid2op.Observation.BaseObservation.prod_q
andgrid2op.Observation.BaseObservation.prod_v
instead.This method is used to retrieve information about the generators (active, reactive production and voltage magnitude of the bus to which it is connected).
- Returns
prod_p
numpy.ndarray
– The active power production for each generator (in MW)prod_q
numpy.ndarray
– The reactive power production for each generator (in MVAr)prod_v
numpy.ndarray
– The voltage magnitude of the bus to which each generators is connected (in kV)
- get_line_flow()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
Prefer using
grid2op.Observation.BaseObservation.a_or
orgrid2op.Observation.BaseObservation.a_ex
for exampleReturn the current flow in each lines of the powergrid. Only one value per powerline is returned.
If the AC mod is used, this shall return the current flow on the end of the powerline where there is a protection. For example, if there is a protection on “origin end” of powerline “l2” then this method shall return the current flow of at the “origin end” of powerline l2.
Note that in general, there is no loss of generality in supposing all protections are set on the “origin end” of the powerline. So this method will return all origin line flows. It is also possible, for a specific application, to return the maximum current flow between both ends of a power _grid for more complex scenario.
For assumption about the order of the powerline flows return in this vector, see the help of the
Backend.get_line_status()
method.- Returns
an array with the line flows of each powerline
- Return type
np.array, dtype:float
- get_line_status()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
Prefer using
grid2op.Observation.BaseObservation.line_status
insteadReturn the status of each lines (connected : True / disconnected: False )
It is assume that the order of the powerline is fixed: if the status of powerline “l1” is put at the 42nd element of the return vector, then it should always be set at the 42nd element.
It is also assumed that all the other methods of the backend that allows to retrieve informations on the powerlines also respect the same convention, and consistent with one another. For example, if powerline “l1” is the 42nd second of the vector returned by
Backend.get_line_status()
then information about it’s flow will be at position 42 of the vector returned byBackend.get_line_flow()
for example.- Returns
an array with the line status of each powerline
- Return type
np.array, dtype:bool
- get_theta()[source]
- Returns
line_or_theta (
numpy.ndarray
) – For each orgin side of powerline, gives the voltage angleline_ex_theta (
numpy.ndarray
) – For each extremity side of powerline, gives the voltage angleload_theta (
numpy.ndarray
) – Gives the voltage angle to the bus at which each load is connectedgen_theta (
numpy.ndarray
) – Gives the voltage angle to the bus at which each generator is connectedstorage_theta (
numpy.ndarray
) – Gives the voltage angle to the bus at which each storage unit is connected
- get_topo_vect()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
Prefer using
grid2op.Observation.BaseObservation.topo_vect
Get the topology vector from the
Backend._grid
. The topology vector defines, for each object, on which bus it is connected. It returns -1 if the object is not connected.It is a vector with as much elements (productions, loads and lines extremity) as there are in the powergrid.
For each elements, it gives on which bus it is connected in its substation.
For example, if the first element of this vector is the load of id 1, then if res[0] = 2 it means that the load of id 1 is connected to the second bus of its substation.
You can check which object of the powerlines is represented by each component of this vector by looking at the *_pos_topo_vect (eg.
grid2op.Space.GridObjects.load_pos_topo_vect
) vectors. For each elements it gives its position in this vector.As any function of the backend, it is not advised to use it directly. You can get this information in the
grid2op.Observation.Observation.topo_vect
instead.- Returns
res – An array saying to which bus the object is connected.
- Return type
numpy.ndarray
dtype:int
- lines_ex_info()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
Prefer using
grid2op.Observation.BaseObservation.p_ex
,grid2op.Observation.BaseObservation.q_ex
,grid2op.Observation.BaseObservation.a_ex
and,grid2op.Observation.BaseObservation.v_ex
insteadIt returns the information extracted from the _grid at the extremity end of each powerline.
For assumption about the order of the powerline flows return in this vector, see the help of the
Backend.get_line_status()
method.- Returns
p_ex
numpy.ndarray
– the extremity active power flowing on the lines (in MW)q_ex
numpy.ndarray
– the extremity reactive power flowing on the lines (in MVAr)v_ex
numpy.ndarray
– the voltage magnitude at the extremity of each powerlines (in kV)a_ex
numpy.ndarray
– the current flow at the extremity of each powerlines (in A)
- lines_or_info()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
Prefer using
grid2op.Observation.BaseObservation.p_or
,grid2op.Observation.BaseObservation.q_or
,grid2op.Observation.BaseObservation.a_or
and,grid2op.Observation.BaseObservation.v_or
insteadIt returns the information extracted from the _grid at the origin end of each powerline.
For assumption about the order of the powerline flows return in this vector, see the help of the
Backend.get_line_status()
method.- Returns
p_or
numpy.ndarray
– the origin active power flowing on the lines (in MW)q_or
numpy.ndarray
– the origin reactive power flowing on the lines (in MVAr)v_or
numpy.ndarray
– the voltage magnitude at the origin of each powerlines (in kV)a_or
numpy.ndarray
– the current flow at the origin of each powerlines (in A)
- load_grid(path=None, filename=None)[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
This is called once at the loading of the powergrid.
Load the powergrid. It should first define self._grid.
And then fill all the helpers used by the backend eg. all the attributes of
Space.GridObjects
.After a the call to
Backend.load_grid()
has been performed, the backend should be in such a state where thegrid2op.Space.GridObjects
is properly set up. See the description ofgrid2op.Space.GridObjects
to know which attributes should be set here and which should not.- Parameters
path (
string
) – the path to find the powergridfilename (
string
, optional) – the filename of the powergrid
- Returns
None
- loads_info()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
Prefer using
grid2op.Observation.BaseObservation.load_p
,grid2op.Observation.BaseObservation.load_q
andgrid2op.Observation.BaseObservation.load_v
instead.This method is used to retrieve information about the loads (active, reactive consumption and voltage magnitude of the bus to which it is connected).
- Returns
load_p
numpy.ndarray
– The active power consumption for each load (in MW)load_q
numpy.ndarray
– The reactive power consumption for each load (in MVAr)load_v
numpy.ndarray
– The voltage magnitude of the bus to which each load is connected (in kV)
- reset(grid_path, grid_filename=None)[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
This is done in the env.reset() method and should be performed otherwise.
Reload the power grid. For backwards compatibility this method calls Backend.load_grid. But it is encouraged to overload it in the subclasses.
- runpf(is_dc=False)[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
This is called by
Backend.next_grid_state()
(that computes some kind of cascading failures).This is one of the core function if you want to code a backend. It will carry out a powerflow.
Run a power flow on the underlying _grid. Powerflow can be AC (is_dc = False) or DC (is_dc = True)
- Parameters
is_dc (
bool
) – is the powerflow run in DC or in AC- Returns
True
if it has converged, or false otherwise. In case of non convergence, no flows can be inspected on the _grid.- Return type
bool
- Returns
an exception in case of divergence (or none if no particular info are available)
- Return type
Exception
- set_solver_max_iter(max_iter)[source]
Set the maximum number of iteration the solver is allowed to perform.
We do not recommend to modify the default value (10), unless you are using the GaussSeidel powerflow. This powerflow being slower, we do not recommend to use it.
Recommendation:
for SolverType.SparseLU: 10
for SolverType.GaussSeidel: 10000
for SolverType.DC: this has no effect
for SolverType.SparseKLU: 10
- Parameters
max_iter (
int
) – Maximum number of iteration the powerflow can run. It should be number >= 1
Notes
This has to be set for every backend that you want to use. For example, you have to set it in the backend of the _obs_env of the observation and if you are using “grid2op.MultMixEnv` you have to set it in all mixes!
- set_solver_type(solver_type)[source]
Change the type of solver you want to use.
Note that a powergrid should have been loaded for this function to work.
This function does not modify
LightSimBackend.max_iter
norLightSimBackend.tol
. You might want to modify these values depending on the solver you are using.Notes
By default, the fastest AC solver is used for your platform. This means that if KLU is available, then it is used otherwise it’s SparseLU.
This has to be set for every backend that you want to use. For example, you have to set it in the backend of the _obs_env of the observation and if you are using “grid2op.MultMixEnv` you have to set it in all mixes!
- Parameters
solver_type (lightsim2grid.SolverType) – The new type of solver you want to use. See backend.available_solvers for a list of available solver on your machine.
- set_tol(new_tol)[source]
Set the tolerance of the powerflow. This means that the powerflow will stop when the Kirchhoff’s Circuit Laws are met up to a tolerance of “new_tol”.
Decrease the tolerance might speed up the computation of the powerflow but will decrease the accuracy. We do not recommend to modify the default value of 1e-8.
- Parameters
new_tol (
float
) – The new tolerance to use (should be a float > 0)
Notes
This has to be set for every backend that you want to use. For example, you have to set it in the backend of the _obs_env of the observation and if you are using “grid2op.MultMixEnv` you have to set it in all mixes!
- shunt_info()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
This method is optional. If implemented, it should return the proper information about the shunt in the powergrid.
If not implemented it returns empty list.
Note that if there are shunt on the powergrid, it is recommended that this method should be implemented before calling
Backend.check_kirchoff()
.If this method is implemented AND
Backend.check_kirchoff()
is called, the methodBackend.sub_from_bus_id()
should also be implemented preferably.- Returns
shunt_p (
numpy.ndarray
) – For each shunt, the active power it withdraw at the bus to which it is connected.shunt_q (
numpy.ndarray
) – For each shunt, the reactive power it withdraw at the bus to which it is connected.shunt_v (
numpy.ndarray
) – For each shunt, the voltage magnitude of the bus to which it is connected.shunt_bus (
numpy.ndarray
) – For each shunt, the bus id to which it is connected.
- storages_info()[source]
INTERNAL
Warning
/!\ Internal, do not use unless you know what you are doing /!\
Prefer using
grid2op.Observation.BaseObservation.storage_power
instead.This method is used to retrieve information about the storage units (active, reactive consumption and voltage magnitude of the bus to which it is connected).
- Returns
storage_p
numpy.ndarray
– The active power consumption for each load (in MW)storage_q
numpy.ndarray
– The reactive power consumption for each load (in MVAr)storage_v
numpy.ndarray
– The voltage magnitude of the bus to which each load is connected (in kV)