Skip to content

Commit

Permalink
fix CI bug and add first basic test for n1reward
Browse files Browse the repository at this point in the history
  • Loading branch information
BDonnot committed Mar 25, 2024
1 parent 98b748a commit 79900d3
Show file tree
Hide file tree
Showing 16 changed files with 366 additions and 81 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ Change Log
- [FIXED] some bugs preventing backward compatibility
- [FIXED] an issue in the computation of gen_q when intialized with pypowsybl
(some overflow cpp side leading to infinite number in gen_q)
- [FIXED] a bug in the "containers" cpp side (wrong bus was assigned)
when elements was disconnected, which lead to wrong computations for
time series or contingency analysis.
- [FIXED] another bug in ContingencyAnalysis (cpp side) leading to wrong computation
when a powerline was disconnected
- [ADDED] some information of compilation directly in the cpp module
- [ADDED] some information of compilation available in the python `compilation_options`
module python side
Expand All @@ -37,6 +42,8 @@ Change Log
- [IMPROVED] speed, by accelerating the reading back of the data (now read only once and then
pointers are re used)
- [IMPROVED] c++ side avoid allocating memory (which allow to gain speed python side too)
- [IMPROVED] type hinting in `LightSimBackend` for all 'public' methods (most
notably the one used by grid2op)

