From 1bade2215a19f5e3793065c40ab625717c5db9ae Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 29 Oct 2021 22:01:00 +0200 Subject: [PATCH 1/9] floating offshore wind - minimal representation --- Snakefile | 2 +- config.default.yaml | 17 +++++++++++++++++ data/costs.csv | 3 +++ scripts/build_renewable_profiles.py | 5 +++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index 1196d47b0..7a1109c71 100644 --- a/Snakefile +++ b/Snakefile @@ -181,7 +181,7 @@ rule build_renewable_profiles: corine="data/bundle/corine/g250_clc06_V18_5.tif", natura="resources/natura.tiff", gebco=lambda w: ("data/bundle/GEBCO_2014_2D.nc" - if "max_depth" in config["renewable"][w.technology].keys() + if any(key in ["max_depth", "min_depth"] for key in config["renewable"][w.technology].keys()) else []), country_shapes='resources/country_shapes.geojson', offshore_shapes='resources/offshore_shapes.geojson', diff --git a/config.default.yaml b/config.default.yaml index a0ffbe478..2fa80f0e0 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -139,6 +139,23 @@ renewable: min_shore_distance: 30000 potential: simple # or conservative clip_p_max_pu: 1.e-2 + offwind-float: + cutout: europe-2013-era5 + resource: + method: wind + turbine: NREL_ReferenceTurbine_5MW_offshore + # ScholzPhd Tab 4.3.1: 10MW/km^2 + capacity_per_sqkm: 2 + correction_factor: 0.8855 + # proxy for wake losses + # from 10.1016/j.energy.2018.08.153 + # until done more rigorously in #153 + corine: [44, 255] + natura: true + min_depth: 50 + max_depth: 500 + potential: simple # or conservative + clip_p_max_pu: 1.e-2 solar: cutout: europe-2013-sarah resource: diff --git a/data/costs.csv b/data/costs.csv index 8953eb8a8..a7412753a 100644 --- a/data/costs.csv +++ b/data/costs.csv @@ -24,6 +24,9 @@ offwind-ac-connection-underground,2030,investment,1342,EUR/MW/km,DEA https://ens offwind-dc-station,2030,investment,400,EUR/kWel,Haertel 2017; assuming one onshore and one offshore node + 13% learning reduction offwind-dc-connection-submarine,2030,investment,2000,EUR/MW/km,DTU report based on Fig 34 of https://ec.europa.eu/energy/sites/ener/files/documents/2014_nsog_report.pdf offwind-dc-connection-underground,2030,investment,1000,EUR/MW/km,Haertel 2017; average + 13% learning reduction +offwind-float-station,2030,investment,400,EUR/kWel,Haertel 2017; assuming one onshore and one offshore node + 13% learning reduction +offwind-float-connection-submarine,2030,investment,2000,EUR/MW/km,DTU report based on Fig 34 of https://ec.europa.eu/energy/sites/ener/files/documents/2014_nsog_report.pdf +offwind-float-connection-underground,2030,investment,1000,EUR/MW/km,Haertel 2017; average + 13% learning reduction solar,2030,investment,600,EUR/kWel,DIW DataDoc http://hdl.handle.net/10419/80348 biomass,2030,investment,2209,EUR/kWel,DIW DataDoc http://hdl.handle.net/10419/80348 geothermal,2030,investment,3392,EUR/kWel,DIW DataDoc http://hdl.handle.net/10419/80348 diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 9ce83de37..ab46ee4f5 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -31,6 +31,7 @@ distance: natura: max_depth: + min_depth: max_shore_distance: min_shore_distance: capacity_per_sqkm: @@ -242,6 +243,10 @@ func = functools.partial(np.greater,-config['max_depth']) excluder.add_raster(paths.gebco, codes=func, crs=4236, nodata=-1000) + if "min_depth" in config: + func = functools.partial(np.greater,-config['min_depth']) + excluder.add_raster(paths.gebco, codes=func, crs=4236, nodata=-1000, invert=True) + if 'min_shore_distance' in config: buffer = config['min_shore_distance'] excluder.add_geometry(paths.country_shapes, buffer=buffer) From 728d74caa889e42003a2146243c7ff9b9719cc3a Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Mon, 6 Nov 2023 15:46:46 +0100 Subject: [PATCH 2/9] update floating wind settings --- config/config.default.yaml | 2 ++ config/test/config.electricity.yaml | 5 ++++- config/test/config.myopic.yaml | 5 ++++- config/test/config.overnight.yaml | 5 ++++- config/test/config.perfect.yaml | 5 ++++- doc/configtables/electricity.csv | 4 ++-- doc/configuration.rst | 20 ++++++++++++++++++-- doc/wildcards.rst | 4 ++-- rules/build_sector.smk | 1 + scripts/plot_summary.py | 1 + scripts/solve_network.py | 4 ++-- 11 files changed, 44 insertions(+), 12 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index e4541f801..dc4de3a3a 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -211,6 +211,8 @@ renewable: # until done more rigorously in #153 corine: [44, 255] natura: true + ship_threshold: 400 + excluder_resolution: 200 min_depth: 60 max_depth: 1000 potential: simple # or conservative diff --git a/config/test/config.electricity.yaml b/config/test/config.electricity.yaml index b750bf629..a2c90659a 100644 --- a/config/test/config.electricity.yaml +++ b/config/test/config.electricity.yaml @@ -32,7 +32,7 @@ electricity: Store: [H2] Link: [H2 pipeline] - renewable_carriers: [solar, onwind, offwind-ac, offwind-dc] + renewable_carriers: [solar, onwind, offwind-ac, offwind-dc, offwind-float] atlite: @@ -53,6 +53,9 @@ renewable: offwind-dc: cutout: be-03-2013-era5 max_depth: false + offwind-float: + cutout: be-03-2013-era5 + max_depth: false solar: cutout: be-03-2013-era5 diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index 0bb85ec6c..8763f4d49 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -39,7 +39,7 @@ electricity: Store: [H2] Link: [H2 pipeline] - renewable_carriers: [solar, onwind, offwind-ac, offwind-dc] + renewable_carriers: [solar, onwind, offwind-ac, offwind-dc, offwind-float] atlite: default_cutout: be-03-2013-era5 @@ -59,6 +59,9 @@ renewable: offwind-dc: cutout: be-03-2013-era5 max_depth: false + offwind-float: + cutout: be-03-2013-era5 + max_depth: false solar: cutout: be-03-2013-era5 diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index a2a0f5a46..121b58bb4 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -36,7 +36,7 @@ electricity: Store: [H2] Link: [H2 pipeline] - renewable_carriers: [solar, onwind, offwind-ac, offwind-dc] + renewable_carriers: [solar, onwind, offwind-ac, offwind-dc, offwind-float] atlite: default_cutout: be-03-2013-era5 @@ -56,6 +56,9 @@ renewable: offwind-dc: cutout: be-03-2013-era5 max_depth: false + offwind-float: + cutout: be-03-2013-era5 + max_depth: false solar: cutout: be-03-2013-era5 diff --git a/config/test/config.perfect.yaml b/config/test/config.perfect.yaml index c99f4122c..9f54d2447 100644 --- a/config/test/config.perfect.yaml +++ b/config/test/config.perfect.yaml @@ -39,7 +39,7 @@ electricity: Store: [H2] Link: [H2 pipeline] - renewable_carriers: [solar, onwind, offwind-ac, offwind-dc] + renewable_carriers: [solar, onwind, offwind-ac, offwind-dc, offwind-float] sector: min_part_load_fischer_tropsch: 0 @@ -62,6 +62,9 @@ renewable: offwind-dc: cutout: be-03-2013-era5 max_depth: false + offwind-float: + cutout: be-03-2013-era5 + max_depth: false solar: cutout: be-03-2013-era5 diff --git a/doc/configtables/electricity.csv b/doc/configtables/electricity.csv index 4c04fee66..7d101b1e0 100644 --- a/doc/configtables/electricity.csv +++ b/doc/configtables/electricity.csv @@ -24,13 +24,13 @@ custom_powerplants,--,"use `pandas.query `_. The value is depreciated but still can be used. -- year,--,bool,Renewable capacities are based on existing capacities reported by IRENA (IRENASTAT) for the specified year -- expansion_limit,--,float or false,"Artificially limit maximum IRENA capacities to a factor. For example, an ``expansion_limit: 1.1`` means 110% of capacities . If false are chosen, the estimated renewable potentials determine by the workflow are used." -- technology_mapping,,,Mapping between PyPSA-Eur and powerplantmatching technology names --- -- Offshore,--,"Any subset of {offwind-ac, offwind-dc}","List of PyPSA-Eur carriers that is considered as (IRENA, OPSD) onshore technology." +-- -- Offshore,--,"Any subset of {offwind-ac, offwind-dc, offwind-float}","List of PyPSA-Eur carriers that is considered as (IRENA, OPSD) onshore technology." -- -- Offshore,--,{onwind},"List of PyPSA-Eur carriers that is considered as (IRENA, OPSD) offshore technology." -- -- PV,--,{solar},"List of PyPSA-Eur carriers that is considered as (IRENA, OPSD) PV technology." diff --git a/doc/configuration.rst b/doc/configuration.rst index ceda11416..4171bcc98 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -265,7 +265,7 @@ Define and specify the ``atlite.Cutout`` used for calculating renewable potentia .. literalinclude:: ../config/config.default.yaml :language: yaml :start-at: offwind-dc: - :end-before: solar: + :end-before: offwind-float: .. csv-table:: :header-rows: 1 @@ -273,9 +273,25 @@ Define and specify the ``atlite.Cutout`` used for calculating renewable potentia :file: configtables/offwind-dc.csv .. note:: - both ``offwind-ac`` and ``offwind-dc`` have the same assumption on + Both ``offwind-ac`` and ``offwind-dc`` have the same assumption on ``capacity_per_sqkm`` and ``correction_factor``. +``offwind-float`` +--------------- + +.. literalinclude:: ../config/config.default.yaml + :language: yaml + :start-at: offwind-float: + :end-before: solar: + +.. csv-table:: + :header-rows: 1 + :widths: 22,7,22,33 + :file: configtables/offwind-dc.csv + +.. note:: + ``offwind-ac``, ``offwind-dc`` , ``offwind-float`` have the same assumption on + ``capacity_per_sqkm`` and ``correction_factor``. ``solar`` --------------- diff --git a/doc/wildcards.rst b/doc/wildcards.rst index 75eec1922..d7b874895 100644 --- a/doc/wildcards.rst +++ b/doc/wildcards.rst @@ -35,8 +35,8 @@ The ``{technology}`` wildcard The ``{technology}`` wildcard specifies for which renewable energy technology to produce availability time series and potentials using the rule :mod:`build_renewable_profiles`. -It can take the values ``onwind``, ``offwind-ac``, ``offwind-dc``, and ``solar`` but **not** ``hydro`` -(since hydroelectric plant profiles are created by a different rule). +It can take the values ``onwind``, ``offwind-ac``, ``offwind-dc``,``offwind-float``, and ``solar`` but **not** ``hydro`` +(since hydroelectric plant profiles are created by a different rule)`` .. _simpl: diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 5a9e8646d..16bbba985 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -748,6 +748,7 @@ rule prepare_sector_network: else "data/costs_{planning_horizons}.csv", profile_offwind_ac=RESOURCES + "profile_offwind-ac.nc", profile_offwind_dc=RESOURCES + "profile_offwind-dc.nc", + profile_offwind_float=RESOURCES + "profile_offwind-float.nc", h2_cavern=RESOURCES + "salt_cavern_potentials_s{simpl}_{clusters}.csv", busmap_s=RESOURCES + "busmap_elec_s{simpl}.csv", busmap=RESOURCES + "busmap_elec_s{simpl}_{clusters}.csv", diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index 2651878a2..0aa514193 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -62,6 +62,7 @@ def rename_techs(label): "offwind": "offshore wind", "offwind-ac": "offshore wind (AC)", "offwind-dc": "offshore wind (DC)", + "offwind-float": "offshore wind (Float)", "onwind": "onshore wind", "ror": "hydroelectricity", "hydro": "hydroelectricity", diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 224d47147..4399c2202 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -115,7 +115,7 @@ def check_p_min_p_max(p_nom_max): def _add_land_use_constraint(n): # warning: this will miss existing offwind which is not classed AC-DC and has carrier 'offwind' - for carrier in ["solar", "onwind", "offwind-ac", "offwind-dc"]: + for carrier in ["solar", "onwind", "offwind-ac", "offwind-dc", "offwind-float"]: extendable_i = (n.generators.carrier == carrier) & n.generators.p_nom_extendable n.generators.loc[extendable_i, "p_nom_min"] = 0 @@ -150,7 +150,7 @@ def _add_land_use_constraint_m(n, planning_horizons, config): grouping_years = config["existing_capacities"]["grouping_years"] current_horizon = snakemake.wildcards.planning_horizons - for carrier in ["solar", "onwind", "offwind-ac", "offwind-dc"]: + for carrier in ["solar", "onwind", "offwind-ac", "offwind-dc", "offwind-float"]: existing = n.generators.loc[n.generators.carrier == carrier, "p_nom"] ind = list( {i.split(sep=" ")[0] + " " + i.split(sep=" ")[1] for i in existing.index} From 520c3fbe98f8f67cef039de1232749fed271b52c Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Mon, 6 Nov 2023 16:23:00 +0100 Subject: [PATCH 3/9] update doc --- doc/configuration.rst | 2 +- doc/wildcards.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/configuration.rst b/doc/configuration.rst index 4171bcc98..e94e8bc1f 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -287,7 +287,7 @@ Define and specify the ``atlite.Cutout`` used for calculating renewable potentia .. csv-table:: :header-rows: 1 :widths: 22,7,22,33 - :file: configtables/offwind-dc.csv + :file: configtables/offwind-float.csv .. note:: ``offwind-ac``, ``offwind-dc`` , ``offwind-float`` have the same assumption on diff --git a/doc/wildcards.rst b/doc/wildcards.rst index d7b874895..167a2ded4 100644 --- a/doc/wildcards.rst +++ b/doc/wildcards.rst @@ -35,7 +35,7 @@ The ``{technology}`` wildcard The ``{technology}`` wildcard specifies for which renewable energy technology to produce availability time series and potentials using the rule :mod:`build_renewable_profiles`. -It can take the values ``onwind``, ``offwind-ac``, ``offwind-dc``,``offwind-float``, and ``solar`` but **not** ``hydro`` +It can take the values ``onwind``, ``offwind-ac``, ``offwind-dc``, ``offwind-float``, and ``solar`` but **not** ``hydro`` (since hydroelectric plant profiles are created by a different rule)`` .. _simpl: From 7241efd3a45d0442df41bba9e861db7e4f2e28d1 Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Mon, 6 Nov 2023 16:31:06 +0100 Subject: [PATCH 4/9] add release note --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 9b1381ce5..7c508627d 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,8 @@ Release Notes Upcoming Release ================ +* Add floating wind to PyPSA-Eur + * Updated Global Energy Monitor LNG terminal data to March 2023 version. * For industry distribution, use EPRTR as fallback if ETS data is not available. From 4f28dfd4fdda639151a8b7558f16fd058e6848ee Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 15:38:03 +0000 Subject: [PATCH 5/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 5 ++++- scripts/build_renewable_profiles.py | 8 +++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 6e1a35ccc..b51e9b4eb 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -220,7 +220,10 @@ rule build_renewable_profiles: gebco=ancient( lambda w: ( "data/bundle/GEBCO_2014_2D.nc" - if (config["renewable"][w.technology].get("max_depth") or config["renewable"][w.technology].get("min_depth")) + if ( + config["renewable"][w.technology].get("max_depth") + or config["renewable"][w.technology].get("min_depth") + ) else [] ) ), diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index a54c73efd..fdb2306b1 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -267,10 +267,12 @@ # and exclude areas where: -max_depth > grid cell depth func = functools.partial(np.greater, -params["max_depth"]) excluder.add_raster(snakemake.input.gebco, codes=func, crs=4326, nodata=-1000) - + if params.get("min_depth"): - func = functools.partial(np.greater,-params['min_depth']) - excluder.add_raster(snakemake.input.gebco, codes=func, crs=4326, nodata=-1000, invert=True) + func = functools.partial(np.greater, -params["min_depth"]) + excluder.add_raster( + snakemake.input.gebco, codes=func, crs=4326, nodata=-1000, invert=True + ) if "min_shore_distance" in params: buffer = params["min_shore_distance"] From 816e7b02387db66b208b6bceac3c27744b91d480 Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Mon, 6 Nov 2023 16:47:05 +0100 Subject: [PATCH 6/9] do not consider floating wind min depth for CI testing --- config/test/config.electricity.yaml | 1 + config/test/config.myopic.yaml | 1 + config/test/config.overnight.yaml | 1 + config/test/config.perfect.yaml | 1 + 4 files changed, 4 insertions(+) diff --git a/config/test/config.electricity.yaml b/config/test/config.electricity.yaml index a2c90659a..cfb04f0e2 100644 --- a/config/test/config.electricity.yaml +++ b/config/test/config.electricity.yaml @@ -56,6 +56,7 @@ renewable: offwind-float: cutout: be-03-2013-era5 max_depth: false + min_depth: false solar: cutout: be-03-2013-era5 diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index 8763f4d49..d29e7925c 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -62,6 +62,7 @@ renewable: offwind-float: cutout: be-03-2013-era5 max_depth: false + min_depth: false solar: cutout: be-03-2013-era5 diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index 121b58bb4..f0ca61729 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -59,6 +59,7 @@ renewable: offwind-float: cutout: be-03-2013-era5 max_depth: false + min_depth: false solar: cutout: be-03-2013-era5 diff --git a/config/test/config.perfect.yaml b/config/test/config.perfect.yaml index 9f54d2447..c450f00fd 100644 --- a/config/test/config.perfect.yaml +++ b/config/test/config.perfect.yaml @@ -65,6 +65,7 @@ renewable: offwind-float: cutout: be-03-2013-era5 max_depth: false + min_depth: false solar: cutout: be-03-2013-era5 From a78137852fb9c37a38dc8557d2ddf7495fec412d Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Tue, 7 Nov 2023 16:54:44 +0100 Subject: [PATCH 7/9] default config: change technology data reference --- config/config.default.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index dc4de3a3a..3c402d0d3 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -584,7 +584,7 @@ industry: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#costs costs: year: 2030 - version: v0.6.0 + version: 1e6e79a rooftop_share: 0.14 # based on the potentials, assuming (0.1 kW/m2 and 10 m2/person) social_discountrate: 0.02 fill_values: From 25df71a5126ad80d520c3a87e324927ca26bac5d Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Fri, 10 May 2024 17:37:42 +0200 Subject: [PATCH 8/9] [no ci] add release note --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b73b56f8b..3158489e2 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,6 +9,8 @@ Release Notes Upcoming Release ================ +* Add floating wind technology for water depths below 60m + * Group existing capacities to the earlier grouping_year for consistency with optimized capacities. * bugfix: installed heating capacities were 5% lower than existing heating capacities From a16b74f68acfe6668cc6b5a5781bfea7ae414a66 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 13 May 2024 10:04:05 +0200 Subject: [PATCH 9/9] Update config/config.default.yaml --- config/config.default.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index dad45cba4..9c838493a 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -233,7 +233,6 @@ renewable: excluder_resolution: 200 min_depth: 60 max_depth: 1000 - potential: simple # or conservative clip_p_max_pu: 1.e-2 solar: cutout: europe-2013-sarah