From 5251e6477234b884882fa108e7fcc94a4e47e6d7 Mon Sep 17 00:00:00 2001 From: bobbyxng Date: Tue, 22 Oct 2024 14:05:32 +0200 Subject: [PATCH 1/5] Implemented simplify_links fix by adding a preceding function removing converters. --- scripts/simplify_network.py | 52 ++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 453bb1ed0..eeef564c4 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -372,13 +372,61 @@ def find_closest_bus(n, x, y, tol=2000): return n.buses.index[dist.argmin()] else: return None + + +def remove_converters( + n: pypsa.Network +) -> pypsa.Network: + """ + Remove all converters from the network and remap all buses that were originally connected to the + converter to the connected AC bus. Preparation step before simplifying links. + + Parameters: + n (pypsa.Network): The network object. + + Returns: + n (pypsa.Network): The network object with all converters removed. + """ + network = n.copy() + + network.links["bus0_carrier"] = network.links.bus0.map(network.buses.carrier) + network.links["bus1_carrier"] = network.links.bus1.map(network.buses.carrier) + + # Only converters + converters = network.links.query("carrier == ''").copy() + + converters["ac_bus"] = converters.apply( + lambda x: x["bus1"] if x["bus1_carrier"] == "AC" else x["bus0"], + axis=1 + ) + + converters["dc_bus"] = converters.apply( + lambda x: x["bus1"] if x["bus1_carrier"] == "DC" else x["bus0"], + axis=1 + ) + + # Dictionary for remapping + dict_dc_to_ac = dict(zip(converters["dc_bus"], converters["ac_bus"])) + + # Remap all buses that were originally connected to the converter to the connected AC bus + network.links["bus0"] = network.links["bus0"].replace(dict_dc_to_ac) + network.links["bus1"] = network.links["bus1"].replace(dict_dc_to_ac) + + # Remove all converters from network.links and associated dc buses from network.buses + network.links = network.links.loc[~network.links.index.isin(converters.index)] + network.buses = network.buses.loc[~network.buses.index.isin(converters["dc_bus"])] + + # Drop helper columns bus0_carrier and bus1_carrier + network.links.drop(["bus0_carrier", "bus1_carrier"], axis=1, inplace=True) + + return network if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("simplify_network") + snakemake = mock_snakemake("simplify_network", configfiles=["config/config.osm-raw.yaml"]) configure_logging(snakemake) set_scenario_config(snakemake) @@ -391,6 +439,8 @@ def find_closest_bus(n, x, y, tol=2000): linetype_380 = snakemake.config["lines"]["types"][380] n, trafo_map = simplify_network_to_380(n, linetype_380) + n = remove_converters(n) + n, simplify_links_map = simplify_links(n, params.p_max_pu) busmaps = [trafo_map, simplify_links_map] From f2bdf0f5930570113e1f6ec1accbacc05529b52d Mon Sep 17 00:00:00 2001 From: bobbyxng Date: Tue, 22 Oct 2024 14:16:20 +0200 Subject: [PATCH 2/5] Added release_notes. --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 7bc693504..3d16e381f 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -78,6 +78,8 @@ Upcoming Release * Bugfix: demand for ammonia was double-counted at current/near-term planning horizons when ``sector['ammonia']`` was set to ``True``. +* Bugfix: Bug when multiple DC links are connected to the same DC bus and the DC bus is connected to an AC bus via converter. In this case, the DC links were wrongly simplified, completely dropping the shared DC bus. Bug fixed by adding preceding converter removal. Other functionalities are not impacted. + PyPSA-Eur 0.13.0 (13th September 2024) ====================================== From 7efe092ab08406c88ed5012e8abb29b07b7a9180 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:17:52 +0000 Subject: [PATCH 3/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/simplify_network.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index eeef564c4..7ecf65c62 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -372,13 +372,11 @@ def find_closest_bus(n, x, y, tol=2000): return n.buses.index[dist.argmin()] else: return None - -def remove_converters( - n: pypsa.Network -) -> pypsa.Network: + +def remove_converters(n: pypsa.Network) -> pypsa.Network: """ - Remove all converters from the network and remap all buses that were originally connected to the + Remove all converters from the network and remap all buses that were originally connected to the converter to the connected AC bus. Preparation step before simplifying links. Parameters: @@ -396,15 +394,13 @@ def remove_converters( converters = network.links.query("carrier == ''").copy() converters["ac_bus"] = converters.apply( - lambda x: x["bus1"] if x["bus1_carrier"] == "AC" else x["bus0"], - axis=1 + lambda x: x["bus1"] if x["bus1_carrier"] == "AC" else x["bus0"], axis=1 ) converters["dc_bus"] = converters.apply( - lambda x: x["bus1"] if x["bus1_carrier"] == "DC" else x["bus0"], - axis=1 + lambda x: x["bus1"] if x["bus1_carrier"] == "DC" else x["bus0"], axis=1 ) - + # Dictionary for remapping dict_dc_to_ac = dict(zip(converters["dc_bus"], converters["ac_bus"])) @@ -426,7 +422,9 @@ def remove_converters( if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("simplify_network", configfiles=["config/config.osm-raw.yaml"]) + snakemake = mock_snakemake( + "simplify_network", configfiles=["config/config.osm-raw.yaml"] + ) configure_logging(snakemake) set_scenario_config(snakemake) From cba81c8ac80807ca91599a4d5c94c3c0892fc0f2 Mon Sep 17 00:00:00 2001 From: bobbyxng Date: Tue, 22 Oct 2024 14:19:27 +0200 Subject: [PATCH 4/5] Dropped manual configfile. --- scripts/simplify_network.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 7ecf65c62..769c42f6a 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -422,9 +422,7 @@ def remove_converters(n: pypsa.Network) -> pypsa.Network: if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake( - "simplify_network", configfiles=["config/config.osm-raw.yaml"] - ) + snakemake = mock_snakemake("simplify_network") configure_logging(snakemake) set_scenario_config(snakemake) From cb29a7ee3b6f6fd7ff75431822c68568450e554e Mon Sep 17 00:00:00 2001 From: bobbyxng Date: Tue, 22 Oct 2024 15:44:06 +0200 Subject: [PATCH 5/5] Cleaned up code. --- scripts/simplify_network.py | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 769c42f6a..1aa455428 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -385,13 +385,10 @@ def remove_converters(n: pypsa.Network) -> pypsa.Network: Returns: n (pypsa.Network): The network object with all converters removed. """ - network = n.copy() - - network.links["bus0_carrier"] = network.links.bus0.map(network.buses.carrier) - network.links["bus1_carrier"] = network.links.bus1.map(network.buses.carrier) - - # Only converters - converters = network.links.query("carrier == ''").copy() + # Extract converters + converters = n.links.query("carrier == ''")[["bus0", "bus1"]] + converters["bus0_carrier"] = converters["bus0"].map(n.buses.carrier) + converters["bus1_carrier"] = converters["bus1"].map(n.buses.carrier) converters["ac_bus"] = converters.apply( lambda x: x["bus1"] if x["bus1_carrier"] == "AC" else x["bus0"], axis=1 @@ -405,17 +402,14 @@ def remove_converters(n: pypsa.Network) -> pypsa.Network: dict_dc_to_ac = dict(zip(converters["dc_bus"], converters["ac_bus"])) # Remap all buses that were originally connected to the converter to the connected AC bus - network.links["bus0"] = network.links["bus0"].replace(dict_dc_to_ac) - network.links["bus1"] = network.links["bus1"].replace(dict_dc_to_ac) + n.links["bus0"] = n.links["bus0"].replace(dict_dc_to_ac) + n.links["bus1"] = n.links["bus1"].replace(dict_dc_to_ac) # Remove all converters from network.links and associated dc buses from network.buses - network.links = network.links.loc[~network.links.index.isin(converters.index)] - network.buses = network.buses.loc[~network.buses.index.isin(converters["dc_bus"])] - - # Drop helper columns bus0_carrier and bus1_carrier - network.links.drop(["bus0_carrier", "bus1_carrier"], axis=1, inplace=True) + n.links = n.links.loc[~n.links.index.isin(converters.index)] + n.buses = n.buses.loc[~n.buses.index.isin(converters["dc_bus"])] - return network + return n if __name__ == "__main__":