[0.8.0] 2024-03-18
--------------------
Expand Down
37 changes: 37 additions & 0 deletions lightsim2grid/compilation_options/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright (c) 2024, RTE (https://www.rte-france.com)
# See AUTHORS.txt
# This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0.
# If a copy of the Mozilla Public License, version 2.0 was not distributed with this file,
# you can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
# This file is part of LightSim2grid, LightSim2grid implements a c++ backend targeting the Grid2Op platform.

__all__ = ["klu_solver_available",
"nicslu_solver_available",
"cktso_solver_available",
"compiled_march_native",
"compiled_o3_optim",
"version",
"lightsim2grid_lib"]

from lightsim2grid_cpp import klu_solver_available
from lightsim2grid_cpp import nicslu_solver_available
from lightsim2grid_cpp import cktso_solver_available
from lightsim2grid_cpp import compiled_march_native
from lightsim2grid_cpp import compiled_o3_optim
from lightsim2grid_cpp import version
from lightsim2grid_cpp import __file__ as lightsim2grid_lib

try:
from lightsim2grid_cpp import nicslu_lib
__all__.append("nicslu_lib")
except ImportError :
# NICSLU linear solver is not available
pass

try:
from lightsim2grid_cpp import cktso_lib
__all__.append("cktso_lib")
except ImportError :
# CKTSO linear solver is not available
pass
11 changes: 8 additions & 3 deletions lightsim2grid/contingencyAnalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,15 @@ def all_contingencies(self, val):
raise RuntimeError("Impossible to add new topologies like this. Please use `add_single_contingency` "
"or `add_multiple_contingencies`.")

def update_grid(self, backend_act):
# TODO implement that !
def __update_grid(self, backend_act):
self.clear(with_contlist=False)
self._ls_backend.apply_action(backend_act)
self.computer = ContingencyAnalysisCPP(self._ls_backend._grid)
# run the powerflow
self._ls_backend.runpf()
# update the computer
# self.computer = ContingencyAnalysisCPP(self._ls_backend._grid)
# self.computer.update_grid(...) # not implemented

def clear(self, with_contlist=True):
"""
Expand Down Expand Up @@ -320,7 +325,7 @@ def compute_V(self):
been entered. Please use `get_flows()` method for easier reading back of the results
"""
v_init = self._ls_backend.V
v_init = 1. * self._ls_backend.V
self.computer.compute(v_init,
self._ls_backend.max_it,
self._ls_backend.tol)
Expand Down
7 changes: 5 additions & 2 deletions lightsim2grid/gridmodel/initGridModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
import numpy as np
from numbers import Number
import warnings

import pandapower
import lightsim2grid
from lightsim2grid_cpp import GridModel, PandaPowerConverter
from lightsim2grid.gridmodel._aux_add_sgen import _aux_add_sgen
from lightsim2grid.gridmodel._aux_add_load import _aux_add_load
Expand All @@ -28,7 +31,7 @@
from lightsim2grid.gridmodel._aux_add_dc_line import _aux_add_dc_line


def init(pp_net):
def init(pp_net: "pandapower.auxiliary.pandapowerNet") -> GridModel:
"""
Convert a pandapower network as input into a GridModel.
Expand All @@ -53,7 +56,7 @@ def init(pp_net):
Parameters
----------
pp_net: :class:`pandapower.grid`
pp_net: :class:`pandapower.auxiliary.pandapowerNet`
The initial pandapower network you want to convert
Returns
Expand Down
58 changes: 35 additions & 23 deletions lightsim2grid/lightSimBackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@
# SPDX-License-Identifier: MPL-2.0
# This file is part of LightSim2grid, LightSim2grid implements a c++ backend targeting the Grid2Op platform.

import os
import copy
from typing import Optional, Union
from typing import Tuple, Optional, Any, Dict, Union
try:
from typing import Self
except ImportError:
# python version is probably bellow 3.11
from typing_extensions import Self

import warnings
import numpy as np
import pandas as pd
import time

import grid2op
from grid2op.Action import CompleteAction
from grid2op.Backend import Backend
from grid2op.Exceptions import BackendError
Expand Down Expand Up @@ -296,7 +304,7 @@ def turnedoff_pv(self):
self._turned_off_pv = True
self._grid.turnedoff_pv()

def get_theta(self):
def get_theta(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
"""
Returns
Expand Down Expand Up @@ -344,7 +352,7 @@ def get_solver_types(self) -> Union[SolverType, SolverType]:
"""
return self._grid.get_solver_type(), self._grid.get_dc_solver_type()

def set_solver_type(self, solver_type: SolverType):
def set_solver_type(self, solver_type: SolverType) -> None:
"""
Change the type of solver you want to use.
Expand Down Expand Up @@ -386,7 +394,7 @@ def _check_suitable_solver_type(self, solver_type, check_in_avail_solver=True):
raise BackendError(f"The solver type provided \"{solver_type}\" is not available on your system. Available"
f"solvers are {self.available_solvers}")

def set_solver_max_iter(self, max_iter):
def set_solver_max_iter(self, max_iter: int) -> None:
"""
Set the maximum number of iteration the solver is allowed to perform.
Expand Down Expand Up @@ -419,7 +427,7 @@ def set_solver_max_iter(self, max_iter):
raise BackendError("max_iter should be a strictly positive integer (integer >= 1)")
self.max_it = max_iter

def set_tol(self, new_tol):
def set_tol(self, new_tol: float) -> None:
"""
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".
Expand Down Expand Up @@ -469,7 +477,9 @@ def _assign_right_solver(self):
else:
self._grid.change_solver(SolverType.SparseLU)

def load_grid(self, path=None, filename=None):
def load_grid(self,
path : Union[os.PathLike, str],
filename : Optional[Union[os.PathLike, str]]=None) -> None:
if hasattr(type(self), "can_handle_more_than_2_busbar"):
# grid2op version >= 1.10.0 then we use this
self.can_handle_more_than_2_busbar()
Expand Down Expand Up @@ -832,7 +842,7 @@ def _aux_finish_setup_after_reading(self):

self.topo_vect = np.ones(cls.dim_topo, dtype=dt_int).reshape(-1)

if type(self).shunts_data_available:
if cls.shunts_data_available:
self.shunt_topo_vect = np.ones(cls.n_shunt, dtype=dt_int)
# shunts
self.sh_p = np.full(cls.n_shunt, dtype=dt_float, fill_value=np.NaN).reshape(-1)
Expand Down Expand Up @@ -877,7 +887,7 @@ def _aux_finish_setup_after_reading(self):
self.__init_topo_vect[:] = self.topo_vect
self.sh_bus[:] = 1

def assert_grid_correct_after_powerflow(self):
def assert_grid_correct_after_powerflow(self) -> None:
"""
This method is called by the environment. It ensure that the backend remains consistent even after a powerflow
has be run with :func:`Backend.runpf` method.
Expand Down Expand Up @@ -945,11 +955,11 @@ def _count_object_per_bus(self):
arr_ = self.shunt_to_subid[is_connected] + self.__nb_bus_before * (arr_[is_connected] - 1)
self.nb_obj_per_bus[arr_] += 1

def close(self):
def close(self) -> None:
self.init_pp_backend.close()
self._grid = None

def apply_action(self, backendAction):
def apply_action(self, backendAction: Union["grid2op.Action._backendAction._BackendAction", None]) -> None:
"""
Specific implementation of the method to apply an action modifying a powergrid in the pandapower format.
"""
Expand Down Expand Up @@ -1031,7 +1041,7 @@ def _fetch_grid_data(self):
self._shunt_res = self._grid.get_shunts_res_full()
self._timer_fetch_data_cpp += time.perf_counter() - beg_test

def runpf(self, is_dc=False):
def runpf(self, is_dc : bool=False) -> Tuple[bool, Union[Exception, None]]:
my_exc_ = None
res = False
try:
Expand Down Expand Up @@ -1217,7 +1227,7 @@ def __deepcopy__(self, memo):
memo[id(self)] = result
return result

def copy(self):
def copy(self) -> Self:
# i can perform a regular copy, everything has been initialized
mygrid = self._grid
__me_at_init = self.__me_at_init
Expand Down Expand Up @@ -1341,36 +1351,36 @@ def copy(self):
self.__me_at_init = __me_at_init
return res

def get_line_status(self):
def get_line_status(self) -> np.ndarray:
l_s = self._grid.get_lines_status()
t_s = self._grid.get_trafo_status()
return np.concatenate((l_s, t_s)).astype(dt_bool)

def get_line_flow(self):
def get_line_flow(self) -> np.ndarray:
return self.a_or

def get_topo_vect(self):
def get_topo_vect(self) -> np.ndarray:
return 1 * self.topo_vect

def generators_info(self):
def generators_info(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
return self.cst_1 * self.prod_p, self.cst_1 * self.prod_q, self.cst_1 * self.prod_v

def loads_info(self):
def loads_info(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
return self.cst_1 * self.load_p, self.cst_1 * self.load_q, self.cst_1 * self.load_v

def lines_or_info(self):
def lines_or_info(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
return self.cst_1 * self.p_or, self.cst_1 * self.q_or, self.cst_1 * self.v_or, self.cst_1 * self.a_or

def lines_ex_info(self):
def lines_ex_info(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
return self.cst_1 * self.p_ex, self.cst_1 * self.q_ex, self.cst_1 * self.v_ex, self.cst_1 * self.a_ex

def storages_info(self):
def storages_info(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
if not self.__has_storage:
raise RuntimeError("Storage units are not supported with your grid2op version. Please upgrade to "
"grid2op >1.5")
return self.cst_1 * self.storage_p, self.cst_1 * self.storage_q, self.cst_1 * self.storage_v

def shunt_info(self):
def shunt_info(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
return self.cst_1 * self.sh_p, self.cst_1 * self.sh_q, self.cst_1 * self.sh_v, self.sh_bus

def _compute_shunt_bus_with_compat(self, shunt_bus):
Expand Down Expand Up @@ -1404,10 +1414,12 @@ def _disconnect_line(self, id_):
else:
self._grid.deactivate_trafo(id_ - self.__nb_powerline)

def get_current_solver_type(self):
def get_current_solver_type(self) -> SolverType:
return self.__current_solver_type

def reset(self, grid_path, grid_filename=None):
def reset(self,
path : Union[os.PathLike, str],
grid_filename : Optional[Union[os.PathLike, str]]=None) -> None:
self._fill_nans()
self._grid = self.__me_at_init.copy()
self._grid.unset_changes()
Expand Down
2 changes: 1 addition & 1 deletion lightsim2grid/rewards/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# you can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
# This file is part of LightSim2grid, LightSim2grid implements a c++ backend targeting the Grid2Op platform.
_

__all__ = ["N1ContingencyReward"]

from lightsim2grid.rewards.n1ContingencyReward import N1ContingencyReward
Loading

0 comments on commit 79900d3

Please sign in to comment.