From eb510223c9be28c802344f4751f5f54570261da1 Mon Sep 17 00:00:00 2001 From: joda9 Date: Tue, 16 Jul 2024 12:42:00 +0200 Subject: [PATCH 01/13] improve python3.11 compatibility --- .github/workflows/tests-coverage.yml | 5 ++++- edisgo/network/topology.py | 2 +- setup.py | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests-coverage.yml b/.github/workflows/tests-coverage.yml index 0005070a1..5468cf565 100644 --- a/.github/workflows/tests-coverage.yml +++ b/.github/workflows/tests-coverage.yml @@ -23,7 +23,10 @@ jobs: python-version: 3.9 - name-suffix: "basic" os: ubuntu-latest - python-version: "3.10" + python-version: 3.10 + - name-suffix: "basic" + os: ubuntu-latest + python-version: 3.11 - name-suffix: "basic" os: windows-latest python-version: 3.9 diff --git a/edisgo/network/topology.py b/edisgo/network/topology.py index f411bf312..2462314f0 100755 --- a/edisgo/network/topology.py +++ b/edisgo/network/topology.py @@ -2123,7 +2123,7 @@ def _choose_random_substation_id(): """ if comp_type == "generator": - random.seed(a=comp_data["generator_id"]) + random.seed(a=int(comp_data["generator_id"])) elif comp_type == "storage_unit": random.seed(a=len(self.storage_units_df)) else: diff --git a/setup.py b/setup.py index 0ccb320b3..efe327250 100644 --- a/setup.py +++ b/setup.py @@ -56,7 +56,7 @@ def read(fname): "pypsa >= 0.17.0, <= 0.20.1", "pyyaml", "saio", - "scikit-learn <= 1.1.1", + "scikit-learn < 1.3.0", "shapely >= 1.7.0", "sqlalchemy < 1.4.0", "sshtunnel", From 55c54d3a8d5800e2adac1fcecf0d1c69d7f20d4e Mon Sep 17 00:00:00 2001 From: joda9 Date: Tue, 16 Jul 2024 12:16:26 +0200 Subject: [PATCH 02/13] improve python3.11 compatibility --- .github/workflows/tests-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests-coverage.yml b/.github/workflows/tests-coverage.yml index 5468cf565..6bcc81f6d 100644 --- a/.github/workflows/tests-coverage.yml +++ b/.github/workflows/tests-coverage.yml @@ -23,7 +23,7 @@ jobs: python-version: 3.9 - name-suffix: "basic" os: ubuntu-latest - python-version: 3.10 + python-version: "3.10" - name-suffix: "basic" os: ubuntu-latest python-version: 3.11 From 6c1ed8034636e21947dbaa7050e76225f81dff17 Mon Sep 17 00:00:00 2001 From: joda9 Date: Tue, 16 Jul 2024 13:20:58 +0200 Subject: [PATCH 03/13] Update pypsa dependency to version 0.26.2 --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index efe327250..f04a4b97c 100644 --- a/setup.py +++ b/setup.py @@ -50,10 +50,9 @@ def read(fname): "plotly", "pydot", "pygeos", - "pyomo <= 6.4.2", # Problem with PyPSA 20.1 fixed in newest PyPSA release "pypower", "pyproj >= 3.0.0", - "pypsa >= 0.17.0, <= 0.20.1", + "pypsa == 0.26.2", "pyyaml", "saio", "scikit-learn < 1.3.0", From 5b0df1b904bd9a9104e7d64b22422c881de0f7fb Mon Sep 17 00:00:00 2001 From: joda9 Date: Tue, 16 Jul 2024 14:14:44 +0200 Subject: [PATCH 04/13] improve python3.11 compatibility --- eDisGo_env.yml | 5 +++-- eDisGo_env_dev.yml | 5 +++-- rtd_requirements.txt | 7 +++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/eDisGo_env.yml b/eDisGo_env.yml index 06e2b03e6..bb82cfdac 100644 --- a/eDisGo_env.yml +++ b/eDisGo_env.yml @@ -3,7 +3,7 @@ channels: - conda-forge - defaults dependencies: - - python >= 3.9, < 3.11 + - python >= 3.9, <= 3.11 - pip - pandas >= 1.4, < 2.2.0 - conda-forge::fiona @@ -16,6 +16,7 @@ dependencies: - conda-forge::pygeos - conda-forge::contextily - conda-forge::descartes - - conda-forge::pypsa >= 0.17.0, <= 0.20.1 + - conda-forge::pypsa == 0.26.2 + - conda-forge::scikit-learn < 1.3.0 - pip: - eDisGo diff --git a/eDisGo_env_dev.yml b/eDisGo_env_dev.yml index eb9cb30df..988743029 100644 --- a/eDisGo_env_dev.yml +++ b/eDisGo_env_dev.yml @@ -3,7 +3,7 @@ channels: - conda-forge - defaults dependencies: - - python >= 3.9, < 3.11 + - python >= 3.9, <= 3.11 - pip - pandas >= 1.4, < 2.2.0 - conda-forge::fiona @@ -16,6 +16,7 @@ dependencies: - conda-forge::pygeos - conda-forge::contextily - conda-forge::descartes - - conda-forge::pypsa >= 0.17.0, <= 0.20.1 + - conda-forge::pypsa == 0.26.2 + - conda-forge::scikit-learn < 1.3.0 - pip: - -e .[dev] diff --git a/rtd_requirements.txt b/rtd_requirements.txt index dd3c393d5..d614ff5c0 100644 --- a/rtd_requirements.txt +++ b/rtd_requirements.txt @@ -1,5 +1,5 @@ dash < 2.9.0 -demandlib +demandlib < 0.2.0 egoio >= 0.4.7 geopy >= 2.0.0 jupyter_dash @@ -8,13 +8,12 @@ multiprocess networkx >= 2.5.0 pandas >= 1.4.0 plotly -pyomo >= 6.0 pypower pyproj >= 3.0.0 -pypsa >=0.17.0, <=0.20.1 +pypsa == 0.26.2 pyyaml saio -scikit-learn +scikit-learn < 1.3.0 sphinx sphinx_rtd_theme >=0.5.2 sphinx-autodoc-typehints From 6a90cc4add1aacbdde66f78d5a0158b67c50e132 Mon Sep 17 00:00:00 2001 From: joda9 Date: Wed, 17 Jul 2024 09:00:02 +0200 Subject: [PATCH 05/13] removing unused conda installs --- eDisGo_env.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/eDisGo_env.yml b/eDisGo_env.yml index bb82cfdac..ccfc6f8d7 100644 --- a/eDisGo_env.yml +++ b/eDisGo_env.yml @@ -17,6 +17,5 @@ dependencies: - conda-forge::contextily - conda-forge::descartes - conda-forge::pypsa == 0.26.2 - - conda-forge::scikit-learn < 1.3.0 - pip: - eDisGo From d8f1a687d9eb0b0e2f814bdae6593d3f0af1cce0 Mon Sep 17 00:00:00 2001 From: joda9 Date: Wed, 17 Jul 2024 09:00:37 +0200 Subject: [PATCH 06/13] removing doubled line --- rtd_requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/rtd_requirements.txt b/rtd_requirements.txt index 2f2937c68..3900ea862 100644 --- a/rtd_requirements.txt +++ b/rtd_requirements.txt @@ -1,6 +1,5 @@ dash < 2.9.0 demandlib < 0.2.0 -demandlib < 0.2.0 egoio >= 0.4.7 geopy >= 2.0.0 jupyter_dash From f9f5fd8da5d44b0cfe02029eabc543aa5b819ab4 Mon Sep 17 00:00:00 2001 From: joda9 Date: Wed, 17 Jul 2024 09:02:39 +0200 Subject: [PATCH 07/13] removing space --- eDisGo_env.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eDisGo_env.yml b/eDisGo_env.yml index ccfc6f8d7..c9f4e6239 100644 --- a/eDisGo_env.yml +++ b/eDisGo_env.yml @@ -16,6 +16,6 @@ dependencies: - conda-forge::pygeos - conda-forge::contextily - conda-forge::descartes - - conda-forge::pypsa == 0.26.2 + - conda-forge::pypsa == 0.26.2 - pip: - eDisGo From f2c7f845d401000c88102d5935d358e0213d1ac0 Mon Sep 17 00:00:00 2001 From: joda9 Date: Wed, 17 Jul 2024 09:04:47 +0200 Subject: [PATCH 08/13] removing unused conda installs --- eDisGo_env_dev.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/eDisGo_env_dev.yml b/eDisGo_env_dev.yml index 988743029..859e39546 100644 --- a/eDisGo_env_dev.yml +++ b/eDisGo_env_dev.yml @@ -16,7 +16,6 @@ dependencies: - conda-forge::pygeos - conda-forge::contextily - conda-forge::descartes - - conda-forge::pypsa == 0.26.2 - - conda-forge::scikit-learn < 1.3.0 + - conda-forge::pypsa == 0.26.2 - pip: - -e .[dev] From 9f00fa701b76c1d59ba0bd3b0fbef620b4674528 Mon Sep 17 00:00:00 2001 From: joda9 Date: Mon, 22 Jul 2024 14:26:17 +0200 Subject: [PATCH 09/13] Add warning if meshes are in the grid --- edisgo/opf/powermodels_opf.py | 28 ++++++++++++++++++++++++++++ tests/opf/test_powermodels_opf.py | 27 ++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/edisgo/opf/powermodels_opf.py b/edisgo/opf/powermodels_opf.py index db4925d3b..2d082f0cf 100644 --- a/edisgo/opf/powermodels_opf.py +++ b/edisgo/opf/powermodels_opf.py @@ -4,6 +4,7 @@ import subprocess import sys +import networkx as nx import numpy as np from edisgo.flex_opt import exceptions @@ -12,6 +13,32 @@ logger = logging.getLogger(__name__) +def find_meshes(edisgo_obj) -> list: + """ + Find all meshes in the grid. + + Parameters + ---------- + edisgo_obj : :class:`~edisgo.EDisGo` + EDisGo object. + + Returns + ------- + meshes : list + List of all meshes in the grid. + + """ + meshes = nx.cycle_basis(edisgo_obj.to_graph()) + if meshes: + logger.warning( + "Grid contains mesh(es). This might cause problems in " + "the power flow or optimisation." + ) + return meshes + else: + return None + + def pm_optimize( edisgo_obj, s_base=1, @@ -105,6 +132,7 @@ def pm_optimize( Default: True. """ + find_meshes(edisgo_obj) opf_dir = os.path.dirname(os.path.abspath(__file__)) solution_dir = os.path.join(opf_dir, "opf_solutions") pm, hv_flex_dict = edisgo_obj.to_powermodels( diff --git a/tests/opf/test_powermodels_opf.py b/tests/opf/test_powermodels_opf.py index 4f6482f97..931a7cb6b 100644 --- a/tests/opf/test_powermodels_opf.py +++ b/tests/opf/test_powermodels_opf.py @@ -3,7 +3,7 @@ import pytest from edisgo import EDisGo -from edisgo.opf.powermodels_opf import pm_optimize +from edisgo.opf.powermodels_opf import find_meshes, pm_optimize from edisgo.tools.tools import aggregate_district_heating_components @@ -337,3 +337,28 @@ def test_pm_optimize(self): ) ) ) + + def test_find_meshes(self, caplog): + meshes = find_meshes(self.edisgo) + assert not meshes + self.edisgo.topology.add_line( + "Bus_GeneratorFluctuating_2", + "Bus_GeneratorFluctuating_6", + 0.1, + x=0.1, + r=0.1, + ) + meshes = find_meshes(self.edisgo) + assert len(meshes) == 1 + assert "Bus_GeneratorFluctuating_2" in meshes[0] + assert "Bus_GeneratorFluctuating_6" in meshes[0] + self.edisgo.topology.add_line( + "Bus_BranchTee_LVGrid_2_3", "Bus_BranchTee_LVGrid_3_3", 0.1, x=0.1, r=0.1 + ) + meshes = find_meshes(self.edisgo) + assert len(meshes) == 2 + assert "Bus_BranchTee_LVGrid_2_3" in meshes[1] + assert ( + "Grid contains mesh(es). This might cause problems" + " in the power flow or optimisation." in caplog.text + ) From 85bd5f11ff231ce50e4c905cfeff82c92790d9d2 Mon Sep 17 00:00:00 2001 From: joda9 Date: Wed, 24 Jul 2024 15:30:50 +0200 Subject: [PATCH 10/13] adding type hints and optional arguments --- edisgo/opf/powermodels_opf.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/edisgo/opf/powermodels_opf.py b/edisgo/opf/powermodels_opf.py index 2d082f0cf..52299c80c 100644 --- a/edisgo/opf/powermodels_opf.py +++ b/edisgo/opf/powermodels_opf.py @@ -4,6 +4,8 @@ import subprocess import sys +from typing import List, Optional + import networkx as nx import numpy as np @@ -13,20 +15,21 @@ logger = logging.getLogger(__name__) -def find_meshes(edisgo_obj) -> list: +def find_meshes(edisgo_obj) -> Optional[List[List[int]]]: """ Find all meshes in the grid. Parameters ---------- - edisgo_obj : :class:`~edisgo.EDisGo` + edisgo_obj : EDisGo EDisGo object. Returns ------- - meshes : list + Optional[List[List[int]]] List of all meshes in the grid. - + Each mesh is represented as a list of node indices. + If no meshes are found, None is returned. """ meshes = nx.cycle_basis(edisgo_obj.to_graph()) if meshes: @@ -41,16 +44,16 @@ def find_meshes(edisgo_obj) -> list: def pm_optimize( edisgo_obj, - s_base=1, - flexible_cps=None, - flexible_hps=None, - flexible_loads=None, - flexible_storage_units=None, - opf_version=1, - method="soc", - warm_start=False, - silence_moi=False, -): + s_base: int = 1, + flexible_cps: Optional[np.ndarray] = None, + flexible_hps: Optional[np.ndarray] = None, + flexible_loads: Optional[np.ndarray] = None, + flexible_storage_units: Optional[np.ndarray] = None, + opf_version: int = 1, + method: str = "soc", + warm_start: bool = False, + silence_moi: bool = False, +) -> None: """ Run OPF for edisgo object in julia subprocess and write results of OPF to edisgo object. Results of OPF are time series of operation schedules of flexibilities. From 28fb71cc023ab78e4c53a9ad00ca30163fb02c5c Mon Sep 17 00:00:00 2001 From: joda9 Date: Wed, 24 Jul 2024 15:31:47 +0200 Subject: [PATCH 11/13] Refactor test_find_meshes to use pytest.LogCaptureFixture --- tests/opf/test_powermodels_opf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/opf/test_powermodels_opf.py b/tests/opf/test_powermodels_opf.py index 931a7cb6b..2efb7d11c 100644 --- a/tests/opf/test_powermodels_opf.py +++ b/tests/opf/test_powermodels_opf.py @@ -338,7 +338,7 @@ def test_pm_optimize(self): ) ) - def test_find_meshes(self, caplog): + def test_find_meshes(self, caplog: pytest.LogCaptureFixture): meshes = find_meshes(self.edisgo) assert not meshes self.edisgo.topology.add_line( From bfe8d13e708a666085b4f967898f2ad19e7f3696 Mon Sep 17 00:00:00 2001 From: joda9 Date: Thu, 15 Aug 2024 19:27:28 +0200 Subject: [PATCH 12/13] move find_meshes to topology.py --- edisgo/network/topology.py | 29 +++++++++++++++++++++++++++ edisgo/opf/powermodels_opf.py | 33 +++---------------------------- tests/network/test_topology.py | 25 +++++++++++++++++++++++ tests/opf/test_powermodels_opf.py | 27 +------------------------ 4 files changed, 58 insertions(+), 56 deletions(-) diff --git a/edisgo/network/topology.py b/edisgo/network/topology.py index 2462314f0..3569a27c5 100755 --- a/edisgo/network/topology.py +++ b/edisgo/network/topology.py @@ -3092,6 +3092,9 @@ def check_integrity(self): f"optimisation." ) + # check for meshed grid + self.find_meshes() + def assign_feeders(self, mode: str = "grid_feeder"): """ Assigns MV or LV feeder to each bus and line, depending on the `mode`. @@ -3160,3 +3163,29 @@ def aggregate_lv_grid_at_station(self, lv_grid_id: int | str) -> None: def __repr__(self): return f"Network topology {self.id}" + + def find_meshes(edisgo_obj) -> list[list[int]] | None: + """ + Find all meshes in the grid. + + Parameters + ---------- + edisgo_obj : EDisGo + EDisGo object. + + Returns + ------- + Optional[List[List[int]]] + List of all meshes in the grid. + Each mesh is represented as a list of node indices. + If no meshes are found, None is returned. + """ + meshes = nx.cycle_basis(edisgo_obj.to_graph()) + if meshes: + logger.warning( + "Grid contains mesh(es). This might cause problems in " + "the power flow or optimisation." + ) + return meshes + else: + return None diff --git a/edisgo/opf/powermodels_opf.py b/edisgo/opf/powermodels_opf.py index 52299c80c..85da160a8 100644 --- a/edisgo/opf/powermodels_opf.py +++ b/edisgo/opf/powermodels_opf.py @@ -4,44 +4,17 @@ import subprocess import sys -from typing import List, Optional +from typing import Optional -import networkx as nx import numpy as np from edisgo.flex_opt import exceptions from edisgo.io.powermodels_io import from_powermodels +from edisgo.network.topology import Topology logger = logging.getLogger(__name__) -def find_meshes(edisgo_obj) -> Optional[List[List[int]]]: - """ - Find all meshes in the grid. - - Parameters - ---------- - edisgo_obj : EDisGo - EDisGo object. - - Returns - ------- - Optional[List[List[int]]] - List of all meshes in the grid. - Each mesh is represented as a list of node indices. - If no meshes are found, None is returned. - """ - meshes = nx.cycle_basis(edisgo_obj.to_graph()) - if meshes: - logger.warning( - "Grid contains mesh(es). This might cause problems in " - "the power flow or optimisation." - ) - return meshes - else: - return None - - def pm_optimize( edisgo_obj, s_base: int = 1, @@ -135,7 +108,7 @@ def pm_optimize( Default: True. """ - find_meshes(edisgo_obj) + Topology.find_meshes(edisgo_obj) opf_dir = os.path.dirname(os.path.abspath(__file__)) solution_dir = os.path.join(opf_dir, "opf_solutions") pm, hv_flex_dict = edisgo_obj.to_powermodels( diff --git a/tests/network/test_topology.py b/tests/network/test_topology.py index 0baf02f34..3ef11d949 100644 --- a/tests/network/test_topology.py +++ b/tests/network/test_topology.py @@ -1909,3 +1909,28 @@ def test_check_integrity(self, caplog): assert "There are lines with very short line lengths" in caplog.text assert "Very small values for impedance of lines" and line in caplog.text caplog.clear() + + def test_find_meshes(self, caplog: pytest.LogCaptureFixture): + meshes = Topology.find_meshes(self.edisgo) + assert not meshes + self.edisgo.topology.add_line( + "Bus_GeneratorFluctuating_2", + "Bus_GeneratorFluctuating_6", + 0.1, + x=0.1, + r=0.1, + ) + meshes = Topology.find_meshes(self.edisgo) + assert len(meshes) == 1 + assert "Bus_GeneratorFluctuating_2" in meshes[0] + assert "Bus_GeneratorFluctuating_6" in meshes[0] + self.edisgo.topology.add_line( + "Bus_BranchTee_LVGrid_2_3", "Bus_BranchTee_LVGrid_3_3", 0.1, x=0.1, r=0.1 + ) + meshes = Topology.find_meshes(self.edisgo) + assert len(meshes) == 2 + assert "Bus_BranchTee_LVGrid_2_3" in meshes[1] + assert ( + "Grid contains mesh(es). This might cause problems" + " in the power flow or optimisation." in caplog.text + ) diff --git a/tests/opf/test_powermodels_opf.py b/tests/opf/test_powermodels_opf.py index 2efb7d11c..4f6482f97 100644 --- a/tests/opf/test_powermodels_opf.py +++ b/tests/opf/test_powermodels_opf.py @@ -3,7 +3,7 @@ import pytest from edisgo import EDisGo -from edisgo.opf.powermodels_opf import find_meshes, pm_optimize +from edisgo.opf.powermodels_opf import pm_optimize from edisgo.tools.tools import aggregate_district_heating_components @@ -337,28 +337,3 @@ def test_pm_optimize(self): ) ) ) - - def test_find_meshes(self, caplog: pytest.LogCaptureFixture): - meshes = find_meshes(self.edisgo) - assert not meshes - self.edisgo.topology.add_line( - "Bus_GeneratorFluctuating_2", - "Bus_GeneratorFluctuating_6", - 0.1, - x=0.1, - r=0.1, - ) - meshes = find_meshes(self.edisgo) - assert len(meshes) == 1 - assert "Bus_GeneratorFluctuating_2" in meshes[0] - assert "Bus_GeneratorFluctuating_6" in meshes[0] - self.edisgo.topology.add_line( - "Bus_BranchTee_LVGrid_2_3", "Bus_BranchTee_LVGrid_3_3", 0.1, x=0.1, r=0.1 - ) - meshes = find_meshes(self.edisgo) - assert len(meshes) == 2 - assert "Bus_BranchTee_LVGrid_2_3" in meshes[1] - assert ( - "Grid contains mesh(es). This might cause problems" - " in the power flow or optimisation." in caplog.text - ) From fc52d08247040db75ceaa273c850cc699dccd642 Mon Sep 17 00:00:00 2001 From: birgits Date: Wed, 21 Aug 2024 14:53:00 +0200 Subject: [PATCH 13/13] Adapt warning message --- edisgo/network/topology.py | 6 ++++-- tests/network/test_topology.py | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/edisgo/network/topology.py b/edisgo/network/topology.py index 3569a27c5..d489641b0 100755 --- a/edisgo/network/topology.py +++ b/edisgo/network/topology.py @@ -3183,8 +3183,10 @@ def find_meshes(edisgo_obj) -> list[list[int]] | None: meshes = nx.cycle_basis(edisgo_obj.to_graph()) if meshes: logger.warning( - "Grid contains mesh(es). This might cause problems in " - "the power flow or optimisation." + "Grid contains mesh(es). Be aware, that the grid expansion methodology " + "is currently not able to handle meshes. Further, the optimisation of " + "flexibility dispatch is not exact in case of meshed grids, but can " + "still be used." ) return meshes else: diff --git a/tests/network/test_topology.py b/tests/network/test_topology.py index 3ef11d949..1f0c2e9ad 100644 --- a/tests/network/test_topology.py +++ b/tests/network/test_topology.py @@ -1930,7 +1930,4 @@ def test_find_meshes(self, caplog: pytest.LogCaptureFixture): meshes = Topology.find_meshes(self.edisgo) assert len(meshes) == 2 assert "Bus_BranchTee_LVGrid_2_3" in meshes[1] - assert ( - "Grid contains mesh(es). This might cause problems" - " in the power flow or optimisation." in caplog.text - ) + assert "Grid contains mesh(es)." in caplog.text