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 0005070a..5468cf56 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 f411bf31..2462314f 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 0ccb320b..efe32725 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 5468cf56..6bcc81f6 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 efe32725..f04a4b97 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 06e2b03e..bb82cfda 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 eb9cb30d..98874302 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 dd3c393d..d614ff5c 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 bb82cfda..ccfc6f8d 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 2f2937c6..3900ea86 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 ccfc6f8d..c9f4e623 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 98874302..859e3954 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 db4925d3..2d082f0c 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 4f6482f9..931a7cb6 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 2d082f0c..52299c80 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 931a7cb6..2efb7d11 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 2462314f..3569a27c 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 52299c80..85da160a 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 0baf02f3..3ef11d94 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 2efb7d11..4f6482f9 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 3569a27c..d489641b 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 3ef11d94..1f0c2e9a 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