From a2315c289e8b264655eb4fab8afaf112d84d681b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 14:31:10 +0100 Subject: [PATCH 01/20] cluster_gas_network: generalise so it can be used elsewhere --- scripts/cluster_gas_network.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/cluster_gas_network.py b/scripts/cluster_gas_network.py index b8da5012..bc4a6e14 100755 --- a/scripts/cluster_gas_network.py +++ b/scripts/cluster_gas_network.py @@ -75,10 +75,10 @@ def build_clustered_gas_network(df, bus_regions, length_factor=1.25): return df -def reindex_pipes(df): +def reindex_pipes(df, prefix="gas pipeline"): def make_index(x): connector = " <-> " if x.bidirectional else " -> " - return "gas pipeline " + x.bus0 + connector + x.bus1 + return prefix + " " + x.bus0 + connector + x.bus1 df.index = df.apply(make_index, axis=1) From a9ac68b50e837a0365e6eb3e66d57f433dfb6804 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 14:31:35 +0100 Subject: [PATCH 02/20] bugfix: correct way to identify if entry is in snakemake.input --- scripts/prepare_sector_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 4d36e7d4..41ff3ac9 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1321,7 +1321,7 @@ def add_storage_and_grids(n, costs): h2_pipes["p_nom"] = 0.0 - if "custom_h2_pipelines" in snakemake.input: + if snakemake.input.get("custom_h2_pipelines"): fn = snakemake.input.custom_h2_pipelines custom_pipes = pd.read_csv(fn, index_col=0) From 2173abdff340bd8a1877bd2465d02962f337f525 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 18:20:52 +0000 Subject: [PATCH 03/20] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/fsfe/reuse-tool: v2.1.0 → v3.0.1](https://github.com/fsfe/reuse-tool/compare/v2.1.0...v3.0.1) --- .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 02d360d3..a38e6800 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -87,6 +87,6 @@ repos: # Check for FSFE REUSE compliance (licensing) - repo: https://github.com/fsfe/reuse-tool - rev: v2.1.0 + rev: v3.0.1 hooks: - id: reuse From 48974edc8d3e9b2236e9e9200db5d4f2867ab280 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 23 Jan 2024 16:27:12 +0100 Subject: [PATCH 04/20] Make data retrieval rules use their own minimal conda env This means that the main conda environment can be changed for development purposes without necessitating the re-running of data retrieval due to software environment change by default. --- envs/retrieve.yaml | 13 +++++++++++++ rules/retrieve.smk | 16 ++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 envs/retrieve.yaml diff --git a/envs/retrieve.yaml b/envs/retrieve.yaml new file mode 100644 index 00000000..b5db795d --- /dev/null +++ b/envs/retrieve.yaml @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT + +name: pypsa-eur-retrieve +channels: +- conda-forge +- bioconda +dependencies: +- python>=3.8 +- snakemake-minimal>=7.7.0,<8.0.0 +- pandas>=2.1 +- tqdm diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 5e1e3e59..da2dc40a 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -37,7 +37,7 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_databundle", mem_mb=1000, retries: 2 conda: - "../envs/environment.yaml" + "../envs/retrieve.yaml" script: "../scripts/retrieve_databundle.py" @@ -55,7 +55,7 @@ if config["enable"].get("retrieve_irena"): mem_mb=1000, retries: 2 conda: - "../envs/environment.yaml" + "../envs/retrieve.yaml" script: "../scripts/retrieve_irena.py" @@ -157,7 +157,7 @@ if config["enable"]["retrieve"] and config["enable"].get( LOGS + "retrieve_sector_databundle.log", retries: 2 conda: - "../envs/environment.yaml" + "../envs/retrieve.yaml" script: "../scripts/retrieve_sector_databundle.py" @@ -180,7 +180,7 @@ if config["enable"]["retrieve"]: LOGS + "retrieve_gas_infrastructure_data.log", retries: 2 conda: - "../envs/environment.yaml" + "../envs/retrieve.yaml" script: "../scripts/retrieve_gas_infrastructure_data.py" @@ -191,7 +191,7 @@ if config["enable"]["retrieve"]: input: HTTP.remote( "data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv".format( - version="2019-06-05" + version="2019-06-05" if config["snapshots"]["end"] < "2019" else "2020-10-06" ), @@ -316,7 +316,7 @@ if config["enable"]["retrieve"]: layer_path = ( f"/vsizip/{params.folder}/WDPA_{bYYYY}_Public_shp_{i}.zip" ) - print(f"Adding layer {i+1} of 3 to combined output file.") + print(f"Adding layer {i + 1} of 3 to combined output file.") shell("ogr2ogr -f gpkg -update -append {output.gpkg} {layer_path}") rule download_wdpa_marine: @@ -340,7 +340,7 @@ if config["enable"]["retrieve"]: for i in range(3): # vsizip is special driver for directly working with zipped shapefiles in ogr2ogr layer_path = f"/vsizip/{params.folder}/WDPA_WDOECM_{bYYYY}_Public_marine_shp_{i}.zip" - print(f"Adding layer {i+1} of 3 to combined output file.") + print(f"Adding layer {i + 1} of 3 to combined output file.") shell("ogr2ogr -f gpkg -update -append {output.gpkg} {layer_path}") @@ -376,6 +376,6 @@ if config["enable"]["retrieve"]: mem_mb=5000, retries: 2 conda: - "../envs/environment.yaml" + "../envs/retrieve.yaml" script: "../scripts/retrieve_monthly_fuel_prices.py" From 58ac6629fee01b6f06ec3ea4b2c86bc5cba53d5d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:35:08 +0000 Subject: [PATCH 05/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/retrieve.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index da2dc40a..05bbefd8 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -191,7 +191,7 @@ if config["enable"]["retrieve"]: input: HTTP.remote( "data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv".format( - version="2019-06-05" + version="2019-06-05" if config["snapshots"]["end"] < "2019" else "2020-10-06" ), From eeb3d0789bcf21fd003dc0a0452712c6ed23c5d0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 09:28:51 +0100 Subject: [PATCH 06/20] correctly read number of solver threads in rule definition --- doc/release_notes.rst | 1 + rules/common.smk | 7 +++++++ rules/solve_electricity.smk | 2 +- rules/solve_myopic.smk | 2 +- rules/solve_overnight.smk | 4 +--- rules/solve_perfect.smk | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index dc1a9dd1..be3b65d0 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -28,6 +28,7 @@ Upcoming Release * Cluster residential and services heat buses by default. Can be disabled with ``cluster_heat_buses: false``. +* Bugfix: Correctly read out number of solver threads from configuration file. PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/rules/common.smk b/rules/common.smk index 2298ff91..1654180f 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -13,6 +13,13 @@ for path in helper_source_path: from _helpers import validate_checksum +def solver_threads(w): + solver_options = config["solving"]["solver_options"] + option_set = config["solving"]["solver"]["options"] + threads = solver_options[option_set].get("threads", 4) + return threads + + def memory(w): factor = 3.0 for o in w.opts.split("-"): diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index 7f6092be..ac433cf9 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -25,7 +25,7 @@ rule solve_network: + "solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", benchmark: BENCHMARKS + "solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" - threads: 4 + threads: solver_threads resources: mem_mb=memory, walltime=config["solving"].get("walltime", "12:00:00"), diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 7ca8857d..aa94c945 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -104,7 +104,7 @@ rule solve_sector_network_myopic: + "elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_solver.log", python=LOGS + "elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", - threads: 4 + threads: solver_threads resources: mem_mb=config["solving"]["mem"], walltime=config["solving"].get("walltime", "12:00:00"), diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index 39778162..aa08b8c3 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -28,9 +28,7 @@ rule solve_sector_network: + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_memory.log", python=RESULTS + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", - threads: config["solving"]["solver_options"][config["solving"]["solver"]["options"]].get( - "threads", 4 -) + threads: solver_threads resources: mem_mb=config["solving"]["mem"], walltime=config["solving"].get("walltime", "12:00:00"), diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index a7856fa9..ad310f9f 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -127,7 +127,7 @@ rule solve_sector_network_perfect: output: RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", - threads: 4 + threads: solver_threads resources: mem_mb=config["solving"]["mem"], shadow: From 9f0555863b4051db14927d0d36431825c689be24 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 23 Jan 2024 18:19:46 +0100 Subject: [PATCH 07/20] powerplantmatching: block version 0.5.9 with breaking bug --- envs/environment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/envs/environment.yaml b/envs/environment.yaml index 535acbdb..6ff4b7f1 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -26,7 +26,7 @@ dependencies: - yaml - pytables - lxml -- powerplantmatching>=0.5.5 +- powerplantmatching>=0.5.5,!=0.5.9 - numpy - pandas>=2.1 - geopandas>=0.11.0 From 2d12f7ddd0c080dd41410b4006f72bf31665ab53 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 23 Jan 2024 18:41:52 +0100 Subject: [PATCH 08/20] add air-sourced heat pumps to rural areas --- doc/release_notes.rst | 2 ++ scripts/prepare_sector_network.py | 42 ++++++++++++++++--------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index dc1a9dd1..38b47a31 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -28,6 +28,8 @@ Upcoming Release * Cluster residential and services heat buses by default. Can be disabled with ``cluster_heat_buses: false``. +* Air-sourced heat pumps can now also be built in rural areas. Previously, only + ground-sourced heat pumps were considered for this category. PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 41ff3ac9..169e2614 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1803,28 +1803,30 @@ def add_heat(n, costs): ## Add heat pumps - heat_pump_type = "air" if "urban" in name else "ground" + heat_pump_types = ["air"] if "urban" in name else ["ground", "air"] - costs_name = f"{name_type} {heat_pump_type}-sourced heat pump" - efficiency = ( - cop[heat_pump_type][nodes[name]] - if options["time_dep_hp_cop"] - else costs.at[costs_name, "efficiency"] - ) + for heat_pump_type in heat_pump_types: - n.madd( - "Link", - nodes[name], - suffix=f" {name} {heat_pump_type} heat pump", - bus0=nodes[name], - bus1=nodes[name] + f" {name} heat", - carrier=f"{name} {heat_pump_type} heat pump", - efficiency=efficiency, - capital_cost=costs.at[costs_name, "efficiency"] - * costs.at[costs_name, "fixed"], - p_nom_extendable=True, - lifetime=costs.at[costs_name, "lifetime"], - ) + costs_name = f"{name_type} {heat_pump_type}-sourced heat pump" + efficiency = ( + cop[heat_pump_type][nodes[name]] + if options["time_dep_hp_cop"] + else costs.at[costs_name, "efficiency"] + ) + + n.madd( + "Link", + nodes[name], + suffix=f" {name} {heat_pump_type} heat pump", + bus0=nodes[name], + bus1=nodes[name] + f" {name} heat", + carrier=f"{name} {heat_pump_type} heat pump", + efficiency=efficiency, + capital_cost=costs.at[costs_name, "efficiency"] + * costs.at[costs_name, "fixed"], + p_nom_extendable=True, + lifetime=costs.at[costs_name, "lifetime"], + ) if options["tes"]: n.add("Carrier", name + " water tanks") From bdc36dc5da5834275450119ea823916adb247b91 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 17:43:02 +0000 Subject: [PATCH 09/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/prepare_sector_network.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 169e2614..00b9d39b 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1806,7 +1806,6 @@ def add_heat(n, costs): heat_pump_types = ["air"] if "urban" in name else ["ground", "air"] for heat_pump_type in heat_pump_types: - costs_name = f"{name_type} {heat_pump_type}-sourced heat pump" efficiency = ( cop[heat_pump_type][nodes[name]] From b1ce26d2708e10ac5bc3bbf8fb6ba003b913cf0e Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 24 Jan 2024 09:37:01 +0100 Subject: [PATCH 10/20] Don't include triple solar potential option by default --- 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 6349f43e..98595d20 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -44,7 +44,7 @@ scenario: opts: - '' sector_opts: - - Co2L0-3H-T-H-B-I-A-solar+p3-dist1 + - Co2L0-3H-T-H-B-I-A-dist1 planning_horizons: # - 2020 # - 2030 From 2bee36be8788bfdd2442312324f7077c4139a099 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 24 Jan 2024 10:17:26 +0100 Subject: [PATCH 11/20] follow-up to #891: remove remaining solar+p3 references --- config/config.perfect.yaml | 6 +- config/config.personal.yaml | 1070 ++++++++++++++++++++++++++ config/test/config.myopic.yaml | 2 +- config/test/config.overnight.yaml | 2 +- config/test/config.perfect.yaml | 2 +- scripts/add_brownfield.py | 2 +- scripts/add_existing_baseyear.py | 2 +- scripts/plot_network.py | 2 +- scripts/prepare_perfect_foresight.py | 2 +- scripts/prepare_sector_network.py | 2 +- scripts/solve_network.py | 2 +- 11 files changed, 1082 insertions(+), 12 deletions(-) create mode 100644 config/config.personal.yaml diff --git a/config/config.perfect.yaml b/config/config.perfect.yaml index 4dde8db9..ff531303 100644 --- a/config/config.perfect.yaml +++ b/config/config.perfect.yaml @@ -19,9 +19,9 @@ scenario: opts: - '' sector_opts: - - 1p5-4380H-T-H-B-I-A-solar+p3-dist1 - - 1p7-4380H-T-H-B-I-A-solar+p3-dist1 - - 2p0-4380H-T-H-B-I-A-solar+p3-dist1 + - 1p5-4380H-T-H-B-I-A-dist1 + - 1p7-4380H-T-H-B-I-A-dist1 + - 2p0-4380H-T-H-B-I-A-dist1 planning_horizons: - 2020 - 2025 diff --git a/config/config.personal.yaml b/config/config.personal.yaml new file mode 100644 index 00000000..b86b56f7 --- /dev/null +++ b/config/config.personal.yaml @@ -0,0 +1,1070 @@ +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: CC0-1.0 + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#top-level-configuration +version: 0.9.0 +tutorial: false + +logging: + level: INFO + format: '%(levelname)s:%(name)s:%(message)s' + +private: + keys: + entsoe_api: + +remote: + ssh: "z1" + path: "SCRATCH/projects/pypsa-eur" + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#run +run: + name: "" + disable_progressbar: false + shared_resources: false + shared_cutouts: true + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#foresight +foresight: overnight + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#scenario +# Wildcard docs in https://pypsa-eur.readthedocs.io/en/latest/wildcards.html +scenario: + simpl: + - '' + ll: + - vopt + clusters: + - 37 + # - 150 + opts: + - '' + sector_opts: + # - Co2L0-3H-T-H-B-I-A + # - Co2L0-2190SEG-T-H-B-I-A + # - Co2L0-25H-T-H-B-I-A + - Co2L0-97H-T-H-B-I-A + planning_horizons: + # - 2020 + - 2030 + # - 2040 + # - 2050 + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#countries +countries: ['AL', 'AT', 'BA', 'BE', 'BG', 'CH', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'ME', 'MK', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'SE', 'SI', 'SK'] + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#snapshots +snapshots: + start: "2013-01-01" + end: "2014-01-01" + inclusive: 'left' + resolution: false + segmentation: false + #representative: false + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#enable +enable: + retrieve: auto + prepare_links_p_nom: false + retrieve_databundle: true + retrieve_sector_databundle: true + retrieve_cost_data: true + build_cutout: false + retrieve_irena: false + retrieve_cutout: true + build_natura_raster: false + retrieve_natura_raster: true + custom_busmap: false + + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#co2-budget +co2_budget: + 2020: 0.701 + 2025: 0.524 + 2030: 0.297 + 2035: 0.150 + 2040: 0.071 + 2045: 0.032 + 2050: 0.000 + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#electricity +electricity: + voltages: [220., 300., 380., 500., 750.] + gaslimit_enable: false + gaslimit: false + co2limit_enable: false + co2limit: 7.75e+7 + co2base: 1.487e+9 + agg_p_nom_limits: data/agg_p_nom_minmax.csv + + operational_reserve: + activate: false + epsilon_load: 0.02 + epsilon_vres: 0.02 + contingency: 4000 + + max_hours: + battery: 6 + H2: 168 + + extendable_carriers: + Generator: [solar, onwind, offwind-ac, offwind-dc, OCGT] + StorageUnit: [] # battery, H2 + Store: [battery, H2] + Link: [] # H2 pipeline + + powerplants_filter: (DateOut >= 2022 or DateOut != DateOut) + custom_powerplants: false + everywhere_powerplants: [nuclear, oil, OCGT, CCGT, coal, lignite, geothermal, biomass] + + conventional_carriers: [nuclear, oil, OCGT, CCGT, coal, lignite, geothermal, biomass] + renewable_carriers: [solar, onwind, offwind-ac, offwind-dc, hydro] + + estimate_renewable_capacities: + enable: true + from_opsd: true + year: 2020 + expansion_limit: false + technology_mapping: + Offshore: [offwind-ac, offwind-dc] + Onshore: [onwind] + PV: [solar] + + autarky: + enable: false + by_country: false + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#atlite +atlite: + default_cutout: europe-2013-era5 + nprocesses: 4 + show_progress: false + cutouts: + # use 'base' to determine geographical bounds and time span from config + # base: + # module: era5 + europe-2013-era5: + module: era5 # in priority order + x: [-12., 42.] + y: [33., 72] + dx: 0.3 + dy: 0.3 + time: ['2013', '2013'] + europe-2013-sarah: + module: [sarah, era5] # in priority order + x: [-12., 42.] + y: [33., 65] + dx: 0.2 + dy: 0.2 + time: ['2013', '2013'] + sarah_interpolate: false + sarah_dir: + features: [influx, temperature] + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#renewable +renewable: + onwind: + cutout: europe-2013-era5 + resource: + method: wind + turbine: Vestas_V112_3MW + add_cutout_windspeed: true + capacity_per_sqkm: 3 + # correction_factor: 0.93 + corine: + grid_codes: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32] + distance: 1000 + distance_grid_codes: [1, 2, 3, 4, 5, 6] + luisa: false + # grid_codes: [1111, 1121, 1122, 1123, 1130, 1210, 1221, 1222, 1230, 1241, 1242] + # distance: 1000 + # distance_grid_codes: [1111, 1121, 1122, 1123, 1130, 1210, 1221, 1222, 1230, 1241, 1242] + natura: true + excluder_resolution: 100 + clip_p_max_pu: 1.e-2 + offwind-ac: + cutout: europe-2013-era5 + resource: + method: wind + turbine: NREL_ReferenceTurbine_2020ATB_5.5MW + add_cutout_windspeed: true + capacity_per_sqkm: 2 + correction_factor: 0.8855 + corine: [44, 255] + luisa: false # [0, 5230] + natura: true + ship_threshold: 400 + max_depth: 50 + max_shore_distance: 30000 + excluder_resolution: 200 + clip_p_max_pu: 1.e-2 + offwind-dc: + cutout: europe-2013-era5 + resource: + method: wind + turbine: NREL_ReferenceTurbine_2020ATB_5.5MW + add_cutout_windspeed: true + capacity_per_sqkm: 2 + correction_factor: 0.8855 + corine: [44, 255] + luisa: false # [0, 5230] + natura: true + ship_threshold: 400 + max_depth: 50 + min_shore_distance: 30000 + excluder_resolution: 200 + clip_p_max_pu: 1.e-2 + solar: + cutout: europe-2013-sarah + resource: + method: pv + panel: CSi + orientation: + slope: 35. + azimuth: 180. + capacity_per_sqkm: 5.1 + # correction_factor: 0.854337 + corine: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 26, 31, 32] + luisa: false # [1111, 1121, 1122, 1123, 1130, 1210, 1221, 1222, 1230, 1241, 1242, 1310, 1320, 1330, 1410, 1421, 1422, 2110, 2120, 2130, 2210, 2220, 2230, 2310, 2410, 2420, 3210, 3320, 3330] + natura: true + excluder_resolution: 100 + clip_p_max_pu: 1.e-2 + hydro: + cutout: europe-2013-era5 + carriers: [ror, PHS, hydro] + PHS_max_hours: 6 + hydro_max_hours: "energy_capacity_totals_by_country" # one of energy_capacity_totals_by_country, estimate_by_large_installations or a float + flatten_dispatch: false + flatten_dispatch_buffer: 0.2 + clip_min_inflow: 1.0 + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#conventional +conventional: + unit_commitment: false + dynamic_fuel_price: false + nuclear: + p_max_pu: "data/nuclear_p_max_pu.csv" # float of file name + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#lines +lines: + types: + 220.: "Al/St 240/40 2-bundle 220.0" + 300.: "Al/St 240/40 3-bundle 300.0" + 380.: "Al/St 240/40 4-bundle 380.0" + 500.: "Al/St 240/40 4-bundle 380.0" + 750.: "Al/St 560/50 4-bundle 750.0" + s_max_pu: 0.7 + s_nom_max: .inf + max_extension: 20000 #MW + length_factor: 1.25 + reconnect_crimea: true + under_construction: 'zero' # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity + dynamic_line_rating: + activate: false + cutout: europe-2013-era5 + correction_factor: 0.95 + max_voltage_difference: false + max_line_rating: false + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#links +links: + p_max_pu: 1.0 + p_nom_max: .inf + max_extension: 30000 #MW + include_tyndp: true + under_construction: 'zero' # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#transformers +transformers: + x: 0.1 + s_nom: 2000. + type: '' + +# docs-load in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#load +load: + power_statistics: true + interpolate_limit: 3 + time_shift_for_large_gaps: 1w + manual_adjustments: true # false + scaling_factor: 1.0 + +# docs +# TODO: PyPSA-Eur merge issue in prepare_sector_network.py +# regulate what components with which carriers are kept from PyPSA-Eur; +# some technologies are removed because they are implemented differently +# (e.g. battery or H2 storage) or have different year-dependent costs +# in PyPSA-Eur-Sec +pypsa_eur: + Bus: + - AC + Link: + - DC + Generator: + - onwind + - offwind-ac + - offwind-dc + - solar + - ror + - nuclear + StorageUnit: + - PHS + - hydro + Store: [] + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#energy +energy: + energy_totals_year: 2011 + base_emissions_year: 1990 + eurostat_report_year: 2016 + emissions: CO2 + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#biomass +biomass: + year: 2030 + scenario: ENS_Med + classes: + solid biomass: + - Agricultural waste + - Fuelwood residues + - Secondary Forestry residues - woodchips + - Sawdust + - Residues from landscape care + - Municipal waste + not included: + - Sugar from sugar beet + - Rape seed + - "Sunflower, soya seed " + - Bioethanol barley, wheat, grain maize, oats, other cereals and rye + - Miscanthus, switchgrass, RCG + - Willow + - Poplar + - FuelwoodRW + - C&P_RW + biogas: + - Manure solid, liquid + - Sludge + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#solar-thermal +solar_thermal: + clearsky_model: simple # should be "simple" or "enhanced"? + orientation: + slope: 45. + azimuth: 180. + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#existing-capacities +existing_capacities: + grouping_years_power: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030] + grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2019] # these should not extend 2020 + threshold_capacity: 10 + conventional_carriers: + - lignite + - coal + - oil + - uranium + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#sector +sector: + district_heating: + potential: 0.6 + progress: + 2020: 0.0 + 2025: 0.15 + 2030: 0.3 + 2035: 0.45 + 2040: 0.6 + 2045: 0.8 + 2050: 1.0 + district_heating_loss: 0.15 + cluster_heat_buses: true + bev_dsm_restriction_value: 0.75 + bev_dsm_restriction_time: 7 + transport_heating_deadband_upper: 20. + transport_heating_deadband_lower: 15. + ICE_lower_degree_factor: 0.375 + ICE_upper_degree_factor: 1.6 + EV_lower_degree_factor: 0.98 + EV_upper_degree_factor: 0.63 + bev_dsm: true + bev_availability: 0.5 + bev_energy: 0.05 + bev_charge_efficiency: 0.9 + bev_plug_to_wheel_efficiency: 0.2 + bev_charge_rate: 0.011 + bev_avail_max: 0.95 + bev_avail_mean: 0.8 + v2g: true + land_transport_fuel_cell_share: + 2020: 0 + 2025: 0 + 2030: 0 + 2035: 0 + 2040: 0 + 2045: 0 + 2050: 0 + land_transport_electric_share: + 2020: 0 + 2025: 0.15 + 2030: 0.3 + 2035: 0.45 + 2040: 0.7 + 2045: 0.85 + 2050: 1 + land_transport_ice_share: + 2020: 1 + 2025: 0.85 + 2030: 0.7 + 2035: 0.55 + 2040: 0.3 + 2045: 0.15 + 2050: 0 + transport_fuel_cell_efficiency: 0.5 + transport_internal_combustion_efficiency: 0.3 + agriculture_machinery_electric_share: 0 + agriculture_machinery_oil_share: 1 + agriculture_machinery_fuel_efficiency: 0.7 + agriculture_machinery_electric_efficiency: 0.3 + MWh_MeOH_per_MWh_H2: 0.8787 + MWh_MeOH_per_tCO2: 4.0321 + MWh_MeOH_per_MWh_e: 3.6907 + shipping_hydrogen_liquefaction: false + shipping_hydrogen_share: + 2020: 0 + 2025: 0 + 2030: 0 + 2035: 0 + 2040: 0 + 2045: 0 + 2050: 0 + shipping_methanol_share: + 2020: 0 + 2025: 0.15 + 2030: 0.3 + 2035: 0.5 + 2040: 0.7 + 2045: 0.85 + 2050: 1 + shipping_oil_share: + 2020: 1 + 2025: 0.85 + 2030: 0.7 + 2035: 0.5 + 2040: 0.3 + 2045: 0.15 + 2050: 0 + shipping_methanol_efficiency: 0.46 + shipping_oil_efficiency: 0.40 + aviation_demand_factor: 1. + HVC_demand_factor: 1. + time_dep_hp_cop: true + heat_pump_sink_T: 55. + reduce_space_heat_exogenously: true + reduce_space_heat_exogenously_factor: + 2020: 0.10 # this results in a space heat demand reduction of 10% + 2025: 0.09 # first heat demand increases compared to 2020 because of larger floor area per capita + 2030: 0.09 + 2035: 0.11 + 2040: 0.16 + 2045: 0.21 + 2050: 0.29 + retrofitting: + retro_endogen: false + cost_factor: 1.0 + interest_rate: 0.04 + annualise_cost: true + tax_weighting: false + construction_index: true + tes: true + tes_tau: + decentral: 3 + central: 180 + boilers: true + resistive_heaters: true + oil_boilers: false + biomass_boiler: true + chp: true + micro_chp: false + solar_thermal: false + solar_cf_correction: 0.788457 # = >>> 1/1.2683 + marginal_cost_storage: 0. #1e-4 + methanation: true + coal_cc: false + dac: true + co2_vent: false + central_heat_vent: false + allam_cycle: false + hydrogen_fuel_cell: true + hydrogen_turbine: false + SMR: true + SMR_cc: true + regional_methanol_demand: false + regional_oil_demand: false + regional_co2_sequestration_potential: + enable: false + attribute: 'conservative estimate Mt' + include_onshore: false + min_size: 3 + max_size: 25 + years_of_storage: 25 + co2_sequestration_potential: 200 + co2_sequestration_cost: 10 + co2_sequestration_lifetime: 50 + co2_spatial: false + co2network: false + co2_network_cost_factor: 1 + cc_fraction: 0.9 + hydrogen_underground_storage: true + hydrogen_underground_storage_locations: + # - onshore # more than 50 km from sea + - nearshore # within 50 km of sea + # - offshore + ammonia: false + min_part_load_fischer_tropsch: 0.7 + min_part_load_methanolisation: 0.3 + min_part_load_methanation: 0.3 + use_fischer_tropsch_waste_heat: true + use_haber_bosch_waste_heat: true + use_methanolisation_waste_heat: true + use_methanation_waste_heat: true + use_fuel_cell_waste_heat: true + use_electrolysis_waste_heat: true + electricity_distribution_grid: true + electricity_distribution_grid_cost_factor: 1.0 + electricity_grid_connection: true + transmission_efficiency: + DC: + efficiency_static: 0.98 + efficiency_per_1000km: 0.977 + H2 pipeline: + efficiency_per_1000km: 1 # 0.979 + compression_per_1000km: 0.019 + gas pipeline: + efficiency_per_1000km: 1 #0.977 + compression_per_1000km: 0.01 + H2_network: true + gas_network: false + H2_retrofit: false + H2_retrofit_capacity_per_CH4: 0.6 + gas_network_connectivity_upgrade: 1 + gas_distribution_grid: true + gas_distribution_grid_cost_factor: 1.0 + biomass_spatial: false + biomass_transport: false + biogas_upgrading_cc: false + conventional_generation: + OCGT: gas + biomass_to_liquid: false + biosng: false + limit_max_growth: + enable: false + # allowing 30% larger than max historic growth + factor: 1.3 + max_growth: # unit GW + onwind: 16 # onshore max grow so far 16 GW in Europe https://www.iea.org/reports/renewables-2020/wind + solar: 28 # solar max grow so far 28 GW in Europe https://www.iea.org/reports/renewables-2020/solar-pv + offwind-ac: 35 # offshore max grow so far 3.5 GW in Europe https://windeurope.org/about-wind/statistics/offshore/european-offshore-wind-industry-key-trends-statistics-2019/ + offwind-dc: 35 + max_relative_growth: + onwind: 3 + solar: 3 + offwind-ac: 3 + offwind-dc: 3 + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#industry +industry: + St_primary_fraction: + 2020: 0.6 + 2025: 0.55 + 2030: 0.5 + 2035: 0.45 + 2040: 0.4 + 2045: 0.35 + 2050: 0.3 + DRI_fraction: + 2020: 0 + 2025: 0 + 2030: 0.05 + 2035: 0.2 + 2040: 0.4 + 2045: 0.7 + 2050: 1 + H2_DRI: 1.7 + elec_DRI: 0.322 + Al_primary_fraction: + 2020: 0.4 + 2025: 0.375 + 2030: 0.35 + 2035: 0.325 + 2040: 0.3 + 2045: 0.25 + 2050: 0.2 + MWh_NH3_per_tNH3: 5.166 + MWh_CH4_per_tNH3_SMR: 10.8 + MWh_elec_per_tNH3_SMR: 0.7 + MWh_H2_per_tNH3_electrolysis: 5.93 + MWh_elec_per_tNH3_electrolysis: 0.2473 + MWh_NH3_per_MWh_H2_cracker: 1.46 # https://github.com/euronion/trace/blob/44a5ff8401762edbef80eff9cfe5a47c8d3c8be4/data/efficiencies.csv + NH3_process_emissions: 24.5 + petrochemical_process_emissions: 25.5 + HVC_primary_fraction: 1. + HVC_mechanical_recycling_fraction: 0. + HVC_chemical_recycling_fraction: 0. + HVC_production_today: 52. + MWh_elec_per_tHVC_mechanical_recycling: 0.547 + MWh_elec_per_tHVC_chemical_recycling: 6.9 + chlorine_production_today: 9.58 + MWh_elec_per_tCl: 3.6 + MWh_H2_per_tCl: -0.9372 + methanol_production_today: 1.5 + MWh_elec_per_tMeOH: 0.167 + MWh_CH4_per_tMeOH: 10.25 + hotmaps_locate_missing: false + reference_year: 2015 + + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#costs +costs: + year: 2030 + version: v0.6.0 + rooftop_share: 0.14 # based on the potentials, assuming (0.1 kW/m2 and 10 m2/person) + social_discountrate: 0.02 + fill_values: + FOM: 0 + VOM: 0 + efficiency: 1 + fuel: 0 + investment: 0 + lifetime: 25 + "CO2 intensity": 0 + "discount rate": 0.07 + # Marginal and capital costs can be overwritten + # capital_cost: + # onwind: 500 + marginal_cost: + solar: 0.01 + onwind: 0.015 + offwind: 0.015 + hydro: 0. + H2: 0. + electrolysis: 0. + fuel cell: 0. + battery: 0. + battery inverter: 0. + emission_prices: + enable: false + co2: 0. + co2_monthly_prices: false + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#clustering +clustering: + focus_weights: false + simplify_network: + to_substations: false + algorithm: kmeans # choose from: [hac, kmeans] + feature: solar+onwind-time + exclude_carriers: [] + remove_stubs: true + remove_stubs_across_borders: true + cluster_network: + algorithm: kmeans + feature: solar+onwind-time + exclude_carriers: [] + consider_efficiency_classes: false + aggregation_strategies: + generators: + committable: any + ramp_limit_up: max + ramp_limit_down: max + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#solving +solving: + #tmpdir: "path/to/tmp" + options: + clip_p_max_pu: 1.e-2 + load_shedding: false + noisy_costs: true + skip_iterations: true + rolling_horizon: false + seed: 123 + custom_extra_functionality: "../data/custom_extra_functionality.py" + # options that go into the optimize function + track_iterations: false + min_iterations: 4 + max_iterations: 6 + transmission_losses: 2 + linearized_unit_commitment: true + horizon: 365 + + constraints: + CCL: false + EQ: false + BAU: false + SAFE: false + + solver: + name: copt + options: copt-default + + solver_options: + highs-default: + # refer to https://ergo-code.github.io/HiGHS/options/definitions.html#solver + threads: 4 + solver: "ipm" + run_crossover: "off" + small_matrix_value: 1e-6 + large_matrix_value: 1e9 + primal_feasibility_tolerance: 1e-5 + dual_feasibility_tolerance: 1e-5 + ipm_optimality_tolerance: 1e-4 + parallel: "on" + random_seed: 123 + gurobi-default: + threads: 8 + method: 2 # barrier + crossover: 0 + BarConvTol: 1.e-6 + Seed: 123 + # AggFill: 0 + # PreDual: 2 + # GURO_PAR_BARDENSETHRESH: 200 + gurobi-numeric-focus: + name: gurobi + NumericFocus: 3 # Favour numeric stability over speed + method: 2 # barrier + crossover: 0 # do not use crossover + BarHomogeneous: 1 # Use homogeneous barrier if standard does not converge + BarConvTol: 1.e-5 + FeasibilityTol: 1.e-4 + OptimalityTol: 1.e-4 + ObjScale: -0.5 + threads: 8 + Seed: 123 + gurobi-fallback: # Use gurobi defaults + name: gurobi + crossover: 0 + method: 2 # barrier + BarHomogeneous: 1 # Use homogeneous barrier if standard does not converge + BarConvTol: 1.e-5 + FeasibilityTol: 1.e-5 + OptimalityTol: 1.e-5 + Seed: 123 + threads: 8 + cplex-default: + threads: 4 + lpmethod: 4 # barrier + solutiontype: 2 # non basic solution, ie no crossover + barrier.convergetol: 1.e-5 + feasopt.tolerance: 1.e-6 + copt-vanilla: + Threads: 8 + copt-default: + Threads: 8 + LpMethod: 2 + Scaling: 1 + Presolve: 3 + Crossover: 0 + cbc-default: {} # Used in CI + glpk-default: {} # Used in CI + + mem: 80000 #memory in MB; 20 GB enough for 50+B+I+H2; 100 GB for 181+B+I+H2 + walltime: "10:00:00" + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#plotting +plotting: + map: + boundaries: [-11, 30, 34, 71] + color_geomap: + ocean: white + land: white + eu_node_location: + x: -5.5 + y: 46. + costs_max: 1000 + costs_threshold: 1 + energy_max: 20000 + energy_min: -20000 + energy_threshold: 50. + + nice_names: + OCGT: "Open-Cycle Gas" + CCGT: "Combined-Cycle Gas" + offwind-ac: "Offshore Wind (AC)" + offwind-dc: "Offshore Wind (DC)" + onwind: "Onshore Wind" + solar: "Solar" + PHS: "Pumped Hydro Storage" + hydro: "Reservoir & Dam" + battery: "Battery Storage" + H2: "Hydrogen Storage" + lines: "Transmission Lines" + ror: "Run of River" + load: "Load Shedding" + ac: "AC" + dc: "DC" + + tech_colors: + # wind + onwind: "#235ebc" + onshore wind: "#235ebc" + offwind: "#6895dd" + offshore wind: "#6895dd" + offwind-ac: "#6895dd" + offshore wind (AC): "#6895dd" + offshore wind ac: "#6895dd" + offwind-dc: "#74c6f2" + offshore wind (DC): "#74c6f2" + offshore wind dc: "#74c6f2" + # water + hydro: '#298c81' + hydro reservoir: '#298c81' + ror: '#3dbfb0' + run of river: '#3dbfb0' + hydroelectricity: '#298c81' + PHS: '#51dbcc' + hydro+PHS: "#08ad97" + wave: '#a7d4cf' + # solar + solar: "#f9d002" + solar PV: "#f9d002" + solar thermal: '#ffbf2b' + residential rural solar thermal: '#f1c069' + services rural solar thermal: '#eabf61' + residential urban decentral solar thermal: '#e5bc5a' + services urban decentral solar thermal: '#dfb953' + urban central solar thermal: '#d7b24c' + solar rooftop: '#ffea80' + # gas + OCGT: '#e0986c' + OCGT marginal: '#e0986c' + OCGT-heat: '#e0986c' + gas boiler: '#db6a25' + gas boilers: '#db6a25' + gas boiler marginal: '#db6a25' + residential rural gas boiler: '#d4722e' + residential urban decentral gas boiler: '#cb7a36' + services rural gas boiler: '#c4813f' + services urban decentral gas boiler: '#ba8947' + urban central gas boiler: '#b0904f' + gas: '#e05b09' + fossil gas: '#e05b09' + natural gas: '#e05b09' + biogas to gas: '#e36311' + biogas to gas CC: '#e51245' + CCGT: '#a85522' + CCGT marginal: '#a85522' + allam: '#B98F76' + gas for industry co2 to atmosphere: '#692e0a' + gas for industry co2 to stored: '#8a3400' + gas for industry: '#853403' + gas for industry CC: '#692e0a' + gas pipeline: '#ebbca0' + gas pipeline new: '#a87c62' + # oil + oil: '#c9c9c9' + imported oil: '#a3a3a3' + oil boiler: '#adadad' + residential rural oil boiler: '#a9a9a9' + services rural oil boiler: '#a5a5a5' + residential urban decentral oil boiler: '#a1a1a1' + urban central oil boiler: '#9d9d9d' + services urban decentral oil boiler: '#999999' + agriculture machinery oil: '#949494' + shipping oil: "#808080" + land transport oil: '#afafaf' + # nuclear + Nuclear: '#ff8c00' + Nuclear marginal: '#ff8c00' + nuclear: '#ff8c00' + uranium: '#ff8c00' + # coal + Coal: '#545454' + coal: '#545454' + Coal marginal: '#545454' + coal for industry: '#343434' + solid: '#545454' + Lignite: '#826837' + lignite: '#826837' + Lignite marginal: '#826837' + # biomass + biogas: '#e3d37d' + biomass: '#baa741' + solid biomass: '#baa741' + solid biomass transport: '#baa741' + solid biomass for industry: '#7a6d26' + solid biomass for industry CC: '#47411c' + solid biomass for industry co2 from atmosphere: '#736412' + solid biomass for industry co2 to stored: '#47411c' + urban central solid biomass CHP: '#9d9042' + urban central solid biomass CHP CC: '#6c5d28' + biomass boiler: '#8A9A5B' + residential rural biomass boiler: '#a1a066' + residential urban decentral biomass boiler: '#b0b87b' + services rural biomass boiler: '#c6cf98' + services urban decentral biomass boiler: '#dde5b5' + biomass to liquid: '#32CD32' + BioSNG: '#123456' + # power transmission + lines: '#6c9459' + transmission lines: '#6c9459' + electricity distribution grid: '#97ad8c' + low voltage: '#97ad8c' + # electricity demand + Electric load: '#110d63' + electric demand: '#110d63' + electricity: '#110d63' + industry electricity: '#2d2a66' + industry new electricity: '#2d2a66' + agriculture electricity: '#494778' + # battery + EVs + battery: '#ace37f' + battery storage: '#ace37f' + battery charger: '#88a75b' + battery discharger: '#5d4e29' + home battery: '#80c944' + home battery storage: '#80c944' + home battery charger: '#5e8032' + home battery discharger: '#3c5221' + BEV charger: '#baf238' + V2G: '#e5ffa8' + land transport EV: '#baf238' + Li ion: '#baf238' + # hot water storage + water tanks: '#e69487' + residential rural water tanks: '#f7b7a3' + services rural water tanks: '#f3afa3' + residential urban decentral water tanks: '#f2b2a3' + services urban decentral water tanks: '#f1b4a4' + urban central water tanks: '#e9977d' + hot water storage: '#e69487' + hot water charging: '#e8998b' + urban central water tanks charger: '#b57a67' + residential rural water tanks charger: '#b4887c' + residential urban decentral water tanks charger: '#b39995' + services rural water tanks charger: '#b3abb0' + services urban decentral water tanks charger: '#b3becc' + hot water discharging: '#e99c8e' + urban central water tanks discharger: '#b9816e' + residential rural water tanks discharger: '#ba9685' + residential urban decentral water tanks discharger: '#baac9e' + services rural water tanks discharger: '#bbc2b8' + services urban decentral water tanks discharger: '#bdd8d3' + # heat demand + Heat load: '#cc1f1f' + heat: '#cc1f1f' + heat vent: '#aa3344' + heat demand: '#cc1f1f' + rural heat: '#ff5c5c' + residential rural heat: '#ff7c7c' + services rural heat: '#ff9c9c' + central heat: '#cc1f1f' + urban central heat: '#d15959' + urban central heat vent: '#a74747' + decentral heat: '#750606' + residential urban decentral heat: '#a33c3c' + services urban decentral heat: '#cc1f1f' + low-temperature heat for industry: '#8f2727' + process heat: '#ff0000' + agriculture heat: '#d9a5a5' + # heat supply + heat pumps: '#2fb537' + heat pump: '#2fb537' + air heat pump: '#36eb41' + residential urban decentral air heat pump: '#48f74f' + services urban decentral air heat pump: '#5af95d' + urban central air heat pump: '#6cfb6b' + ground heat pump: '#2fb537' + residential rural ground heat pump: '#48f74f' + services rural ground heat pump: '#5af95d' + Ambient: '#98eb9d' + CHP: '#8a5751' + urban central gas CHP: '#8d5e56' + CHP CC: '#634643' + urban central gas CHP CC: '#6e4e4c' + CHP heat: '#8a5751' + CHP electric: '#8a5751' + district heating: '#e8beac' + resistive heater: '#d8f9b8' + residential rural resistive heater: '#bef5b5' + residential urban decentral resistive heater: '#b2f1a9' + services rural resistive heater: '#a5ed9d' + services urban decentral resistive heater: '#98e991' + urban central resistive heater: '#8cdf85' + retrofitting: '#8487e8' + building retrofitting: '#8487e8' + # hydrogen + H2 for industry: "#f073da" + H2 for shipping: "#ebaee0" + H2: '#bf13a0' + hydrogen: '#bf13a0' + retrofitted H2 boiler: '#e5a0d9' + SMR: '#870c71' + SMR CC: '#4f1745' + H2 liquefaction: '#d647bd' + hydrogen storage: '#bf13a0' + H2 Store: '#bf13a0' + H2 storage: '#bf13a0' + land transport fuel cell: '#6b3161' + H2 pipeline: '#f081dc' + H2 pipeline retrofitted: '#ba99b5' + H2 Fuel Cell: '#c251ae' + H2 fuel cell: '#c251ae' + H2 turbine: '#991f83' + H2 Electrolysis: '#ff29d9' + H2 electrolysis: '#ff29d9' + # ammonia + NH3: '#46caf0' + ammonia: '#46caf0' + ammonia store: '#00ace0' + ammonia cracker: '#87d0e6' + Haber-Bosch: '#076987' + # syngas + Sabatier: '#9850ad' + methanation: '#c44ce6' + methane: '#c44ce6' + # synfuels + Fischer-Tropsch: '#25c49a' + liquid: '#25c49a' + kerosene for aviation: '#a1ffe6' + naphtha for industry: '#57ebc4' + methanolisation: '#83d6d5' + methanol: '#468c8b' + shipping methanol: '#468c8b' + # co2 + CC: '#f29dae' + CCS: '#f29dae' + CO2 sequestration: '#f29dae' + DAC: '#ff5270' + co2 stored: '#f2385a' + co2 sequestered: '#f2682f' + co2: '#f29dae' + co2 vent: '#ffd4dc' + CO2 pipeline: '#f5627f' + # emissions + process emissions CC: '#000000' + process emissions: '#222222' + process emissions to stored: '#444444' + process emissions to atmosphere: '#888888' + oil emissions: '#aaaaaa' + shipping oil emissions: "#555555" + shipping methanol emissions: '#666666' + land transport oil emissions: '#777777' + agriculture machinery oil emissions: '#333333' + # other + shipping: '#03a2ff' + power-to-heat: '#2fb537' + power-to-gas: '#c44ce6' + power-to-H2: '#ff29d9' + power-to-liquid: '#25c49a' + gas-to-power/heat: '#ee8340' + waste: '#e3d37d' + other: '#000000' + geothermal: '#ba91b1' + AC: "#70af1d" + AC-AC: "#70af1d" + AC line: "#70af1d" + links: "#8a1caf" + HVDC links: "#8a1caf" + DC: "#8a1caf" + DC-DC: "#8a1caf" + DC link: "#8a1caf" + load: "#dd2e23" diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index d566c6cb..2dab7b04 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -18,7 +18,7 @@ scenario: clusters: - 5 sector_opts: - - 24H-T-H-B-I-A-solar+p3-dist1 + - 24H-T-H-B-I-A-dist1 planning_horizons: - 2030 - 2040 diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index a2a0f5a4..6d1900cf 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -17,7 +17,7 @@ scenario: clusters: - 5 sector_opts: - - CO2L0-24H-T-H-B-I-A-solar+p3-dist1 + - CO2L0-24H-T-H-B-I-A-dist1 planning_horizons: - 2030 diff --git a/config/test/config.perfect.yaml b/config/test/config.perfect.yaml index 49886b26..f20a2c9f 100644 --- a/config/test/config.perfect.yaml +++ b/config/test/config.perfect.yaml @@ -18,7 +18,7 @@ scenario: clusters: - 5 sector_opts: - - 8760H-T-H-B-I-A-solar+p3-dist1 + - 8760H-T-H-B-I-A-dist1 planning_horizons: - 2030 - 2040 diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index ac58136a..00a729b0 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -153,7 +153,7 @@ if __name__ == "__main__": clusters="37", opts="", ll="v1.0", - sector_opts="168H-T-H-B-I-solar+p3-dist1", + sector_opts="168H-T-H-B-I-dist1", planning_horizons=2030, ) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index c8486758..f219b912 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -638,7 +638,7 @@ if __name__ == "__main__": clusters="37", ll="v1.0", opts="", - sector_opts="1p7-4380H-T-H-B-I-A-solar+p3-dist1", + sector_opts="1p7-4380H-T-H-B-I-A-dist1", planning_horizons=2020, ) diff --git a/scripts/plot_network.py b/scripts/plot_network.py index 6a3783e7..33312a44 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -1068,7 +1068,7 @@ if __name__ == "__main__": opts="", clusters="37", ll="v1.0", - sector_opts="4380H-T-H-B-I-A-solar+p3-dist1", + sector_opts="4380H-T-H-B-I-A-dist1", ) logging.basicConfig(level=snakemake.config["logging"]["level"]) diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index 1c3a0ebe..f5ae3919 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -503,7 +503,7 @@ if __name__ == "__main__": opts="", clusters="37", ll="v1.5", - sector_opts="1p7-4380H-T-H-B-I-A-solar+p3-dist1", + sector_opts="1p7-4380H-T-H-B-I-A-dist1", ) update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 00b9d39b..d24feb79 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3621,7 +3621,7 @@ if __name__ == "__main__": opts="", clusters="37", ll="v1.0", - sector_opts="CO2L0-24H-T-H-B-I-A-solar+p3-dist1", + sector_opts="CO2L0-24H-T-H-B-I-A-dist1", planning_horizons="2030", ) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 1c37bfd2..5d2701bb 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -943,7 +943,7 @@ if __name__ == "__main__": opts="", clusters="37", ll="v1.0", - sector_opts="CO2L0-1H-T-H-B-I-A-solar+p3-dist1", + sector_opts="CO2L0-1H-T-H-B-I-A-dist1", planning_horizons="2030", ) configure_logging(snakemake) From 3e32dbccb5090e07803fd648ab348d00a7cd0cd0 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 24 Jan 2024 11:23:56 +0100 Subject: [PATCH 12/20] Add support for the linopy `io_api` option --- config/config.default.yaml | 1 + doc/configtables/solving.csv | 1 + doc/release_notes.rst | 2 ++ scripts/solve_network.py | 1 + 4 files changed, 5 insertions(+) diff --git a/config/config.default.yaml b/config/config.default.yaml index 98595d20..255e3869 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -687,6 +687,7 @@ solving: rolling_horizon: false seed: 123 custom_extra_functionality: "../data/custom_extra_functionality.py" + # io_api: "direct" # Increases performance but only supported for the highs and gurobi solvers # options that go into the optimize function track_iterations: false min_iterations: 4 diff --git a/doc/configtables/solving.csv b/doc/configtables/solving.csv index 6eff10ae..406fd1f9 100644 --- a/doc/configtables/solving.csv +++ b/doc/configtables/solving.csv @@ -7,6 +7,7 @@ options,,, -- rolling_horizon,bool,"{'true','false'}","Whether to optimize the network in a rolling horizon manner, where the snapshot range is split into slices of size `horizon` which are solved consecutively." -- seed,--,int,Random seed for increased deterministic behaviour. -- custom_extra_functionality,--,str,Path to a Python file with custom extra functionality code to be injected into the solving rules of the workflow relative to ``rules`` directory. +-- io_api,string,"{'lp','mps','direct'}",Passed to linopy and determines the API used to communicate with the solver. With the ``'lp'`` and ``'mps'`` options linopy passes a file to the solver; with the ``'direct'`` option (only supported for HIGHS and Gurobi) linopy uses an in-memory python API resulting in better performance. -- track_iterations,bool,"{'true','false'}",Flag whether to store the intermediate branch capacities and objective function values are recorded for each iteration in ``network.lines['s_nom_opt_X']`` (where ``X`` labels the iteration) -- min_iterations,--,int,Minimum number of solving iterations in between which resistance and reactence (``x/r``) are updated for branches according to ``s_nom_opt`` of the previous run. -- max_iterations,--,int,Maximum number of solving iterations in between which resistance and reactence (``x/r``) are updated for branches according to ``s_nom_opt`` of the previous run. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 914617d4..b55e8ac7 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -33,6 +33,8 @@ Upcoming Release * Bugfix: Correctly read out number of solver threads from configuration file. +* Add support for the linopy ``io_api`` option; set to ``"direct"`` to increase model reading and writing performance for the highs and gurobi solvers. + PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 5d2701bb..9fc41555 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -890,6 +890,7 @@ def solve_network(n, config, solving, opts="", **kwargs): "linearized_unit_commitment", False ) kwargs["assign_all_duals"] = cf_solving.get("assign_all_duals", False) + kwargs["io_api"] = cf_solving.get("io_api", None) if kwargs["solver_name"] == "gurobi": logging.getLogger("gurobipy").setLevel(logging.CRITICAL) From 9843397b5a4effda6418f85fcf5c03291435804b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:48:52 +0000 Subject: [PATCH 13/20] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/configtables/solving.csv | 2 +- doc/release_notes.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/configtables/solving.csv b/doc/configtables/solving.csv index 406fd1f9..7189399b 100644 --- a/doc/configtables/solving.csv +++ b/doc/configtables/solving.csv @@ -7,7 +7,7 @@ options,,, -- rolling_horizon,bool,"{'true','false'}","Whether to optimize the network in a rolling horizon manner, where the snapshot range is split into slices of size `horizon` which are solved consecutively." -- seed,--,int,Random seed for increased deterministic behaviour. -- custom_extra_functionality,--,str,Path to a Python file with custom extra functionality code to be injected into the solving rules of the workflow relative to ``rules`` directory. --- io_api,string,"{'lp','mps','direct'}",Passed to linopy and determines the API used to communicate with the solver. With the ``'lp'`` and ``'mps'`` options linopy passes a file to the solver; with the ``'direct'`` option (only supported for HIGHS and Gurobi) linopy uses an in-memory python API resulting in better performance. +-- io_api,string,"{'lp','mps','direct'}",Passed to linopy and determines the API used to communicate with the solver. With the ``'lp'`` and ``'mps'`` options linopy passes a file to the solver; with the ``'direct'`` option (only supported for HIGHS and Gurobi) linopy uses an in-memory python API resulting in better performance. -- track_iterations,bool,"{'true','false'}",Flag whether to store the intermediate branch capacities and objective function values are recorded for each iteration in ``network.lines['s_nom_opt_X']`` (where ``X`` labels the iteration) -- min_iterations,--,int,Minimum number of solving iterations in between which resistance and reactence (``x/r``) are updated for branches according to ``s_nom_opt`` of the previous run. -- max_iterations,--,int,Maximum number of solving iterations in between which resistance and reactence (``x/r``) are updated for branches according to ``s_nom_opt`` of the previous run. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b55e8ac7..f8f958cd 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -33,7 +33,7 @@ Upcoming Release * Bugfix: Correctly read out number of solver threads from configuration file. -* Add support for the linopy ``io_api`` option; set to ``"direct"`` to increase model reading and writing performance for the highs and gurobi solvers. +* Add support for the linopy ``io_api`` option; set to ``"direct"`` to increase model reading and writing performance for the highs and gurobi solvers. PyPSA-Eur 0.9.0 (5th January 2024) From 1fab74c46324a308b8104ce888c98da4f11d2013 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 24 Jan 2024 14:39:50 +0100 Subject: [PATCH 14/20] avoid the use use of `workflow.source_path` The above function returns a path to a cached source file, which changes for every run, causing the resulting parameter to change and the solve_network rule to re-run --- rules/common.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/common.smk b/rules/common.smk index 1654180f..5aa7ae53 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -43,7 +43,7 @@ def memory(w): def input_custom_extra_functionality(w): path = config["solving"]["options"].get("custom_extra_functionality", False) if path: - return workflow.source_path(path) + return os.path.join(os.path.dirname(workflow.snakefile), path) return [] From e4a130353f26076f2ec93ce2758689c126043640 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 24 Jan 2024 14:47:20 +0100 Subject: [PATCH 15/20] Make copying default config file compatible with snakemake module --- Snakefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Snakefile b/Snakefile index 7c16ff9f..14c9e821 100644 --- a/Snakefile +++ b/Snakefile @@ -13,9 +13,10 @@ from snakemake.utils import min_version min_version("7.7") - -if not exists("config/config.yaml") and exists("config/config.default.yaml"): - copyfile("config/config.default.yaml", "config/config.yaml") +conf_file = os.path.join(workflow.current_basedir, "config/config.yaml") +conf_default_file = os.path.join(workflow.current_basedir, "config/config.default.yaml") +if not exists(conf_file) and exists(conf_default_file): + copyfile(conf_default_file, conf_file) configfile: "config/config.yaml" From d8d3b2f2ab161056c2166b4a869cc792b98fac58 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 24 Jan 2024 15:48:33 +0100 Subject: [PATCH 16/20] Fix plotting: compatibility with 4th link port --- scripts/plot_summary.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index b2ec0892..92bf726c 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -282,7 +282,10 @@ def plot_balances(): # remove trailing link ports df.index = [ i[:-1] - if ((i not in ["co2", "NH3", "H2"]) and (i[-1:] in ["0", "1", "2", "3"])) + if ( + (i not in ["co2", "NH3", "H2"]) + and (i[-1:] in ["0", "1", "2", "3", "4"]) + ) else i for i in df.index ] From 2ce7d78dbbe9a85b8ee5f0d8ba06ce429eb8212d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 24 Jan 2024 16:23:44 +0100 Subject: [PATCH 17/20] revert accidental addition of personal config file --- config/config.personal.yaml | 1070 ----------------------------------- 1 file changed, 1070 deletions(-) delete mode 100644 config/config.personal.yaml diff --git a/config/config.personal.yaml b/config/config.personal.yaml deleted file mode 100644 index b86b56f7..00000000 --- a/config/config.personal.yaml +++ /dev/null @@ -1,1070 +0,0 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: CC0-1.0 - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#top-level-configuration -version: 0.9.0 -tutorial: false - -logging: - level: INFO - format: '%(levelname)s:%(name)s:%(message)s' - -private: - keys: - entsoe_api: - -remote: - ssh: "z1" - path: "SCRATCH/projects/pypsa-eur" - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#run -run: - name: "" - disable_progressbar: false - shared_resources: false - shared_cutouts: true - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#foresight -foresight: overnight - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#scenario -# Wildcard docs in https://pypsa-eur.readthedocs.io/en/latest/wildcards.html -scenario: - simpl: - - '' - ll: - - vopt - clusters: - - 37 - # - 150 - opts: - - '' - sector_opts: - # - Co2L0-3H-T-H-B-I-A - # - Co2L0-2190SEG-T-H-B-I-A - # - Co2L0-25H-T-H-B-I-A - - Co2L0-97H-T-H-B-I-A - planning_horizons: - # - 2020 - - 2030 - # - 2040 - # - 2050 - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#countries -countries: ['AL', 'AT', 'BA', 'BE', 'BG', 'CH', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'ME', 'MK', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'SE', 'SI', 'SK'] - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#snapshots -snapshots: - start: "2013-01-01" - end: "2014-01-01" - inclusive: 'left' - resolution: false - segmentation: false - #representative: false - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#enable -enable: - retrieve: auto - prepare_links_p_nom: false - retrieve_databundle: true - retrieve_sector_databundle: true - retrieve_cost_data: true - build_cutout: false - retrieve_irena: false - retrieve_cutout: true - build_natura_raster: false - retrieve_natura_raster: true - custom_busmap: false - - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#co2-budget -co2_budget: - 2020: 0.701 - 2025: 0.524 - 2030: 0.297 - 2035: 0.150 - 2040: 0.071 - 2045: 0.032 - 2050: 0.000 - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#electricity -electricity: - voltages: [220., 300., 380., 500., 750.] - gaslimit_enable: false - gaslimit: false - co2limit_enable: false - co2limit: 7.75e+7 - co2base: 1.487e+9 - agg_p_nom_limits: data/agg_p_nom_minmax.csv - - operational_reserve: - activate: false - epsilon_load: 0.02 - epsilon_vres: 0.02 - contingency: 4000 - - max_hours: - battery: 6 - H2: 168 - - extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, OCGT] - StorageUnit: [] # battery, H2 - Store: [battery, H2] - Link: [] # H2 pipeline - - powerplants_filter: (DateOut >= 2022 or DateOut != DateOut) - custom_powerplants: false - everywhere_powerplants: [nuclear, oil, OCGT, CCGT, coal, lignite, geothermal, biomass] - - conventional_carriers: [nuclear, oil, OCGT, CCGT, coal, lignite, geothermal, biomass] - renewable_carriers: [solar, onwind, offwind-ac, offwind-dc, hydro] - - estimate_renewable_capacities: - enable: true - from_opsd: true - year: 2020 - expansion_limit: false - technology_mapping: - Offshore: [offwind-ac, offwind-dc] - Onshore: [onwind] - PV: [solar] - - autarky: - enable: false - by_country: false - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#atlite -atlite: - default_cutout: europe-2013-era5 - nprocesses: 4 - show_progress: false - cutouts: - # use 'base' to determine geographical bounds and time span from config - # base: - # module: era5 - europe-2013-era5: - module: era5 # in priority order - x: [-12., 42.] - y: [33., 72] - dx: 0.3 - dy: 0.3 - time: ['2013', '2013'] - europe-2013-sarah: - module: [sarah, era5] # in priority order - x: [-12., 42.] - y: [33., 65] - dx: 0.2 - dy: 0.2 - time: ['2013', '2013'] - sarah_interpolate: false - sarah_dir: - features: [influx, temperature] - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#renewable -renewable: - onwind: - cutout: europe-2013-era5 - resource: - method: wind - turbine: Vestas_V112_3MW - add_cutout_windspeed: true - capacity_per_sqkm: 3 - # correction_factor: 0.93 - corine: - grid_codes: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32] - distance: 1000 - distance_grid_codes: [1, 2, 3, 4, 5, 6] - luisa: false - # grid_codes: [1111, 1121, 1122, 1123, 1130, 1210, 1221, 1222, 1230, 1241, 1242] - # distance: 1000 - # distance_grid_codes: [1111, 1121, 1122, 1123, 1130, 1210, 1221, 1222, 1230, 1241, 1242] - natura: true - excluder_resolution: 100 - clip_p_max_pu: 1.e-2 - offwind-ac: - cutout: europe-2013-era5 - resource: - method: wind - turbine: NREL_ReferenceTurbine_2020ATB_5.5MW - add_cutout_windspeed: true - capacity_per_sqkm: 2 - correction_factor: 0.8855 - corine: [44, 255] - luisa: false # [0, 5230] - natura: true - ship_threshold: 400 - max_depth: 50 - max_shore_distance: 30000 - excluder_resolution: 200 - clip_p_max_pu: 1.e-2 - offwind-dc: - cutout: europe-2013-era5 - resource: - method: wind - turbine: NREL_ReferenceTurbine_2020ATB_5.5MW - add_cutout_windspeed: true - capacity_per_sqkm: 2 - correction_factor: 0.8855 - corine: [44, 255] - luisa: false # [0, 5230] - natura: true - ship_threshold: 400 - max_depth: 50 - min_shore_distance: 30000 - excluder_resolution: 200 - clip_p_max_pu: 1.e-2 - solar: - cutout: europe-2013-sarah - resource: - method: pv - panel: CSi - orientation: - slope: 35. - azimuth: 180. - capacity_per_sqkm: 5.1 - # correction_factor: 0.854337 - corine: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 26, 31, 32] - luisa: false # [1111, 1121, 1122, 1123, 1130, 1210, 1221, 1222, 1230, 1241, 1242, 1310, 1320, 1330, 1410, 1421, 1422, 2110, 2120, 2130, 2210, 2220, 2230, 2310, 2410, 2420, 3210, 3320, 3330] - natura: true - excluder_resolution: 100 - clip_p_max_pu: 1.e-2 - hydro: - cutout: europe-2013-era5 - carriers: [ror, PHS, hydro] - PHS_max_hours: 6 - hydro_max_hours: "energy_capacity_totals_by_country" # one of energy_capacity_totals_by_country, estimate_by_large_installations or a float - flatten_dispatch: false - flatten_dispatch_buffer: 0.2 - clip_min_inflow: 1.0 - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#conventional -conventional: - unit_commitment: false - dynamic_fuel_price: false - nuclear: - p_max_pu: "data/nuclear_p_max_pu.csv" # float of file name - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#lines -lines: - types: - 220.: "Al/St 240/40 2-bundle 220.0" - 300.: "Al/St 240/40 3-bundle 300.0" - 380.: "Al/St 240/40 4-bundle 380.0" - 500.: "Al/St 240/40 4-bundle 380.0" - 750.: "Al/St 560/50 4-bundle 750.0" - s_max_pu: 0.7 - s_nom_max: .inf - max_extension: 20000 #MW - length_factor: 1.25 - reconnect_crimea: true - under_construction: 'zero' # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity - dynamic_line_rating: - activate: false - cutout: europe-2013-era5 - correction_factor: 0.95 - max_voltage_difference: false - max_line_rating: false - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#links -links: - p_max_pu: 1.0 - p_nom_max: .inf - max_extension: 30000 #MW - include_tyndp: true - under_construction: 'zero' # 'zero': set capacity to zero, 'remove': remove, 'keep': with full capacity - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#transformers -transformers: - x: 0.1 - s_nom: 2000. - type: '' - -# docs-load in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#load -load: - power_statistics: true - interpolate_limit: 3 - time_shift_for_large_gaps: 1w - manual_adjustments: true # false - scaling_factor: 1.0 - -# docs -# TODO: PyPSA-Eur merge issue in prepare_sector_network.py -# regulate what components with which carriers are kept from PyPSA-Eur; -# some technologies are removed because they are implemented differently -# (e.g. battery or H2 storage) or have different year-dependent costs -# in PyPSA-Eur-Sec -pypsa_eur: - Bus: - - AC - Link: - - DC - Generator: - - onwind - - offwind-ac - - offwind-dc - - solar - - ror - - nuclear - StorageUnit: - - PHS - - hydro - Store: [] - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#energy -energy: - energy_totals_year: 2011 - base_emissions_year: 1990 - eurostat_report_year: 2016 - emissions: CO2 - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#biomass -biomass: - year: 2030 - scenario: ENS_Med - classes: - solid biomass: - - Agricultural waste - - Fuelwood residues - - Secondary Forestry residues - woodchips - - Sawdust - - Residues from landscape care - - Municipal waste - not included: - - Sugar from sugar beet - - Rape seed - - "Sunflower, soya seed " - - Bioethanol barley, wheat, grain maize, oats, other cereals and rye - - Miscanthus, switchgrass, RCG - - Willow - - Poplar - - FuelwoodRW - - C&P_RW - biogas: - - Manure solid, liquid - - Sludge - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#solar-thermal -solar_thermal: - clearsky_model: simple # should be "simple" or "enhanced"? - orientation: - slope: 45. - azimuth: 180. - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#existing-capacities -existing_capacities: - grouping_years_power: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030] - grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2019] # these should not extend 2020 - threshold_capacity: 10 - conventional_carriers: - - lignite - - coal - - oil - - uranium - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#sector -sector: - district_heating: - potential: 0.6 - progress: - 2020: 0.0 - 2025: 0.15 - 2030: 0.3 - 2035: 0.45 - 2040: 0.6 - 2045: 0.8 - 2050: 1.0 - district_heating_loss: 0.15 - cluster_heat_buses: true - bev_dsm_restriction_value: 0.75 - bev_dsm_restriction_time: 7 - transport_heating_deadband_upper: 20. - transport_heating_deadband_lower: 15. - ICE_lower_degree_factor: 0.375 - ICE_upper_degree_factor: 1.6 - EV_lower_degree_factor: 0.98 - EV_upper_degree_factor: 0.63 - bev_dsm: true - bev_availability: 0.5 - bev_energy: 0.05 - bev_charge_efficiency: 0.9 - bev_plug_to_wheel_efficiency: 0.2 - bev_charge_rate: 0.011 - bev_avail_max: 0.95 - bev_avail_mean: 0.8 - v2g: true - land_transport_fuel_cell_share: - 2020: 0 - 2025: 0 - 2030: 0 - 2035: 0 - 2040: 0 - 2045: 0 - 2050: 0 - land_transport_electric_share: - 2020: 0 - 2025: 0.15 - 2030: 0.3 - 2035: 0.45 - 2040: 0.7 - 2045: 0.85 - 2050: 1 - land_transport_ice_share: - 2020: 1 - 2025: 0.85 - 2030: 0.7 - 2035: 0.55 - 2040: 0.3 - 2045: 0.15 - 2050: 0 - transport_fuel_cell_efficiency: 0.5 - transport_internal_combustion_efficiency: 0.3 - agriculture_machinery_electric_share: 0 - agriculture_machinery_oil_share: 1 - agriculture_machinery_fuel_efficiency: 0.7 - agriculture_machinery_electric_efficiency: 0.3 - MWh_MeOH_per_MWh_H2: 0.8787 - MWh_MeOH_per_tCO2: 4.0321 - MWh_MeOH_per_MWh_e: 3.6907 - shipping_hydrogen_liquefaction: false - shipping_hydrogen_share: - 2020: 0 - 2025: 0 - 2030: 0 - 2035: 0 - 2040: 0 - 2045: 0 - 2050: 0 - shipping_methanol_share: - 2020: 0 - 2025: 0.15 - 2030: 0.3 - 2035: 0.5 - 2040: 0.7 - 2045: 0.85 - 2050: 1 - shipping_oil_share: - 2020: 1 - 2025: 0.85 - 2030: 0.7 - 2035: 0.5 - 2040: 0.3 - 2045: 0.15 - 2050: 0 - shipping_methanol_efficiency: 0.46 - shipping_oil_efficiency: 0.40 - aviation_demand_factor: 1. - HVC_demand_factor: 1. - time_dep_hp_cop: true - heat_pump_sink_T: 55. - reduce_space_heat_exogenously: true - reduce_space_heat_exogenously_factor: - 2020: 0.10 # this results in a space heat demand reduction of 10% - 2025: 0.09 # first heat demand increases compared to 2020 because of larger floor area per capita - 2030: 0.09 - 2035: 0.11 - 2040: 0.16 - 2045: 0.21 - 2050: 0.29 - retrofitting: - retro_endogen: false - cost_factor: 1.0 - interest_rate: 0.04 - annualise_cost: true - tax_weighting: false - construction_index: true - tes: true - tes_tau: - decentral: 3 - central: 180 - boilers: true - resistive_heaters: true - oil_boilers: false - biomass_boiler: true - chp: true - micro_chp: false - solar_thermal: false - solar_cf_correction: 0.788457 # = >>> 1/1.2683 - marginal_cost_storage: 0. #1e-4 - methanation: true - coal_cc: false - dac: true - co2_vent: false - central_heat_vent: false - allam_cycle: false - hydrogen_fuel_cell: true - hydrogen_turbine: false - SMR: true - SMR_cc: true - regional_methanol_demand: false - regional_oil_demand: false - regional_co2_sequestration_potential: - enable: false - attribute: 'conservative estimate Mt' - include_onshore: false - min_size: 3 - max_size: 25 - years_of_storage: 25 - co2_sequestration_potential: 200 - co2_sequestration_cost: 10 - co2_sequestration_lifetime: 50 - co2_spatial: false - co2network: false - co2_network_cost_factor: 1 - cc_fraction: 0.9 - hydrogen_underground_storage: true - hydrogen_underground_storage_locations: - # - onshore # more than 50 km from sea - - nearshore # within 50 km of sea - # - offshore - ammonia: false - min_part_load_fischer_tropsch: 0.7 - min_part_load_methanolisation: 0.3 - min_part_load_methanation: 0.3 - use_fischer_tropsch_waste_heat: true - use_haber_bosch_waste_heat: true - use_methanolisation_waste_heat: true - use_methanation_waste_heat: true - use_fuel_cell_waste_heat: true - use_electrolysis_waste_heat: true - electricity_distribution_grid: true - electricity_distribution_grid_cost_factor: 1.0 - electricity_grid_connection: true - transmission_efficiency: - DC: - efficiency_static: 0.98 - efficiency_per_1000km: 0.977 - H2 pipeline: - efficiency_per_1000km: 1 # 0.979 - compression_per_1000km: 0.019 - gas pipeline: - efficiency_per_1000km: 1 #0.977 - compression_per_1000km: 0.01 - H2_network: true - gas_network: false - H2_retrofit: false - H2_retrofit_capacity_per_CH4: 0.6 - gas_network_connectivity_upgrade: 1 - gas_distribution_grid: true - gas_distribution_grid_cost_factor: 1.0 - biomass_spatial: false - biomass_transport: false - biogas_upgrading_cc: false - conventional_generation: - OCGT: gas - biomass_to_liquid: false - biosng: false - limit_max_growth: - enable: false - # allowing 30% larger than max historic growth - factor: 1.3 - max_growth: # unit GW - onwind: 16 # onshore max grow so far 16 GW in Europe https://www.iea.org/reports/renewables-2020/wind - solar: 28 # solar max grow so far 28 GW in Europe https://www.iea.org/reports/renewables-2020/solar-pv - offwind-ac: 35 # offshore max grow so far 3.5 GW in Europe https://windeurope.org/about-wind/statistics/offshore/european-offshore-wind-industry-key-trends-statistics-2019/ - offwind-dc: 35 - max_relative_growth: - onwind: 3 - solar: 3 - offwind-ac: 3 - offwind-dc: 3 - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#industry -industry: - St_primary_fraction: - 2020: 0.6 - 2025: 0.55 - 2030: 0.5 - 2035: 0.45 - 2040: 0.4 - 2045: 0.35 - 2050: 0.3 - DRI_fraction: - 2020: 0 - 2025: 0 - 2030: 0.05 - 2035: 0.2 - 2040: 0.4 - 2045: 0.7 - 2050: 1 - H2_DRI: 1.7 - elec_DRI: 0.322 - Al_primary_fraction: - 2020: 0.4 - 2025: 0.375 - 2030: 0.35 - 2035: 0.325 - 2040: 0.3 - 2045: 0.25 - 2050: 0.2 - MWh_NH3_per_tNH3: 5.166 - MWh_CH4_per_tNH3_SMR: 10.8 - MWh_elec_per_tNH3_SMR: 0.7 - MWh_H2_per_tNH3_electrolysis: 5.93 - MWh_elec_per_tNH3_electrolysis: 0.2473 - MWh_NH3_per_MWh_H2_cracker: 1.46 # https://github.com/euronion/trace/blob/44a5ff8401762edbef80eff9cfe5a47c8d3c8be4/data/efficiencies.csv - NH3_process_emissions: 24.5 - petrochemical_process_emissions: 25.5 - HVC_primary_fraction: 1. - HVC_mechanical_recycling_fraction: 0. - HVC_chemical_recycling_fraction: 0. - HVC_production_today: 52. - MWh_elec_per_tHVC_mechanical_recycling: 0.547 - MWh_elec_per_tHVC_chemical_recycling: 6.9 - chlorine_production_today: 9.58 - MWh_elec_per_tCl: 3.6 - MWh_H2_per_tCl: -0.9372 - methanol_production_today: 1.5 - MWh_elec_per_tMeOH: 0.167 - MWh_CH4_per_tMeOH: 10.25 - hotmaps_locate_missing: false - reference_year: 2015 - - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#costs -costs: - year: 2030 - version: v0.6.0 - rooftop_share: 0.14 # based on the potentials, assuming (0.1 kW/m2 and 10 m2/person) - social_discountrate: 0.02 - fill_values: - FOM: 0 - VOM: 0 - efficiency: 1 - fuel: 0 - investment: 0 - lifetime: 25 - "CO2 intensity": 0 - "discount rate": 0.07 - # Marginal and capital costs can be overwritten - # capital_cost: - # onwind: 500 - marginal_cost: - solar: 0.01 - onwind: 0.015 - offwind: 0.015 - hydro: 0. - H2: 0. - electrolysis: 0. - fuel cell: 0. - battery: 0. - battery inverter: 0. - emission_prices: - enable: false - co2: 0. - co2_monthly_prices: false - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#clustering -clustering: - focus_weights: false - simplify_network: - to_substations: false - algorithm: kmeans # choose from: [hac, kmeans] - feature: solar+onwind-time - exclude_carriers: [] - remove_stubs: true - remove_stubs_across_borders: true - cluster_network: - algorithm: kmeans - feature: solar+onwind-time - exclude_carriers: [] - consider_efficiency_classes: false - aggregation_strategies: - generators: - committable: any - ramp_limit_up: max - ramp_limit_down: max - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#solving -solving: - #tmpdir: "path/to/tmp" - options: - clip_p_max_pu: 1.e-2 - load_shedding: false - noisy_costs: true - skip_iterations: true - rolling_horizon: false - seed: 123 - custom_extra_functionality: "../data/custom_extra_functionality.py" - # options that go into the optimize function - track_iterations: false - min_iterations: 4 - max_iterations: 6 - transmission_losses: 2 - linearized_unit_commitment: true - horizon: 365 - - constraints: - CCL: false - EQ: false - BAU: false - SAFE: false - - solver: - name: copt - options: copt-default - - solver_options: - highs-default: - # refer to https://ergo-code.github.io/HiGHS/options/definitions.html#solver - threads: 4 - solver: "ipm" - run_crossover: "off" - small_matrix_value: 1e-6 - large_matrix_value: 1e9 - primal_feasibility_tolerance: 1e-5 - dual_feasibility_tolerance: 1e-5 - ipm_optimality_tolerance: 1e-4 - parallel: "on" - random_seed: 123 - gurobi-default: - threads: 8 - method: 2 # barrier - crossover: 0 - BarConvTol: 1.e-6 - Seed: 123 - # AggFill: 0 - # PreDual: 2 - # GURO_PAR_BARDENSETHRESH: 200 - gurobi-numeric-focus: - name: gurobi - NumericFocus: 3 # Favour numeric stability over speed - method: 2 # barrier - crossover: 0 # do not use crossover - BarHomogeneous: 1 # Use homogeneous barrier if standard does not converge - BarConvTol: 1.e-5 - FeasibilityTol: 1.e-4 - OptimalityTol: 1.e-4 - ObjScale: -0.5 - threads: 8 - Seed: 123 - gurobi-fallback: # Use gurobi defaults - name: gurobi - crossover: 0 - method: 2 # barrier - BarHomogeneous: 1 # Use homogeneous barrier if standard does not converge - BarConvTol: 1.e-5 - FeasibilityTol: 1.e-5 - OptimalityTol: 1.e-5 - Seed: 123 - threads: 8 - cplex-default: - threads: 4 - lpmethod: 4 # barrier - solutiontype: 2 # non basic solution, ie no crossover - barrier.convergetol: 1.e-5 - feasopt.tolerance: 1.e-6 - copt-vanilla: - Threads: 8 - copt-default: - Threads: 8 - LpMethod: 2 - Scaling: 1 - Presolve: 3 - Crossover: 0 - cbc-default: {} # Used in CI - glpk-default: {} # Used in CI - - mem: 80000 #memory in MB; 20 GB enough for 50+B+I+H2; 100 GB for 181+B+I+H2 - walltime: "10:00:00" - -# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#plotting -plotting: - map: - boundaries: [-11, 30, 34, 71] - color_geomap: - ocean: white - land: white - eu_node_location: - x: -5.5 - y: 46. - costs_max: 1000 - costs_threshold: 1 - energy_max: 20000 - energy_min: -20000 - energy_threshold: 50. - - nice_names: - OCGT: "Open-Cycle Gas" - CCGT: "Combined-Cycle Gas" - offwind-ac: "Offshore Wind (AC)" - offwind-dc: "Offshore Wind (DC)" - onwind: "Onshore Wind" - solar: "Solar" - PHS: "Pumped Hydro Storage" - hydro: "Reservoir & Dam" - battery: "Battery Storage" - H2: "Hydrogen Storage" - lines: "Transmission Lines" - ror: "Run of River" - load: "Load Shedding" - ac: "AC" - dc: "DC" - - tech_colors: - # wind - onwind: "#235ebc" - onshore wind: "#235ebc" - offwind: "#6895dd" - offshore wind: "#6895dd" - offwind-ac: "#6895dd" - offshore wind (AC): "#6895dd" - offshore wind ac: "#6895dd" - offwind-dc: "#74c6f2" - offshore wind (DC): "#74c6f2" - offshore wind dc: "#74c6f2" - # water - hydro: '#298c81' - hydro reservoir: '#298c81' - ror: '#3dbfb0' - run of river: '#3dbfb0' - hydroelectricity: '#298c81' - PHS: '#51dbcc' - hydro+PHS: "#08ad97" - wave: '#a7d4cf' - # solar - solar: "#f9d002" - solar PV: "#f9d002" - solar thermal: '#ffbf2b' - residential rural solar thermal: '#f1c069' - services rural solar thermal: '#eabf61' - residential urban decentral solar thermal: '#e5bc5a' - services urban decentral solar thermal: '#dfb953' - urban central solar thermal: '#d7b24c' - solar rooftop: '#ffea80' - # gas - OCGT: '#e0986c' - OCGT marginal: '#e0986c' - OCGT-heat: '#e0986c' - gas boiler: '#db6a25' - gas boilers: '#db6a25' - gas boiler marginal: '#db6a25' - residential rural gas boiler: '#d4722e' - residential urban decentral gas boiler: '#cb7a36' - services rural gas boiler: '#c4813f' - services urban decentral gas boiler: '#ba8947' - urban central gas boiler: '#b0904f' - gas: '#e05b09' - fossil gas: '#e05b09' - natural gas: '#e05b09' - biogas to gas: '#e36311' - biogas to gas CC: '#e51245' - CCGT: '#a85522' - CCGT marginal: '#a85522' - allam: '#B98F76' - gas for industry co2 to atmosphere: '#692e0a' - gas for industry co2 to stored: '#8a3400' - gas for industry: '#853403' - gas for industry CC: '#692e0a' - gas pipeline: '#ebbca0' - gas pipeline new: '#a87c62' - # oil - oil: '#c9c9c9' - imported oil: '#a3a3a3' - oil boiler: '#adadad' - residential rural oil boiler: '#a9a9a9' - services rural oil boiler: '#a5a5a5' - residential urban decentral oil boiler: '#a1a1a1' - urban central oil boiler: '#9d9d9d' - services urban decentral oil boiler: '#999999' - agriculture machinery oil: '#949494' - shipping oil: "#808080" - land transport oil: '#afafaf' - # nuclear - Nuclear: '#ff8c00' - Nuclear marginal: '#ff8c00' - nuclear: '#ff8c00' - uranium: '#ff8c00' - # coal - Coal: '#545454' - coal: '#545454' - Coal marginal: '#545454' - coal for industry: '#343434' - solid: '#545454' - Lignite: '#826837' - lignite: '#826837' - Lignite marginal: '#826837' - # biomass - biogas: '#e3d37d' - biomass: '#baa741' - solid biomass: '#baa741' - solid biomass transport: '#baa741' - solid biomass for industry: '#7a6d26' - solid biomass for industry CC: '#47411c' - solid biomass for industry co2 from atmosphere: '#736412' - solid biomass for industry co2 to stored: '#47411c' - urban central solid biomass CHP: '#9d9042' - urban central solid biomass CHP CC: '#6c5d28' - biomass boiler: '#8A9A5B' - residential rural biomass boiler: '#a1a066' - residential urban decentral biomass boiler: '#b0b87b' - services rural biomass boiler: '#c6cf98' - services urban decentral biomass boiler: '#dde5b5' - biomass to liquid: '#32CD32' - BioSNG: '#123456' - # power transmission - lines: '#6c9459' - transmission lines: '#6c9459' - electricity distribution grid: '#97ad8c' - low voltage: '#97ad8c' - # electricity demand - Electric load: '#110d63' - electric demand: '#110d63' - electricity: '#110d63' - industry electricity: '#2d2a66' - industry new electricity: '#2d2a66' - agriculture electricity: '#494778' - # battery + EVs - battery: '#ace37f' - battery storage: '#ace37f' - battery charger: '#88a75b' - battery discharger: '#5d4e29' - home battery: '#80c944' - home battery storage: '#80c944' - home battery charger: '#5e8032' - home battery discharger: '#3c5221' - BEV charger: '#baf238' - V2G: '#e5ffa8' - land transport EV: '#baf238' - Li ion: '#baf238' - # hot water storage - water tanks: '#e69487' - residential rural water tanks: '#f7b7a3' - services rural water tanks: '#f3afa3' - residential urban decentral water tanks: '#f2b2a3' - services urban decentral water tanks: '#f1b4a4' - urban central water tanks: '#e9977d' - hot water storage: '#e69487' - hot water charging: '#e8998b' - urban central water tanks charger: '#b57a67' - residential rural water tanks charger: '#b4887c' - residential urban decentral water tanks charger: '#b39995' - services rural water tanks charger: '#b3abb0' - services urban decentral water tanks charger: '#b3becc' - hot water discharging: '#e99c8e' - urban central water tanks discharger: '#b9816e' - residential rural water tanks discharger: '#ba9685' - residential urban decentral water tanks discharger: '#baac9e' - services rural water tanks discharger: '#bbc2b8' - services urban decentral water tanks discharger: '#bdd8d3' - # heat demand - Heat load: '#cc1f1f' - heat: '#cc1f1f' - heat vent: '#aa3344' - heat demand: '#cc1f1f' - rural heat: '#ff5c5c' - residential rural heat: '#ff7c7c' - services rural heat: '#ff9c9c' - central heat: '#cc1f1f' - urban central heat: '#d15959' - urban central heat vent: '#a74747' - decentral heat: '#750606' - residential urban decentral heat: '#a33c3c' - services urban decentral heat: '#cc1f1f' - low-temperature heat for industry: '#8f2727' - process heat: '#ff0000' - agriculture heat: '#d9a5a5' - # heat supply - heat pumps: '#2fb537' - heat pump: '#2fb537' - air heat pump: '#36eb41' - residential urban decentral air heat pump: '#48f74f' - services urban decentral air heat pump: '#5af95d' - urban central air heat pump: '#6cfb6b' - ground heat pump: '#2fb537' - residential rural ground heat pump: '#48f74f' - services rural ground heat pump: '#5af95d' - Ambient: '#98eb9d' - CHP: '#8a5751' - urban central gas CHP: '#8d5e56' - CHP CC: '#634643' - urban central gas CHP CC: '#6e4e4c' - CHP heat: '#8a5751' - CHP electric: '#8a5751' - district heating: '#e8beac' - resistive heater: '#d8f9b8' - residential rural resistive heater: '#bef5b5' - residential urban decentral resistive heater: '#b2f1a9' - services rural resistive heater: '#a5ed9d' - services urban decentral resistive heater: '#98e991' - urban central resistive heater: '#8cdf85' - retrofitting: '#8487e8' - building retrofitting: '#8487e8' - # hydrogen - H2 for industry: "#f073da" - H2 for shipping: "#ebaee0" - H2: '#bf13a0' - hydrogen: '#bf13a0' - retrofitted H2 boiler: '#e5a0d9' - SMR: '#870c71' - SMR CC: '#4f1745' - H2 liquefaction: '#d647bd' - hydrogen storage: '#bf13a0' - H2 Store: '#bf13a0' - H2 storage: '#bf13a0' - land transport fuel cell: '#6b3161' - H2 pipeline: '#f081dc' - H2 pipeline retrofitted: '#ba99b5' - H2 Fuel Cell: '#c251ae' - H2 fuel cell: '#c251ae' - H2 turbine: '#991f83' - H2 Electrolysis: '#ff29d9' - H2 electrolysis: '#ff29d9' - # ammonia - NH3: '#46caf0' - ammonia: '#46caf0' - ammonia store: '#00ace0' - ammonia cracker: '#87d0e6' - Haber-Bosch: '#076987' - # syngas - Sabatier: '#9850ad' - methanation: '#c44ce6' - methane: '#c44ce6' - # synfuels - Fischer-Tropsch: '#25c49a' - liquid: '#25c49a' - kerosene for aviation: '#a1ffe6' - naphtha for industry: '#57ebc4' - methanolisation: '#83d6d5' - methanol: '#468c8b' - shipping methanol: '#468c8b' - # co2 - CC: '#f29dae' - CCS: '#f29dae' - CO2 sequestration: '#f29dae' - DAC: '#ff5270' - co2 stored: '#f2385a' - co2 sequestered: '#f2682f' - co2: '#f29dae' - co2 vent: '#ffd4dc' - CO2 pipeline: '#f5627f' - # emissions - process emissions CC: '#000000' - process emissions: '#222222' - process emissions to stored: '#444444' - process emissions to atmosphere: '#888888' - oil emissions: '#aaaaaa' - shipping oil emissions: "#555555" - shipping methanol emissions: '#666666' - land transport oil emissions: '#777777' - agriculture machinery oil emissions: '#333333' - # other - shipping: '#03a2ff' - power-to-heat: '#2fb537' - power-to-gas: '#c44ce6' - power-to-H2: '#ff29d9' - power-to-liquid: '#25c49a' - gas-to-power/heat: '#ee8340' - waste: '#e3d37d' - other: '#000000' - geothermal: '#ba91b1' - AC: "#70af1d" - AC-AC: "#70af1d" - AC line: "#70af1d" - links: "#8a1caf" - HVDC links: "#8a1caf" - DC: "#8a1caf" - DC-DC: "#8a1caf" - DC link: "#8a1caf" - load: "#dd2e23" From 9aa154bd048c02fb511e78b1dc4f9524ef09251b Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 25 Jan 2024 10:20:19 +0100 Subject: [PATCH 18/20] Add several map projection options --- config/config.default.yaml | 1 + doc/configtables/plotting.csv | 1 + doc/release_notes.rst | 2 ++ scripts/plot_network.py | 29 ++++++++++++++++++++++++----- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 255e3869..ef410ad6 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -773,6 +773,7 @@ plotting: color_geomap: ocean: white land: white + projection: "EqualEarth" eu_node_location: x: -5.5 y: 46. diff --git a/doc/configtables/plotting.csv b/doc/configtables/plotting.csv index ed5d9c9f..656ed9be 100644 --- a/doc/configtables/plotting.csv +++ b/doc/configtables/plotting.csv @@ -1,6 +1,7 @@ ,Unit,Values,Description map,,, -- boundaries,°,"[x1,x2,y1,y2]",Boundaries of the map plots in degrees latitude (y) and longitude (x) +projection,--,"{EqualEarth, EuroPP, LambertAzimuthalEqualArea, LambertConformal, Orthographic}",Projection to use for maps; default is EqualEarth. LambertConformal is recommended by the European Environmental Agency. costs_max,bn Euro,float,Upper y-axis limit in cost bar plots. costs_threshold,bn Euro,float,Threshold below which technologies will not be shown in cost bar plots. energy_max,TWh,float,Upper y-axis limit in energy bar plots. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index f8f958cd..0386cf49 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -35,6 +35,8 @@ Upcoming Release * Add support for the linopy ``io_api`` option; set to ``"direct"`` to increase model reading and writing performance for the highs and gurobi solvers. +* Add several map projection options for plotting. + PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/scripts/plot_network.py b/scripts/plot_network.py index 33312a44..c078e412 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -170,7 +170,7 @@ def plot_map( line_widths = line_widths.replace(line_lower_threshold, 0) link_widths = link_widths.replace(line_lower_threshold, 0) - fig, ax = plt.subplots(subplot_kw={"projection": ccrs.EqualEarth()}) + fig, ax = plt.subplots(subplot_kw={"projection": proj}) fig.set_size_inches(7, 6) n.plot( @@ -358,7 +358,6 @@ def plot_h2_map(network, regions): n.links.bus0 = n.links.bus0.str.replace(" H2", "") n.links.bus1 = n.links.bus1.str.replace(" H2", "") - proj = ccrs.EqualEarth() regions = regions.to_crs(proj.proj4_init) fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": proj}) @@ -568,7 +567,7 @@ def plot_ch4_map(network): "biogas": "seagreen", } - fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": ccrs.EqualEarth()}) + fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": proj}) n.plot( bus_sizes=bus_sizes, @@ -679,7 +678,7 @@ def plot_map_without(network): # Drop non-electric buses so they don't clutter the plot n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True) - fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": ccrs.EqualEarth()}) + fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": proj}) # PDF has minimum width, so set these to zero line_lower_threshold = 200.0 @@ -993,7 +992,7 @@ def plot_map_perfect( link_widths[link_widths > line_upper_threshold] = line_upper_threshold for year in costs.columns: - fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()}) + fig, ax = plt.subplots(subplot_kw={"projection": proj}) fig.set_size_inches(7, 6) fig.suptitle(year) @@ -1082,6 +1081,26 @@ if __name__ == "__main__": if map_opts["boundaries"] is None: map_opts["boundaries"] = regions.total_bounds[[0, 2, 1, 3]] + [-1, 1, -1, 1] + proj_str = snakemake.params.plotting.get("projection", "EqualEarth") + central_coords = dict(central_longitude=10.0, central_latitude=50.0) + if proj_str == "EqualEarth": + # Equal area but large distortions towards the poles. + proj = ccrs.EqualEarth() + elif proj_str == "EuroPP": + # UTM Zone 32 projection + proj = ccrs.EuroPP() + elif proj_str == "LambertConformal": + # The European Environment Agency recommends using this + # projection for conformal pan-European mapping + proj = ccrs.LambertConformal(standard_parallels=(35, 65), **central_coords) + elif proj_str == "Orthographic": + proj = ccrs.Orthographic(**central_coords) + else: + logger.warning( + f"Plotting project {proj_str} not recognised; falling back on EqualEarth" + ) + proj = ccrs.EqualEarth() + if snakemake.params["foresight"] == "perfect": plot_map_perfect( n, From 03c914bef136bea7fe5b17fdb649ecd3239cf938 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 25 Jan 2024 14:34:03 +0100 Subject: [PATCH 19/20] Make projection selection flexible by reading directly from config --- config/config.default.yaml | 8 +++++++- doc/configtables/plotting.csv | 4 +++- doc/release_notes.rst | 2 +- scripts/plot_network.py | 22 +++------------------- 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index ef410ad6..51080862 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -773,7 +773,13 @@ plotting: color_geomap: ocean: white land: white - projection: "EqualEarth" + projection: + name: "EqualEarth" + # See https://scitools.org.uk/cartopy/docs/latest/reference/projections.html for alternatives, for example: + # name: "LambertConformal" + # central_longitude: 10. + # central_latitude: 50. + # standard_parallels: [35, 65] eu_node_location: x: -5.5 y: 46. diff --git a/doc/configtables/plotting.csv b/doc/configtables/plotting.csv index 656ed9be..82fc203c 100644 --- a/doc/configtables/plotting.csv +++ b/doc/configtables/plotting.csv @@ -1,7 +1,9 @@ ,Unit,Values,Description map,,, -- boundaries,°,"[x1,x2,y1,y2]",Boundaries of the map plots in degrees latitude (y) and longitude (x) -projection,--,"{EqualEarth, EuroPP, LambertAzimuthalEqualArea, LambertConformal, Orthographic}",Projection to use for maps; default is EqualEarth. LambertConformal is recommended by the European Environmental Agency. +projection,,,, +-- name,--,"Valid Cartopy projection name","See https://scitools.org.uk/cartopy/docs/latest/reference/projections.html for list of available projections." +-- args,--,--,"Other entries under 'projection' are passed as keyword arguments to the projection constructor, e.g. ``central_longitude: 10.``." costs_max,bn Euro,float,Upper y-axis limit in cost bar plots. costs_threshold,bn Euro,float,Threshold below which technologies will not be shown in cost bar plots. energy_max,TWh,float,Upper y-axis limit in energy bar plots. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 0386cf49..93d1a268 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -35,7 +35,7 @@ Upcoming Release * Add support for the linopy ``io_api`` option; set to ``"direct"`` to increase model reading and writing performance for the highs and gurobi solvers. -* Add several map projection options for plotting. +* Add the option to customise map projection in plotting config. PyPSA-Eur 0.9.0 (5th January 2024) diff --git a/scripts/plot_network.py b/scripts/plot_network.py index c078e412..13736d01 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -1081,25 +1081,9 @@ if __name__ == "__main__": if map_opts["boundaries"] is None: map_opts["boundaries"] = regions.total_bounds[[0, 2, 1, 3]] + [-1, 1, -1, 1] - proj_str = snakemake.params.plotting.get("projection", "EqualEarth") - central_coords = dict(central_longitude=10.0, central_latitude=50.0) - if proj_str == "EqualEarth": - # Equal area but large distortions towards the poles. - proj = ccrs.EqualEarth() - elif proj_str == "EuroPP": - # UTM Zone 32 projection - proj = ccrs.EuroPP() - elif proj_str == "LambertConformal": - # The European Environment Agency recommends using this - # projection for conformal pan-European mapping - proj = ccrs.LambertConformal(standard_parallels=(35, 65), **central_coords) - elif proj_str == "Orthographic": - proj = ccrs.Orthographic(**central_coords) - else: - logger.warning( - f"Plotting project {proj_str} not recognised; falling back on EqualEarth" - ) - proj = ccrs.EqualEarth() + proj_kwargs = snakemake.params.plotting.get("projection", dict(name="EqualEarth")) + proj_func = getattr(ccrs, proj_kwargs.pop("name")) + proj = proj_func(**proj_kwargs) if snakemake.params["foresight"] == "perfect": plot_map_perfect( From 987930c2503d2e45425d7571307db70235aa341f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 25 Jan 2024 16:43:08 +0100 Subject: [PATCH 20/20] document that resolution and segmentation config options are only for electricity-only --- doc/configtables/snapshots.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/configtables/snapshots.csv b/doc/configtables/snapshots.csv index 4a3e1212..0226a9aa 100644 --- a/doc/configtables/snapshots.csv +++ b/doc/configtables/snapshots.csv @@ -2,5 +2,5 @@ start,--,str or datetime-like; e.g. YYYY-MM-DD,Left bound of date range end,--,str or datetime-like; e.g. YYYY-MM-DD,Right bound of date range inclusive,--,"One of {'neither', 'both', ‘left’, ‘right’}","Make the time interval closed to the ``left``, ``right``, or both sides ``both`` or neither side ``None``." -resolution ,--,"{false,``nH``; i.e. ``2H``-``6H``}",Resample the time-resolution by averaging over every ``n`` snapshots -segmentation,--,"{false,``n``; e.g. ``4380``}","Apply time series segmentation with `tsam `_ package to ``n`` adjacent snapshots of varying lengths based on capacity factors of varying renewables, hydro inflow and load." +resolution ,--,"{false,``nH``; i.e. ``2H``-``6H``}","Resample the time-resolution by averaging over every ``n`` snapshots in :mod:`prepare_network`. **Warning:** This option should currently only be used with electricity-only networks, not for sector-coupled networks." +segmentation,--,"{false,``n``; e.g. ``4380``}","Apply time series segmentation with `tsam `_ package to ``n`` adjacent snapshots of varying lengths based on capacity factors of varying renewables, hydro inflow and load in :mod:`prepare_network`. **Warning:** This option should currently only be used with electricity-only networks, not for sector-coupled networks."