Source code for lightsim2grid.injectionSweep

# Copyright (c) 2020, 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__ = ["InjectionSweepCPP"]

from lightsim2grid.timeSerie import TimeSerie, GRID2OP_INSTALLED
from .lightsim2grid_cpp import InjectionSweepCPP

if GRID2OP_INSTALLED:
    __all__.append("InjectionSweep")


[docs] class InjectionSweep(TimeSerie): """ Same computation as :class:`lightsim2grid.timeSerie.TimeSerie` -- a fixed grid topology, one powerflow per set of injections -- but every powerflow starts from the same voltage instead of from the result of the previous one. That makes the steps independent of one another: the result of a step does not depend on the steps computed before it, nor on the order in which they were given. Use this class when the "steps" are unrelated scenarios rather than consecutive instants of a time series. Two practical consequences: - the computation can be spread over several OS threads, see ``nb_thread`` below (:class:`lightsim2grid.timeSerie.TimeSerie` cannot: splitting a chained computation would make its results depend on how it was split); - a step that is far from its neighbours does not inherit a bad starting point from them -- but a step that IS close to its neighbours no longer benefits from their solution, so a genuine time series usually converges in fewer iterations with :class:`lightsim2grid.timeSerie.TimeSerie`. Examples --------- It is used exactly like :class:`lightsim2grid.timeSerie.TimeSerie`: .. code-block:: python import grid2op from lightsim2grid import InjectionSweep from lightsim2grid import LightSimBackend env_name = ... env = grid2op.make(env_name, backend=LightSimBackend()) sweep = InjectionSweep(env) sweep.nb_thread = 4 # optional, the results do not depend on it res_p, res_a, res_v = sweep.get_flows(scenario_id=..., seed=...) """ _CPP_CLASS = InjectionSweepCPP @property def nb_thread(self): """Number of OS threads used to compute the steps (default: ``1``). The steps are split into contiguous ranges, each solved by its own thread with its own solver, writing to disjoint rows of the result matrix: the results do **not** depend on the number of threads. Values ``< 1`` are clamped to ``1``. Must be set before the computation actually runs (eg before ``compute_V`` is called); it has no effect on a batch that has already been computed. """ return self.computer.nb_thread @nb_thread.setter def nb_thread(self, val: int): if int(val) != val: raise ValueError("The `nb_thread` attribute must be an integer.") self.computer.nb_thread = int(val) @property def init_from_n_powerflow(self): """Whether to initialize the complex voltages of **each** step of the batch with the results of a "n" powerflow (a powerflow at the current state of the grid) instead of the vector given to ``compute_V``. Default: ``False``. Unlike :attr:`lightsim2grid.timeSerie.TimeSerie.init_from_n_powerflow`, this applies to every step and not only the first one -- here every step starts from that same voltage. Must be set before the computation actually runs. """ return self.computer.init_from_n_powerflow @init_from_n_powerflow.setter def init_from_n_powerflow(self, val: bool): if bool(val) != val: raise ValueError("The `init_from_n_powerflow` attribute must be a boolean.") self.computer.init_from_n_powerflow = bool(val)