From 99963edaaf7c6b7b6d70fe586a15eb4770d3e166 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 12 May 2023 09:29:38 +0200 Subject: [PATCH 1/8] add option to limit maximum extension per line/link; linemaxext --- config/config.default.yaml | 2 ++ doc/configtables/lines.csv | 1 + doc/configtables/links.csv | 1 + doc/release_notes.rst | 4 ++++ scripts/prepare_network.py | 18 +++++++++++++++--- scripts/prepare_sector_network.py | 1 - 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 10e6a6ed..5733b942 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -264,12 +264,14 @@ lines: 380.: "Al/St 240/40 4-bundle 380.0" s_max_pu: 0.7 s_nom_max: .inf + max_extension: .inf length_factor: 1.25 under_construction: 'zero' # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity links: p_max_pu: 1.0 p_nom_max: .inf + max_extension: .inf include_tyndp: true under_construction: 'zero' # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity diff --git a/doc/configtables/lines.csv b/doc/configtables/lines.csv index ddf02e54..ad5dd690 100644 --- a/doc/configtables/lines.csv +++ b/doc/configtables/lines.csv @@ -2,5 +2,6 @@ types,--,"Values should specify a `line type in PyPSA `_. Keys should specify the corresponding voltage level (e.g. 220., 300. and 380. kV)","Specifies line types to assume for the different voltage levels of the ENTSO-E grid extraction. Should normally handle voltage levels 220, 300, and 380 kV" s_max_pu,--,"Value in [0.,1.]","Correction factor for line capacities (``s_nom``) to approximate :math:`N-1` security and reserve capacity for reactive power flows" s_nom_max,MW,"float","Global upper limit for the maximum capacity of each extendable line." +max_extension,MW,"float","Upper limit for the extended capacity of each extendable line." length_factor,--,float,"Correction factor to account for the fact that buses are *not* connected by lines through air-line distance." under_construction,--,"One of {'zero': set capacity to zero, 'remove': remove completely, 'keep': keep with full capacity}","Specifies how to handle lines which are currently under construction." diff --git a/doc/configtables/links.csv b/doc/configtables/links.csv index c9981dc7..c1ffb427 100644 --- a/doc/configtables/links.csv +++ b/doc/configtables/links.csv @@ -1,5 +1,6 @@ ,Unit,Values,Description p_max_pu,--,"Value in [0.,1.]","Correction factor for link capacities ``p_nom``." p_nom_max,MW,"float","Global upper limit for the maximum capacity of each extendable DC link." +max_extension,MW,"float","Upper limit for the extended capacity of each extendable DC link." include_tyndp,bool,"{'true', 'false'}","Specifies whether to add HVDC link projects from the `TYNDP 2018 `_ which are at least in permitting." under_construction,--,"One of {'zero': set capacity to zero, 'remove': remove completely, 'keep': keep with full capacity}","Specifies how to handle lines which are currently under construction." diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 14f2939d..818227d8 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -25,6 +25,10 @@ Upcoming Release * Remove ``vresutils`` dependency. +* Added configuration option ``lines: max_extension:`` and ``links: + max_extension:``` to control the maximum capacity addition per line or link in + MW. + PyPSA-Eur 0.8.0 (18th March 2023) ================================= diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 14a003ae..01b72605 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -233,7 +233,17 @@ def enforce_autarky(n, only_crossborder=False): n.mremove("Link", links_rm) -def set_line_nom_max(n, s_nom_max_set=np.inf, p_nom_max_set=np.inf): +def set_line_nom_max(n, s_nom_max_set=np.inf, p_nom_max_set=np.inf, s_nom_max_ext=np.inf, p_nom_max_ext=np.inf): + + if np.isfinite(s_nom_max_ext) and s_nom_max_ext > 0: + logger.info(f"Limiting line extensions to {s_nom_max_ext} MW") + n.lines["s_nom_max"] = n.lines["s_nom"] + s_nom_max_ext + + if np.isfinite(p_nom_max_ext) and p_nom_max_ext > 0: + logger.info(f"Limiting line extensions to {p_nom_max_ext} MW") + hvdc = n.links.index[n.links.carrier == "DC"] + n.links.loc[hvdc, "p_nom_max"] = n.links.loc[hvdc, "p_nom"] + p_nom_max_ext + n.lines.s_nom_max.clip(upper=s_nom_max_set, inplace=True) n.links.p_nom_max.clip(upper=p_nom_max_set, inplace=True) @@ -330,8 +340,10 @@ if __name__ == "__main__": set_line_nom_max( n, - s_nom_max_set=snakemake.config["lines"].get("s_nom_max,", np.inf), - p_nom_max_set=snakemake.config["links"].get("p_nom_max,", np.inf), + s_nom_max_set=snakemake.config["lines"]["s_nom_max,"], + p_nom_max_set=snakemake.config["links"]["p_nom_max,"], + s_nom_max_ext=snakemake.config["lines"]["max_extension,"], + p_nom_max_ext=snakemake.config["links"]["max_extension,"], ) if "ATK" in opts: diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 012c9714..3009bfd9 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3052,7 +3052,6 @@ def maybe_adjust_costs_and_potentials(n, opts): logger.info(f"changing {attr} for {carrier} by factor {factor}") -# TODO this should rather be a config no wildcard def limit_individual_line_extension(n, maxext): logger.info(f"Limiting new HVAC and HVDC extensions to {maxext} MW") n.lines["s_nom_max"] = n.lines["s_nom"] + maxext From 3343394c65e4268b0c375fd3024daff9d6f94c60 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 12 May 2023 07:30:10 +0000 Subject: [PATCH 2/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/prepare_network.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 01b72605..e4bc9705 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -233,8 +233,13 @@ def enforce_autarky(n, only_crossborder=False): n.mremove("Link", links_rm) -def set_line_nom_max(n, s_nom_max_set=np.inf, p_nom_max_set=np.inf, s_nom_max_ext=np.inf, p_nom_max_ext=np.inf): - +def set_line_nom_max( + n, + s_nom_max_set=np.inf, + p_nom_max_set=np.inf, + s_nom_max_ext=np.inf, + p_nom_max_ext=np.inf, +): if np.isfinite(s_nom_max_ext) and s_nom_max_ext > 0: logger.info(f"Limiting line extensions to {s_nom_max_ext} MW") n.lines["s_nom_max"] = n.lines["s_nom"] + s_nom_max_ext From e88b57f42250f062768bc12e6b4ae0889f8414e2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 12 May 2023 10:42:06 +0200 Subject: [PATCH 3/8] prepare_network: fix typo --- scripts/prepare_network.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index e4bc9705..e16339ba 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -345,10 +345,10 @@ if __name__ == "__main__": set_line_nom_max( n, - s_nom_max_set=snakemake.config["lines"]["s_nom_max,"], - p_nom_max_set=snakemake.config["links"]["p_nom_max,"], - s_nom_max_ext=snakemake.config["lines"]["max_extension,"], - p_nom_max_ext=snakemake.config["links"]["max_extension,"], + s_nom_max_set=snakemake.config["lines"]["s_nom_max"], + p_nom_max_set=snakemake.config["links"]["p_nom_max"], + s_nom_max_ext=snakemake.config["lines"]["max_extension"], + p_nom_max_ext=snakemake.config["links"]["max_extension"], ) if "ATK" in opts: From d751f4694d713505be004af3da9a8634e1328f76 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 3 Jul 2023 18:58:15 +0200 Subject: [PATCH 4/8] Update scripts/prepare_network.py --- scripts/prepare_network.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 1c286818..7b7f77f9 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -349,8 +349,8 @@ if __name__ == "__main__": n, s_nom_max_set=snakemake.params.lines.get("s_nom_max", np.inf), p_nom_max_set=snakemake.params.links.get("p_nom_max", np.inf), - s_nom_max_set=snakemake.params.lines.get("max_extension", np.inf), - p_nom_max_set=snakemake.params.links.get("max_extension", np.inf), + s_nom_max_ext=snakemake.params.lines.get("max_extension", np.inf), + p_nom_max_ext=snakemake.params.links.get("max_extension", np.inf), ) if "ATK" in opts: From 3ea8b26ae01fb4dc35cde2f66dea8ffd069c344f Mon Sep 17 00:00:00 2001 From: Fabian Hofmann Date: Thu, 6 Jul 2023 15:01:00 +0200 Subject: [PATCH 5/8] fix carrier assignment --- scripts/add_electricity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 2f6251f0..7cea165b 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -161,7 +161,7 @@ def sanitize_carriers(n, config): for c in n.iterate_components(): if "carrier" in c.df: - add_missing_carriers(n, c.df) + add_missing_carriers(n, c.df.carrier) carrier_i = n.carriers.index nice_names = ( From 26156943cf427418408f921e3078c3282c7c060f Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Mon, 10 Jul 2023 16:15:27 +0200 Subject: [PATCH 6/8] remove TODO comment the clipping of the p_min_pu value cannot be removed since it is used for the retrofitting generators which have to follow the heat demand profile. Otherwise the network becomes infeasibe. --- scripts/solve_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 58f4db72..1a7e4641 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -152,7 +152,7 @@ def prepare_network( if "clip_p_max_pu" in solve_opts: for df in ( n.generators_t.p_max_pu, - n.generators_t.p_min_pu, # TODO: check if this can be removed + n.generators_t.p_min_pu, n.storage_units_t.inflow, ): df.where(df > solve_opts["clip_p_max_pu"], other=0.0, inplace=True) From 5026b560700271bfba3de65172727205376e0307 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 23:01:49 +0000 Subject: [PATCH 7/8] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/docformatter: v1.7.3 → v1.7.4](https://github.com/PyCQA/docformatter/compare/v1.7.3...v1.7.4) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7bb35b53..cf811240 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,7 +39,7 @@ repos: # Make docstrings PEP 257 compliant - repo: https://github.com/PyCQA/docformatter - rev: v1.7.3 + rev: v1.7.4 hooks: - id: docformatter args: ["--in-place", "--make-summary-multi-line", "--pre-summary-newline"] From 6492b1a195e3e8868bce18b3ac13f4f0602820b3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 23:02:55 +0000 Subject: [PATCH 8/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/solve_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 1a7e4641..f7ab724c 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -152,7 +152,7 @@ def prepare_network( if "clip_p_max_pu" in solve_opts: for df in ( n.generators_t.p_max_pu, - n.generators_t.p_min_pu, + n.generators_t.p_min_pu, n.storage_units_t.inflow, ): df.where(df > solve_opts["clip_p_max_pu"], other=0.0, inplace=True)