From f8e460bd837a68f21bb04196e0e1069b3d002a0a Mon Sep 17 00:00:00 2001 From: Yoann Janvier Date: Thu, 2 Nov 2023 15:28:22 +0100 Subject: [PATCH] First version of powsybl backend (#4) Signed-off-by: Yoann Janvier Co-authored-by: rtschupp Co-authored-by: Vincent Renault --- Authors.txt | 4 + ChronicsCreatorAuthors.txt | 4 + Notebook/CleanWorkflow1stAssessment.ipynb | 4377 +++++++++++++++++ Notebook/Conversion issues.ipynb | 554 +++ .../Tests move connectable and bugs.ipynb | 3168 ++++++++++++ README.md | 122 +- chronics_chreator.py | 330 ++ pyproject.toml | 21 + src/Backend/__init__.py | 9 + src/Backend/network.py | 79 + src/Backend/powsybl_backend.py | 1464 ++++++ src/ScriptForSimpleUseCase.py | 73 + src/__init__.py | 12 + .../chronics/0000/load_p.csv | 577 +++ .../chronics/0000/load_p.csv.bz2 | Bin 0 -> 4954 bytes .../chronics/0000/load_p_forecasted.csv | 577 +++ .../chronics/0000/load_p_forecasted.csv.bz2 | Bin 0 -> 4045 bytes .../chronics/0000/load_q.csv.bz2 | Bin 0 -> 4316 bytes .../chronics/0000/load_q_forecasted.csv.bz2 | Bin 0 -> 3408 bytes .../chronics/0000/prod_p.csv | 577 +++ .../chronics/0000/prod_p.csv.bz2 | Bin 0 -> 3546 bytes .../chronics/0000/prod_p_forecasted.csv.bz2 | Bin 0 -> 3173 bytes .../chronics/0000/prod_v.csv | 577 +++ .../chronics/0000/prod_v.csv.bz2 | Bin 0 -> 107 bytes .../chronics/0000/prod_v_forecasted.csv | 577 +++ .../chronics/0000/prod_v_forecasted.csv.bz2 | Bin 0 -> 107 bytes .../chronics/0000/start_datetime.info | 1 + .../chronics/0000/time_interval.info | 1 + .../chronics/0001/load_p.csv | 577 +++ .../chronics/0001/load_p.csv.bz2 | Bin 0 -> 5215 bytes .../chronics/0001/load_p_forecasted.csv | 577 +++ .../chronics/0001/load_p_forecasted.csv.bz2 | Bin 0 -> 4420 bytes .../chronics/0001/load_q.csv.bz2 | Bin 0 -> 4523 bytes .../chronics/0001/load_q_forecasted.csv.bz2 | Bin 0 -> 3645 bytes .../chronics/0001/prod_p.csv.bz2 | Bin 0 -> 3596 bytes .../chronics/0001/prod_p_forecasted.csv.bz2 | Bin 0 -> 3272 bytes .../chronics/0001/prod_v.csv.bz2 | Bin 0 -> 107 bytes .../chronics/0001/prod_v_forecasted.csv.bz2 | Bin 0 -> 107 bytes .../chronics/0001/start_datetime.info | 1 + .../chronics/0001/time_interval.info | 1 + .../chronics/0002/load_p.csv.bz2 | Bin 0 -> 5411 bytes .../chronics/0002/load_p_forecasted.csv.bz2 | Bin 0 -> 4643 bytes .../chronics/0002/load_q.csv.bz2 | Bin 0 -> 4749 bytes .../chronics/0002/load_q_forecasted.csv.bz2 | Bin 0 -> 3870 bytes .../chronics/0002/prod_p.csv.bz2 | Bin 0 -> 3739 bytes .../chronics/0002/prod_p_forecasted.csv.bz2 | Bin 0 -> 3515 bytes .../chronics/0002/prod_v.csv.bz2 | Bin 0 -> 107 bytes .../chronics/0002/prod_v_forecasted.csv.bz2 | Bin 0 -> 107 bytes .../chronics/0002/start_datetime.info | 1 + .../chronics/0002/time_interval.info | 1 + .../l2rpn_case14_sandbox_Pypowsybl/config.py | 40 + .../l2rpn_case14_sandbox_Pypowsybl/grid.json | 1780 +++++++ .../grid_layout.json | 58 + .../prods_charac.csv | 7 + src/setup.py | 0 src/tests/__init__.py | 7 + src/tests/base_backend_test_powsybl.py | 3197 ++++++++++++ src/tests/test_powsybl_backend.py | 82 + 58 files changed, 19432 insertions(+), 1 deletion(-) create mode 100644 Authors.txt create mode 100644 ChronicsCreatorAuthors.txt create mode 100644 Notebook/CleanWorkflow1stAssessment.ipynb create mode 100644 Notebook/Conversion issues.ipynb create mode 100644 Notebook/Tests move connectable and bugs.ipynb create mode 100644 chronics_chreator.py create mode 100644 pyproject.toml create mode 100644 src/Backend/__init__.py create mode 100644 src/Backend/network.py create mode 100644 src/Backend/powsybl_backend.py create mode 100644 src/ScriptForSimpleUseCase.py create mode 100644 src/__init__.py create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_p.csv create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_p.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_p_forecasted.csv create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_p_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_q.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_q_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p.csv create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_v.csv create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_v.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_v_forecasted.csv create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_v_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/start_datetime.info create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/time_interval.info create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_p.csv create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_p.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_p_forecasted.csv create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_p_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_q.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_q_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/prod_p.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/prod_p_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/prod_v.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/prod_v_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/start_datetime.info create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/time_interval.info create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/load_p.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/load_p_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/load_q.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/load_q_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/prod_p.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/prod_p_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/prod_v.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/prod_v_forecasted.csv.bz2 create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/start_datetime.info create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/time_interval.info create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/config.py create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/grid.json create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/grid_layout.json create mode 100644 src/data_test/l2rpn_case14_sandbox_Pypowsybl/prods_charac.csv create mode 100644 src/setup.py create mode 100644 src/tests/__init__.py create mode 100644 src/tests/base_backend_test_powsybl.py create mode 100644 src/tests/test_powsybl_backend.py diff --git a/Authors.txt b/Authors.txt new file mode 100644 index 0000000..efb4765 --- /dev/null +++ b/Authors.txt @@ -0,0 +1,4 @@ +Authors for src code : +Rémi Tschupp +Yoann Janvier +Vincent Renault \ No newline at end of file diff --git a/ChronicsCreatorAuthors.txt b/ChronicsCreatorAuthors.txt new file mode 100644 index 0000000..f14b7d7 --- /dev/null +++ b/ChronicsCreatorAuthors.txt @@ -0,0 +1,4 @@ +ChronicsCreator authors: +Rémi Tschupp +Yoann Janvier +Benjamin Donnot \ No newline at end of file diff --git a/Notebook/CleanWorkflow1stAssessment.ipynb b/Notebook/CleanWorkflow1stAssessment.ipynb new file mode 100644 index 0000000..a604d05 --- /dev/null +++ b/Notebook/CleanWorkflow1stAssessment.ipynb @@ -0,0 +1,4377 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7137b170", + "metadata": {}, + "source": [ + "# Notebook for first assessment" + ] + }, + { + "cell_type": "markdown", + "id": "b8b07e65", + "metadata": {}, + "source": [ + "### Import of libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "fb5651a9", + "metadata": {}, + "outputs": [], + "source": [ + "import pypowsybl.network as pp\n", + "import pypowsybl.loadflow as lf" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "3ebd4552", + "metadata": {}, + "outputs": [], + "source": [ + "import pandapower as pdp\n", + "import pandapower.networks as pn\n", + "from pandapower.plotting.plotly import simple_plotly" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "83c314ef", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\rtschupp\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\test-paKUVtLg-py3.10\\lib\\site-packages\\grid2op\\Backend\\PandaPowerBackend.py:31: UserWarning: Numba cannot be loaded. You will gain possibly massive speed if installing it by \n", + "\tC:\\Users\\rtschupp\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\test-paKUVtLg-py3.10\\Scripts\\python.exe -m pip install numba\n", + "\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "import grid2op" + ] + }, + { + "cell_type": "markdown", + "id": "1c361152", + "metadata": {}, + "source": [ + "## First part : drop IEEE14 realisitic scenario by Grid2op and load it with pypowsybl" + ] + }, + { + "cell_type": "markdown", + "id": "fd3dc633", + "metadata": {}, + "source": [ + "#### Export of Grid2op IEEE14 realistic scenario by Grid2op" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9fce99eb", + "metadata": {}, + "outputs": [], + "source": [ + "env = grid2op.make(\"rte_case14_realistic\")" + ] + }, + { + "cell_type": "markdown", + "id": "c7c7b01e", + "metadata": {}, + "source": [ + "Use of pandapower (which is the default backend of Grid2op) to convert our grid file to a .mat file rather then a .json file. Pypowsybl could only read matpower, xiidm, UCTE, CGMES, PSS/E or IEEE-CDF type of file. So this is the only possible type of file that is making the bridge between pandapower and powsybl backend." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b15d9492", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "gen vm_pu > bus max_vm_pu for gens [2 3]. Setting bus limit for these gens.\n" + ] + } + ], + "source": [ + "_ = pdp.converter.to_mpc(env.backend._grid, \"case14_grid2op_realistic.mat\")" + ] + }, + { + "cell_type": "markdown", + "id": "4368f603", + "metadata": {}, + "source": [ + "#### Load of Grid2op's IEEE14 realistic dropped matpower file with pypowsybl" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "102fda5a", + "metadata": {}, + "outputs": [], + "source": [ + "pypowsybl_network = pp.load(\"case14_grid2op_realistic.mat\",{'matpower.import.ignore-base-voltage' : 'false'}) #change the voltage from per unit to Kv" + ] + }, + { + "cell_type": "markdown", + "id": "5c7b825f", + "metadata": {}, + "source": [ + "#### Visualisation of the network" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "01ec812e", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-1-2\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-1-5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-9-10\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-10-11\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-6-11\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-6-12\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-12-13\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-6-13\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-13-14\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-9-14\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-2-3\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-2-4\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-2-5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-3-4\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-4-5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " TWT-4-7\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " TWT-4-9\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " TWT-5-6\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-7-8\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-9-7\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
VL-1
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
142.1 kV / 0.0°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-10
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
21.1 kV / -9.7°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-11
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
21.5 kV / -9.5°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-12
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
21.6 kV / -9.6°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-13
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
21.4 kV / -9.6°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-14
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
20.7 kV / -10.4°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-2
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
142.1 kV / -1.5°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-3
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
142.1 kV / -4.0°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-4
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
138.7 kV / -5.3°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-5
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
139.4 kV / -4.7°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-6
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
22.0 kV / -9.0°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-7
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
14.9 kV / -8.1°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-8
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
13.2 kV / -8.1°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-9
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
21.1 kV / -9.6°
\n", + "
\n", + "
\n", + "
\n", + "
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pypowsybl_network.get_network_area_diagram()" + ] + }, + { + "cell_type": "markdown", + "id": "1a2eb19c", + "metadata": {}, + "source": [ + "#### Run of a loadflow with pypowsybl" + ] + }, + { + "cell_type": "markdown", + "id": "b4c9b83c", + "metadata": {}, + "source": [ + "AC loadflow" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "ce016f62", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ComponentResult(connected_component_num=0, synchronous_component_num=0, status=CONVERGED, iteration_count=8, slack_bus_id='VL-1_0', slack_bus_active_power_mismatch=7.082909160023066, distributed_active_power=8.627012866844364)]\n" + ] + } + ], + "source": [ + "results_pypow_ac = lf.run_ac(pypowsybl_network,parameters=lf.Parameters(distributed_slack=False))\n", + "print(results_pypow_ac)" + ] + }, + { + "cell_type": "markdown", + "id": "553404f0", + "metadata": {}, + "source": [ + "DC loadflow (optionnal run AC or DC but not both)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e7ca19f2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ComponentResult(connected_component_num=0, synchronous_component_num=0, status=CONVERGED, iteration_count=0, slack_bus_id='VL-1_0', slack_bus_active_power_mismatch=-3.7000045776367148, distributed_active_power=nan)]\n" + ] + } + ], + "source": [ + "results_pypow_dc = lf.run_dc(pypowsybl_network,parameters=lf.Parameters(distributed_slack=False))\n", + "print(results_pypow_dc)" + ] + }, + { + "cell_type": "markdown", + "id": "45e5d5d7", + "metadata": {}, + "source": [ + "## Second Part : Take an action on the network" + ] + }, + { + "cell_type": "markdown", + "id": "58353c06", + "metadata": {}, + "source": [ + "#### An agent takes an action on the network : disconnection of the Line 4-5" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "13d6f247", + "metadata": {}, + "outputs": [], + "source": [ + "pypowsybl_network.update_lines(id='LINE-4-5', connected1=False,connected2=False)" + ] + }, + { + "cell_type": "markdown", + "id": "f5cef086", + "metadata": {}, + "source": [ + "#### Visualisation of the network" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "3cb1fd08", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 40\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -40\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-1-2\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 36\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -36\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-1-5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-9-10\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -4\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 4\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-10-11\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 8\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -8\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-6-11\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 7\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -7\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-6-12\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 2\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -2\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-12-13\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 17\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -17\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-6-13\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 6\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -6\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-13-14\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 9\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -9\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-9-14\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 22\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -22\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-2-3\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 40\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -40\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-2-4\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 33\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -33\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-2-5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 16\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -16\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-3-4\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -32\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 32\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-4-5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 28\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -28\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " TWT-4-7\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 15\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -15\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " TWT-4-9\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 31\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -31\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " TWT-5-6\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -0\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 0\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-7-8\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -28\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 28\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-9-7\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
VL-1
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / 0.0°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-10
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -10.2°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-11
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -9.8°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-12
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -9.9°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-13
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -10.1°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-14
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -11.4°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-2
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -1.4°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-3
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -3.8°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-4
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -5.4°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-5
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -4.7°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-6
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -8.9°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-7
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -8.7°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-8
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -8.7°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-9
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -10.0°
\n", + "
\n", + "
\n", + "
\n", + "
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pypowsybl_network.get_network_area_diagram()" + ] + }, + { + "cell_type": "markdown", + "id": "9d0440c6", + "metadata": {}, + "source": [ + "#### Run of a loadflow" + ] + }, + { + "cell_type": "markdown", + "id": "891181a3", + "metadata": {}, + "source": [ + "AC loadflow" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "161479eb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ComponentResult(connected_component_num=0, synchronous_component_num=0, status=CONVERGED, iteration_count=9, slack_bus_id='VL-1_0', slack_bus_active_power_mismatch=9.048937323852545, distributed_active_power=7.7717968118416465)]\n" + ] + } + ], + "source": [ + "results_pypow_after_disconnection_ac = lf.run_ac(pypowsybl_network,parameters=lf.Parameters(distributed_slack=False))\n", + "print(results_pypow_after_disconnection_ac)" + ] + }, + { + "cell_type": "markdown", + "id": "0209ee25", + "metadata": {}, + "source": [ + "DC loadflow (optionnal run AC or DC but not both)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "7c6b614b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ComponentResult(connected_component_num=0, synchronous_component_num=0, status=CONVERGED, iteration_count=0, slack_bus_id='VL-1_0', slack_bus_active_power_mismatch=-3.7000045776367148, distributed_active_power=nan)]\n" + ] + } + ], + "source": [ + "results_pypow_after_disconnection_dc = lf.run_dc(pypowsybl_network,parameters=lf.Parameters(distributed_slack=False))\n", + "print(results_pypow_after_disconnection_dc)" + ] + }, + { + "cell_type": "markdown", + "id": "5ece1e45", + "metadata": {}, + "source": [ + "#### Final visualisation" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "dc56db3c", + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 49\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -49\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-1-2\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 27\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -27\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-1-5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 1\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -1\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-9-10\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -9\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 9\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-10-11\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 12\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -12\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-6-11\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 8\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -8\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-6-12\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 2\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -2\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-12-13\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 19\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -19\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-6-13\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 9\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -9\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-13-14\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 6\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -6\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-9-14\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 30\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -30\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-2-3\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 56\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -56\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-2-4\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 18\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -18\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-2-5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 24\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -24\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-3-4\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-4-5\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 23\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -23\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " TWT-4-7\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 12\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -12\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " TWT-4-9\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 39\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -39\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " TWT-5-6\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -0\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 0\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-7-8\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " -23\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " 23\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " LINE-9-7\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
VL-1
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / 0.0°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-10
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -11.1°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-11
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -10.2°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-12
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -9.9°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-13
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -10.2°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-14
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -12.0°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-2
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -1.7°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-3
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -5.0°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-4
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -7.4°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-5
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -3.5°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-6
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -8.8°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-7
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -10.1°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-8
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -10.1°
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
VL-9
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
kV / -11.1°
\n", + "
\n", + "
\n", + "
\n", + "
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pypowsybl_network.get_network_area_diagram()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Notebook/Conversion issues.ipynb b/Notebook/Conversion issues.ipynb new file mode 100644 index 0000000..28ebc42 --- /dev/null +++ b/Notebook/Conversion issues.ipynb @@ -0,0 +1,554 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fc820d4f", + "metadata": {}, + "source": [ + "### Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "3b750114", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\rtschupp\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\pypowsybltest-3L0u-b9v-py3.10\\lib\\site-packages\\grid2op\\Backend\\PandaPowerBackend.py:31: UserWarning: Numba cannot be loaded. You will gain possibly massive speed if installing it by \n", + "\tC:\\Users\\rtschupp\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\pypowsybltest-3L0u-b9v-py3.10\\Scripts\\python.exe -m pip install numba\n", + "\n", + " warnings.warn(\n", + "C:\\Users\\rtschupp\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\pypowsybltest-3L0u-b9v-py3.10\\lib\\site-packages\\lightsim2grid\\securityAnalysis.py:76: FutureWarning: In the future `np.str` will be defined as the corresponding NumPy scalar.\n", + " STR_TYPES = (str, np.str, np.str_)\n" + ] + } + ], + "source": [ + "import pypowsybl.network as pp\n", + "import pypowsybl.loadflow as lf\n", + "import pypowsybl as ppow\n", + "import pandapower as pp\n", + "from pypowsybl.network import _path_to_str" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b725fe65", + "metadata": {}, + "outputs": [], + "source": [ + "full_path = \"../src/data_test/l2rpn_case14_sandbox_Pypowsybl/grid.json\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "28e75f53", + "metadata": {}, + "outputs": [], + "source": [ + "pandapow_net = pp.from_json(full_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2d7982f0", + "metadata": {}, + "outputs": [], + "source": [ + "mat_path = full_path[:2] + full_path[2:].split('.')[0] + '.mat'" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "cb2613c2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'../src/data_test/l2rpn_case14_sandbox_Pypowsybl/grid.mat'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mat_path" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4e805b6d", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "gen vm_pu > bus max_vm_pu for gens [2 3 4]. Setting bus limit for these gens.\n" + ] + } + ], + "source": [ + "_ = pp.converter.to_mpc(pandapow_net, mat_path , init='flat')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "504ebc06", + "metadata": {}, + "outputs": [], + "source": [ + "grid = ppow.network.load(_path_to_str(mat_path),{'matpower.import.ignore-base-voltage': 'false'})" + ] + }, + { + "cell_type": "markdown", + "id": "2a3744c2", + "metadata": {}, + "source": [ + "### Illustrative example the transformers" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "f82d0c35", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namestd_typehv_buslv_bussn_mvavn_hv_kvvn_lv_kvvk_percentvkr_percentpfe_kwi0_percentshift_degreetap_sidetap_neutraltap_mintap_maxtap_step_percenttap_step_degreetap_postap_phase_shifterparalleldfin_servicemax_loading_percent
0NoneNone369900.0138.014.02070.2880.00.00.00.0hv0NaNNaN2.20.0-1False11.0True100.0
1NoneNone389900.0138.020.05506.1820.00.00.00.0hv0NaNNaN3.10.0-1False11.0True100.0
2NoneNone459900.0138.020.02494.9980.00.00.00.0hv0NaNNaN6.80.0-1False11.0True100.0
3NoneNone679900.014.012.01743.8850.00.00.00.0False0NaNNaN0.00.00False11.0True100.0
4NoneNone869900.020.014.01089.0990.00.00.00.0False0NaNNaN0.00.00False11.0True100.0
\n", + "
" + ], + "text/plain": [ + " name std_type hv_bus lv_bus sn_mva vn_hv_kv vn_lv_kv vk_percent \n", + "0 None None 3 6 9900.0 138.0 14.0 2070.288 \\\n", + "1 None None 3 8 9900.0 138.0 20.0 5506.182 \n", + "2 None None 4 5 9900.0 138.0 20.0 2494.998 \n", + "3 None None 6 7 9900.0 14.0 12.0 1743.885 \n", + "4 None None 8 6 9900.0 20.0 14.0 1089.099 \n", + "\n", + " vkr_percent pfe_kw i0_percent shift_degree tap_side tap_neutral \n", + "0 0.0 0.0 0.0 0.0 hv 0 \\\n", + "1 0.0 0.0 0.0 0.0 hv 0 \n", + "2 0.0 0.0 0.0 0.0 hv 0 \n", + "3 0.0 0.0 0.0 0.0 False 0 \n", + "4 0.0 0.0 0.0 0.0 False 0 \n", + "\n", + " tap_min tap_max tap_step_percent tap_step_degree tap_pos \n", + "0 NaN NaN 2.2 0.0 -1 \\\n", + "1 NaN NaN 3.1 0.0 -1 \n", + "2 NaN NaN 6.8 0.0 -1 \n", + "3 NaN NaN 0.0 0.0 0 \n", + "4 NaN NaN 0.0 0.0 0 \n", + "\n", + " tap_phase_shifter parallel df in_service max_loading_percent \n", + "0 False 1 1.0 True 100.0 \n", + "1 False 1 1.0 True 100.0 \n", + "2 False 1 1.0 True 100.0 \n", + "3 False 1 1.0 True 100.0 \n", + "4 False 1 1.0 True 100.0 " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pandapow_net.trafo" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e91c771b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namerxgbrated_u1rated_u2rated_sp1q1i1p2q2i2voltage_level1_idvoltage_level2_idbus1_idbus2_idconnected1connected2
id
TWT-4-70.00.4098750.00.0134.96414.0NaNNaNNaNNaNNaNNaNNaNVL-4VL-7VL-4_0VL-7_0TrueTrue
TWT-4-90.02.2247200.00.0133.72220.0NaNNaNNaNNaNNaNNaNNaNVL-4VL-9VL-4_0VL-9_0TrueTrue
TWT-5-60.01.0080800.00.0128.61620.0NaNNaNNaNNaNNaNNaNNaNVL-5VL-6VL-5_0VL-6_0TrueTrue
\n", + "
" + ], + "text/plain": [ + " name r x g b rated_u1 rated_u2 rated_s p1 q1 \n", + "id \n", + "TWT-4-7 0.0 0.409875 0.0 0.0 134.964 14.0 NaN NaN NaN \\\n", + "TWT-4-9 0.0 2.224720 0.0 0.0 133.722 20.0 NaN NaN NaN \n", + "TWT-5-6 0.0 1.008080 0.0 0.0 128.616 20.0 NaN NaN NaN \n", + "\n", + " i1 p2 q2 i2 voltage_level1_id voltage_level2_id bus1_id bus2_id \n", + "id \n", + "TWT-4-7 NaN NaN NaN NaN VL-4 VL-7 VL-4_0 VL-7_0 \\\n", + "TWT-4-9 NaN NaN NaN NaN VL-4 VL-9 VL-4_0 VL-9_0 \n", + "TWT-5-6 NaN NaN NaN NaN VL-5 VL-6 VL-5_0 VL-6_0 \n", + "\n", + " connected1 connected2 \n", + "id \n", + "TWT-4-7 True True \n", + "TWT-4-9 True True \n", + "TWT-5-6 True True " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "grid.get_2_windings_transformers()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Notebook/Tests move connectable and bugs.ipynb b/Notebook/Tests move connectable and bugs.ipynb new file mode 100644 index 0000000..2a8738a --- /dev/null +++ b/Notebook/Tests move connectable and bugs.ipynb @@ -0,0 +1,3168 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fc820d4f", + "metadata": {}, + "source": [ + "### Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "3b750114", + "metadata": {}, + "outputs": [], + "source": [ + "import pypowsybl.network as pp\n", + "import pypowsybl.loadflow as lf\n", + "import pypowsybl as ppow" + ] + }, + { + "cell_type": "markdown", + "id": "ee2e2bfd", + "metadata": {}, + "source": [ + "### Definition of doubling bus function as we are doing in Grid2op" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b8f69f24", + "metadata": {}, + "outputs": [], + "source": [ + "def _double_buses(grid):\n", + "\n", + " df = grid.get_buses()\n", + " L = []\n", + " for elem in grid.get_voltage_levels().index:\n", + " for bus_id in grid.get_bus_breaker_topology(voltage_level_id=elem).buses.index:\n", + " L.append(bus_id)\n", + " L_voltage_id = df['voltage_level_id'].to_list()\n", + " for i in range(len(L)):\n", + " grid.create_buses(id=L[i] + '_bis', voltage_level_id=L_voltage_id[i], name=df['name'][i])" + ] + }, + { + "cell_type": "markdown", + "id": "95d1b9b0", + "metadata": {}, + "source": [ + "### Move connectable test" + ] + }, + { + "cell_type": "markdown", + "id": "f3379b1a", + "metadata": {}, + "source": [ + "#### Description of network" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "101ddbbb", + "metadata": {}, + "outputs": [], + "source": [ + "network_pp = pp.create_ieee14()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7c464c69", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namerxg1b1g2b2p1q1i1...voltage_level2_idbus1_idbus_breaker_bus1_idnode1bus2_idbus_breaker_bus2_idnode2connected1connected2fictitious
id
L1-2-13.53200510.7837320.00.0001450.00.000145NaNNaNNaN...VL2VL1_0B1-1VL2_0B2-1TrueTrueFalse
L1-5-19.84696740.6490400.00.0001350.00.000135NaNNaNNaN...VL5VL1_0B1-1VL5_0B5-1TrueTrueFalse
L2-3-18.56392736.0800330.00.0001200.00.000120NaNNaNNaN...VL3VL2_0B2-1VL3_0B3-1TrueTrueFalse
L2-4-110.59054732.1343200.00.0000930.00.000093NaNNaNNaN...VL4VL2_0B2-1VL4_0B4-1TrueTrueFalse
L2-5-110.37913731.6896300.00.0000950.00.000095NaNNaNNaN...VL5VL2_0B2-1VL5_0B5-1TrueTrueFalse
L3-4-112.21257331.1702170.00.0000350.00.000035NaNNaNNaN...VL4VL3_0B3-1VL4_0B4-1TrueTrueFalse
L4-5-12.4330387.6745480.00.0000000.00.000000NaNNaNNaN...VL5VL4_0B4-1VL5_0B5-1TrueTrueFalse
L6-11-10.1367710.2864160.00.0000000.00.000000NaNNaNNaN...VL11VL6_0B6-1VL11_0B11-1TrueTrueFalse
L6-12-10.1769900.3683660.00.0000000.00.000000NaNNaNNaN...VL12VL6_0B6-1VL12_0B12-1TrueTrueFalse
L6-13-10.0952560.1875890.00.0000000.00.000000NaNNaNNaN...VL13VL6_0B6-1VL13_0B13-1TrueTrueFalse
L7-8-10.0000000.4932200.0-0.8689250.00.608248NaNNaNNaN...VL8VL7_0B7-1VL8_0B8-1TrueTrueFalse
L7-9-10.0000000.1848170.00.7729660.0-0.901794NaNNaNNaN...VL9VL7_0B7-1VL9_0B9-1TrueTrueFalse
L9-10-10.0458060.1216800.00.0000000.00.000000NaNNaNNaN...VL10VL9_0B9-1VL10_0B10-1TrueTrueFalse
L9-14-10.1830380.3893470.00.0000000.00.000000NaNNaNNaN...VL14VL9_0B9-1VL14_0B14-1TrueTrueFalse
L10-11-10.1181520.2765810.00.0000000.00.000000NaNNaNNaN...VL11VL10_0B10-1VL11_0B11-1TrueTrueFalse
L12-13-10.3181250.2878270.00.0000000.00.000000NaNNaNNaN...VL13VL12_0B12-1VL13_0B13-1TrueTrueFalse
L13-14-10.2461390.5011490.00.0000000.00.000000NaNNaNNaN...VL14VL13_0B13-1VL14_0B14-1TrueTrueFalse
\n", + "

17 rows × 24 columns

\n", + "
" + ], + "text/plain": [ + " name r x g1 b1 g2 b2 p1 q1 i1 \n", + "id \n", + "L1-2-1 3.532005 10.783732 0.0 0.000145 0.0 0.000145 NaN NaN NaN \\\n", + "L1-5-1 9.846967 40.649040 0.0 0.000135 0.0 0.000135 NaN NaN NaN \n", + "L2-3-1 8.563927 36.080033 0.0 0.000120 0.0 0.000120 NaN NaN NaN \n", + "L2-4-1 10.590547 32.134320 0.0 0.000093 0.0 0.000093 NaN NaN NaN \n", + "L2-5-1 10.379137 31.689630 0.0 0.000095 0.0 0.000095 NaN NaN NaN \n", + "L3-4-1 12.212573 31.170217 0.0 0.000035 0.0 0.000035 NaN NaN NaN \n", + "L4-5-1 2.433038 7.674548 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L6-11-1 0.136771 0.286416 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L6-12-1 0.176990 0.368366 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L6-13-1 0.095256 0.187589 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L7-8-1 0.000000 0.493220 0.0 -0.868925 0.0 0.608248 NaN NaN NaN \n", + "L7-9-1 0.000000 0.184817 0.0 0.772966 0.0 -0.901794 NaN NaN NaN \n", + "L9-10-1 0.045806 0.121680 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L9-14-1 0.183038 0.389347 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L10-11-1 0.118152 0.276581 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L12-13-1 0.318125 0.287827 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L13-14-1 0.246139 0.501149 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "\n", + " ... voltage_level2_id bus1_id bus_breaker_bus1_id node1 bus2_id \n", + "id ... \n", + "L1-2-1 ... VL2 VL1_0 B1 -1 VL2_0 \\\n", + "L1-5-1 ... VL5 VL1_0 B1 -1 VL5_0 \n", + "L2-3-1 ... VL3 VL2_0 B2 -1 VL3_0 \n", + "L2-4-1 ... VL4 VL2_0 B2 -1 VL4_0 \n", + "L2-5-1 ... VL5 VL2_0 B2 -1 VL5_0 \n", + "L3-4-1 ... VL4 VL3_0 B3 -1 VL4_0 \n", + "L4-5-1 ... VL5 VL4_0 B4 -1 VL5_0 \n", + "L6-11-1 ... VL11 VL6_0 B6 -1 VL11_0 \n", + "L6-12-1 ... VL12 VL6_0 B6 -1 VL12_0 \n", + "L6-13-1 ... VL13 VL6_0 B6 -1 VL13_0 \n", + "L7-8-1 ... VL8 VL7_0 B7 -1 VL8_0 \n", + "L7-9-1 ... VL9 VL7_0 B7 -1 VL9_0 \n", + "L9-10-1 ... VL10 VL9_0 B9 -1 VL10_0 \n", + "L9-14-1 ... VL14 VL9_0 B9 -1 VL14_0 \n", + "L10-11-1 ... VL11 VL10_0 B10 -1 VL11_0 \n", + "L12-13-1 ... VL13 VL12_0 B12 -1 VL13_0 \n", + "L13-14-1 ... VL14 VL13_0 B13 -1 VL14_0 \n", + "\n", + " bus_breaker_bus2_id node2 connected1 connected2 fictitious \n", + "id \n", + "L1-2-1 B2 -1 True True False \n", + "L1-5-1 B5 -1 True True False \n", + "L2-3-1 B3 -1 True True False \n", + "L2-4-1 B4 -1 True True False \n", + "L2-5-1 B5 -1 True True False \n", + "L3-4-1 B4 -1 True True False \n", + "L4-5-1 B5 -1 True True False \n", + "L6-11-1 B11 -1 True True False \n", + "L6-12-1 B12 -1 True True False \n", + "L6-13-1 B13 -1 True True False \n", + "L7-8-1 B8 -1 True True False \n", + "L7-9-1 B9 -1 True True False \n", + "L9-10-1 B10 -1 True True False \n", + "L9-14-1 B14 -1 True True False \n", + "L10-11-1 B11 -1 True True False \n", + "L12-13-1 B13 -1 True True False \n", + "L13-14-1 B14 -1 True True False \n", + "\n", + "[17 rows x 24 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "network_pp.get_lines(all_attributes=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "317286ee", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nametypep0q0pqivoltage_level_idbus_idbus_breaker_bus_idnodeconnectedfictitious
id
B2-LUNDEFINED21.712.7NaNNaNNaNVL2VL2_0B2-1TrueFalse
B3-LUNDEFINED94.219.0NaNNaNNaNVL3VL3_0B3-1TrueFalse
B4-LUNDEFINED47.8-3.9NaNNaNNaNVL4VL4_0B4-1TrueFalse
B5-LUNDEFINED7.61.6NaNNaNNaNVL5VL5_0B5-1TrueFalse
B6-LUNDEFINED11.27.5NaNNaNNaNVL6VL6_0B6-1TrueFalse
B9-LUNDEFINED29.516.6NaNNaNNaNVL9VL9_0B9-1TrueFalse
B10-LUNDEFINED9.05.8NaNNaNNaNVL10VL10_0B10-1TrueFalse
B11-LUNDEFINED3.51.8NaNNaNNaNVL11VL11_0B11-1TrueFalse
B12-LUNDEFINED6.11.6NaNNaNNaNVL12VL12_0B12-1TrueFalse
B13-LUNDEFINED13.55.8NaNNaNNaNVL13VL13_0B13-1TrueFalse
B14-LUNDEFINED14.95.0NaNNaNNaNVL14VL14_0B14-1TrueFalse
\n", + "
" + ], + "text/plain": [ + " name type p0 q0 p q i voltage_level_id bus_id \n", + "id \n", + "B2-L UNDEFINED 21.7 12.7 NaN NaN NaN VL2 VL2_0 \\\n", + "B3-L UNDEFINED 94.2 19.0 NaN NaN NaN VL3 VL3_0 \n", + "B4-L UNDEFINED 47.8 -3.9 NaN NaN NaN VL4 VL4_0 \n", + "B5-L UNDEFINED 7.6 1.6 NaN NaN NaN VL5 VL5_0 \n", + "B6-L UNDEFINED 11.2 7.5 NaN NaN NaN VL6 VL6_0 \n", + "B9-L UNDEFINED 29.5 16.6 NaN NaN NaN VL9 VL9_0 \n", + "B10-L UNDEFINED 9.0 5.8 NaN NaN NaN VL10 VL10_0 \n", + "B11-L UNDEFINED 3.5 1.8 NaN NaN NaN VL11 VL11_0 \n", + "B12-L UNDEFINED 6.1 1.6 NaN NaN NaN VL12 VL12_0 \n", + "B13-L UNDEFINED 13.5 5.8 NaN NaN NaN VL13 VL13_0 \n", + "B14-L UNDEFINED 14.9 5.0 NaN NaN NaN VL14 VL14_0 \n", + "\n", + " bus_breaker_bus_id node connected fictitious \n", + "id \n", + "B2-L B2 -1 True False \n", + "B3-L B3 -1 True False \n", + "B4-L B4 -1 True False \n", + "B5-L B5 -1 True False \n", + "B6-L B6 -1 True False \n", + "B9-L B9 -1 True False \n", + "B10-L B10 -1 True False \n", + "B11-L B11 -1 True False \n", + "B12-L B12 -1 True False \n", + "B13-L B13 -1 True False \n", + "B14-L B14 -1 True False " + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "network_pp.get_loads(all_attributes=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f5ca9f7b", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nameenergy_sourcetarget_pmin_pmax_pmin_qmax_qmin_q_at_target_pmax_q_at_target_pmin_q_at_p...regulated_element_idpqivoltage_level_idbus_idbus_breaker_bus_idnodeconnectedfictitious
id
B1-GOTHER232.4-9999.09999.0-1.797693e+3081.797693e+308-1.797693e+3081.797693e+308-1.797693e+308...NaNNaNNaNVL1VL1_0B1-1TrueFalse
B2-GOTHER40.0-9999.09999.0-4.000000e+015.000000e+01-4.000000e+015.000000e+01-4.000000e+01...NaNNaNNaNVL2VL2_0B2-1TrueFalse
B3-GOTHER0.0-9999.09999.00.000000e+004.000000e+010.000000e+004.000000e+010.000000e+00...NaNNaNNaNVL3VL3_0B3-1TrueFalse
B6-GOTHER0.0-9999.09999.0-6.000000e+002.400000e+01-6.000000e+002.400000e+01-6.000000e+00...NaNNaNNaNVL6VL6_0B6-1TrueFalse
B8-GOTHER0.0-9999.09999.0-6.000000e+002.400000e+01-6.000000e+002.400000e+01-6.000000e+00...NaNNaNNaNVL8VL8_0B8-1TrueFalse
\n", + "

5 rows × 25 columns

\n", + "
" + ], + "text/plain": [ + " name energy_source target_p min_p max_p min_q \n", + "id \n", + "B1-G OTHER 232.4 -9999.0 9999.0 -1.797693e+308 \\\n", + "B2-G OTHER 40.0 -9999.0 9999.0 -4.000000e+01 \n", + "B3-G OTHER 0.0 -9999.0 9999.0 0.000000e+00 \n", + "B6-G OTHER 0.0 -9999.0 9999.0 -6.000000e+00 \n", + "B8-G OTHER 0.0 -9999.0 9999.0 -6.000000e+00 \n", + "\n", + " max_q min_q_at_target_p max_q_at_target_p min_q_at_p ... \n", + "id ... \n", + "B1-G 1.797693e+308 -1.797693e+308 1.797693e+308 -1.797693e+308 ... \\\n", + "B2-G 5.000000e+01 -4.000000e+01 5.000000e+01 -4.000000e+01 ... \n", + "B3-G 4.000000e+01 0.000000e+00 4.000000e+01 0.000000e+00 ... \n", + "B6-G 2.400000e+01 -6.000000e+00 2.400000e+01 -6.000000e+00 ... \n", + "B8-G 2.400000e+01 -6.000000e+00 2.400000e+01 -6.000000e+00 ... \n", + "\n", + " regulated_element_id p q i voltage_level_id bus_id \n", + "id \n", + "B1-G NaN NaN NaN VL1 VL1_0 \\\n", + "B2-G NaN NaN NaN VL2 VL2_0 \n", + "B3-G NaN NaN NaN VL3 VL3_0 \n", + "B6-G NaN NaN NaN VL6 VL6_0 \n", + "B8-G NaN NaN NaN VL8 VL8_0 \n", + "\n", + " bus_breaker_bus_id node connected fictitious \n", + "id \n", + "B1-G B1 -1 True False \n", + "B2-G B2 -1 True False \n", + "B3-G B3 -1 True False \n", + "B6-G B6 -1 True False \n", + "B8-G B8 -1 True False \n", + "\n", + "[5 rows x 25 columns]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "network_pp.get_generators(all_attributes=True)" + ] + }, + { + "cell_type": "markdown", + "id": "a05f7ac9", + "metadata": {}, + "source": [ + "#### Moving generator only : verification of bug" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "94694046", + "metadata": {}, + "outputs": [], + "source": [ + "network_pp = pp.create_ieee14()\n", + "_double_buses(network_pp)\n", + "\n", + "ppow.network.move_connectable(network=network_pp, equipment_id='B2-G', bus_origin_id='B2',\n", + " bus_destination_id='B2_bis')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "7015dd7c", + "metadata": {}, + "outputs": [], + "source": [ + "results_pypow = lf.run_ac(network_pp)" + ] + }, + { + "cell_type": "markdown", + "id": "5f50a697", + "metadata": {}, + "source": [ + "Convergence but can not access to generators" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "1bf98a04", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[ComponentResult(connected_component_num=0, synchronous_component_num=0, status=CONVERGED, iteration_count=4, slack_bus_id='VL1_0', slack_bus_active_power_mismatch=42.67140651682162, distributed_active_power=0.0007053703923176613)]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "results_pypow" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "5148b36c", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "ename": "PyPowsyblError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mPyPowsyblError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[10], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mnetwork_pp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_generators\u001b[49m\u001b[43m(\u001b[49m\u001b[43mall_attributes\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32m~\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\pypowsybltest-3L0u-b9v-py3.10\\lib\\site-packages\\pypowsybl\\network.py:684\u001b[0m, in \u001b[0;36mNetwork.get_generators\u001b[1;34m(self, all_attributes, attributes, **kwargs)\u001b[0m\n\u001b[0;32m 574\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_generators\u001b[39m(\u001b[38;5;28mself\u001b[39m, all_attributes: \u001b[38;5;28mbool\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m, attributes: _List[\u001b[38;5;28mstr\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m 575\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: _ArrayLike) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m _DataFrame:\n\u001b[0;32m 576\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124mr\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 577\u001b[0m \u001b[38;5;124;03m Get a dataframe of generators.\u001b[39;00m\n\u001b[0;32m 578\u001b[0m \n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 682\u001b[0m \u001b[38;5;124;03m should hold.\u001b[39;00m\n\u001b[0;32m 683\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m--> 684\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_elements(ElementType\u001b[38;5;241m.\u001b[39mGENERATOR, all_attributes, attributes, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[1;32m~\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\pypowsybltest-3L0u-b9v-py3.10\\lib\\site-packages\\pypowsybl\\network.py:484\u001b[0m, in \u001b[0;36mNetwork.get_elements\u001b[1;34m(self, element_type, all_attributes, attributes, **kwargs)\u001b[0m\n\u001b[0;32m 481\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 482\u001b[0m elements_array \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m--> 484\u001b[0m series_array \u001b[38;5;241m=\u001b[39m \u001b[43m_pp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate_network_elements_series_array\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_handle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43melement_type\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfilter_attributes\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 485\u001b[0m \u001b[43m \u001b[49m\u001b[43mattributes\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43melements_array\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 486\u001b[0m result \u001b[38;5;241m=\u001b[39m _create_data_frame_from_series_array(series_array)\n\u001b[0;32m 487\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m attributes:\n", + "\u001b[1;31mPyPowsyblError\u001b[0m: " + ] + } + ], + "source": [ + "network_pp.get_generators(all_attributes=True)" + ] + }, + { + "cell_type": "markdown", + "id": "1dbc09e0", + "metadata": {}, + "source": [ + "#### Test with load" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "8940c313", + "metadata": {}, + "outputs": [], + "source": [ + "network_pp = pp.create_ieee14()\n", + "_double_buses(network_pp)\n", + "\n", + "ppow.network.move_connectable(network=network_pp, equipment_id='B2-L', bus_origin_id='B2',\n", + " bus_destination_id='B2_bis')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "6cde7ad6", + "metadata": {}, + "outputs": [], + "source": [ + "results_pypow = lf.run_ac(network_pp)" + ] + }, + { + "cell_type": "markdown", + "id": "bb97b4c6", + "metadata": {}, + "source": [ + "Converge and can access to load even if isolate" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "88b5b791", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[ComponentResult(connected_component_num=0, synchronous_component_num=0, status=CONVERGED, iteration_count=3, slack_bus_id='VL1_0', slack_bus_active_power_mismatch=-22.82232432434799, distributed_active_power=0.0)]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "results_pypow" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "3a024241", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nametypep0q0pqivoltage_level_idbus_idbus_breaker_bus_idnodeconnectedfictitious
id
B2-LUNDEFINED21.712.7NaNNaNNaNVL2VL2_1B2_bis-1TrueFalse
B3-LUNDEFINED94.219.094.219.0406.906114VL3VL3_0B3-1TrueFalse
B4-LUNDEFINED47.8-3.947.8-3.9201.540406VL4VL4_0B4-1TrueFalse
B5-LUNDEFINED7.61.67.61.632.577010VL5VL5_0B5-1TrueFalse
B6-LUNDEFINED11.27.511.27.5606.093828VL6VL6_0B6-1TrueFalse
B9-LUNDEFINED29.516.629.516.61542.266502VL9VL9_0B9-1TrueFalse
B10-LUNDEFINED9.05.89.05.8490.131106VL10VL10_0B10-1TrueFalse
B11-LUNDEFINED3.51.83.51.8179.158152VL11VL11_0B11-1TrueFalse
B12-LUNDEFINED6.11.66.11.6287.544857VL12VL12_0B12-1TrueFalse
B13-LUNDEFINED13.55.813.55.8673.012046VL13VL13_0B13-1TrueFalse
B14-LUNDEFINED14.95.014.95.0730.195425VL14VL14_0B14-1TrueFalse
\n", + "
" + ], + "text/plain": [ + " name type p0 q0 p q i voltage_level_id \n", + "id \n", + "B2-L UNDEFINED 21.7 12.7 NaN NaN NaN VL2 \\\n", + "B3-L UNDEFINED 94.2 19.0 94.2 19.0 406.906114 VL3 \n", + "B4-L UNDEFINED 47.8 -3.9 47.8 -3.9 201.540406 VL4 \n", + "B5-L UNDEFINED 7.6 1.6 7.6 1.6 32.577010 VL5 \n", + "B6-L UNDEFINED 11.2 7.5 11.2 7.5 606.093828 VL6 \n", + "B9-L UNDEFINED 29.5 16.6 29.5 16.6 1542.266502 VL9 \n", + "B10-L UNDEFINED 9.0 5.8 9.0 5.8 490.131106 VL10 \n", + "B11-L UNDEFINED 3.5 1.8 3.5 1.8 179.158152 VL11 \n", + "B12-L UNDEFINED 6.1 1.6 6.1 1.6 287.544857 VL12 \n", + "B13-L UNDEFINED 13.5 5.8 13.5 5.8 673.012046 VL13 \n", + "B14-L UNDEFINED 14.9 5.0 14.9 5.0 730.195425 VL14 \n", + "\n", + " bus_id bus_breaker_bus_id node connected fictitious \n", + "id \n", + "B2-L VL2_1 B2_bis -1 True False \n", + "B3-L VL3_0 B3 -1 True False \n", + "B4-L VL4_0 B4 -1 True False \n", + "B5-L VL5_0 B5 -1 True False \n", + "B6-L VL6_0 B6 -1 True False \n", + "B9-L VL9_0 B9 -1 True False \n", + "B10-L VL10_0 B10 -1 True False \n", + "B11-L VL11_0 B11 -1 True False \n", + "B12-L VL12_0 B12 -1 True False \n", + "B13-L VL13_0 B13 -1 True False \n", + "B14-L VL14_0 B14 -1 True False " + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "network_pp.get_loads(all_attributes=True)" + ] + }, + { + "cell_type": "markdown", + "id": "9e5964d3", + "metadata": {}, + "source": [ + "#### Test with line changes before" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "8354f368", + "metadata": {}, + "outputs": [], + "source": [ + "network_pp = pp.create_ieee14()\n", + "_double_buses(network_pp)\n", + "\n", + "pp.move_connectable(network=network_pp,equipment_id='L2-3-1', bus_origin_id='B2', bus_destination_id='B2_bis')\n", + "pp.move_connectable(network=network_pp,equipment_id='B2-G', bus_origin_id='B2', bus_destination_id='B2_bis')" + ] + }, + { + "cell_type": "markdown", + "id": "29a3f199", + "metadata": {}, + "source": [ + "It seems there is a Powsybl Error" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "f3f383c4", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "ename": "PyPowsyblError", + "evalue": "java.lang.NullPointerException", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mPyPowsyblError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[16], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m results_pypow \u001b[38;5;241m=\u001b[39m \u001b[43mlf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_ac\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnetwork_pp\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32m~\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\pypowsybltest-3L0u-b9v-py3.10\\lib\\site-packages\\pypowsybl\\loadflow.py:265\u001b[0m, in \u001b[0;36mrun_ac\u001b[1;34m(network, parameters, provider, reporter)\u001b[0m\n\u001b[0;32m 252\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 253\u001b[0m \u001b[38;5;124;03mRun an AC loadflow on a network.\u001b[39;00m\n\u001b[0;32m 254\u001b[0m \n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 262\u001b[0m \u001b[38;5;124;03m A list of component results, one for each component of the network.\u001b[39;00m\n\u001b[0;32m 263\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 264\u001b[0m p \u001b[38;5;241m=\u001b[39m parameters\u001b[38;5;241m.\u001b[39m_to_c_parameters() \u001b[38;5;28;01mif\u001b[39;00m parameters \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;28;01melse\u001b[39;00m _pypowsybl\u001b[38;5;241m.\u001b[39mLoadFlowParameters()\n\u001b[1;32m--> 265\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m [ComponentResult(res) \u001b[38;5;28;01mfor\u001b[39;00m res \u001b[38;5;129;01min\u001b[39;00m \u001b[43m_pypowsybl\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_loadflow\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnetwork\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_handle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mp\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprovider\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mreporter\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mis\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mreporter\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_reporter_model\u001b[49m\u001b[43m)\u001b[49m]\n", + "\u001b[1;31mPyPowsyblError\u001b[0m: java.lang.NullPointerException" + ] + } + ], + "source": [ + "results_pypow = lf.run_ac(network_pp)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "29496819", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namerxg1b1g2b2p1q1i1...voltage_level2_idbus1_idbus_breaker_bus1_idnode1bus2_idbus_breaker_bus2_idnode2connected1connected2fictitious
id
L1-2-13.53200510.7837320.00.0001450.00.000145NaNNaNNaN...VL2VL1_0B1-1VL2_0B2-1TrueTrueFalse
L1-5-19.84696740.6490400.00.0001350.00.000135NaNNaNNaN...VL5VL1_0B1-1VL5_0B5-1TrueTrueFalse
L2-3-18.56392736.0800330.00.0001200.00.000120NaNNaNNaN...VL3VL2_1B2_bis-1VL3_0B3-1TrueTrueFalse
L2-4-110.59054732.1343200.00.0000930.00.000093NaNNaNNaN...VL4VL2_0B2-1VL4_0B4-1TrueTrueFalse
L2-5-110.37913731.6896300.00.0000950.00.000095NaNNaNNaN...VL5VL2_0B2-1VL5_0B5-1TrueTrueFalse
L3-4-112.21257331.1702170.00.0000350.00.000035NaNNaNNaN...VL4VL3_0B3-1VL4_0B4-1TrueTrueFalse
L4-5-12.4330387.6745480.00.0000000.00.000000NaNNaNNaN...VL5VL4_0B4-1VL5_0B5-1TrueTrueFalse
L6-11-10.1367710.2864160.00.0000000.00.000000NaNNaNNaN...VL11VL6_0B6-1VL11_0B11-1TrueTrueFalse
L6-12-10.1769900.3683660.00.0000000.00.000000NaNNaNNaN...VL12VL6_0B6-1VL12_0B12-1TrueTrueFalse
L6-13-10.0952560.1875890.00.0000000.00.000000NaNNaNNaN...VL13VL6_0B6-1VL13_0B13-1TrueTrueFalse
L7-8-10.0000000.4932200.0-0.8689250.00.608248NaNNaNNaN...VL8VL7_0B7-1VL8_0B8-1TrueTrueFalse
L7-9-10.0000000.1848170.00.7729660.0-0.901794NaNNaNNaN...VL9VL7_0B7-1VL9_0B9-1TrueTrueFalse
L9-10-10.0458060.1216800.00.0000000.00.000000NaNNaNNaN...VL10VL9_0B9-1VL10_0B10-1TrueTrueFalse
L9-14-10.1830380.3893470.00.0000000.00.000000NaNNaNNaN...VL14VL9_0B9-1VL14_0B14-1TrueTrueFalse
L10-11-10.1181520.2765810.00.0000000.00.000000NaNNaNNaN...VL11VL10_0B10-1VL11_0B11-1TrueTrueFalse
L12-13-10.3181250.2878270.00.0000000.00.000000NaNNaNNaN...VL13VL12_0B12-1VL13_0B13-1TrueTrueFalse
L13-14-10.2461390.5011490.00.0000000.00.000000NaNNaNNaN...VL14VL13_0B13-1VL14_0B14-1TrueTrueFalse
\n", + "

17 rows × 24 columns

\n", + "
" + ], + "text/plain": [ + " name r x g1 b1 g2 b2 p1 q1 i1 \n", + "id \n", + "L1-2-1 3.532005 10.783732 0.0 0.000145 0.0 0.000145 NaN NaN NaN \\\n", + "L1-5-1 9.846967 40.649040 0.0 0.000135 0.0 0.000135 NaN NaN NaN \n", + "L2-3-1 8.563927 36.080033 0.0 0.000120 0.0 0.000120 NaN NaN NaN \n", + "L2-4-1 10.590547 32.134320 0.0 0.000093 0.0 0.000093 NaN NaN NaN \n", + "L2-5-1 10.379137 31.689630 0.0 0.000095 0.0 0.000095 NaN NaN NaN \n", + "L3-4-1 12.212573 31.170217 0.0 0.000035 0.0 0.000035 NaN NaN NaN \n", + "L4-5-1 2.433038 7.674548 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L6-11-1 0.136771 0.286416 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L6-12-1 0.176990 0.368366 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L6-13-1 0.095256 0.187589 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L7-8-1 0.000000 0.493220 0.0 -0.868925 0.0 0.608248 NaN NaN NaN \n", + "L7-9-1 0.000000 0.184817 0.0 0.772966 0.0 -0.901794 NaN NaN NaN \n", + "L9-10-1 0.045806 0.121680 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L9-14-1 0.183038 0.389347 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L10-11-1 0.118152 0.276581 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L12-13-1 0.318125 0.287827 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "L13-14-1 0.246139 0.501149 0.0 0.000000 0.0 0.000000 NaN NaN NaN \n", + "\n", + " ... voltage_level2_id bus1_id bus_breaker_bus1_id node1 bus2_id \n", + "id ... \n", + "L1-2-1 ... VL2 VL1_0 B1 -1 VL2_0 \\\n", + "L1-5-1 ... VL5 VL1_0 B1 -1 VL5_0 \n", + "L2-3-1 ... VL3 VL2_1 B2_bis -1 VL3_0 \n", + "L2-4-1 ... VL4 VL2_0 B2 -1 VL4_0 \n", + "L2-5-1 ... VL5 VL2_0 B2 -1 VL5_0 \n", + "L3-4-1 ... VL4 VL3_0 B3 -1 VL4_0 \n", + "L4-5-1 ... VL5 VL4_0 B4 -1 VL5_0 \n", + "L6-11-1 ... VL11 VL6_0 B6 -1 VL11_0 \n", + "L6-12-1 ... VL12 VL6_0 B6 -1 VL12_0 \n", + "L6-13-1 ... VL13 VL6_0 B6 -1 VL13_0 \n", + "L7-8-1 ... VL8 VL7_0 B7 -1 VL8_0 \n", + "L7-9-1 ... VL9 VL7_0 B7 -1 VL9_0 \n", + "L9-10-1 ... VL10 VL9_0 B9 -1 VL10_0 \n", + "L9-14-1 ... VL14 VL9_0 B9 -1 VL14_0 \n", + "L10-11-1 ... VL11 VL10_0 B10 -1 VL11_0 \n", + "L12-13-1 ... VL13 VL12_0 B12 -1 VL13_0 \n", + "L13-14-1 ... VL14 VL13_0 B13 -1 VL14_0 \n", + "\n", + " bus_breaker_bus2_id node2 connected1 connected2 fictitious \n", + "id \n", + "L1-2-1 B2 -1 True True False \n", + "L1-5-1 B5 -1 True True False \n", + "L2-3-1 B3 -1 True True False \n", + "L2-4-1 B4 -1 True True False \n", + "L2-5-1 B5 -1 True True False \n", + "L3-4-1 B4 -1 True True False \n", + "L4-5-1 B5 -1 True True False \n", + "L6-11-1 B11 -1 True True False \n", + "L6-12-1 B12 -1 True True False \n", + "L6-13-1 B13 -1 True True False \n", + "L7-8-1 B8 -1 True True False \n", + "L7-9-1 B9 -1 True True False \n", + "L9-10-1 B10 -1 True True False \n", + "L9-14-1 B14 -1 True True False \n", + "L10-11-1 B11 -1 True True False \n", + "L12-13-1 B13 -1 True True False \n", + "L13-14-1 B14 -1 True True False \n", + "\n", + "[17 rows x 24 columns]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "network_pp.get_lines(all_attributes=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "16fd833e", + "metadata": {}, + "outputs": [ + { + "ename": "PyPowsyblError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mPyPowsyblError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[18], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mnetwork_pp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_generators\u001b[49m\u001b[43m(\u001b[49m\u001b[43mall_attributes\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32m~\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\pypowsybltest-3L0u-b9v-py3.10\\lib\\site-packages\\pypowsybl\\network.py:684\u001b[0m, in \u001b[0;36mNetwork.get_generators\u001b[1;34m(self, all_attributes, attributes, **kwargs)\u001b[0m\n\u001b[0;32m 574\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_generators\u001b[39m(\u001b[38;5;28mself\u001b[39m, all_attributes: \u001b[38;5;28mbool\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m, attributes: _List[\u001b[38;5;28mstr\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m 575\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: _ArrayLike) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m _DataFrame:\n\u001b[0;32m 576\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124mr\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 577\u001b[0m \u001b[38;5;124;03m Get a dataframe of generators.\u001b[39;00m\n\u001b[0;32m 578\u001b[0m \n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 682\u001b[0m \u001b[38;5;124;03m should hold.\u001b[39;00m\n\u001b[0;32m 683\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m--> 684\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_elements(ElementType\u001b[38;5;241m.\u001b[39mGENERATOR, all_attributes, attributes, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[1;32m~\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\pypowsybltest-3L0u-b9v-py3.10\\lib\\site-packages\\pypowsybl\\network.py:484\u001b[0m, in \u001b[0;36mNetwork.get_elements\u001b[1;34m(self, element_type, all_attributes, attributes, **kwargs)\u001b[0m\n\u001b[0;32m 481\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 482\u001b[0m elements_array \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m--> 484\u001b[0m series_array \u001b[38;5;241m=\u001b[39m \u001b[43m_pp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate_network_elements_series_array\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_handle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43melement_type\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfilter_attributes\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 485\u001b[0m \u001b[43m \u001b[49m\u001b[43mattributes\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43melements_array\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 486\u001b[0m result \u001b[38;5;241m=\u001b[39m _create_data_frame_from_series_array(series_array)\n\u001b[0;32m 487\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m attributes:\n", + "\u001b[1;31mPyPowsyblError\u001b[0m: " + ] + } + ], + "source": [ + "network_pp.get_generators(all_attributes=True)" + ] + }, + { + "cell_type": "markdown", + "id": "cc4835cf", + "metadata": {}, + "source": [ + "#### Same test with load instead of generator" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "6989f682", + "metadata": {}, + "outputs": [], + "source": [ + "network_pp = pp.create_ieee14()\n", + "_double_buses(network_pp)\n", + "\n", + "pp.move_connectable(network=network_pp,equipment_id='L2-3-1', bus_origin_id='B2', bus_destination_id='B2_bis')\n", + "ppow.network.move_connectable(network=network_pp, equipment_id='B2-L', bus_origin_id='B2', bus_destination_id='B2_bis')" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "0781048a", + "metadata": {}, + "outputs": [], + "source": [ + "results_pypow = lf.run_ac(network_pp)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "7fa2e255", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[ComponentResult(connected_component_num=0, synchronous_component_num=0, status=CONVERGED, iteration_count=9, slack_bus_id='VL1_0', slack_bus_active_power_mismatch=20.989262691554433, distributed_active_power=-1.7883366733083328)]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "results_pypow" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "e8c30571", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namerxg1b1g2b2p1q1i1...voltage_level2_idbus1_idbus_breaker_bus1_idnode1bus2_idbus_breaker_bus2_idnode2connected1connected2fictitious
id
L1-2-13.53200510.7837320.00.0001450.00.000145150.860506-12.339939610.693555...VL2VL1_0B1-1VL2_0B2-1TrueTrueFalse
L1-5-19.84696740.6490400.00.0001350.00.000135102.52875720.849020422.127727...VL5VL1_0B1-1VL5_0B5-1TrueTrueFalse
L2-3-18.56392736.0800330.00.0001200.00.000120-21.698011-12.699783130.681779...VL3VL2_1B2_bis-1VL3_0B3-1TrueTrueFalse
L2-4-110.59054732.1343200.00.0000930.00.000093107.55871317.670456447.712564...VL4VL2_0B2-1VL4_0B4-1TrueTrueFalse
L2-5-110.37913731.6896300.00.0000950.00.00009579.35559413.813905330.849492...VL5VL2_0B2-1VL5_0B5-1TrueTrueFalse
L3-4-112.21257331.1702170.00.0000350.00.000035-116.3062779.668565578.105791...VL4VL3_0B3-1VL4_0B4-1TrueTrueFalse
L4-5-12.4330387.6745480.00.0000000.00.000000-115.1450052.905321511.270311...VL5VL4_0B4-1VL5_0B5-1TrueTrueFalse
L6-11-10.1367710.2864160.00.0000000.00.0000009.9305825.928420533.658402...VL11VL6_0B6-1VL11_0B11-1TrueTrueFalse
L6-12-10.1769900.3683660.00.0000000.00.0000008.1978172.770150399.275680...VL12VL6_0B6-1VL12_0B12-1TrueTrueFalse
L6-13-10.0952560.1875890.00.0000000.00.00000019.1415998.495212966.307015...VL13VL6_0B6-1VL13_0B13-1TrueTrueFalse
L7-8-10.0000000.4932200.0-0.8689250.00.6082480.000000-23.094521934.829441...VL8VL7_0B7-1VL8_0B8-1TrueTrueFalse
L7-9-10.0000000.1848170.00.7729660.0-0.90179425.4410286.0240091058.287502...VL9VL7_0B7-1VL9_0B9-1TrueTrueFalse
L9-10-10.0458060.1216800.00.0000000.00.0000002.7325732.026749161.639091...VL10VL9_0B9-1VL10_0B10-1TrueTrueFalse
L9-14-10.1830380.3893470.00.0000000.00.0000007.7069672.231035381.197675...VL14VL9_0B9-1VL14_0B14-1TrueTrueFalse
L10-11-10.1181520.2765810.00.0000000.00.000000-6.270690-3.782764348.813811...VL11VL10_0B10-1VL11_0B11-1TrueTrueFalse
L12-13-10.3181250.2878270.00.0000000.00.0000002.0134070.993932105.253484...VL13VL12_0B12-1VL13_0B13-1TrueTrueFalse
L13-14-10.2461390.5011490.00.0000000.00.0000007.3779913.154082378.436712...VL14VL13_0B13-1VL14_0B14-1TrueTrueFalse
\n", + "

17 rows × 24 columns

\n", + "
" + ], + "text/plain": [ + " name r x g1 b1 g2 b2 p1 \n", + "id \n", + "L1-2-1 3.532005 10.783732 0.0 0.000145 0.0 0.000145 150.860506 \\\n", + "L1-5-1 9.846967 40.649040 0.0 0.000135 0.0 0.000135 102.528757 \n", + "L2-3-1 8.563927 36.080033 0.0 0.000120 0.0 0.000120 -21.698011 \n", + "L2-4-1 10.590547 32.134320 0.0 0.000093 0.0 0.000093 107.558713 \n", + "L2-5-1 10.379137 31.689630 0.0 0.000095 0.0 0.000095 79.355594 \n", + "L3-4-1 12.212573 31.170217 0.0 0.000035 0.0 0.000035 -116.306277 \n", + "L4-5-1 2.433038 7.674548 0.0 0.000000 0.0 0.000000 -115.145005 \n", + "L6-11-1 0.136771 0.286416 0.0 0.000000 0.0 0.000000 9.930582 \n", + "L6-12-1 0.176990 0.368366 0.0 0.000000 0.0 0.000000 8.197817 \n", + "L6-13-1 0.095256 0.187589 0.0 0.000000 0.0 0.000000 19.141599 \n", + "L7-8-1 0.000000 0.493220 0.0 -0.868925 0.0 0.608248 0.000000 \n", + "L7-9-1 0.000000 0.184817 0.0 0.772966 0.0 -0.901794 25.441028 \n", + "L9-10-1 0.045806 0.121680 0.0 0.000000 0.0 0.000000 2.732573 \n", + "L9-14-1 0.183038 0.389347 0.0 0.000000 0.0 0.000000 7.706967 \n", + "L10-11-1 0.118152 0.276581 0.0 0.000000 0.0 0.000000 -6.270690 \n", + "L12-13-1 0.318125 0.287827 0.0 0.000000 0.0 0.000000 2.013407 \n", + "L13-14-1 0.246139 0.501149 0.0 0.000000 0.0 0.000000 7.377991 \n", + "\n", + " q1 i1 ... voltage_level2_id bus1_id \n", + "id ... \n", + "L1-2-1 -12.339939 610.693555 ... VL2 VL1_0 \\\n", + "L1-5-1 20.849020 422.127727 ... VL5 VL1_0 \n", + "L2-3-1 -12.699783 130.681779 ... VL3 VL2_1 \n", + "L2-4-1 17.670456 447.712564 ... VL4 VL2_0 \n", + "L2-5-1 13.813905 330.849492 ... VL5 VL2_0 \n", + "L3-4-1 9.668565 578.105791 ... VL4 VL3_0 \n", + "L4-5-1 2.905321 511.270311 ... VL5 VL4_0 \n", + "L6-11-1 5.928420 533.658402 ... VL11 VL6_0 \n", + "L6-12-1 2.770150 399.275680 ... VL12 VL6_0 \n", + "L6-13-1 8.495212 966.307015 ... VL13 VL6_0 \n", + "L7-8-1 -23.094521 934.829441 ... VL8 VL7_0 \n", + "L7-9-1 6.024009 1058.287502 ... VL9 VL7_0 \n", + "L9-10-1 2.026749 161.639091 ... VL10 VL9_0 \n", + "L9-14-1 2.231035 381.197675 ... VL14 VL9_0 \n", + "L10-11-1 -3.782764 348.813811 ... VL11 VL10_0 \n", + "L12-13-1 0.993932 105.253484 ... VL13 VL12_0 \n", + "L13-14-1 3.154082 378.436712 ... VL14 VL13_0 \n", + "\n", + " bus_breaker_bus1_id node1 bus2_id bus_breaker_bus2_id node2 \n", + "id \n", + "L1-2-1 B1 -1 VL2_0 B2 -1 \\\n", + "L1-5-1 B1 -1 VL5_0 B5 -1 \n", + "L2-3-1 B2_bis -1 VL3_0 B3 -1 \n", + "L2-4-1 B2 -1 VL4_0 B4 -1 \n", + "L2-5-1 B2 -1 VL5_0 B5 -1 \n", + "L3-4-1 B3 -1 VL4_0 B4 -1 \n", + "L4-5-1 B4 -1 VL5_0 B5 -1 \n", + "L6-11-1 B6 -1 VL11_0 B11 -1 \n", + "L6-12-1 B6 -1 VL12_0 B12 -1 \n", + "L6-13-1 B6 -1 VL13_0 B13 -1 \n", + "L7-8-1 B7 -1 VL8_0 B8 -1 \n", + "L7-9-1 B7 -1 VL9_0 B9 -1 \n", + "L9-10-1 B9 -1 VL10_0 B10 -1 \n", + "L9-14-1 B9 -1 VL14_0 B14 -1 \n", + "L10-11-1 B10 -1 VL11_0 B11 -1 \n", + "L12-13-1 B12 -1 VL13_0 B13 -1 \n", + "L13-14-1 B13 -1 VL14_0 B14 -1 \n", + "\n", + " connected1 connected2 fictitious \n", + "id \n", + "L1-2-1 True True False \n", + "L1-5-1 True True False \n", + "L2-3-1 True True False \n", + "L2-4-1 True True False \n", + "L2-5-1 True True False \n", + "L3-4-1 True True False \n", + "L4-5-1 True True False \n", + "L6-11-1 True True False \n", + "L6-12-1 True True False \n", + "L6-13-1 True True False \n", + "L7-8-1 True True False \n", + "L7-9-1 True True False \n", + "L9-10-1 True True False \n", + "L9-14-1 True True False \n", + "L10-11-1 True True False \n", + "L12-13-1 True True False \n", + "L13-14-1 True True False \n", + "\n", + "[17 rows x 24 columns]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "network_pp.get_lines(all_attributes=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "8849cbfc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nametypep0q0pqivoltage_level_idbus_idbus_breaker_bus_idnodeconnectedfictitious
id
B2-LUNDEFINED21.712.721.712.7130.691274VL2VL2_1B2_bis-1TrueFalse
B3-LUNDEFINED94.219.094.219.0476.012860VL3VL3_0B3-1TrueFalse
B4-LUNDEFINED47.8-3.947.8-3.9212.880513VL4VL4_0B4-1TrueFalse
B5-LUNDEFINED7.61.67.61.633.911364VL5VL5_0B5-1TrueFalse
B6-LUNDEFINED11.27.511.27.5621.958565VL6VL6_0B6-1TrueFalse
B9-LUNDEFINED29.516.629.516.61608.230841VL9VL9_0B9-1TrueFalse
B10-LUNDEFINED9.05.89.05.8509.981449VL10VL10_0B10-1TrueFalse
B11-LUNDEFINED3.51.83.51.8185.201775VL11VL11_0B11-1TrueFalse
B12-LUNDEFINED6.11.66.11.6295.614230VL12VL12_0B12-1TrueFalse
B13-LUNDEFINED13.55.813.55.8692.985252VL13VL13_0B13-1TrueFalse
B14-LUNDEFINED14.95.014.95.0758.291161VL14VL14_0B14-1TrueFalse
\n", + "
" + ], + "text/plain": [ + " name type p0 q0 p q i voltage_level_id \n", + "id \n", + "B2-L UNDEFINED 21.7 12.7 21.7 12.7 130.691274 VL2 \\\n", + "B3-L UNDEFINED 94.2 19.0 94.2 19.0 476.012860 VL3 \n", + "B4-L UNDEFINED 47.8 -3.9 47.8 -3.9 212.880513 VL4 \n", + "B5-L UNDEFINED 7.6 1.6 7.6 1.6 33.911364 VL5 \n", + "B6-L UNDEFINED 11.2 7.5 11.2 7.5 621.958565 VL6 \n", + "B9-L UNDEFINED 29.5 16.6 29.5 16.6 1608.230841 VL9 \n", + "B10-L UNDEFINED 9.0 5.8 9.0 5.8 509.981449 VL10 \n", + "B11-L UNDEFINED 3.5 1.8 3.5 1.8 185.201775 VL11 \n", + "B12-L UNDEFINED 6.1 1.6 6.1 1.6 295.614230 VL12 \n", + "B13-L UNDEFINED 13.5 5.8 13.5 5.8 692.985252 VL13 \n", + "B14-L UNDEFINED 14.9 5.0 14.9 5.0 758.291161 VL14 \n", + "\n", + " bus_id bus_breaker_bus_id node connected fictitious \n", + "id \n", + "B2-L VL2_1 B2_bis -1 True False \n", + "B3-L VL3_0 B3 -1 True False \n", + "B4-L VL4_0 B4 -1 True False \n", + "B5-L VL5_0 B5 -1 True False \n", + "B6-L VL6_0 B6 -1 True False \n", + "B9-L VL9_0 B9 -1 True False \n", + "B10-L VL10_0 B10 -1 True False \n", + "B11-L VL11_0 B11 -1 True False \n", + "B12-L VL12_0 B12 -1 True False \n", + "B13-L VL13_0 B13 -1 True False \n", + "B14-L VL14_0 B14 -1 True False " + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "network_pp.get_loads(all_attributes=True)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/README.md b/README.md index f6088c7..2e15afe 100644 --- a/README.md +++ b/README.md @@ -1 +1,121 @@ -# pypowsybl-grid2opbackend \ No newline at end of file +# pypowsybl-grid2opbackend integration (AIRGo project) + +## Prerequisite +To be able to work properly with this backend integration you will have to install a specific version of pypowsybl. +You can find it there : [specific pypowsybl branch](https://github.com/powsybl/pypowsybl/tree/move_connectable_prototype). + +### Installation process +You will have to follow the requirements from the pypowsybl repo [build from sources](https://github.com/powsybl/pypowsybl#build-from-sources) +I copy/paste here a version of those requirements (from 10/10/2023). + +> ## Build from sources +> +>That section is intended for developers who wish to build pypowsybl from the sources in this repository. +> +>Requirements: +> +>- Maven >= 3.1 +>- Cmake >= 3.14 +>- C++11 compiler +>- Python >= 3.7 for Linux, Windows and MacOS amd64 +>- Python >= 3.8 for MacOS arm64 +>- [Oracle GraalVM Java 17](https://www.graalvm.org/downloads/) +> +>To build from sources and install PyPowSyBl package: +> +>```bash +>git clone --recursive https://github.com/powsybl/pypowsybl.git +>export JAVA_HOME= +>pip install --upgrade setuptools pip +>pip install -r requirements.txt +>pip install . +>``` +> +>While developing, you may find it convenient to use the developer (or editable) +>mode of installation: +> +>```bash +>pip install -e . +># or, to build the C extension with debug symbols: +>python setup.py build --debug develop --user +>``` +> +>Please refer to pip and setuptools documentations for more information. +> +>To run unit tests: +> +>```bash +>pytest tests +>``` +> +>To run static type checking with `mypy`: +>```bash +>mypy -p pypowsybl +>``` +> +>To run linting inspection with `pylint`: +>```bash +>pylint pypowsybl +>``` +> +## Simple example of use +In the script [ScriptForSimpleUseCase.py](src/ScriptForSimpleUseCase.py) you can find an example of simple agent doing +one action using our backend on the ieee14 case network. Some several actions could be taken up for you to +comment/decomment to act as you like on the network. + +## Definition and comparison of objects between Pypowsybl and Grid2op + +### Lines and transformers + +#### Pypowsybl +In Pypowsybl there is a real distinction between lines, 2 winding transformers and 3 winding transformers. + +#### Grid2op +In Grid2op all those objects are assimilated as lines. Nevertheless, Grid2op knows which of these lines are real powerlines +and those that are not. + +#### Use of pandapower format to test pypowsybl backend +Because of the converter chain (Pandapower format -> Matpower -> Pypowsybl inner format), issues often happen and some +lines or transfos are considered by pypowsybl as the opposite. A way to see those changes is to analyze the lines +that have a null resistance (they were transfos in pandapower format), but it is still a workaround and not a solution +or complete analysis. + + +### Thermal limitation + +#### Pypowsybl +In Pypowsybl thermal limitations are set for both buses of a line (two extremities). + +#### Grid2op +In Grid2op thermal limitations are set for the entire line. + +We decided to choose the smallest value of both extremities in pypowsybl and to give that information for the line thermal +limitation in Grid2op. We also chose to take into account only permanent limit in current. By default if none information +is available in pypowsybl I set a huge limit which is equal to no limit. + +### Substations + +#### Pypowsybl +In Pypowsybl substations should contain at least one voltage level and busbar. + +#### Grid2op +We chose to have 2 busbars at each substation to facilitate the integration of our backend with existent tests but this +remains a personal choice, the explanation is bellow. + +Because we don't want to have to make topological choices on how to deal when multiple buses are in the same substation +in pypowybl we decided to double the busbars in the backend and to give the information to Grid2op as described in the doc : +[*This “coding” allows for easily mapping the bus id (each bus is represented with an id in pandapower) and whether its busbar 1 or busbar 2 (grid2op side). More precisely: busbar 1 of substation with id sub_id will have id sub_id and busbar 2 of the same substation will have id sub_id + n_sub (recall that n_sub is the number of substation on the grid).*](https://grid2op.readthedocs.io/en/latest/createbackend.html#:~:text=This%20%E2%80%9Ccoding%E2%80%9D%20allows,on%20the%20grid) + +## Function part + +### Usage in the code + +### Functions for topological actions + +#### Doubling buses (Pypowsybl backend) +This is done by calling the _double_buses function in the PowsyblBackend.py file. Like so the initial buses (in bus_breaker_view) are doubled but initially connected with none object. + +#### Usage of move_connectable (Pypowsybl backend) +This allows the user to move any object from one bus to another in the backend. This function could only use bus_breaker_view +buses id to work (different from bus_view buses id in pypowsybl). This is particularly useful for Grid2op topological +changes to switch any object from a bus to another inside a substation (only possible topological action in Grid2op) \ No newline at end of file diff --git a/chronics_chreator.py b/chronics_chreator.py new file mode 100644 index 0000000..9fb033a --- /dev/null +++ b/chronics_chreator.py @@ -0,0 +1,330 @@ +# Copyright (c) 2020, RTE (https://www.rte-france.com) +# See ChronicsCreatorAuthors.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 comes from LightSim2grid, LightSim2grid a implements a c++ backend targeting the Grid2Op platform. It was +# modified to be able to create chronics for pypowsybl backend and takes part of pypowsybl-grid2opbackend. + +import json +import warnings +import re +import pypowsybl as ppow +import pandapower as pp +import numpy as np +from scipy.interpolate import interp1d +import matplotlib.pyplot as plt +from src.Backend.powsybl_backend import PowsyblBackend +from grid2op.Backend import PandaPowerBackend +from grid2op import make, Parameters +from grid2op.dtypes import dt_int, dt_float, dt_bool +from grid2op.Chronics import FromNPY +from lightsim2grid import LightSimBackend, TimeSerie, SecurityAnalysis +from tqdm import tqdm +import os +import datetime +import pandas as pd +from src.Backend.network import load as load_ppow_network + +FRAMEWORK = ppow + + +try: + from tabulate import tabulate + + TABULATE_AVAIL = True +except ImportError: + print("The tabulate package is not installed. Some output might not work properly") + TABULATE_AVAIL = False + +VERBOSE = False +MAKE_PLOT = True + +case_names = [ + # "case14.json", + # "case118.json", + # "case_illinois200.json", + # "case300.json", + # "case1354pegase.json", + "case1888rte.json", + #"test_1888rte_from_pp.json", + # "GBnetwork.json", # 2224 buses + # "case2848rte.json", + # "case2869pegase.json", + # "case3120sp.json", + # "case6495rte.json", + # "case6515rte.json", + # "case9241pegase.json" +] + + +def make_grid2op_env(Backend, load_p, load_q, gen_p): + param = Parameters.Parameters() + param.init_from_dict({"NO_OVERFLOW_DISCONNECTION": True}) + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = make("blank", + param=param, test=True, + backend=Backend(), + chronics_class=FromNPY, + data_feeding_kwargs={"load_p": load_p, + "load_q": load_q, + "prod_p": gen_p + }, + grid_path=case_name, + _add_to_name=f"{case_name}", + ) + return env + + +def get_loads_gens(load_p_init, load_q_init, gen_p_init, sgen_p_init=None): + # scale loads + + # use some French time series data for loads + # see https://github.com/BDonnot/data_generation for where to find this file + coeffs = {"sources": { + "country": "France", + "year": "2012", + "web": "http://clients.rte-france.com/lang/fr/visiteurs/vie/vie_stats_conso_inst.jsp" + }, + "month": { + "jan": 1.21, + "feb": 1.40, + "mar": 1.05, + "apr": 1.01, + "may": 0.86, + "jun": 0.84, + "jul": 0.84, + "aug": 0.79, + "sep": 0.85, + "oct": 0.94, + "nov": 1.01, + "dec": 1.20 + }, + "day": { + "mon": 1.01, + "tue": 1.05, + "wed": 1.05, + "thu": 1.05, + "fri": 1.03, + "sat": 0.93, + "sun": 0.88 + }, + "hour": { + "00:00": 1.00, + "01:00": 0.93, + "02:00": 0.91, + "03:00": 0.86, + "04:00": 0.84, + "05:00": 0.85, + "06:00": 0.90, + "07:00": 0.97, + "08:00": 1.03, + "09:00": 1.06, + "10:00": 1.08, + "11:00": 1.09, + "12:00": 1.09, + "13:00": 1.09, + "14:00": 1.06, + "15:00": 1.03, + "16:00": 1.00, + "17:00": 1.00, + "18:00": 1.04, + "19:00": 1.09, + "20:00": 1.05, + "21:00": 1.01, + "22:00": 0.99, + "23:00": 1.03 + } + } + vals = list(coeffs["hour"].values()) + x_final = np.arange(12 * len(vals)) + + # interpolate them at 5 minutes resolution (instead of 1h) + vals.append(vals[0]) + vals = np.array(vals) * coeffs["month"]["oct"] * coeffs["day"]["mon"] + x_interp = 12 * np.arange(len(vals)) + # start_date_time = datetime.date.fromisocalendar(coeffs.year,) + coeffs = interp1d(x=x_interp, y=vals, kind="cubic") + all_vals = coeffs(x_final) + + # compute the "smooth" loads matrix + load_p_smooth = all_vals.reshape(-1, 1) * load_p_init.reshape(1, -1) + load_q_smooth = all_vals.reshape(-1, 1) * load_q_init.reshape(1, -1) + + # add a bit of noise to it to get the "final" loads matrix + load_p = load_p_smooth * np.random.lognormal(mean=0., sigma=0.003, size=load_p_smooth.shape) + load_q = load_q_smooth * np.random.lognormal(mean=0., sigma=0.003, size=load_q_smooth.shape) + + # scale generators accordingly + gen_p = load_p.sum(axis=1).reshape(-1, 1) / load_p_init.sum() * gen_p_init.reshape(1, -1) + if sgen_p_init is None or len(sgen_p_init) <= 0 or sgen_p_init.all(): + return load_p, load_q, gen_p + else : + sgen_p = load_p.sum(axis=1).reshape(-1, 1) / load_p_init.sum() * sgen_p_init.reshape(1, -1) + return load_p, load_q, gen_p, sgen_p + +def save_loads_gens(list_columns,list_chronics,save_names): + """ + Function used to save as csv files the chronics created above with the other get_loads_gens function. The different + lists should be ordered, so they can correspond adequately (list of loads name combined with list of chronics for load + combined with the corresponding name to save it) + + :param list_columns: list of names for loads and gens under the format [list_of_loads_name,list_of_loads_name,list_of_gens_name...] + :type list_columns: :class:`list` + + :param list_chronics: list of chronics for loads and gens under the format [load_p,load_q,prod_p,...] coming from + get_loads_gens output + :type list_chronics: :class:`list` + + :param save_names: list of pathnames where to save the load_p/load_q/prod_p... files + :type save_names: :class: `list` + + :return: ``None`` + """ + try: + if len(list_columns) != len(list_chronics): + raise ValueError + for i in range(len(list_columns)): + compression_opts = dict(method='bz2') + df = pd.DataFrame(list_chronics[i], columns=list_columns[i]) + df.to_csv(save_names[i], sep=';', index=False, compression=compression_opts) + except ValueError: + print("List does not have the same size, which implies that there are some chronics with unnamed objects") + + +def prods_charac_creator(back): + """ + Create and save the prods_charac.csv file use in chronics. + + :param back: Backend created by Grid2op using pypowsybl + :type back: :class: PypowsyblBackend + + """ + grid = back._grid + columns = ['Pmax', 'Pmin', 'name', 'type', 'bus', 'max_ramp_up', 'max_ramp_down', 'min_up_time', 'min_down_time', + 'marginal_cost', 'shut_down_cost', 'start_cost', 'x', 'y', 'V'] + df = pd.DataFrame(columns=columns) + df['Pmax'] = grid.get_generators(all_attributes=True)['max_p'] + df['Pmin'] = grid.get_generators(all_attributes=True)['min_p'] + df['name'] = grid.get_generators(all_attributes=True).index.values + df['type'] = 'thermal' + df['bus'] = [back.map_sub[elem] for elem in grid.get_generators(all_attributes=True)['bus_breaker_bus_id'].values] + df['max_ramp_up'] = 1 #10 + df['max_ramp_down'] = 1 #10 + df['min_up_time'] = 4 + df['min_down_time'] = 4 + df['marginal_cost'] = 70 + df['shut_down_cost'] = 1 + df['start_cost'] = 2 + df['V'] = grid.get_generators(all_attributes=True)['target_v'] + df.to_csv('prods_charac.csv', sep=',', index=False) + + +def get_env_name_displayed(env_name): + res = re.sub("^l2rpn_", "", env_name) + res = re.sub("_small$", "", res) + res = re.sub("_large$", "", res) + res = re.sub("\\.json$", "", res) + return res + + + +if __name__ == "__main__": + np.random.seed(42) + + case_names_displayed = [get_env_name_displayed(el) for el in case_names] + g2op_times = [] + g2op_speeds = [] + g2op_sizes = [] + g2op_step_time = [] + + ts_times = [] + ts_speeds = [] + ts_sizes = [] + sa_times = [] + sa_speeds = [] + sa_sizes = [] + + for case_name in tqdm(case_names): + + if not os.path.exists(case_name): + import pandapower.networks as pn + + case = getattr(pn, os.path.splitext(case_name)[0])() + pp.to_json(case, case_name) + + # load the case file + if FRAMEWORK == ppow: + back = PowsyblBackend() + back.load_grid(case_name) + pandapow_net = pp.from_json(case_name) + # Handling thermal limits + with open(r'Thermal_limits.json', 'w') as fp: + thermal = 1000 * np.concatenate( + ( + pandapow_net.line["max_i_ka"].values, + pandapow_net.trafo["sn_mva"].values / (np.sqrt(3) * pandapow_net.trafo["vn_hv_kv"].values) + ) + ) + json.dump(list(thermal), fp) # Multiplying by 1000 : kA -> A + + back.runpf(is_dc=True) + prods_charac_creator(back) + coeff_l = 1.0 + # extract reference data + load_p_init = coeff_l * back._grid.get_loads()["p"].values.astype(dt_float) + load_q_init = coeff_l * back._grid.get_loads()["q"].values.astype(dt_float) + gen_p_init = coeff_l * back._grid.get_generators()["p"].values.astype(dt_float) + + elif FRAMEWORK == pp: + case = FRAMEWORK.from_json(case_name) + # Handling thermal limits + with open(r'Thermal_limits.json', 'w') as fp: + thermal = 1000 * np.concatenate( + ( + case.line["max_i_ka"].values, + case.trafo["sn_mva"].values / (np.sqrt(3) * case.trafo["vn_hv_kv"].values) + ) + ) + json.dump(list(thermal), fp) # Multiplying by 1000 : kA -> A + back = PandaPowerBackend() + back.load_grid(case_name) + FRAMEWORK.runpp(case) # for slack + + # extract reference data + load_p_init = 1.0 * case.load["p_mw"].values + load_q_init = 1.0 * case.load["q_mvar"].values + gen_p_init = 1.0 * case.gen["p_mw"].values + sgen_p_init = 1.0 * case.sgen["p_mw"].values + + #prods_charac_creator(back) + # extract reference data + #load_p_init = 1.0 * back._grid.get_loads()["p"].values.astype(dt_float) + #load_q_init = 1.0 * back._grid.get_loads()["q"].values.astype(dt_float) + #gen_p_init = 1.0 * back._grid.get_generators()["p"].values.astype(dt_float) + + res_time = 1. + res_unit = "s" + if len(load_p_init) <= 1000: + # report results in ms if there are less than 1000 loads + # only affects "verbose" printing + res_time = 1e3 + res_unit = "ms" + + # simulate the data + if FRAMEWORK == ppow: + load_p, load_q, gen_p = get_loads_gens(load_p_init, load_q_init, gen_p_init) + columns_loads = back._grid.get_loads(all_attributes=True).index.values + column_gens = back._grid.get_generators(all_attributes=True).index.values + save_loads_gens([columns_loads, columns_loads, column_gens], [load_p, load_q, gen_p], ['load_p.csv.bz2', 'load_q.csv.bz2', 'prod_p.csv.bz2']) + + elif FRAMEWORK == pp: + load_p, load_q, gen_p, sgen_p = get_loads_gens(load_p_init, load_q_init, gen_p_init, sgen_p_init) + columns_loads = case.load.index.values + column_gens = case.gen.index.values + save_loads_gens([columns_loads, columns_loads, column_gens], [load_p, load_q, gen_p], ['load_p.csv.bz2', 'load_q.csv.bz2', 'prod_p.csv.bz2']) + #save the data + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0df7a3c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,21 @@ +[tool.poetry] +name = "pypowsybl-grid2opbackend" +version = "0.1.0" +description = "" +authors = [ + "Rémi Tschupp ", + "Yoann Janvier ", + "Vincent Renault " +] +readme = "README.md" +packages = [{include = "pypowsybl_grid2opbackend"}] + +[tool.poetry.dependencies] +python = "^3.10" +grid2op = "^1.9.5" +pypowsybl = "^0.23.0.dev1" # Local installation following grid2op maybe this should be removd from .toml and install by pip +pandapower = "^2.13.1" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/src/Backend/__init__.py b/src/Backend/__init__.py new file mode 100644 index 0000000..3a5b1f4 --- /dev/null +++ b/src/Backend/__init__.py @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Artelys (https://www.artelys.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 pypowsybl-grid2opbackend. + +__all__ = ["powsybl_backend"] \ No newline at end of file diff --git a/src/Backend/network.py b/src/Backend/network.py new file mode 100644 index 0000000..40a325d --- /dev/null +++ b/src/Backend/network.py @@ -0,0 +1,79 @@ +# Copyright (c) 2023, Artelys (https://www.artelys.com/) +# @author Vincent Renault +# 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 pypowsybl-grid2opbackend. + +from __future__ import annotations # Necessary for type alias like _DataFrame to work with sphinx +import copy + +from os import PathLike as _PathLike +from typing import Dict as _Dict +from typing import Optional as _Optional +from typing import TYPE_CHECKING as _TYPE_CHECKING +from typing import Union as _Union + +import pypowsybl._pypowsybl as _pp +from pypowsybl.network import Network, _path_to_str +from pypowsybl.report import Reporter as _Reporter + +# Type definitions +if _TYPE_CHECKING: + ParamsDict = _Optional[_Dict[str, str]] + PathOrStr = _Union[str, _PathLike] + + +class SortedNetwork(Network): + def __init__(self, *args, **kwargs): + super(SortedNetwork, self).__init__(*args, **kwargs) + self._loads_index = super(SortedNetwork, self).get_loads().index + + def deepcopy(self): + network_copy = copy.deepcopy(self) + network_copy._loads_index = self._loads_index + return network_copy + + def get_loads(self, *args, **kwargs): + if self._loads_index is None: + return super(SortedNetwork, self).get_loads(*args, **kwargs) + else: + return super(SortedNetwork, self).get_loads(*args, **kwargs).loc[self._loads_index, :] + + +def load(file: _Union[str, _PathLike], parameters: _Dict[str, str] = None, reporter: _Reporter = None) -> Network: + """ + Load a network from a file. File should be in a supported format. + + Basic compression formats are also supported (gzip, bzip2). + + Args: + file: path to the network file + parameters: a dictionary of import parameters + reporter: the reporter to be used to create an execution report, default is None (no report) + + Returns: + The loaded network + + Examples: + + Some examples of file loading, including relative or absolute paths, and compressed files: + + .. code-block:: python + + network = pp.network.load('network.xiidm') + network = pp.network.load('/path/to/network.xiidm') + network = pp.network.load('network.xiidm.gz') + network = pp.network.load('network.uct') + ... + """ + file = _path_to_str(file) + if parameters is None: + parameters = {} + return SortedNetwork(_pp.load_network(file, parameters, + None if reporter is None else reporter._reporter_model)) # pylint: disable=protected-access + + +def _create_network(name: str, network_id: str = '') -> Network: + return SortedNetwork(_pp.create_network(name, network_id)) \ No newline at end of file diff --git a/src/Backend/powsybl_backend.py b/src/Backend/powsybl_backend.py new file mode 100644 index 0000000..de3212a --- /dev/null +++ b/src/Backend/powsybl_backend.py @@ -0,0 +1,1464 @@ +# Copyright (c) 2023, Artelys (https://www.artelys.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 pypowsybl-grid2opbackend. It is mostly inspired by the development of the several backends from +# Grid2op framework. Some part of codes have been paste/copy. + +import os # load the python os default module +import warnings +import numpy as np +import pandas as pd +import pandapower as pdp +import pypowsybl as ppow +import scipy +import copy +import itertools +from grid2op.dtypes import dt_int, dt_float, dt_bool +from grid2op.Backend.backend import Backend +from grid2op.Exceptions import * +from grid2op.Action._BackendAction import _BackendAction +from grid2op.Action import ActionSpace +from grid2op.Rules import RulesChecker +from src.Backend.network import load as load_ppow_network + +BUS_EXTENSION = '_dummy' + +class PowsyblBackend(Backend): + """ + This is a class that is designed to ease the interaction between pypowsybl and grid2op. + + This backend currently does not work with 3 windings transformers, storages and other exotic objects (It could be + achieved with pypowsybl but the integration is not properly set with grid2op) + + Attributes + ---------- + p_or: :class:`numpy.array`, dtype:float + The active power flowing at the origin end of each powerline + + q_or: :class:`numpy.array`, dtype:float + The reactive power flowing at the origin end of each powerline + + v_or: :class:`numpy.array`, dtype:float + The voltage magnitude at the origin bus of the powerline + + theta_or: :class:`numpy.array`, dtype:float + The voltage angle at the origin bus of the powerline + + a_or: :class:`numpy.array`, dtype:float + The current flowing at the origin end of each powerline + + p_ex: :class:`numpy.array`, dtype:float + The active power flowing at the extremity end of each powerline + + q_ex: :class:`numpy.array`, dtype:float + The reactive power flowing at the extremity end of each powerline + + v_ex: :class:`numpy.array`, dtype:float + The voltage magnitude at the extremity bus of the powerline + + theta_ex: :class:`numpy.array`, dtype:float + The voltage angle at the extremity bus of the powerline + + a_ex: :class:`numpy.array`, dtype:float + The current flowing at the extremity end of each powerline + + load_p: :class:`numpy.array`, dtype:float + The result active load consumption, it is NaN if no loadflow has been computed (MW) + + load_q: :class:`numpy.array`, dtype:float + The result reactive load consumption, it is NaN if no loadflow has been computed (MVAr) + + load_v: :class:`numpy.array`, dtype:float + The voltage magnitude at the bus where each load is connected + + load_theta: :class:`numpy.array`, dtype:float + The voltage angle at the bus where each load is connected + + prod_p: :class:`numpy.array`, dtype:float + The actual active production of the generator, NaN if no loadflow has been computed (MW) + + prod_q: :class:`numpy.array`, dtype:float + The actual reactive production of the generator, NaN if no loadflow has been computed (MVAr) + + prod_v: :class:`numpy.array`, dtype:float + The voltage magnitude at the bus where each generator is connected + + gen_theta: :class:`numpy.array`, dtype:float + The voltage angle at the bus where each generator is connected + + Examples + --------- + The only recommended way to use this class is by passing an instance of a Backend into the "make" + function of grid2op. Do not attempt to use a backend outside of this specific usage. + + .. code-block:: python + + import grid2op + from src.Backend.powsybl_backend import PowsyblBackend + backend = PowsyblBackend() + + env = grid2op.make(backend=backend) + # and use "env" as any open ai gym environment. + + """ + + def __init__( + self, + detailed_infos_for_cascading_failures=False, + dist_slack=False, + can_be_copied=True, + ): + Backend.__init__( + self, + detailed_infos_for_cascading_failures=detailed_infos_for_cascading_failures, + dist_slack=dist_slack, + can_be_copied=can_be_copied + ) + + self._dist_slack = dist_slack + + self.p_or = None + self.q_or = None + self.v_or = None + self.a_or = None + self.p_ex = None + self.q_ex = None + self.v_ex = None + self.a_ex = None + + self.load_p = None + self.load_q = None + self.load_v = None + + self.storage_p = None + self.storage_q = None + self.storage_v = None + + self.prod_p = None + self.prod_q = None + self.prod_v = None + self.line_status = None + + self._nb_bus_before = None + + self.can_output_theta = True # I support the voltage angle + self.theta_or = None + self.theta_ex = None + self.load_theta = None + self.gen_theta = None + self.storage_theta = None + + self._topo_vect = None + self._init_bus_load = None + self._init_bus_gen = None + self._init_bus_lor = None + self._init_bus_lex = None + self._get_vector_inj = None + self._big_topo_to_obj = None + self._big_topo_to_backend = None + self.__ppow_backend_initial_grid = None + + # Mapping some fun to apply bus updates + self._type_to_bus_set = [ + self._apply_load_bus, + self._apply_gen_bus, + self._apply_lor_bus, + self._apply_trafo_hv, + self._apply_lex_bus, + self._apply_trafo_lv, + ] + + self.dim_topo = -1 + self._number_true_line = -1 + + self.tol = None + self.map_sub = {} + self.__nb_bus_before = None # number of substation in the powergrid + self.__nb_powerline = ( + None # number of powerline (real powerline, not transformer) + ) + + def load_grid(self, path, filename=None): + """ + Regarding the type of entry file (.json designed for pandapower, .mat for matpower or .xiidm for pypowsybl) + we use different kind of loading to be sure that our network is loaded properly. + + Parameters + ---------- + path : str + The path to the folder where the grid file is + filename : str + The name of the grid file + Returns + ------- + """ + + if path is None and filename is None: + raise RuntimeError( + "You must provide at least one of path or file to load a powergrid." + ) + if path is None: + full_path = filename + elif filename is None: + full_path = path + else: + full_path = os.path.join(path, filename) + if not os.path.exists(full_path): + raise RuntimeError('There is no powergrid at "{}"'.format(full_path)) + + try: + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + if full_path.endswith('.json'): + pandapow_net = pdp.from_json(full_path) + if not pandapow_net.res_bus.shape[ + 0]: # if there is no info on bus initialize with flat values the matpower network + _ = pdp.converter.to_mpc(pandapow_net, full_path.split('.')[0] + '.mat', init='flat') + else: + _ = pdp.converter.to_mpc(pandapow_net, full_path.split('.')[0] + '.mat') + self._grid = load_ppow_network(full_path.split('.')[0] + '.mat', + {'matpower.import.ignore-base-voltage': 'false'}) + + elif full_path.endswith('.mat'): + self._grid = load_ppow_network(full_path, {'matpower.import.ignore-base-voltage': 'false'}) + elif full_path.endswith('.xiidm'): + self._grid = load_ppow_network(full_path) + else: + raise RuntimeError('This type of file is not handled try a .mat, .xiidm or .json format') + except Exception as exc_: + raise BackendError( + f'Impossible to load the powergrid located at "{full_path}". Please ' + f"check the file exist and that the file represent a valid pypowsybl " + f"grid. For your information, the error is:\n{exc_}" + ) + # """ + # Because sometimes we got negative pmin coming from matpower translation + # """ + + # ind = self._grid.get_generators(all_attributes=True).index[self._grid.get_generators(all_attributes=True)['min_p'].values < 0] + # corresp = [0 for elem in range(len(ind))] + # self._grid.update_generators(id=ind, min_p=corresp) + + lines = self._grid.get_lines(all_attributes=True) + self.__nb_bus_before = self._grid.get_buses().shape[0] + self.__nb_powerline = copy.deepcopy(lines[lines["r"] != 0].shape[0]) + self._init_bus_load = self._grid.get_loads(all_attributes=True)["bus_breaker_bus_id"].values + self._init_bus_gen = self._grid.get_generators(all_attributes=True)["bus_breaker_bus_id"].values + self._init_bus_lor = lines["bus_breaker_bus1_id"].values + self._init_bus_lex = lines["bus_breaker_bus2_id"].values + + winding_transfo = self._grid.get_2_windings_transformers(all_attributes=True) + t_for = winding_transfo["bus_breaker_bus1_id"].values + t_fex = winding_transfo["bus_breaker_bus2_id"].values + self._init_bus_lor = np.concatenate((self._init_bus_lor, t_for)) + self._init_bus_lex = np.concatenate((self._init_bus_lex, t_fex)) + + # and now initialize the attributes (see list bellow) + if self._grid.get_3_windings_transformers().shape[0] > 0: + raise BackendError(f"3 windings transformers are currently not supported. " + f"{self._grid.get_3_windings_transformers().shape[0]} found") + + self.n_line = copy.deepcopy(self._grid.get_lines().shape[0]) + \ + copy.deepcopy(self._grid.get_2_windings_transformers().shape[0]) + + df_lines, df_transfo = self._return_real_lines_transfo() + self.name_line = np.array( + df_lines["name"].index.to_list() + + df_transfo["name"].index.to_list() + ) + + self.n_gen = copy.deepcopy( + self._grid.get_generators().shape[0]) # number of generators in the grid should be read from self._grid + self.name_gen = np.array(self._grid.get_generators()["name"].index.to_list()) + + self.n_load = copy.deepcopy( + self._grid.get_loads().shape[0]) # number of loads in the grid should be read from self._grid + self.name_load = np.array(self._grid.get_loads()["name"].index.to_list()) + self.n_sub = copy.deepcopy( + self._grid.get_buses().shape[0]) # we give as an input the number of buses that seems to be corresponding to substations in Grid2op + self.topo_per_elem = self._pypowsbyl_bus_name_utility_fct(self._grid) + self.name_sub = np.array(["sub_{}".format(i) for i in self.topo_per_elem]) + + self.n_storage = copy.deepcopy(self._grid.get_batteries().shape[0]) + + if self.n_storage == 0: + self.set_no_storage() # deactivate storage in grid objects + else: + self.name_storage = np.array(self._grid.get_batteries()[ + "name"].index.to_list()) # By default in powsybl only one type of storage : batteries + + # the initial thermal limit + self.thermal_limit_a = None + + list_buses = [] + for elem in self._grid.get_voltage_levels()['name'].index.values: + list_buses = list_buses+list(self._grid.get_bus_breaker_topology(voltage_level_id=elem).buses.index) + + for i, bus in enumerate(list_buses): + self.map_sub[bus] = i + + # Doubling the buses for Grid2op necessities + self._double_buses() + + # Contrarly to Pandapower i do not have to handle issues with slack buses if the files are xiidm and well written + # I run a powerflow to initialize the paramaters of the grid in the backend + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + ppow.loadflow.run_ac(self._grid, + parameters=ppow.loadflow.Parameters(distributed_slack=self._dist_slack)) + + # other attributes should be read from self._grid (see table below for a full list of the attributes) + self._init_private_attrs() + + def reset(self, path=None, grid_filename=None): + """ + Reload the grid. + """ + # Assign the content of itself as saved at the end of load_grid + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FutureWarning) + self._grid = self.__ppow_backend_initial_grid.deepcopy() + self._reset_all_nan() + self._topo_vect[:] = self._get_topo_vect() + + def _init_private_attrs(self): + """ + Internal function that is used to initialize all grid2op objects from backend, see + https://grid2op.readthedocs.io/en/latest/space.html#grid2op.Space.GridObjects for more detail. + + We chose to have 2 busbars at each substation to facilitate the integration of our backend with existent tests + but this remains a personal choice. + This is done by using the internal function :func: `PowsyblBackend._double_buses` + + I also create some mapping dictionaries to be able to translate bus naming from Grid2op to pypowsybl and vice + versa + Returns + ------- + """ + self.sub_info = np.zeros(self.n_sub, dtype=dt_int) + self.load_to_subid = np.zeros(self.n_load, dtype=dt_int) + self.gen_to_subid = np.zeros(self.n_gen, dtype=dt_int) + self.line_or_to_subid = np.zeros(self.n_line, dtype=dt_int) + self.line_ex_to_subid = np.zeros(self.n_line, dtype=dt_int) + + self.load_to_sub_pos = np.zeros(self.n_load, dtype=dt_int) + self.gen_to_sub_pos = np.zeros(self.n_gen, dtype=dt_int) + self.line_or_to_sub_pos = np.zeros(self.n_line, dtype=dt_int) + self.line_ex_to_sub_pos = np.zeros(self.n_line, dtype=dt_int) + + if self.n_storage > 0: + self.storage_to_subid = np.zeros(self.n_storage, dtype=dt_int) + self.storage_to_sub_pos = np.zeros(self.n_storage, dtype=dt_int) + + pos_already_used = np.zeros(self.n_sub, dtype=dt_int) + + # Allows us to map the id of each substation in Grid2op (an integer) with the name of each corresponding + add_map = {} + for bus, bus_position_id in self.map_sub.items(): + add_map[bus + BUS_EXTENSION] = bus_position_id + self.__nb_bus_before + self.map_sub.update(add_map) + + # For lines & transfos + df_lines, df_transfo = self._return_real_lines_transfo() + self.line_or_to_subid = np.array( + [self.map_sub[i] for i in df_lines["bus_breaker_bus1_id"].values] + + [self.map_sub[i] for i in df_transfo["bus_breaker_bus1_id"].values]) + self.line_ex_to_subid = np.array( + [self.map_sub[i] for i in df_lines["bus_breaker_bus2_id"].values] + + [self.map_sub[i] for i in df_transfo["bus_breaker_bus2_id"].values] + ) + + for i, (line_or_pos_id, line_ex_pos_id) in enumerate(zip(self.line_or_to_subid, self.line_ex_to_subid)): + self.sub_info[line_or_pos_id] += 1 + self.sub_info[line_ex_pos_id] += 1 + self.line_or_to_sub_pos[i] = pos_already_used[line_or_pos_id] + self.line_ex_to_sub_pos[i] = pos_already_used[line_ex_pos_id] + pos_already_used[line_or_pos_id] += 1 + pos_already_used[line_ex_pos_id] += 1 + + self._number_true_line = copy.deepcopy(self._grid.get_lines(all_attributes=True)[self._grid.get_lines(all_attributes=True)["r"] != 0].shape[0]) + + # For generators + self.gen_to_subid = np.array( + [self.map_sub[i] for i in self._grid.get_generators(all_attributes=True)["bus_breaker_bus_id"].to_list()] + ) + + for i, gen_subid in enumerate(self.gen_to_subid): + self.sub_info[gen_subid] += 1 + self.gen_to_sub_pos[i] = pos_already_used[gen_subid] + pos_already_used[gen_subid] += 1 + + # For loads + self.load_to_subid = np.array( + [self.map_sub[i] for i in self._grid.get_loads(all_attributes=True)["bus_breaker_bus_id"].to_list()] + ) + + for i, load_subid in enumerate(self.load_to_subid): + self.sub_info[load_subid] += 1 + self.load_to_sub_pos[i] = pos_already_used[load_subid] + pos_already_used[load_subid] += 1 + + # For storage + self.storage_to_subid = np.array( + [self.map_sub[i] for i in self._grid.get_batteries(all_attributes=True)["bus_breaker_bus_id"].to_list()] + ) + + if self.n_storage > 0: + for i in range(len(self.storage_to_subid)): + self.sub_info[self.storage_to_subid[i]] += 1 + self.storage_to_sub_pos[i] = pos_already_used[self.storage_to_subid[i]] + pos_already_used[self.storage_to_subid[i]] += 1 + + self.dim_topo = np.sum(self.sub_info) + self._compute_pos_big_topo() + + self._get_vector_inj = dict() + self._get_vector_inj[ + "load_p" + ] = self._load_grid_load_p_mw + self._get_vector_inj[ + "load_q" + ] = self._load_grid_load_q_mvar + self._get_vector_inj[ + "prod_p" + ] = self._load_grid_gen_p_mw + self._get_vector_inj[ + "prod_v" + ] = self._load_grid_gen_vm + + cpt = 0 + self.thermal_limit_a = np.full(self.n_line, fill_value=1000000, dtype=dt_float) + operational_limits = self._grid.get_operational_limits() + current_operational_limits = operational_limits[np.array(self._grid.get_operational_limits()["type"] == "CURRENT")] + current_and_dur_operational_limits = operational_limits[np.array(self._grid.get_operational_limits()["acceptable_duration"] == -1) & #If this is a permanent limitation, we are not going to take into account other type of limitation + np.array(self._grid.get_operational_limits()["type"] == "CURRENT")] + for elem in self.name_line: + if elem in current_operational_limits: + lim_list = [] + #If this is a permanent limitation, we are not going to take into account other type of limitation + #If this is a limitation on current + for line_side in current_and_dur_operational_limits.iterrows(): + lim_list.append(line_side[1]["value"]) + limit = min(lim_list) + self.thermal_limit_a[cpt] = limit + cpt += 1 + + self.p_or = np.full(self.n_line, dtype=dt_float, fill_value=np.NaN) + self.q_or = np.full(self.n_line, dtype=dt_float, fill_value=np.NaN) + self.v_or = np.full(self.n_line, dtype=dt_float, fill_value=np.NaN) + self.a_or = np.full(self.n_line, dtype=dt_float, fill_value=np.NaN) + self.p_ex = np.full(self.n_line, dtype=dt_float, fill_value=np.NaN) + self.q_ex = np.full(self.n_line, dtype=dt_float, fill_value=np.NaN) + self.v_ex = np.full(self.n_line, dtype=dt_float, fill_value=np.NaN) + self.a_ex = np.full(self.n_line, dtype=dt_float, fill_value=np.NaN) + self.line_status = np.full(self.n_line, dtype=dt_bool, fill_value=np.NaN) + self.load_p = np.full(self.n_load, dtype=dt_float, fill_value=np.NaN) + self.load_q = np.full(self.n_load, dtype=dt_float, fill_value=np.NaN) + self.load_v = np.full(self.n_load, dtype=dt_float, fill_value=np.NaN) + self.prod_p = np.full(self.n_gen, dtype=dt_float, fill_value=np.NaN) + self.prod_v = np.full(self.n_gen, dtype=dt_float, fill_value=np.NaN) + self.prod_q = np.full(self.n_gen, dtype=dt_float, fill_value=np.NaN) + self.storage_p = np.full(self.n_storage, dtype=dt_float, fill_value=np.NaN) + self.storage_q = np.full(self.n_storage, dtype=dt_float, fill_value=np.NaN) + self.storage_v = np.full(self.n_storage, dtype=dt_float, fill_value=np.NaN) + self._nb_bus_before = None + + # shunts data + self.n_shunt = self._grid.get_shunt_compensators().shape[0] + self.shunt_to_subid = np.zeros(self.n_shunt, dtype=dt_int) - 1 + self.name_shunt = np.array(self._grid.get_shunt_compensators()["name"].index.to_list()) + self.shunt_to_subid = np.array( + [self.map_sub[i] for i in self._grid.get_shunt_compensators(all_attributes=True)["bus_breaker_bus_id"].to_list()]) + self._sh_vnkv = self._grid.get_buses()['v_mag'][ + self._grid.get_shunt_compensators()['bus_id'].values].values.astype( + dt_float + ) + self.shunts_data_available = True + + # store the topoid -> objid + self._big_topo_to_obj = [(None, None) for _ in range(self.dim_topo)] + nm_ = "load" + for load_id, pos_big_topo in enumerate(self.load_pos_topo_vect): + self._big_topo_to_obj[pos_big_topo] = (load_id, nm_) + nm_ = "gen" + for gen_id, pos_big_topo in enumerate(self.gen_pos_topo_vect): + self._big_topo_to_obj[pos_big_topo] = (gen_id, nm_) + nm_ = "lineor" + for l_id, pos_big_topo in enumerate(self.line_or_pos_topo_vect): + self._big_topo_to_obj[pos_big_topo] = (l_id, nm_) + nm_ = "lineex" + for l_id, pos_big_topo in enumerate(self.line_ex_pos_topo_vect): + self._big_topo_to_obj[pos_big_topo] = (l_id, nm_) + + # store the topoid -> objid + self._big_topo_to_backend = [(None, None, None) for _ in range(self.dim_topo)] + for load_id, pos_big_topo in enumerate(self.load_pos_topo_vect): + self._big_topo_to_backend[pos_big_topo] = (load_id, load_id, 0) + for gen_id, pos_big_topo in enumerate(self.gen_pos_topo_vect): + self._big_topo_to_backend[pos_big_topo] = (gen_id, gen_id, 1) + for l_id, pos_big_topo in enumerate(self.line_or_pos_topo_vect): + if l_id < self.__nb_powerline: + self._big_topo_to_backend[pos_big_topo] = (l_id, l_id, 2) + else: + self._big_topo_to_backend[pos_big_topo] = ( + l_id, + l_id - self.__nb_powerline, + 3, + ) + for l_id, pos_big_topo in enumerate(self.line_ex_pos_topo_vect): + if l_id < self.__nb_powerline: + self._big_topo_to_backend[pos_big_topo] = (l_id, l_id, 4) + else: + self._big_topo_to_backend[pos_big_topo] = ( + l_id, + l_id - self.__nb_powerline, + 5, + ) + + self.theta_or = np.full(self.n_line, fill_value=np.NaN, dtype=dt_float) + self.theta_ex = np.full(self.n_line, fill_value=np.NaN, dtype=dt_float) + self.load_theta = np.full(self.n_load, fill_value=np.NaN, dtype=dt_float) + self.gen_theta = np.full(self.n_gen, fill_value=np.NaN, dtype=dt_float) + self.storage_theta = np.full(self.n_storage, fill_value=np.NaN, dtype=dt_float) + + self.dim_topo = np.sum(self.sub_info) + self._compute_pos_big_topo() + + self.line_status[:] = self._get_line_status() + self._topo_vect = self._get_topo_vect() + self.tol = 1e-5 # this is NOT the pypowsybl tolerance !!!! this is used to check if a storage unit + # produce / absorbs anything + + # Create a deep copy of itself in the initial state + # Store it under super private attribute + with warnings.catch_warnings(): + # raised on some versions of pandapower / pandas + warnings.simplefilter("ignore", FutureWarning) + self.__ppow_backend_initial_grid = self._grid.deepcopy() # will be initialized in the "assert_grid_correct" + + self.map_sub_invert = {v: k for k, v in self.map_sub.items()} + + def storage_deact_for_backward_comaptibility(self): + self._init_private_attrs() + + def apply_action(self, backendAction=None): + """ + Specific implementation of the method to apply an action modifying a powergrid in the pypowsybl format. + """ + + if backendAction is None: + return + cls = type(self) + + ( + active_bus, + (prod_p, prod_v, load_p, load_q, storage), + topo__, + shunts__, + ) = backendAction() + + if np.any(prod_p.changed): + self._grid.update_generators(id=self.name_gen[prod_p.changed], target_p=prod_p.values[prod_p.changed]) + + if np.any(prod_v.changed): + self._grid.update_generators(id=self.name_gen[prod_v.changed], target_v=prod_v.values[prod_v.changed]) + + if np.any(load_p.changed): + self._grid.update_loads(id=self.name_load[load_p.changed], p0=load_p.values[load_p.changed]) + + if np.any(load_q.changed): + self._grid.update_loads(id=self.name_load[load_q.changed], q0=load_q.values[load_q.changed]) + + if self.n_storage > 0: + # active setpoint + #TODO wrong way to change storage p and topo look up to understand with loads and gens + raise BackendError("Not ready for production") + + if np.any(storage.changed): + self._grid.update_batteries(id=self.name_storage[storage.changed])# target_p=storage.values[storage.changed]) ? not sure of how to use storage.values + + # topology of the storage + stor_bus = backendAction.get_storages_bus() + new_bus_id = stor_bus.values[stor_bus.changed] # id of the busbar 1 or 2 if + activated = new_bus_id > 0 # mask of storage that have been activated + new_bus_num = ( + self.storage_to_subid[stor_bus.changed] + (new_bus_id - 1) * self.n_sub + ) # bus number + new_bus_num[~activated] = self.storage_to_subid[stor_bus.changed][ + ~activated + ] + self._grid.get_batteries()["connected"].values[stor_bus.changed] = activated + self._grid.get_batteries(all_attributes=True)["bus_breaker_bus_id"].values[stor_bus.changed] = new_bus_num + self._topo_vect[self.storage_pos_topo_vect[stor_bus.changed]] = new_bus_num + self._topo_vect[ + self.storage_pos_topo_vect[stor_bus.changed][~activated] + ] = -1 + + #TODO WIP for the shunts need to have a fix architecture for the buses + + if type(backendAction).shunts_data_available: + shunt_p, shunt_q, shunt_bus = shunts__ + + if np.any(shunt_p.changed): + self._grid.update_shunt_compensators(id=self.name_shunt[shunt_p.changed], + p=shunt_p.values[shunt_p.changed]) + + if np.any(shunt_q.changed): + self._grid.update_shunt_compensators(id=self.name_shunt[shunt_q.changed], q=shunt_q.values[shunt_q.changed]) + + if np.any(shunt_bus.changed): + sh_service = shunt_bus.values[shunt_bus.changed] != -1 + self._grid.get_shunt_compensators()["connected"].iloc[shunt_bus.changed] = sh_service + chg_and_in_service = sh_service & shunt_bus.changed + + for i in range(len(chg_and_in_service)): + equipment_name = self.name_shunt[i] + if chg_and_in_service[i]: + self.move_buses(equipment_name=equipment_name, + bus_or=self._grid.get_shunt_compensators(all_attributes=True).loc[equipment_name] + ["bus_breaker_bus_id"], + bus_dest=int(cls.local_bus_to_global(shunt_bus.values[chg_and_in_service], + cls.shunt_to_subid[chg_and_in_service])) + ) + # i made at least a real change, so i implement it in the backend + for id_el, new_bus in topo__: + id_el_backend, id_topo, type_obj = self._big_topo_to_backend[id_el] + + if type_obj is not None: + # storage unit are handled elsewhere + self._type_to_bus_set[type_obj](new_bus, id_el_backend) + + def _apply_load_bus(self, new_bus, id_el_backend): + """ + Change load bus. + If : + - new_bus_backend<0 : this means that we want to disconnect the load from the bus + - new_bus_backend>=0 : the load will be connected to the correspondant bus. + + Parameters + ---------- + new_bus: int + id of the given new bus in local substation way, could only be 1 or 2 + id_el_backend: int + id of the specific load in the backend + + Returns + ------- + + """ + new_bus_backend = type(self).local_bus_to_global_int( + new_bus, self.map_sub[self._init_bus_load[id_el_backend]] + ) + equipment_name = self.name_load[id_el_backend] + if new_bus_backend >= 0: + self.move_buses(equipment_name=equipment_name, + bus_or=self._grid.get_loads(all_attributes=True).loc[equipment_name][ + "bus_breaker_bus_id"], + bus_dest=new_bus_backend) + self._grid.update_loads(id=equipment_name, connected=True) + else: + self._grid.update_loads(id=equipment_name, connected=False) + + def _apply_gen_bus(self, new_bus, id_el_backend): + """ + Change gen bus. + If : + - new_bus_backend<0 : this means that we want to disconnect the load from the bus + - new_bus_backend>=0 : the load will be connected to the correspondant bus. + + Parameters + ---------- + new_bus: int + id of the given new bus in local substation way, could only be 1 or 2 + id_el_backend: int + id of the specific gen in the backend + + Returns + ------- + """ + new_bus_backend = type(self).local_bus_to_global_int( + new_bus, self.map_sub[self._init_bus_gen[id_el_backend]] + ) + equipment_name = self.name_gen[id_el_backend] + if new_bus_backend >= 0: + self.move_buses(equipment_name=equipment_name, + bus_or=self._grid.get_generators(all_attributes=True).loc[equipment_name]["bus_breaker_bus_id"], + bus_dest=new_bus_backend) + self._grid.update_generators(id=equipment_name, connected=True) + else: + self._grid.update_generators(id=equipment_name, connected=False) + + def _apply_lor_bus(self, new_bus, id_el_backend): + new_bus_backend = type(self).local_bus_to_global_int( + new_bus, self.map_sub[self._init_bus_lor[id_el_backend]] + ) + self.change_bus_powerline_or(id_el_backend, new_bus_backend) + + def change_bus_powerline_or(self, id_powerline_backend, new_bus_backend): + """ + Change line origin bus. + If : + - new_bus_backend<0 : this means that we want to disconnect the transfo from the bus + - new_bus_backend>=0 : the transfo will be connected to the correspondant bus. + + Parameters + ---------- + id_powerline_backend: int + id of the given line in the backend + new_bus_backend: int + id of the new bus for the line to be connected to + + Returns + ------- + """ + equipment_name = self.name_line[id_powerline_backend] + if new_bus_backend >= 0: + self.move_buses(equipment_name=equipment_name, + bus_or=self._grid.get_lines(all_attributes=True).loc[equipment_name][ + "bus_breaker_bus1_id"], + bus_dest=new_bus_backend) + self._grid.update_lines(id=equipment_name, connected1=True) + else: + self._grid.update_lines(id=equipment_name, connected1=False) + + def _apply_lex_bus(self, new_bus, id_el_backend): + new_bus_backend = type(self).local_bus_to_global_int( + new_bus, self.map_sub[self._init_bus_lex[id_el_backend]] + ) + self.change_bus_powerline_ex(id_el_backend, new_bus_backend) + + def change_bus_powerline_ex(self, id_powerline_backend, new_bus_backend): + """ + Change line extremity bus. + If : + - new_bus_backend<0 : this means that we want to disconnect the transfo from the bus + - new_bus_backend>=0 : the transfo will be connected to the correspondant bus. + + Parameters + ---------- + id_powerline_backend: int + id of the given line in the backend + new_bus_backend: int + id of the new bus for the line to be connected to + + Returns + ------- + """ + + equipment_name = self.name_line[id_powerline_backend] + if new_bus_backend >= 0: + self.move_buses(equipment_name=equipment_name, + bus_or=self._grid.get_lines(all_attributes=True).loc[equipment_name][ + "bus_breaker_bus2_id"], + bus_dest=new_bus_backend) + self._grid.update_lines(id=equipment_name, connected2=True) + else: + self._grid.update_lines(id=equipment_name, connected2=False) + + def _apply_trafo_hv(self, new_bus, id_el_backend): + new_bus_backend = type(self).local_bus_to_global_int( + new_bus, self.map_sub[self._init_bus_lor[id_el_backend]] + ) + self.change_bus_trafo_hv(id_el_backend, new_bus_backend) + + def change_bus_trafo_hv(self, id_powerline_backend, new_bus_backend): + """ + Change high voltage transfo bus. Because of the translation between grid.json (pandapower format) and matpower + to be used by pypowsybl some transfos are changed to lines and reciprocally, I have to check there type in the + backend to be sure to use the right functions. + If : + - new_bus_backend<0 : this means that we want to disconnect the transfo from the bus + - new_bus_backend>=0 : the transfo will be connected to the correspondant bus. + + Parameters + ---------- + id_powerline_backend: int + id of the given transfo in the backend + new_bus_backend: int + id of the new bus for the transfo to be connected to + + Returns + ------- + """ + # TODO by convention I observed that hv are connected on bus_1 but need to be checked and otherwise do some improvment + equipment_name = self.name_line[id_powerline_backend] + type = self._grid.get_identifiables().loc[equipment_name]["type"] + if new_bus_backend >= 0: + if type == "LINE": + self.move_buses(equipment_name=equipment_name, + bus_or=self._grid.get_lines(all_attributes=True).loc[equipment_name][ + "bus_breaker_bus1_id"], + bus_dest=new_bus_backend) + self._grid.update_lines(id=equipment_name, connected1=True) + elif type == "TWO_WINDINGS_TRANSFORMER": + self.move_buses(equipment_name=equipment_name, + bus_or=self._grid.get_2_windings_transformers(all_attributes=True).loc[equipment_name][ + "bus_breaker_bus1_id"], + bus_dest=new_bus_backend) + self._grid.update_2_windings_transformers(id=equipment_name, connected1=True) + else: + raise BackendError(f"The elements named {equipment_name} is not a transfo") + else: + if type == "LINE": + self._grid.update_lines(id=equipment_name, connected1=False) + elif type == "TWO_WINDINGS_TRANSFORMER": + self._grid.update_2_windings_transformers(id=equipment_name, connected1=False) + else: + raise BackendError(f"The elements named {equipment_name} is not a transfo") + + def _apply_trafo_lv(self, new_bus, id_el_backend): + new_bus_backend = type(self).local_bus_to_global_int( + new_bus, self.map_sub[self._init_bus_lex[id_el_backend]] + ) + self.change_bus_trafo_lv(id_el_backend, new_bus_backend) + + def change_bus_trafo_lv(self, id_powerline_backend, new_bus_backend): + """ + Change low voltage transfo bus. Because of the translation between grid.json (pandapower format) and matpower + to be used by pypowsybl some transfos are changed to lines and reciprocally, I have to check there type in the + backend to be sure to use the right functions. + If : + - new_bus_backend<0 : this means that we want to disconnect the transfo from the bus + - new_bus_backend>=0 : the transfo will be connected to the correspondant bus. + + Parameters + ---------- + id_powerline_backend: int + id of the given transfo in the backend + new_bus_backend: int + id of the new bus for the transfo to be connected to + + Returns + ------- + """ + # TODO by convention I observed that lv are connected on bus_2 but need to be checked and otherwise do some improvment + + equipment_name = self.name_line[id_powerline_backend] + type = self._grid.get_identifiables().loc[equipment_name]["type"] + if new_bus_backend >= 0: + if type == "LINE": + self.move_buses(equipment_name=equipment_name, + bus_or=self._grid.get_lines(all_attributes=True).loc[equipment_name][ + "bus_breaker_bus2_id"], + bus_dest=new_bus_backend) + self._grid.update_lines(id=equipment_name, connected2=True) + elif type == "TWO_WINDINGS_TRANSFORMER": + self.move_buses(equipment_name=equipment_name, + bus_or=self._grid.get_2_windings_transformers(all_attributes=True).loc[equipment_name]["bus_breaker_bus2_id"], + bus_dest=new_bus_backend) + self._grid.update_2_windings_transformers(id=equipment_name, connected2=True) + else: + raise BackendError(f"The elements named {equipment_name} is not a transfo") + else: + if type == "LINE": + self._grid.update_lines(id=equipment_name, connected2=False) + elif type == "TWO_WINDINGS_TRANSFORMER": + self._grid.update_2_windings_transformers(id=equipment_name, connected2=False) + else: + raise BackendError(f"The elements named {equipment_name} is not a transfo") + + def runpf(self, is_dc=False): + """ + + Run a power flow on the underlying _grid. + """ + + nb_bus = self.get_nb_active_bus() + + try: + with warnings.catch_warnings(): + # remove the warning if _grid non connex. And it that case load flow as not converged + warnings.filterwarnings( + "ignore", category=scipy.sparse.linalg.MatrixRankWarning + ) + warnings.filterwarnings("ignore", category=RuntimeWarning) + warnings.filterwarnings("ignore", category=DeprecationWarning) + + if nb_bus == self._nb_bus_before: + self._pf_init = ppow._pypowsybl.VoltageInitMode.PREVIOUS_VALUES + else: + self._pf_init = ppow._pypowsybl.VoltageInitMode.DC_VALUES + + if np.any(~self._grid.get_loads()["connected"]): + # TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state + raise BackendError("Disconnected load: for now grid2op cannot handle properly" + " disconnected load. If you want to disconnect one, say it" + " consumes 0. instead. Please check loads: " + f"{np.where(~self._grid.get_loads()['connected'])[0]}" + ) + if np.any(~self._grid.get_generators()["connected"]): + # TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state + raise BackendError("Disconnected gen: for now grid2op cannot handle properly" + " disconnected generators. If you want to disconnect one, say it" + " produces 0. instead. Please check generators: " + f"{np.where(~self._grid.get_generators()['connected'])[0]}" + ) + + if is_dc: + res = ppow.loadflow.run_dc(self._grid, + parameters=ppow.loadflow.Parameters(distributed_slack=self._dist_slack)) + else: + res = ppow.loadflow.run_ac(self._grid, + parameters=ppow.loadflow.Parameters(distributed_slack=self._dist_slack, + voltage_init_mode=self._pf_init + )) + + # TODO handle the cases where things are disconnected + ( + self.prod_p[:], + self.prod_q[:], + self.prod_v[:], + self.gen_theta[:], + ) = self._gens_info() + ( + self.load_p[:], + self.load_q[:], + self.load_v[:], + self.load_theta[:], + ) = self._loads_info() + + branches = self._grid.get_branches() + branches_bus1 = branches['bus1_id'] + branches_bus2 = branches['bus2_id'] + + self.p_or[:] = self._aux_get_line_info("p1") + self.q_or[:] = self._aux_get_line_info("q1") + self.v_or[:] = self._aux_get_voltage_info(branches_bus1) + self.a_or[:] = self._aux_get_line_info("i1") + self.theta_or[:] = self._aux_get_theta_info(branches_bus1) + self.a_or[~np.isfinite(self.a_or)] = 0.0 + self.v_or[~np.isfinite(self.v_or)] = 0.0 + + self.p_ex[:] = self._aux_get_line_info("p2") + self.q_ex[:] = self._aux_get_line_info("q2") + self.v_ex[:] = self._aux_get_voltage_info(branches_bus2) + self.a_ex[:] = self._aux_get_line_info("i2") + self.theta_ex[:] = self._aux_get_theta_info(branches_bus2) + self.a_ex[~np.isfinite(self.a_ex)] = 0.0 + self.v_ex[~np.isfinite(self.v_ex)] = 0.0 + + + # handle storage units + # note that we have to look ourselves for disconnected storage + ( + self.storage_p[:], + self.storage_q[:], + self.storage_v[:], + self.storage_theta[:], + ) = self._storages_info() + deact_storage = ~np.isfinite(self.storage_v) + if np.any(np.abs(self.storage_p[deact_storage]) > self.tol): + raise BackendError( + "Isolated storage set to absorb / produce something" + ) + self.storage_p[deact_storage] = 0.0 + self.storage_q[deact_storage] = 0.0 + self.storage_v[deact_storage] = 0.0 + self._grid.get_batteries()["connected"].values[deact_storage] = False + + self.line_status[:] = self._get_line_status() + self._topo_vect[:] = self._get_topo_vect() + + + if res[0].status == ppow._pypowsybl.LoadFlowComponentStatus.FAILED\ + or res[0].status == ppow._pypowsybl.LoadFlowComponentStatus.MAX_ITERATION_REACHED: + return False, None + else: + return True, None + + except BackendError as exc_: + # of the powerflow has not converged, results are Nan + self._reset_all_nan() + msg = exc_.__str__() + return False, DivergingPowerFlow(f'powerflow diverged with error :"{msg}"') + + def get_line_status(self): + """ + + As all the functions related to powerline, pypowsybl split them into multiple objects to access with separated + getters (some for transformers, some for lines etc.). We make sure to get them all here. + """ + return self.line_status + + def _get_line_status(self): + lines = self._grid.get_lines(all_attributes=True) + connected_1_lines = lines[lines["r"] != 0]['connected1'] + connected_2_lines = lines[lines["r"] != 0]['connected2'] + line_connected = connected_1_lines.values & connected_2_lines.values + + windings_transfo = self._grid.get_2_windings_transformers() + connected_1_2_transfo = pd.concat([windings_transfo['connected1'], lines[lines["r"] == 0]['connected1']]) + connected_2_2_transfo = pd.concat([windings_transfo['connected2'], lines[lines["r"] == 0]['connected2']]) + transfo_2_connected = connected_1_2_transfo.values & connected_2_2_transfo.values + + # We do not take into account 3 windings transfos for the moment + + return np.concatenate( + ( + line_connected, + transfo_2_connected, + ) + ).astype(dt_bool) + + def _aux_get_voltage_info(self, elements): + buses = self._grid.get_buses()['v_mag'] + v_list = [buses[elt] if elt != '' else 0 for elt in elements] + return v_list + + def _aux_get_theta_info(self, elements): + buses = self._grid.get_buses()['v_angle'] + v_list = [buses[elt] if elt != '' else 0 for elt in elements] + return v_list + + def get_topo_vect(self): + return self._topo_vect + + def _get_topo_vect(self): + res = np.full(self.dim_topo, fill_value=np.nan, dtype=dt_int) + + line_status = self.get_line_status() + + i = 0 + for row in self._grid.get_lines(all_attributes=True)[self._grid.get_lines(all_attributes=True)["r"] != 0][["bus_breaker_bus1_id", "bus_breaker_bus2_id"]].values: + + if line_status[i]: + bus_or_id = self.map_sub[row[0]] + bus_ex_id = self.map_sub[row[1]] + res[self.line_or_pos_topo_vect[i]] = ( + 1 if bus_or_id == self.line_or_to_subid[i] else 2 + ) + res[self.line_ex_pos_topo_vect[i]] = ( + 1 if bus_ex_id == self.line_ex_to_subid[i] else 2 + ) + else: + res[self.line_or_pos_topo_vect[i]] = -1 + res[self.line_ex_pos_topo_vect[i]] = -1 + i += 1 + + nb = self._number_true_line + + # For 2 windings transfo + i = 0 + """ + Because there is a problem of transcription between pandapower and pypowsybl using matpower I have to give all + the elements considered as transformers + """ + for row in np.concatenate((self._grid.get_2_windings_transformers(all_attributes=True)[["bus_breaker_bus1_id", "bus_breaker_bus2_id"]].values, self._grid.get_lines(all_attributes=True)[self._grid.get_lines(all_attributes=True)["r"] == 0][["bus_breaker_bus1_id", "bus_breaker_bus2_id"]].values), axis=0): + j = i + nb + if line_status[j]: + bus_or_id = self.map_sub[row[0]] + bus_ex_id = self.map_sub[row[1]] + res[self.line_or_pos_topo_vect[j]] = ( + 1 if bus_or_id == self.line_or_to_subid[j] else 2 + ) + res[self.line_ex_pos_topo_vect[j]] = ( + 1 if bus_ex_id == self.line_ex_to_subid[j] else 2 + ) + else: + res[self.line_or_pos_topo_vect[j]] = -1 + res[self.line_ex_pos_topo_vect[j]] = -1 + i += 1 + + # We do not handle three windings transfos + + i = 0 + for bus_id in self._grid.get_generators(all_attributes=True)["bus_breaker_bus_id"].values: + res[self.gen_pos_topo_vect[i]] = 1 if self.map_sub[bus_id] == self.gen_to_subid[i] else 2 + i += 1 + + i = 0 + for bus_id in self._grid.get_loads(all_attributes=True)["bus_breaker_bus_id"].values: + res[self.load_pos_topo_vect[i]] = ( + 1 if self.map_sub[bus_id] == self.load_to_subid[i] else 2 + ) + i += 1 + + if self.n_storage: + # storage can be deactivated by the environment for backward compatibility + i = 0 + for bus_id in self._grid.get_batteries(all_attributes=True)["bus_breaker_bus_id"].values: + status = self._grid.get_batteries()["connected"].values[i] + if status: + res[self.storage_pos_topo_vect[i]] = ( + 1 if self.map_sub[bus_id] == self.storage_to_subid[i] else 2 + ) + else: + res[self.storage_pos_topo_vect[i]] = -1 + i += 1 + + return res + + def shunt_info(self): + shunt_p = self._grid.get_shunt_compensators()["p"].values.astype(dt_float) + shunt_q = self._grid.get_shunt_compensators()["q"].values.astype(dt_float) + shunt_v = self._grid.get_buses()['v_mag'][self._grid.get_shunt_compensators()['bus_id']].values.astype(dt_float) + shunt_bus = self.global_bus_to_local( + np.array( + [self.map_sub[elem] for elem in + self._grid.get_shunt_compensators(all_attributes=True)["bus_breaker_bus_id"].values] + ), + self.shunt_to_subid) + shunt_v[~self._grid.get_shunt_compensators()["connected"].values] = -1.0 + shunt_bus[~self._grid.get_shunt_compensators()["connected"].values] = -1 + return shunt_p, shunt_q, shunt_v, shunt_bus + + def storages_info(self): + return ( + copy.deepcopy(self.storage_p), + copy.deepcopy(self.storage_q), + copy.deepcopy(self.storage_v), + ) + + def _storages_info(self): + if self.n_storage: + # this is because we support "backward comaptibility" feature. So the storage can be + # deactivated from the Environment... + p_storage = self._grid.get_batteries()["p"].values.astype(dt_float) + q_storage = self._grid.get_batteries()["q"].values.astype(dt_float) + v_storage = self._aux_get_voltage_info(self._grid.get_batteries()['bus_id']) + theta_storage = self._aux_get_theta_info(self._grid.get_batteries()['bus_id']) + else: + p_storage = np.zeros(shape=0, dtype=dt_float) + q_storage = np.zeros(shape=0, dtype=dt_float) + v_storage = np.zeros(shape=0, dtype=dt_float) + theta_storage = np.zeros(shape=0, dtype=dt_float) + return p_storage, q_storage, v_storage, theta_storage + + def generators_info(self): + return ( + copy.deepcopy(self.prod_p), + copy.deepcopy(self.prod_q), + copy.deepcopy(self.prod_v), + ) + + def _gens_info(self): + prod_p = - self._grid.get_generators()["p"].values.astype(dt_float) + prod_q = - self._grid.get_generators()["q"].values.astype(dt_float) + prod_v = self._aux_get_voltage_info(self._grid.get_generators()['bus_id']) + prod_theta = self._aux_get_theta_info(self._grid.get_generators()['bus_id']) + + return copy.deepcopy(prod_p), copy.deepcopy(prod_q), copy.deepcopy(prod_v), copy.deepcopy(prod_theta) + + def loads_info(self): + return ( + copy.deepcopy(self.load_p), + copy.deepcopy(self.load_q), + copy.deepcopy(self.load_v) + ) + + def _loads_info(self): + load_p = self._grid.get_loads()["p"].values.astype(dt_float) + load_q = self._grid.get_loads()["q"].values.astype(dt_float) + load_v = self._aux_get_voltage_info(self._grid.get_loads()['bus_id']) + load_theta = self._aux_get_theta_info(self._grid.get_loads()['bus_id']) + return load_p, load_q, load_v, load_theta + + def lines_or_info(self): + return ( + copy.deepcopy(self.p_or), + copy.deepcopy(self.q_or), + copy.deepcopy(self.v_or), + copy.deepcopy(self.a_or) + ) + + def lines_ex_info(self): + return ( + copy.deepcopy(self.p_ex), + copy.deepcopy(self.q_ex), + copy.deepcopy(self.v_ex), + copy.deepcopy(self.a_ex) + ) + + def get_theta(self): + return ( + copy.deepcopy(self.theta_or), + copy.deepcopy(self.theta_ex), + copy.deepcopy(self.load_theta), + copy.deepcopy(self.gen_theta), + copy.deepcopy(self.storage_theta), + ) + + def assert_grid_correct(self): + """ + This is done as it should be by the Environment + """ + super().assert_grid_correct() + + def _aux_get_line_info(self, colname): + lines = self._grid.get_lines(all_attributes=True) + winding_transfo = self._grid.get_2_windings_transformers(all_attributes=True) + res = np.concatenate( + ( + lines[lines["r"] != 0][colname].values, + winding_transfo[colname].values, + lines[lines["r"] == 0][colname].values, + ) + ) + return res + + def _return_real_lines_transfo(self): + """ + Allows to retrieve the same order as in pandapower with json files, because some transformers (the one with low + voltage and not any tap change possible) are considered as lines by pypowsybl + """ + lines = self._grid.get_lines(all_attributes=True) + return lines[lines["r"] != 0], \ + pd.concat([self._grid.get_2_windings_transformers(all_attributes=True), lines[lines["r"] == 0]], join='inner') + + def sub_from_bus_id(self, bus_id): + # TODO check that the function is doing what we want + if bus_id >= self._number_true_line: + return bus_id - self._number_true_line + return bus_id + + def get_nb_active_bus(self): + """ + Compute the amount of buses "in service" eg with at least a powerline connected to it. + + Returns + ------- + res: :class:`int` + The total number of active buses. + """ + return len(self._grid.get_buses()) + + def _reset_all_nan(self): + self.p_or[:] = np.NaN + self.q_or[:] = np.NaN + self.v_or[:] = np.NaN + self.a_or[:] = np.NaN + self.p_ex[:] = np.NaN + self.q_ex[:] = np.NaN + self.v_ex[:] = np.NaN + self.a_ex[:] = np.NaN + self.prod_p[:] = np.NaN + self.prod_q[:] = np.NaN + self.prod_v[:] = np.NaN + self.load_p[:] = np.NaN + self.load_q[:] = np.NaN + self.load_v[:] = np.NaN + self.storage_p[:] = np.NaN + self.storage_q[:] = np.NaN + self.storage_v[:] = np.NaN + self._nb_bus_before = None + + self.theta_or[:] = np.NaN + self.theta_ex[:] = np.NaN + self.load_theta[:] = np.NaN + self.gen_theta[:] = np.NaN + self.storage_theta[:] = np.NaN + + @staticmethod + def _load_grid_load_p_mw(grid): + return grid.get_loads()["p"] + + @staticmethod + def _load_grid_load_q_mvar(grid): + return grid.get_loads()["q"] + + @staticmethod + def _load_grid_gen_p_mw(grid): + return grid.get_generators()["p"] + + @staticmethod + def _load_grid_gen_vm(grid): + return grid.get_buses()['v_mag'][grid.get_generators()['bus_id']] + + def _pypowsbyl_bus_name_utility_fct(self, grid): + """ + Function use to access all the name of the buses in bus_breaker_topology way. + + Parameters + ---------- + grid + Pypowsybl grid object + + Returns + ------- + res: :class:`List` + List of all the buses in format bus_breaker_topology + """ + vol_levels = [list(grid.get_bus_breaker_topology(voltage_level_id=elem).buses.index) for elem in grid.get_voltage_levels().index] + L = list(itertools.chain.from_iterable(vol_levels)) + #L = [bus_id for elem in grid.get_voltage_levels().index for bus_id in grid.get_bus_breaker_topology(voltage_level_id=elem).buses.index] + #L = [] + #for elem in grid.get_voltage_levels().index: + # for bus_id in grid.get_bus_breaker_topology(voltage_level_id=elem).buses.index: + # L.append(bus_id) + return L + + def _double_buses(self): + """ + Double the buses in the pypowybl backend to ensure that Grid2op framework is working as desired. Modifies + directly the underlying grid. + Returns + ------- + """ + + df = self._grid.get_buses() + #L = self._pypowsbyl_bus_name_utility_fct(self._grid) + #L = [] + #for elem in grid.get_voltage_levels().index: + # for bus_id in self._grid.get_bus_breaker_topology(voltage_level_id=elem).buses.index: + # L.append(bus_id) + L_voltage_id = df['voltage_level_id'].to_list() + for i in range(len(self.topo_per_elem)): + self._grid.create_buses(id=self.topo_per_elem[i] + BUS_EXTENSION, voltage_level_id=L_voltage_id[i], name=df['name'][i]) + + def move_buses(self, equipment_name, bus_or, bus_dest): + """ + Function use to call the move_connectable method for every kind of powsybl object. I use self.map_sub_invert to + get the name of the destination bus in pypowsybl norm (not Grid2op) + + Parameters + ---------- + equipment_name: str + Name of the equipment in pypowsybl backend context + bus_or: str + The name of the origin bus in pypowsybl backend context + bus_dest: str + The name of the destination bus in Grid2op context + Returns + ------- + + """ + + real_bus_dest = self.map_sub_invert[bus_dest] + if real_bus_dest != bus_or: + ppow.network.move_connectable(network=self._grid, + equipment_id=equipment_name, + bus_origin_id=bus_or, + bus_destination_id=real_bus_dest) + + def copy(self): + """ + Performs a deep copy of the power :attr:`_grid`. + """ + res = type(self)(**self._my_kwargs) + + # copy from base class (backend) + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FutureWarning) + res._grid = self._grid.deepcopy() + res.thermal_limit_a = copy.deepcopy(self.thermal_limit_a) + res._sh_vnkv = copy.deepcopy(self._sh_vnkv) + res.can_output_theta = self.can_output_theta + res._is_loaded = self._is_loaded + + # copy all attributes from myself + res.map_sub = copy.deepcopy(self.map_sub) + res.map_sub_invert = copy.deepcopy(self.map_sub_invert) + + res.p_or = copy.deepcopy(self.p_or) + res.q_or = copy.deepcopy(self.q_or) + res.v_or = copy.deepcopy(self.v_or) + res.a_or = copy.deepcopy(self.a_or) + res.p_ex = copy.deepcopy(self.p_ex) + res.q_ex = copy.deepcopy(self.q_ex) + res.v_ex = copy.deepcopy(self.v_ex) + res.a_ex = copy.deepcopy(self.a_ex) + + res.load_p = copy.deepcopy(self.load_p) + res.load_q = copy.deepcopy(self.load_q) + res.load_v = copy.deepcopy(self.load_v) + + res.storage_p = copy.deepcopy(self.storage_p) + res.storage_q = copy.deepcopy(self.storage_q) + res.storage_v = copy.deepcopy(self.storage_v) + + res.prod_p = copy.deepcopy(self.prod_p) + res.prod_q = copy.deepcopy(self.prod_q) + res.prod_v = copy.deepcopy(self.prod_v) + res.line_status = copy.deepcopy(self.line_status) + + res._pf_init = self._pf_init + res._nb_bus_before = self._nb_bus_before + + res.thermal_limit_a = copy.deepcopy(self.thermal_limit_a) + + res._number_true_line = self._number_true_line + res.dim_topo = self.dim_topo + res._topo_vect = copy.deepcopy(self._topo_vect) + + # function to rstore some information + res.__nb_bus_before = ( + self.__nb_bus_before + ) # number of substation in the powergrid + res.__nb_powerline = ( + self.__nb_powerline + ) # number of powerline (real powerline, not transformer) + res._init_bus_load = copy.deepcopy(self._init_bus_load) + res._init_bus_gen = copy.deepcopy(self._init_bus_gen) + res._init_bus_lor = copy.deepcopy(self._init_bus_lor) + res._init_bus_lex = copy.deepcopy(self._init_bus_lex) + res._get_vector_inj = copy.deepcopy(self._get_vector_inj) + res._big_topo_to_obj = copy.deepcopy(self._big_topo_to_obj) + res._big_topo_to_backend = copy.deepcopy(self._big_topo_to_backend) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FutureWarning) + res.__ppow_backend_initial_grid = self.__ppow_backend_initial_grid.deepcopy() + + res.tol = ( + self.tol + ) # this is NOT the pypowsybl tolerance !!!! this is used to check if a storage unit + # produce / absorbs anything + + # TODO storage doc (in grid2op rst) of the backend + res.theta_or = copy.deepcopy(self.theta_or) + res.theta_ex = copy.deepcopy(self.theta_ex) + res.load_theta = copy.deepcopy(self.load_theta) + res.gen_theta = copy.deepcopy(self.gen_theta) + res.storage_theta = copy.deepcopy(self.storage_theta) + + return res + + def close(self): + """ + + Called when the :class:`grid2op;Environment` has terminated, this function only reset the grid to a state + where it has not been loaded. + """ + del self._grid + self._grid = None + del self.__ppow_backend_initial_grid + self.__ppow_backend_initial_grid = None + + def _disconnect_line(self, id_): + """ + Function only use in unittest + """ + game_rules = RulesChecker() + self._topo_vect[self.line_or_pos_topo_vect[id_]] = -1 + self._topo_vect[self.line_ex_pos_topo_vect[id_]] = -1 + self.line_status[id_] = False + action_env_class = ActionSpace.init_grid(self) + action_env = action_env_class( + gridobj=self, legal_action=game_rules.legal_action + ) + action = action_env({"change_line_status": id_}) + bk_class = _BackendAction.init_grid(self) + bk_action = bk_class() + bk_action += action + self.apply_action(backendAction=bk_action) + + def _reconnect_line(self, id_): + """ + Function only use in unittest + """ + self._topo_vect[self.line_or_pos_topo_vect[id_]] = 1 + self._topo_vect[self.line_ex_pos_topo_vect[id_]] = 1 + self.line_status[id_] = True + game_rules = RulesChecker() + action_env_class = ActionSpace.init_grid(self) + action_env = action_env_class( + gridobj=self, legal_action=game_rules.legal_action + ) + action = action_env({"change_line_status": id_}) + bk_class = _BackendAction.init_grid(self) + bk_action = bk_class() + bk_action += action + self.apply_action(backendAction=bk_action) diff --git a/src/ScriptForSimpleUseCase.py b/src/ScriptForSimpleUseCase.py new file mode 100644 index 0000000..8e4dfd3 --- /dev/null +++ b/src/ScriptForSimpleUseCase.py @@ -0,0 +1,73 @@ +# Copyright (c) 2023, Artelys (https://www.artelys.com/) +# @author Rémi Tschupp +# 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 pypowsybl-grid2opbackend. It is mostly inspired by the development of the several backends from +# Grid2op framework. Some part of codes have been paste/copy. + +import grid2op +from grid2op.Agent import OneChangeThenNothing +from grid2op.PlotGrid import PlotMatplot, PlotPlotly +from grid2op.Runner import Runner +from src.Backend.powsybl_backend import PowsyblBackend + +def run_onechange(acts_dict_=None, nb_of_iterations=5, PlotHelper=PlotMatplot): + print(f"Run_onechange : " + str(grid2op.__file__)) + env = grid2op.make( + "data_test\l2rpn_case14_sandbox_Pypowsybl", + backend=PowsyblBackend(detailed_infos_for_cascading_failures=False), + ) + + env.set_max_iter(nb_of_iterations) + env.seed(42) + plot_helper = PlotHelper(env.observation_space) + for Agent_name, act_as_dict in acts_dict_.items(): + # generate the proper class that will perform the first action (encoded by {}) in acts_dict_ + agent_class = OneChangeThenNothing.gen_next(act_as_dict) + # start a runner with this agent + runner = Runner(**env.get_params_for_runner(), agentClass=agent_class) + # run 1 episode with it + *_, episode_data = runner.run(nb_episode=1, pbar=True, add_detailed_output=True)[0] + fig = plot_helper.plot_obs( + episode_data.observations[1], + line_info="p", + gen_info="p" + ) + + if isinstance(plot_helper, PlotPlotly): + fig.write_html(f"Observation n°{1} - Agent {Agent_name}.html") + fig.update_layout(title=f"Observation n°{1} - Agent {Agent_name}") + else: + fig.suptitle(f"Observation n°{1} - Agent {Agent_name}") + fig.savefig(f"Observation n°{1} - Agent {Agent_name}.svg") + + # you can do something with it now + for elem in episode_data.observations: + print(elem.is_alarm_illegal) + print(elem.topo_vect) + +if __name__ == "__main__": + + acts_dict_ = { + # "Donothing": {}, + # "OneChange_disconnection": {"set_line_status": [(0, -1)]}, + # "OneRedispatch": {"redispatch": [(1, -1.3)]} + # "OneChange_disconnection": {"set_line_status": [(0, -1)]}, + "OneChange_set_bus": { + "set_bus": { + "lines_or_id": [(3, 2), (4, 2)], + "loads_id": [(0, 2)], + "generators_id": [(1, 2)] + }, + # }, + # "OneChange_change_bus": { + # "change_bus": { + # "lines_or_id": [3, 4], + # "loads_id": [0], + # "generators_id": [1] + # }, + } + } + run_onechange(acts_dict_, nb_of_iterations=10) diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..bc45917 --- /dev/null +++ b/src/__init__.py @@ -0,0 +1,12 @@ +# Copyright (c) 2023, Artelys (https://www.artelys.com/) +# @author Rémi Tschupp +# 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 pypowsybl-grid2opbackend. + +__all__ = [ + "Backend", + "tests" +] \ No newline at end of file diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_p.csv b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_p.csv new file mode 100644 index 0000000..3a5b34d --- /dev/null +++ b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_p.csv @@ -0,0 +1,577 @@ +LOAD-2;LOAD-3;LOAD-4;LOAD-5;LOAD-6;LOAD-9;LOAD-10;LOAD-11;LOAD-12;LOAD-13;LOAD-14 +22.0;87.0;45.8;7.0;12.0;28.2;8.7;3.5;5.5;12.7;14.8 +22.1;89.0;45.9;6.9;12.3;28.4;8.8;3.4;5.5;12.9;15.2 +22.2;88.1;45.0;6.9;12.2;28.1;8.9;3.4;5.5;12.8;15.1 +22.1;87.5;44.8;6.9;12.0;28.6;8.9;3.4;5.4;12.8;15.1 +22.0;88.2;45.3;6.8;12.1;28.4;9.0;3.4;5.4;12.8;14.9 +22.1;87.8;45.0;6.9;12.1;28.7;8.8;3.4;5.3;12.7;15.2 +22.0;88.1;45.7;6.8;11.8;28.3;8.8;3.4;5.5;12.5;15.1 +21.3;87.6;44.6;7.0;11.9;27.9;8.6;3.3;5.3;12.3;14.9 +21.4;87.0;43.7;6.8;11.8;28.0;8.7;3.3;5.4;12.4;14.9 +21.3;85.6;44.1;6.6;11.7;27.9;8.4;3.3;5.2;12.5;15.1 +21.6;86.4;42.4;6.7;11.6;27.9;8.6;3.3;5.2;12.2;14.7 +21.4;84.9;43.3;6.6;11.5;27.3;8.5;3.2;5.1;12.1;15.0 +21.1;84.3;42.8;6.6;11.4;27.1;8.6;3.2;5.2;12.2;14.4 +21.1;84.2;42.8;6.5;11.3;27.1;8.4;3.2;5.1;11.6;14.6 +20.7;82.8;43.5;6.6;11.4;27.3;8.3;3.2;5.1;11.9;14.5 +20.7;85.8;42.1;6.5;11.5;27.1;8.4;3.2;5.1;11.9;14.6 +21.4;85.0;42.5;6.5;11.5;27.3;8.3;3.2;5.1;11.8;14.7 +20.8;86.6;42.5;6.5;11.5;27.7;8.4;3.2;5.0;11.9;14.6 +20.7;84.5;42.3;6.5;11.6;27.9;8.3;3.2;5.1;12.1;14.8 +20.4;85.8;42.1;6.3;11.5;27.7;8.3;3.2;5.1;11.7;14.6 +20.7;85.7;42.5;6.5;11.7;27.3;8.3;3.2;5.1;11.9;14.6 +20.3;84.2;42.8;6.6;11.4;27.5;8.3;3.3;5.2;12.0;14.9 +20.8;84.1;42.1;6.6;11.3;27.1;8.3;3.2;5.1;12.0;14.7 +20.5;84.9;43.2;6.5;11.4;27.5;8.3;3.2;5.1;11.7;14.7 +20.7;83.6;42.5;6.6;11.7;27.6;8.3;3.2;5.0;11.9;14.8 +20.7;84.2;42.1;6.5;11.6;27.8;8.3;3.2;5.1;11.8;15.0 +20.7;82.2;42.6;6.5;11.3;27.2;8.3;3.2;5.0;11.7;15.0 +20.4;84.3;42.8;6.4;11.5;27.0;8.4;3.2;5.0;11.7;14.7 +20.1;84.7;42.5;6.3;11.5;27.1;8.2;3.2;5.0;11.8;14.8 +20.4;83.6;42.4;6.4;11.4;27.2;8.3;3.1;5.0;11.7;14.9 +20.7;85.0;41.6;6.3;11.4;27.2;8.3;3.2;5.1;11.9;14.8 +20.5;84.1;41.9;6.3;11.4;27.0;8.3;3.1;5.0;11.4;14.6 +20.0;83.8;41.9;6.4;11.5;26.8;8.3;3.1;4.9;11.8;14.7 +20.6;83.0;42.0;6.3;11.2;26.9;8.1;3.2;4.9;11.2;14.5 +20.0;82.9;41.6;6.3;11.3;26.7;8.2;3.1;5.0;11.4;14.5 +19.5;82.8;41.3;6.1;11.3;26.5;8.2;3.0;4.8;11.3;14.2 +19.4;81.3;41.5;6.3;11.1;26.9;8.0;3.1;4.8;11.2;14.2 +19.6;82.5;40.5;6.2;11.0;26.8;8.1;3.0;4.8;11.1;14.2 +19.4;81.3;40.6;6.2;11.0;26.4;8.0;3.0;4.8;10.9;14.3 +19.5;80.6;41.1;6.1;11.0;26.4;7.9;3.0;4.8;11.0;14.2 +19.2;81.1;39.9;6.1;11.1;25.9;7.9;3.0;4.8;11.0;14.3 +19.1;80.4;40.3;6.1;10.9;26.5;7.8;3.0;4.8;11.2;14.3 +18.8;81.0;39.8;6.1;10.5;26.7;7.9;3.0;4.7;10.9;14.0 +19.3;80.8;40.1;6.2;10.8;25.8;7.8;3.0;4.6;11.0;14.0 +19.3;81.1;39.8;6.0;10.9;25.6;7.9;2.9;4.6;11.0;13.9 +19.3;80.8;40.2;5.9;10.8;25.9;7.8;3.0;4.6;10.8;14.0 +19.0;78.5;39.5;6.1;10.9;25.8;7.9;3.0;4.7;10.9;14.1 +19.0;78.1;38.9;5.9;10.6;25.8;7.8;3.0;4.6;10.6;13.6 +18.7;79.0;40.0;5.9;10.7;25.2;7.8;2.9;4.7;10.7;13.6 +18.8;79.0;39.3;6.1;10.4;25.8;7.8;2.9;4.6;10.4;13.6 +18.8;78.7;39.2;5.9;10.6;25.7;7.8;2.9;4.6;10.7;14.0 +18.4;78.3;38.8;5.8;10.5;25.7;7.6;2.9;4.5;10.7;13.7 +18.6;76.7;39.1;5.8;10.7;25.3;7.6;2.9;4.6;10.5;13.7 +18.3;78.4;39.0;6.0;10.5;25.5;7.6;2.9;4.5;10.4;14.0 +18.6;78.3;39.1;5.8;10.3;25.2;7.6;2.9;4.5;10.6;13.9 +19.0;78.7;38.8;5.9;10.5;25.7;7.6;2.9;4.4;10.6;13.9 +18.3;77.1;39.0;5.8;10.4;25.7;7.6;2.9;4.5;10.4;13.8 +18.5;76.5;38.5;6.0;10.7;25.3;7.6;2.9;4.5;10.3;13.7 +18.7;77.7;39.4;5.8;10.3;25.5;7.6;2.9;4.5;10.2;13.8 +18.8;77.1;39.2;5.8;10.3;24.9;7.5;2.9;4.4;10.4;13.8 +18.4;76.8;37.9;5.8;10.5;25.6;7.5;2.9;4.5;10.6;13.6 +18.6;77.6;38.9;5.7;10.4;25.0;7.6;2.9;4.5;10.5;13.7 +18.5;78.0;39.2;5.9;10.5;25.3;7.7;2.9;4.5;10.4;13.8 +18.4;77.5;39.2;5.7;10.4;25.8;7.7;2.8;4.4;10.4;13.7 +18.3;77.8;39.2;5.8;10.5;25.0;7.6;2.9;4.5;10.3;13.7 +18.6;77.5;38.1;5.9;10.6;25.6;7.7;2.9;4.5;10.4;13.6 +18.8;77.7;39.0;5.9;10.5;25.4;7.6;2.9;4.5;10.3;14.0 +18.5;77.2;39.4;5.8;10.7;26.0;7.7;2.9;4.5;10.4;13.9 +18.9;77.6;39.1;5.8;10.6;25.2;7.6;2.9;4.5;10.6;13.9 +18.8;74.9;39.2;5.9;10.5;26.0;7.5;3.0;4.5;10.6;13.7 +18.3;78.6;39.3;5.8;10.5;25.7;7.6;3.0;4.5;10.5;13.6 +18.6;77.7;38.2;5.9;10.5;25.8;7.8;3.0;4.5;10.4;13.9 +18.4;77.1;38.8;5.8;10.4;26.0;7.6;3.0;4.6;10.6;13.9 +18.6;77.4;39.0;5.9;10.5;25.6;7.7;2.9;4.5;10.7;13.5 +18.4;79.6;38.9;5.8;10.6;26.0;7.7;3.0;4.5;10.4;13.5 +18.6;78.2;39.2;5.9;10.4;25.9;7.7;3.0;4.6;10.6;13.7 +18.9;77.9;38.6;5.8;10.5;26.0;7.7;2.9;4.6;10.7;14.0 +18.4;78.2;39.3;5.9;10.4;26.3;7.6;3.0;4.5;10.6;13.8 +18.8;78.5;39.3;5.9;10.6;26.1;7.8;3.0;4.5;10.5;13.9 +18.8;77.8;39.8;5.8;10.8;26.2;7.8;3.0;4.7;10.6;13.7 +18.9;77.6;38.8;5.9;10.6;25.9;7.8;3.0;4.7;10.7;14.1 +18.5;77.8;39.4;5.9;10.6;26.5;7.7;2.9;4.6;10.7;13.9 +18.8;78.4;39.5;5.9;10.6;25.7;7.7;3.0;4.7;10.6;13.7 +18.7;79.8;40.3;5.9;10.6;26.3;7.8;3.0;4.7;10.5;14.0 +19.0;78.8;39.2;5.9;10.7;26.4;7.9;3.0;4.6;10.7;13.8 +18.8;78.8;39.2;5.9;10.6;26.3;7.7;3.1;4.6;10.5;13.9 +18.8;78.5;40.7;6.0;10.6;25.6;7.8;3.0;4.6;10.4;14.0 +18.7;78.9;40.0;5.9;10.6;25.8;7.9;3.0;4.6;10.4;13.9 +18.7;76.5;39.6;6.0;10.7;26.5;7.9;3.0;4.6;10.6;13.8 +18.7;79.2;40.1;6.1;10.6;26.5;7.9;3.0;4.6;10.4;14.0 +18.9;78.1;40.0;6.0;10.7;26.4;7.8;3.0;4.7;10.6;13.9 +18.9;79.1;40.3;6.0;10.7;26.7;7.9;3.0;4.7;10.7;13.9 +18.9;79.4;40.0;6.0;10.6;27.1;7.7;3.0;4.7;10.8;13.8 +19.0;79.8;40.7;5.9;10.7;26.8;7.8;3.0;4.7;10.5;13.8 +18.9;78.0;40.3;6.0;10.8;26.6;7.8;3.0;4.7;10.9;14.0 +19.0;80.4;40.6;6.0;10.6;26.8;7.8;3.0;4.7;10.6;14.2 +18.9;78.3;40.4;6.0;10.7;26.6;7.9;3.0;4.7;10.8;14.1 +19.2;79.3;40.3;6.0;10.6;26.6;7.8;3.0;4.7;10.9;14.0 +19.3;79.6;40.2;6.0;10.6;26.9;7.9;3.1;4.8;10.7;14.1 +19.3;80.1;41.0;6.1;10.8;26.9;8.0;3.1;4.7;10.9;14.2 +19.2;79.9;41.5;6.0;10.9;27.1;7.9;3.0;4.8;10.9;14.1 +19.2;79.9;39.5;6.1;10.7;26.8;7.9;3.1;4.8;11.0;14.1 +19.6;80.2;40.7;6.1;10.6;27.0;8.0;3.1;4.8;11.1;14.0 +19.2;79.1;41.4;6.2;10.7;26.8;7.9;3.1;4.9;11.1;14.3 +19.2;80.5;41.4;6.0;10.8;27.5;8.0;3.1;4.9;11.1;14.3 +19.2;79.5;41.4;6.4;10.9;27.2;7.9;3.2;4.9;11.3;14.1 +19.2;80.0;41.1;6.3;11.0;27.2;8.0;3.1;4.9;11.4;14.3 +18.9;81.1;40.7;6.2;11.0;27.1;8.0;3.2;5.0;11.3;14.2 +19.8;80.1;41.9;6.2;11.0;27.1;8.0;3.2;5.0;11.1;14.3 +19.7;80.7;42.1;6.3;11.1;28.0;8.1;3.2;5.0;11.2;14.2 +19.8;80.2;41.2;6.2;10.9;27.6;8.2;3.2;5.1;11.3;14.2 +19.6;81.3;42.1;6.3;10.9;27.9;8.0;3.1;5.1;11.3;14.2 +19.9;81.4;41.8;6.3;11.1;28.1;8.2;3.2;5.0;11.5;14.5 +19.8;83.0;42.5;6.4;10.9;27.9;8.3;3.2;5.0;11.4;14.7 +19.9;82.5;42.3;6.4;11.1;28.0;8.2;3.3;5.1;11.7;14.7 +20.3;84.0;42.2;6.6;11.2;27.5;8.2;3.3;5.1;11.6;14.5 +20.5;83.6;43.1;6.4;11.2;27.9;8.2;3.3;5.0;11.8;14.4 +19.8;84.3;43.4;6.6;11.2;28.1;8.2;3.3;5.2;11.5;14.9 +20.1;83.2;43.2;6.5;11.3;28.0;8.4;3.2;5.1;11.7;14.6 +19.6;84.1;43.0;6.6;11.3;27.8;8.3;3.3;5.0;11.6;14.6 +20.0;84.3;43.9;6.6;11.2;27.8;8.5;3.4;5.2;11.7;14.8 +20.4;84.8;43.2;6.6;11.4;28.1;8.2;3.3;5.3;11.9;14.7 +20.4;83.4;43.3;6.6;11.1;27.8;8.4;3.4;5.2;11.8;15.1 +20.4;84.7;43.2;6.7;11.5;27.7;8.4;3.4;5.2;11.7;14.6 +20.6;86.0;43.8;6.7;11.4;27.7;8.4;3.4;5.3;11.7;14.7 +20.9;84.4;43.6;6.7;11.4;27.4;8.3;3.4;5.2;12.0;14.8 +20.8;84.5;43.1;6.7;11.4;27.6;8.4;3.4;5.3;11.7;14.8 +20.4;84.2;44.0;6.8;11.3;28.3;8.3;3.4;5.3;11.7;14.7 +21.1;85.6;44.1;6.9;11.5;28.1;8.3;3.4;5.3;12.0;15.2 +20.8;85.8;43.7;6.7;11.4;27.8;8.2;3.4;5.3;11.9;14.7 +21.0;83.5;43.8;6.8;11.4;27.8;8.4;3.4;5.2;12.0;14.7 +21.0;86.0;44.0;6.8;11.4;26.9;8.4;3.4;5.4;11.9;14.7 +20.9;85.6;44.1;6.9;11.4;27.9;8.3;3.4;5.3;11.9;14.8 +21.0;84.4;44.6;6.8;11.6;27.7;8.4;3.4;5.4;12.0;14.7 +21.0;84.5;44.2;6.9;11.4;27.7;8.4;3.4;5.3;12.0;14.8 +21.4;84.9;44.1;6.9;11.5;27.7;8.2;3.5;5.3;12.1;14.7 +21.3;86.1;44.8;6.9;11.5;27.6;8.2;3.5;5.4;11.9;14.6 +21.1;86.1;44.2;6.9;11.5;27.6;8.3;3.5;5.3;12.1;14.5 +20.5;86.5;43.7;6.9;11.3;27.5;8.5;3.5;5.4;12.0;14.7 +21.0;84.6;44.3;6.9;11.5;27.4;8.3;3.4;5.3;11.9;14.9 +21.2;85.9;44.5;7.0;11.5;27.3;8.3;3.5;5.4;12.3;14.6 +20.9;86.0;43.8;6.9;11.3;27.7;8.6;3.5;5.4;12.0;14.8 +20.5;85.8;43.9;6.9;11.5;27.2;8.5;3.5;5.4;12.2;15.0 +21.3;87.2;43.5;6.9;11.5;27.6;8.2;3.4;5.4;11.9;14.6 +21.5;84.4;43.6;7.0;11.5;27.5;8.3;3.5;5.3;12.0;14.8 +21.5;86.4;44.2;7.0;11.5;27.9;8.2;3.5;5.5;12.1;14.7 +21.3;86.4;44.2;7.0;11.6;26.8;8.4;3.5;5.4;12.3;14.8 +21.5;87.1;44.7;7.0;11.6;27.4;8.4;3.5;5.4;11.9;14.6 +21.1;87.0;44.4;7.0;11.6;26.7;8.4;3.6;5.5;12.4;14.4 +21.1;85.7;44.5;7.2;11.7;27.0;8.3;3.5;5.5;12.5;14.3 +21.5;86.6;44.3;7.1;11.5;27.6;8.4;3.4;5.5;12.1;14.7 +21.3;86.9;44.9;7.0;11.7;27.4;8.5;3.6;5.4;12.4;14.5 +21.4;86.2;44.1;7.1;11.5;27.3;8.4;3.5;5.5;12.2;14.8 +21.9;87.4;44.6;7.3;11.7;27.7;8.3;3.5;5.5;12.3;14.6 +21.3;86.4;44.7;7.2;11.5;27.2;8.4;3.5;5.4;12.4;14.3 +21.5;87.1;44.2;7.2;11.6;27.3;8.3;3.6;5.5;12.2;14.4 +21.5;85.2;43.8;7.1;11.5;27.1;8.3;3.5;5.4;12.3;14.7 +21.4;86.2;44.5;7.1;11.5;27.5;8.2;3.5;5.5;12.4;14.4 +21.5;86.0;44.3;7.2;11.4;27.4;8.4;3.6;5.4;12.3;14.4 +21.0;84.5;43.4;7.0;11.4;26.8;8.3;3.5;5.4;12.4;14.6 +21.4;85.0;44.4;7.0;11.2;26.7;8.3;3.5;5.4;12.0;14.5 +21.2;85.1;43.9;7.0;11.4;26.5;8.1;3.5;5.3;12.1;14.2 +21.2;84.9;42.8;6.8;11.0;26.3;8.0;3.5;5.3;11.9;14.2 +20.3;82.7;42.2;6.8;11.0;25.7;7.9;3.4;5.2;11.8;13.8 +20.7;83.5;42.5;6.8;11.1;25.3;8.0;3.4;5.2;11.7;13.9 +20.5;82.5;41.9;6.7;10.9;25.5;7.8;3.4;5.1;11.7;13.9 +20.4;82.6;41.6;6.8;10.9;25.3;7.9;3.4;5.2;11.6;13.8 +20.1;82.7;42.6;6.8;10.9;25.3;8.1;3.3;5.1;11.7;13.6 +20.0;80.6;41.4;6.7;10.6;25.1;7.9;3.3;5.1;11.4;13.7 +20.3;80.9;41.5;6.7;10.7;24.8;7.8;3.3;5.1;11.2;13.3 +20.4;81.9;41.4;6.6;10.7;24.9;7.7;3.3;5.1;11.6;13.4 +20.3;80.8;41.4;6.6;10.7;24.9;7.8;3.3;5.1;11.2;13.5 +19.8;82.1;40.7;6.7;10.5;25.1;7.9;3.3;5.0;11.2;13.5 +20.0;81.1;40.9;6.5;10.4;24.5;7.8;3.3;5.0;11.1;13.3 +19.8;80.5;40.5;6.6;10.5;24.3;7.5;3.3;5.0;11.2;13.1 +19.8;78.6;40.8;6.5;10.6;24.4;7.6;3.3;5.0;11.1;13.2 +19.7;79.3;41.0;6.6;10.3;24.2;7.6;3.2;5.0;10.9;13.1 +19.7;79.7;40.1;6.5;10.5;23.9;7.6;3.2;4.9;10.8;12.8 +19.5;80.6;39.6;6.5;10.3;24.0;7.4;3.2;4.9;10.8;13.1 +19.5;78.8;39.7;6.5;10.3;24.0;7.4;3.2;4.8;10.9;13.0 +19.4;79.2;39.6;6.4;10.3;23.5;7.4;3.2;4.8;10.9;12.6 +19.3;80.2;38.4;6.4;10.0;23.4;7.3;3.1;4.8;10.7;12.8 +19.2;78.0;39.4;6.4;10.2;23.7;7.3;3.1;4.7;10.7;12.7 +19.1;77.9;38.8;6.4;10.0;23.6;7.3;3.1;4.7;10.7;12.6 +19.0;78.0;39.3;6.3;10.3;23.0;7.3;3.2;4.8;10.6;12.5 +19.2;79.2;39.6;6.5;10.2;23.1;7.3;3.1;4.9;10.9;12.8 +18.9;78.0;38.2;6.3;9.9;23.4;7.2;3.1;4.9;10.5;12.6 +18.8;76.4;38.7;6.4;10.0;23.1;7.1;3.2;4.8;10.7;12.5 +18.8;77.7;39.6;6.3;9.8;23.1;7.2;3.1;4.8;10.4;12.3 +19.0;78.0;38.5;6.3;9.9;23.0;7.2;3.1;4.6;10.3;12.5 +18.7;77.5;38.7;6.2;10.0;23.1;7.1;3.1;4.7;10.5;12.5 +19.0;77.9;37.9;6.3;9.9;23.2;7.2;3.1;4.8;10.4;12.4 +18.9;79.3;38.0;6.2;9.8;22.5;7.1;3.1;4.7;10.3;12.2 +18.5;76.5;38.3;6.2;9.9;22.5;7.1;3.1;4.7;10.6;12.4 +19.1;76.5;38.9;6.2;9.8;22.7;7.1;3.1;4.7;10.4;12.5 +18.8;75.8;38.5;6.3;9.7;23.0;7.2;3.1;4.7;10.2;12.4 +18.5;76.8;38.9;6.3;9.5;22.6;7.1;3.1;4.8;10.3;12.4 +18.4;77.2;38.0;6.2;9.8;22.9;7.0;3.1;4.7;10.2;12.3 +18.5;76.0;38.5;6.2;9.9;22.9;7.2;3.1;4.7;10.1;12.3 +18.5;78.0;38.6;6.2;9.7;22.7;6.9;3.0;4.6;10.3;12.4 +18.6;76.9;38.4;6.3;9.8;22.8;7.0;3.1;4.6;10.1;12.3 +18.6;78.5;38.0;6.3;9.6;22.6;7.1;3.0;4.7;10.3;12.5 +18.4;76.6;38.3;6.3;9.6;22.7;6.9;3.0;4.6;10.1;12.4 +18.4;77.9;38.3;6.2;9.8;22.8;7.1;3.1;4.6;10.1;12.3 +18.3;76.9;38.0;6.2;9.6;22.5;6.9;3.1;4.6;10.1;12.3 +18.7;78.1;38.2;6.3;9.7;22.6;6.9;3.1;4.7;10.1;12.4 +18.4;77.7;37.8;6.2;9.8;22.7;7.0;3.0;4.6;10.2;12.5 +18.6;78.1;37.8;6.3;9.9;22.8;7.1;3.0;4.7;10.1;12.4 +18.9;78.0;38.5;6.3;9.6;23.0;7.0;3.0;4.8;10.1;12.3 +18.7;78.5;38.8;6.2;9.8;22.7;7.1;3.0;4.7;10.4;12.6 +18.9;79.3;39.2;6.3;9.7;22.7;7.0;3.0;4.7;10.3;12.5 +19.3;79.6;38.8;6.2;9.8;23.3;7.1;3.0;4.7;10.2;12.7 +19.2;81.3;39.6;6.4;9.9;23.0;7.3;3.1;4.8;10.4;12.7 +19.6;80.0;38.9;6.3;9.9;23.1;7.2;3.0;4.8;10.4;12.7 +19.8;81.2;38.9;6.4;9.8;23.5;7.3;3.1;4.7;10.5;12.8 +19.7;81.8;39.0;6.4;9.8;23.4;7.1;3.1;4.8;10.5;13.1 +19.7;83.9;40.8;6.4;10.0;23.7;7.3;3.1;4.9;10.3;13.3 +20.0;83.7;41.4;6.5;9.9;23.9;7.2;3.1;4.8;10.4;13.4 +20.0;85.3;41.4;6.6;10.1;24.4;7.4;3.1;4.9;10.6;13.5 +20.0;82.6;41.6;6.6;10.4;24.2;7.5;3.1;5.0;10.6;13.6 +20.0;84.4;42.3;6.8;10.5;24.9;7.5;3.1;4.9;10.7;13.7 +20.4;86.6;42.9;6.8;10.6;24.4;7.5;3.1;4.9;10.9;13.9 +20.2;85.9;43.6;6.9;10.6;25.4;7.6;3.2;5.1;10.8;13.9 +20.5;86.7;43.2;7.0;10.8;25.5;7.7;3.2;5.0;11.1;14.2 +20.3;85.9;42.5;7.0;10.8;26.1;7.9;3.3;5.1;11.3;14.1 +20.8;86.7;43.9;7.0;10.9;26.4;8.0;3.3;5.2;11.4;14.2 +20.6;88.1;44.0;7.1;11.0;26.5;8.2;3.4;5.3;11.2;14.2 +21.1;87.7;43.3;7.0;11.1;26.9;8.3;3.4;5.4;11.6;14.2 +21.0;87.5;44.7;7.2;11.2;27.2;8.2;3.4;5.4;11.5;14.3 +21.0;87.6;45.2;7.2;11.2;27.4;8.4;3.4;5.5;11.5;14.3 +21.1;87.1;45.4;7.3;11.3;27.7;8.5;3.5;5.5;11.8;14.5 +21.4;87.9;44.4;7.4;11.3;27.8;8.4;3.5;5.6;11.9;14.4 +20.9;87.4;44.8;7.2;11.3;27.8;8.6;3.6;5.8;12.1;14.3 +20.6;90.0;44.6;7.4;11.4;28.5;8.6;3.6;5.6;12.5;14.6 +21.1;88.3;44.6;7.1;11.6;28.2;8.7;3.5;5.8;12.5;14.4 +20.8;88.0;45.2;7.2;11.5;28.4;8.7;3.6;5.9;12.7;14.4 +21.0;89.4;45.7;7.3;11.4;28.4;8.7;3.6;5.8;12.5;14.4 +21.1;88.7;44.8;7.3;11.3;28.4;8.7;3.6;5.7;12.6;14.6 +20.7;89.9;45.2;7.2;11.4;28.0;8.8;3.6;5.9;12.9;14.2 +21.0;89.7;45.2;7.3;11.5;28.3;8.6;3.6;5.8;12.7;14.6 +20.8;88.7;45.2;7.2;11.4;28.4;8.5;3.6;5.8;12.5;14.6 +21.0;88.7;44.5;7.1;11.3;28.4;8.5;3.6;5.7;13.0;14.5 +20.5;87.4;44.5;7.3;11.1;28.2;8.6;3.6;5.8;12.7;14.5 +20.8;87.7;45.0;7.2;11.3;27.9;8.5;3.6;5.7;12.6;14.3 +20.7;87.2;44.8;7.2;11.1;27.8;8.4;3.5;5.8;12.5;14.6 +20.4;87.7;44.3;7.2;11.3;27.7;8.5;3.5;5.7;12.3;14.7 +20.6;87.9;44.2;7.0;11.1;27.6;8.4;3.5;5.7;12.4;14.4 +20.5;85.2;44.4;7.0;11.0;27.9;8.4;3.5;5.6;12.4;14.3 +20.7;85.3;43.7;7.1;11.3;27.3;8.3;3.5;5.7;12.5;14.4 +20.8;86.8;44.1;7.0;11.2;27.3;8.5;3.6;5.6;12.4;14.3 +21.0;85.7;44.5;6.9;11.0;27.5;8.4;3.5;5.7;12.3;14.1 +20.5;87.2;43.7;6.9;11.1;27.3;8.2;3.5;5.6;12.2;13.9 +20.4;87.1;44.1;7.1;10.9;27.2;8.4;3.5;5.5;12.3;14.1 +20.3;86.5;43.2;7.0;10.9;27.5;8.3;3.4;5.5;12.2;14.2 +20.4;86.1;44.4;7.0;10.9;27.6;8.2;3.5;5.4;12.0;14.3 +20.4;87.2;43.7;6.9;11.0;27.3;8.3;3.5;5.5;12.0;14.1 +20.5;84.9;43.6;6.9;10.9;26.8;8.3;3.4;5.5;12.1;14.1 +20.0;84.8;43.1;6.9;10.9;27.2;8.2;3.4;5.6;12.3;14.2 +19.9;84.7;43.2;7.0;10.9;27.2;8.1;3.4;5.5;12.1;14.0 +20.1;83.4;44.1;7.0;10.7;27.1;8.2;3.4;5.4;12.0;14.2 +19.8;83.6;43.3;6.9;10.8;26.9;8.2;3.4;5.5;11.6;14.0 +19.8;83.3;43.1;6.9;10.7;26.5;8.1;3.4;5.3;11.7;14.0 +20.1;84.8;42.7;6.7;10.8;27.1;8.1;3.3;5.4;11.9;14.1 +20.1;83.1;42.9;6.8;10.7;27.0;8.1;3.4;5.4;11.9;14.1 +19.5;83.5;42.8;6.9;10.7;26.6;8.1;3.3;5.3;11.7;13.8 +19.9;83.3;42.0;6.8;10.6;26.7;8.1;3.3;5.3;11.8;13.7 +19.6;84.5;42.6;6.8;10.6;26.7;8.0;3.3;5.5;11.7;13.7 +19.6;84.2;42.0;6.7;10.8;27.0;8.0;3.3;5.2;11.6;13.9 +19.7;84.2;42.9;6.6;10.7;26.8;7.9;3.3;5.3;11.9;14.1 +19.7;83.3;42.9;6.8;10.6;27.3;8.0;3.3;5.4;11.8;13.5 +19.7;83.9;42.4;6.8;10.8;26.7;8.0;3.3;5.3;11.8;14.2 +19.8;85.2;44.0;6.9;10.6;26.9;8.0;3.3;5.3;12.0;14.2 +20.2;85.8;43.9;6.9;10.8;27.4;8.2;3.4;5.6;12.1;14.1 +20.4;85.7;44.2;6.9;10.9;27.5;8.3;3.4;5.6;12.0;14.7 +20.2;88.0;43.8;6.9;11.2;27.7;8.4;3.4;5.6;12.3;14.5 +20.6;85.5;44.7;7.1;11.3;27.7;8.4;3.4;5.6;12.2;14.7 +20.6;87.2;45.7;7.1;11.2;28.5;8.4;3.5;5.7;12.5;14.8 +20.9;88.4;45.1;7.3;11.5;28.4;8.6;3.5;5.8;12.8;14.5 +20.8;88.3;44.9;7.1;11.4;28.9;8.5;3.5;5.7;12.7;14.7 +20.9;88.5;45.5;7.2;11.3;29.0;8.5;3.5;5.7;12.6;14.6 +20.7;86.8;45.2;7.1;11.3;28.2;8.6;3.4;5.8;12.8;14.6 +20.5;89.6;44.5;7.2;11.3;28.6;8.5;3.5;5.6;12.6;14.7 +20.8;88.9;45.2;7.0;11.3;29.0;8.5;3.5;5.8;12.6;14.7 +20.8;87.0;44.5;7.1;11.2;28.4;8.4;3.5;5.8;12.7;14.1 +20.8;87.6;45.6;7.1;11.2;28.5;8.6;3.5;5.7;12.6;14.7 +20.7;89.7;44.6;7.2;11.2;28.3;8.5;3.5;5.7;12.7;14.7 +20.3;88.7;46.4;7.3;11.3;28.3;8.4;3.5;5.7;12.6;14.5 +20.9;88.3;45.8;7.2;11.3;28.3;8.6;3.5;5.7;12.6;14.8 +20.8;88.4;45.2;7.2;11.1;28.0;8.5;3.5;5.8;12.6;14.8 +21.3;86.6;45.6;7.0;11.3;29.3;8.6;3.5;5.7;12.4;14.9 +21.0;88.3;45.8;7.2;11.3;28.7;8.4;3.5;5.8;12.9;14.7 +20.8;88.8;45.1;7.1;11.3;28.6;8.5;3.5;5.6;12.7;14.8 +21.1;88.5;45.9;7.3;11.2;28.2;8.6;3.4;5.7;12.6;14.8 +20.9;87.9;45.5;7.1;11.2;28.8;8.5;3.4;5.8;12.5;14.7 +20.8;86.7;45.0;7.1;11.1;28.1;8.5;3.4;5.6;12.4;14.5 +20.4;87.8;44.9;7.3;11.1;28.1;8.3;3.4;5.7;12.3;14.6 +20.2;87.2;43.5;7.1;11.1;27.8;8.3;3.4;5.6;12.2;14.8 +20.3;86.4;44.1;7.0;10.8;27.7;8.4;3.4;5.4;12.0;14.3 +20.2;86.1;43.9;6.9;11.0;27.4;8.2;3.3;5.5;12.0;14.3 +19.7;84.6;43.4;6.9;10.9;27.2;8.3;3.3;5.5;11.8;14.4 +20.2;85.8;43.7;7.0;10.6;27.0;8.2;3.3;5.4;12.0;14.0 +19.9;84.4;42.9;6.8;10.7;27.0;8.1;3.3;5.5;11.7;14.0 +19.7;86.1;42.8;6.8;10.7;26.8;8.1;3.2;5.3;11.7;14.2 +19.7;85.4;43.4;6.8;10.6;27.3;8.1;3.3;5.3;11.6;14.1 +19.6;86.8;43.5;6.9;10.5;27.1;8.0;3.3;5.4;11.6;14.2 +19.9;84.8;43.5;6.7;10.8;27.6;8.3;3.3;5.4;11.7;14.3 +19.8;84.5;43.3;6.9;10.7;26.7;8.1;3.2;5.3;11.8;14.3 +20.1;86.7;43.2;6.9;10.6;27.3;8.1;3.3;5.5;11.6;14.5 +19.7;83.6;42.9;6.8;10.8;27.4;8.0;3.3;5.3;11.8;14.5 +20.1;84.6;42.9;6.8;10.7;27.3;8.1;3.3;5.4;11.7;14.2 +20.0;82.9;43.3;6.8;10.9;27.6;7.9;3.2;5.3;11.6;14.2 +20.1;85.3;43.6;6.8;10.8;26.8;8.0;3.2;5.3;11.6;14.2 +20.3;84.6;42.7;6.8;10.8;26.8;8.0;3.3;5.4;11.5;14.5 +19.8;84.2;43.4;6.9;10.6;26.8;8.1;3.3;5.4;11.7;14.6 +20.0;85.0;43.8;6.8;10.7;27.2;8.0;3.2;5.3;11.5;14.4 +20.0;84.9;43.3;6.9;10.7;27.0;8.0;3.2;5.3;11.6;14.5 +20.0;84.5;42.7;6.8;10.7;27.1;7.9;3.2;5.3;11.4;14.3 +19.9;85.4;43.1;6.8;10.7;27.3;8.0;3.3;5.3;11.6;14.4 +19.5;82.6;43.3;6.8;10.7;27.0;8.0;3.2;5.3;11.5;14.5 +19.9;84.2;43.0;6.8;10.7;26.8;8.1;3.3;5.3;11.3;14.5 +19.5;83.3;42.8;6.7;10.5;27.2;8.0;3.2;5.2;11.5;14.2 +19.8;84.6;43.4;6.8;10.5;26.3;7.9;3.1;5.3;11.3;14.0 +19.8;82.2;42.3;6.8;10.3;27.0;7.9;3.2;5.2;11.2;14.1 +19.5;83.9;41.8;6.8;10.5;26.2;7.8;3.1;5.2;11.2;14.0 +19.4;82.0;41.6;6.7;10.3;26.1;7.9;3.1;5.1;11.0;14.1 +19.1;83.3;41.1;6.6;10.1;26.3;7.9;3.1;5.1;11.0;14.2 +19.5;81.9;41.4;6.4;10.2;25.9;7.8;3.1;5.1;10.8;13.7 +19.1;82.1;42.8;6.6;10.4;25.8;7.7;3.0;5.1;11.1;13.9 +18.9;81.4;40.8;6.5;10.4;25.6;7.7;3.1;5.1;10.9;13.9 +18.9;80.0;41.0;6.4;10.4;26.1;7.7;3.0;5.0;11.0;13.9 +19.0;80.8;41.1;6.6;10.1;25.7;7.7;3.0;5.1;11.0;14.0 +19.3;79.5;41.6;6.5;10.2;25.8;7.7;3.1;5.0;10.8;13.7 +19.1;81.4;41.0;6.5;10.2;25.4;7.6;3.0;4.9;10.8;13.9 +18.9;79.3;40.6;6.4;10.1;25.4;7.5;3.0;4.9;10.9;13.9 +18.9;79.3;40.1;6.3;9.8;25.3;7.5;3.0;5.0;10.6;13.7 +18.8;79.8;39.5;6.3;10.1;25.9;7.5;3.1;5.0;10.9;13.6 +19.0;79.4;40.6;6.4;9.9;25.4;7.5;3.0;5.0;10.6;13.5 +18.8;78.8;40.0;6.4;10.1;25.1;7.5;3.0;4.9;10.7;13.5 +18.5;79.0;40.2;6.5;9.9;25.2;7.6;3.0;5.0;10.6;13.5 +18.8;79.4;40.4;6.4;9.8;24.9;7.4;3.0;5.0;10.6;13.7 +18.7;79.6;40.0;6.4;10.1;25.5;7.5;3.0;4.9;10.3;13.8 +18.9;77.7;39.6;6.5;9.9;25.4;7.4;3.1;5.1;10.6;13.3 +18.7;78.9;40.0;6.5;9.9;24.8;7.4;3.0;5.0;10.7;13.8 +18.8;80.0;40.3;6.4;9.9;25.3;7.5;3.1;5.0;10.6;13.6 +18.4;78.5;39.8;6.4;9.9;25.8;7.6;3.0;5.0;10.8;13.4 +18.7;78.8;39.9;6.5;10.0;25.3;7.6;3.0;5.1;10.7;13.9 +18.6;79.9;39.3;6.4;10.0;25.0;7.5;2.9;5.0;10.6;13.6 +19.1;79.2;40.4;6.5;10.1;25.4;7.3;3.1;5.0;10.8;13.4 +18.9;79.4;40.1;6.5;9.8;25.4;7.6;3.0;5.0;10.7;13.6 +19.0;79.4;40.2;6.3;10.0;25.8;7.6;3.0;5.1;11.0;13.5 +18.6;79.4;40.3;6.5;10.0;24.9;7.5;3.0;5.1;10.8;13.5 +19.0;79.3;40.7;6.6;10.1;25.8;7.5;3.1;5.1;11.0;13.8 +19.1;79.5;40.6;6.5;10.3;26.1;7.7;3.1;5.0;11.1;13.6 +19.0;81.7;40.5;6.5;10.2;26.1;7.8;3.2;5.3;11.0;13.7 +19.3;82.1;41.1;6.7;10.3;26.5;7.7;3.2;5.2;11.2;14.0 +19.3;82.3;41.0;6.7;10.5;26.5;8.0;3.1;5.3;11.4;13.8 +19.6;81.5;42.7;6.7;10.3;26.3;7.9;3.3;5.3;11.2;14.0 +19.5;81.5;41.9;6.8;10.5;26.5;8.0;3.2;5.4;11.3;13.8 +19.6;83.2;42.6;6.9;10.6;26.6;8.0;3.3;5.5;11.7;14.1 +19.4;82.4;42.3;6.8;10.3;26.8;8.1;3.3;5.5;11.7;14.0 +19.8;82.2;43.0;6.8;10.8;26.9;8.1;3.3;5.5;11.4;13.9 +19.4;83.8;42.8;6.9;10.8;27.0;8.2;3.3;5.6;11.6;14.2 +19.8;83.9;42.9;7.0;10.7;27.6;8.3;3.3;5.6;11.9;14.2 +20.0;84.2;42.9;7.1;10.6;27.7;8.2;3.3;5.7;12.2;14.6 +20.4;84.9;43.9;7.2;10.9;28.0;8.5;3.4;5.8;12.1;14.6 +20.5;85.5;44.5;7.2;11.1;28.5;8.5;3.4;5.8;12.5;14.3 +20.5;85.9;44.8;7.4;11.1;28.4;8.6;3.4;6.0;12.4;14.5 +21.4;87.7;45.7;7.4;11.2;28.7;8.6;3.6;6.0;12.6;14.7 +20.9;88.0;45.5;7.4;11.6;28.8;8.8;3.6;6.1;12.8;15.1 +21.0;88.0;45.0;7.5;11.2;29.0;8.8;3.6;6.1;12.7;14.8 +21.1;87.2;45.9;7.5;11.3;29.3;8.9;3.7;6.1;12.9;15.1 +21.4;89.1;45.9;7.7;11.7;30.1;9.2;3.6;6.2;13.0;15.2 +21.2;90.6;47.5;7.7;11.4;29.3;9.1;3.7;6.2;13.0;14.9 +21.8;90.7;47.1;7.7;11.4;30.2;9.2;3.7;6.3;13.1;15.4 +22.0;90.1;48.3;7.7;11.6;30.2;9.2;3.8;6.2;13.2;15.9 +21.7;91.5;48.4;7.8;11.6;30.7;9.3;3.8;6.2;13.4;15.5 +22.2;92.9;48.4;7.8;11.8;30.4;9.3;3.8;6.4;13.5;15.4 +22.1;93.8;48.4;7.8;12.0;30.3;9.3;3.8;6.4;13.5;15.7 +22.2;93.7;49.0;8.0;12.1;30.4;9.2;3.8;6.5;13.6;15.9 +22.7;91.9;49.5;8.2;12.1;30.8;9.5;3.8;6.4;13.7;15.8 +22.3;94.6;49.4;8.2;12.0;31.0;9.5;3.8;6.5;13.7;16.1 +22.6;93.8;49.8;8.1;12.1;30.9;9.5;3.8;6.5;13.7;16.1 +22.6;94.9;49.4;8.2;12.0;31.3;9.5;3.9;6.4;13.7;15.9 +22.8;96.3;49.8;8.2;12.3;30.8;9.4;3.7;6.5;13.9;16.0 +22.9;96.4;48.8;8.3;12.1;31.4;9.5;3.9;6.5;13.8;15.7 +23.2;95.8;50.2;8.1;12.1;31.4;9.6;3.9;6.5;13.9;15.9 +23.2;96.0;49.6;8.3;12.1;31.7;9.4;3.9;6.7;13.9;16.0 +23.1;95.8;48.9;8.2;12.3;31.5;9.6;3.9;6.6;14.0;16.3 +23.2;93.9;50.6;8.3;12.1;31.5;9.5;3.9;6.5;13.9;16.1 +23.1;94.9;50.4;8.1;12.3;32.1;9.6;3.9;6.7;14.2;16.0 +23.2;94.6;49.4;8.3;12.3;31.5;9.6;3.9;6.6;13.9;15.7 +22.9;95.0;49.2;8.2;12.4;31.3;9.6;3.9;6.7;14.3;16.3 +22.7;96.5;50.1;8.2;12.1;31.5;9.5;3.9;6.6;14.3;15.8 +22.9;95.2;49.1;7.9;12.2;31.4;9.6;3.9;6.6;14.3;16.1 +23.1;94.2;49.0;8.1;12.3;31.9;9.7;3.9;6.6;14.0;16.1 +22.9;94.8;50.2;8.2;12.2;31.7;9.7;3.8;6.6;14.3;16.0 +22.8;94.1;49.8;8.3;12.3;32.0;9.6;3.9;6.5;14.0;15.8 +23.0;94.6;49.5;8.1;12.5;31.5;9.7;4.0;6.6;14.3;15.9 +23.0;94.8;49.8;8.2;11.9;31.7;9.7;3.9;6.5;14.1;15.8 +22.7;93.1;49.1;8.2;12.1;31.7;9.7;4.0;6.5;14.3;15.8 +22.7;93.5;49.5;8.1;12.3;31.8;9.6;3.9;6.6;14.2;15.7 +22.6;94.1;49.2;8.2;12.1;32.0;9.7;3.9;6.6;14.1;15.9 +23.0;95.7;49.6;8.2;12.0;31.2;9.6;4.0;6.6;14.3;15.8 +22.8;94.3;49.6;8.3;12.1;31.9;9.8;4.0;6.6;14.1;16.0 +23.0;94.9;49.6;8.2;12.3;31.7;9.7;3.9;6.6;14.1;15.9 +23.1;95.5;50.0;8.1;12.3;31.3;9.5;3.9;6.7;13.8;15.9 +22.8;95.9;48.6;8.2;12.1;32.0;9.7;3.9;6.7;14.2;15.8 +22.8;94.9;49.9;8.1;12.3;31.7;9.7;3.9;6.5;14.2;16.1 +22.4;93.3;49.0;8.1;12.0;31.8;9.6;3.9;6.6;14.3;15.8 +22.7;94.2;49.4;8.0;12.0;31.8;9.6;4.0;6.6;14.1;15.7 +22.5;95.1;49.8;8.1;12.3;31.1;9.6;3.9;6.4;14.3;16.0 +22.6;94.3;48.7;8.1;12.3;31.2;9.6;4.0;6.5;14.1;15.7 +22.6;92.7;49.8;8.1;12.3;32.3;9.5;3.9;6.4;14.2;15.8 +22.4;93.6;48.8;8.1;12.2;31.6;9.5;3.9;6.5;14.1;15.6 +22.6;92.8;49.5;7.9;12.1;31.9;9.4;3.9;6.4;14.2;15.5 +22.6;91.9;49.0;8.1;12.1;30.9;9.7;4.0;6.5;14.2;15.5 +22.5;93.8;48.2;8.2;11.9;31.5;9.7;3.9;6.4;14.0;15.8 +22.6;93.0;48.7;8.1;12.1;31.2;9.5;3.9;6.4;14.1;15.6 +22.5;92.2;48.3;8.0;11.8;31.1;9.3;3.9;6.5;14.4;15.6 +22.0;92.9;48.4;7.9;11.8;31.2;9.5;3.9;6.4;14.1;15.6 +21.9;91.1;48.1;7.9;11.8;31.5;9.3;4.0;6.4;14.0;15.5 +22.5;93.2;48.5;7.9;12.0;30.8;9.5;3.9;6.4;14.2;15.3 +22.0;93.0;49.0;7.9;12.1;31.6;9.5;4.0;6.2;14.0;15.5 +22.3;91.7;48.9;8.1;11.9;30.7;9.4;3.9;6.4;14.0;15.0 +22.0;91.9;48.6;8.0;11.8;31.3;9.5;3.9;6.4;13.8;15.3 +22.5;92.6;48.9;8.1;11.9;31.0;9.4;4.0;6.3;13.9;15.2 +21.7;94.2;49.3;8.1;12.0;30.9;9.6;3.9;6.4;14.0;15.4 +22.2;91.3;49.8;8.0;11.8;30.9;9.6;3.8;6.4;13.9;15.3 +22.3;94.1;48.8;8.0;11.7;31.7;9.7;3.9;6.3;14.1;15.2 +22.3;92.2;48.9;7.9;11.8;30.9;9.4;3.9;6.4;14.1;15.3 +21.9;92.4;48.9;8.0;11.9;31.0;9.6;3.9;6.2;13.9;15.5 +21.7;91.7;49.0;8.1;11.7;31.5;9.6;3.9;6.3;14.0;15.4 +21.9;93.8;49.7;8.0;11.8;31.4;9.5;3.9;6.4;14.2;15.4 +22.2;90.8;49.0;8.0;11.9;30.5;9.4;3.9;6.3;13.8;15.0 +22.1;93.6;49.0;7.9;11.7;31.6;9.4;3.9;6.3;13.9;15.4 +21.9;90.4;48.8;7.8;11.7;30.8;9.5;3.9;6.2;13.8;15.2 +22.1;92.0;47.7;7.9;11.6;31.2;9.4;3.8;6.3;14.2;14.8 +21.8;91.1;47.9;7.7;11.7;30.6;9.3;3.8;6.1;13.8;15.1 +22.3;93.5;48.2;7.9;11.7;30.8;9.3;3.8;6.2;13.9;14.8 +21.6;94.0;47.8;7.7;11.6;30.5;9.5;3.8;6.2;13.8;15.0 +21.6;89.6;48.5;7.7;11.3;30.5;9.4;3.8;6.1;13.9;15.1 +21.6;89.6;49.0;7.8;11.7;30.8;9.3;3.8;6.2;14.1;15.0 +21.7;92.5;48.0;7.7;11.5;30.8;9.4;3.8;6.2;14.1;15.1 +22.0;91.7;48.3;7.8;11.6;30.7;9.3;3.8;6.2;14.0;15.0 +22.0;91.2;48.2;7.7;11.4;30.7;9.3;3.8;6.1;14.0;14.9 +21.6;91.6;47.8;7.8;11.5;31.1;9.3;3.8;6.1;14.0;15.2 +21.8;90.9;47.6;7.8;11.5;30.8;9.3;3.8;6.1;13.9;14.7 +21.5;89.7;48.8;7.8;11.5;30.8;9.3;3.7;6.1;13.9;15.3 +21.6;89.3;47.9;7.7;11.5;30.1;9.3;3.8;6.2;13.8;14.7 +21.5;91.2;46.4;7.7;11.4;30.5;9.3;3.7;6.1;13.9;14.5 +21.1;92.5;47.6;7.7;11.5;30.7;9.1;3.7;6.0;13.7;14.7 +21.3;89.6;47.5;7.8;11.2;29.9;9.1;3.7;6.1;13.7;14.5 +21.3;90.3;47.6;7.7;11.1;30.1;9.2;3.7;5.9;13.7;14.5 +21.0;89.5;47.2;7.6;11.3;29.6;9.1;3.7;5.9;13.4;14.3 +21.3;91.1;47.1;7.7;11.2;29.5;9.0;3.7;5.9;13.6;14.4 +21.3;90.1;46.4;7.5;11.2;29.8;9.2;3.7;6.0;13.5;14.3 +20.9;88.9;47.2;7.5;11.1;29.7;9.1;3.6;5.9;13.7;14.3 +21.0;89.4;46.5;7.7;11.2;29.8;9.1;3.7;5.9;13.3;14.5 +21.1;89.6;47.4;7.5;11.1;29.2;9.1;3.7;5.9;13.5;14.5 +21.3;90.2;47.0;7.5;11.1;30.2;9.2;3.7;5.9;13.4;14.5 +21.2;89.1;46.9;7.4;11.3;29.3;8.9;3.7;5.8;13.2;14.3 +20.6;88.6;46.2;7.5;10.9;29.3;9.1;3.6;5.9;13.4;14.4 +20.9;89.1;46.4;7.5;10.9;28.9;9.1;3.6;5.7;13.6;14.3 +21.0;88.5;46.6;7.4;11.2;29.5;9.0;3.5;5.8;13.3;14.5 +20.5;89.1;46.1;7.3;10.9;29.6;9.1;3.6;5.8;13.5;14.1 +20.7;88.4;45.7;7.4;11.0;28.6;9.0;3.6;5.8;13.2;14.0 +20.6;88.8;45.0;7.4;10.9;29.0;9.0;3.5;5.8;13.4;14.1 +20.6;87.3;45.4;7.4;11.0;28.9;9.1;3.5;5.7;13.3;13.9 +20.5;88.3;44.9;7.3;10.7;29.0;9.0;3.5;5.7;13.0;14.1 +20.6;87.4;44.8;7.3;10.9;28.2;8.7;3.5;5.6;13.2;13.9 +20.3;86.3;44.1;7.2;10.9;28.5;8.7;3.6;5.7;12.9;13.7 +19.8;86.5;44.8;7.2;10.8;28.3;8.7;3.5;5.6;13.2;13.6 +20.0;87.6;45.3;7.3;10.5;28.4;8.7;3.5;5.6;12.9;13.7 +19.9;86.8;45.6;7.3;10.6;28.1;8.7;3.4;5.7;12.7;13.8 +20.4;86.5;44.8;7.3;10.7;28.5;8.7;3.5;5.6;13.1;13.9 +20.1;86.5;45.1;7.3;10.7;27.8;8.7;3.4;5.5;12.8;14.0 +19.9;85.8;45.0;7.2;10.7;28.2;8.7;3.5;5.6;12.8;13.9 +19.8;87.0;44.8;7.2;10.7;28.5;8.6;3.5;5.6;12.9;13.9 +20.2;88.4;44.7;7.2;10.7;27.9;8.8;3.5;5.5;13.1;14.1 +19.7;85.9;44.7;7.2;10.7;28.5;8.7;3.5;5.5;12.9;13.6 +19.9;87.9;44.1;7.2;10.5;28.2;8.8;3.5;5.5;12.6;13.7 +20.2;87.5;44.0;7.2;10.5;28.7;8.7;3.4;5.4;12.8;13.7 +19.7;86.4;43.9;7.3;10.7;27.7;8.6;3.5;5.6;12.6;13.6 +20.1;86.3;44.1;7.2;10.5;27.8;8.6;3.4;5.5;12.6;14.0 +20.1;87.3;44.5;7.2;10.6;28.0;8.7;3.4;5.5;12.8;13.8 +19.9;87.9;44.4;7.2;10.5;27.6;8.7;3.4;5.5;12.6;13.6 +20.3;87.2;43.9;7.1;10.3;27.8;8.6;3.4;5.5;12.8;13.7 +19.9;85.5;44.3;7.1;10.4;27.6;8.6;3.5;5.4;12.7;13.7 +19.9;87.5;44.2;7.1;10.6;28.2;8.7;3.5;5.5;13.0;13.9 +20.1;85.6;43.9;7.2;10.7;28.1;8.8;3.5;5.5;12.9;13.6 +20.2;85.4;43.9;7.2;10.6;27.9;8.8;3.4;5.4;12.7;13.8 +20.1;87.0;44.7;7.2;10.5;27.9;8.4;3.4;5.4;12.4;13.5 +20.6;88.4;44.1;7.2;10.5;27.7;8.6;3.5;5.5;12.6;13.8 +20.3;86.9;44.9;7.0;10.5;27.6;8.7;3.4;5.5;12.5;13.6 +20.1;87.7;44.3;7.2;10.6;28.0;8.7;3.5;5.4;12.8;14.0 +20.3;85.4;43.9;7.1;10.4;27.7;8.6;3.4;5.5;12.4;14.0 +20.5;87.9;44.2;7.1;10.6;27.7;8.7;3.4;5.4;12.7;13.9 +20.7;87.3;44.0;7.4;10.5;27.8;8.7;3.5;5.5;12.4;14.1 +20.4;87.8;44.5;7.3;10.5;27.9;8.7;3.5;5.5;12.7;14.1 +20.9;88.7;43.6;7.3;10.9;27.7;8.8;3.5;5.5;12.9;13.7 +21.0;90.9;45.6;7.3;10.7;28.2;8.8;3.5;5.5;12.7;14.2 +20.5;90.5;45.5;7.2;10.8;27.6;8.9;3.5;5.6;12.6;14.1 +21.1;91.4;45.0;7.3;10.7;28.0;8.6;3.5;5.5;12.9;14.5 +21.0;92.0;45.9;7.3;10.7;28.0;8.8;3.5;5.6;13.0;14.5 +21.3;92.3;46.6;7.4;10.9;28.1;8.9;3.5;5.6;12.9;14.6 +21.0;93.7;46.0;7.5;10.8;28.1;9.0;3.6;5.6;13.0;14.6 +21.2;93.7;47.3;7.5;11.1;28.7;9.1;3.6;5.6;13.1;14.9 +21.6;94.5;46.3;7.6;11.0;28.8;8.9;3.6;5.6;13.1;14.9 +21.8;94.4;47.4;7.6;11.4;29.5;9.1;3.6;5.7;13.1;15.2 +22.0;93.7;47.5;7.8;11.5;29.8;9.3;3.6;5.8;13.3;15.2 +21.8;97.7;47.7;7.7;11.6;29.9;9.3;3.7;5.7;13.4;15.1 +22.0;95.8;47.4;8.0;11.6;30.0;9.3;3.7;5.9;13.2;15.3 +21.6;93.9;47.9;8.0;11.4;30.3;9.3;3.7;6.0;13.5;15.5 +22.5;96.3;49.8;8.1;12.1;30.3;9.5;3.8;6.0;13.5;15.6 +22.2;96.8;47.8;8.0;11.8;30.8;9.6;3.8;6.1;13.9;15.4 +22.0;96.9;49.4;8.0;12.0;31.2;9.8;3.9;6.1;14.1;15.7 +22.2;98.2;49.2;8.1;12.3;31.5;10.0;3.9;6.2;14.2;15.8 +22.4;97.6;48.3;8.1;12.3;32.5;9.9;3.9;6.3;14.2;15.4 +22.5;98.5;50.2;8.2;12.4;32.3;10.1;4.0;6.4;14.5;15.8 +22.6;97.3;49.4;8.3;12.0;31.8;10.2;3.9;6.6;14.7;15.9 +22.8;99.0;49.5;8.2;12.2;32.1;10.0;4.0;6.5;14.6;16.0 +22.1;95.3;49.6;8.2;12.2;32.2;10.1;4.0;6.6;14.8;15.8 +21.9;97.6;48.6;7.9;12.2;31.9;10.2;4.0;6.5;14.6;15.8 +22.3;97.8;49.4;8.2;12.4;32.3;10.1;4.0;6.6;15.0;15.7 +21.9;98.2;48.8;8.1;12.2;31.9;10.1;4.0;6.6;15.0;15.7 +22.5;98.0;48.3;8.1;12.3;31.3;10.1;4.0;6.6;14.7;15.9 +21.9;96.6;47.7;8.1;12.0;31.5;10.1;4.1;6.6;14.9;15.6 +21.8;97.5;48.6;8.0;12.0;32.2;10.0;3.9;6.6;15.0;15.4 +22.1;95.1;48.4;8.0;12.0;31.6;9.9;3.9;6.5;14.8;15.4 +21.7;95.3;47.8;8.0;12.0;31.1;9.8;4.0;6.5;14.6;15.5 +21.9;95.4;47.4;7.9;12.0;31.0;9.9;3.9;6.4;14.4;15.4 +21.2;95.6;47.9;7.9;12.1;30.8;9.8;4.0;6.5;14.4;15.4 +21.4;93.9;46.7;8.0;11.9;30.7;9.9;3.9;6.5;14.3;15.2 +21.6;94.0;47.7;7.8;11.8;30.7;9.8;3.9;6.4;14.4;15.5 +21.3;95.0;46.1;7.9;11.6;30.7;9.6;3.8;6.4;14.2;15.3 +21.0;94.2;46.2;7.7;11.7;30.2;9.7;3.8;6.4;14.4;15.2 +21.0;91.7;46.3;7.6;11.5;30.6;9.5;3.9;6.3;13.9;15.1 +21.1;92.7;46.7;7.5;11.5;30.1;9.7;3.9;6.3;14.1;15.2 +21.1;92.0;45.3;7.8;11.7;29.8;9.5;3.8;6.1;14.1;15.0 +21.1;91.9;46.2;7.6;11.5;30.1;9.5;3.7;6.2;13.9;14.8 +20.8;93.0;45.1;7.6;11.6;29.4;9.5;3.8;6.2;13.9;15.2 +20.5;91.9;45.0;7.6;11.4;29.6;9.5;3.8;6.2;13.6;15.1 +20.8;91.4;45.3;7.4;11.2;29.6;9.2;3.8;6.2;13.6;14.8 +20.6;90.3;44.6;7.7;11.3;29.3;9.2;3.7;6.0;13.7;14.7 +20.6;91.9;44.9;7.5;11.5;29.5;9.3;3.7;6.0;13.5;14.8 +20.5;90.7;44.1;7.4;11.2;29.3;9.3;3.7;6.1;13.4;14.6 +20.5;91.9;45.2;7.5;11.2;29.1;9.3;3.6;6.0;13.4;14.7 +20.9;89.5;43.8;7.3;11.0;29.0;9.1;3.7;6.0;13.3;14.6 +20.7;89.5;44.5;7.4;11.1;29.0;9.1;3.7;5.8;13.3;14.3 +20.4;92.0;43.2;7.2;11.1;28.4;9.1;3.6;5.9;13.4;14.3 +20.5;91.5;44.6;7.2;11.2;28.7;8.9;3.6;6.0;13.1;14.4 +20.1;90.2;42.8;7.3;11.2;28.6;9.0;3.6;5.9;13.1;14.4 +19.7;89.8;43.3;7.2;10.8;28.3;8.9;3.5;5.9;13.2;14.4 +20.1;89.5;43.6;7.2;11.0;28.6;8.9;3.6;5.8;13.1;14.4 +20.0;88.9;42.8;7.2;10.9;28.5;9.0;3.6;5.9;13.2;14.4 +20.0;88.9;43.5;7.3;10.9;28.4;8.9;3.5;5.9;12.9;14.4 +19.5;88.0;42.5;7.3;11.1;28.7;9.0;3.6;5.8;13.1;14.2 +20.0;89.8;43.7;7.2;10.8;28.6;8.8;3.6;6.0;13.0;14.3 +19.9;89.2;43.1;7.3;10.9;27.7;8.9;3.5;6.0;13.2;14.6 +20.2;89.3;43.4;7.3;11.0;28.8;9.1;3.6;5.9;13.4;14.7 +20.4;90.8;44.1;7.3;11.0;28.9;9.2;3.6;6.0;13.2;14.9 +20.3;90.6;44.4;7.4;11.1;29.2;9.0;3.6;6.0;13.3;14.9 +20.2;91.8;44.9;7.4;11.3;30.0;9.3;3.7;6.1;13.6;14.9 +20.4;93.8;44.7;7.6;11.2;29.5;9.2;3.7;6.2;13.9;14.7 +21.1;94.4;45.0;7.6;11.6;29.5;9.4;3.7;6.1;13.7;14.8 +21.1;93.4;44.7;7.6;11.5;30.3;9.4;3.8;6.2;13.9;15.1 +21.2;93.1;45.1;7.6;11.4;29.6;9.4;3.8;6.3;13.8;15.1 +21.0;95.4;46.5;7.6;11.7;29.7;9.2;3.8;6.3;13.8;15.1 +20.4;93.3;44.9;7.6;11.5;30.0;9.5;3.8;6.3;14.1;15.5 +20.8;94.5;45.3;7.5;11.7;29.9;9.4;3.7;6.1;13.8;15.2 +20.7;94.1;44.4;7.4;11.7;30.1;9.4;3.7;6.2;14.0;15.2 +20.9;94.4;44.8;7.6;11.5;29.9;9.3;3.7;6.3;13.7;15.1 +20.9;94.2;44.8;7.6;11.5;29.7;9.4;3.7;6.3;14.0;15.0 +20.9;93.9;45.5;7.5;11.5;29.5;9.3;3.7;6.3;13.8;15.1 +20.7;94.4;45.3;7.7;11.2;30.2;9.5;3.8;6.3;13.9;14.9 +21.0;93.7;44.8;7.6;11.6;29.9;9.4;3.7;6.3;13.9;15.2 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_p.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_p.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..03aa9f657f3eb5d7450356c370a4c5c5c86e875d GIT binary patch literal 4954 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 literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_q.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/load_q.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..12d7e3e8a7f4c603bdbc843f03f9303e7d955de0 GIT binary patch literal 4316 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 literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p.csv b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p.csv new file mode 100644 index 0000000..776f091 --- /dev/null +++ b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p.csv @@ -0,0 +1,577 @@ +GEN-1;GEN-2;GEN-3;GEN-6;GEN-6#0;GEN-8 +70.9;73.2;71.7;36.4;0.0;0.0 +71.7;73.3;72.6;36.6;0.0;0.0 +70.5;73.9;72.7;35.6;0.0;0.0 +71.6;74.3;71.8;35.4;0.0;0.0 +71.7;73.8;72.0;34.4;0.0;0.0 +72.2;74.2;71.5;33.7;0.0;0.0 +70.3;74.9;73.1;33.6;0.0;0.0 +70.5;73.7;72.2;32.8;0.0;0.0 +72.2;73.1;71.9;32.7;0.0;0.0 +71.8;72.9;71.0;31.8;0.0;0.0 +71.1;72.4;70.0;31.4;0.0;0.0 +69.2;71.5;70.2;30.6;0.0;0.0 +70.7;71.1;70.1;29.6;0.0;0.0 +70.6;72.1;70.5;29.3;0.0;0.0 +68.8;72.9;69.2;28.9;0.0;0.0 +69.9;72.2;70.7;28.0;0.0;0.0 +70.9;73.1;70.7;28.0;0.0;0.0 +71.4;72.1;71.0;27.2;0.0;0.0 +71.4;71.2;70.6;26.4;0.0;0.0 +71.3;73.1;71.8;26.4;0.0;0.0 +71.8;74.0;71.9;25.6;0.0;0.0 +70.9;73.9;71.1;24.8;0.0;0.0 +71.9;73.2;71.5;24.5;0.0;0.0 +72.3;73.7;72.2;24.3;0.0;0.0 +72.8;73.5;71.0;23.5;0.0;0.0 +71.3;73.7;71.4;23.3;0.0;0.0 +72.1;73.5;71.3;22.8;0.0;0.0 +71.1;74.0;71.5;22.6;0.0;0.0 +72.0;73.5;72.5;22.0;0.0;0.0 +72.6;74.4;72.3;21.2;0.0;0.0 +72.3;73.6;72.1;21.0;0.0;0.0 +71.9;73.6;72.6;20.6;0.0;0.0 +71.7;73.7;72.9;20.2;0.0;0.0 +71.9;73.7;71.7;20.4;0.0;0.0 +70.0;73.3;70.6;19.4;0.0;0.0 +71.5;71.4;70.1;19.1;0.0;0.0 +71.4;73.5;70.8;19.2;0.0;0.0 +71.6;72.8;70.6;18.7;0.0;0.0 +68.8;72.1;71.1;18.1;0.0;0.0 +70.7;72.3;70.3;17.6;0.0;0.0 +69.6;71.5;70.3;17.7;0.0;0.0 +70.0;71.4;68.8;17.3;0.0;0.0 +69.5;72.7;68.4;17.1;0.0;0.0 +69.2;71.0;69.4;16.7;0.0;0.0 +70.0;69.0;69.7;16.2;0.0;0.0 +69.8;70.1;69.3;16.0;0.0;0.0 +70.2;71.0;69.6;15.7;0.0;0.0 +69.8;70.8;69.1;15.5;0.0;0.0 +68.2;69.7;69.0;15.4;0.0;0.0 +68.3;70.5;67.9;15.2;0.0;0.0 +68.9;70.2;68.4;15.2;0.0;0.0 +69.1;70.4;68.9;15.1;0.0;0.0 +68.1;69.5;68.5;14.8;0.0;0.0 +69.0;69.9;68.6;14.3;0.0;0.0 +69.4;69.2;68.2;14.5;0.0;0.0 +67.9;70.5;68.3;14.2;0.0;0.0 +67.9;69.4;68.1;14.2;0.0;0.0 +67.6;70.2;68.7;13.9;0.0;0.0 +68.5;69.6;69.3;13.8;0.0;0.0 +67.9;69.6;66.6;13.7;0.0;0.0 +69.2;69.6;67.9;13.6;0.0;0.0 +67.2;68.8;67.7;13.3;0.0;0.0 +67.8;70.1;68.1;13.3;0.0;0.0 +68.1;70.5;68.9;13.2;0.0;0.0 +68.9;71.0;68.2;13.2;0.0;0.0 +68.1;69.8;69.1;12.8;0.0;0.0 +68.4;70.0;68.8;13.1;0.0;0.0 +69.0;69.6;69.7;13.1;0.0;0.0 +68.2;69.1;67.5;12.8;0.0;0.0 +67.8;71.4;69.1;12.8;0.0;0.0 +70.1;70.0;68.9;12.7;0.0;0.0 +69.1;71.1;70.5;12.6;0.0;0.0 +69.4;69.9;67.8;12.7;0.0;0.0 +67.6;72.1;69.4;12.4;0.0;0.0 +68.7;70.1;68.0;12.4;0.0;0.0 +69.1;68.6;69.7;12.6;0.0;0.0 +69.8;71.3;68.4;12.3;0.0;0.0 +70.1;70.2;68.3;12.5;0.0;0.0 +70.8;71.7;70.0;12.3;0.0;0.0 +69.6;71.7;69.2;12.3;0.0;0.0 +70.4;71.1;70.9;12.3;0.0;0.0 +69.2;70.6;69.8;12.2;0.0;0.0 +70.2;71.2;69.6;12.0;0.0;0.0 +69.4;70.4;69.8;12.3;0.0;0.0 +71.0;70.3;70.0;12.3;0.0;0.0 +69.7;71.0;70.5;12.2;0.1;0.0 +70.5;72.3;70.6;12.2;0.1;0.1 +70.2;70.6;70.6;12.1;0.2;0.1 +69.7;71.8;70.0;11.7;0.3;0.2 +70.1;71.0;69.8;11.9;0.5;0.3 +69.5;71.1;69.9;12.0;0.7;0.4 +71.4;71.7;68.8;11.6;1.0;0.6 +69.7;71.9;70.7;11.8;1.3;0.7 +71.3;70.6;70.5;11.4;1.7;0.9 +70.0;71.2;69.4;11.6;1.9;1.1 +70.7;71.8;70.7;11.4;2.2;1.3 +70.4;71.7;71.0;11.2;2.5;1.5 +70.0;71.5;70.2;11.0;3.0;1.9 +70.4;71.5;69.2;11.3;3.8;2.3 +68.3;71.2;69.1;10.7;4.8;2.9 +68.4;71.0;68.9;10.8;5.9;3.5 +68.0;69.6;68.8;10.5;7.0;4.2 +68.3;69.9;68.4;10.4;8.3;4.9 +67.1;69.7;65.9;10.4;9.3;5.5 +68.0;68.4;66.2;10.2;10.0;5.8 +66.8;69.0;66.4;10.0;10.6;5.8 +67.4;68.7;68.4;9.9;10.3;5.8 +68.6;71.4;68.0;9.9;10.2;5.6 +69.8;70.3;68.4;9.7;10.1;5.4 +68.5;69.4;69.7;9.6;10.1;5.3 +69.2;68.9;70.0;9.6;10.6;5.5 +69.4;70.0;68.3;9.3;11.6;5.9 +69.4;69.8;69.1;9.1;12.7;6.6 +68.4;69.4;67.5;8.9;13.9;7.4 +68.4;68.7;67.3;9.0;15.1;8.0 +67.2;69.6;67.6;8.9;16.0;8.7 +66.2;69.3;67.0;8.5;17.2;9.1 +66.6;68.5;67.3;8.6;17.7;9.0 +67.5;68.4;67.9;8.5;17.8;8.7 +68.7;70.6;68.3;8.4;18.2;8.5 +69.1;69.9;68.5;8.3;18.3;8.5 +67.6;70.3;67.5;8.2;19.1;8.8 +67.6;68.9;67.8;8.2;19.7;9.7 +66.7;68.0;66.7;8.2;20.7;10.7 +67.5;68.0;67.1;8.1;20.9;11.7 +67.3;67.2;67.7;8.0;20.9;11.9 +67.4;68.8;67.4;7.9;21.0;12.4 +68.0;67.6;66.2;7.9;20.5;12.1 +67.3;68.6;66.6;8.0;20.2;12.1 +67.4;68.5;68.4;8.0;20.4;11.4 +67.8;69.4;68.6;8.1;20.3;11.1 +67.6;67.9;67.7;7.9;21.0;11.0 +66.9;68.6;66.8;7.9;23.0;11.3 +66.2;68.3;65.8;8.0;24.9;12.2 +64.2;65.8;64.8;7.8;26.6;13.6 +64.6;66.0;64.2;7.8;28.1;14.9 +64.1;64.8;63.3;7.8;28.1;15.8 +63.8;64.9;64.5;7.7;27.0;15.8 +66.0;66.5;66.5;8.0;24.0;15.9 +67.5;68.6;66.8;7.9;21.3;15.1 +67.1;68.6;67.2;7.9;19.5;14.7 +66.8;67.3;66.8;8.1;20.5;15.0 +64.6;68.1;64.9;7.9;22.8;14.9 +65.6;67.7;65.5;7.9;25.4;14.9 +64.0;66.1;65.3;8.1;27.5;14.8 +65.4;67.2;65.4;7.9;27.4;14.3 +66.4;66.9;65.6;8.0;26.2;13.4 +67.1;68.4;67.2;8.1;24.4;12.6 +67.0;69.6;67.6;7.9;23.0;12.8 +67.4;68.2;67.2;8.1;22.8;12.7 +67.2;68.0;65.5;8.1;23.3;12.9 +67.3;68.0;65.8;8.1;23.6;13.3 +67.1;69.5;68.7;8.2;22.5;13.2 +68.5;69.9;68.0;8.2;20.8;12.2 +70.6;71.4;70.0;8.0;18.2;10.9 +71.1;73.0;69.8;8.3;15.5;9.9 +71.2;73.0;72.4;8.2;13.5;8.7 +71.9;72.6;73.0;8.1;13.3;8.8 +70.5;72.8;70.6;8.1;14.6;9.2 +70.2;70.7;69.8;8.2;16.3;10.1 +68.2;69.4;67.9;8.3;18.0;10.8 +66.7;69.3;66.8;8.1;19.9;11.2 +66.6;67.5;67.4;8.3;21.0;11.3 +65.3;65.5;65.4;8.2;21.4;11.3 +63.9;65.9;64.8;8.4;21.6;11.0 +64.9;66.6;65.3;8.2;20.6;10.5 +65.2;66.4;64.7;8.3;20.1;9.9 +65.5;66.9;64.3;8.1;18.3;9.7 +65.0;67.7;65.1;8.1;17.5;9.3 +65.7;67.3;65.5;8.1;16.7;9.4 +65.1;67.2;65.2;8.0;16.1;9.3 +65.7;66.7;65.3;8.0;15.6;9.2 +65.6;67.4;65.4;8.1;14.7;8.7 +66.2;65.9;65.6;8.0;13.2;7.9 +66.1;68.5;67.8;7.9;11.9;6.8 +68.1;69.4;66.4;7.7;10.2;5.9 +67.0;69.2;67.1;7.8;9.0;5.2 +68.0;69.7;67.9;7.8;8.4;4.7 +67.3;68.6;68.5;7.6;8.2;4.5 +66.9;67.8;67.6;7.7;7.7;4.4 +67.1;68.4;66.4;7.7;7.6;4.2 +65.8;68.6;66.0;7.7;7.0;3.8 +67.1;68.5;67.0;7.5;6.3;3.4 +66.5;67.3;66.9;7.5;5.7;3.0 +68.1;69.1;67.5;7.2;5.1;2.6 +68.2;69.3;66.4;7.4;4.4;2.3 +67.5;69.2;67.6;7.2;3.9;2.0 +68.5;69.5;69.7;7.1;3.3;1.7 +68.3;68.8;67.8;7.2;2.7;1.4 +69.2;70.5;68.3;7.1;2.1;1.1 +69.3;70.0;69.1;7.0;1.6;0.8 +68.8;69.7;67.5;6.9;1.1;0.6 +67.8;69.8;68.7;6.9;0.8;0.4 +68.7;70.3;67.9;6.8;0.5;0.3 +68.7;70.1;68.2;6.7;0.3;0.2 +68.7;68.6;67.2;6.7;0.2;0.1 +68.5;71.2;68.6;6.7;0.1;0.0 +68.6;69.6;68.9;6.6;0.0;0.0 +68.6;70.3;68.3;6.7;0.0;0.0 +68.5;69.7;67.8;6.5;0.0;0.0 +68.1;71.1;68.8;6.6;0.0;0.0 +69.4;70.4;69.2;6.7;0.0;0.0 +68.0;69.8;68.8;6.5;0.0;0.0 +69.5;71.6;69.1;6.5;0.0;0.0 +68.1;70.2;68.3;6.4;0.0;0.0 +69.3;70.5;69.2;6.5;0.0;0.0 +68.6;71.0;68.0;6.3;0.0;0.0 +69.2;71.1;70.1;6.4;0.0;0.0 +70.1;70.4;68.2;6.4;0.0;0.0 +68.4;71.1;70.4;6.3;0.0;0.0 +69.4;71.0;69.6;6.5;0.0;0.0 +71.8;72.1;70.9;6.5;0.0;0.0 +70.6;71.4;70.3;6.5;0.0;0.0 +70.1;72.8;71.9;6.5;0.0;0.0 +72.2;72.9;70.8;6.3;0.0;0.0 +71.3;72.4;72.1;6.5;0.0;0.0 +73.0;74.4;72.1;6.6;0.0;0.0 +73.3;76.0;73.6;6.6;0.0;0.0 +75.5;75.4;73.4;6.8;0.0;0.0 +74.4;75.1;75.4;6.8;0.0;0.0 +75.6;76.6;76.0;7.0;0.0;0.0 +74.2;77.9;75.0;6.9;0.0;0.0 +76.8;78.0;76.9;7.0;0.0;0.0 +77.0;79.6;76.6;7.0;0.0;0.0 +77.2;78.3;76.9;7.1;0.0;0.0 +77.4;81.3;78.7;7.2;0.0;0.0 +78.1;79.6;79.0;7.4;0.0;0.0 +78.1;80.4;77.1;7.3;0.0;0.0 +77.5;80.9;78.1;7.6;0.0;0.0 +80.4;81.0;79.6;7.7;0.0;0.0 +80.5;82.5;80.7;7.8;0.0;0.0 +79.4;83.1;80.1;7.8;0.0;0.0 +79.1;82.3;78.5;7.9;0.0;0.0 +79.6;82.9;80.3;8.0;0.0;0.0 +78.9;81.3;79.7;8.0;0.0;0.0 +79.1;82.1;80.9;8.1;0.0;0.0 +79.8;81.8;81.3;8.3;0.0;0.0 +79.4;81.4;80.8;8.4;0.0;0.0 +81.2;81.7;79.8;8.3;0.0;0.0 +81.4;81.8;78.7;8.3;0.0;0.0 +80.9;81.1;80.5;8.4;0.0;0.0 +79.5;82.0;79.8;8.5;0.0;0.0 +79.6;82.4;77.9;8.5;0.0;0.0 +79.8;82.9;79.5;8.4;0.0;0.0 +79.4;82.1;78.5;8.6;0.0;0.0 +77.7;81.5;79.4;8.5;0.0;0.0 +78.7;80.5;78.0;8.5;0.0;0.0 +77.9;79.5;79.2;8.4;0.0;0.0 +77.8;80.2;79.0;8.7;0.0;0.0 +79.5;80.6;78.2;8.4;0.0;0.0 +79.5;79.9;79.4;8.4;0.0;0.0 +78.2;80.0;77.2;8.3;0.0;0.0 +78.9;80.6;78.1;8.4;0.0;0.0 +79.3;79.6;78.5;8.3;0.0;0.0 +77.4;78.8;79.0;8.2;0.0;0.0 +78.1;79.9;78.3;8.3;0.0;0.0 +76.5;79.5;76.8;8.1;0.0;0.0 +77.2;77.6;78.6;8.0;0.0;0.0 +77.4;77.6;77.7;8.2;0.0;0.0 +76.6;78.5;77.0;8.0;0.0;0.0 +77.0;78.9;76.8;8.0;0.0;0.0 +75.8;78.2;77.8;8.0;0.0;0.0 +75.6;78.2;75.7;7.9;0.0;0.0 +76.8;77.5;75.6;7.9;0.0;0.0 +76.4;77.4;75.1;7.8;0.0;0.0 +75.6;76.6;76.0;7.9;0.0;0.0 +75.8;78.0;77.6;7.8;0.0;0.0 +77.1;77.9;75.4;8.0;0.0;0.0 +76.9;76.6;75.8;7.9;0.0;0.0 +76.0;76.4;76.2;7.9;0.0;0.0 +76.2;76.4;77.0;7.8;0.0;0.0 +77.2;79.3;76.2;7.9;0.0;0.0 +77.1;79.5;78.8;7.9;0.0;0.0 +76.6;79.2;78.9;7.9;0.0;0.0 +78.3;79.7;79.7;7.9;0.0;0.0 +79.3;80.8;79.8;7.9;0.0;0.0 +81.4;80.4;79.5;8.0;0.0;0.0 +80.1;81.7;80.5;8.0;0.0;0.0 +80.6;81.2;80.7;7.9;0.0;0.0 +81.6;83.1;79.8;8.0;0.0;0.0 +79.9;81.4;78.6;8.1;0.0;0.0 +80.7;81.4;79.6;8.1;0.0;0.0 +80.0;83.0;80.5;8.2;0.0;0.0 +80.7;81.4;79.3;8.2;0.0;0.0 +80.7;82.7;79.6;8.3;0.0;0.0 +80.7;81.6;79.4;8.4;0.0;0.0 +79.3;82.1;81.1;8.5;0.0;0.0 +81.5;82.4;80.3;8.6;0.0;0.0 +80.7;82.5;80.4;8.5;0.0;0.0 +80.7;82.5;81.0;8.6;0.0;0.0 +81.0;81.8;80.4;8.7;0.0;0.0 +81.2;82.4;81.2;8.6;0.0;0.0 +79.8;82.7;81.5;8.7;0.0;0.0 +80.4;81.1;78.9;8.8;0.0;0.0 +79.2;81.7;79.8;9.1;0.0;0.0 +80.9;80.3;79.0;9.0;0.0;0.0 +78.0;78.9;77.3;9.1;0.0;0.0 +77.3;80.1;78.4;9.2;0.0;0.0 +77.4;80.2;76.4;9.3;0.0;0.0 +75.5;79.6;77.4;9.4;0.0;0.0 +76.3;77.9;76.9;9.5;0.0;0.0 +76.2;77.4;74.4;9.7;0.0;0.0 +76.3;77.0;76.9;9.6;0.0;0.0 +77.3;78.6;75.4;9.8;0.0;0.0 +74.9;77.0;76.6;9.9;0.0;0.0 +75.1;77.4;75.9;9.9;0.0;0.0 +77.2;77.7;77.0;10.2;0.0;0.0 +76.7;78.1;74.8;10.2;0.0;0.0 +74.9;77.9;77.4;10.5;0.0;0.0 +76.0;77.2;75.7;10.4;0.0;0.0 +76.3;78.0;75.5;10.4;0.0;0.0 +76.2;77.6;75.9;10.8;0.0;0.0 +74.6;76.4;76.2;11.1;0.0;0.0 +75.9;77.8;75.5;10.9;0.0;0.0 +74.9;77.5;75.7;11.1;0.0;0.0 +75.4;76.9;75.6;10.9;0.0;0.0 +75.0;77.2;76.4;11.1;0.0;0.0 +75.5;78.5;76.0;11.5;0.0;0.0 +74.8;75.3;75.9;11.7;0.0;0.0 +75.7;77.0;76.7;11.9;0.0;0.0 +75.4;76.5;76.3;12.1;0.0;0.0 +73.5;76.8;73.9;11.9;0.0;0.0 +72.0;75.2;74.2;12.3;0.0;0.0 +73.5;73.8;74.0;12.4;0.0;0.0 +73.3;73.5;73.5;12.6;0.0;0.0 +71.8;72.3;71.9;12.7;0.0;0.0 +71.9;72.9;72.1;12.9;0.0;0.0 +72.3;73.9;70.9;13.0;0.0;0.0 +70.2;73.2;71.2;13.0;0.0;0.0 +71.5;72.6;71.2;13.3;0.0;0.0 +70.3;73.1;72.1;13.2;0.0;0.0 +70.9;72.5;70.6;13.8;0.0;0.0 +70.6;72.2;70.7;13.6;0.0;0.0 +70.4;71.5;71.1;13.7;0.0;0.0 +70.8;71.1;70.2;13.9;0.0;0.0 +69.6;72.0;70.4;14.1;0.0;0.0 +70.2;71.0;70.2;13.9;0.0;0.0 +69.1;69.8;68.7;14.1;0.0;0.0 +70.0;70.0;69.1;14.1;0.0;0.0 +68.9;69.9;67.4;14.3;0.0;0.0 +67.8;70.8;69.4;14.5;0.0;0.0 +69.9;70.9;70.6;14.5;0.0;0.0 +69.4;71.0;68.5;14.6;0.0;0.0 +69.0;72.3;68.9;14.7;0.0;0.0 +68.6;70.5;68.1;14.9;0.0;0.0 +69.0;71.6;66.8;14.7;0.0;0.0 +70.2;70.8;68.8;14.9;0.0;0.0 +69.2;69.8;69.3;14.8;0.0;0.0 +68.4;71.3;69.1;15.0;0.0;0.0 +68.3;69.5;69.5;15.0;0.0;0.0 +70.2;71.4;68.7;15.2;0.0;0.0 +70.6;72.3;70.6;14.9;0.0;0.0 +68.8;71.0;70.4;15.5;0.0;0.0 +70.2;72.0;70.7;15.3;0.0;0.0 +71.2;73.6;70.9;15.3;0.0;0.0 +72.6;73.0;71.7;15.1;0.0;0.0 +71.2;73.2;71.4;15.3;0.0;0.0 +73.0;72.9;72.8;15.6;0.0;0.0 +73.4;73.2;72.4;15.5;0.0;0.0 +73.0;73.8;72.8;15.5;0.0;0.0 +73.1;74.1;72.6;15.7;0.0;0.0 +72.9;75.4;73.1;15.3;0.0;0.0 +73.9;76.8;73.8;15.7;0.0;0.0 +74.3;75.4;73.9;15.5;0.0;0.0 +75.6;76.4;75.5;15.6;0.0;0.0 +77.2;78.0;77.0;15.6;0.0;0.0 +78.0;79.7;76.7;15.9;0.0;0.0 +77.6;80.6;78.4;16.2;0.0;0.0 +78.2;81.5;79.3;15.9;0.0;0.0 +79.9;80.9;80.1;16.0;0.0;0.0 +78.8;81.6;80.4;15.9;0.0;0.0 +80.0;82.0;79.4;15.9;0.0;0.0 +81.8;81.9;80.1;16.3;0.0;0.0 +80.5;83.1;81.1;16.1;0.1;0.1 +82.0;82.8;82.4;16.4;0.2;0.1 +82.4;84.6;81.6;16.0;0.3;0.2 +83.5;84.0;81.9;16.1;0.5;0.3 +83.2;85.0;83.7;16.2;0.7;0.4 +82.3;85.7;82.1;16.1;1.0;0.5 +83.7;85.4;81.8;16.2;1.3;0.7 +83.8;84.3;83.2;16.4;1.7;0.8 +83.6;85.0;85.7;16.6;2.0;0.9 +83.7;87.0;84.0;16.3;2.3;1.1 +83.2;86.1;84.1;16.5;2.5;1.2 +83.3;85.6;83.2;16.7;2.8;1.4 +83.9;86.0;84.2;16.9;3.1;1.5 +83.0;84.7;84.8;16.7;3.4;1.7 +83.8;84.4;84.3;16.7;3.7;1.9 +83.5;86.1;84.0;16.7;4.1;2.1 +83.0;84.6;81.5;16.8;4.4;2.5 +83.1;85.0;82.5;17.0;4.7;2.8 +81.7;84.7;82.7;16.9;5.1;3.1 +82.2;84.8;82.8;17.0;5.5;3.5 +80.7;83.8;81.7;17.1;6.3;3.9 +79.4;83.2;80.6;17.3;7.2;4.3 +81.5;82.8;80.6;17.1;8.5;4.8 +80.1;82.5;79.7;17.3;9.7;5.2 +79.3;81.1;79.2;17.2;10.8;5.8 +79.8;81.7;79.4;17.3;12.0;6.4 +78.3;79.2;76.9;17.5;12.6;6.9 +78.5;79.2;78.1;18.0;13.6;7.5 +77.8;78.0;78.1;17.6;14.5;7.7 +75.8;77.8;77.8;17.6;14.7;7.9 +77.2;78.0;75.4;18.3;14.9;7.9 +75.8;77.9;77.0;18.4;14.9;7.8 +77.9;78.9;75.7;18.2;14.9;7.8 +77.8;78.4;76.4;18.9;15.0;7.6 +77.3;78.9;77.2;18.8;14.3;7.4 +76.6;76.3;76.4;19.2;13.8;7.3 +77.2;79.8;76.9;19.1;13.2;7.5 +77.4;78.8;75.0;19.8;12.9;7.6 +75.8;78.2;76.5;20.5;13.2;8.1 +74.9;77.2;74.8;19.8;13.6;8.7 +75.3;76.0;74.3;21.0;14.9;9.7 +73.4;75.2;73.0;21.1;17.3;10.6 +73.3;72.8;72.4;21.4;19.0;11.6 +71.5;73.2;71.7;21.7;20.8;12.6 +70.9;71.8;70.8;22.2;22.1;12.9 +70.1;71.6;70.4;22.7;22.8;13.1 +70.6;71.6;69.9;23.1;23.5;13.3 +70.1;72.5;67.8;23.9;23.1;13.4 +69.5;70.5;69.5;23.7;22.3;13.3 +68.1;70.6;70.0;23.9;22.2;13.8 +69.7;70.3;69.4;24.4;21.2;13.5 +68.6;70.8;68.8;25.1;20.4;13.3 +69.8;70.3;70.4;25.4;19.0;12.7 +70.3;72.0;70.9;25.6;18.6;12.8 +71.0;72.2;70.3;26.1;18.1;12.3 +70.7;72.6;70.2;26.5;18.3;11.8 +70.5;70.8;71.2;26.6;18.9;12.1 +69.4;69.7;69.5;26.8;20.1;12.5 +69.3;68.6;67.8;27.2;20.8;13.1 +68.4;69.7;67.2;27.4;22.2;13.0 +68.9;71.2;67.9;27.9;21.6;12.9 +67.5;69.1;68.5;28.3;20.6;12.9 +68.1;69.7;67.3;28.0;20.3;12.5 +68.5;70.6;68.0;28.4;20.0;12.7 +66.6;69.5;67.6;27.8;20.6;12.8 +67.5;67.7;68.0;28.5;21.5;13.4 +65.5;68.0;68.3;28.5;22.0;13.9 +66.4;68.9;66.2;28.0;22.0;13.7 +65.6;66.6;66.2;28.7;21.9;13.0 +66.0;68.2;67.3;28.9;21.3;12.1 +67.0;69.2;66.8;28.3;20.2;11.0 +68.1;68.2;68.0;28.0;19.0;10.3 +68.9;68.7;68.5;28.3;18.6;10.1 +67.9;69.4;68.2;28.0;18.6;10.1 +67.9;69.7;69.2;28.2;17.8;10.6 +67.5;68.0;68.0;27.8;18.0;11.1 +67.6;69.4;69.1;27.7;17.3;10.9 +67.5;68.4;68.2;27.8;16.4;10.5 +69.4;70.4;69.1;28.2;15.0;9.7 +68.1;71.0;68.9;27.5;13.4;8.6 +70.2;72.9;70.8;27.5;11.4;6.8 +72.3;71.6;71.7;27.6;9.4;5.2 +71.8;73.6;71.3;27.6;7.9;4.0 +73.0;74.2;72.4;27.2;7.3;3.5 +71.4;74.0;71.7;27.9;7.6;4.2 +71.3;73.4;71.0;27.3;8.7;5.3 +69.9;71.4;71.1;26.9;10.2;6.4 +69.6;70.9;69.8;27.9;11.0;7.1 +69.6;70.6;68.9;28.0;11.6;7.3 +69.8;69.9;68.7;28.3;11.8;7.0 +69.3;70.8;69.4;28.3;11.3;6.5 +68.4;71.1;69.3;27.9;10.5;5.9 +69.6;72.0;69.3;28.4;9.4;5.4 +70.5;71.1;70.2;28.6;8.4;5.0 +70.3;70.7;68.9;28.0;7.3;4.5 +68.2;70.3;69.4;28.7;6.4;4.2 +70.4;72.2;69.8;28.6;5.8;3.8 +70.0;70.9;69.2;28.3;5.2;3.5 +70.3;70.8;71.6;29.3;4.8;3.1 +70.3;71.7;70.5;28.8;4.2;2.7 +69.7;72.4;70.4;30.1;3.7;2.4 +71.1;72.3;69.8;29.6;3.1;2.0 +70.5;71.8;72.2;29.6;2.5;1.7 +70.3;71.9;70.7;30.2;2.1;1.3 +69.1;72.0;71.9;29.4;1.6;1.1 +72.4;73.3;70.9;29.5;1.3;0.8 +70.7;72.0;71.1;29.6;1.0;0.6 +69.3;72.6;70.3;29.6;0.7;0.4 +71.4;72.2;71.5;30.4;0.5;0.3 +71.6;72.0;71.8;30.8;0.3;0.2 +71.4;71.2;70.5;30.7;0.2;0.1 +71.4;72.5;70.7;30.5;0.1;0.0 +71.7;72.8;72.9;30.9;0.0;0.0 +71.4;72.8;70.6;31.0;0.0;0.0 +71.1;72.7;71.1;30.8;0.0;0.0 +71.3;72.1;70.0;31.1;0.0;0.0 +70.8;69.8;70.5;31.0;0.0;0.0 +71.2;71.6;70.1;31.4;0.0;0.0 +70.6;72.8;71.4;31.3;0.0;0.0 +69.2;73.0;70.0;31.0;0.0;0.0 +70.8;71.5;71.5;31.1;0.0;0.0 +70.5;73.0;70.9;30.9;0.1;0.0 +71.0;72.5;69.0;31.5;0.1;0.0 +71.2;71.1;70.7;31.3;0.1;0.0 +71.6;74.1;71.4;31.9;0.1;0.0 +72.5;73.4;70.2;31.9;0.1;0.0 +71.5;72.6;72.2;32.2;0.0;0.0 +72.0;74.3;73.2;32.7;0.0;0.0 +73.3;73.7;72.7;32.4;0.0;0.0 +72.5;73.6;72.3;32.6;0.0;0.0 +72.3;75.5;74.1;31.9;0.0;0.0 +72.9;75.4;73.5;33.0;0.0;0.0 +74.2;75.7;74.9;33.1;0.0;0.0 +76.4;77.1;75.5;32.9;0.0;0.0 +76.0;75.7;75.5;33.6;0.0;0.0 +76.8;77.3;75.8;34.2;0.0;0.0 +75.5;77.0;75.5;34.2;0.0;0.0 +75.9;79.0;76.3;34.5;0.0;0.0 +78.2;78.8;77.4;35.1;0.0;0.0 +77.5;79.4;76.2;35.4;0.0;0.0 +76.8;79.7;78.2;35.1;0.0;0.0 +78.8;82.1;78.1;36.6;0.0;0.0 +78.2;80.3;79.1;36.7;0.0;0.0 +78.7;81.4;79.2;36.8;0.0;0.0 +80.1;81.4;80.1;37.4;0.0;0.0 +78.7;81.6;79.1;36.9;0.0;0.0 +81.2;82.8;78.9;37.5;0.0;0.0 +79.7;80.5;79.9;37.7;0.0;0.0 +79.9;80.9;78.9;38.8;0.0;0.0 +78.1;78.7;79.0;38.7;0.0;0.0 +79.8;81.0;78.2;38.7;0.0;0.0 +80.1;79.9;79.8;38.3;0.0;0.0 +79.4;80.6;77.3;38.7;0.0;0.0 +77.3;79.2;79.2;39.7;0.0;0.0 +77.9;80.2;79.3;40.4;0.0;0.0 +76.4;79.4;77.0;40.2;0.0;0.0 +78.0;78.4;78.2;40.6;0.0;0.0 +76.8;78.7;75.7;40.8;0.0;0.0 +75.2;76.5;75.3;40.6;0.0;0.0 +76.0;77.2;76.2;40.9;0.0;0.0 +74.2;76.6;75.4;40.9;0.0;0.0 +73.5;76.4;74.5;41.8;0.0;0.0 +74.4;75.3;73.4;41.7;0.0;0.0 +74.5;75.5;74.8;41.6;0.0;0.0 +73.6;74.9;73.7;41.9;0.0;0.0 +72.7;75.0;72.5;41.9;0.0;0.0 +73.8;75.4;72.1;42.0;0.0;0.0 +72.4;72.1;72.7;42.2;0.0;0.0 +71.3;74.3;71.6;41.6;0.0;0.0 +70.6;72.7;72.9;42.8;0.0;0.0 +71.1;73.2;70.0;42.3;0.0;0.0 +71.6;72.3;72.0;42.5;0.0;0.0 +72.0;71.5;71.0;42.0;0.0;0.0 +69.9;72.4;70.4;42.0;0.0;0.0 +70.6;70.7;70.8;43.3;0.0;0.0 +69.3;71.5;69.9;42.5;0.0;0.0 +68.4;70.2;70.6;43.4;0.0;0.0 +68.7;71.0;69.3;42.3;0.0;0.0 +70.9;70.8;68.3;43.3;0.0;0.0 +69.5;70.7;68.6;42.8;0.0;0.0 +69.3;71.1;68.8;43.0;0.0;0.0 +68.2;68.7;68.5;42.6;0.0;0.0 +67.5;69.5;68.0;43.4;0.0;0.0 +67.9;70.6;69.2;42.9;0.0;0.0 +67.5;69.6;68.2;43.9;0.0;0.0 +68.9;70.7;68.1;43.4;0.0;0.0 +69.1;70.0;68.6;42.9;0.0;0.0 +69.0;71.0;69.2;43.3;0.0;0.0 +69.2;71.2;69.7;43.7;0.0;0.0 +71.9;73.3;69.3;43.8;0.0;0.0 +72.0;71.8;70.6;43.7;0.0;0.0 +72.7;74.2;70.9;43.6;0.0;0.0 +72.0;73.4;71.8;43.8;0.0;0.0 +73.2;73.9;72.9;44.1;0.0;0.0 +71.1;73.2;74.3;44.4;0.0;0.0 +72.2;74.8;73.2;43.6;0.0;0.0 +71.2;74.1;73.1;44.0;0.0;0.0 +70.2;72.0;71.7;44.5;0.0;0.0 +71.6;73.1;70.9;44.1;0.0;0.0 +72.0;74.0;72.5;43.7;0.0;0.0 +71.8;72.2;71.8;44.7;0.0;0.0 +71.4;74.2;72.1;44.9;0.0;0.0 +72.1;73.8;72.4;44.5;0.0;0.0 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..eef64f90b97edd06be1fb3528c04b16e5cf34b7b GIT binary patch literal 3546 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 U-ya?ygWsa=NT&)C0oXHGz@8Gpq5uE@ literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p_forecasted.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_p_forecasted.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..1776ec0f978eba10f95dfdf97860ff233d79684f GIT binary patch literal 3173 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 Lig2MJR@5ZOA*af4 literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_v.csv b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_v.csv new file mode 100644 index 0000000..65ecc56 --- /dev/null +++ b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_v.csv @@ -0,0 +1,577 @@ +GEN-1;GEN-2;GEN-3;GEN-6;GEN-6#0;GEN-8 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 +142.1;142.1;142.1;22.0;22.0;13.2 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_v.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0000/prod_v.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..8c9736d484107239ad44a6ff625c62af03bc5417 GIT binary patch literal 107 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 literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_p_forecasted.csv b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_p_forecasted.csv new file mode 100644 index 0000000..93ca56e --- /dev/null +++ b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_p_forecasted.csv @@ -0,0 +1,577 @@ +LOAD-2;LOAD-3;LOAD-4;LOAD-5;LOAD-6;LOAD-9;LOAD-10;LOAD-11;LOAD-12;LOAD-13;LOAD-14 +21.9;86.6;44.6;6.9;11.8;28.2;8.8;3.4;5.5;12.6;14.8 +22.0;86.8;44.8;6.9;11.8;28.3;8.8;3.5;5.5;12.6;14.9 +22.0;86.9;44.8;6.9;11.8;28.3;8.8;3.5;5.5;12.6;14.9 +22.0;86.9;44.8;6.9;11.8;28.3;8.8;3.5;5.5;12.6;14.9 +21.9;86.8;44.8;6.9;11.8;28.3;8.8;3.4;5.5;12.6;14.9 +21.9;86.7;44.7;6.9;11.8;28.2;8.8;3.4;5.4;12.5;14.9 +21.8;86.5;44.6;6.9;11.8;28.1;8.7;3.4;5.4;12.4;14.8 +21.8;86.2;44.4;6.8;11.7;28.0;8.7;3.4;5.4;12.4;14.8 +21.7;85.9;44.3;6.8;11.7;27.8;8.7;3.4;5.3;12.3;14.8 +21.6;85.6;44.1;6.8;11.6;27.7;8.6;3.4;5.3;12.2;14.7 +21.6;85.3;44.0;6.7;11.6;27.5;8.6;3.3;5.3;12.1;14.7 +21.6;85.1;43.9;6.7;11.5;27.4;8.5;3.3;5.2;12.0;14.6 +21.5;85.0;43.8;6.7;11.5;27.4;8.5;3.3;5.2;12.0;14.6 +21.5;85.0;43.8;6.7;11.5;27.4;8.5;3.3;5.2;11.9;14.6 +21.6;85.0;43.8;6.7;11.5;27.4;8.5;3.3;5.2;11.9;14.7 +21.6;85.2;43.9;6.7;11.5;27.5;8.5;3.3;5.2;12.0;14.7 +21.6;85.3;43.9;6.7;11.5;27.6;8.5;3.3;5.2;12.0;14.7 +21.7;85.5;44.0;6.7;11.6;27.6;8.5;3.3;5.2;12.0;14.8 +21.7;85.6;44.1;6.7;11.6;27.7;8.6;3.3;5.2;12.0;14.8 +21.7;85.7;44.1;6.7;11.6;27.7;8.6;3.3;5.2;12.0;14.8 +21.8;85.7;44.1;6.7;11.6;27.8;8.6;3.3;5.2;12.0;14.8 +21.8;85.7;44.1;6.7;11.6;27.8;8.6;3.3;5.2;12.0;14.8 +21.8;85.7;44.1;6.7;11.6;27.7;8.6;3.3;5.2;11.9;14.8 +21.8;85.6;44.1;6.7;11.6;27.7;8.6;3.3;5.2;11.9;14.8 +21.8;85.7;44.2;6.7;11.6;27.7;8.6;3.3;5.2;11.9;14.8 +21.9;85.7;44.2;6.7;11.6;27.8;8.6;3.3;5.2;11.9;14.9 +21.9;85.8;44.3;6.7;11.6;27.8;8.6;3.3;5.2;11.9;14.9 +21.9;85.8;44.4;6.7;11.6;27.8;8.6;3.3;5.2;11.9;14.9 +21.9;85.8;44.4;6.7;11.6;27.8;8.6;3.3;5.2;11.9;14.9 +21.9;85.8;44.4;6.7;11.6;27.8;8.6;3.3;5.2;11.9;14.9 +21.8;85.7;44.3;6.7;11.6;27.8;8.5;3.3;5.2;11.8;14.9 +21.7;85.4;44.2;6.7;11.5;27.7;8.5;3.3;5.2;11.8;14.9 +21.6;85.1;44.0;6.6;11.5;27.6;8.5;3.3;5.1;11.7;14.8 +21.5;84.7;43.8;6.6;11.4;27.5;8.4;3.3;5.1;11.6;14.8 +21.4;84.3;43.6;6.6;11.4;27.4;8.4;3.2;5.1;11.6;14.7 +21.3;83.9;43.4;6.5;11.3;27.3;8.3;3.2;5.0;11.5;14.6 +21.2;83.6;43.2;6.5;11.3;27.2;8.3;3.2;5.0;11.4;14.6 +21.2;83.3;43.1;6.5;11.2;27.1;8.3;3.2;5.0;11.3;14.6 +21.1;83.1;43.0;6.4;11.2;27.0;8.2;3.2;5.0;11.3;14.5 +21.1;82.9;42.9;6.4;11.2;27.0;8.2;3.2;4.9;11.3;14.5 +21.0;82.7;42.8;6.4;11.1;26.9;8.2;3.2;4.9;11.2;14.5 +21.0;82.5;42.8;6.4;11.1;26.9;8.2;3.2;4.9;11.2;14.5 +21.0;82.2;42.7;6.4;11.1;26.8;8.2;3.1;4.9;11.2;14.4 +20.9;82.0;42.5;6.4;11.0;26.7;8.1;3.1;4.9;11.1;14.4 +20.9;81.7;42.4;6.3;11.0;26.6;8.1;3.1;4.9;11.1;14.3 +20.8;81.5;42.2;6.3;11.0;26.6;8.1;3.1;4.8;11.0;14.3 +20.7;81.2;42.0;6.3;10.9;26.5;8.1;3.1;4.8;11.0;14.2 +20.7;81.0;41.9;6.3;10.9;26.4;8.0;3.1;4.8;10.9;14.2 +20.6;80.8;41.8;6.2;10.9;26.3;8.0;3.1;4.8;10.9;14.2 +20.6;80.6;41.7;6.2;10.9;26.3;8.0;3.1;4.8;10.8;14.2 +20.5;80.5;41.7;6.2;10.8;26.3;8.0;3.1;4.8;10.8;14.1 +20.5;80.5;41.6;6.2;10.8;26.3;8.0;3.1;4.7;10.8;14.1 +20.5;80.4;41.6;6.2;10.8;26.3;8.0;3.1;4.7;10.8;14.1 +20.4;80.4;41.6;6.2;10.8;26.3;8.0;3.1;4.7;10.7;14.1 +20.4;80.3;41.6;6.2;10.8;26.3;7.9;3.1;4.7;10.7;14.1 +20.4;80.2;41.6;6.2;10.8;26.2;7.9;3.1;4.7;10.7;14.1 +20.3;80.0;41.5;6.2;10.7;26.2;7.9;3.0;4.7;10.7;14.1 +20.3;79.9;41.4;6.2;10.7;26.1;7.9;3.0;4.7;10.7;14.1 +20.3;79.8;41.4;6.2;10.7;26.1;7.9;3.0;4.7;10.7;14.1 +20.3;79.7;41.3;6.2;10.7;26.1;7.9;3.0;4.7;10.7;14.1 +20.3;79.7;41.3;6.1;10.7;26.1;7.9;3.0;4.7;10.7;14.1 +20.3;79.7;41.4;6.1;10.7;26.1;7.9;3.0;4.7;10.7;14.1 +20.3;79.7;41.4;6.2;10.7;26.2;7.9;3.0;4.7;10.7;14.1 +20.3;79.8;41.5;6.2;10.7;26.3;7.9;3.1;4.7;10.7;14.1 +20.3;79.9;41.6;6.2;10.8;26.3;7.9;3.1;4.7;10.7;14.1 +20.4;80.0;41.6;6.2;10.8;26.4;7.9;3.1;4.7;10.8;14.1 +20.4;80.0;41.7;6.2;10.8;26.5;7.9;3.1;4.7;10.8;14.1 +20.4;80.0;41.7;6.2;10.8;26.5;7.9;3.1;4.7;10.8;14.1 +20.4;80.0;41.7;6.2;10.8;26.5;7.9;3.1;4.7;10.8;14.1 +20.4;80.0;41.7;6.2;10.8;26.5;8.0;3.1;4.8;10.8;14.1 +20.4;79.9;41.6;6.2;10.8;26.5;8.0;3.1;4.8;10.8;14.1 +20.4;79.9;41.6;6.2;10.8;26.5;8.0;3.1;4.8;10.8;14.1 +20.4;79.9;41.6;6.2;10.8;26.6;8.0;3.1;4.8;10.8;14.1 +20.4;80.0;41.7;6.2;10.8;26.6;8.0;3.1;4.8;10.8;14.1 +20.4;80.1;41.7;6.2;10.8;26.7;8.0;3.1;4.8;10.9;14.1 +20.4;80.2;41.8;6.2;10.8;26.8;8.0;3.1;4.8;10.9;14.1 +20.4;80.3;41.9;6.2;10.8;26.8;8.0;3.1;4.8;10.9;14.1 +20.4;80.4;42.0;6.3;10.8;26.9;8.1;3.1;4.8;11.0;14.2 +20.5;80.5;42.1;6.3;10.8;27.0;8.1;3.1;4.8;11.0;14.2 +20.5;80.5;42.2;6.3;10.8;27.0;8.1;3.1;4.8;11.0;14.2 +20.5;80.5;42.2;6.3;10.8;27.1;8.1;3.1;4.9;10.9;14.2 +20.5;80.5;42.3;6.3;10.8;27.1;8.1;3.1;4.8;10.9;14.2 +20.5;80.4;42.3;6.3;10.8;27.1;8.1;3.1;4.8;10.8;14.2 +20.5;80.4;42.3;6.3;10.8;27.1;8.1;3.1;4.8;10.8;14.2 +20.5;80.4;42.4;6.3;10.8;27.1;8.1;3.1;4.8;10.8;14.2 +20.5;80.4;42.4;6.3;10.9;27.2;8.1;3.1;4.8;10.8;14.2 +20.5;80.4;42.5;6.3;10.9;27.2;8.1;3.1;4.8;10.8;14.2 +20.5;80.5;42.6;6.3;10.9;27.3;8.1;3.1;4.8;10.8;14.2 +20.5;80.6;42.6;6.3;10.9;27.3;8.1;3.1;4.8;10.8;14.3 +20.5;80.7;42.7;6.3;10.9;27.4;8.1;3.1;4.8;10.8;14.3 +20.5;80.9;42.8;6.3;10.9;27.4;8.1;3.1;4.8;10.9;14.3 +20.6;81.0;42.9;6.4;10.9;27.4;8.1;3.1;4.8;10.9;14.3 +20.6;81.2;42.9;6.4;10.9;27.4;8.1;3.1;4.8;10.9;14.4 +20.6;81.3;43.0;6.4;10.9;27.3;8.1;3.1;4.8;10.9;14.4 +20.7;81.5;43.0;6.4;10.9;27.3;8.1;3.1;4.8;11.0;14.4 +20.7;81.6;43.0;6.4;10.9;27.3;8.1;3.1;4.9;11.0;14.4 +20.7;81.7;43.1;6.4;10.9;27.3;8.1;3.1;4.9;11.0;14.5 +20.8;81.8;43.1;6.4;10.9;27.4;8.1;3.2;4.9;11.1;14.5 +20.8;81.9;43.0;6.4;10.9;27.4;8.1;3.2;4.9;11.1;14.5 +20.8;82.0;43.0;6.4;10.9;27.5;8.1;3.2;4.9;11.1;14.5 +20.8;82.1;43.0;6.4;10.9;27.5;8.1;3.2;5.0;11.2;14.4 +20.8;82.1;43.0;6.4;11.0;27.6;8.2;3.2;5.0;11.2;14.4 +20.8;82.2;43.1;6.4;11.0;27.7;8.2;3.2;5.0;11.3;14.5 +20.9;82.3;43.1;6.4;11.0;27.8;8.2;3.2;5.0;11.3;14.5 +20.9;82.4;43.2;6.5;11.0;27.8;8.2;3.2;5.1;11.4;14.5 +20.9;82.5;43.3;6.5;11.1;27.9;8.3;3.3;5.1;11.4;14.5 +20.9;82.7;43.5;6.5;11.1;28.0;8.3;3.3;5.1;11.5;14.6 +21.0;82.9;43.6;6.5;11.2;28.0;8.3;3.3;5.1;11.5;14.6 +21.0;83.1;43.8;6.6;11.2;28.1;8.3;3.3;5.1;11.6;14.6 +21.0;83.3;43.9;6.6;11.2;28.2;8.4;3.3;5.2;11.6;14.7 +21.1;83.6;44.1;6.6;11.3;28.2;8.4;3.3;5.2;11.7;14.7 +21.2;83.8;44.2;6.7;11.3;28.3;8.4;3.3;5.2;11.7;14.8 +21.2;84.1;44.4;6.7;11.4;28.3;8.4;3.4;5.2;11.8;14.8 +21.3;84.4;44.5;6.7;11.4;28.4;8.5;3.4;5.3;11.8;14.8 +21.3;84.6;44.6;6.7;11.4;28.4;8.5;3.4;5.3;11.8;14.9 +21.4;84.9;44.8;6.8;11.4;28.5;8.5;3.4;5.3;11.9;14.9 +21.4;85.1;44.9;6.8;11.5;28.5;8.5;3.4;5.3;11.9;14.9 +21.5;85.3;45.0;6.8;11.5;28.5;8.5;3.4;5.3;11.9;15.0 +21.5;85.5;45.1;6.8;11.5;28.5;8.5;3.4;5.3;11.9;15.0 +21.6;85.7;45.2;6.8;11.5;28.5;8.5;3.4;5.3;12.0;15.0 +21.6;85.9;45.2;6.9;11.5;28.5;8.5;3.4;5.4;12.0;15.0 +21.7;86.1;45.3;6.9;11.6;28.5;8.5;3.5;5.4;12.0;15.0 +21.7;86.3;45.4;6.9;11.6;28.5;8.5;3.5;5.4;12.0;15.0 +21.8;86.5;45.4;6.9;11.6;28.5;8.5;3.5;5.4;12.1;15.1 +21.8;86.6;45.5;7.0;11.6;28.5;8.5;3.5;5.4;12.1;15.1 +21.9;86.8;45.5;7.0;11.6;28.4;8.6;3.5;5.4;12.1;15.1 +21.9;86.9;45.5;7.0;11.7;28.4;8.6;3.5;5.4;12.1;15.0 +21.9;87.0;45.6;7.0;11.7;28.4;8.6;3.5;5.4;12.1;15.0 +21.9;87.0;45.6;7.0;11.7;28.3;8.6;3.5;5.4;12.2;15.0 +21.9;87.1;45.6;7.0;11.7;28.3;8.6;3.5;5.4;12.2;15.0 +21.9;87.1;45.6;7.0;11.7;28.2;8.5;3.5;5.4;12.2;15.0 +21.9;87.2;45.6;7.1;11.7;28.2;8.5;3.5;5.4;12.2;15.0 +21.9;87.2;45.6;7.1;11.7;28.2;8.5;3.5;5.5;12.2;15.0 +22.0;87.3;45.6;7.1;11.7;28.1;8.5;3.5;5.5;12.2;15.0 +22.0;87.4;45.6;7.1;11.7;28.1;8.5;3.5;5.5;12.2;15.0 +22.0;87.4;45.6;7.1;11.7;28.1;8.5;3.5;5.5;12.2;15.0 +22.0;87.5;45.6;7.1;11.7;28.1;8.5;3.5;5.5;12.2;15.0 +22.0;87.6;45.6;7.1;11.7;28.1;8.5;3.6;5.5;12.3;15.0 +22.1;87.7;45.6;7.2;11.7;28.1;8.5;3.6;5.5;12.3;15.0 +22.1;87.8;45.6;7.2;11.7;28.0;8.5;3.6;5.5;12.3;15.0 +22.1;87.8;45.6;7.2;11.8;28.0;8.5;3.6;5.5;12.3;15.0 +22.1;87.9;45.6;7.2;11.8;28.0;8.6;3.6;5.5;12.4;15.0 +22.1;88.0;45.6;7.2;11.8;28.0;8.6;3.6;5.5;12.4;15.0 +22.1;88.1;45.6;7.2;11.8;27.9;8.6;3.6;5.5;12.4;15.0 +22.1;88.1;45.7;7.2;11.8;27.9;8.6;3.6;5.6;12.5;15.0 +22.1;88.2;45.7;7.2;11.8;27.9;8.6;3.6;5.6;12.5;14.9 +22.1;88.3;45.7;7.2;11.8;27.9;8.6;3.6;5.6;12.5;14.9 +22.1;88.4;45.7;7.3;11.8;27.9;8.6;3.6;5.6;12.5;14.9 +22.1;88.5;45.7;7.3;11.8;27.9;8.6;3.6;5.6;12.5;14.9 +22.1;88.6;45.7;7.3;11.8;27.9;8.6;3.6;5.6;12.5;14.9 +22.1;88.7;45.7;7.3;11.8;27.9;8.6;3.6;5.6;12.6;14.9 +22.1;88.8;45.8;7.3;11.8;28.0;8.6;3.6;5.6;12.6;14.9 +22.2;89.0;45.9;7.3;11.9;28.0;8.6;3.6;5.7;12.6;14.9 +22.2;89.1;45.9;7.3;11.9;28.0;8.6;3.7;5.7;12.7;14.9 +22.2;89.1;46.0;7.4;11.9;28.0;8.7;3.7;5.7;12.7;14.9 +22.2;89.1;45.9;7.4;11.9;28.0;8.7;3.7;5.7;12.7;14.9 +22.2;88.9;45.8;7.3;11.8;27.9;8.6;3.7;5.7;12.7;14.9 +22.1;88.7;45.7;7.3;11.8;27.8;8.6;3.6;5.6;12.6;14.8 +22.0;88.3;45.4;7.3;11.7;27.6;8.6;3.6;5.6;12.5;14.8 +21.9;87.8;45.1;7.2;11.7;27.4;8.5;3.6;5.6;12.4;14.7 +21.8;87.4;44.8;7.2;11.6;27.2;8.4;3.6;5.5;12.3;14.6 +21.6;86.9;44.5;7.2;11.5;27.0;8.4;3.6;5.5;12.2;14.5 +21.5;86.4;44.2;7.1;11.4;26.8;8.3;3.5;5.4;12.1;14.4 +21.4;85.9;43.9;7.1;11.4;26.6;8.2;3.5;5.4;12.0;14.3 +21.3;85.5;43.6;7.0;11.3;26.4;8.2;3.5;5.4;12.0;14.2 +21.1;85.2;43.4;7.0;11.2;26.3;8.1;3.5;5.3;11.9;14.1 +21.0;84.9;43.2;7.0;11.2;26.1;8.1;3.5;5.3;11.8;14.1 +21.0;84.6;43.0;7.0;11.1;26.0;8.1;3.5;5.3;11.8;14.0 +20.9;84.4;42.9;6.9;11.1;25.8;8.0;3.4;5.3;11.7;14.0 +20.8;84.3;42.7;6.9;11.1;25.7;8.0;3.4;5.2;11.7;13.9 +20.7;84.1;42.6;6.9;11.0;25.6;8.0;3.4;5.2;11.7;13.9 +20.7;84.0;42.5;6.9;11.0;25.6;8.0;3.4;5.2;11.7;13.9 +20.6;83.9;42.4;6.9;11.0;25.5;8.0;3.4;5.2;11.6;13.8 +20.5;83.8;42.2;6.9;10.9;25.4;7.9;3.4;5.2;11.6;13.8 +20.5;83.6;42.1;6.8;10.9;25.3;7.9;3.4;5.2;11.6;13.7 +20.4;83.3;41.9;6.8;10.8;25.2;7.9;3.4;5.2;11.5;13.7 +20.3;83.0;41.7;6.8;10.8;25.1;7.8;3.4;5.1;11.5;13.6 +20.2;82.7;41.5;6.8;10.7;24.9;7.8;3.3;5.1;11.4;13.5 +20.1;82.4;41.3;6.7;10.7;24.8;7.8;3.3;5.1;11.3;13.5 +20.1;82.2;41.2;6.7;10.7;24.7;7.7;3.3;5.1;11.3;13.4 +20.0;82.0;41.0;6.7;10.6;24.6;7.7;3.3;5.0;11.2;13.4 +19.9;81.9;40.9;6.7;10.6;24.5;7.7;3.3;5.0;11.2;13.3 +19.9;81.8;40.9;6.7;10.6;24.5;7.7;3.3;5.0;11.2;13.3 +19.8;81.8;40.8;6.7;10.5;24.4;7.7;3.3;5.0;11.2;13.3 +19.8;81.8;40.8;6.6;10.5;24.4;7.6;3.3;5.0;11.1;13.3 +19.8;81.8;40.7;6.6;10.5;24.3;7.6;3.3;5.0;11.1;13.3 +19.7;81.8;40.7;6.6;10.5;24.3;7.6;3.3;5.0;11.1;13.3 +19.7;81.7;40.6;6.6;10.5;24.3;7.6;3.3;5.0;11.1;13.2 +19.7;81.7;40.5;6.6;10.5;24.2;7.6;3.3;5.0;11.1;13.2 +19.6;81.6;40.4;6.6;10.4;24.2;7.6;3.2;5.0;11.0;13.2 +19.6;81.5;40.4;6.6;10.4;24.1;7.6;3.2;5.0;11.0;13.2 +19.6;81.4;40.3;6.6;10.4;24.1;7.5;3.2;5.0;11.0;13.2 +19.5;81.4;40.2;6.6;10.4;24.1;7.5;3.2;5.0;11.0;13.2 +19.5;81.4;40.2;6.6;10.4;24.0;7.5;3.2;5.0;10.9;13.1 +19.5;81.4;40.1;6.6;10.4;24.0;7.5;3.2;5.0;10.9;13.1 +19.5;81.4;40.1;6.6;10.4;24.0;7.5;3.2;5.0;10.9;13.1 +19.5;81.5;40.2;6.6;10.4;24.0;7.5;3.2;5.0;10.9;13.1 +19.4;81.5;40.2;6.6;10.4;24.0;7.5;3.2;5.0;10.9;13.1 +19.4;81.6;40.2;6.6;10.4;24.0;7.5;3.2;5.0;10.9;13.2 +19.4;81.7;40.2;6.6;10.4;24.0;7.5;3.2;5.0;10.9;13.2 +19.4;81.8;40.3;6.6;10.4;24.0;7.5;3.2;5.0;10.9;13.2 +19.4;82.0;40.3;6.6;10.4;24.0;7.5;3.2;4.9;10.8;13.2 +19.5;82.1;40.3;6.6;10.4;24.1;7.5;3.2;5.0;10.8;13.2 +19.5;82.3;40.4;6.6;10.4;24.1;7.5;3.2;5.0;10.8;13.2 +19.5;82.5;40.4;6.6;10.4;24.1;7.5;3.2;5.0;10.9;13.3 +19.6;82.8;40.5;6.6;10.4;24.2;7.5;3.2;5.0;10.9;13.3 +19.7;83.1;40.6;6.6;10.4;24.3;7.5;3.2;5.0;10.9;13.3 +19.8;83.5;40.7;6.6;10.4;24.4;7.5;3.2;5.0;10.9;13.3 +19.9;83.9;40.8;6.6;10.4;24.5;7.6;3.2;5.0;11.0;13.4 +20.0;84.4;41.0;6.7;10.4;24.6;7.6;3.2;5.0;11.0;13.5 +20.1;85.0;41.2;6.7;10.5;24.7;7.6;3.3;5.1;11.1;13.5 +20.3;85.6;41.5;6.7;10.5;24.8;7.6;3.3;5.1;11.1;13.6 +20.4;86.3;41.8;6.8;10.5;24.9;7.7;3.3;5.1;11.1;13.7 +20.6;87.0;42.2;6.8;10.6;25.1;7.7;3.3;5.1;11.2;13.9 +20.7;87.7;42.6;6.9;10.6;25.2;7.8;3.3;5.2;11.3;14.0 +20.9;88.4;43.0;6.9;10.7;25.4;7.8;3.3;5.2;11.3;14.1 +21.0;89.0;43.5;7.0;10.8;25.6;7.9;3.3;5.2;11.4;14.3 +21.1;89.6;44.0;7.0;10.9;25.8;7.9;3.4;5.3;11.5;14.4 +21.3;90.2;44.5;7.1;11.0;26.1;8.0;3.4;5.3;11.5;14.5 +21.4;90.7;45.0;7.2;11.2;26.4;8.1;3.4;5.3;11.6;14.7 +21.5;91.1;45.5;7.3;11.3;26.7;8.1;3.4;5.4;11.7;14.8 +21.6;91.6;45.9;7.4;11.4;27.0;8.2;3.5;5.4;11.8;14.9 +21.7;92.0;46.3;7.4;11.6;27.4;8.3;3.5;5.5;11.9;15.0 +21.8;92.5;46.6;7.5;11.7;27.8;8.5;3.5;5.6;12.0;15.1 +21.9;92.9;46.9;7.6;11.8;28.2;8.6;3.6;5.6;12.1;15.2 +22.0;93.3;47.1;7.6;11.9;28.6;8.7;3.6;5.7;12.3;15.3 +22.1;93.6;47.3;7.7;12.0;29.0;8.9;3.7;5.8;12.4;15.3 +22.2;93.8;47.5;7.7;12.1;29.4;9.0;3.7;5.9;12.5;15.4 +22.3;94.0;47.6;7.7;12.1;29.7;9.1;3.8;6.0;12.7;15.5 +22.3;94.1;47.8;7.7;12.2;29.9;9.2;3.8;6.0;12.9;15.5 +22.4;94.1;47.9;7.8;12.2;30.1;9.2;3.8;6.1;13.0;15.5 +22.4;94.0;48.0;7.8;12.2;30.2;9.3;3.9;6.2;13.2;15.5 +22.4;93.9;48.2;7.8;12.2;30.2;9.3;3.9;6.2;13.3;15.5 +22.3;93.8;48.2;7.8;12.2;30.2;9.3;3.9;6.2;13.4;15.5 +22.3;93.7;48.3;7.8;12.2;30.2;9.3;3.9;6.3;13.5;15.5 +22.3;93.6;48.3;7.8;12.2;30.2;9.3;3.9;6.3;13.6;15.5 +22.3;93.5;48.3;7.8;12.2;30.2;9.3;3.9;6.3;13.7;15.5 +22.2;93.4;48.3;7.8;12.2;30.2;9.3;3.9;6.3;13.7;15.4 +22.2;93.3;48.3;7.7;12.2;30.2;9.3;3.9;6.3;13.7;15.4 +22.1;93.1;48.2;7.7;12.1;30.1;9.3;3.9;6.3;13.7;15.4 +22.1;92.9;48.1;7.7;12.1;30.0;9.2;3.9;6.2;13.6;15.3 +22.0;92.7;47.9;7.7;12.1;29.9;9.2;3.9;6.2;13.6;15.3 +22.0;92.4;47.8;7.7;12.0;29.8;9.2;3.9;6.2;13.5;15.3 +21.9;92.1;47.6;7.6;12.0;29.7;9.1;3.8;6.2;13.5;15.2 +21.9;91.7;47.4;7.6;11.9;29.6;9.1;3.8;6.1;13.4;15.2 +21.8;91.4;47.3;7.6;11.9;29.5;9.0;3.8;6.1;13.3;15.1 +21.8;91.1;47.1;7.5;11.8;29.3;9.0;3.8;6.1;13.3;15.1 +21.7;90.8;46.9;7.5;11.8;29.2;9.0;3.8;6.1;13.2;15.0 +21.6;90.5;46.8;7.5;11.8;29.1;8.9;3.8;6.0;13.2;15.0 +21.5;90.2;46.7;7.5;11.7;29.1;8.9;3.7;6.0;13.1;14.9 +21.5;89.9;46.5;7.4;11.7;29.0;8.9;3.7;6.0;13.1;14.9 +21.4;89.5;46.4;7.4;11.6;28.9;8.9;3.7;6.0;13.0;14.8 +21.3;89.1;46.3;7.4;11.6;28.8;8.8;3.7;6.0;13.0;14.8 +21.3;88.7;46.1;7.4;11.5;28.7;8.8;3.7;5.9;12.9;14.7 +21.2;88.3;46.0;7.3;11.5;28.7;8.7;3.7;5.9;12.9;14.7 +21.1;87.8;45.8;7.3;11.4;28.6;8.7;3.7;5.9;12.8;14.7 +21.1;87.4;45.7;7.3;11.4;28.5;8.7;3.7;5.9;12.7;14.6 +21.0;86.9;45.5;7.3;11.3;28.4;8.6;3.6;5.8;12.6;14.6 +20.9;86.5;45.4;7.2;11.3;28.3;8.6;3.6;5.8;12.6;14.5 +20.8;86.0;45.2;7.2;11.2;28.2;8.5;3.6;5.8;12.5;14.5 +20.8;85.6;45.1;7.2;11.2;28.1;8.5;3.6;5.7;12.5;14.4 +20.7;85.3;44.9;7.2;11.1;28.0;8.5;3.6;5.7;12.4;14.4 +20.6;84.9;44.7;7.1;11.1;27.9;8.5;3.5;5.7;12.4;14.3 +20.6;84.6;44.6;7.1;11.1;27.8;8.4;3.5;5.7;12.3;14.3 +20.5;84.4;44.4;7.1;11.0;27.7;8.4;3.5;5.7;12.3;14.2 +20.4;84.2;44.3;7.1;11.0;27.7;8.4;3.5;5.6;12.3;14.2 +20.4;84.0;44.2;7.1;11.0;27.6;8.4;3.5;5.6;12.2;14.1 +20.3;83.9;44.2;7.0;11.0;27.6;8.3;3.5;5.6;12.2;14.1 +20.3;84.0;44.2;7.0;11.0;27.7;8.3;3.5;5.6;12.2;14.1 +20.4;84.1;44.3;7.1;11.0;27.8;8.4;3.5;5.6;12.3;14.1 +20.4;84.4;44.5;7.1;11.0;27.9;8.4;3.5;5.7;12.3;14.2 +20.6;84.8;44.8;7.1;11.1;28.1;8.4;3.5;5.7;12.4;14.3 +20.7;85.2;45.1;7.2;11.2;28.3;8.5;3.6;5.8;12.5;14.4 +20.9;85.7;45.4;7.3;11.2;28.5;8.6;3.6;5.8;12.6;14.5 +21.0;86.2;45.8;7.3;11.3;28.8;8.6;3.6;5.9;12.8;14.6 +21.1;86.6;46.0;7.4;11.4;28.9;8.7;3.6;5.9;12.9;14.6 +21.2;86.8;46.2;7.4;11.4;29.0;8.7;3.7;5.9;12.9;14.7 +21.2;86.8;46.2;7.4;11.4;29.1;8.8;3.7;5.9;12.9;14.7 +21.2;86.6;46.2;7.4;11.4;29.0;8.8;3.6;5.9;12.9;14.6 +21.1;86.4;46.0;7.3;11.3;28.9;8.7;3.6;5.9;12.9;14.6 +21.0;86.1;45.8;7.3;11.3;28.8;8.7;3.6;5.9;12.8;14.5 +20.9;85.8;45.7;7.3;11.2;28.7;8.7;3.6;5.9;12.8;14.4 +20.9;85.5;45.5;7.3;11.2;28.6;8.6;3.6;5.9;12.7;14.3 +20.8;85.4;45.5;7.2;11.2;28.6;8.6;3.6;5.8;12.7;14.3 +20.8;85.3;45.5;7.2;11.2;28.6;8.6;3.6;5.8;12.7;14.3 +20.9;85.3;45.5;7.2;11.2;28.6;8.6;3.6;5.8;12.7;14.3 +20.9;85.3;45.5;7.2;11.2;28.6;8.6;3.6;5.8;12.7;14.3 +20.9;85.3;45.6;7.2;11.1;28.6;8.6;3.6;5.8;12.7;14.3 +20.9;85.2;45.5;7.2;11.1;28.5;8.6;3.6;5.8;12.7;14.3 +20.9;85.0;45.5;7.2;11.1;28.5;8.6;3.6;5.8;12.6;14.3 +20.8;84.8;45.4;7.2;11.1;28.4;8.6;3.5;5.8;12.6;14.3 +20.7;84.5;45.2;7.2;11.0;28.2;8.5;3.5;5.8;12.5;14.2 +20.6;84.1;45.0;7.1;10.9;28.1;8.5;3.5;5.7;12.4;14.2 +20.5;83.6;44.7;7.1;10.9;27.9;8.4;3.5;5.7;12.3;14.1 +20.3;83.1;44.4;7.0;10.8;27.7;8.4;3.4;5.6;12.2;14.0 +20.2;82.5;44.1;7.0;10.7;27.4;8.3;3.4;5.6;12.1;13.9 +20.0;81.9;43.7;6.9;10.6;27.2;8.2;3.4;5.5;12.0;13.8 +19.9;81.2;43.4;6.9;10.5;27.0;8.1;3.4;5.5;11.8;13.8 +19.7;80.7;43.0;6.8;10.4;26.8;8.1;3.3;5.4;11.7;13.7 +19.6;80.1;42.7;6.8;10.4;26.6;8.0;3.3;5.4;11.6;13.6 +19.5;79.7;42.5;6.7;10.3;26.5;8.0;3.3;5.4;11.5;13.5 +19.4;79.4;42.4;6.7;10.3;26.4;7.9;3.3;5.3;11.5;13.5 +19.4;79.2;42.3;6.7;10.3;26.3;7.9;3.3;5.3;11.4;13.5 +19.4;79.1;42.2;6.7;10.2;26.3;7.9;3.2;5.3;11.4;13.5 +19.4;79.1;42.2;6.7;10.2;26.3;7.9;3.2;5.3;11.4;13.5 +19.4;79.0;42.1;6.7;10.2;26.2;7.9;3.2;5.3;11.4;13.5 +19.4;78.9;42.1;6.7;10.2;26.2;7.9;3.2;5.3;11.4;13.5 +19.4;78.8;42.0;6.7;10.2;26.2;7.9;3.2;5.3;11.3;13.5 +19.4;78.6;41.9;6.7;10.2;26.1;7.8;3.2;5.3;11.3;13.5 +19.3;78.5;41.8;6.7;10.1;26.0;7.8;3.2;5.2;11.3;13.5 +19.3;78.3;41.7;6.6;10.1;26.0;7.8;3.2;5.2;11.2;13.4 +19.3;78.1;41.6;6.6;10.1;25.9;7.8;3.2;5.2;11.2;13.4 +19.2;78.0;41.5;6.6;10.1;25.8;7.8;3.2;5.2;11.1;13.4 +19.2;77.9;41.5;6.6;10.0;25.8;7.7;3.2;5.2;11.1;13.4 +19.2;77.8;41.5;6.6;10.0;25.8;7.7;3.2;5.2;11.1;13.4 +19.2;77.7;41.5;6.6;10.0;25.8;7.7;3.2;5.2;11.1;13.4 +19.2;77.6;41.4;6.6;10.0;25.8;7.7;3.2;5.2;11.0;13.3 +19.1;77.4;41.4;6.6;10.0;25.7;7.7;3.1;5.2;11.0;13.3 +19.1;77.2;41.3;6.5;10.0;25.6;7.7;3.1;5.1;11.0;13.3 +19.0;76.8;41.1;6.5;9.9;25.5;7.7;3.1;5.1;10.9;13.2 +18.9;76.5;40.9;6.5;9.9;25.4;7.6;3.1;5.1;10.8;13.2 +18.8;76.0;40.6;6.4;9.8;25.2;7.6;3.1;5.0;10.8;13.1 +18.7;75.6;40.3;6.4;9.8;25.0;7.5;3.1;5.0;10.7;13.1 +18.6;75.2;40.1;6.4;9.7;24.9;7.5;3.0;5.0;10.6;13.0 +18.5;74.9;39.8;6.3;9.7;24.7;7.4;3.0;4.9;10.5;12.9 +18.4;74.7;39.6;6.3;9.6;24.6;7.4;3.0;4.9;10.5;12.9 +18.3;74.5;39.5;6.3;9.6;24.5;7.3;3.0;4.9;10.4;12.9 +18.3;74.3;39.3;6.2;9.6;24.4;7.3;3.0;4.9;10.4;12.9 +18.3;74.2;39.2;6.2;9.5;24.3;7.3;3.0;4.9;10.3;12.8 +18.2;74.1;39.1;6.2;9.5;24.3;7.3;3.0;4.8;10.3;12.8 +18.2;74.0;39.0;6.2;9.5;24.2;7.2;2.9;4.8;10.3;12.8 +18.1;73.8;38.8;6.2;9.5;24.1;7.2;2.9;4.8;10.2;12.8 +18.1;73.6;38.7;6.2;9.4;24.1;7.2;2.9;4.8;10.2;12.7 +18.0;73.3;38.5;6.1;9.4;24.0;7.2;2.9;4.8;10.1;12.7 +17.9;73.1;38.4;6.1;9.4;23.9;7.1;2.9;4.8;10.1;12.7 +17.9;73.0;38.2;6.1;9.3;23.9;7.1;2.9;4.7;10.0;12.6 +17.9;72.9;38.1;6.1;9.3;23.8;7.1;2.9;4.7;10.0;12.6 +17.8;72.8;38.1;6.1;9.3;23.8;7.1;2.9;4.7;10.0;12.6 +17.8;72.8;38.1;6.1;9.3;23.8;7.1;2.9;4.7;10.0;12.6 +17.8;72.9;38.0;6.1;9.3;23.8;7.1;2.9;4.7;10.0;12.6 +17.8;73.0;38.0;6.1;9.3;23.8;7.1;2.9;4.7;10.0;12.6 +17.8;73.1;38.0;6.1;9.3;23.8;7.1;2.9;4.7;10.0;12.7 +17.8;73.1;38.0;6.1;9.3;23.8;7.1;2.9;4.7;10.0;12.7 +17.8;73.2;38.0;6.1;9.3;23.8;7.1;2.9;4.7;10.0;12.7 +17.8;73.3;38.0;6.1;9.3;23.8;7.1;2.9;4.7;10.0;12.7 +17.8;73.3;37.9;6.1;9.3;23.8;7.1;2.9;4.7;10.1;12.7 +17.9;73.5;38.0;6.1;9.4;23.9;7.1;2.9;4.8;10.1;12.7 +17.9;73.7;38.0;6.1;9.4;24.0;7.1;2.9;4.8;10.1;12.7 +17.9;74.0;38.1;6.1;9.4;24.1;7.2;2.9;4.8;10.1;12.8 +18.0;74.3;38.3;6.2;9.5;24.2;7.2;2.9;4.8;10.2;12.8 +18.1;74.8;38.5;6.2;9.5;24.4;7.2;2.9;4.9;10.3;12.9 +18.2;75.3;38.8;6.2;9.6;24.5;7.3;2.9;4.9;10.4;13.0 +18.3;75.9;39.0;6.3;9.7;24.7;7.3;3.0;4.9;10.5;13.0 +18.4;76.4;39.3;6.3;9.7;24.9;7.4;3.0;5.0;10.5;13.1 +18.5;76.9;39.5;6.4;9.8;25.0;7.5;3.0;5.0;10.6;13.2 +18.6;77.3;39.7;6.4;9.9;25.2;7.5;3.0;5.1;10.7;13.3 +18.7;77.7;39.9;6.4;9.9;25.3;7.5;3.0;5.1;10.8;13.3 +18.7;78.1;40.0;6.5;10.0;25.4;7.6;3.1;5.1;10.8;13.4 +18.8;78.5;40.2;6.5;10.0;25.5;7.6;3.1;5.2;10.9;13.5 +18.9;78.9;40.4;6.5;10.1;25.7;7.7;3.1;5.2;11.0;13.6 +19.0;79.5;40.7;6.6;10.2;25.9;7.7;3.1;5.2;11.1;13.6 +19.2;80.3;41.0;6.6;10.2;26.1;7.8;3.1;5.3;11.3;13.7 +19.4;81.1;41.4;6.7;10.3;26.4;7.9;3.2;5.4;11.4;13.8 +19.5;82.0;41.9;6.8;10.4;26.7;8.0;3.2;5.4;11.6;14.0 +19.7;83.0;42.3;6.8;10.6;27.0;8.1;3.2;5.5;11.7;14.1 +19.9;83.9;42.8;6.9;10.7;27.3;8.2;3.3;5.6;11.9;14.2 +20.1;84.8;43.2;7.0;10.8;27.6;8.3;3.3;5.6;12.0;14.3 +20.3;85.7;43.7;7.1;10.9;27.9;8.4;3.4;5.7;12.1;14.5 +20.4;86.5;44.1;7.1;10.9;28.1;8.5;3.4;5.7;12.2;14.6 +20.6;87.2;44.4;7.2;11.0;28.3;8.5;3.4;5.8;12.3;14.7 +20.7;88.0;44.8;7.3;11.1;28.5;8.6;3.4;5.8;12.4;14.8 +20.8;88.7;45.2;7.3;11.2;28.6;8.7;3.5;5.9;12.5;15.0 +21.0;89.4;45.5;7.4;11.3;28.8;8.8;3.5;5.9;12.5;15.1 +21.1;90.2;45.9;7.5;11.4;29.1;8.8;3.5;6.0;12.6;15.2 +21.3;90.9;46.3;7.5;11.4;29.3;8.9;3.5;6.0;12.8;15.3 +21.4;91.7;46.6;7.6;11.5;29.5;8.9;3.6;6.0;12.9;15.4 +21.6;92.4;47.0;7.6;11.6;29.7;9.0;3.6;6.1;13.0;15.5 +21.7;93.1;47.3;7.7;11.7;29.9;9.0;3.6;6.1;13.1;15.6 +21.9;93.8;47.6;7.7;11.8;30.1;9.1;3.6;6.1;13.2;15.7 +22.0;94.4;47.9;7.8;11.9;30.3;9.1;3.6;6.2;13.3;15.8 +22.1;94.9;48.1;7.8;11.9;30.4;9.1;3.6;6.2;13.4;15.9 +22.3;95.4;48.3;7.8;11.9;30.5;9.1;3.7;6.2;13.4;15.9 +22.4;95.8;48.5;7.9;12.0;30.5;9.2;3.7;6.2;13.5;16.0 +22.4;96.2;48.6;7.9;12.0;30.6;9.2;3.7;6.3;13.5;16.0 +22.5;96.5;48.7;7.9;12.0;30.7;9.2;3.7;6.3;13.6;16.1 +22.6;96.8;48.8;7.9;12.1;30.7;9.2;3.7;6.3;13.6;16.1 +22.6;97.0;48.8;7.9;12.1;30.8;9.3;3.7;6.3;13.7;16.1 +22.7;97.1;48.8;7.9;12.1;30.9;9.3;3.7;6.3;13.7;16.1 +22.7;97.2;48.9;8.0;12.1;31.0;9.3;3.7;6.3;13.7;16.2 +22.7;97.3;48.9;8.0;12.2;31.1;9.3;3.7;6.3;13.8;16.2 +22.8;97.4;48.9;8.0;12.2;31.2;9.4;3.7;6.4;13.8;16.2 +22.8;97.5;48.9;8.0;12.2;31.3;9.4;3.7;6.4;13.9;16.2 +22.8;97.6;49.0;8.0;12.2;31.4;9.4;3.7;6.4;13.9;16.2 +22.8;97.8;49.0;8.0;12.3;31.5;9.4;3.8;6.4;13.9;16.2 +22.8;97.9;49.1;8.0;12.3;31.5;9.4;3.8;6.4;14.0;16.3 +22.8;98.0;49.2;8.1;12.3;31.6;9.5;3.8;6.4;14.0;16.3 +22.8;98.1;49.3;8.1;12.3;31.7;9.5;3.8;6.4;14.0;16.3 +22.8;98.3;49.3;8.1;12.4;31.8;9.5;3.8;6.4;14.1;16.3 +22.8;98.4;49.4;8.1;12.4;31.8;9.5;3.8;6.4;14.1;16.3 +22.9;98.6;49.5;8.1;12.4;31.9;9.5;3.8;6.4;14.1;16.4 +22.9;98.7;49.6;8.1;12.4;31.9;9.6;3.8;6.4;14.2;16.4 +22.9;98.8;49.7;8.1;12.5;31.9;9.6;3.8;6.4;14.2;16.4 +22.9;99.0;49.7;8.1;12.5;32.0;9.6;3.9;6.5;14.2;16.4 +23.0;99.1;49.8;8.1;12.5;32.0;9.6;3.9;6.5;14.2;16.4 +23.0;99.2;49.8;8.2;12.5;32.0;9.6;3.9;6.5;14.2;16.4 +23.0;99.3;49.8;8.2;12.5;32.1;9.6;3.9;6.4;14.2;16.4 +23.0;99.3;49.9;8.2;12.5;32.1;9.6;3.9;6.4;14.3;16.4 +23.1;99.4;49.9;8.2;12.5;32.1;9.6;3.9;6.4;14.3;16.4 +23.1;99.4;49.9;8.2;12.5;32.2;9.6;3.9;6.4;14.3;16.4 +23.1;99.4;50.0;8.2;12.5;32.2;9.6;3.9;6.4;14.3;16.4 +23.1;99.4;50.0;8.2;12.5;32.2;9.6;3.9;6.4;14.3;16.4 +23.1;99.5;50.1;8.2;12.5;32.2;9.7;3.9;6.4;14.3;16.4 +23.1;99.5;50.1;8.2;12.5;32.2;9.7;3.9;6.4;14.3;16.4 +23.2;99.5;50.2;8.2;12.5;32.2;9.7;3.9;6.4;14.4;16.4 +23.2;99.5;50.3;8.2;12.5;32.2;9.7;3.9;6.4;14.4;16.4 +23.2;99.5;50.3;8.2;12.5;32.2;9.7;3.9;6.4;14.4;16.4 +23.2;99.5;50.4;8.2;12.5;32.2;9.7;3.9;6.4;14.4;16.4 +23.2;99.5;50.4;8.2;12.5;32.2;9.7;3.9;6.4;14.4;16.4 +23.2;99.5;50.5;8.2;12.5;32.2;9.7;3.9;6.4;14.4;16.4 +23.2;99.5;50.5;8.2;12.5;32.2;9.7;4.0;6.4;14.4;16.4 +23.2;99.6;50.6;8.2;12.5;32.2;9.7;4.0;6.4;14.4;16.4 +23.3;99.6;50.7;8.2;12.5;32.2;9.7;4.0;6.4;14.4;16.4 +23.3;99.7;50.7;8.2;12.5;32.3;9.7;4.0;6.4;14.4;16.4 +23.3;99.8;50.8;8.3;12.5;32.3;9.8;4.0;6.4;14.5;16.4 +23.3;99.8;50.9;8.3;12.5;32.4;9.8;4.0;6.4;14.5;16.4 +23.4;99.9;51.0;8.3;12.5;32.5;9.8;4.0;6.5;14.5;16.4 +23.4;100.0;51.1;8.3;12.5;32.5;9.8;4.0;6.5;14.5;16.4 +23.4;100.1;51.2;8.3;12.5;32.6;9.8;4.0;6.5;14.6;16.4 +23.5;100.2;51.3;8.3;12.5;32.7;9.9;4.0;6.5;14.6;16.4 +23.5;100.3;51.4;8.4;12.5;32.7;9.9;4.0;6.5;14.6;16.4 +23.6;100.3;51.5;8.4;12.5;32.8;9.9;4.0;6.5;14.7;16.4 +23.6;100.3;51.5;8.4;12.5;32.8;9.9;4.0;6.5;14.7;16.4 +23.6;100.3;51.5;8.4;12.5;32.8;9.9;4.0;6.5;14.7;16.4 +23.6;100.2;51.5;8.4;12.5;32.8;9.9;4.0;6.5;14.7;16.4 +23.5;100.0;51.5;8.3;12.5;32.7;9.9;4.0;6.5;14.7;16.3 +23.5;99.8;51.4;8.3;12.4;32.7;9.9;4.0;6.5;14.7;16.3 +23.5;99.6;51.3;8.3;12.4;32.6;9.9;4.0;6.5;14.7;16.2 +23.5;99.5;51.3;8.3;12.4;32.6;9.9;4.0;6.5;14.6;16.2 +23.5;99.4;51.3;8.3;12.4;32.6;9.9;4.0;6.5;14.6;16.2 +23.5;99.4;51.3;8.3;12.4;32.6;9.9;4.0;6.5;14.7;16.2 +23.5;99.4;51.4;8.3;12.4;32.6;9.9;4.0;6.5;14.7;16.2 +23.6;99.4;51.6;8.3;12.4;32.7;9.9;4.0;6.5;14.8;16.2 +23.6;99.5;51.7;8.3;12.4;32.7;10.0;4.0;6.5;14.8;16.2 +23.6;99.5;51.8;8.4;12.4;32.7;10.0;4.0;6.5;14.8;16.2 +23.6;99.4;51.8;8.4;12.4;32.7;10.0;4.0;6.5;14.9;16.2 +23.6;99.3;51.8;8.4;12.4;32.7;10.0;4.0;6.5;14.9;16.1 +23.6;99.1;51.8;8.4;12.4;32.7;10.0;4.0;6.5;14.8;16.1 +23.6;98.8;51.7;8.3;12.3;32.6;9.9;4.0;6.5;14.8;16.0 +23.5;98.6;51.6;8.3;12.3;32.5;9.9;4.0;6.5;14.8;16.0 +23.5;98.3;51.5;8.3;12.2;32.5;9.9;4.0;6.5;14.7;15.9 +23.4;98.1;51.4;8.3;12.2;32.4;9.9;4.0;6.5;14.7;15.8 +23.4;97.9;51.4;8.3;12.2;32.3;9.9;4.0;6.4;14.7;15.8 +23.4;97.8;51.4;8.3;12.1;32.3;9.9;4.0;6.4;14.6;15.8 +23.4;97.7;51.4;8.3;12.1;32.3;9.9;4.0;6.4;14.6;15.7 +23.4;97.6;51.4;8.3;12.1;32.2;9.9;4.0;6.4;14.6;15.7 +23.4;97.6;51.4;8.3;12.1;32.2;9.9;4.0;6.4;14.6;15.7 +23.4;97.5;51.4;8.3;12.1;32.2;9.9;4.0;6.4;14.6;15.6 +23.4;97.4;51.5;8.3;12.1;32.2;9.9;4.0;6.4;14.6;15.6 +23.4;97.3;51.5;8.3;12.1;32.1;9.9;4.0;6.4;14.6;15.6 +23.4;97.2;51.4;8.2;12.1;32.1;9.9;4.0;6.4;14.6;15.6 +23.3;97.0;51.4;8.2;12.1;32.1;9.9;4.0;6.4;14.6;15.5 +23.3;96.8;51.4;8.2;12.0;32.0;9.9;4.0;6.4;14.6;15.5 +23.3;96.5;51.3;8.2;12.0;31.9;9.9;4.0;6.4;14.6;15.5 +23.2;96.2;51.1;8.2;12.0;31.8;9.8;4.0;6.4;14.6;15.4 +23.2;95.9;51.0;8.2;11.9;31.7;9.8;3.9;6.3;14.5;15.4 +23.1;95.6;50.8;8.1;11.9;31.6;9.8;3.9;6.3;14.5;15.3 +23.0;95.3;50.6;8.1;11.8;31.5;9.7;3.9;6.3;14.4;15.2 +23.0;94.9;50.5;8.1;11.8;31.4;9.7;3.9;6.3;14.3;15.2 +22.9;94.6;50.3;8.1;11.7;31.3;9.7;3.9;6.2;14.3;15.1 +22.9;94.4;50.2;8.1;11.7;31.2;9.7;3.9;6.2;14.2;15.1 +22.9;94.2;50.2;8.1;11.7;31.1;9.6;3.9;6.2;14.2;15.1 +22.8;94.0;50.1;8.0;11.6;31.0;9.6;3.9;6.2;14.2;15.0 +22.8;93.9;50.1;8.0;11.6;31.0;9.6;3.9;6.2;14.2;15.0 +22.8;93.8;50.1;8.0;11.6;30.9;9.6;3.9;6.2;14.1;15.0 +22.8;93.7;50.0;8.0;11.6;30.9;9.6;3.9;6.2;14.1;15.0 +22.8;93.6;50.0;8.0;11.6;30.8;9.6;3.9;6.2;14.1;14.9 +22.7;93.5;49.9;8.0;11.6;30.8;9.6;3.9;6.2;14.1;14.9 +22.7;93.4;49.8;8.0;11.5;30.7;9.6;3.9;6.1;14.1;14.9 +22.7;93.4;49.8;8.0;11.5;30.7;9.6;3.9;6.1;14.0;14.9 +22.7;93.3;49.7;8.0;11.5;30.6;9.6;3.9;6.1;14.0;14.8 +22.7;93.2;49.6;8.0;11.5;30.6;9.6;3.9;6.1;14.0;14.8 +22.7;93.1;49.6;8.0;11.5;30.5;9.6;3.8;6.1;14.0;14.8 +22.7;93.1;49.5;8.0;11.5;30.5;9.5;3.8;6.1;13.9;14.8 +22.7;93.0;49.5;8.0;11.5;30.4;9.5;3.8;6.1;13.9;14.8 +22.7;92.9;49.5;8.0;11.5;30.4;9.5;3.8;6.1;13.9;14.8 +22.7;92.9;49.4;8.0;11.4;30.4;9.5;3.8;6.1;13.9;14.8 +22.7;92.9;49.4;8.0;11.4;30.3;9.5;3.8;6.1;13.9;14.8 +22.7;92.9;49.4;8.0;11.4;30.3;9.5;3.8;6.0;13.8;14.8 +22.8;93.0;49.3;7.9;11.4;30.3;9.5;3.8;6.0;13.8;14.8 +22.8;93.1;49.3;7.9;11.4;30.3;9.5;3.8;6.0;13.8;14.8 +22.8;93.2;49.3;7.9;11.4;30.2;9.5;3.8;6.0;13.8;14.8 +22.8;93.3;49.2;7.9;11.4;30.2;9.5;3.8;6.0;13.8;14.8 +22.9;93.4;49.2;7.9;11.4;30.2;9.5;3.8;6.0;13.8;14.8 +22.9;93.5;49.2;7.9;11.4;30.1;9.5;3.8;6.0;13.7;14.8 +23.0;93.7;49.2;8.0;11.4;30.1;9.5;3.8;6.0;13.7;14.9 +23.1;93.9;49.2;8.0;11.4;30.1;9.5;3.8;6.0;13.7;14.9 +23.2;94.2;49.3;8.0;11.4;30.1;9.5;3.8;6.0;13.7;14.9 +23.3;94.6;49.4;8.0;11.4;30.1;9.5;3.8;6.0;13.7;15.0 +23.4;95.0;49.5;8.0;11.4;30.1;9.5;3.8;6.0;13.7;15.1 +23.5;95.6;49.7;8.0;11.5;30.1;9.5;3.8;6.0;13.7;15.1 +23.6;96.3;49.9;8.1;11.5;30.2;9.5;3.8;6.0;13.8;15.2 +23.7;97.0;50.2;8.1;11.5;30.2;9.6;3.8;6.0;13.8;15.4 +23.9;97.7;50.4;8.1;11.6;30.3;9.6;3.8;6.0;13.8;15.5 +24.0;98.4;50.7;8.2;11.6;30.4;9.6;3.8;6.1;13.9;15.6 +24.1;99.0;51.0;8.2;11.7;30.5;9.6;3.9;6.1;13.9;15.7 +24.2;99.6;51.2;8.2;11.8;30.7;9.7;3.9;6.1;13.9;15.8 +24.2;100.1;51.5;8.3;11.9;30.9;9.7;3.9;6.1;14.0;15.9 +24.3;100.5;51.7;8.4;12.0;31.1;9.8;3.9;6.1;14.0;16.0 +24.3;100.9;51.9;8.4;12.1;31.3;9.8;3.9;6.2;14.1;16.1 +24.4;101.3;52.2;8.5;12.2;31.6;9.9;3.9;6.2;14.1;16.1 +24.5;101.7;52.4;8.6;12.3;31.9;10.0;4.0;6.3;14.2;16.2 +24.5;102.1;52.7;8.6;12.4;32.2;10.1;4.0;6.3;14.3;16.3 +24.6;102.5;52.9;8.7;12.5;32.6;10.2;4.0;6.4;14.4;16.4 +24.7;102.9;53.2;8.7;12.6;32.9;10.3;4.1;6.5;14.6;16.5 +24.7;103.3;53.3;8.8;12.7;33.3;10.4;4.1;6.6;14.7;16.5 +24.8;103.6;53.5;8.8;12.7;33.5;10.5;4.2;6.6;14.8;16.6 +24.8;103.8;53.6;8.8;12.8;33.7;10.6;4.2;6.7;15.0;16.6 +24.8;103.8;53.6;8.8;12.8;33.8;10.6;4.2;6.8;15.1;16.6 +24.8;103.8;53.5;8.8;12.8;33.9;10.7;4.2;6.8;15.2;16.6 +24.7;103.6;53.3;8.8;12.8;33.8;10.7;4.2;6.8;15.3;16.6 +24.6;103.4;53.2;8.7;12.8;33.7;10.6;4.2;6.9;15.3;16.5 +24.6;103.1;52.9;8.7;12.8;33.6;10.6;4.2;6.9;15.4;16.5 +24.5;102.7;52.7;8.7;12.7;33.5;10.6;4.2;6.9;15.4;16.4 +24.3;102.4;52.4;8.6;12.7;33.3;10.5;4.2;6.9;15.4;16.4 +24.2;102.0;52.1;8.6;12.6;33.2;10.5;4.2;6.9;15.4;16.3 +24.1;101.6;51.8;8.5;12.6;33.1;10.4;4.2;6.9;15.4;16.3 +24.0;101.2;51.5;8.5;12.5;32.9;10.4;4.2;6.9;15.3;16.2 +23.9;100.8;51.2;8.5;12.5;32.7;10.4;4.1;6.8;15.2;16.1 +23.7;100.3;50.9;8.4;12.4;32.5;10.3;4.1;6.8;15.1;16.1 +23.6;99.9;50.6;8.4;12.3;32.3;10.2;4.1;6.7;15.0;16.0 +23.5;99.5;50.3;8.3;12.3;32.1;10.2;4.1;6.7;14.9;15.9 +23.4;99.0;50.1;8.3;12.2;31.9;10.1;4.0;6.6;14.8;15.8 +23.3;98.6;49.8;8.2;12.1;31.7;10.0;4.0;6.6;14.7;15.8 +23.2;98.1;49.5;8.2;12.1;31.4;10.0;4.0;6.5;14.6;15.7 +23.0;97.7;49.2;8.1;12.0;31.2;9.9;3.9;6.5;14.4;15.6 +22.9;97.2;48.9;8.0;11.9;31.0;9.8;3.9;6.4;14.3;15.6 +22.8;96.8;48.5;8.0;11.9;30.8;9.8;3.9;6.4;14.2;15.5 +22.6;96.3;48.2;7.9;11.8;30.6;9.7;3.8;6.3;14.1;15.4 +22.5;95.8;47.9;7.9;11.7;30.4;9.6;3.8;6.3;14.0;15.3 +22.4;95.4;47.6;7.8;11.7;30.3;9.6;3.8;6.2;13.9;15.3 +22.2;94.9;47.3;7.8;11.6;30.1;9.5;3.8;6.2;13.8;15.2 +22.1;94.5;47.0;7.8;11.5;30.0;9.4;3.7;6.1;13.7;15.1 +22.0;94.1;46.7;7.7;11.5;29.8;9.4;3.7;6.1;13.6;15.1 +21.9;93.7;46.5;7.7;11.4;29.6;9.3;3.7;6.1;13.5;15.0 +21.8;93.3;46.2;7.6;11.4;29.5;9.3;3.7;6.1;13.4;14.9 +21.7;92.9;46.0;7.6;11.3;29.3;9.2;3.7;6.0;13.3;14.9 +21.7;92.6;45.8;7.5;11.3;29.2;9.2;3.6;6.0;13.3;14.8 +21.6;92.2;45.5;7.5;11.2;29.0;9.1;3.6;6.0;13.2;14.8 +21.5;91.9;45.3;7.5;11.2;28.9;9.1;3.6;5.9;13.1;14.7 +21.4;91.7;45.0;7.4;11.1;28.7;9.0;3.6;5.9;13.0;14.6 +21.3;91.4;44.8;7.4;11.1;28.6;9.0;3.6;5.8;13.0;14.6 +21.2;91.1;44.6;7.4;11.0;28.4;9.0;3.5;5.8;12.9;14.5 +21.1;90.9;44.4;7.3;11.0;28.3;8.9;3.5;5.8;12.9;14.5 +21.0;90.7;44.2;7.3;10.9;28.2;8.9;3.5;5.8;12.8;14.5 +21.0;90.5;44.1;7.3;10.9;28.1;8.8;3.5;5.7;12.8;14.4 +20.9;90.4;44.0;7.3;10.9;28.1;8.8;3.5;5.7;12.7;14.4 +20.9;90.4;44.0;7.3;10.8;28.1;8.8;3.5;5.7;12.7;14.4 +21.0;90.5;44.0;7.3;10.9;28.1;8.8;3.5;5.7;12.8;14.4 +21.0;90.9;44.2;7.3;10.9;28.2;8.9;3.5;5.8;12.8;14.5 +21.2;91.4;44.4;7.3;11.0;28.4;8.9;3.5;5.8;12.9;14.6 +21.3;92.0;44.7;7.4;11.1;28.6;9.0;3.5;5.9;13.0;14.6 +21.4;92.7;45.1;7.4;11.1;28.8;9.0;3.6;5.9;13.2;14.7 +21.6;93.3;45.4;7.5;11.2;29.0;9.1;3.6;6.0;13.3;14.8 +21.7;93.8;45.6;7.5;11.3;29.2;9.2;3.6;6.0;13.4;14.9 +21.8;94.2;45.8;7.6;11.4;29.3;9.2;3.6;6.0;13.4;15.0 +21.8;94.2;45.8;7.6;11.4;29.3;9.2;3.6;6.1;13.5;15.0 +21.7;94.1;45.7;7.5;11.4;29.3;9.2;3.6;6.0;13.4;14.9 +21.7;93.8;45.6;7.5;11.3;29.2;9.2;3.6;6.0;13.4;14.9 +21.6;93.5;45.4;7.5;11.3;29.1;9.1;3.6;6.0;13.3;14.8 +21.5;93.1;45.2;7.5;11.2;29.0;9.1;3.6;6.0;13.3;14.8 +21.4;92.9;45.1;7.4;11.2;28.9;9.1;3.6;6.0;13.2;14.7 +21.4;92.7;45.0;7.4;11.2;28.8;9.1;3.6;6.0;13.2;14.7 +21.3;92.7;45.0;7.4;11.2;28.8;9.1;3.6;6.0;13.2;14.7 +21.3;92.7;45.0;7.4;11.1;28.8;9.1;3.5;6.0;13.2;14.7 +21.3;92.8;45.0;7.4;11.1;28.8;9.1;3.5;6.0;13.2;14.7 +21.3;92.8;45.0;7.4;11.1;28.8;9.1;3.5;6.0;13.2;14.7 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_p_forecasted.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_p_forecasted.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..b27c3cb4a92bd9e8a9a09283e8461ab4b838d82b GIT binary patch literal 4420 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 KI8cxVq`sX!$bgCf literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_q.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_q.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..9ff8163c64d207e78389871a572c98937cf5d888 GIT binary patch literal 4523 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 JBm;krj=;cpnoR%z literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_q_forecasted.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/load_q_forecasted.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..aaa8a40ef96df10e54678a0611f4927bd15a7697 GIT binary patch literal 3645 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 S`}Uus{4V5*aG@cDg5B(9JpGvf literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/prod_p_forecasted.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/prod_p_forecasted.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..45d145bc8d44337e5b6084cfdb32541ab085a1a4 GIT binary patch literal 3272 zcmV;(3^(&aT4*^jL0KkKS??9$NdO?!TmS$P2m^oU0)b!@x=VanyPLV)HtsglV`}Ad zc4xoqN<@&kDIZhM3fEgCAuOuWLx%id^ba@SPu@e(usDVUgW4Xe50KmJtd$1Ad0~)RH+)ApjjtrAz0tK^QI79j zLkGCh?{mIM3joxbff6Yt?p{#4ytD-j1m!+nGVWVTCX`leT=s0LLI>(wDJ=IqitizrtRr{T*eYnO#Oe#a2 zHrGo{0`)94vr^YW!$QXF0fg4cS6QSP;UqO53li z<0lCT9NU!PL3h}MS3BD`y7Sj7(RsBolIV~WriH-hEC_*&wCGYKamwr(jcEj zArL?Z$$Wd*Z;(MexrtU{olU}L@NwkEFE)93(s`x^IhR3^T3~=fH*z5NJ&7br2t7N& z;2Fr{IFwwx*G4X+K@slAxv{QHSlyeo zO3cm1PA1|EbuHxu3)IYUe+jjrTdgzP@tF}93bIt%p#k#1)atpe7cjR>Rg9}NI|W!D zK#K0*XsoFu2>BoY{V)~|^BF$((jqP^Q>=Z!aT3Nlq`}d1CI%|;L7E34t}YqIc5A;#*&+EQwnJV=NR8ZDR%Vo5LP8I3 zWW3Tnm0VVv0+my-p_~{H#d$y|rLj`B#;dFd6?3iL+;W3RxoDqk;Goi3T$$Ois?t_9 zYS=h&f`uHZp=;y`0r$B-dA~LDK{2%%qUb>>TA|ISVjDu(*d>QSoHK*7Gb2h=v&h#X z3>M+!CNmkBIN~6PTlD?NuKx7{<$qcjbVTroN`+KORyEQIBL0Tqo z)Xj06^Lpj?S~y7u$txksnQ&g1(4u;&=-uj^c_}*7+}!EsiQjrUwR_!_GjfE?6!B9x z8mjcfO&!_K)3SlRuHom%x17R~P|Pimd_q2@u&$ZXt5qwVx+>Mv+r77!XBTiaE>JO; zo=Pv)WeF@-PVCwwj5xFfOu9w*;uir)Z(a2#yd8$u9#u!HRl3SmM@n7IvfWl4tF~_L zZanA~#HCEvD{35;I%^@&%2z8U!`q!tFOMUsW#Mi0C=}V!P8CFZ+P$=9TbI(uiaKUZ zOV?XAbB@QYzYunrc^mWL%(9cau-VFm+L@h|&jYm$1%l^-uH}~bOS~>RkWHw%qSMPv z82 zlGX+@T_%d5BLjnA$_IpiF$w13$hoIH3%znm;mvX`Ck?<|E=}3OwmY$o?2sXv?Gc1FF>%rm*&V|+t7>kQ zyy9W5gsmgYcufu)(iFV|fbKwvnJ1)VGI^lnlv5{(foOY_|rv@p5vp5X*{4trbbN^nqQ>wfPCPLo?S=Idf`jP%(g*z-3(qnn*1Z{>JP#{Mck226eK&v Gcv3*WsVd6= literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/prod_v.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0001/prod_v.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..8c9736d484107239ad44a6ff625c62af03bc5417 GIT binary patch literal 107 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 NF64@Ep&%|tNkW|RH+cX6 literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/load_p_forecasted.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/load_p_forecasted.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..9c46039945c5f2ff80d76b5d2ed697b04f077d99 GIT binary patch literal 4643 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 literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/load_q_forecasted.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/load_q_forecasted.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..de204780d3da81de8d672cc801fe3c3780b842f9 GIT binary patch literal 3870 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 F6M+BdD$xJ{ literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/prod_p_forecasted.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/prod_p_forecasted.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..7420a98fef9f9603032451ffe58646f7071e345b GIT binary patch literal 3515 zcmV;s4Mg%nT4*^jL0KkKS#);$vj8C%+yDR)2m^oU0)b!^{et>#ddmruYcUgM*%M}W zg&SjRPzCS|AZ%C`Hpbq4RH~#_7c{Wv47z0zt(?wJm15+|+)l@XVB-DYF zr7~#3PgPXWqtajkL>fw(fHMFH9FYGQr_7eg`%lC_Dz=;bdt7wOFuXxDC6t%O(2}xk zx^pPY$$kS*z3M&+RZG{F_@2AS9N7j(upw)VT|_- z(H3JS(o%i2?05|?B0Y;8z#vrE&777G9fdEsjqzQ=(XHX=N z?H_v*gRiS;+v=gdaNesg!)`l=Pl?|RBS^-Y!^S5Adk;t@69p^cqjfNkv+MRfI4-2g=+<4Y8Jv(r70X4+%_#c))uFlWha_ixnD=i+BUdWM_1cx$r-nh3 zFDdK$Gme{mZmfP}Jbc6A7`O{jC%}Ns40|e!20hPXK$u4$};F3y|Z)FeNEv zVADti?R|)$POO5dX}PmOlE98>EeT@Xd3Rl*oq5dls*A<NpT)qzEeV(0eGY_AEEX z`zL)TUp~GdSF1+{V^KUi8dyPKxVC6T@UdhJP{ZydYL5+sQ1mp>t$HXzdU!KkkI$&6 zVP5)H*R0=$gMFkO%d8-T`#9%7B(Eyls9L`REcM%p^G?3N$m5r8Ea*cWV}jmAphDeZ z(r5xo&u$JY%g@0L3qW3;0SJXiTAv~YMLHKDK-;s6hm4OK1{y`UFgD6oRaVZB$T1ZsPc77=6^TdlY~GZw+DL%hAy*Z~O+=r^W8 zmJXJ5=8=6gM_YA3=CDY4?K1u7=xvR*hek~}4(F>Yjkn>pS8Y3e#DtIt;AAWGi3f3_ zZ0YZ9wZ{ZL@M7_g7Z{qrfrF?R53;m-;lBJndI?dlkileO-# zE^Fh7-i=4rhin50z3d%qzc_Ij1FGBf6)Niq2&Y++hf;J!(aXiTybA|3&~&+#3iWrn zElt?yd+veQ&x5m!T(L6`f-iyeAZhSVr_&}zMiY;b>~NUF8HyTTaFTE#&w3}&?|L8@wl zb&X`-ryF#|LcJr1ZEir8GJ=wzvO*!IxMxH@p?L`c592{D(eSo=FwHbqlT&8ABj`Sr zfrQ#jb3CZ%j3$|*pahYI7A8tPUPhd(K*^&U9&4N~aMIWV`b6h=_R zEj`#$;{80&Q_Bp053Jt3vyqFL^(&0(_FS|rQ!N>SJ@SZj~>4qG3Gcr50kI zZ^6QxxS>$4fUxf4k1n3?6lEQ&eSViUg|IZSm}>QJqxI77S}|@-@auUlr7^b1X09kG zI+55;d(V0fX!PHX2fSU+Fi#wT0LdW<@&vD~lr%}oh8IEb!(pKe8kcM59h}N~xa2gz zyF@l(-5{!s4ccXfhOu1*rCfDz%oI_kiURr!mW&9962r7a7;`40ieS;!C%YP0h@7OF zDJ#^`wL`sH!IW`{At87|5IBxz@Eu;70jU}rzKU}OGvguU<|b0^H5|_}=W{4%VYk&F z(am1)+U5gPvmroL zK~WJA5g5iv2&qh%#gfKNGBjC{l9^1#nM}!&lFDXeq}i0sGi5BzGNzd*voy*}Gf8G@ zN-AY0l-WutDAP2|l#!-cN||i5(v>P&RM};c%(En^rJ1u$rc|3sYLimwZM9$gxZ$SZ z?=T%DxV1XHOG+2RR8C}!Y)w)zYM(hy25?_<8fIasRRP4(UF3`%24o3kS&(ip8B29V zRo%QXhbmJiG1*qJz^O=d8=67U7N!KM=l8CXDJm_NQ!J*;q@^f|EYP%BDKcYbV5Vrv z6*fszO(mLWrfO(Wqf%&%ie@%4Mv?+3rfHO!nrTvOno5~ur2{e%SK7CO1qfR zK+1-4bgJ0&VJI&n3oOcd*f5})n9McfM$oZBQmt8~A*v>*HEPGY*wa*rsm#+#3I>W$ zh?Z_qMyg89Qe;};M)f#OYn)<}w096iV8$^81X(GTX_FdEnK4YpgG|~>CQUL;NsMAB z$)-uNl`N$!(`ArS86?R}vPQ{cMP#EUWhFC8Qd2BOl*zJ@CQUO2%3`Ay3nGzZMi&AA zVhm4eg^=m~5nJQS)MJhxl7Sd|yRLx***}6M4V*uJqGH7EU(uJv3JfTv+ydipn zN(;p1<1}Jwlu(*mHvFzy;SmuULXs&XBvDjE5rnXk0Qj8eWeKzjCEja#%xRZN6teI!1{kvy8G}H|S(kwEVTO#;S{|LY+TH7G zn{8szwY37?_-)I=8sy(Iayskk$p# zw(;(6-M%C=`M#)OwtI(i-dgno>z=wxr*)FWJ7S)B-ZoEL*|+9%FPPoV9A?N!JWLCd zIPLbE^KPoBT^5y!-CRIXm?-Mb&h2i-9;t(N;>pg{c9&UZQ7ILhSK395#yfKJM58Sr z?z1)A+M3RV$2;8(yBt#5uoOCBeXZungqTjo)$z!y9(0)WsO4e1W^*oPZd<#S4vL6b zB-1NdV|6i^w&RRd3(ng!96EM_nHEk}+NWXe;b98YaNE>0t(Hg-9&2b@L{471rM19>>}JaBW;Sg>S6OzQt(=c1 zgz0Y5?UXB8!3}ubcCNnbhIa{u;@799WI0UE4Ru$E+N{GCwR18W*7Iu_8gy`HG&~L{ zXy}GtBk5%5nlfJyu%5b(z05A#O-FUduP#|_yy)0Ukg*8o!kgOLyBiI5$T|vEqoIb$ z>uDz8H3E|!Bgok;?I=4|7bM!O>nKvr%rv)nuXfq^OudsMM6u{)K~p)M<=uG{##k-3<3p+<3D3Dq#Lq z5x~Nn^+Z$5M$4L+ddZr`jJ=hEIT9A?;r9iUb5RVWMiihC6Rkn$#X*|83Z1h~OrosL zt3xXWiQW_3!)n4GD$r-Pm`@dE)ML8o4Gf#e3zC53 zfe8^gVtZg4IbQn*SC|wMq@9BJBo6f#6mA87H!n_ycI?(xZvqS16HKu$uCDE*}HC3jm z>T2EjggrJAy%lT1xIDXzP11aMPWJkgHUQvyD?KB^(X`?D{IqbUFY literal 0 HcmV?d00001 diff --git a/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/prod_v.csv.bz2 b/src/data_test/l2rpn_case14_sandbox_Pypowsybl/chronics/0002/prod_v.csv.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..8c9736d484107239ad44a6ff625c62af03bc5417 GIT binary patch literal 107 zcmV-x0F?hiT4*^jL0KkKS>twVf&eB>+yDR)2m^gc0)a39xC$5m1q=WHr7AQqo~D@s zI@}2BwcrU(fQ|r0`T{rtFa&u5mpBA_0U839z$0w|8GusDKu3TPfJQ)%U30ftwVf&eB>+yDR)2m^gc0)a39xC$5m1q=WHr7AQqo~D@s zI@}2BwcrU(fQ|r0`T{rtFa&u5mpBA_0U839z$0w|8GusDKu3TPfJQ)%U30f "+str(path)) + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + with make( + os.path.join(path, "5bus_example_diff_name"), + backend=backend, + _add_to_name="_BaseTestNames", + ) as env: + obs = env.reset() + assert np.all(type(obs).name_load == ["tutu", "toto", "tata"]) + assert np.all(type(env).name_load == ["tutu", "toto", "tata"]) + + +class BaseTestLoadingCase(MakeBackend): + def test_load_file(self): + backend = self.make_backend() + path_matpower = self.get_path() + case_file = self.get_casefile() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + backend.load_grid(path_matpower, case_file) + type(backend).set_env_name("BaseTestLoadingCase") + backend.assert_grid_correct() + + assert backend.n_line == 20 + assert backend.n_gen == 6 + assert backend.n_load == 11 + assert backend.n_sub == 14 + + name_line = ['LINE-1-2', + 'LINE-1-5', + 'LINE-2-3', + 'LINE-2-4', + 'LINE-2-5', + 'LINE-3-4', + 'LINE-4-5', + 'LINE-6-11', + 'LINE-6-12', + 'LINE-6-13', + 'LINE-9-10', + 'LINE-9-14', + 'LINE-10-11', + 'LINE-12-13', + 'LINE-13-14', + 'TWT-4-7', + 'TWT-4-9', + 'TWT-5-6', + 'LINE-7-8', + 'LINE-9-7'] + name_line = np.array(name_line) + assert np.all(sorted(backend.name_line) == sorted(name_line)) + + name_sub = ['sub_BUS-1', + 'sub_BUS-10', + 'sub_BUS-11', + 'sub_BUS-12', + 'sub_BUS-13', + 'sub_BUS-14', + 'sub_BUS-2', + 'sub_BUS-3', + 'sub_BUS-4', + 'sub_BUS-5', + 'sub_BUS-6', + 'sub_BUS-7', + 'sub_BUS-8', + 'sub_BUS-9'] + name_sub = np.array(name_sub) + assert np.all(sorted(backend.name_sub) == sorted(name_sub)) + + name_gen = ['GEN-1', 'GEN-2', 'GEN-3', 'GEN-6', 'GEN-6#0', 'GEN-8'] + name_gen = np.array(name_gen) + assert np.all(sorted(backend.name_gen) == sorted(name_gen)) + + name_load = ['LOAD-'+str(x) for x in [2,3,4,5,6,9,10,11,12,13,14]] + assert np.all(sorted(backend.name_load) == sorted(name_load)) + + assert np.all(backend.get_topo_vect() == np.ones(np.sum(backend.sub_info))) + + conv = backend.runpf() + assert conv, "powerflow diverge it is not supposed to!" + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + p_subs, q_subs, p_bus, q_bus, v_bus = backend.check_kirchoff() + + assert np.max(np.abs(p_subs))/10**6 <= self.tolvect # I considered that the cst was given in pu (so I divided + # to make MW in pu), I am not sure + assert np.max(np.abs(p_bus.flatten()))/10**6 <= self.tolvect # Same here + if backend.shunts_data_available: + assert np.max(np.abs(q_subs))/10**6 <= self.tolvect # Same here + assert np.max(np.abs(q_bus.flatten()))/10**6 <= self.tolvect # Same here + + def test_assert_grid_correct(self): + backend = self.make_backend() + path_matpower = self.get_path() + case_file = self.get_casefile() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + backend.load_grid(path_matpower, case_file) + type(backend).set_env_name("TestLoadingCase_env2_test_assert_grid_correct") + backend.assert_grid_correct() + conv = backend.runpf() + assert conv, "powerflow diverge it is not supposed to!" + backend.assert_grid_correct_after_powerflow() + + +class BaseTestLoadingBackendFunc(MakeBackend): + def setUp(self): + self.backend = self.make_backend() + self.path_matpower = self.get_path() + self.case_file = self.get_casefile() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.backend.load_grid(self.path_matpower, self.case_file) + type(self.backend).set_env_name("TestLoadingBackendFunc_env") + type(self.backend).set_no_storage() + self.backend.assert_grid_correct() + self.game_rules = RulesChecker() + self.action_env_class = ActionSpace.init_grid(self.backend) + self.action_env = self.action_env_class( + gridobj=self.backend, legal_action=self.game_rules.legal_action + ) + self.bkact_class = _BackendAction.init_grid(self.backend) + self.backend.runpf() + self.backend.assert_grid_correct_after_powerflow() + + def tearDown(self): + pass + + def test_theta_ok(self): + self.skip_if_needed() + if self.backend.can_output_theta: + ( + theta_or, + theta_ex, + load_theta, + gen_theta, + storage_theta, + ) = self.backend.get_theta() + assert theta_or.shape[0] == self.backend.n_line + assert theta_ex.shape[0] == self.backend.n_line + assert load_theta.shape[0] == self.backend.n_load + assert gen_theta.shape[0] == self.backend.n_gen + assert storage_theta.shape[0] == self.backend.n_storage + assert np.all(np.isfinite(theta_or)) + assert np.all(np.isfinite(theta_ex)) + assert np.all(np.isfinite(load_theta)) + assert np.all(np.isfinite(gen_theta)) + assert np.all(np.isfinite(storage_theta)) + else: + with self.assertRaises(NotImplementedError): + # if the "can_output_theta" flag is set to false, then it means the backend + # should not implement the get_theta class + self.backend.get_theta() + + def test_runpf_dc(self): + self.skip_if_needed() + conv = self.backend.runpf(is_dc=True) + assert conv + true_values_dc = np.array( + [147.83859, + 71.161407, + 70.014633, + 55.151852, + 40.972107, + -24.185364, + -61.746490, + 6.7283459, + 7.6073580, + 17.251316, + 5.7716541, + 9.6413250, + -3.2283459, + 1.5073582, + 5.2586751, + 28.361153, + 16.551826, + 42.787022, + 0.0, + -28.361153] + ) + print(self.backend.lines_or_info()) + p_or, *_ = self.backend.lines_or_info() + assert self.compare_vect(p_or, true_values_dc) + + def test_runpf(self): + self.skip_if_needed() + true_values_ac = np.array( + [156.88213, + 75.51009, + 73.23742, + 56.131298, + 41.516052, + -23.285782, + -61.15813, + 7.353236, + 7.7860556, + 17.748, + 5.227596, + 9.426435, + -3.7852585, + 1.6142408, + 5.6437955, + 28.074074, + 16.079672, + 44.086914, + 0., + -28.073921] + ) + conv = self.backend.runpf(is_dc=False) + assert conv + p_or, *_ = self.backend.lines_or_info() + assert self.compare_vect(p_or, true_values_ac) + + def test_voltage_convert_powerlines(self): + + # TODO Test do not pass because of lines order, and more specifically because of transformers, it looks like order are + # TODO not the same for p/q/v/a_th and a_or + + self.skip_if_needed() + # i have the correct voltages in powerlines if the formula to link mw, mvar, kv and amps is correct + conv = self.backend.runpf(is_dc=False) + assert conv[0], "powerflow diverge at loading" + + p_or, q_or, v_or, a_or = self.backend.lines_or_info() + + p_ex, q_ex, v_ex, a_ex = self.backend.lines_ex_info() + a_th = np.sqrt(p_or ** 2 + q_or ** 2) * 1e3 / (np.sqrt(3) * v_or) + print("p_or="+str(p_or)) + print("q_or="+str(q_or)) + print("v_or="+str(v_or)) + print("a_or="+str(dt_float(a_or))) + + print("a_ex="+str(dt_float(a_ex))) + print("a_th="+str(a_th)) + + print(self.backend._grid.get_lines(all_attributes=True)) + + print(self.backend._grid.get_2_windings_transformers(all_attributes=True)) + assert self.compare_vect(a_th, dt_float(a_or)) + + p_ex, q_ex, v_ex, a_ex = self.backend.lines_ex_info() + a_th = np.sqrt(p_ex ** 2 + q_ex ** 2) * 1e3 / (np.sqrt(3) * v_ex) + assert self.compare_vect(a_th, a_ex) + + def test_voltages_correct_load_gen(self): + self.skip_if_needed() + # i have the right voltages to generators and load, if it's the same as the voltage (correct from the above test) + # of the powerline connected to it. + + conv = self.backend.runpf(is_dc=False) + assert conv, "powerflow diverge at loading" + load_p, load_q, load_v = self.backend.loads_info() + gen_p, gen__q, gen_v = self.backend.generators_info() + p_or, q_or, v_or, a_or = self.backend.lines_or_info() + p_ex, q_ex, v_ex, a_ex = self.backend.lines_ex_info() + + for c_id, sub_id in enumerate(self.backend.load_to_subid): + l_ids = np.where(self.backend.line_or_to_subid == sub_id)[0] + print("l_ids:"+str(l_ids)) + if len(l_ids): + l_id = l_ids[0] + if np.abs(v_or[l_id] - load_v[c_id]) > self.tol_one: + print("l_ids="+str(l_ids)) + print("c_id= "+str(c_id)) + print("load_to_subid: "+str(list(enumerate(self.backend.load_to_subid)))) + print("v_or=" + str(v_or)) + print("v_ex=" + str(v_ex)) + print("load_v=" + str(load_v)) + print("self.tol_one="+str(self.tol_one)) + print("v_or[l_id]="+str(v_or[l_id])) + print("load_v[c_id]="+str(load_v[c_id])) + assert ( + np.abs(v_or[l_id] - load_v[c_id]) <= self.tol_one + ), "problem for load {}".format(c_id) + continue + + l_ids = np.where(self.backend.line_ex_to_subid == sub_id)[0] + if len(l_ids): + l_id = l_ids[0] + assert ( + np.abs(v_ex[l_id] - load_v[c_id]) <= self.tol_one + ), "problem for load {}".format(c_id) + continue + assert False, "load {} has not been checked".format(c_id) + + for g_id, sub_id in enumerate(self.backend.gen_to_subid): + l_ids = np.where(self.backend.line_or_to_subid == sub_id)[0] + if len(l_ids): + l_id = l_ids[0] + assert ( + np.abs(v_or[l_id] - gen_v[g_id]) <= self.tol_one + ), "problem for generator {}".format(g_id) + continue + + l_ids = np.where(self.backend.line_ex_to_subid == sub_id)[0] + if len(l_ids): + print("v_or="+str(v_or)) + print("v_ex="+str(v_ex)) + print("load_v="+str(load_v)) + print("gen_v="+str(gen_v)) + l_id = l_ids[0] + if np.abs(v_ex[l_id] - gen_v[g_id]) > self.tol_one: + print("l_ids="+str(l_ids)) + print("c_id= "+str(c_id)) + print("self.tol_one="+str(self.tol_one)) + print("v_ex[l_id]="+str(v_ex[l_id])) + print("gen_v[g_id]="+str(gen_v[g_id])) + assert ( + np.abs(v_ex[l_id] - gen_v[g_id]) <= self.tol_one + ), "problem for generator {}".format(g_id) + continue + assert False, "generator {} has not been checked".format(g_id) + + def test_copy(self): + self.skip_if_needed() + conv = self.backend.runpf(is_dc=False) + assert conv, "powerflow diverge at loading" + l_id = 3 + + p_or_orig, *_ = self.backend.lines_or_info() + adn_backend_cpy = self.backend.copy() + + self.backend._disconnect_line(l_id) + conv = self.backend.runpf(is_dc=False) + assert conv + conv2 = adn_backend_cpy.runpf(is_dc=False) + assert conv2 + p_or_ref, *_ = self.backend.lines_or_info() + p_or, *_ = adn_backend_cpy.lines_or_info() + assert self.compare_vect( + p_or_orig, p_or + ), "the copied object affects its original 'parent'" + assert ( + np.isnan(p_or_ref[l_id]) + ), "powerline {} has not been disconnected".format(l_id) + + def test_copy2(self): + self.skip_if_needed() + self.backend._disconnect_line(8) + conv = self.backend.runpf(is_dc=False) + p_or_orig, *_ = self.backend.lines_or_info() + + adn_backend_cpy = self.backend.copy() + adn_backend_cpy._disconnect_line(11) + assert not adn_backend_cpy.get_line_status()[8] + assert not adn_backend_cpy.get_line_status()[11] + assert not self.backend.get_line_status()[8] + assert self.backend.get_line_status()[11] + + def test_get_private_line_status(self): + self.skip_if_needed() + if hasattr(self.backend, "_get_line_status"): + assert np.all(self.backend._get_line_status()) + else: + assert np.all(self.backend.get_line_status()) + + self.backend._disconnect_line(3) + if hasattr(self.backend, "_get_line_status"): + vect_ = self.backend._get_line_status() + else: + vect_ = self.backend.get_line_status() + assert np.sum(~vect_) == 1 + assert not vect_[3] + + def test_get_line_flow(self): + self.skip_if_needed() + self.backend.runpf(is_dc=False) + true_values_ac = np.array( + [-20.404114, + 3.8547115, + 3.5602188, + -1.5506924, + 1.1706527, + 4.4727535, + 15.823638, + 3.5601146, + 2.5031068, + 7.2157326, + 4.2192044, + 3.6097445, + -1.6148087, + 0.7538382, + 1.7469339, + -9.681188, + -0.42773214, + 12.470952, + -17.162441, + -4.9762697] + ) + p_or_orig, q_or_orig, *_ = self.backend.lines_or_info() + assert self.compare_vect(q_or_orig, true_values_ac) + + self.backend._disconnect_line(3) + a = self.backend.runpf(is_dc=False) + true_values_ac = np.array( + [-16.960958, + 6.5786576, + 2.1715472, + "nan", + 0.10771065, + 4.060638, + 23.061537, + 4.1333365, + 2.5463302, + 7.530744, + 3.714779, + 3.2982507, + -2.1058052, + 0.78852546, + 2.0548112, + -12.435264, + -1.4942673, + 8.84297, + -20.169308, + -5.3284087] + ) + p_or_orig, q_or_orig, *_ = self.backend.lines_or_info() + q_or_orig = np.where(np.isnan(q_or_orig ), 'nan', q_or_orig) + assert (q_or_orig == true_values_ac).all()# self.compare_vect(q_or_orig, true_values_ac) + + def test_pf_ac_dc(self): + self.skip_if_needed() + true_values_ac = np.array( + [-20.404114, + 3.8547115, + 3.5602188, + -1.5506924, + 1.1706527, + 4.4727535, + 15.823638, + 3.5601146, + 2.5031068, + 7.2157326, + 4.2192044, + 3.6097445, + -1.6148087, + 0.7538382, + 1.7469339, + -9.681188, + -0.42773214, + 12.470952, + -17.162441, + -4.9762697] + ) + conv = self.backend.runpf(is_dc=True) + assert conv + p_or_orig, q_or_orig, *_ = self.backend.lines_or_info() + assert np.all(np.isnan(q_or_orig)), "in dc mode all q must be nan, equivalent to zero" + conv = self.backend.runpf(is_dc=False) + assert conv + p_or_orig, q_or_orig, *_ = self.backend.lines_or_info() + assert self.compare_vect(q_or_orig, true_values_ac) + + def test_get_thermal_limit(self): + self.skip_if_needed() + res = self.backend.get_thermal_limit() + true_values_ac = np.array( + # [ + # 42339.01974057, + # 42339.01974057, + # 27479652.23546777, + # 27479652.23546777, + # 27479652.23546777, + # 27479652.23546777, + # 27479652.23546777, + # 42339.01974057, + # 42339.01974057, + # 42339.01974057, + # 42339.01974057, + # 42339.01974057, + # 27479652.23546777, + # 27479652.23546777, + # 27479652.23546777, + # 42339.01974057, + # 42339.01974057, + # 42339.01974057, + # 408269.11892695, + # 408269.11892695, + # ], + [1000000. for x in range(20)], + dtype=dt_float, + ) + assert self.compare_vect(res, true_values_ac) + + def test_disconnect_line(self): + self.skip_if_needed() + for i in range(self.backend.n_line): + if i == 18: + # powerflow diverge if line 1 is removed, unfortunately + continue + backend_cpy = self.backend.copy() + backend_cpy._disconnect_line(i) + conv = backend_cpy.runpf() + assert ( + conv + ), "Power flow computation does not converge if line {} is removed".format( + i + ) + flows = backend_cpy.get_line_status() + assert not flows[i] + assert np.sum(~flows) == 1 + + def test_donothing_action(self): + self.skip_if_needed() + conv = self.backend.runpf() + init_flow = self.backend.get_line_flow() + init_lp, *_ = self.backend.loads_info() + init_gp, *_ = self.backend.generators_info() + init_ls = self.backend.get_line_status() + + action = self.action_env({}) # update the action + bk_action = self.bkact_class() + bk_action += action + self.backend.apply_action(bk_action) + after_lp, *_ = self.backend.loads_info() + after_gp, *_ = self.backend.generators_info() + after_ls = self.backend.get_line_status() + assert self.compare_vect(init_lp, after_lp) # check i didn't modify the loads + assert self.compare_vect(init_gp, after_gp) # check i didn't modify the generators + assert np.all(init_ls == after_ls) # check i didn't disconnect any powerlines + + conv = self.backend.runpf() + assert conv, "Cannot perform a powerflow after doing nothing" + after_flow = self.backend.get_line_flow() + assert self.compare_vect(init_flow, after_flow) + + def test_apply_action_active_value(self): + self.skip_if_needed() + # test that i can modify only the load / prod active values of the powergrid + # to do that i modify the productions and load all of a factor 0.5 and compare that the DC flows are + # also multiply by 2 + + # i set up the stuff to have exactly 0 losses + conv = self.backend.runpf(is_dc=True) + assert conv, "powergrid diverge after loading (even in DC)" + init_flow, *_ = self.backend.lines_or_info() + init_lp, init_l_q, *_ = self.backend.loads_info() + init_gp, *_ = self.backend.generators_info() + init_ls = self.backend.get_line_status() + ratio = 1.0 + new_cp = ratio * init_lp + new_pp = ratio * init_gp * np.sum(init_lp) / np.sum(init_gp) + action = self.action_env( + {"injection": {"load_p": new_cp, "prod_p": new_pp}} + ) # update the action + bk_action = self.bkact_class() + bk_action += action + self.backend.apply_action(bk_action) + conv = self.backend.runpf(is_dc=True) + # now the system has exactly 0 losses (ie sum load = sum gen) + + # i check that if i divide by 2, then everything is divided by 2 + assert conv + init_flow, *_ = self.backend.lines_or_info() + init_lp, init_l_q, *_ = self.backend.loads_info() + init_gp, *_ = self.backend.generators_info() + init_ls = self.backend.get_line_status() + ratio = 0.5 + new_cp = ratio * init_lp + new_pp = ratio * init_gp + action = self.action_env( + {"injection": {"load_p": new_cp, "prod_p": new_pp}} + ) # update the action + bk_action = self.bkact_class() + bk_action += action + self.backend.apply_action(bk_action) + conv = self.backend.runpf(is_dc=True) + assert conv, "Cannot perform a powerflow after doing nothing" + + after_lp, after_lq, *_ = self.backend.loads_info() + after_gp, *_ = self.backend.generators_info() + after_ls = self.backend.get_line_status() + assert self.compare_vect(new_cp, after_lp) # check i didn't modify the loads + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + p_subs, q_subs, p_bus, q_bus, v_bus = self.backend.check_kirchoff() + + # i'm in DC mode, i can't check for reactive values... + assert ( + np.max(np.abs(p_subs)) <= self.tolvect + ), "problem with active values, at substation" + assert ( + np.max(np.abs(p_bus.flatten())) <= self.tolvect + ), "problem with active values, at a bus" + + assert self.compare_vect( + new_pp, after_gp + ) # check i didn't modify the generators + assert np.all(init_ls == after_ls) # check i didn't disconnect any powerlines + + after_flow, *_ = self.backend.lines_or_info() + assert self.compare_vect( + ratio * init_flow, after_flow + ) # probably an error with the DC approx + + def test_apply_action_prod_v(self): + self.skip_if_needed() + conv = self.backend.runpf(is_dc=False) + assert conv, "powergrid diverge after loading" + prod_p_init, prod_q_init, prod_v_init = self.backend.generators_info() + ratio = 1.05 + action = self.action_env( + {"injection": {"prod_v": ratio * prod_v_init}} + ) # update the action + bk_action = self.bkact_class() + bk_action += action + self.backend.apply_action(bk_action) + conv = self.backend.runpf(is_dc=False) + assert conv, "Cannot perform a powerflow after modifying the powergrid" + + prod_p_after, prod_q_after, prod_v_after = self.backend.generators_info() + assert self.compare_vect( + ratio * prod_v_init, prod_v_after + ) # check i didn't modify the generators + + def test_apply_action_maintenance(self): + self.skip_if_needed() + # retrieve some initial data to be sure only a subpart of the _grid is modified + conv = self.backend.runpf() + init_lp, *_ = self.backend.loads_info() + init_gp, *_ = self.backend.generators_info() + + # check that maintenance vector is properly taken into account + maintenance = np.full((self.backend.n_line,), fill_value=False, dtype=dt_bool) + maintenance[19] = True + action = self.action_env({"maintenance": maintenance}) # update the action + bk_action = self.bkact_class() + bk_action += action + + # apply the action here + self.backend.apply_action(bk_action) + + # compute a load flow an performs more tests + conv = self.backend.runpf() + assert conv, "Power does not converge if line {} is removed".format(19) + + # performs basic check + after_lp, *_ = self.backend.loads_info() + after_gp, *_ = self.backend.generators_info() + after_ls = self.backend.get_line_status() + assert self.compare_vect(init_lp, after_lp) # check i didn't modify the loads + assert self.compare_vect(init_gp, after_gp) # check i didn't modify the generators + assert np.all( + ~maintenance == after_ls + ) # check i didn't disconnect any powerlines beside the correct one + + flows = self.backend.get_line_status() + assert np.sum(~flows) == 1 + assert not flows[19] + + def test_apply_action_hazard(self): + self.skip_if_needed() + conv = self.backend.runpf() + assert conv, "powerflow did not converge at iteration 0" + init_lp, *_ = self.backend.loads_info() + init_gp, *_ = self.backend.generators_info() + + # check that maintenance vector is properly taken into account + maintenance = np.full((self.backend.n_line,), fill_value=False, dtype=dt_bool) + maintenance[17] = True + action = self.action_env({"hazards": maintenance}) # update the action + bk_action = self.bkact_class() + bk_action += action + # apply the action here + self.backend.apply_action(bk_action) + + # compute a load flow an performs more tests + conv = self.backend.runpf() + assert conv, "Power does not converge if line {} is removed".format(19) + + # performs basic check + after_lp, *_ = self.backend.loads_info() + after_gp, *_ = self.backend.generators_info() + after_ls = self.backend.get_line_status() + assert self.compare_vect(init_lp, after_lp) # check i didn't modify the loads + assert self.compare_vect(init_gp, after_gp) # check i didn't modify the generators + assert np.all( + maintenance == ~after_ls + ) # check i didn't disconnect any powerlines beside the correct one + + def test_apply_action_disconnection(self): + self.skip_if_needed() + # retrieve some initial data to be sure only a subpart of the _grid is modified + conv = self.backend.runpf() + init_lp, *_ = self.backend.loads_info() + init_gp, *_ = self.backend.generators_info() + + # check that maintenance vector is properly taken into account + maintenance = np.full((self.backend.n_line,), fill_value=False, dtype=dt_bool) + maintenance[19] = True + + disc = np.full((self.backend.n_line,), fill_value=False, dtype=dt_bool) + disc[17] = True + + action = self.action_env( + {"hazards": disc, "maintenance": maintenance} + ) # update the action + bk_action = self.bkact_class() + bk_action += action + # apply the action here + self.backend.apply_action(bk_action) + + # compute a load flow an performs more tests + conv = self.backend.runpf() + assert ( + conv[0] + ), "Powerflow does not converge if lines {} and {} are removed".format(17, 19) + + # performs basic check + after_lp, *_ = self.backend.loads_info() + after_gp, *_ = self.backend.generators_info() + after_ls = self.backend.get_line_status() + assert self.compare_vect(init_lp, after_lp) # check i didn't modify the loads + assert self.compare_vect(init_gp, after_gp) # check i didn't modify the generators + assert np.all( + disc | maintenance == ~after_ls + ) # check i didn't disconnect any powerlines beside the correct one + + flows = self.backend.get_line_status() + assert np.sum(~flows) == 2 + assert not flows[19] + assert not flows[17] + + +class BaseTestTopoAction(MakeBackend): + def setUp(self): + self.backend = self.make_backend() + self.path_matpower = self.get_path() + self.case_file = self.get_casefile() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.backend.load_grid(self.path_matpower, self.case_file) + type(self.backend).set_env_name("BaseTestTopoAction") + type(self.backend).set_no_storage() + self.backend.assert_grid_correct() + self.game_rules = RulesChecker() + as_class = ActionSpace.init_grid(self.backend) + self.helper_action = as_class( + gridobj=self.backend, legal_action=self.game_rules.legal_action + ) + self.bkact_class = _BackendAction.init_grid(self.backend) + + def tearDown(self): + pass + + def compare_vect(self, pred, true): + return np.max(np.abs(pred - true)) <= self.tolvect + + def _check_kirchoff(self): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + p_subs, q_subs, p_bus, q_bus, v_bus = self.backend.check_kirchoff() + assert ( + np.max(np.abs(p_subs)) <= self.tolvect + ), "problem with active values, at substation" + assert ( + np.max(np.abs(p_bus.flatten())) <= self.tolvect + ), "problem with active values, at a bus" + + if self.backend.shunts_data_available: + assert ( + np.max(np.abs(q_subs)) <= self.tolvect + ), "problem with reactive values, at substation" + assert ( + np.max(np.abs(q_bus.flatten())) <= self.tolvect + ), "problem with reaactive values, at a bus" + + def test_get_topo_vect_speed(self): + # retrieve some initial data to be sure only a subpart of the _grid is modified + self.skip_if_needed() + conv = self.backend.runpf() + init_amps_flow = self.backend.get_line_flow() + + # check that maintenance vector is properly taken into account + arr = np.array([1, 1, 1, 2, 2, 2], dtype=dt_int) + id_ = 1 + action = self.helper_action({"set_bus": {"substations_id": [(id_, arr)]}}) + bk_action = self.bkact_class() + bk_action += action + # apply the action here + self.backend.apply_action(bk_action) + conv = self.backend.runpf() + assert conv + after_amps_flow = self.backend.get_line_flow() + + topo_vect = self.backend.get_topo_vect() + topo_vect_old = np.array( + [ + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + dtype=dt_int, + ) + assert self.compare_vect(topo_vect, topo_vect_old) + + def test_topo_set1sub(self): + # retrieve some initial data to be sure only a subpart of the _grid is modified + self.skip_if_needed() + conv = self.backend.runpf() + init_amps_flow = self.backend.get_line_flow() + + # check that maintenance vector is properly taken into account + arr = np.array([1, 1, 1, 2, 2, 2], dtype=dt_int) + id_ = 1 + action = self.helper_action({"set_bus": {"substations_id": [(id_, arr)]}}) + bk_action = self.bkact_class() + bk_action += action + + # apply the action here + self.backend.apply_action(bk_action) + conv = self.backend.runpf() + assert conv + after_amps_flow = self.backend.get_line_flow() + + topo_vect = self.backend.get_topo_vect() + assert np.min(topo_vect) == 1, "all buses have been changed" + assert np.max(topo_vect) == 2, "no buses have been changed" + + # check that the objects have been properly moved + load_ids = np.where(self.backend.load_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.load_pos_topo_vect[load_ids]] + == arr[self.backend.load_to_sub_pos[load_ids]] + ) + lor_ids = np.where(self.backend.line_or_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.line_or_pos_topo_vect[lor_ids]] + == arr[self.backend.line_or_to_sub_pos[lor_ids]] + ) + lex_ids = np.where(self.backend.line_ex_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.line_ex_pos_topo_vect[lex_ids]] + == arr[self.backend.line_ex_to_sub_pos[lex_ids]] + ) + gen_ids = np.where(self.backend.gen_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.gen_pos_topo_vect[gen_ids]] + == arr[self.backend.gen_to_sub_pos[gen_ids]] + ) + + after_amps_flow_th = np.array( + [ + 583.6123, + 334.8705, + 315.5799, + 267.74664, + 80.43121, + 79.1541, + 201.56798, + 212.99492, + 219.70985, + 512.4593, + 188.68764, + 281.67615, + 105.61588, + 48.10775, + 156.67145, + 125.26039, + 67.50609, + 184.34944, + 688.1158, + 792.68823 + ] + ) + assert self.compare_vect(after_amps_flow, after_amps_flow_th) + # There might be some issues with the related grid, it can not + self._check_kirchoff() + + def test_topo_change1sub(self): + # check that switching the bus of 3 object is equivalent to set them to bus 2 (as above) + self.skip_if_needed() + conv = self.backend.runpf() + init_amps_flow = self.backend.get_line_flow() + + # check that maintenance vector is properly taken into account + arr = np.array([False, False, False, True, True, True], dtype=dt_bool) + id_ = 1 + action = self.helper_action({"change_bus": {"substations_id": [(id_, arr)]}}) + bk_action = self.bkact_class() + bk_action += action + # apply the action here + self.backend.apply_action(bk_action) + + # run the powerflow + conv = self.backend.runpf() + assert conv + after_amps_flow = self.backend.get_line_flow() + + topo_vect = self.backend.get_topo_vect() + assert np.min(topo_vect) == 1, "all buses have been changed" + assert np.max(topo_vect) == 2, "no buses have been changed" + + # check that the objects have been properly moved + load_ids = np.where(self.backend.load_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.load_pos_topo_vect[load_ids]] + == 1 + arr[self.backend.load_to_sub_pos[load_ids]] + ) + lor_ids = np.where(self.backend.line_or_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.line_or_pos_topo_vect[lor_ids]] + == 1 + arr[self.backend.line_or_to_sub_pos[lor_ids]] + ) + lex_ids = np.where(self.backend.line_ex_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.line_ex_pos_topo_vect[lex_ids]] + == 1 + arr[self.backend.line_ex_to_sub_pos[lex_ids]] + ) + gen_ids = np.where(self.backend.gen_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.gen_pos_topo_vect[gen_ids]] + == 1 + arr[self.backend.gen_to_sub_pos[gen_ids]] + ) + + after_amps_flow_th = np.array( + [ + 583.6123, + 334.8705, + 315.5799, + 267.74664, + 80.43121, + 79.1541, + 201.56798, + 212.99492, + 219.70985, + 512.4593, + 188.68764, + 281.67615, + 105.61588, + 48.10775, + 156.67145, + 125.26039, + 67.50609, + 184.34944, + 688.1158, + 792.68823 + ] + + # [ + # 596.5815, + # 342.3121, + # 18143.043, + # 27084.244, + # 10155.374, + # 4625.745, + # 15064.5625, + # 322.59277, + # 273.69656, + # 82.21857, + # 80.91308, + # 206.04727, + # 20480.281, + # 21125.947, + # 49274.934, + # 128.04396, + # 69.006226, + # 188.44609, + # 688.1158, + # 1132.4117, + # ] + ) + + print(after_amps_flow_th) + print(after_amps_flow) + + assert self.compare_vect(after_amps_flow, after_amps_flow_th) + #Issue with the grid + self._check_kirchoff() + + def test_topo_change_1sub_twice(self): + # check that switching the bus of 3 object is equivalent to set them to bus 2 (as above) + # and that setting it again is equivalent to doing nothing + self.skip_if_needed() + conv = self.backend.runpf() + init_amps_flow = copy.deepcopy(self.backend.get_line_flow()) + + # check that maintenance vector is properly taken into account + arr = np.array([False, False, False, True, True, True], dtype=dt_bool) + id_ = 1 + action = self.helper_action({"change_bus": {"substations_id": [(id_, arr)]}}) + bk_action = self.bkact_class() + bk_action += action + + # apply the action here + self.backend.apply_action(bk_action) + conv = self.backend.runpf() + bk_action.reset() + assert conv + after_amps_flow = self.backend.get_line_flow() + + topo_vect = self.backend.get_topo_vect() + assert np.min(topo_vect) == 1, "all buses have been changed" + assert np.max(topo_vect) == 2, "no buses have been changed" + + # check that the objects have been properly moved + load_ids = np.where(self.backend.load_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.load_pos_topo_vect[load_ids]] + == 1 + arr[self.backend.load_to_sub_pos[load_ids]] + ) + lor_ids = np.where(self.backend.line_or_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.line_or_pos_topo_vect[lor_ids]] + == 1 + arr[self.backend.line_or_to_sub_pos[lor_ids]] + ) + lex_ids = np.where(self.backend.line_ex_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.line_ex_pos_topo_vect[lex_ids]] + == 1 + arr[self.backend.line_ex_to_sub_pos[lex_ids]] + ) + gen_ids = np.where(self.backend.gen_to_subid == id_)[0] + assert np.all( + topo_vect[self.backend.gen_pos_topo_vect[gen_ids]] + == 1 + arr[self.backend.gen_to_sub_pos[gen_ids]] + ) + + after_amps_flow_th = np.array( + [ + 583.6123, + 334.8705, + 315.5799, + 267.74664, + 80.43121, + 79.1541, + 201.56798, + 212.99492, + 219.70985, + 512.4593, + 188.68764, + 281.67615, + 105.61588, + 48.10775, + 156.67145, + 125.26039, + 67.50609, + 184.34944, + 688.1158, + 792.68823 + ] + ) + assert self.compare_vect(after_amps_flow, after_amps_flow_th) + self._check_kirchoff() + + action = self.helper_action({"change_bus": {"substations_id": [(id_, arr)]}}) + bk_action += action + + # apply the action here + self.backend.apply_action(bk_action) + conv = self.backend.runpf() + assert conv + + after_amps_flow = self.backend.get_line_flow() + assert self.compare_vect(after_amps_flow, init_amps_flow) + topo_vect = self.backend.get_topo_vect() + assert np.min(topo_vect) == 1 + assert np.max(topo_vect) == 1 + self._check_kirchoff() + + def test_topo_change_2sub(self): + # check that maintenance vector is properly taken into account + self.skip_if_needed() + arr1 = np.array([False, False, False, True, True, True], dtype=dt_bool) + arr2 = np.array([1, 1, 2, 2], dtype=dt_int) + id_1 = 1 + id_2 = 12 + action = self.helper_action( + { + "change_bus": {"substations_id": [(id_1, arr1)]}, + "set_bus": {"substations_id": [(id_2, arr2)]}, + } + ) + bk_action = self.bkact_class() + bk_action += action + + # apply the action here + self.backend.apply_action(bk_action) + conv = self.backend.runpf() + assert conv, "powerflow diverge it should not" + + # check the _grid is correct + topo_vect = self.backend.get_topo_vect() + assert np.min(topo_vect) == 1, "all buses have been changed" + assert np.max(topo_vect) == 2, "no buses have been changed" + + # check that the objects have been properly moved + load_ids = np.where(self.backend.load_to_subid == id_1)[0] + assert np.all( + topo_vect[self.backend.load_pos_topo_vect[load_ids]] + == 1 + arr1[self.backend.load_to_sub_pos[load_ids]] + ) + lor_ids = np.where(self.backend.line_or_to_subid == id_1)[0] + assert np.all( + topo_vect[self.backend.line_or_pos_topo_vect[lor_ids]] + == 1 + arr1[self.backend.line_or_to_sub_pos[lor_ids]] + ) + lex_ids = np.where(self.backend.line_ex_to_subid == id_1)[0] + assert np.all( + topo_vect[self.backend.line_ex_pos_topo_vect[lex_ids]] + == 1 + arr1[self.backend.line_ex_to_sub_pos[lex_ids]] + ) + gen_ids = np.where(self.backend.gen_to_subid == id_1)[0] + assert np.all( + topo_vect[self.backend.gen_pos_topo_vect[gen_ids]] + == 1 + arr1[self.backend.gen_to_sub_pos[gen_ids]] + ) + + load_ids = np.where(self.backend.load_to_subid == id_2)[0] + # TODO check the topology symmetry + assert np.all( + topo_vect[self.backend.load_pos_topo_vect[load_ids]] + == arr2[self.backend.load_to_sub_pos[load_ids]] + ) + lor_ids = np.where(self.backend.line_or_to_subid == id_2)[0] + assert np.all( + topo_vect[self.backend.line_or_pos_topo_vect[lor_ids]] + == arr2[self.backend.line_or_to_sub_pos[lor_ids]] + ) + lex_ids = np.where(self.backend.line_ex_to_subid == id_2)[0] + assert np.all( + topo_vect[self.backend.line_ex_pos_topo_vect[lex_ids]] + == arr2[self.backend.line_ex_to_sub_pos[lex_ids]] + ) + gen_ids = np.where(self.backend.gen_to_subid == id_2)[0] + assert np.all( + topo_vect[self.backend.gen_pos_topo_vect[gen_ids]] + == arr2[self.backend.gen_to_sub_pos[gen_ids]] + ) + + after_amps_flow = self.backend.get_line_flow() + after_amps_flow_th = np.array( + [ + 592.3022, + 334.58173, + 319.68008, + 272.15067, + 82.911255, + 78.952034, + 235.09232, + 485.83984, + 104.81853, + 67.99528, + 156.10371, + 937.6077, + 380.4651, + 67.99528, + 466.0704, + 147.80254, + 84.15815, + 148.39969, + 911.69543, + 1055.2267 + ] + ) + print(after_amps_flow) + + assert self.compare_vect(after_amps_flow, after_amps_flow_th) + self._check_kirchoff() + + def _aux_test_back_orig(self, act_set, prod_p, load_p, p_or, sh_q): + """function used for test_get_action_to_set""" + bk_act = self.backend.my_bk_act_class() + bk_act += act_set + self.backend.apply_action(bk_act) + self._aux_aux_check_if_matches(prod_p, load_p, p_or, sh_q) + + def _aux_aux_check_if_matches(self, prod_p, load_p, p_or, sh_q): + self.backend.runpf() + prod_p3, prod_q3, prod_v3 = self.backend.generators_info() + load_p3, load_q3, load_v3 = self.backend.loads_info() + p_or3, *_ = self.backend.lines_or_info() + if self.backend.shunts_data_available: + _, sh_q3, *_ = self.backend.shunt_info() + assert np.all( + np.abs(prod_p3 - prod_p) <= self.tol_one + ), "wrong generators value" + assert np.all(np.abs(load_p3 - load_p) <= self.tol_one), "wrong load value" + assert np.all( + np.abs(p_or3 - p_or) <= self.tol_one + ), "wrong value for active flow origin" + assert np.all( + np.abs(p_or3 - p_or) <= self.tol_one + ), "wrong value for active flow origin" + if self.backend.shunts_data_available: + assert np.all( + np.abs(sh_q3 - sh_q) <= self.tol_one + ), "wrong value for shunt readtive" + + def test_get_action_to_set(self): + """this tests the "get_action_to_set" method""" + self.skip_if_needed() + self.backend.runpf() + self.backend.assert_grid_correct_after_powerflow() + + self.backend.runpf() + act = self.backend.get_action_to_set() + + prod_p, prod_q, prod_v = self.backend.generators_info() + load_p, load_q, load_v = self.backend.loads_info() + p_or, *_ = self.backend.lines_or_info() + + if self.backend.shunts_data_available: + _, sh_q, *_ = self.backend.shunt_info() + else: + sh_q = None + + # modify its state for injection + act2 = copy.deepcopy(act) + act2._dict_inj["prod_p"] *= 1 + act2._dict_inj["load_p"] *= 1 + bk_act2 = self.backend.my_bk_act_class() + bk_act2 += act2 + self.backend.apply_action(bk_act2) + self.backend.runpf() + prod_p2, prod_q2, prod_v2 = self.backend.generators_info() + load_p2, load_q2, load_v2 = self.backend.loads_info() + p_or2, *_ = self.backend.lines_or_info() + assert np.any(np.abs(prod_p2 - prod_p) >= self.tol_one) + assert np.any(np.abs(load_p2 - load_p) >= self.tol_one) + assert np.any(np.abs(p_or2 - p_or) >= self.tol_one) + # check i can put it back to orig state + try: + self._aux_test_back_orig(act, prod_p, load_p, p_or, sh_q) + except AssertionError as exc_: + raise AssertionError("Error for injection: {}".format(exc_)) + + # disconnect a powerline + act2 = copy.deepcopy(act) + l_id = 0 + act2._set_line_status[l_id] = -1 + act2._set_topo_vect[act2.line_or_pos_topo_vect[l_id]] = -1 + act2._set_topo_vect[act2.line_ex_pos_topo_vect[l_id]] = -1 + bk_act2 = self.backend.my_bk_act_class() + bk_act2 += act2 + self.backend.apply_action(bk_act2) + self.backend.runpf() + p_or2, *_ = self.backend.lines_or_info() + assert np.abs(p_or2[l_id]) <= self.tol_one, "line has not been disconnected" + assert np.any(np.abs(p_or2 - p_or) >= self.tol_one) + # check i can put it back to orig state + try: + self._aux_test_back_orig(act, prod_p, load_p, p_or, sh_q) + except AssertionError as exc_: + raise AssertionError("Error for line_status: {}".format(exc_)) + + # change topology + act2 = copy.deepcopy(act) + act2._set_topo_vect[6:9] = 2 + act2._set_topo_vect[6:9] = 2 + bk_act2 = self.backend.my_bk_act_class() + bk_act2 += act2 + self.backend.apply_action(bk_act2) + self.backend.runpf() + p_or2, *_ = self.backend.lines_or_info() + assert np.any(np.abs(p_or2 - p_or) >= self.tol_one) + # check i can put it back to orig state + try: + self._aux_test_back_orig(act, prod_p, load_p, p_or, sh_q) + except AssertionError as exc_: + raise AssertionError("Error for topo: {}".format(exc_)) + + # change shunt + if self.backend.shunts_data_available: + act2 = copy.deepcopy(act) + act2.shunt_q[:] = -25.0 + bk_act2 = self.backend.my_bk_act_class() + bk_act2 += act2 + self.backend.apply_action(bk_act2) + self.backend.runpf() + prod_p2, prod_q2, prod_v2 = self.backend.generators_info() + _, sh_q2, *_ = self.backend.shunt_info() + p_or2, *_ = self.backend.lines_or_info() + assert np.any(np.abs(prod_p2 - prod_p) >= self.tol_one) + assert np.any(np.abs(p_or2 - p_or) >= self.tol_one) + assert np.any(np.abs(sh_q2 - sh_q) >= self.tol_one) + # check i can put it back to orig state + try: + self._aux_test_back_orig(act, prod_p, load_p, p_or, sh_q) + except AssertionError as exc_: + raise AssertionError("Error for shunt: {}".format(exc_)) + + def test_get_action_to_set_storage(self): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = make( + "educ_case14_storage", + test=True, + backend=self.make_backend(), + _add_to_name="test_gats_storage", + ) + env2 = make( + "educ_case14_storage", + test=True, + backend=self.make_backend(), + _add_to_name="test_gats_storage", + ) + obs, *_ = env.step(env.action_space({"set_storage": [-1.0, 1.0]})) + act = env.backend.get_action_to_set() + + bk_act2 = env2.backend.my_bk_act_class() + bk_act2 += act + env2.backend.apply_action(bk_act2) + env2.backend.runpf() + assert np.all(env2.backend.storages_info()[0] == env.backend.storages_info()[0]) + + def _aux_test_back_orig_2(self, obs, prod_p, load_p, p_or, sh_q): + self.backend.update_from_obs(obs) + self._aux_aux_check_if_matches(prod_p, load_p, p_or, sh_q) + + def test_update_from_obs(self): + """this tests the "update_from_obs" method""" + self.skip_if_needed() + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = make( + '../data_test/l2rpn_case14_sandbox_Pypowsybl', + test=True, + backend=self.make_backend(), + _add_to_name="test_update_from_obs", + ) + + self.backend.close() + self.backend = env.backend + act = self.backend.get_action_to_set() + obs = env.reset() + + # store the initial value that should be there when i reapply the "update_from_obs" + prod_p, prod_q, prod_v = self.backend.generators_info() + load_p, load_q, load_v = self.backend.loads_info() + p_or, *_ = self.backend.lines_or_info() + if self.backend.shunts_data_available: + _, sh_q, *_ = self.backend.shunt_info() + else: + sh_q = None + + # modify its state for injection + act2 = copy.deepcopy(act) + act2._dict_inj["prod_p"] *= 1.5 + act2._dict_inj["load_p"] *= 1.5 + bk_act2 = self.backend.my_bk_act_class() + bk_act2 += act2 + self.backend.apply_action(bk_act2) + self.backend.runpf() + prod_p2, prod_q2, prod_v2 = self.backend.generators_info() + load_p2, load_q2, load_v2 = self.backend.loads_info() + p_or2, *_ = self.backend.lines_or_info() + assert np.any(np.abs(prod_p2 - prod_p) >= self.tol_one) + assert np.any(np.abs(load_p2 - load_p) >= self.tol_one) + assert np.any(np.abs(p_or2 - p_or) >= self.tol_one) + # check i can put it back to orig state + try: + self._aux_test_back_orig_2(obs, prod_p, load_p, p_or, sh_q) + except AssertionError as exc_: + raise AssertionError("Error for injection: {}".format(exc_)) + + # disconnect a powerline + act2 = copy.deepcopy(act) + l_id = 0 + act2._set_line_status[l_id] = -1 + act2._set_topo_vect[act2.line_or_pos_topo_vect[l_id]] = -1 + act2._set_topo_vect[act2.line_ex_pos_topo_vect[l_id]] = -1 + bk_act2 = self.backend.my_bk_act_class() + bk_act2 += act2 + self.backend.apply_action(bk_act2) + self.backend.runpf() + p_or2, *_ = self.backend.lines_or_info() + assert np.abs(p_or2[l_id]) <= self.tol_one, "line has not been disconnected" + assert np.any(np.abs(p_or2 - p_or) >= self.tol_one) + # check i can put it back to orig state + try: + self._aux_test_back_orig_2(obs, prod_p, load_p, p_or, sh_q) + except AssertionError as exc_: + raise AssertionError("Error for line_status: {}".format(exc_)) + + # change topology + act2 = copy.deepcopy(act) + act2._set_topo_vect[6:9] = 2 + act2._set_topo_vect[6:9] = 2 + bk_act2 = self.backend.my_bk_act_class() + bk_act2 += act2 + self.backend.apply_action(bk_act2) + self.backend.runpf() + p_or2, *_ = self.backend.lines_or_info() + assert np.any(np.abs(p_or2 - p_or) >= self.tol_one) + # check i can put it back to orig state + try: + self._aux_test_back_orig_2(obs, prod_p, load_p, p_or, sh_q) + except AssertionError as exc_: + raise AssertionError("Error for topo: {}".format(exc_)) + + # change shunt + if self.backend.shunts_data_available: + act2 = copy.deepcopy(act) + act2.shunt_q[:] = -25.0 + bk_act2 = self.backend.my_bk_act_class() + bk_act2 += act2 + self.backend.apply_action(bk_act2) + self.backend.runpf() + prod_p2, prod_q2, prod_v2 = self.backend.generators_info() + _, sh_q2, *_ = self.backend.shunt_info() + p_or2, *_ = self.backend.lines_or_info() + assert np.any(np.abs(prod_p2 - prod_p) >= self.tol_one) + assert np.any(np.abs(p_or2 - p_or) >= self.tol_one) + assert np.any(np.abs(sh_q2 - sh_q) >= self.tol_one) + # check i can put it back to orig state + try: + self._aux_test_back_orig_2(obs, prod_p, load_p, p_or, sh_q) + except AssertionError as exc_: + raise AssertionError("Error for shunt: {}".format(exc_)) + + +class BaseTestEnvPerformsCorrectCascadingFailures(MakeBackend): + """ + Test the "next_grid_state" method of the back-end + """ + + def setUp(self): + self.backend = self.make_backend(detailed_infos_for_cascading_failures=True) + type(self.backend)._clear_class_attribute() + self.path_matpower = self.get_path() + self.case_file = self.get_casefile() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.backend.load_grid(self.path_matpower, self.case_file) + type(self.backend).set_env_name("TestEnvPerformsCorrectCascadingFailures_env") + type(self.backend).set_no_storage() + self.backend.assert_grid_correct() + self.game_rules = RulesChecker() + self.action_env = ActionSpace( + gridobj=self.backend, legal_action=self.game_rules.legal_action + ) + + self.lines_flows_init = np.array( + [ + 638.28966637, + 305.05042301, + 17658.9674809, + 26534.04334098, + 10869.23856329, + 4686.71726729, + 15612.65903298, + 300.07915572, + 229.8060832, + 169.97292682, + 100.40192958, + 265.47505664, + 21193.86923911, + 21216.44452327, + 49701.1565287, + 124.79684388, + 67.59759985, + 192.19424706, + 666.76961936, + 1113.52773632, + ] + ) + # _parameters for the environment + self.env_params = Parameters() + + # used for init an env too + self.chronics_handler = ChronicsHandler() + self.id_first_line_disco = 8 # due to hard overflow + self.id_2nd_line_disco = 11 # due to soft overflow + + def tearDown(self): + pass + + def next_grid_state_no_overflow(self): + # first i test that, when there is no overflow, i dont do a cascading failure + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = Environment( + init_grid_path=os.path.join(self.path_matpower, self.case_file), + backend=self.backend, + init_env_path=os.path.join(self.path_matpower, self.case_file), + chronics_handler=self.chronics_handler, + parameters=self.env_params, + name="test_pp_env1", + ) + + disco, infos, conv_ = self.backend.next_grid_state(env, is_dc=False) + assert conv_ is None + assert not infos + + def test_next_grid_state_1overflow(self): + # second i test that, when is one line on hard overflow it is disconnected + self.skip_if_needed() + case_file = self.case_file + env_params = copy.deepcopy(self.env_params) + env_params.HARD_OVERFLOW_THRESHOLD = 1.5 + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = Environment( + init_grid_path=os.path.join(self.path_matpower, case_file), + init_env_path=os.path.join(self.path_matpower, case_file), + backend=self.backend, + chronics_handler=self.chronics_handler, + parameters=env_params, + name="test_pp_env2", + ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.backend.load_grid(self.path_matpower, case_file) + type(self.backend).set_no_storage() + self.backend.assert_grid_correct() + + thermal_limit = 10 * self.lines_flows_init + thermal_limit[self.id_first_line_disco] = ( + self.lines_flows_init[self.id_first_line_disco] / 2 + ) + self.backend.set_thermal_limit(thermal_limit) + + disco, infos, conv_ = self.backend.next_grid_state(env, is_dc=False) + assert conv_ is None + assert len(infos) == 1 # check that i have only one overflow + assert np.sum(disco >= 0) == 1 + + def test_next_grid_state_1overflow_envNoCF(self): + # third i test that, if a line is on hard overflow, but i'm on a "no cascading failure" mode, + # i don't simulate a cascading failure + self.skip_if_needed() + self.env_params.NO_OVERFLOW_DISCONNECTION = True + case_file = self.case_file + env_params = copy.deepcopy(self.env_params) + env_params.HARD_OVERFLOW_THRESHOLD = 1.5 + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = Environment( + init_grid_path=os.path.join(self.path_matpower, case_file), + backend=self.backend, + init_env_path=os.path.join(self.path_matpower, case_file), + chronics_handler=self.chronics_handler, + parameters=self.env_params, + name="test_pp_env3", + ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.backend.load_grid(self.path_matpower, case_file) + type(self.backend).set_no_storage() + self.backend.assert_grid_correct() + conv = self.backend.runpf() + assert conv, "powerflow should converge at loading" + lines_flows_init = self.backend.get_line_flow() + thermal_limit = 10 * lines_flows_init + thermal_limit[self.id_first_line_disco] = ( + lines_flows_init[self.id_first_line_disco] / 2 + ) + self.backend.set_thermal_limit(thermal_limit) + + disco, infos, conv_ = self.backend.next_grid_state(env, is_dc=False) + assert conv_ is None + assert not infos # check that don't simulate a cascading failure + assert np.sum(disco >= 0) == 0 + + def test_set_thermal_limit(self): + thermal_limit = np.arange(self.backend.n_line) + self.backend.set_thermal_limit(thermal_limit) + assert np.all(self.backend.thermal_limit_a == thermal_limit) + + def test_nb_timestep_overflow_disc0(self): + # on this _grid, first line with id 5 is overheated, + # it is disconnected + # then powerline 16 have a relative flow of 1.5916318201096937 + # in this scenario i don't have a second line disconnection. + self.skip_if_needed() + case_file = self.case_file + env_params = copy.deepcopy(self.env_params) + env_params.HARD_OVERFLOW_THRESHOLD = 1.5 + env_params.NB_TIMESTEP_OVERFLOW_ALLOWED = 0 + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = Environment( + init_grid_path=os.path.join(self.path_matpower, case_file), + backend=self.backend, + init_env_path=os.path.join(self.path_matpower, case_file), + chronics_handler=self.chronics_handler, + parameters=env_params, + name="test_pp_env4", + ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.backend.load_grid(self.path_matpower, case_file) + type(self.backend).set_no_storage() + self.backend.assert_grid_correct() + conv = self.backend.runpf() + assert conv, "powerflow should converge at loading" + lines_flows_init = self.backend.get_line_flow() + + thermal_limit = 10 * lines_flows_init + thermal_limit[self.id_first_line_disco] = ( + lines_flows_init[self.id_first_line_disco] / 2 + ) + thermal_limit[self.id_2nd_line_disco] = 400 + self.backend.set_thermal_limit(thermal_limit) + + disco, infos, conv_ = self.backend.next_grid_state(env, is_dc=False) + assert conv_ is None + assert len(infos) == 2 # check that there is a cascading failure of length 2 + assert disco[self.id_first_line_disco] >= 0 + assert disco[self.id_2nd_line_disco] >= 0 + assert np.sum(disco >= 0) == 2 + + def test_nb_timestep_overflow_nodisc(self): + # on this _grid, first line with id 18 is overheated, + # it is disconnected + # then powerline 16 have a relative flow of 1.5916318201096937 + + # in this scenario i don't have a second line disconnection because + # the overflow is a soft overflow and the powerline is presumably overflow since 0 + # timestep + self.skip_if_needed() + case_file = self.case_file + env_params = copy.deepcopy(self.env_params) + env_params.HARD_OVERFLOW_THRESHOLD = 1.5 + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = Environment( + init_grid_path=os.path.join(self.path_matpower, case_file), + backend=self.backend, + chronics_handler=self.chronics_handler, + init_env_path=os.path.join(self.path_matpower, case_file), + parameters=env_params, + name="test_pp_env5", + ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.backend.load_grid(self.path_matpower, case_file) + type(self.backend).set_no_storage() + self.backend.assert_grid_correct() + + env._timestep_overflow[self.id_2nd_line_disco] = 0 + thermal_limit = 10 * self.lines_flows_init + thermal_limit[self.id_first_line_disco] = ( + self.lines_flows_init[self.id_first_line_disco] / 2 + ) + thermal_limit[self.id_2nd_line_disco] = 400 + self.backend.set_thermal_limit(thermal_limit) + + disco, infos, conv_ = self.backend.next_grid_state(env, is_dc=False) + assert conv_ is None + assert len(infos) == 1 # check that don't simulate a cascading failure + assert disco[self.id_first_line_disco] >= 0 + assert np.sum(disco >= 0) == 1 + + def test_nb_timestep_overflow_nodisc_2(self): + # on this _grid, first line with id 18 is overheated, + # it is disconnected + # then powerline 16 have a relative flow of 1.5916318201096937 + + # in this scenario i don't have a second line disconnection because + # the overflow is a soft overflow and the powerline is presumably overflow since only 1 + # timestep + self.skip_if_needed() + case_file = self.case_file + env_params = copy.deepcopy(self.env_params) + env_params.HARD_OVERFLOW_THRESHOLD = 1.5 + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = Environment( + init_grid_path=os.path.join(self.path_matpower, case_file), + backend=self.backend, + chronics_handler=self.chronics_handler, + init_env_path=os.path.join(self.path_matpower, case_file), + parameters=env_params, + name="test_pp_env6", + ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.backend.load_grid(self.path_matpower, case_file) + type(self.backend).set_no_storage() + self.backend.assert_grid_correct() + + env._timestep_overflow[self.id_2nd_line_disco] = 1 + + thermal_limit = 10 * self.lines_flows_init + thermal_limit[self.id_first_line_disco] = ( + self.lines_flows_init[self.id_first_line_disco] / 2 + ) + thermal_limit[self.id_2nd_line_disco] = 400 + self.backend.set_thermal_limit(thermal_limit) + + disco, infos, conv_ = self.backend.next_grid_state(env, is_dc=False) + assert conv_ is None + assert len(infos) == 1 # check that don't simulate a cascading failure + assert disco[self.id_first_line_disco] >= 0 + assert np.sum(disco >= 0) == 1 + + def test_nb_timestep_overflow_disc2(self): + # on this _grid, first line with id 18 is overheated, + # it is disconnected + # then powerline 16 have a relative flow of 1.5916318201096937 + + # in this scenario I have a second disconnection, because the powerline is allowed to be on overflow for 2 + # timestep and is still on overflow here. + self.skip_if_needed() + case_file = self.case_file + env_params = copy.deepcopy(self.env_params) + env_params.HARD_OVERFLOW_THRESHOLD = 1.5 + env_params.NB_TIMESTEP_OVERFLOW_ALLOWED = 2 + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = Environment( + init_grid_path=os.path.join(self.path_matpower, case_file), + backend=self.backend, + chronics_handler=self.chronics_handler, + init_env_path=os.path.join(self.path_matpower, case_file), + parameters=env_params, + name="test_pp_env7", + ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.backend.load_grid(self.path_matpower, case_file) + type(self.backend).set_no_storage() + self.backend.assert_grid_correct() + + env._timestep_overflow[self.id_2nd_line_disco] = 2 + + thermal_limit = 10 * self.lines_flows_init + thermal_limit[self.id_first_line_disco] = ( + self.lines_flows_init[self.id_first_line_disco] / 2 + ) + thermal_limit[self.id_2nd_line_disco] = 400 + self.backend.set_thermal_limit(thermal_limit) + + disco, infos, conv_ = self.backend.next_grid_state(env, is_dc=False) + assert conv_ is None + assert len(infos) == 2 # check that there is a cascading failure of length 2 + assert disco[self.id_first_line_disco] >= 0 + assert disco[self.id_2nd_line_disco] >= 0 + assert np.sum(disco >= 0) == 2 + for i, grid_tmp in enumerate(infos): + assert not grid_tmp.get_line_status()[self.id_first_line_disco] + if i == 1: + assert not grid_tmp.get_line_status()[self.id_2nd_line_disco] + + +class BaseTestChangeBusAffectRightBus(MakeBackend): + def test_set_bus(self): + self.skip_if_needed() + # print("test_set_bus") + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = make(test=True, backend=backend) + env.reset() + action = env.action_space({"set_bus": {"lines_or_id": [(17, 2)]}}) + obs, reward, done, info = env.step(action) + assert np.all(np.isfinite(obs.v_or)) + assert np.sum(env.backend.get_topo_vect() == 2) == 1 + assert np.all(np.isfinite(obs.to_vect())) + + def test_change_bus(self): + self.skip_if_needed() + # print("test_change_bus") + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = make(test=True, backend=backend) + env.reset() + action = env.action_space({"change_bus": {"lines_or_id": [17]}}) + obs, reward, done, info = env.step(action) + assert np.all(np.isfinite(obs.v_or)) + assert np.sum(env.backend.get_topo_vect() == 2) == 1 + + def test_change_bustwice(self): + self.skip_if_needed() + # print("test_change_bustwice") + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = make(test=True, backend=backend) + env.reset() + action = env.action_space({"change_bus": {"lines_or_id": [17]}}) + obs, reward, done, info = env.step(action) + assert not done + assert np.all(np.isfinite(obs.v_or)) + assert np.sum(env.backend.get_topo_vect() == 2) == 1 + + action = env.action_space({"change_bus": {"lines_or_id": [17]}}) + obs, reward, done, info = env.step(action) + assert not done + assert np.all(np.isfinite(obs.v_or)) + assert np.sum(env.backend.get_topo_vect() == 2) == 0 + + def test_isolate_load(self): + self.skip_if_needed() + # print("test_isolate_load") + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = make(test=True, backend=backend) + act = env.action_space({"set_bus": {"loads_id": [(0, 2)]}}) + obs, reward, done, info = env.step(act) + assert done, "an isolated load has not lead to a game over" + + def test_reco_disco_bus(self): + self.skip_if_needed() + # print("test_reco_disco_bus") + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env_case1 = make( + "rte_case5_example", + test=True, + gamerules_class=AlwaysLegal, + backend=backend, + ) + obs = env_case1.reset() # reset is good + act = env_case1.action_space.disconnect_powerline( + line_id=5 + ) # I disconnect a powerline + obs, reward, done, info = env_case1.step(act) # do the action, it's valid + act_case1 = env_case1.action_space.reconnect_powerline( + line_id=5, bus_or=2, bus_ex=2 + ) # reconnect powerline on bus 2 both ends + # this should lead to a game over a the powerline is out of the grid, 2 buses are, but without anything + # this is a non connex grid + obs_case1, reward_case1, done_case1, info_case1 = env_case1.step(act_case1) + assert done_case1 + + def test_reco_disco_bus2(self): + self.skip_if_needed() + # print("test_reco_disco_bus2") + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env_case2 = make( + "rte_case5_example", + test=True, + gamerules_class=AlwaysLegal, + backend=backend, + ) + obs = env_case2.reset() # reset is good + obs, reward, done, info = env_case2.step( + env_case2.action_space() + ) # do the action, it's valid + act_case2 = env_case2.action_space.reconnect_powerline( + line_id=5, bus_or=2, bus_ex=2 + ) # reconnect powerline on bus 2 both ends + # this should lead to a game over a the powerline is out of the grid, 2 buses are, but without anything + # this is a non connex grid + obs_case2, reward_case2, done_case2, info_case2 = env_case2.step(act_case2) + # this was illegal before, but test it is still illegal + assert done_case2 + + def test_reco_disco_bus3(self): + self.skip_if_needed() + # print("test_reco_disco_bus3") + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env_case2 = make( + "rte_case5_example", + test=True, + gamerules_class=AlwaysLegal, + backend=backend, + ) + obs = env_case2.reset() # reset is good + obs, reward, done, info = env_case2.step( + env_case2.action_space() + ) # do the action, it's valid + act_case2 = env_case2.action_space.reconnect_powerline( + line_id=5, bus_or=1, bus_ex=2 + ) # reconnect powerline on bus 2 both ends + # this should not lead to a game over this time, the grid is connex! + obs_case2, reward_case2, done_case2, info_case2 = env_case2.step(act_case2) + assert done_case2 is False + + def test_reco_disco_bus4(self): + self.skip_if_needed() + # print("test_reco_disco_bus4") + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env_case2 = make( + "rte_case5_example", + test=True, + gamerules_class=AlwaysLegal, + backend=backend, + ) + obs = env_case2.reset() # reset is good + obs, reward, done, info = env_case2.step( + env_case2.action_space() + ) # do the action, it's valid + act_case2 = env_case2.action_space.reconnect_powerline( + line_id=5, bus_or=2, bus_ex=1 + ) # reconnect powerline on bus 2 both ends + # this should not lead to a game over this time, the grid is connex! + obs_case2, reward_case2, done_case2, info_case2 = env_case2.step(act_case2) + assert done_case2 is False + + def test_reco_disco_bus5(self): + self.skip_if_needed() + # print("test_reco_disco_bus5") + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env_case2 = make( + "rte_case5_example", + test=True, + gamerules_class=AlwaysLegal, + backend=backend, + ) + obs = env_case2.reset() # reset is good + act_case2 = env_case2.action_space( + {"set_bus": {"lines_or_id": [(5, 2)], "lines_ex_id": [(5, 2)]}} + ) # reconnect powerline on bus 2 both ends + # this should not lead to a game over this time, the grid is connex! + obs_case2, reward_case2, done_case2, info_case2 = env_case2.step(act_case2) + assert done_case2 + + +class BaseTestShuntAction(MakeBackend): + def test_shunt_ambiguous_id_incorrect(self): + self.skip_if_needed() + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + with make( + "rte_case5_example", + test=True, + gamerules_class=AlwaysLegal, + action_class=CompleteAction, + backend=backend, + ) as env_case2: + with self.assertRaises(AmbiguousAction): + act = env_case2.action_space({"shunt": {"set_bus": [(0, 2)]}}) + + def test_shunt_effect(self): + self.skip_if_needed() + backend1 = self.make_backend() + backend2 = self.make_backend() + type(backend1)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env_ref = make( + "rte_case14_realistic", + test=True, + gamerules_class=AlwaysLegal, + action_class=CompleteAction, + backend=backend1, + _add_to_name="BaseTestShuntAction", + ) + env_change_q = make( + "rte_case14_realistic", + test=True, + gamerules_class=AlwaysLegal, + action_class=CompleteAction, + backend=backend2, + _add_to_name="BaseTestShuntAction", + ) + param = env_ref.parameters + param.NO_OVERFLOW_DISCONNECTION = True + env_ref.change_parameters(param) + env_change_q.change_parameters(param) + env_ref.set_id(0) + env_change_q.set_id(0) + env_ref.reset() + env_change_q.reset() + + obs_ref, *_ = env_ref.step(env_ref.action_space()) + with warnings.catch_warnings(): + warnings.filterwarnings("error") + act = env_change_q.action_space({"shunt": {"shunt_q": [(0, -30)]}}) + obs_change_p_down, *_ = env_change_q.step(act) + assert obs_ref.v_or[10] < obs_change_p_down.v_or[10] - self.tol_one + obs_change_p_up, *_ = env_change_q.step( + env_change_q.action_space({"shunt": {"shunt_q": [(0, +30)]}}) + ) + obs_ref, *_ = env_ref.step(env_ref.action_space()) + assert obs_ref.v_or[10] > obs_change_p_up.v_or[10] + self.tol_one + obs_disco_sh, *_ = env_change_q.step( + env_change_q.action_space({"shunt": {"set_bus": [(0, -1)]}}) + ) + # given the shunt amount at first, this is the right test to do + assert obs_ref.v_or[10] > obs_disco_sh.v_or[10] + self.tol_one + + # test specific rule on shunt: if alone on a bus, it's disconnected ??? + obs_co_bus2_sh_alone, *_ = env_change_q.step( + env_change_q.action_space({"shunt": {"set_bus": [(0, 2)]}}) + ) + assert obs_co_bus2_sh_alone._shunt_bus == -1 + assert obs_co_bus2_sh_alone._shunt_v == 0. + assert obs_co_bus2_sh_alone._shunt_p == 0 + assert obs_co_bus2_sh_alone._shunt_q == 0 + + # note that above the backend can diverge (shunt is alone on its bus !) + # on pp it does not ... but it probably should + env_ref.set_id(0) + env_change_q.set_id(0) + env_ref.reset() + env_change_q.reset() + act = env_change_q.action_space({"set_bus": {"lines_or_id": [(10, 2)]}, + "shunt": {"set_bus": [(0, 2)]} + }) + + obs_co_bus2_sh_notalone, *_ = env_change_q.step(act) + assert obs_co_bus2_sh_notalone.line_or_bus[10] == 2 + assert np.allclose(obs_co_bus2_sh_notalone.v_or[10], 23.15359878540039) + assert obs_co_bus2_sh_notalone._shunt_bus == 2 + assert np.allclose(obs_co_bus2_sh_notalone._shunt_v, 23.15359878540039) + assert obs_co_bus2_sh_notalone._shunt_p == 0 + assert obs_co_bus2_sh_notalone._shunt_q == -25.464233 + + +class BaseTestResetEqualsLoadGrid(MakeBackend): + def setUp(self): + backend1 = self.make_backend() + backend2 = self.make_backend() + type(backend1)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.env1 = make("rte_case5_example", test=True, backend=backend1) + self.backend1 = self.env1.backend + self.env2 = make("rte_case5_example", test=True, backend=backend2) + self.backend2 = self.env2.backend + np.random.seed(69) + + def tearDown(self): + self.env1.close() + self.env2.close() + + def test_reset_equals_reset(self): + self.skip_if_needed() + # Reset backend1 with reset + self.env1.reset() + # Reset backend2 with reset + self.env2.reset() + self._compare_backends() + + def _compare_backends(self): + # Compare + if hasattr(self.backend1, "prod_pu_to_kv") and hasattr( + self.backend2, "prod_pu_to_kv" + ): + assert np.all(self.backend1.prod_pu_to_kv == self.backend2.prod_pu_to_kv) + if hasattr(self.backend1, "load_pu_to_kv") and hasattr( + self.backend2, "load_pu_to_kv" + ): + assert np.all(self.backend1.load_pu_to_kv == self.backend2.load_pu_to_kv) + if hasattr(self.backend1, "lines_or_pu_to_kv") and hasattr( + self.backend2, "lines_or_pu_to_kv" + ): + assert np.all( + self.backend1.lines_or_pu_to_kv == self.backend2.lines_or_pu_to_kv + ) + if hasattr(self.backend1, "lines_ex_pu_to_kv") and hasattr( + self.backend2, "lines_ex_pu_to_kv" + ): + assert np.all( + self.backend1.lines_ex_pu_to_kv == self.backend2.lines_ex_pu_to_kv + ) + if hasattr(self.backend1, "p_or") and hasattr(self.backend2, "p_or"): + assert np.all(self.backend1.p_or == self.backend2.p_or) + if hasattr(self.backend1, "q_or") and hasattr(self.backend2, "q_or"): + assert np.all(self.backend1.q_or == self.backend2.q_or) + if hasattr(self.backend1, "v_or") and hasattr(self.backend2, "v_or"): + assert np.all(self.backend1.v_or == self.backend2.v_or) + if hasattr(self.backend1, "a_or") and hasattr(self.backend2, "a_or"): + assert np.all(self.backend1.a_or == self.backend2.a_or) + if hasattr(self.backend1, "p_ex") and hasattr(self.backend2, "p_ex"): + assert np.all(self.backend1.p_ex == self.backend2.p_ex) + if hasattr(self.backend1, "a_ex") and hasattr(self.backend2, "a_ex"): + assert np.all(self.backend1.a_ex == self.backend2.a_ex) + if hasattr(self.backend1, "v_ex") and hasattr(self.backend2, "v_ex"): + assert np.all(self.backend1.v_ex == self.backend2.v_ex) + + def test_reset_equals_load_grid(self): + self.skip_if_needed() + # Reset backend1 with reset + self.env1.reset() + # Reset backend2 with load_grid + self.backend2.reset = self.backend2.load_grid + self.env2.reset() + + # Compare + self._compare_backends() + + def test_load_grid_equals_load_grid(self): + self.skip_if_needed() + # Reset backend1 with load_grid + self.backend1.reset = self.backend1.load_grid + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.env1.reset() + # Reset backend2 with load_grid + self.backend2.reset = self.backend2.load_grid + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.env2.reset() + + # Compare + self._compare_backends() + + def test_obs_from_same_chronic(self): + self.skip_if_needed() + # Store first observation + obs1 = self.env1.current_obs + obs2 = None + for i in range(3): + self.env1.step(self.env1.action_space({})) + + # Reset to first chronic + self.env1.chronics_handler.tell_id(-1) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.env1.reset() + + # Store second observation + obs2 = self.env1.current_obs + + # Compare + assert np.allclose(obs1.prod_p, obs2.prod_p) + assert np.allclose(obs1.prod_q, obs2.prod_q) + assert np.allclose(obs1.prod_v, obs2.prod_v) + assert np.allclose(obs1.load_p, obs2.load_p) + assert np.allclose(obs1.load_q, obs2.load_q) + assert np.allclose(obs1.load_v, obs2.load_v) + assert np.allclose(obs1.p_or, obs2.p_or) + assert np.allclose(obs1.q_or, obs2.q_or) + assert np.allclose(obs1.v_or, obs2.v_or) + assert np.allclose(obs1.a_or, obs2.a_or) + assert np.allclose(obs1.p_ex, obs2.p_ex) + assert np.allclose(obs1.q_ex, obs2.q_ex) + assert np.allclose(obs1.v_ex, obs2.v_ex) + assert np.allclose(obs1.a_ex, obs2.a_ex) + assert np.allclose(obs1.rho, obs2.rho) + assert np.all(obs1.line_status == obs2.line_status) + assert np.all(obs1.topo_vect == obs2.topo_vect) + assert np.all(obs1.timestep_overflow == obs2.timestep_overflow) + assert np.all(obs1.time_before_cooldown_line == obs2.time_before_cooldown_line) + assert np.all(obs1.time_before_cooldown_sub == obs2.time_before_cooldown_sub) + assert np.all(obs1.time_next_maintenance == obs2.time_next_maintenance) + assert np.all(obs1.duration_next_maintenance == obs2.duration_next_maintenance) + assert np.all(obs1.target_dispatch == obs2.target_dispatch) + assert np.all(obs1.actual_dispatch == obs2.actual_dispatch) + + def test_combined_changes(self): + # Unlimited sub changes + backend = self.make_backend() + type(backend)._clear_class_attribute() + params = grid2op.Parameters.Parameters() + params.MAX_SUB_CHANGED = 999 + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = grid2op.make( + "rte_case14_realistic", test=True, backend=backend, param=params + ) + + # Find N valid iadd combination of R change actions + acts = self.aux_random_topos_act(env, n=16, r=3) + # Pick one at random + act = np.random.choice(acts) + + # Reset env + obs = env.reset() + # At t=0 everything is on bus 1 normally + assert np.all(obs.topo_vect == 1) + + # Step + obs, _, done, _ = env.step(act) + # This should use valid actions + assert done == False + # At t=1, unchanged elements should be on bus 1 + assert np.all(obs.topo_vect[~act._change_bus_vect] == 1) + + def aux_nth_combination(self, iterable, r, index): + "Equivalent to list(combinations(iterable, r))[index]" + pool = tuple(iterable) + n = len(pool) + if r < 0 or r > n: + raise ValueError + c = 1 + k = min(r, n - r) + for i in range(1, k + 1): + c = c * (n - k + i) // i + if index < 0: + index += c + if index < 0 or index >= c: + raise IndexError + result = [] + while r: + c, n, r = c * r // n, n - 1, r - 1 + while index >= c: + index -= c + c, n = c * (n - r) // n, n - 1 + result.append(pool[-1 - n]) + return tuple(result) + + def aux_random_topos_act(self, env, n=128, r=2): + actsp = env.action_space + acts = actsp.get_all_unitary_topologies_change(actsp) + res = [] + n_comb = comb(len(acts), r) + while len(res) < n: + env.reset() + rnd_idx = np.random.randint(n_comb) + a = self.aux_nth_combination(acts, r, rnd_idx) + atest = env.action_space({}) + for atmp in a: + atest += atmp + _, _, done, _ = env.step(atest) + if not done: + res.append(copy.deepcopy(atest)) + return res + + +class BaseTestVoltageOWhenDisco(MakeBackend): + def test_this(self): + self.skip_if_needed() + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + with make("rte_case14_realistic", test=True, backend=backend) as env: + line_id = 1 + act = env.action_space({"set_line_status": [(line_id, -1)]}) + obs, *_ = env.step(act) + assert ( + obs.v_or[line_id] == 0.0 + ) # is not 0 however line is not connected + + +class BaseTestChangeBusSlack(MakeBackend): + def test_change_slack_case14(self): + self.skip_if_needed() + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = grid2op.make("rte_case14_realistic", test=True, backend=backend) + action = env.action_space( + { + "set_bus": { + "generators_id": [(env.n_gen - 1, 2)], + "lines_or_id": [(0, 2)], + } + } + ) + obs, reward, am_i_done, info = env.step(action) + assert am_i_done is False + assert np.all(obs.prod_p >= 0.0) + assert np.sum(obs.prod_p) >= np.sum(obs.load_p) + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + p_subs, q_subs, p_bus, q_bus, v_bus = env.backend.check_kirchoff() + assert np.all(np.abs(p_subs) <= self.tol_one) + assert np.all(np.abs(p_bus) <= self.tol_one) + + +class BaseTestStorageAction(MakeBackend): + def _aux_test_kirchoff(self): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + p_subs, q_subs, p_bus, q_bus, diff_v_bus = self.env.backend.check_kirchoff() + assert np.all( + np.abs(p_subs) <= self.tol_one + ), "error with active value at some substations" + assert np.all( + np.abs(q_subs) <= self.tol_one + ), "error with reactive value at some substations" + assert np.all( + np.abs(p_bus) <= self.tol_one + ), "error with active value at some bus" + assert np.all( + np.abs(q_bus) <= self.tol_one + ), "error with reactive value at some bus" + assert np.all(diff_v_bus <= self.tol_one), "error with voltage discrepency" + + def test_there_are_storage(self): + """test the backend properly loaded the storage units""" + self.skip_if_needed() + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.env = grid2op.make("educ_case14_storage", test=True, backend=backend) + assert self.env.n_storage == 2 + + def test_storage_action_mw(self): + """test the actions are properly implemented in the backend""" + self.skip_if_needed() + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.env = grid2op.make("educ_case14_storage", test=True, backend=backend) + + array_modif = np.array([-1.5, -10.0], dtype=dt_float) + act = self.env.action_space({"set_storage": array_modif}) + obs, reward, done, info = self.env.step(act) + assert not info["exception"] + storage_p, storage_q, storage_v = self.env.backend.storages_info() + assert np.all(np.abs(storage_p - array_modif) <= self.tol_one) + assert np.all(np.abs(storage_q - 0.0) <= self.tol_one) + self._aux_test_kirchoff() + + array_modif = np.array([2, 8], dtype=dt_float) + act = self.env.action_space({"set_storage": array_modif}) + obs, reward, done, info = self.env.step(act) + assert not info["exception"] + storage_p, storage_q, storage_v = self.env.backend.storages_info() + assert np.all(np.abs(storage_p - array_modif) <= self.tol_one) + assert np.all(np.abs(storage_q - 0.0) <= self.tol_one) + self._aux_test_kirchoff() + + # illegal action + array_modif = np.array([2, 12], dtype=dt_float) + act = self.env.action_space({"set_storage": array_modif}) + obs, reward, done, info = self.env.step(act) + assert info["exception"] + storage_p, storage_q, storage_v = self.env.backend.storages_info() + assert np.all(np.abs(storage_p - [0.0, 0.0]) <= self.tol_one) + assert np.all(np.abs(storage_q - 0.0) <= self.tol_one) + self._aux_test_kirchoff() + + # full discharge now + array_modif = np.array([-1.5, -10.0], dtype=dt_float) + for nb_ts in range(3): + act = self.env.action_space({"set_storage": array_modif}) + obs, reward, done, info = self.env.step(act) + assert not info["exception"] + storage_p, storage_q, storage_v = self.env.backend.storages_info() + assert np.all( + np.abs(storage_p - array_modif) <= self.tol_one + ), f"error for P for time step {nb_ts}" + assert np.all( + np.abs(storage_q - 0.0) <= self.tol_one + ), f"error for Q for time step {nb_ts}" + self._aux_test_kirchoff() + + obs, reward, done, info = self.env.step(act) + assert not info["exception"] + # i have emptied second battery + storage_p, *_ = self.env.backend.storages_info() + assert np.all(np.abs(storage_p - [-1.5, -4.4599934]) <= self.tol_one) + assert np.all(np.abs(obs.storage_charge[1] - 0.0) <= self.tol_one) + self._aux_test_kirchoff() + + obs, reward, done, info = self.env.step(act) + assert not info["exception"] + # i have emptied second battery + storage_p, *_ = self.env.backend.storages_info() + assert np.all(np.abs(storage_p - [-1.5, 0.0]) <= self.tol_one) + assert np.all(np.abs(obs.storage_charge[1] - 0.0) <= self.tol_one) + self._aux_test_kirchoff() + + def test_storage_action_topo(self): + """test the modification of the bus of a storage unit""" + self.skip_if_needed() + param = Parameters() + param.NB_TIMESTEP_COOLDOWN_SUB = 0 + param.NB_TIMESTEP_COOLDOWN_LINE = 0 + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + self.env = grid2op.make( + "educ_case14_storage", + test=True, + backend=backend, + param=param, + action_class=CompleteAction, + ) + + # test i can do a reset + obs = self.env.reset() + + # test i can do a step + obs, reward, done, info = self.env.step(self.env.action_space()) + exc_ = info["exception"] + assert ( + not done + ), f"i should be able to do a step with some storage units error is {exc_}" + storage_p, storage_q, storage_v = self.env.backend.storages_info() + assert np.all(np.abs(storage_p - 0.0) <= self.tol_one) + assert np.all(np.abs(storage_q - 0.0) <= self.tol_one) + + # first case, standard modification + array_modif = np.array([-1.5, -10.0], dtype=dt_float) + act = self.env.action_space( + { + "set_storage": array_modif, + "set_bus": { + "storages_id": [(0, 2)], + "lines_or_id": [(8, 2)], + "generators_id": [(3, 2)], + }, + } + ) + obs, reward, done, info = self.env.step(act) + assert not info["exception"] + storage_p, storage_q, storage_v = self.env.backend.storages_info() + assert np.all(np.abs(storage_p - array_modif) <= self.tol_one) + assert np.all(np.abs(storage_q - 0.0) <= self.tol_one) + assert obs.storage_bus[0] == 2 + assert obs.line_or_bus[8] == 2 + assert obs.gen_bus[3] == 2 + self._aux_test_kirchoff() + + # second case, still standard modification (set to orig) + array_modif = np.array([1.5, 10.0], dtype=dt_float) + act = self.env.action_space( + { + "set_storage": array_modif, + "set_bus": { + "storages_id": [(0, 1)], + "lines_or_id": [(8, 1)], + "generators_id": [(3, 1)], + }, + } + ) + obs, reward, done, info = self.env.step(act) + assert not info["exception"] + storage_p, storage_q, storage_v = self.env.backend.storages_info() + assert np.all(np.abs(storage_p - array_modif) <= self.tol_one) + assert np.all(np.abs(storage_q - 0.0) <= self.tol_one) + assert obs.storage_bus[0] == 1 + assert obs.line_or_bus[8] == 1 + assert obs.gen_bus[3] == 1 + self._aux_test_kirchoff() + + # fourth case: isolated storage on a busbar (so it is disconnected, but with 0. production => so thats fine) + array_modif = np.array([0.0, 7.0], dtype=dt_float) + act = self.env.action_space( + { + "set_storage": array_modif, + "set_bus": { + "storages_id": [(0, 2)], + "lines_or_id": [(8, 1)], + "generators_id": [(3, 1)], + }, + } + ) + obs, reward, done, info = self.env.step(act) + assert not info[ + "exception" + ], "error when storage is disconnected with 0 production, throw an error, but should not" + assert not done + storage_p, storage_q, storage_v = self.env.backend.storages_info() + assert np.all( + np.abs(storage_p - [0.0, array_modif[1]]) <= self.tol_one + ), "storage is not disconnected, yet alone on its busbar" + assert obs.storage_bus[0] == -1, "storage should be disconnected" + assert storage_v[0] == 0.0, "storage 0 should be disconnected" + assert obs.line_or_bus[8] == 1 + assert obs.gen_bus[3] == 1 + self._aux_test_kirchoff() + + # check that if i don't touch it it's set to 0 + act = self.env.action_space() + obs, reward, done, info = self.env.step(act) + assert not info["exception"] + storage_p, storage_q, storage_v = self.env.backend.storages_info() + assert np.all( + np.abs(storage_p - 0.0) <= self.tol_one + ), "storage should produce 0" + assert np.all( + np.abs(storage_q - 0.0) <= self.tol_one + ), "storage should produce 0" + assert obs.storage_bus[0] == -1, "storage should be disconnected" + assert storage_v[0] == 0.0, "storage 0 should be disconnected" + assert obs.line_or_bus[8] == 1 + assert obs.gen_bus[3] == 1 + self._aux_test_kirchoff() + + # trying to act on a disconnected storage => illegal) + array_modif = np.array([2.0, 7.0], dtype=dt_float) + act = self.env.action_space({"set_storage": array_modif}) + obs, reward, done, info = self.env.step(act) + assert info["exception"] # action should be illegal + assert not done # this is fine, as it's illegal it's replaced by do nothing + self._aux_test_kirchoff() + + # trying to reconnect a storage alone on a bus => game over, not connected bus + array_modif = np.array([1.0, 7.0], dtype=dt_float) + act = self.env.action_space( + { + "set_storage": array_modif, + "set_bus": { + "storages_id": [(0, 2)], + "lines_or_id": [(8, 1)], + "generators_id": [(3, 1)], + }, + } + ) + obs, reward, done, info = self.env.step(act) + assert info["exception"] # this is a game over + assert done + + +class BaseIssuesTest(MakeBackend): + def test_issue_125(self): + # https://github.com/rte-france/Grid2Op/issues/125 + self.skip_if_needed() + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = grid2op.make("rte_case14_realistic", test=True, backend=backend) + action = env.action_space({"set_bus": {"loads_id": [(1, -1)]}}) + obs, reward, am_i_done, info = env.step(action) + assert info["is_illegal"] is False + assert info["is_ambiguous"] is False + assert len(info["exception"]) + assert am_i_done + + env.reset() + action = env.action_space({"set_bus": {"generators_id": [(1, -1)]}}) + obs, reward, am_i_done, info = env.step(action) + assert info["is_illegal"] is False + assert info["is_ambiguous"] is False + assert len(info["exception"]) + assert am_i_done + + def test_issue_134(self): + self.skip_if_needed() + backend = self.make_backend() + type(backend)._clear_class_attribute() + param = Parameters() + + param.NB_TIMESTEP_COOLDOWN_LINE = 0 + param.NB_TIMESTEP_COOLDOWN_SUB = 0 + # param.NO_OVERFLOW_DISCONNECTION = True + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = grid2op.make( + "rte_case14_realistic", test=True, backend=backend, param=param + ) + obs_init = env.get_obs() + LINE_ID = 2 + + # Disconnect ex + action = env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, 0)], + "lines_ex_id": [(LINE_ID, -1)], + } + } + ) + obs, reward, done, info = env.step(action) + assert not done + assert obs.line_status[LINE_ID] == False + assert obs.topo_vect[obs.line_or_pos_topo_vect[LINE_ID]] == -1 + assert obs.topo_vect[obs.line_ex_pos_topo_vect[LINE_ID]] == -1 + + # Reconnect ex on bus 2 + action = env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, 0)], + "lines_ex_id": [(LINE_ID, 2)], + } + } + ) + obs, reward, done, info = env.step(action) + assert not done + assert obs.line_status[LINE_ID] == True + assert obs.topo_vect[obs.line_or_pos_topo_vect[LINE_ID]] == 1 + assert obs.topo_vect[obs.line_ex_pos_topo_vect[LINE_ID]] == 2 + + # Disconnect or + action = env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, -1)], + "lines_ex_id": [(LINE_ID, 0)], + } + } + ) + obs, reward, done, info = env.step(action) + assert not done + assert obs.line_status[LINE_ID] == False + assert obs.topo_vect[obs.line_or_pos_topo_vect[LINE_ID]] == -1 + assert obs.topo_vect[obs.line_ex_pos_topo_vect[LINE_ID]] == -1 + + # Reconnect or on bus 1 + action = env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, 1)], + "lines_ex_id": [(LINE_ID, 0)], + } + } + ) + obs, reward, done, info = env.step(action) + assert not done + assert obs.line_status[LINE_ID] == True + assert obs.topo_vect[obs.line_or_pos_topo_vect[LINE_ID]] == 1 + assert obs.topo_vect[obs.line_ex_pos_topo_vect[LINE_ID]] == 2 + + def test_issue_134_check_ambiguity(self): + self.skip_if_needed() + backend = self.make_backend() + type(backend)._clear_class_attribute() + param = Parameters() + + param.MAX_LINE_STATUS_CHANGED = 9999 + param.MAX_SUB_CHANGED = 99999 + param.NB_TIMESTEP_COOLDOWN_LINE = 0 + param.NB_TIMESTEP_COOLDOWN_SUB = 0 + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = grid2op.make( + "rte_case14_realistic", test=True, backend=backend, param=param + ) + LINE_ID = 2 + + # Reconnect or on bus 1 disconnect on bus ex -> this should be ambiguous + action = env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, 1)], + "lines_ex_id": [(LINE_ID, -1)], + } + } + ) + obs, reward, done, info = env.step(action) + assert info["is_ambiguous"] == True + + def test_issue_134_withcooldown_forrules(self): + self.skip_if_needed() + backend = self.make_backend() + type(backend)._clear_class_attribute() + param = Parameters() + + param.NB_TIMESTEP_COOLDOWN_LINE = 20 + param.NB_TIMESTEP_COOLDOWN_SUB = 2 + param.NO_OVERFLOW_DISCONNECTION = True + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = grid2op.make( + "rte_case14_realistic", test=True, backend=backend, param=param + ) + LINE_ID = 2 + + # Disconnect ex -> this is an action on the powerline + for (or_, ex_) in [(0, -1), (-1, 0)]: + obs = env.reset() + action = env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, or_)], + "lines_ex_id": [(LINE_ID, ex_)], + } + } + ) + # i disconnect a powerline, i should not act on the substation but on the line LINE_ID + obs, reward, done, info = env.step(action) + assert np.all(obs.time_before_cooldown_sub == 0) + assert ( + obs.time_before_cooldown_line[LINE_ID] + == param.NB_TIMESTEP_COOLDOWN_LINE + ) + assert obs.line_status[LINE_ID] == False + assert obs.topo_vect[obs.line_or_pos_topo_vect[LINE_ID]] == -1 + assert obs.topo_vect[obs.line_ex_pos_topo_vect[LINE_ID]] == -1 + + # i try to reconnect it, should not be possible whether i do it from + # setting a bus at one extremity or playing with the status + obs, *_ = env.step(env.action_space({"set_line_status": [(LINE_ID, 1)]})) + assert obs.line_status[LINE_ID] == False + assert np.all(obs.time_before_cooldown_sub == 0) + assert ( + obs.time_before_cooldown_line[LINE_ID] + == param.NB_TIMESTEP_COOLDOWN_LINE - 1 + ) + + obs, *_ = env.step(env.action_space({"change_line_status": [LINE_ID]})) + assert obs.line_status[LINE_ID] == False + assert np.all(obs.time_before_cooldown_sub == 0) + assert ( + obs.time_before_cooldown_line[LINE_ID] + == param.NB_TIMESTEP_COOLDOWN_LINE - 2 + ) + + obs, *_ = env.step( + env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, 0)], + "lines_ex_id": [(LINE_ID, 1)], + } + } + ) + ) + assert obs.line_status[LINE_ID] == False + assert np.all(obs.time_before_cooldown_sub == 0) + assert ( + obs.time_before_cooldown_line[LINE_ID] + == param.NB_TIMESTEP_COOLDOWN_LINE - 3 + ) + + obs, *_ = env.step( + env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, 1)], + "lines_ex_id": [(LINE_ID, 0)], + } + } + ) + ) + assert obs.line_status[LINE_ID] == False + assert np.all(obs.time_before_cooldown_sub == 0) + assert ( + obs.time_before_cooldown_line[LINE_ID] + == param.NB_TIMESTEP_COOLDOWN_LINE - 4 + ) + + # i wait enough for the cooldown to pass + for _ in range(param.NB_TIMESTEP_COOLDOWN_LINE - 4): + obs, *_ = env.step(env.action_space()) + assert np.all(obs.time_before_cooldown_sub == 0) + + # and now i try to reconnect, this should not affect the substation but the cooldown on the line + obs, *_ = env.step( + env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, -2 * or_)], + "lines_ex_id": [(LINE_ID, -2 * ex_)], + } + } + ) + ) + assert obs.line_status[LINE_ID] == True + assert np.all(obs.time_before_cooldown_sub == 0) + assert ( + obs.time_before_cooldown_line[LINE_ID] + == param.NB_TIMESTEP_COOLDOWN_LINE + ) + + # and now i try to modify the buses at one end of the powerline, + # this should affect the substation and NOT the line (so be possible) + obs, *_ = env.step( + env.action_space( + { + "set_bus": { + "lines_or_id": [(LINE_ID, -1 * or_)], + "lines_ex_id": [(LINE_ID, -1 * ex_)], + } + } + ) + ) + assert obs.line_status[LINE_ID] == True + if or_ != 0: + assert ( + obs.time_before_cooldown_sub[obs.line_or_to_subid[LINE_ID]] + == param.NB_TIMESTEP_COOLDOWN_SUB + ) + else: + assert ( + obs.time_before_cooldown_sub[obs.line_ex_to_subid[LINE_ID]] + == param.NB_TIMESTEP_COOLDOWN_SUB + ) + assert ( + obs.time_before_cooldown_line[LINE_ID] + == param.NB_TIMESTEP_COOLDOWN_LINE - 1 + ) + + def test_issue_copyenv(self): + # https://github.com/BDonnot/lightsim2grid/issues/10 + backend = self.make_backend() + type(backend)._clear_class_attribute() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env1 = grid2op.make("rte_case14_realistic", test=True, backend=backend) + env2 = env1.copy() + obs1 = env1.reset() + obs2 = env2.get_obs() + assert np.any(obs1.prod_p != obs2.prod_p) + + +class BaseStatusActions(MakeBackend): + def _make_my_env(self): + backend = self.make_backend() + type(backend)._clear_class_attribute() + param = Parameters() + param.NB_TIMESTEP_COOLDOWN_LINE = 0 + param.NB_TIMESTEP_COOLDOWN_SUB = 0 + param.NO_OVERFLOW_DISCONNECTION = True + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = grid2op.make( + "rte_case14_realistic", test=True, backend=backend, param=param + ) + return env + + def _init_disco_or_not(self, LINE_ID, env, disco_before_the_action): + if not disco_before_the_action: + # powerline is supposed to be connected before the action takes place + statuses = env.get_obs().line_status + else: + # i disconnect it + action = env.action_space({"set_line_status": [(LINE_ID, -1)]}) + obs, reward, done, info = env.step(action) + statuses = obs.line_status + return statuses + + def _line_connected(self, LINE_ID, obs, busor=1): + assert obs.line_status[LINE_ID] + assert obs.topo_vect[obs.line_or_pos_topo_vect[LINE_ID]] == busor + assert obs.topo_vect[obs.line_ex_pos_topo_vect[LINE_ID]] == 1 + + def _line_disconnected(self, LINE_ID, obs): + assert not obs.line_status[LINE_ID] + assert obs.topo_vect[obs.line_or_pos_topo_vect[LINE_ID]] == -1 + assert obs.topo_vect[obs.line_ex_pos_topo_vect[LINE_ID]] == -1 + + def _only_line_impacted(self, LINE_ID, action, statuses): + lines_impacted, subs_impacted = action.get_topological_impact(statuses) + assert np.sum(subs_impacted) == 0 + assert np.sum(lines_impacted) == 1 and lines_impacted[LINE_ID] + + def _only_sub_impacted(self, LINE_ID, action, statuses): + lines_impacted, subs_impacted = action.get_topological_impact(statuses) + assert ( + np.sum(subs_impacted) == 1 + and subs_impacted[action.line_or_to_subid[LINE_ID]] + ) + assert np.sum(lines_impacted) == 0 + + def test_setmin1_prevConn(self): + """{"set_line_status": [(LINE_ID, -1)]} when connected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=False) + + action = env.action_space({"set_line_status": [(LINE_ID, -1)]}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_disconnected(LINE_ID, obs) + + # right way to count it + self._only_line_impacted(LINE_ID, action, statuses) + + def test_set1_prevConn(self): + """{"set_line_status": [(LINE_ID, +1)]} when connected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=False) + + action = env.action_space({"set_line_status": [(LINE_ID, +1)]}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_connected(LINE_ID, obs) + + # right way to count it + self._only_line_impacted(LINE_ID, action, statuses) + + def test_setmin1_prevDisc(self): + """{"set_line_status": [(LINE_ID, -1)]} when disconnected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=True) + + # and now i test the impact of the action + action = env.action_space({"set_line_status": [(LINE_ID, -1)]}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_disconnected(LINE_ID, obs) + + # right way to count it + self._only_line_impacted(LINE_ID, action, statuses) + + def test_set1_prevDisc(self): + """{"set_line_status": [(LINE_ID, +1)]} when disconnected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=True) + + # and now i test the impact of the action + action = env.action_space({"set_line_status": [(LINE_ID, +1)]}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_connected(LINE_ID, obs) + + # right way to count it + self._only_line_impacted(LINE_ID, action, statuses) + + def test_chgt_prevConn(self): + """{"change_line_status": [LINE_ID]} when connected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=False) + + # and now i test the impact of the action + action = env.action_space({"change_line_status": [LINE_ID]}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_disconnected(LINE_ID, obs) + + # right way to count it + self._only_line_impacted(LINE_ID, action, statuses) + + def test_chgt_prevDisc(self): + """{"change_line_status": [LINE_ID]} when disconnected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=True) + + # and now i test the impact of the action + action = env.action_space({"change_line_status": [LINE_ID]}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_connected(LINE_ID, obs) + + # right way to count it + self._only_line_impacted(LINE_ID, action, statuses) + + def test_setbusmin1_prevConn(self): + """{"set_bus": {"lines_or_id": [(LINE_ID, -1)]}} when connected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=False) + + # and now i test the impact of the action + action = env.action_space({"set_bus": {"lines_or_id": [(LINE_ID, -1)]}}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_disconnected(LINE_ID, obs) + + # right way to count it + self._only_line_impacted(LINE_ID, action, statuses) + + def test_setbusmin1_prevDisc(self): + """{"set_bus": {"lines_or_id": [(LINE_ID, -1)]}} when disco""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=True) + + # and now i test the impact of the action + action = env.action_space({"set_bus": {"lines_or_id": [(LINE_ID, -1)]}}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_disconnected(LINE_ID, obs) + + # right way to count it + self._only_sub_impacted(LINE_ID, action, statuses) + + def test_setbus2_prevConn(self): + """{"set_bus": {"lines_or_id": [(LINE_ID, 2)]}} when connected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=False) + + # and now i test the impact of the action + action = env.action_space({"set_bus": {"lines_or_id": [(LINE_ID, 2)]}}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_connected(LINE_ID, obs, busor=2) + + # right way to count it + self._only_sub_impacted(LINE_ID, action, statuses) + + def test_setbus2_prevDisc(self): + """{"set_bus": {"lines_or_id": [(LINE_ID, 2)]}} when disconnected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=True) + + # and now i test the impact of the action + action = env.action_space({"set_bus": {"lines_or_id": [(LINE_ID, 2)]}}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_connected(LINE_ID, obs, busor=2) + + # right way to count it + self._only_line_impacted(LINE_ID, action, statuses) + + def test_chgtbus_prevConn(self): + """{"change_bus": {"lines_or_id": [LINE_ID]}} when connected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=False) + + # and now i test the impact of the action + action = env.action_space({"change_bus": {"lines_or_id": [LINE_ID]}}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_connected(LINE_ID, obs, busor=2) + + # right way to count it + self._only_sub_impacted(LINE_ID, action, statuses) + + def test_chgtbus_prevDisc(self): + """{"change_bus": {"lines_or_id": [LINE_ID]}} when discconnected""" + self.skip_if_needed() + env = self._make_my_env() + LINE_ID = 1 + + # set the grid to right configuration + statuses = self._init_disco_or_not(LINE_ID, env, disco_before_the_action=True) + + # and now i test the impact of the action + action = env.action_space({"change_bus": {"lines_or_id": [LINE_ID]}}) + obs, reward, done, info = env.step(action) + + # right consequences + self._line_disconnected(LINE_ID, obs) + + # right way to count it + self._only_sub_impacted(LINE_ID, action, statuses) diff --git a/src/tests/test_powsybl_backend.py b/src/tests/test_powsybl_backend.py new file mode 100644 index 0000000..a5e36c1 --- /dev/null +++ b/src/tests/test_powsybl_backend.py @@ -0,0 +1,82 @@ +# Copyright (c) 2023, Artelys (https://www.artelys.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 pypowsybl-grid2opbackend. It is mostly inspired by the development of the several backends from +# Grid2op framework. Most parts of code have been paste/copy. + +import unittest +import os +from pathlib import Path +from src.Backend.powsybl_backend import PowsyblBackend +from grid2op.tests.helper_path_test import HelperTests +from src.tests.base_backend_test_powsybl import BaseTestLoadingCase +from src.tests.base_backend_test_powsybl import BaseTestLoadingBackendFunc +from src.tests.base_backend_test_powsybl import BaseTestTopoAction +import warnings +warnings.simplefilter("error") + +test_dir = Path(__file__).parent.absolute() +implementation_dir = os.fspath(test_dir.parent.absolute()) +data_dir = os.path.abspath(os.path.join(implementation_dir, "data_test")) +PATH_DATA_TEST_PYPOW = data_dir + + +class TestLoadingCase(HelperTests, BaseTestLoadingCase): + def make_backend(self, detailed_infos_for_cascading_failures=False): + return PowsyblBackend( + detailed_infos_for_cascading_failures=detailed_infos_for_cascading_failures + ) + + def get_path(self): + return PATH_DATA_TEST_PYPOW + + def get_casefile(self): + return "grid.json" + + +class TestLoadingBackendFunc(HelperTests, BaseTestLoadingBackendFunc): + def setUp(self): + # TODO find something more elegant + BaseTestLoadingBackendFunc.setUp(self) + + def tearDown(self): + # TODO find something more elegant + BaseTestLoadingBackendFunc.tearDown(self) + + def make_backend(self, detailed_infos_for_cascading_failures=False): + return PowsyblBackend( + detailed_infos_for_cascading_failures=detailed_infos_for_cascading_failures + ) + + def get_path(self): + return PATH_DATA_TEST_PYPOW + + def get_casefile(self): + return "grid.json" + + +class TestTopoAction(HelperTests, BaseTestTopoAction): + def setUp(self): + BaseTestTopoAction.setUp(self) + + def tearDown(self): + # TODO find something more elegant + BaseTestTopoAction.tearDown(self) + + def make_backend(self, detailed_infos_for_cascading_failures=False): + return PowsyblBackend( + detailed_infos_for_cascading_failures=detailed_infos_for_cascading_failures + ) + + def get_path(self): + return PATH_DATA_TEST_PYPOW + + def get_casefile(self): + return "grid.json" + +if __name__ == "__main__": + unittest.main() +