From f6dd2e12f382aa58d599e90c4ce7eb11d844a663 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 11 Sep 2020 12:40:53 +0200 Subject: [PATCH 001/591] some refactoring and code cleaning --- .gitignore | 1 + {LICENSES => .licenses}/CC-BY-4.0.txt | 0 {LICENSES => .licenses}/CC0-1.0.txt | 0 {LICENSES => .licenses}/GPL-3.0-or-later.txt | 0 Snakefile | 129 ++++++++------- cluster.yaml | 22 --- config.default.yaml | 67 +------- config.tutorial.yaml | 160 ------------------- doc/configtables/plotting.csv | 3 +- doc/configtables/scenario.csv | 3 +- doc/index.rst | 8 +- doc/wildcards.rst | 10 -- matplotlibrc | 1 - scripts/_helpers.py | 8 +- scripts/add_electricity.py | 42 ++--- scripts/add_extra_components.py | 12 +- scripts/base_network.py | 34 +++- scripts/build_bus_regions.py | 23 +-- scripts/build_country_flh.py | 5 +- scripts/build_cutout.py | 7 +- scripts/build_hydro_profile.py | 13 +- scripts/build_natura_raster.py | 3 +- scripts/build_powerplants.py | 9 +- scripts/build_renewable_profiles.py | 13 +- scripts/build_shapes.py | 18 ++- scripts/cluster_network.py | 68 ++++---- scripts/make_summary.py | 98 +++--------- scripts/plot_network.py | 36 ++--- scripts/plot_p_nom_max.py | 8 +- scripts/plot_summary.py | 33 +--- scripts/prepare_links_p_nom.py | 33 ++-- scripts/prepare_network.py | 17 +- scripts/retrieve_databundle.py | 7 +- scripts/retrieve_natura_raster.py | 3 +- scripts/simplify_network.py | 12 +- scripts/solve_network.py | 14 +- scripts/solve_operations_network.py | 6 +- test/config.test1.yaml | 141 ---------------- 38 files changed, 331 insertions(+), 736 deletions(-) rename {LICENSES => .licenses}/CC-BY-4.0.txt (100%) rename {LICENSES => .licenses}/CC0-1.0.txt (100%) rename {LICENSES => .licenses}/GPL-3.0-or-later.txt (100%) delete mode 100644 cluster.yaml delete mode 100644 matplotlibrc diff --git a/.gitignore b/.gitignore index 5ed82d0d..b4734ab2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ __pycache__ *dconf gurobi.log +.vscode /bak /resources diff --git a/LICENSES/CC-BY-4.0.txt b/.licenses/CC-BY-4.0.txt similarity index 100% rename from LICENSES/CC-BY-4.0.txt rename to .licenses/CC-BY-4.0.txt diff --git a/LICENSES/CC0-1.0.txt b/.licenses/CC0-1.0.txt similarity index 100% rename from LICENSES/CC0-1.0.txt rename to .licenses/CC0-1.0.txt diff --git a/LICENSES/GPL-3.0-or-later.txt b/.licenses/GPL-3.0-or-later.txt similarity index 100% rename from LICENSES/GPL-3.0-or-later.txt rename to .licenses/GPL-3.0-or-later.txt diff --git a/Snakefile b/Snakefile index 72b726fc..ce27174a 100644 --- a/Snakefile +++ b/Snakefile @@ -11,33 +11,31 @@ if not exists("config.yaml"): configfile: "config.yaml" COSTS="data/costs.csv" +ATLITE_NPROCESSES = config['atlite'].get('nprocesses', 4) + wildcard_constraints: - ll="(v|c)([0-9\.]+|opt|all)|all", # line limit, can be volume or cost simpl="[a-zA-Z0-9]*|all", clusters="[0-9]+m?|all", - sectors="[+a-zA-Z0-9]+", + ll="(v|c)([0-9\.]+|opt|all)|all", opts="[-+a-zA-Z0-9\.]*" + rule cluster_all_elec_networks: - input: - expand("networks/elec_s{simpl}_{clusters}.nc", - **config['scenario']) + input: expand("networks/elec_s{simpl}_{clusters}.nc", **config['scenario']) + rule extra_components_all_elec_networks: - input: - expand("networks/elec_s{simpl}_{clusters}_ec.nc", - **config['scenario']) + input: expand("networks/elec_s{simpl}_{clusters}_ec.nc", **config['scenario']) + rule prepare_all_elec_networks: - input: - expand("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - **config['scenario']) + input: expand("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config['scenario']) + rule solve_all_elec_networks: - input: - expand("results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - **config['scenario']) + input: expand("results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config['scenario']) + if config['enable'].get('prepare_links_p_nom', False): rule prepare_links_p_nom: @@ -45,7 +43,6 @@ if config['enable'].get('prepare_links_p_nom', False): log: 'logs/prepare_links_p_nom.log' threads: 1 resources: mem=500 - # group: 'nonfeedin_preparation' script: 'scripts/prepare_links_p_nom.py' @@ -56,15 +53,18 @@ datafiles = ['ch_cantons.csv', 'je-e-21.03.02.xls', 'nama_10r_3gdp.tsv.gz', 'time_series_60min_singleindex_filtered.csv', 'corine/g250_clc06_V18_5.tif'] + if not config.get('tutorial', False): datafiles.extend(["natura/Natura2000_end2015.shp", "GEBCO_2014_2D.nc"]) + if config['enable'].get('retrieve_databundle', True): rule retrieve_databundle: - output: expand('data/bundle/{file}', file=datafiles) + output: expand('data/bundle/{file}', file=datafiles) log: "logs/retrieve_databundle.log" script: 'scripts/retrieve_databundle.py' + rule build_powerplants: input: base_network="networks/base.nc", @@ -73,9 +73,9 @@ rule build_powerplants: log: "logs/build_powerplants.log" threads: 1 resources: mem=500 - # group: 'nonfeedin_preparation' script: "scripts/build_powerplants.py" + rule base_network: input: eg_buses='data/entsoegridkit/buses.csv', @@ -94,9 +94,9 @@ rule base_network: benchmark: "benchmarks/base_network" threads: 1 resources: mem=500 - # group: 'nonfeedin_preparation' script: "scripts/base_network.py" + rule build_shapes: input: naturalearth='data/bundle/naturalearth/ne_10m_admin_0_countries.shp', @@ -114,9 +114,9 @@ rule build_shapes: log: "logs/build_shapes.log" threads: 1 resources: mem=500 - # group: 'nonfeedin_preparation' script: "scripts/build_shapes.py" + rule build_bus_regions: input: country_shapes='resources/country_shapes.geojson', @@ -126,20 +126,21 @@ rule build_bus_regions: regions_onshore="resources/regions_onshore.geojson", regions_offshore="resources/regions_offshore.geojson" log: "logs/build_bus_regions.log" + threads: 1 resources: mem=1000 - # group: 'nonfeedin_preparation' script: "scripts/build_bus_regions.py" -if config['enable'].get('build_cutout', False): + +if config['enable'].get('build_cutout', False): rule build_cutout: output: directory("cutouts/{cutout}") log: "logs/build_cutout/{cutout}.log" - resources: mem=config['atlite'].get('nprocesses', 4) * 1000 - threads: config['atlite'].get('nprocesses', 4) benchmark: "benchmarks/build_cutout_{cutout}" - # group: 'feedin_preparation' + threads: ATLITE_NPROCESSES + resources: mem=ATLITE_NPROCESSES * 1000 script: "scripts/build_cutout.py" + if config['enable'].get('retrieve_cutout', True): rule retrieve_cutout: output: directory(expand("cutouts/{cutouts}", **config['atlite'])), @@ -156,34 +157,37 @@ if config['enable'].get('build_natura_raster', False): log: "logs/build_natura_raster.log" script: "scripts/build_natura_raster.py" + if config['enable'].get('retrieve_natura_raster', True): rule retrieve_natura_raster: output: "resources/natura.tiff" log: "logs/retrieve_natura_raster.log" script: 'scripts/retrieve_natura_raster.py' + rule build_renewable_profiles: input: base_network="networks/base.nc", corine="data/bundle/corine/g250_clc06_V18_5.tif", natura="resources/natura.tiff", - gebco=lambda wildcards: ("data/bundle/GEBCO_2014_2D.nc" - if "max_depth" in config["renewable"][wildcards.technology].keys() - else []), + gebco=lambda w: ("data/bundle/GEBCO_2014_2D.nc" + if "max_depth" in config["renewable"][w.technology].keys() + else []), country_shapes='resources/country_shapes.geojson', offshore_shapes='resources/offshore_shapes.geojson', - regions=lambda wildcards: ("resources/regions_onshore.geojson" - if wildcards.technology in ('onwind', 'solar') - else "resources/regions_offshore.geojson"), - cutout=lambda wildcards: "cutouts/" + config["renewable"][wildcards.technology]['cutout'] - output: profile="resources/profile_{technology}.nc", + regions=lambda w: ("resources/regions_onshore.geojson" + if w.technology in ('onwind', 'solar') + else "resources/regions_offshore.geojson"), + cutout=lambda w: "cutouts/" + config["renewable"][w.technology]['cutout'] + output: + profile="resources/profile_{technology}.nc", log: "logs/build_renewable_profile_{technology}.log" - resources: mem=config['atlite'].get('nprocesses', 2) * 5000 - threads: config['atlite'].get('nprocesses', 2) benchmark: "benchmarks/build_renewable_profiles_{technology}" - # group: 'feedin_preparation' + threads: ATLITE_NPROCESSES + resources: mem=ATLITE_NPROCESSES * 5000 script: "scripts/build_renewable_profiles.py" + if 'hydro' in config['renewable'].keys(): rule build_hydro_profile: input: @@ -193,9 +197,9 @@ if 'hydro' in config['renewable'].keys(): output: 'resources/profile_hydro.nc' log: "logs/build_hydro_profile.log" resources: mem=5000 - # group: 'feedin_preparation' script: 'scripts/build_hydro_profile.py' + rule add_electricity: input: base_network='networks/base.nc', @@ -206,16 +210,16 @@ rule add_electricity: geth_hydro_capacities='data/geth2015_hydro_capacities.csv', opsd_load='data/bundle/time_series_60min_singleindex_filtered.csv', nuts3_shapes='resources/nuts3_shapes.geojson', - **{'profile_' + t: "resources/profile_" + t + ".nc" - for t in config['renewable']} + **{'profile_' + tech: "resources/profile_" + tech + ".nc" + for tech in config['renewable']} output: "networks/elec.nc" log: "logs/add_electricity.log" benchmark: "benchmarks/add_electricity" threads: 1 resources: mem=3000 - # group: 'build_pypsa_networks' script: "scripts/add_electricity.py" + rule simplify_network: input: network='networks/{network}.nc', @@ -231,9 +235,9 @@ rule simplify_network: benchmark: "benchmarks/simplify_network/{network}_s{simpl}" threads: 1 resources: mem=4000 - # group: 'build_pypsa_networks' script: "scripts/simplify_network.py" + rule cluster_network: input: network='networks/{network}_s{simpl}.nc', @@ -250,7 +254,6 @@ rule cluster_network: benchmark: "benchmarks/cluster_network/{network}_s{simpl}_{clusters}" threads: 1 resources: mem=3000 - # group: 'build_pypsa_networks' script: "scripts/cluster_network.py" @@ -263,7 +266,6 @@ rule add_extra_components: benchmark: "benchmarks/add_extra_components/{network}_s{simpl}_{clusters}_ec" threads: 1 resources: mem=3000 - # group: 'build_pypsa_networks' script: "scripts/add_extra_components.py" @@ -271,11 +273,12 @@ rule prepare_network: input: 'networks/{network}_s{simpl}_{clusters}_ec.nc', tech_costs=COSTS output: 'networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc' log: "logs/prepare_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" + benchmark: "benchmarks/prepare_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: 1 resources: mem=1000 - # benchmark: "benchmarks/prepare_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}" script: "scripts/prepare_network.py" + def memory(w): factor = 3. for o in w.opts.split('-'): @@ -287,12 +290,11 @@ def memory(w): return int(factor * (18000 + 180 * int(w.clusters[:-1]))) else: return int(factor * (10000 + 195 * int(w.clusters))) - # return 4890+310 * int(w.clusters) + rule solve_network: input: "networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" output: "results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - shadow: "shallow" log: solver=normpath("logs/solve_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log"), python="logs/solve_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", @@ -300,15 +302,15 @@ rule solve_network: benchmark: "benchmarks/solve_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: 4 resources: mem=memory - # group: "solve" # with group, threads is ignored https://bitbucket.org/snakemake/snakemake/issues/971/group-job-description-does-not-contain + shadow: "shallow" script: "scripts/solve_network.py" + rule solve_operations_network: input: unprepared="networks/{network}_s{simpl}_{clusters}_ec.nc", optimized="results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" output: "results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc" - shadow: "shallow" log: solver=normpath("logs/solve_operations_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log"), python="logs/solve_operations_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log", @@ -316,9 +318,10 @@ rule solve_operations_network: benchmark: "benchmarks/solve_operations_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: 4 resources: mem=(lambda w: 5000 + 372 * int(w.clusters)) - # group: "solve_operations" + shadow: "shallow" script: "scripts/solve_operations_network.py" + rule plot_network: input: network="results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", @@ -329,6 +332,7 @@ rule plot_network: log: "logs/plot_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}_{ext}.log" script: "scripts/plot_network.py" + def input_make_summary(w): # It's mildly hacky to include the separate costs input as first entry if w.ll.endswith("all"): @@ -344,42 +348,48 @@ def input_make_summary(w): **{k: config["scenario"][k] if getattr(w, k) == "all" else getattr(w, k) for k in ["simpl", "clusters", "opts"]})) + rule make_summary: input: input_make_summary output: directory("results/summaries/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}") log: "logs/make_summary/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.log", script: "scripts/make_summary.py" + rule plot_summary: input: "results/summaries/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}" output: "results/plots/summary_{summary}_{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.{ext}" log: "logs/plot_summary/{summary}_{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}_{ext}.log" script: "scripts/plot_summary.py" -def input_plot_p_nom_max(wildcards): - return [('networks/{network}_s{simpl}{maybe_cluster}.nc' - .format(maybe_cluster=('' if c == 'full' else ('_' + c)), **wildcards)) - for c in wildcards.clusts.split(",")] + +def input_plot_p_nom_max(w): + return [("networks/{network}_s{simpl}{maybe_cluster}.nc" + .format(maybe_cluster=('' if c == 'full' else ('_' + c)), **w)) + for c in w.clusts.split(",")] + + rule plot_p_nom_max: input: input_plot_p_nom_max output: "results/plots/{network}_s{simpl}_cum_p_nom_max_{clusts}_{techs}_{country}.{ext}" log: "logs/plot_p_nom_max/{network}_s{simpl}_{clusts}_{techs}_{country}_{ext}.log" script: "scripts/plot_p_nom_max.py" + rule build_country_flh: input: base_network="networks/base.nc", corine="data/bundle/corine/g250_clc06_V18_5.tif", natura="resources/natura.tiff", - gebco=lambda wildcards: ("data/bundle/GEBCO_2014_2D.nc" - if "max_depth" in config["renewable"][wildcards.technology].keys() - else []), + gebco=lambda w: ("data/bundle/GEBCO_2014_2D.nc" + if "max_depth" in config["renewable"][w.technology].keys() + else []), country_shapes='resources/country_shapes.geojson', offshore_shapes='resources/offshore_shapes.geojson', pietzker="data/pietzker2014.xlsx", regions=lambda w: ("resources/country_shapes.geojson" - if w.technology in ('onwind', 'solar') - else "resources/offshore_shapes.geojson"), + if w.technology in ('onwind', 'solar') + else "resources/offshore_shapes.geojson"), cutout=lambda w: "cutouts/" + config["renewable"][w.technology]['cutout'] output: area="resources/country_flh_area_{technology}.csv", @@ -390,9 +400,4 @@ rule build_country_flh: log: "logs/build_country_flh_{technology}.log" resources: mem=10000 benchmark: "benchmarks/build_country_flh_{technology}" - # group: 'feedin_preparation' script: "scripts/build_country_flh.py" - -# Local Variables: -# mode: python -# End: diff --git a/cluster.yaml b/cluster.yaml deleted file mode 100644 index b36e6ed2..00000000 --- a/cluster.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-FileCopyrightText: : 2017-2020 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: GPL-3.0-or-later - -__default__: - log: "logs/cluster/{{name}}.log" - -feedin_preparation: - walltime: "12:00:00" - -solve_network: - walltime: "05:00:00:00" - -trace_solve_network: - walltime: "05:00:00:00" - -solve: - walltime: "05:00:00:00" - threads: 4 # Group threads are not aggregated - -solve_operations: - walltime: "01:00:00:00" diff --git a/config.default.yaml b/config.default.yaml index 375bcda6..d94d9842 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -12,7 +12,6 @@ logging: summary_dir: results scenario: - sectors: [E] simpl: [''] ll: ['copt'] clusters: [37, 128, 256, 512, 1024] @@ -257,67 +256,18 @@ plotting: 'waste' : '#68896b' 'geothermal' : '#ba91b1' "OCGT" : "#d35050" - "OCGT marginal" : "#d35050" - "OCGT-heat" : "#d35050" - "gas boiler" : "#d35050" - "gas boilers" : "#d35050" - "gas boiler marginal" : "#d35050" - "gas-to-power/heat" : "#d35050" "gas" : "#d35050" "natural gas" : "#d35050" "CCGT" : "#b20101" - "CCGT marginal" : "#b20101" - "Nuclear" : "#ff9000" - "Nuclear marginal" : "#ff9000" "nuclear" : "#ff9000" "coal" : "#707070" - "Coal" : "#707070" - "Coal marginal" : "#707070" "lignite" : "#9e5a01" - "Lignite" : "#9e5a01" - "Lignite marginal" : "#9e5a01" - "Oil" : "#262626" "oil" : "#262626" "H2" : "#ea048a" "hydrogen storage" : "#ea048a" - "Sabatier" : "#a31597" - "methanation" : "#a31597" - "helmeth" : "#a31597" - "DAC" : "#d284ff" - "co2 stored" : "#e5e5e5" - "CO2 sequestration" : "#e5e5e5" "battery" : "#b8ea04" - "battery storage" : "#b8ea04" - "Li ion" : "#b8ea04" - "BEV charger" : "#e2ff7c" - "V2G" : "#7a9618" - "transport fuel cell" : "#e884be" - "retrofitting" : "#e0d6a8" - "building retrofitting" : "#e0d6a8" - "heat pumps" : "#ff9768" - "heat pump" : "#ff9768" - "air heat pump" : "#ffbea0" - "ground heat pump" : "#ff7a3d" - "power-to-heat" : "#a59e7c" - "power-to-gas" : "#db8585" - "power-to-liquid" : "#a9acd1" - "Fischer-Tropsch" : "#a9acd1" - "resistive heater" : "#aa4925" - "water tanks" : "#401f75" - "hot water storage" : "#401f75" - "hot water charging" : "#351c5e" - "hot water discharging" : "#683ab2" - "CHP" : "#d80a56" - "CHP heat" : "#d80a56" - "CHP electric" : "#d80a56" - "district heating" : "#93864b" - "Ambient" : "#262626" "Electric load" : "#f9d002" "electricity" : "#f9d002" - "Heat load" : "#d35050" - "heat" : "#d35050" - "Transport load" : "#235ebc" - "transport" : "#235ebc" "lines" : "#70af1d" "transmission lines" : "#70af1d" "AC-AC" : "#70af1d" @@ -337,18 +287,5 @@ plotting: hydro: "Reservoir & Dam" battery: "Battery Storage" H2: "Hydrogen Storage" - lines: "Transmission lines" - ror: "Run of river" - nice_names_n: - OCGT: "Open-Cycle\nGas" - CCGT: "Combined-Cycle\nGas" - offwind-ac: "Offshore\nWind (AC)" - offwind-dc: "Offshore\nWind (DC)" - onwind: "Onshore\nWind" - battery: "Battery\nStorage" - H2: "Hydrogen\nStorage" - lines: "Transmission\nlines" - ror: "Run of\nriver" - PHS: "Pumped Hydro\nStorage" - hydro: "Reservoir\n& Dam" - + lines: "Transmission Lines" + ror: "Run of River" diff --git a/config.tutorial.yaml b/config.tutorial.yaml index f77ad2bd..7fda5daf 100755 --- a/config.tutorial.yaml +++ b/config.tutorial.yaml @@ -11,7 +11,6 @@ logging: summary_dir: results scenario: - sectors: [E] simpl: [''] ll: ['copt'] clusters: [5] @@ -169,164 +168,5 @@ solving: clip_p_max_pu: 0.01 skip_iterations: false track_iterations: false - #nhours: 10 solver: name: cbc - # solver: - # name: gurobi - # threads: 4 - # method: 2 # barrier - # crossover: 0 - # BarConvTol: 1.e-5 - # FeasibilityTol: 1.e-6 - # AggFill: 0 - # PreDual: 0 - # GURO_PAR_BARDENSETHRESH: 200 - # solver: - # name: cplex - # threads: 4 - # lpmethod: 4 # barrier - # solutiontype: 2 # non basic solution, ie no crossover - # barrier_convergetol: 1.e-5 - # feasopt_tolerance: 1.e-6 - -plotting: - map: - figsize: [7, 7] - boundaries: [-10.2, 29, 35, 72] - p_nom: - bus_size_factor: 5.e+4 - linewidth_factor: 3.e+3 - - costs_max: 800 - costs_threshold: 1 - - energy_max: 15000. - energy_min: -10000. - energy_threshold: 50. - - vre_techs: ["onwind", "offwind-ac", "offwind-dc", "solar", "ror"] - conv_techs: ["OCGT", "CCGT", "Nuclear", "Coal"] - storage_techs: ["hydro+PHS", "battery", "H2"] - load_carriers: ["AC load"] - AC_carriers: ["AC line", "AC transformer"] - link_carriers: ["DC line", "Converter AC-DC"] - tech_colors: - "onwind" : "#235ebc" - "onshore wind" : "#235ebc" - 'offwind' : "#6895dd" - 'offwind-ac' : "#6895dd" - 'offshore wind' : "#6895dd" - 'offshore wind ac' : "#6895dd" - 'offwind-dc' : "#74c6f2" - 'offshore wind dc' : "#74c6f2" - "hydro" : "#08ad97" - "hydro+PHS" : "#08ad97" - "PHS" : "#08ad97" - "hydro reservoir" : "#08ad97" - 'hydroelectricity' : '#08ad97' - "ror" : "#4adbc8" - "run of river" : "#4adbc8" - 'solar' : "#f9d002" - 'solar PV' : "#f9d002" - 'solar thermal' : '#ffef60' - 'biomass' : '#0c6013' - 'solid biomass' : '#06540d' - 'biogas' : '#23932d' - 'waste' : '#68896b' - 'geothermal' : '#ba91b1' - "OCGT" : "#d35050" - "OCGT marginal" : "#d35050" - "OCGT-heat" : "#d35050" - "gas boiler" : "#d35050" - "gas boilers" : "#d35050" - "gas boiler marginal" : "#d35050" - "gas-to-power/heat" : "#d35050" - "gas" : "#d35050" - "natural gas" : "#d35050" - "CCGT" : "#b20101" - "CCGT marginal" : "#b20101" - "Nuclear" : "#ff9000" - "Nuclear marginal" : "#ff9000" - "nuclear" : "#ff9000" - "coal" : "#707070" - "Coal" : "#707070" - "Coal marginal" : "#707070" - "lignite" : "#9e5a01" - "Lignite" : "#9e5a01" - "Lignite marginal" : "#9e5a01" - "Oil" : "#262626" - "oil" : "#262626" - "H2" : "#ea048a" - "hydrogen storage" : "#ea048a" - "Sabatier" : "#a31597" - "methanation" : "#a31597" - "helmeth" : "#a31597" - "DAC" : "#d284ff" - "co2 stored" : "#e5e5e5" - "CO2 sequestration" : "#e5e5e5" - "battery" : "#b8ea04" - "battery storage" : "#b8ea04" - "Li ion" : "#b8ea04" - "BEV charger" : "#e2ff7c" - "V2G" : "#7a9618" - "transport fuel cell" : "#e884be" - "retrofitting" : "#e0d6a8" - "building retrofitting" : "#e0d6a8" - "heat pumps" : "#ff9768" - "heat pump" : "#ff9768" - "air heat pump" : "#ffbea0" - "ground heat pump" : "#ff7a3d" - "power-to-heat" : "#a59e7c" - "power-to-gas" : "#db8585" - "power-to-liquid" : "#a9acd1" - "Fischer-Tropsch" : "#a9acd1" - "resistive heater" : "#aa4925" - "water tanks" : "#401f75" - "hot water storage" : "#401f75" - "hot water charging" : "#351c5e" - "hot water discharging" : "#683ab2" - "CHP" : "#d80a56" - "CHP heat" : "#d80a56" - "CHP electric" : "#d80a56" - "district heating" : "#93864b" - "Ambient" : "#262626" - "Electric load" : "#f9d002" - "electricity" : "#f9d002" - "Heat load" : "#d35050" - "heat" : "#d35050" - "Transport load" : "#235ebc" - "transport" : "#235ebc" - "lines" : "#70af1d" - "transmission lines" : "#70af1d" - "AC-AC" : "#70af1d" - "AC line" : "#70af1d" - "links" : "#8a1caf" - "HVDC links" : "#8a1caf" - "DC-DC" : "#8a1caf" - "DC link" : "#8a1caf" - 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" - nice_names_n: - OCGT: "Open-Cycle\nGas" - CCGT: "Combined-Cycle\nGas" - offwind-ac: "Offshore\nWind (AC)" - offwind-dc: "Offshore\nWind (DC)" - onwind: "Onshore\nWind" - battery: "Battery\nStorage" - H2: "Hydrogen\nStorage" - lines: "Transmission\nlines" - ror: "Run of\nriver" - PHS: "Pumped Hydro\nStorage" - hydro: "Reservoir\n& Dam" diff --git a/doc/configtables/plotting.csv b/doc/configtables/plotting.csv index 0f21c9a8..754f2e83 100644 --- a/doc/configtables/plotting.csv +++ b/doc/configtables/plotting.csv @@ -11,5 +11,4 @@ energy_max,TWh,float,"Upper y-axis limit in energy bar plots." energy_min,TWh,float,"Lower y-axis limit in energy bar plots." energy_threshold,TWh,float,"Threshold below which technologies will not be shown in energy bar plots." tech_colors,--,"carrier -> HEX colour code","Mapping from network ``carrier`` to a colour (`HEX colour code `_)." -nice_names,--,"str -> str","Mapping from network ``carrier`` to a more readable name." -nice_names_n,--,"str -> str","Same as nice_names, but with linebreaks." \ No newline at end of file +nice_names,--,"str -> str","Mapping from network ``carrier`` to a more readable name." \ No newline at end of file diff --git a/doc/configtables/scenario.csv b/doc/configtables/scenario.csv index 52dafa56..7a2d3bcd 100644 --- a/doc/configtables/scenario.csv +++ b/doc/configtables/scenario.csv @@ -1,6 +1,5 @@ ,Unit,Values,Description -sectors,--,"Must be 'elec'","Placeholder for integration of other energy sectors." simpl,--,cf. :ref:`simpl`,"List of ``{simpl}`` wildcards to run." -ll,--,cf. :ref:`ll`,"List of ``{ll}`` wildcards to run." clusters,--,cf. :ref:`clusters`,"List of ``{clusters}`` wildcards to run." +ll,--,cf. :ref:`ll`,"List of ``{ll}`` wildcards to run." opts,--,cf. :ref:`opts`,"List of ``{opts}`` wildcards to run." \ No newline at end of file diff --git a/doc/index.rst b/doc/index.rst index bd2ec5f2..d375cfac 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -194,10 +194,10 @@ Licence PyPSA-Eur work is released under multiple licenses: -* All original source code is licensed as free software under `GPL-3.0-or-later `_. -* The documentation is licensed under `CC-BY-4.0 `_. -* Configuration files are mostly licensed under `CC0-1.0 `_. -* Data files are licensed under `CC-BY-4.0 `_. +* All original source code is licensed as free software under `GPL-3.0-or-later <.licenses/GPL-3.0-or-later.txt>`_. +* The documentation is licensed under `CC-BY-4.0 <.licenses/CC-BY-4.0.txt>`_. +* Configuration files are mostly licensed under `CC0-1.0 <.licenses/CC0-1.0.txt>`_. +* Data files are licensed under `CC-BY-4.0 <.licenses/CC-BY-4.0.txt>`_. See the individual files and the `dep5 <.reuse/dep5>`_ file for license details. diff --git a/doc/wildcards.rst b/doc/wildcards.rst index 9f1c2248..a180d04b 100644 --- a/doc/wildcards.rst +++ b/doc/wildcards.rst @@ -18,16 +18,6 @@ what data to retrieve and what files to produce. Detailed explanations of how wildcards work in ``snakemake`` can be found in the `relevant section of the documentation `_. -.. _network: - -The ``{network}`` wildcard -========================== - -The ``{network}`` wildcard specifies the considered energy sector(s) -and, as currently only ``elec`` (for electricity) is included, -it currently represents rather a placeholder wildcard to facilitate -future extensions including multiple energy sectors at once. - .. _simpl: The ``{simpl}`` wildcard diff --git a/matplotlibrc b/matplotlibrc deleted file mode 100644 index 13468274..00000000 --- a/matplotlibrc +++ /dev/null @@ -1 +0,0 @@ -backend : Agg diff --git a/scripts/_helpers.py b/scripts/_helpers.py index fff8143d..e0e16d20 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -44,6 +44,7 @@ def configure_logging(snakemake, skip_handlers=False): }) logging.basicConfig(**kwargs) + def load_network(import_name=None, custom_components=None): """ Helper for importing a pypsa.Network with additional custom components. @@ -70,7 +71,6 @@ def load_network(import_name=None, custom_components=None): ------- pypsa.Network """ - import pypsa from pypsa.descriptors import Dict @@ -90,10 +90,12 @@ def load_network(import_name=None, custom_components=None): override_components=override_components, override_component_attrs=override_component_attrs) + def pdbcast(v, h): return pd.DataFrame(v.values.reshape((-1, 1)) * h.values, index=v.index, columns=h.index) + def load_network_for_plots(fn, tech_costs, config, combine_hydro_ps=True): import pypsa from add_electricity import update_transmission_costs, load_costs @@ -113,11 +115,11 @@ def load_network_for_plots(fn, tech_costs, config, combine_hydro_ps=True): if combine_hydro_ps: n.storage_units.loc[n.storage_units.carrier.isin({'PHS', 'hydro'}), 'carrier'] = 'hydro+PHS' - # #if the carrier was not set on the heat storage units + # if the carrier was not set on the heat storage units # bus_carrier = n.storage_units.bus.map(n.buses.carrier) # n.storage_units.loc[bus_carrier == "heat","carrier"] = "water tanks" - Nyears = n.snapshot_weightings.sum()/8760. + Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears, tech_costs, config['costs'], config['electricity']) update_transmission_costs(n, costs) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 7a32e628..14667679 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -90,26 +90,28 @@ It further adds extendable ``generators`` with **zero** capacity for - additional open- and combined-cycle gas turbines (if ``OCGT`` and/or ``CCGT`` is listed in the config setting ``electricity: extendable_carriers``) """ -from vresutils.costdata import annuity -from vresutils.load import timeseries_opsd -from vresutils import transfer as vtransfer - import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging +import pypsa import pandas as pd import numpy as np import xarray as xr import geopandas as gpd -import pypsa import powerplantmatching as ppm +from vresutils.costdata import annuity +from vresutils.load import timeseries_opsd +from vresutils import transfer as vtransfer + idx = pd.IndexSlice +logger = logging.getLogger(__name__) + def normed(s): return s/s.sum() + def _add_missing_carriers_from_costs(n, costs, carriers): missing_carriers = pd.Index(carriers).difference(n.carriers.index) if missing_carriers.empty: return @@ -121,6 +123,7 @@ def _add_missing_carriers_from_costs(n, costs, carriers): emissions.index = missing_carriers n.import_components_from_dataframe(emissions, 'Carrier') + def load_costs(Nyears=1., tech_costs=None, config=None, elec_config=None): if tech_costs is None: tech_costs = snakemake.input.tech_costs @@ -193,10 +196,11 @@ def load_costs(Nyears=1., tech_costs=None, config=None, elec_config=None): return costs + def load_powerplants(ppl_fn=None): if ppl_fn is None: ppl_fn = snakemake.input.powerplants - carrier_dict = {'ocgt': 'OCGT', 'ccgt': 'CCGT', 'bioenergy':'biomass', + carrier_dict = {'ocgt': 'OCGT', 'ccgt': 'CCGT', 'bioenergy': 'biomass', 'ccgt, thermal': 'CCGT', 'hard coal': 'coal'} return (pd.read_csv(ppl_fn, index_col=0, dtype={'bus': 'str'}) .powerplant.to_pypsa_names() @@ -204,12 +208,6 @@ def load_powerplants(ppl_fn=None): .replace({'carrier': carrier_dict})) -# ============================================================================= -# Attach components -# ============================================================================= - -# ### Load - def attach_load(n): substation_lv_i = n.buses.index[n.buses['substation_lv']] regions = (gpd.read_file(snakemake.input.regions).set_index('name') @@ -249,7 +247,6 @@ def attach_load(n): n.madd("Load", substation_lv_i, bus=substation_lv_i, p_set=load) -### Set line costs def update_transmission_costs(n, costs, length_factor=1.0, simple_hvdc_costs=False): n.lines['capital_cost'] = (n.lines['length'] * length_factor * @@ -270,7 +267,6 @@ def update_transmission_costs(n, costs, length_factor=1.0, simple_hvdc_costs=Fal costs.at['HVDC inverter pair', 'capital_cost']) n.links.loc[dc_b, 'capital_cost'] = costs -### Generators def attach_wind_and_solar(n, costs): for tech in snakemake.config['renewable']: @@ -309,15 +305,17 @@ def attach_wind_and_solar(n, costs): p_max_pu=ds['profile'].transpose('time', 'bus').to_pandas()) - def attach_conventional_generators(n, costs, ppl): carriers = snakemake.config['electricity']['conventional_carriers'] + _add_missing_carriers_from_costs(n, costs, carriers) + ppl = (ppl.query('carrier in @carriers').join(costs, on='carrier') .rename(index=lambda s: 'C' + str(s))) logger.info('Adding {} generators with capacities\n{}' .format(len(ppl), ppl.groupby('carrier').p_nom.sum())) + n.madd("Generator", ppl.index, carrier=ppl.carrier, bus=ppl.bus, @@ -325,6 +323,7 @@ def attach_conventional_generators(n, costs, ppl): efficiency=ppl.efficiency, marginal_cost=ppl.marginal_cost, capital_cost=0) + logger.warning(f'Capital costs for conventional generators put to 0 EUR/MW.') @@ -374,8 +373,8 @@ def attach_hydro(n, costs, ppl): .where(lambda df: df<=1., other=1.))) if 'PHS' in carriers and not phs.empty: - # fill missing max hours to config value and assume no natural inflow - # due to lack of data + # fill missing max hours to config value and + # assume no natural inflow due to lack of data phs = phs.replace({'max_hours': {0: c['PHS_max_hours']}}) n.madd('StorageUnit', phs.index, carrier='PHS', @@ -413,7 +412,6 @@ def attach_hydro(n, costs, ppl): hydro_max_hours = hydro.max_hours.where(hydro.max_hours > 0, hydro.country.map(max_hours_country)).fillna(6) - n.madd('StorageUnit', hydro.index, carrier='hydro', bus=hydro['bus'], p_nom=hydro['p_nom'], @@ -432,6 +430,7 @@ def attach_hydro(n, costs, ppl): def attach_extendable_generators(n, costs, ppl): elec_opts = snakemake.config['electricity'] carriers = pd.Index(elec_opts['extendable_carriers']['Generator']) + _add_missing_carriers_from_costs(n, costs, carriers) for tech in carriers: @@ -497,10 +496,11 @@ def estimate_renewable_capacities(n, tech_map=None): n.generators.loc[tech_i, 'p_nom'] = ( (n.generators_t.p_max_pu[tech_i].mean() * n.generators.loc[tech_i, 'p_nom_max']) # maximal yearly generation - .groupby(n.generators.bus.map(n.buses.country)) # for each country + .groupby(n.generators.bus.map(n.buses.country)) .transform(lambda s: normed(s) * tech_capacities.at[s.name]) .where(lambda s: s>0.1, 0.)) # only capacities above 100kW + def add_nice_carrier_names(n, config=None): if config is None: config = snakemake.config carrier_i = n.carriers.index @@ -522,7 +522,7 @@ if __name__ == "__main__": configure_logging(snakemake) n = pypsa.Network(snakemake.input.base_network) - Nyears = n.snapshot_weightings.sum()/8760. + Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears) ppl = load_powerplants() diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index 219c082d..d0b627a3 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -50,17 +50,20 @@ The rule :mod:`add_extra_components` attaches additional extendable components t - ``Stores`` of carrier 'H2' and/or 'battery' in combination with ``Links``. If this option is chosen, the script adds extra buses with corresponding carrier where energy ``Stores`` are attached and which are connected to the corresponding power buses via two links, one each for charging and discharging. This leads to three investment variables for the energy capacity, charging and discharging capacity of the storage unit. """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging +import pypsa import pandas as pd import numpy as np -import pypsa + from add_electricity import (load_costs, add_nice_carrier_names, _add_missing_carriers_from_costs) idx = pd.IndexSlice +logger = logging.getLogger(__name__) + + def attach_storageunits(n, costs): elec_opts = snakemake.config['electricity'] carriers = elec_opts['extendable_carriers']['StorageUnit'] @@ -82,6 +85,7 @@ def attach_storageunits(n, costs): max_hours=max_hours[carrier], cyclic_state_of_charge=True) + def attach_stores(n, costs): elec_opts = snakemake.config['electricity'] carriers = elec_opts['extendable_carriers']['Store'] @@ -144,6 +148,7 @@ def attach_stores(n, costs): capital_cost=costs.at['battery inverter', 'capital_cost'], p_nom_extendable=True) + def attach_hydrogen_pipelines(n, costs): elec_opts = snakemake.config['electricity'] ext_carriers = elec_opts['extendable_carriers'] @@ -176,6 +181,7 @@ def attach_hydrogen_pipelines(n, costs): efficiency=costs.at['H2 pipeline','efficiency'], carrier="H2 pipeline") + if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake @@ -184,7 +190,7 @@ if __name__ == "__main__": configure_logging(snakemake) n = pypsa.Network(snakemake.input.network) - Nyears = n.snapshot_weightings.sum()/8760. + Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears, tech_costs=snakemake.input.tech_costs, config=snakemake.config['costs'], elec_config=snakemake.config['electricity']) diff --git a/scripts/base_network.py b/scripts/base_network.py index 1d5fddd7..034eeb2f 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -63,14 +63,16 @@ Description """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging +import pypsa import yaml import pandas as pd import geopandas as gpd import numpy as np import scipy as sp +import networkx as nx + from scipy.sparse import csgraph from six import iteritems from itertools import product @@ -78,9 +80,8 @@ from itertools import product from shapely.geometry import Point, LineString import shapely, shapely.prepared, shapely.wkt -import networkx as nx +logger = logging.getLogger(__name__) -import pypsa def _get_oid(df): if "tags" in df.columns: @@ -88,12 +89,14 @@ def _get_oid(df): else: return pd.Series(np.nan, df.index) + def _get_country(df): if "tags" in df.columns: return df.tags.str.extract('"country"=>"([A-Z]{2})"', expand=False) else: return pd.Series(np.nan, df.index) + def _find_closest_links(links, new_links, distance_upper_bound=1.5): treecoords = np.asarray([np.asarray(shapely.wkt.loads(s))[[0, -1]].flatten() for s in links.geometry]) @@ -109,6 +112,7 @@ def _find_closest_links(links, new_links, distance_upper_bound=1.5): [lambda ds: ~ds.index.duplicated(keep='first')]\ .sort_index()['i'] + def _load_buses_from_eg(): buses = (pd.read_csv(snakemake.input.eg_buses, quotechar="'", true_values='t', false_values='f', @@ -130,6 +134,7 @@ def _load_buses_from_eg(): return pd.DataFrame(buses.loc[buses_in_europe_b & buses_with_v_nom_to_keep_b]) + def _load_transformers_from_eg(buses): transformers = (pd.read_csv(snakemake.input.eg_transformers, quotechar="'", true_values='t', false_values='f', @@ -140,6 +145,7 @@ def _load_transformers_from_eg(buses): return transformers + def _load_converters_from_eg(buses): converters = (pd.read_csv(snakemake.input.eg_converters, quotechar="'", true_values='t', false_values='f', @@ -241,6 +247,7 @@ def _add_links_from_tyndp(buses, links): return buses, links.append(links_tyndp, sort=True) + def _load_lines_from_eg(buses): lines = (pd.read_csv(snakemake.input.eg_lines, quotechar="'", true_values='t', false_values='f', dtype=dict(line_id='str', bus0='str', bus1='str', @@ -254,11 +261,13 @@ def _load_lines_from_eg(buses): return lines + def _apply_parameter_corrections(n): with open(snakemake.input.parameter_corrections) as f: corrections = yaml.safe_load(f) if corrections is None: return + for component, attrs in iteritems(corrections): df = n.df(component) oid = _get_oid(df) @@ -275,6 +284,7 @@ def _apply_parameter_corrections(n): inds = r.index.intersection(df.index) df.loc[inds, attr] = r[inds].astype(df[attr].dtype) + def _set_electrical_parameters_lines(lines): v_noms = snakemake.config['electricity']['voltages'] linetypes = snakemake.config['lines']['types'] @@ -286,12 +296,14 @@ def _set_electrical_parameters_lines(lines): return lines + def _set_lines_s_nom_from_linetypes(n): n.lines['s_nom'] = ( np.sqrt(3) * n.lines['type'].map(n.line_types.i_nom) * n.lines['v_nom'] * n.lines.num_parallel ) + def _set_electrical_parameters_links(links): if links.empty: return links @@ -301,11 +313,11 @@ def _set_electrical_parameters_links(links): links_p_nom = pd.read_csv(snakemake.input.links_p_nom) - #Filter links that are not in operation anymore + # filter links that are not in operation anymore removed_b = links_p_nom.Remarks.str.contains('Shut down|Replaced', na=False) links_p_nom = links_p_nom[~removed_b] - #find closest link for all links in links_p_nom + # find closest link for all links in links_p_nom links_p_nom['j'] = _find_closest_links(links, links_p_nom) links_p_nom = links_p_nom.groupby(['j'],as_index=False).agg({'Power (MW)': 'sum'}) @@ -318,6 +330,7 @@ def _set_electrical_parameters_links(links): return links + def _set_electrical_parameters_converters(converters): p_max_pu = snakemake.config['links'].get('p_max_pu', 1.) converters['p_max_pu'] = p_max_pu @@ -331,6 +344,7 @@ def _set_electrical_parameters_converters(converters): return converters + def _set_electrical_parameters_transformers(transformers): config = snakemake.config['transformers'] @@ -341,9 +355,11 @@ def _set_electrical_parameters_transformers(transformers): return transformers + def _remove_dangling_branches(branches, buses): return pd.DataFrame(branches.loc[branches.bus0.isin(buses.index) & branches.bus1.isin(buses.index)]) + def _remove_unconnected_components(network): _, labels = csgraph.connected_components(network.adjacency_matrix(), directed=False) component = pd.Series(labels, index=network.buses.index) @@ -356,6 +372,7 @@ def _remove_unconnected_components(network): return network[component == component_sizes.index[0]] + def _set_countries_and_substations(n): buses = n.buses @@ -442,6 +459,7 @@ def _set_countries_and_substations(n): return buses + def _replace_b2b_converter_at_country_border_by_link(n): # Affects only the B2B converter in Lithuania at the Polish border at the moment buscntry = n.buses.country @@ -479,6 +497,7 @@ def _replace_b2b_converter_at_country_border_by_link(n): logger.info("Replacing B2B converter `{}` together with bus `{}` and line `{}` by an HVDC tie-line {}-{}" .format(i, b0, line, linkcntry.at[i], buscntry.at[b1])) + def _set_links_underwater_fraction(n): if n.links.empty: return @@ -489,6 +508,7 @@ def _set_links_underwater_fraction(n): links = gpd.GeoSeries(n.links.geometry.dropna().map(shapely.wkt.loads)) n.links['underwater_fraction'] = links.intersection(offshore_shape).length / links.length + def _adjust_capacities_of_under_construction_branches(n): lines_mode = snakemake.config['lines'].get('under_construction', 'undef') if lines_mode == 'zero': @@ -513,6 +533,7 @@ def _adjust_capacities_of_under_construction_branches(n): return n + def base_network(): buses = _load_buses_from_eg() @@ -534,7 +555,7 @@ def base_network(): n.name = 'PyPSA-Eur' n.set_snapshots(pd.date_range(freq='h', **snakemake.config['snapshots'])) - n.snapshot_weightings[:] *= 8760./n.snapshot_weightings.sum() + n.snapshot_weightings[:] *= 8760. / n.snapshot_weightings.sum() n.import_components_from_dataframe(buses, "Bus") n.import_components_from_dataframe(lines, "Line") @@ -565,4 +586,5 @@ if __name__ == "__main__": configure_logging(snakemake) n = base_network() + n.export_to_netcdf(snakemake.output[0]) diff --git a/scripts/build_bus_regions.py b/scripts/build_bus_regions.py index ce012c39..87890d92 100644 --- a/scripts/build_bus_regions.py +++ b/scripts/build_bus_regions.py @@ -42,17 +42,24 @@ Description """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging -from vresutils.graph import voronoi_partition_pts - +import pypsa import os - import pandas as pd import geopandas as gpd -import pypsa +from vresutils.graph import voronoi_partition_pts + +logger = logging.getLogger(__name__) + + +def save_to_geojson(s, fn): + if os.path.exists(fn): + os.unlink(fn) + schema = {**gpd.io.file.infer_schema(s), 'geometry': 'Unknown'} + s.to_file(fn, driver='GeoJSON', schema=schema) + if __name__ == "__main__": if 'snakemake' not in globals(): @@ -96,12 +103,6 @@ if __name__ == "__main__": offshore_regions_c = offshore_regions_c.loc[offshore_regions_c.area > 1e-2] offshore_regions.append(offshore_regions_c) - def save_to_geojson(s, fn): - if os.path.exists(fn): - os.unlink(fn) - schema = {**gpd.io.file.infer_schema(s), 'geometry': 'Unknown'} - s.to_file(fn, driver='GeoJSON', schema=schema) - save_to_geojson(pd.concat(onshore_regions, ignore_index=True), snakemake.output.regions_onshore) save_to_geojson(pd.concat(offshore_regions, ignore_index=True), snakemake.output.regions_offshore) diff --git a/scripts/build_country_flh.py b/scripts/build_country_flh.py index 2fb8a173..459b8f38 100644 --- a/scripts/build_country_flh.py +++ b/scripts/build_country_flh.py @@ -63,7 +63,6 @@ Description """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging import os @@ -84,6 +83,9 @@ import progressbar as pgb from build_renewable_profiles import init_globals, calculate_potential +logger = logging.getLogger(__name__) + + def build_area(flh, countries, areamatrix, breaks, fn): area_unbinned = xr.DataArray(areamatrix.todense(), [countries, capacity_factor.coords['spatial']]) bins = xr.DataArray(pd.cut(flh.to_series(), bins=breaks), flh.coords, name="bins") @@ -92,6 +94,7 @@ def build_area(flh, countries, areamatrix, breaks, fn): area.columns = area.columns.map(lambda s: s.left) return area + def plot_area_not_solar(area, countries): # onshore wind/offshore wind a = area.T diff --git a/scripts/build_cutout.py b/scripts/build_cutout.py index b6fc6761..1e55faf5 100644 --- a/scripts/build_cutout.py +++ b/scripts/build_cutout.py @@ -92,12 +92,13 @@ Description """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging import os import atlite +logger = logging.getLogger(__name__) + if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake @@ -113,4 +114,6 @@ if __name__ == "__main__": cutout_dir=os.path.dirname(snakemake.output[0]), **cutout_params) - cutout.prepare(nprocesses=snakemake.config['atlite'].get('nprocesses', 4)) + nprocesses = snakemake.config['atlite'].get('nprocesses', 4) + + cutout.prepare(nprocesses=nprocesses) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 0736511a..339fccaf 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -60,7 +60,6 @@ Description """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging import os @@ -68,6 +67,8 @@ import atlite import geopandas as gpd from vresutils import hydro as vhydro +logger = logging.getLogger(__name__) + if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake @@ -75,8 +76,8 @@ if __name__ == "__main__": configure_logging(snakemake) config = snakemake.config['renewable']['hydro'] - cutout = atlite.Cutout(config['cutout'], - cutout_dir=os.path.dirname(snakemake.input.cutout)) + cutout_dir = os.path.dirname(snakemake.input.cutout) + cutout = atlite.Cutout(config['cutout'], cutout_dir=cutout_dir) countries = snakemake.config['countries'] country_shapes = gpd.read_file(snakemake.input.country_shapes).set_index('name')['geometry'].reindex(countries) @@ -84,9 +85,9 @@ if __name__ == "__main__": eia_stats = vhydro.get_eia_annual_hydro_generation(snakemake.input.eia_hydro_generation).reindex(columns=countries) inflow = cutout.runoff(shapes=country_shapes, - smooth=True, - lower_threshold_quantile=True, - normalize_using_yearly=eia_stats) + smooth=True, + lower_threshold_quantile=True, + normalize_using_yearly=eia_stats) if 'clip_min_inflow' in config: inflow.values[inflow.values < config['clip_min_inflow']] = 0. diff --git a/scripts/build_natura_raster.py b/scripts/build_natura_raster.py index f2ee491b..39667ca0 100644 --- a/scripts/build_natura_raster.py +++ b/scripts/build_natura_raster.py @@ -41,6 +41,7 @@ Description import logging from _helpers import configure_logging + import atlite import geokit as gk from pathlib import Path @@ -58,7 +59,7 @@ def determine_cutout_xXyY(cutout_name): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('build_natura_raster') #has to be enabled + snakemake = mock_snakemake('build_natura_raster') configure_logging(snakemake) cutout_dir = Path(snakemake.input.cutouts[0]).parent.resolve() diff --git a/scripts/build_powerplants.py b/scripts/build_powerplants.py index 67bdaeb9..8b329469 100755 --- a/scripts/build_powerplants.py +++ b/scripts/build_powerplants.py @@ -72,16 +72,18 @@ The configuration options ``electricity: powerplants_filter`` and ``electricity: """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging -from scipy.spatial import cKDTree as KDTree - import pypsa import powerplantmatching as pm import pandas as pd import numpy as np +from scipy.spatial import cKDTree as KDTree + +logger = logging.getLogger(__name__) + + def add_custom_powerplants(ppl): custom_ppl_query = snakemake.config['electricity']['custom_powerplants'] if not custom_ppl_query: @@ -94,7 +96,6 @@ def add_custom_powerplants(ppl): if __name__ == "__main__": - if 'snakemake' not in globals(): from _helpers import mock_snakemake snakemake = mock_snakemake('build_powerplants') diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 6578fd75..71adb66e 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -181,27 +181,28 @@ node (`p_nom_max`): ``simple`` and ``conservative``: """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging -import matplotlib.pyplot as plt - import os import atlite + import numpy as np import xarray as xr import pandas as pd import multiprocessing as mp +import matplotlib.pyplot as plt +import progressbar as pgb from scipy.sparse import csr_matrix, vstack - from pypsa.geo import haversine from vresutils import landuse as vlanduse from vresutils.array import spdiag -import progressbar as pgb +logger = logging.getLogger(__name__) bounds = dx = dy = config = paths = gebco = clc = natura = None + + def init_globals(bounds_xXyY, n_dx, n_dy, n_config, n_paths): # Late import so that the GDAL Context is only created in the new processes global gl, gk, gdal @@ -227,6 +228,7 @@ def init_globals(bounds_xXyY, n_dx, n_dy, n_config, n_paths): natura = gk.raster.loadRaster(paths["natura"]) + def downsample_to_coarse_grid(bounds, dx, dy, mask, data): # The GDAL warp function with the 'average' resample algorithm needs a band of zero values of at least # the size of one coarse cell around the original raster or it produces erroneous results @@ -238,6 +240,7 @@ def downsample_to_coarse_grid(bounds, dx, dy, mask, data): assert gdal.Warp(average, padded, resampleAlg='average') == 1, "gdal warp failed: %s" % gdal.GetLastErrorMsg() return average + def calculate_potential(gid, save_map=None): feature = gk.vector.extractFeature(paths["regions"], where=gid) ec = gl.ExclusionCalculator(feature.geom) diff --git a/scripts/build_shapes.py b/scripts/build_shapes.py index 1d6fc5e1..2651837b 100644 --- a/scripts/build_shapes.py +++ b/scripts/build_shapes.py @@ -92,6 +92,7 @@ def _get_country(target, **keys): except (KeyError, AttributeError): return np.nan + def _simplify_polys(polys, minarea=0.1, tolerance=0.01, filterremote=True): if isinstance(polys, MultiPolygon): polys = sorted(polys, key=attrgetter('area'), reverse=True) @@ -105,6 +106,7 @@ def _simplify_polys(polys, minarea=0.1, tolerance=0.01, filterremote=True): polys = mainpoly return polys.simplify(tolerance=tolerance) + def countries(): cntries = snakemake.config['countries'] if 'RS' in cntries: cntries.append('KV') @@ -121,6 +123,7 @@ def countries(): return s + def eez(country_shapes): df = gpd.read_file(snakemake.input.eez) df = df.loc[df['ISO_3digit'].isin([_get_country('alpha_3', alpha_2=c) for c in snakemake.config['countries']])] @@ -130,6 +133,7 @@ def eez(country_shapes): s.index.name = "name" return s + def country_cover(country_shapes, eez_shapes=None): shapes = list(country_shapes) if eez_shapes is not None: @@ -140,6 +144,7 @@ def country_cover(country_shapes, eez_shapes=None): europe_shape = max(europe_shape, key=attrgetter('area')) return Polygon(shell=europe_shape.exterior) + def nuts3(country_shapes): df = gpd.read_file(snakemake.input.nuts3) df = df.loc[df['STAT_LEVL_'] == 3] @@ -158,7 +163,6 @@ def nuts3(country_shapes): .applymap(lambda x: pd.to_numeric(x, errors='coerce')) .fillna(method='bfill', axis=1))['2014'] - # Swiss data cantons = pd.read_csv(snakemake.input.ch_cantons) cantons = cantons.set_index(cantons['HASC'].str[3:])['NUTS'] cantons = cantons.str.pad(5, side='right', fillchar='0') @@ -197,6 +201,7 @@ def nuts3(country_shapes): return df + def save_to_geojson(df, fn): if os.path.exists(fn): os.unlink(fn) @@ -206,20 +211,23 @@ def save_to_geojson(df, fn): schema = {**gpd.io.file.infer_schema(df), 'geometry': 'Unknown'} df.to_file(fn, driver='GeoJSON', schema=schema) + if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake snakemake = mock_snakemake('build_shapes') configure_logging(snakemake) + out = snakemake.output + country_shapes = countries() - save_to_geojson(country_shapes, snakemake.output.country_shapes) + save_to_geojson(country_shapes, out.country_shapes) offshore_shapes = eez(country_shapes) - save_to_geojson(offshore_shapes, snakemake.output.offshore_shapes) + save_to_geojson(offshore_shapes, out.offshore_shapes) europe_shape = country_cover(country_shapes, offshore_shapes) - save_to_geojson(gpd.GeoSeries(europe_shape), snakemake.output.europe_shape) + save_to_geojson(gpd.GeoSeries(europe_shape), out.europe_shape) nuts3_shapes = nuts3(country_shapes) - save_to_geojson(nuts3_shapes, snakemake.output.nuts3_shapes) + save_to_geojson(nuts3_shapes, out.nuts3_shapes) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index ff85bcf3..2c384926 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -120,31 +120,33 @@ Exemplary unsolved network clustered to 37 nodes: """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging -import pandas as pd -idx = pd.IndexSlice - +import pypsa import os +import shapely + +import pandas as pd import numpy as np import geopandas as gpd -import shapely +import pyomo.environ as po import matplotlib.pyplot as plt import seaborn as sns from six.moves import reduce -import pyomo.environ as po - -import pypsa from pypsa.networkclustering import (busmap_by_kmeans, busmap_by_spectral_clustering, _make_consense, get_clustering_from_busmap) from add_electricity import load_costs -def normed(x): - return (x/x.sum()).fillna(0.) +idx = pd.IndexSlice + +logger = logging.getLogger(__name__) + + +def normed(x): return (x/x.sum()).fillna(0.) + def weighting_for_country(n, x): conv_carriers = {'OCGT','CCGT','PHS', 'hydro'} @@ -162,22 +164,13 @@ def weighting_for_country(n, x): g = normed(gen.reindex(b_i, fill_value=0)) l = normed(load.reindex(b_i, fill_value=0)) - w= g + l + w = g + l return (w * (100. / w.max())).clip(lower=1.).astype(int) -## Plot weighting for Germany - -def plot_weighting(n, country, country_shape=None): - n.plot(bus_sizes=(2*weighting_for_country(n.buses.loc[n.buses.country == country])).reindex(n.buses.index, fill_value=1)) - if country_shape is not None: - plt.xlim(country_shape.bounds[0], country_shape.bounds[2]) - plt.ylim(country_shape.bounds[1], country_shape.bounds[3]) - - -# # Determining the number of clusters per country - def distribute_clusters(n, n_clusters, focus_weights=None, solver_name=None): + """Determine the number of clusters per country""" + if solver_name is None: solver_name = snakemake.config['solving']['solver']['name'] @@ -189,7 +182,7 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name=None): N = n.buses.groupby(['country', 'sub_network']).size() assert n_clusters >= len(N) and n_clusters <= N.sum(), \ - "Number of clusters must be {} <= n_clusters <= {} for this selection of countries.".format(len(N), N.sum()) + f"Number of clusters must be {len(N)} <= n_clusters <= {N.sum()} for this selection of countries." if focus_weights is not None: @@ -205,7 +198,7 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name=None): logger.warning('Using custom focus weights for determining number of clusters.') - assert np.isclose(L.sum(), 1.0, rtol=1e-3), "Country weights L must sum up to 1.0 when distributing clusters. Is {}.".format(L.sum()) + assert np.isclose(L.sum(), 1.0, rtol=1e-3), f"Country weights L must sum up to 1.0 when distributing clusters. Is {L.sum()}." m = po.ConcreteModel() def n_bounds(model, *n_id): @@ -221,10 +214,11 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name=None): opt = po.SolverFactory('ipopt') results = opt.solve(m) - assert results['Solver'][0]['Status'] == 'ok', "Solver returned non-optimally: {}".format(results) + assert results['Solver'][0]['Status'] == 'ok', f"Solver returned non-optimally: {results}" return pd.Series(m.n.get_values(), index=L.index).astype(int) + def busmap_for_n_clusters(n, n_clusters, solver_name, focus_weights=None, algorithm="kmeans", **algorithm_kwds): if algorithm == "kmeans": algorithm_kwds.setdefault('n_init', 1000) @@ -243,7 +237,7 @@ def busmap_for_n_clusters(n, n_clusters, solver_name, focus_weights=None, algori def busmap_for_country(x): prefix = x.name[0] + x.name[1] + ' ' - logger.debug("Determining busmap for country {}".format(prefix[:-1])) + logger.debug(f"Determining busmap for country {prefix[:-1]}") if len(x) == 1: return pd.Series(prefix + '0', index=x.index) weight = weighting_for_country(n, x) @@ -260,12 +254,6 @@ def busmap_for_n_clusters(n, n_clusters, solver_name, focus_weights=None, algori return (n.buses.groupby(['country', 'sub_network'], group_keys=False, squeeze=True) .apply(busmap_for_country).rename('busmap')) -def plot_busmap_for_n_clusters(n, n_clusters=50): - busmap = busmap_for_n_clusters(n, n_clusters) - cs = busmap.unique() - cr = sns.color_palette("hls", len(cs)) - n.plot(bus_colors=busmap.map(dict(zip(cs, cr)))) - del cs, cr def clustering_for_n_clusters(n, n_clusters, aggregate_carriers=None, line_length_factor=1.25, potential_mode='simple', @@ -277,8 +265,7 @@ def clustering_for_n_clusters(n, n_clusters, aggregate_carriers=None, elif potential_mode == 'conservative': p_nom_max_strategy = np.min else: - raise AttributeError("potential_mode should be one of 'simple' or 'conservative', " - "but is '{}'".format(potential_mode)) + raise AttributeError(f"potential_mode should be one of 'simple' or 'conservative' but is '{potential_mode}'") clustering = get_clustering_from_busmap( n, busmap_for_n_clusters(n, n_clusters, solver_name, focus_weights, algorithm), @@ -301,6 +288,7 @@ def clustering_for_n_clusters(n, n_clusters, aggregate_carriers=None, return clustering + def save_to_geojson(s, fn): if os.path.exists(fn): os.unlink(fn) @@ -308,6 +296,7 @@ def save_to_geojson(s, fn): schema = {**gpd.io.file.infer_schema(df), 'geometry': 'Unknown'} df.to_file(fn, driver='GeoJSON', schema=schema) + def cluster_regions(busmaps, input=None, output=None): if input is None: input = snakemake.input if output is None: output = snakemake.output @@ -321,6 +310,17 @@ def cluster_regions(busmaps, input=None, output=None): regions_c.index.name = 'name' save_to_geojson(regions_c, getattr(output, which)) + +def plot_busmap_for_n_clusters(n, n_clusters, fn=None): + busmap = busmap_for_n_clusters(n, n_clusters) + cs = busmap.unique() + cr = sns.color_palette("hls", len(cs)) + n.plot(bus_colors=busmap.map(dict(zip(cs, cr)))) + if fn is not None: + plt.savefig(fn, bbox_inches='tight') + del cs, cr + + if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake diff --git a/scripts/make_summary.py b/scripts/make_summary.py index db9eff46..ac0119ab 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -54,22 +54,22 @@ Replacing '/summaries/' with '/plots/' creates nice colored maps of the results. """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging import os - -from six import iteritems +import pypsa import pandas as pd -import pypsa - +from six import iteritems from add_electricity import load_costs, update_transmission_costs idx = pd.IndexSlice +logger = logging.getLogger(__name__) + opt_name = {"Store": "e", "Line" : "s", "Transformer" : "s"} + def _add_indexed_rows(df, raw_index): new_index = df.index|pd.MultiIndex.from_product(raw_index) if isinstance(new_index, pd.Index): @@ -77,6 +77,7 @@ def _add_indexed_rows(df, raw_index): return df.reindex(new_index) + def assign_carriers(n): if "carrier" not in n.loads: @@ -97,7 +98,8 @@ def assign_carriers(n): if "EU gas store" in n.stores.index and n.stores.loc["EU gas Store","carrier"] == "": n.stores.loc["EU gas Store","carrier"] = "gas Store" -def calculate_costs(n,label,costs): + +def calculate_costs(n, label, costs): for c in n.iterate_components(n.branch_components|n.controllable_one_port_components^{"Load"}): capital_costs = c.df.capital_cost*c.df[opt_name.get(c.name,"p") + "_nom_opt"] @@ -130,7 +132,7 @@ def calculate_costs(n,label,costs): return costs -def calculate_curtailment(n,label,curtailment): +def calculate_curtailment(n, label, curtailment): avail = n.generators_t.p_max_pu.multiply(n.generators.p_nom_opt).sum().groupby(n.generators.carrier).sum() used = n.generators_t.p.sum().groupby(n.generators.carrier).sum() @@ -139,7 +141,7 @@ def calculate_curtailment(n,label,curtailment): return curtailment -def calculate_energy(n,label,energy): +def calculate_energy(n, label, energy): for c in n.iterate_components(n.one_port_components|n.branch_components): @@ -159,6 +161,7 @@ def include_in_summary(summary, multiindexprefix, label, item): summary = _add_indexed_rows(summary, raw_index) summary.loc[idx[raw_index], label] = item.values + return summary def calculate_capacity(n,label,capacity): @@ -178,7 +181,7 @@ def calculate_capacity(n,label,capacity): return capacity -def calculate_supply(n,label,supply): +def calculate_supply(n, label, supply): """calculate the max dispatch of each component at the buses where the loads are attached""" load_types = n.loads.carrier.value_counts().index @@ -224,7 +227,8 @@ def calculate_supply(n,label,supply): return supply -def calculate_supply_energy(n,label,supply_energy): + +def calculate_supply_energy(n, label, supply_energy): """calculate the total dispatch of each component at the buses where the loads are attached""" load_types = n.loads.carrier.value_counts().index @@ -269,6 +273,7 @@ def calculate_supply_energy(n,label,supply_energy): return supply_energy + def calculate_metrics(n,label,metrics): metrics = metrics.reindex(metrics.index|pd.Index(["line_volume","line_volume_limit","line_volume_AC","line_volume_DC","line_volume_shadow","co2_shadow"])) @@ -295,16 +300,15 @@ def calculate_prices(n,label,prices): prices = prices.reindex(prices.index|bus_type.value_counts().index) - #WARNING: this is time-averaged, should really be load-weighted average + logger.warning("Prices are time-averaged, not load-weighted") prices[label] = n.buses_t.marginal_price.mean().groupby(bus_type).mean() return prices - def calculate_weighted_prices(n,label,weighted_prices): - # Warning: doesn't include storage units as loads - + + logger.warning("Weighted prices don't include storage units as loads") weighted_prices = weighted_prices.reindex(pd.Index(["electricity","heat","space heat","urban heat","space urban heat","gas","H2"])) @@ -347,7 +351,7 @@ def calculate_weighted_prices(n,label,weighted_prices): load += n.links_t.p0[names].groupby(n.links.loc[names,"bus0"],axis=1).sum(axis=1) - #Add H2 Store when charging + # Add H2 Store when charging if carrier == "H2": stores = n.stores_t.p[buses+ " Store"].groupby(n.stores.loc[buses+ " Store","bus"],axis=1).sum(axis=1) stores[stores > 0.] = 0. @@ -361,62 +365,6 @@ def calculate_weighted_prices(n,label,weighted_prices): return weighted_prices - -# BROKEN don't use -# -# def calculate_market_values(n, label, market_values): -# # Warning: doesn't include storage units - -# n.buses["suffix"] = n.buses.index.str[2:] -# suffix = "" -# buses = n.buses.index[n.buses.suffix == suffix] - -# ## First do market value of generators ## -# generators = n.generators.index[n.buses.loc[n.generators.bus,"suffix"] == suffix] -# techs = n.generators.loc[generators,"carrier"].value_counts().index -# market_values = market_values.reindex(market_values.index | techs) - -# for tech in techs: -# gens = generators[n.generators.loc[generators,"carrier"] == tech] -# dispatch = n.generators_t.p[gens].groupby(n.generators.loc[gens,"bus"],axis=1).sum().reindex(columns=buses,fill_value=0.) -# revenue = dispatch*n.buses_t.marginal_price[buses] -# market_values.at[tech,label] = revenue.sum().sum()/dispatch.sum().sum() - -# ## Now do market value of links ## - -# for i in ["0","1"]: -# all_links = n.links.index[n.buses.loc[n.links["bus"+i],"suffix"] == suffix] -# techs = n.links.loc[all_links,"carrier"].value_counts().index -# market_values = market_values.reindex(market_values.index | techs) - -# for tech in techs: -# links = all_links[n.links.loc[all_links,"carrier"] == tech] -# dispatch = n.links_t["p"+i][links].groupby(n.links.loc[links,"bus"+i],axis=1).sum().reindex(columns=buses,fill_value=0.) -# revenue = dispatch*n.buses_t.marginal_price[buses] -# market_values.at[tech,label] = revenue.sum().sum()/dispatch.sum().sum() - -# return market_values - - -# OLD CODE must be adapted - -# def calculate_price_statistics(n, label, price_statistics): - - -# price_statistics = price_statistics.reindex(price_statistics.index|pd.Index(["zero_hours","mean","standard_deviation"])) -# n.buses["suffix"] = n.buses.index.str[2:] -# suffix = "" -# buses = n.buses.index[n.buses.suffix == suffix] - -# threshold = 0.1 #higher than phoney marginal_cost of wind/solar -# df = pd.DataFrame(data=0.,columns=buses,index=n.snapshots) -# df[n.buses_t.marginal_price[buses] < threshold] = 1. -# price_statistics.at["zero_hours", label] = df.sum().sum()/(df.shape[0]*df.shape[1]) -# price_statistics.at["mean", label] = n.buses_t.marginal_price[buses].unstack().mean() -# price_statistics.at["standard_deviation", label] = n.buses_t.marginal_price[buses].unstack().std() -# return price_statistics - - outputs = ["costs", "curtailment", "energy", @@ -425,11 +373,10 @@ outputs = ["costs", "supply_energy", "prices", "weighted_prices", - # "price_statistics", - # "market_values", "metrics", ] + def make_summaries(networks_dict, country='all'): columns = pd.MultiIndex.from_tuples(networks_dict.keys(),names=["simpl","clusters","ll","opts"]) @@ -454,7 +401,7 @@ def make_summaries(networks_dict, country='all'): if country != 'all': n = n[n.buses.country == country] - Nyears = n.snapshot_weightings.sum()/8760. + Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears, snakemake.input[0], snakemake.config['costs'], snakemake.config['electricity']) update_transmission_costs(n, costs, simple_hvdc_costs=False) @@ -484,7 +431,6 @@ if __name__ == "__main__": network_dir = os.path.join('results', 'networks') configure_logging(snakemake) - def expand_from_wildcard(key): w = getattr(snakemake.wildcards, key) return snakemake.config["scenario"][key] if w == "all" else [w] @@ -504,8 +450,6 @@ if __name__ == "__main__": for l in ll for opts in expand_from_wildcard("opts")} - print(networks_dict) - dfs = make_summaries(networks_dict, country=snakemake.wildcards.country) to_csv(dfs) diff --git a/scripts/plot_network.py b/scripts/plot_network.py index 4e162e2f..84423916 100755 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -20,7 +20,6 @@ Description """ import logging -logger = logging.getLogger(__name__) from _helpers import (load_network_for_plots, aggregate_p, aggregate_costs, configure_logging) @@ -35,6 +34,9 @@ from matplotlib.patches import Circle, Ellipse from matplotlib.legend_handler import HandlerPatch to_rgba = mpl.colors.colorConverter.to_rgba +logger = logging.getLogger(__name__) + + def make_handler_map_to_scale_circles_as_in(ax, dont_resize_actively=False): fig = ax.get_figure() def axes2pt(): @@ -57,9 +59,11 @@ def make_handler_map_to_scale_circles_as_in(ax, dont_resize_actively=False): return e return {Circle: HandlerPatch(patch_func=legend_circle_handler)} + def make_legend_circles_for(sizes, scale=1.0, **kw): return [Circle((0,0), radius=(s/scale)**0.5, **kw) for s in sizes] + def set_plot_style(): plt.style.use(['classic', 'seaborn-white', {'axes.grid': False, 'grid.linestyle': '--', 'grid.color': u'0.6', @@ -69,9 +73,9 @@ def set_plot_style(): 'legend.fontsize': 'medium', 'lines.linewidth': 1.5, 'pdf.fonttype': 42, - # 'font.family': 'Times New Roman' }]) + def plot_map(n, ax=None, attribute='p_nom', opts={}): if ax is None: ax = plt.gca() @@ -114,16 +118,11 @@ def plot_map(n, ax=None, attribute='p_nom', opts={}): bus_sizes=0, bus_colors=tech_colors, boundaries=map_boundaries, - geomap=True, # TODO : Turn to False, after the release of PyPSA 0.14.2 (refer to https://github.com/PyPSA/PyPSA/issues/75) + geomap=False, ax=ax) ax.set_aspect('equal') ax.axis('off') - # x1, y1, x2, y2 = map_boundaries - # ax.set_xlim(x1, x2) - # ax.set_ylim(y1, y2) - - # Rasterize basemap # TODO : Check if this also works with cartopy for c in ax.collections[:2]: c.set_rasterized(True) @@ -176,13 +175,9 @@ def plot_map(n, ax=None, attribute='p_nom', opts={}): return fig -#n = load_network_for_plots(snakemake.input.network, opts, combine_hydro_ps=False) - def plot_total_energy_pie(n, ax=None): - """Add total energy pie plot""" - if ax is None: - ax = plt.gca() + if ax is None: ax = plt.gca() ax.set_title('Energy per technology', fontdict=dict(fontsize="medium")) @@ -190,7 +185,7 @@ def plot_total_energy_pie(n, ax=None): patches, texts, autotexts = ax.pie(e_primary, startangle=90, - labels = e_primary.rename(opts['nice_names_n']).index, + labels = e_primary.rename(opts['nice_names']).index, autopct='%.0f%%', shadow=False, colors = [opts['tech_colors'][tech] for tech in e_primary.index]) @@ -200,9 +195,7 @@ def plot_total_energy_pie(n, ax=None): t2.remove() def plot_total_cost_bar(n, ax=None): - """Add average system cost bar plot""" - if ax is None: - ax = plt.gca() + if ax is None: ax = plt.gca() total_load = (n.snapshot_weightings * n.loads_t.p.sum(axis=1)).sum() tech_colors = opts['tech_colors'] @@ -240,14 +233,13 @@ def plot_total_cost_bar(n, ax=None): if abs(data[-1]) < 5: continue - text = ax.text(1.1,(bottom-0.5*data)[-1]-3,opts['nice_names_n'].get(ind,ind)) + text = ax.text(1.1,(bottom-0.5*data)[-1]-3,opts['nice_names'].get(ind,ind)) texts.append(text) ax.set_ylabel("Average system cost [Eur/MWh]") - ax.set_ylim([0, 80]) # opts['costs_max']]) + ax.set_ylim([0, opts.get('costs_max', 80)]) ax.set_xlim([0, 1]) - #ax.set_xticks([0.5]) - ax.set_xticklabels([]) #["w/o\nEp", "w/\nEp"]) + ax.set_xticklabels([]) ax.grid(True, axis="y", color='k', linestyle='dotted') @@ -280,8 +272,6 @@ if __name__ == "__main__": ax2 = fig.add_axes([-0.075, 0.1, 0.1, 0.45]) plot_total_cost_bar(n, ax2) - #fig.tight_layout() - ll = snakemake.wildcards.ll ll_type = ll[0] ll_factor = ll[1:] diff --git a/scripts/plot_p_nom_max.py b/scripts/plot_p_nom_max.py index 0c2e06f2..bc346785 100644 --- a/scripts/plot_p_nom_max.py +++ b/scripts/plot_p_nom_max.py @@ -19,19 +19,19 @@ Description """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging import pypsa - import pandas as pd import matplotlib.pyplot as plt +logger = logging.getLogger(__name__) + + def cum_p_nom_max(net, tech, country=None): carrier_b = net.generators.carrier == tech - generators = \ - pd.DataFrame(dict( + generators = pd.DataFrame(dict( p_nom_max=net.generators.loc[carrier_b, 'p_nom_max'], p_max_pu=net.generators_t.p_max_pu.loc[:,carrier_b].mean(), country=net.generators.loc[carrier_b, 'bus'].map(net.buses.country) diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index 8eceea91..4aaa0d37 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -21,41 +21,19 @@ Description import os import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging import pandas as pd import matplotlib.pyplot as plt -#consolidate and rename -def rename_techs(label): - if label.startswith("central "): - label = label[len("central "):] - elif label.startswith("urban "): - label = label[len("urban "):] +logger = logging.getLogger(__name__) - if "retrofitting" in label: - label = "building retrofitting" + +def rename_techs(label): elif "H2" in label: label = "hydrogen storage" - elif "CHP" in label: - label = "CHP" - elif "water tank" in label: - label = "water tanks" - elif label == "water tanks": - label = "hot water storage" - elif "gas" in label and label != "gas boiler": - label = "natural gas" - elif "solar thermal" in label: - label = "solar thermal" elif label == "solar": label = "solar PV" - elif label == "heat pump": - label = "air heat pump" - elif label == "Sabatier": - label = "methanation" - elif label == "offwind": - label = "offshore wind" elif label == "offwind-ac": label = "offshore wind ac" elif label == "offwind-dc": @@ -68,15 +46,14 @@ def rename_techs(label): label = "hydroelectricity" elif label == "PHS": label = "hydroelectricity" - elif label == "co2 Store": - label = "DAC" elif "battery" in label: label = "battery storage" return label -preferred_order = pd.Index(["transmission lines","hydroelectricity","hydro reservoir","run of river","pumped hydro storage","onshore wind","offshore wind ac", "offshore wind dc","solar PV","solar thermal","building retrofitting","ground heat pump","air heat pump","resistive heater","CHP","OCGT","gas boiler","gas","natural gas","methanation","hydrogen storage","battery storage","hot water storage"]) +preferred_order = pd.Index(["transmission lines","hydroelectricity","hydro reservoir","run of river","pumped hydro storage","onshore wind","offshore wind ac", "offshore wind dc","solar PV","solar thermal","OCGT","hydrogen storage","battery storage"]) + def plot_costs(infn, fn=None): diff --git a/scripts/prepare_links_p_nom.py b/scripts/prepare_links_p_nom.py index 757e8345..7623d1bf 100644 --- a/scripts/prepare_links_p_nom.py +++ b/scripts/prepare_links_p_nom.py @@ -37,11 +37,26 @@ Description """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging import pandas as pd +logger = logging.getLogger(__name__) + + +def multiply(s): + return s.str[0].astype(float) * s.str[1].astype(float) + + +def extract_coordinates(s): + regex = (r"(\d{1,2})°(\d{1,2})′(\d{1,2})″(N|S) " + r"(\d{1,2})°(\d{1,2})′(\d{1,2})″(E|W)") + e = s.str.extract(regex, expand=True) + lat = (e[0].astype(float) + (e[1].astype(float) + e[2].astype(float)/60.)/60.)*e[3].map({'N': +1., 'S': -1.}) + lon = (e[4].astype(float) + (e[5].astype(float) + e[6].astype(float)/60.)/60.)*e[7].map({'E': +1., 'W': -1.}) + return lon, lat + + if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake #rule must be enabled in config @@ -50,19 +65,11 @@ if __name__ == "__main__": links_p_nom = pd.read_html('https://en.wikipedia.org/wiki/List_of_HVDC_projects', header=0, match="SwePol")[0] - def extract_coordinates(s): - regex = (r"(\d{1,2})°(\d{1,2})′(\d{1,2})″(N|S) " - r"(\d{1,2})°(\d{1,2})′(\d{1,2})″(E|W)") - e = s.str.extract(regex, expand=True) - lat = (e[0].astype(float) + (e[1].astype(float) + e[2].astype(float)/60.)/60.)*e[3].map({'N': +1., 'S': -1.}) - lon = (e[4].astype(float) + (e[5].astype(float) + e[6].astype(float)/60.)/60.)*e[7].map({'E': +1., 'W': -1.}) - return lon, lat + mw = "Power (MW)" + m_b = links_p_nom[mw].str.contains('x').fillna(False) - m_b = links_p_nom["Power (MW)"].str.contains('x').fillna(False) - def multiply(s): return s.str[0].astype(float) * s.str[1].astype(float) - - links_p_nom.loc[m_b, "Power (MW)"] = links_p_nom.loc[m_b, "Power (MW)"].str.split('x').pipe(multiply) - links_p_nom["Power (MW)"] = links_p_nom["Power (MW)"].str.extract("[-/]?([\d.]+)", expand=False).astype(float) + links_p_nom.loc[m_b, mw] = links_p_nom.loc[m_b, mw].str.split('x').pipe(multiply) + links_p_nom[mw] = links_p_nom[mw].str.extract("[-/]?([\d.]+)", expand=False).astype(float) links_p_nom['x1'], links_p_nom['y1'] = extract_coordinates(links_p_nom['Converterstation 1']) links_p_nom['x2'], links_p_nom['y2'] = extract_coordinates(links_p_nom['Converterstation 2']) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 1fcba99f..bb7640be 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -55,19 +55,21 @@ Description """ import logging -logger = logging.getLogger(__name__) from _helpers import configure_logging -from add_electricity import load_costs, update_transmission_costs -from six import iteritems - -import numpy as np import re import pypsa +import numpy as np import pandas as pd +from six import iteritems + +from add_electricity import load_costs, update_transmission_costs idx = pd.IndexSlice +logger = logging.getLogger(__name__) + + def add_co2limit(n, Nyears=1., factor=None): if factor is not None: @@ -129,10 +131,10 @@ def set_transmission_limit(n, ll_type, factor, Nyears=1): n.add('GlobalConstraint', f'l{ll_type}_limit', type=f'transmission_{con_type}_limit', sense='<=', constant=rhs, carrier_attribute='AC, DC') + return n - def average_every_nhours(n, offset): logger.info('Resampling the network to {}'.format(offset)) m = n.copy(with_time=False) @@ -160,7 +162,7 @@ if __name__ == "__main__": opts = snakemake.wildcards.opts.split('-') n = pypsa.Network(snakemake.input[0]) - Nyears = n.snapshot_weightings.sum()/8760. + Nyears = n.snapshot_weightings.sum() / 8760. set_line_s_max_pu(n) @@ -179,6 +181,7 @@ if __name__ == "__main__": add_co2limit(n, Nyears, float(m[0])) else: add_co2limit(n, Nyears) + break for o in opts: oo = o.split("+") diff --git a/scripts/retrieve_databundle.py b/scripts/retrieve_databundle.py index 9bb85833..7ee6c2b1 100644 --- a/scripts/retrieve_databundle.py +++ b/scripts/retrieve_databundle.py @@ -33,14 +33,15 @@ The :ref:`tutorial` uses a smaller `data bundle Date: Fri, 11 Sep 2020 15:26:43 +0200 Subject: [PATCH 002/591] execute pre-commit --- .github/ISSUE_TEMPLATE/bug_report.md | 4 +- .github/ISSUE_TEMPLATE/config.yml | 2 +- .github/pull_request_template.md | 4 +- .pre-commit-config.yaml | 8 ++++ .readthedocs.yml | 2 +- .reuse/dep5 | 2 +- .travis.yml | 5 ++- README.md | 2 +- Snakefile | 20 +++++----- data/links_tyndp.csv | 2 +- data/parameter_corrections.yaml | 12 +++--- doc/_static/theme_overrides.css | 4 +- doc/cloudcomputing.rst | 40 +++++++++---------- doc/configtables/atlite.csv | 2 +- doc/configtables/costs.csv | 2 +- doc/configtables/hydro.csv | 2 +- doc/configtables/lines.csv | 2 +- doc/configtables/links.csv | 2 +- doc/configtables/load.csv | 2 +- doc/configtables/offwind-ac.csv | 2 +- doc/configtables/offwind-dc.csv | 2 +- doc/configtables/onwind.csv | 2 +- doc/configtables/opts.csv | 2 +- doc/configtables/plotting.csv | 2 +- doc/configtables/scenario.csv | 2 +- doc/configtables/snapshots.csv | 2 +- doc/configtables/solar.csv | 2 +- doc/configtables/solving-options.csv | 2 +- doc/configtables/solving-solver.csv | 2 +- doc/configtables/toplevel.csv | 2 +- doc/configtables/transformers.csv | 2 +- doc/configuration.rst | 4 +- doc/costs.rst | 2 +- doc/index.rst | 10 ++--- doc/installation.rst | 16 ++++---- doc/introduction.rst | 4 +- doc/limitations.rst | 3 +- doc/plotting.rst | 2 +- doc/preparation/base_network.rst | 4 +- doc/preparation/build_bus_regions.rst | 2 +- doc/preparation/build_cutout.rst | 2 +- doc/release_notes.rst | 8 ++-- doc/simplification.rst | 2 +- doc/tutorial.rst | 16 ++++---- doc/wildcards.rst | 4 +- .../environment.docs.yaml | 29 ++++---------- .../environment.fixed.yaml | 0 environment.yaml => envs/environment.yaml | 0 scripts/add_electricity.py | 2 +- scripts/base_network.py | 16 ++++---- scripts/cluster_network.py | 2 +- scripts/make_summary.py | 2 +- scripts/prepare_network.py | 2 +- test/config.test1.yaml | 1 - 54 files changed, 135 insertions(+), 141 deletions(-) create mode 100644 .pre-commit-config.yaml rename environment.docs.yaml => envs/environment.docs.yaml (60%) rename environment.fixedversions.yaml => envs/environment.fixed.yaml (100%) rename environment.yaml => envs/environment.yaml (100%) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index a1671b69..2654595c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -11,7 +11,7 @@ assignees: '' ## Checklist - [ ] I am using the current [`master`](https://github.com/PyPSA/pypsa-eur/tree/master) branch or the latest [release](https://github.com/PyPSA/pypsa-eur/releases). Please indicate. -- [ ] I am running on an up-to-date [`pypsa-eur` environment](https://github.com/PyPSA/pypsa-eur/blob/master/environment.yaml). Update via `conda env update -f environment.yaml`. +- [ ] I am running on an up-to-date [`pypsa-eur` environment](https://github.com/PyPSA/pypsa-eur/blob/master/envs/environment.yaml). Update via `conda env update -f envs/environment.yaml`. ## Describe the Bug @@ -24,4 +24,4 @@ assignees: '' ``` -``` \ No newline at end of file +``` diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index bb1951c0..5b64d242 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,4 +2,4 @@ blank_issues_enabled: false contact_links: - name: PyPSA Mailing List url: https://groups.google.com/forum/#!forum/pypsa - about: Please ask and answer general usage questions here. \ No newline at end of file + about: Please ask and answer general usage questions here. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b431c08a..05601c58 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,7 +7,7 @@ Closes # (if applicable). - [ ] I tested my contribution locally and it seems to work fine. - [ ] Code and workflow changes are sufficiently documented. -- [ ] Newly introduced dependencies are added to `environment.yaml` and `environment.docs.yaml`. +- [ ] Newly introduced dependencies are added to `envs/environment.yaml` and `envs/environment.docs.yaml`. - [ ] Changes in configuration options are added in all of `config.default.yaml`, `config.tutorial.yaml`, and `test/config.test1.yaml`. - [ ] Changes in configuration options are also documented in `doc/configtables/*.csv` and line references are adjusted in `doc/configuration.rst` and `doc/tutorial.rst`. -- [ ] A note for the release notes `doc/release_notes.rst` is amended in the format of previous release notes. \ No newline at end of file +- [ ] A note for the release notes `doc/release_notes.rst` is amended in the format of previous release notes. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..c5d05ee9 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,8 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.4.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files diff --git a/.readthedocs.yml b/.readthedocs.yml index 0ccb7def..173d21d7 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -5,4 +5,4 @@ version: 2 conda: - environment: environment.docs.yaml \ No newline at end of file + environment: envs/environment.docs.yaml diff --git a/.reuse/dep5 b/.reuse/dep5 index ef2e4f85..eb64a172 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -25,4 +25,4 @@ License: CC0-1.0 Files: borg-it Copyright: : 2017-2020 The PyPSA-Eur Authors -License: CC0-1.0 \ No newline at end of file +License: CC0-1.0 diff --git a/.travis.yml b/.travis.yml index a8e6e36e..75c5d524 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,11 +15,12 @@ before_install: - source conda4travis.sh # install conda environment - - conda env create -f ./environment.yaml + - conda install -c conda-forge mamba + - mamba env create -f ./envs/environment.yaml - conda activate pypsa-eur # install open-source solver - - conda install -c conda-forge ipopt glpk + - mamba install -c conda-forge ipopt glpk script: - cp ./test/config.test1.yaml ./config.yaml diff --git a/README.md b/README.md index dcc7c6fc..c281e589 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ and local grid bottlenecks may cause unrealistic load-shedding or generator curtailment. We recommend to cluster the network to a couple of hundred nodes to remove these local inconsistencies. See the -discussion in Section 3.4 "Model validation" of the paper. +discussion in Section 3.4 "Model validation" of the paper. ![PyPSA-Eur Grid Model](doc/img/base.png) diff --git a/Snakefile b/Snakefile index ce27174a..3eddad7c 100644 --- a/Snakefile +++ b/Snakefile @@ -46,11 +46,11 @@ if config['enable'].get('prepare_links_p_nom', False): script: 'scripts/prepare_links_p_nom.py' -datafiles = ['ch_cantons.csv', 'je-e-21.03.02.xls', - 'eez/World_EEZ_v8_2014.shp', 'EIA_hydro_generation_2000_2014.csv', - 'hydro_capacities.csv', 'naturalearth/ne_10m_admin_0_countries.shp', - 'NUTS_2013_60M_SH/data/NUTS_RG_60M_2013.shp', 'nama_10r_3popgdp.tsv.gz', - 'nama_10r_3gdp.tsv.gz', 'time_series_60min_singleindex_filtered.csv', +datafiles = ['ch_cantons.csv', 'je-e-21.03.02.xls', + 'eez/World_EEZ_v8_2014.shp', 'EIA_hydro_generation_2000_2014.csv', + 'hydro_capacities.csv', 'naturalearth/ne_10m_admin_0_countries.shp', + 'NUTS_2013_60M_SH/data/NUTS_RG_60M_2013.shp', 'nama_10r_3popgdp.tsv.gz', + 'nama_10r_3gdp.tsv.gz', 'time_series_60min_singleindex_filtered.csv', 'corine/g250_clc06_V18_5.tif'] @@ -131,7 +131,7 @@ rule build_bus_regions: script: "scripts/build_bus_regions.py" -if config['enable'].get('build_cutout', False): +if config['enable'].get('build_cutout', False): rule build_cutout: output: directory("cutouts/{cutout}") log: "logs/build_cutout/{cutout}.log" @@ -148,9 +148,9 @@ if config['enable'].get('retrieve_cutout', True): script: 'scripts/retrieve_cutout.py' -if config['enable'].get('build_natura_raster', False): +if config['enable'].get('build_natura_raster', False): rule build_natura_raster: - input: + input: natura="data/bundle/natura/Natura2000_end2015.shp", cutouts=expand("cutouts/{cutouts}", **config['atlite']) output: "resources/natura.tiff" @@ -179,7 +179,7 @@ rule build_renewable_profiles: if w.technology in ('onwind', 'solar') else "resources/regions_offshore.geojson"), cutout=lambda w: "cutouts/" + config["renewable"][w.technology]['cutout'] - output: + output: profile="resources/profile_{technology}.nc", log: "logs/build_renewable_profile_{technology}.log" benchmark: "benchmarks/build_renewable_profiles_{technology}" @@ -210,7 +210,7 @@ rule add_electricity: geth_hydro_capacities='data/geth2015_hydro_capacities.csv', opsd_load='data/bundle/time_series_60min_singleindex_filtered.csv', nuts3_shapes='resources/nuts3_shapes.geojson', - **{'profile_' + tech: "resources/profile_" + tech + ".nc" + **{f"profile_{tech}": f"resources/profile_{tech}.nc" for tech in config['renewable']} output: "networks/elec.nc" log: "logs/add_electricity.log" diff --git a/data/links_tyndp.csv b/data/links_tyndp.csv index 5d0aec28..ca977c27 100644 --- a/data/links_tyndp.csv +++ b/data/links_tyndp.csv @@ -23,4 +23,4 @@ HVDC Ultranet,Osterath (DE),Philippsburg (DE),,314,600,in permitting,,https://ty Gridlink,Kingsnorth (UK),Warande (FR),160,,1400,in permitting,,https://tyndp.entsoe.eu/tyndp2018/projects/projects/285,0.596111111111111,51.41972,2.376776,51.034368 NeuConnect,Grain (UK),Fedderwarden (DE),680,,1400,in permitting,,https://tyndp.entsoe.eu/tyndp2018/projects/projects/309,0.716666666666667,51.44,8.046524,53.562763 NordBalt,Klaipeda (LT),Nybro (SE),450,,700,built,,https://en.wikipedia.org/wiki/NordBalt,21.256667,55.681667,15.854167,56.767778 -Estlink 1,Harku (EE),Espoo (FI),105,,350,built,,https://en.wikipedia.org/wiki/Estlink,24.560278,59.384722,24.551667,60.203889 \ No newline at end of file +Estlink 1,Harku (EE),Espoo (FI),105,,350,built,,https://en.wikipedia.org/wiki/Estlink,24.560278,59.384722,24.551667,60.203889 diff --git a/data/parameter_corrections.yaml b/data/parameter_corrections.yaml index 83a17d51..0962b1b8 100644 --- a/data/parameter_corrections.yaml +++ b/data/parameter_corrections.yaml @@ -33,12 +33,12 @@ Link: "14559": "6240" # fix wrong bus allocation from 6241 "12998": "1333" # combine link 12998 + 12997 in 12998 "5627": '2309' # combine link 5627 + 5628 in 5627 - length: + length: index: - "12998": 409.0 + "12998": 409.0 "5627": 26.39 - bus0: - index: + bus0: + index: # set bus0 == bus1 for removing the link in remove_unconnected_components - "5628": "7276" - "12997": "7276" \ No newline at end of file + "5628": "7276" + "12997": "7276" diff --git a/doc/_static/theme_overrides.css b/doc/_static/theme_overrides.css index efbe909c..778756c1 100644 --- a/doc/_static/theme_overrides.css +++ b/doc/_static/theme_overrides.css @@ -11,7 +11,7 @@ white-space: normal !important; /* background: #eeeeee !important; */ } - + .wy-table-responsive { max-width: 100%; overflow: visible !important; @@ -20,4 +20,4 @@ .wy-nav-content { max-width: 910px !important; } - } \ No newline at end of file + } diff --git a/doc/cloudcomputing.rst b/doc/cloudcomputing.rst index 3da6b9c2..f91441a5 100644 --- a/doc/cloudcomputing.rst +++ b/doc/cloudcomputing.rst @@ -1,6 +1,6 @@ .. SPDX-FileCopyrightText: 2020 Maximilian Parzen and Emmanuel Paez - + SPDX-License-Identifier: CC-BY-4.0 @@ -18,7 +18,7 @@ Google Cloud Platform (GCP) We are happy to take pull requests explaining where the procedures deviate from the descriptions below for other operating systems. Likewise, tutorials for other cloud computing solutions are also highly welcome. -The Google Cloud Platform (GCP) is a cloud computing service you can use to run PyPSA-Eur calculations, especially if +The Google Cloud Platform (GCP) is a cloud computing service you can use to run PyPSA-Eur calculations, especially if - you do not have immediate access to high-performance computating facilities, - you have problems with the Windows operating system and want a quick run on a linux-based system, @@ -26,7 +26,7 @@ The Google Cloud Platform (GCP) is a cloud computing service you can use to run - you need quick results (trial version includes 32 vCPU cores and up to 800 GB of memory). With the Google Cloud Platform you set up a virtual machine in the cloud which can store and operate data. -Like on your local computer, you have to install all software and solvers, and create paths on the virtual machine to set up the required environment. +Like on your local computer, you have to install all software and solvers, and create paths on the virtual machine to set up the required environment. The 300$ free trial budget is offered which equals roughly 10-20 simulations with 180 nodes at hourly basis. The following steps are required: @@ -38,7 +38,7 @@ The following steps are required: Step 1 - Google Cloud Platform registration ------------------------------------------- -First, register at the `Google Cloud Platform `_ (GCP). +First, register at the `Google Cloud Platform `_ (GCP). Ann active bank account is required, which will not be charged unless you exceed the trial budget. Step 2 - Create your Virtual Machine instance @@ -73,26 +73,26 @@ Step 3 - Installation of Cloud SDK - Download Google Cloud SDK `SDK `_. Check that you are logged in in your Google account. The link should lead you to the Windows installation of Google Cloud SDK. - Follow the "Quickstart for Windows - Before you begin" steps. - After the successfull installation and initialization, close the Google Cloud SDK reopen it again. Type the following command into the "Google Cloud SDK Shell": - + .. code:: bash - + gcloud compute ssh -- -L 8888:localhost:8888 - + - This command above will open a PuTTy command window that is connected to your Virtual Machine. Time to celebrate if it works! -- Now install all necessary tools. As little help, the first steps: +- Now install all necessary tools. As little help, the first steps: .. code:: bash - + sudo apt-get update sudo apt-get install bzip2 libxml2-dev sudo apt-get install wget wget https://repo.anaconda.com/archive/Anaconda3-2020.07-Linux-x86_64.sh (Check the link. To be up to date with anaconda, check the Anaconda website https://www.anaconda.com/products/individual ) ls (to see what anaconda file to bash) - bash Anaconda3-2020.07-Linux-x86_64.sh - source ~/.bashrc - + bash Anaconda3-2020.07-Linux-x86_64.sh + source ~/.bashrc + - Close and reopen the PuTTy file (-> open Google Cloud SDK -> initialize again with the command above to open the PuTTY command window). Now ``conda`` can be listed with ``conda list``. Noq you can follow the standard installation instructions to finalize your machine (don't forget the solvers - for bigger simulations use commercial solvers such as Gurobi). - + Step 4 - Installation of WinSCP ------------------------------- @@ -102,22 +102,22 @@ Make sure that your instance is operating for the next steps. - Download `WinSCP `_ and follow the default installation steps. - Open WinSCP after the installation. A login window will open. - Keep SFTP as file protocol. -- As host name insert the External IP of your VM (click in your internet browser on your GCP VM instance to see the external IP) +- As host name insert the External IP of your VM (click in your internet browser on your GCP VM instance to see the external IP) - Set the User name in WinSCP to the name you see in your PuTTy window (check step 3 - for instance [username]@[VM-name]:~$) -- Click on the advanced setting. SSH -> Authentication. -- Option 1. Click on the Tools button and "Install Public Key into Server..". Somewhere in your folder structure must be a public key. I found it with the following folder syntax on my local windows computer -> :\Users\...\.ssh (there should be a PKK file). -- Option 2. Click on the Tools button and "Generate new key pair...". Save the private key at a folder you remember and add it to the "private key file" field in WinSCP. Upload the public key to the metadeta of your instance. +- Click on the advanced setting. SSH -> Authentication. +- Option 1. Click on the Tools button and "Install Public Key into Server..". Somewhere in your folder structure must be a public key. I found it with the following folder syntax on my local windows computer -> :\Users\...\.ssh (there should be a PKK file). +- Option 2. Click on the Tools button and "Generate new key pair...". Save the private key at a folder you remember and add it to the "private key file" field in WinSCP. Upload the public key to the metadeta of your instance. - Click ok and save. Then click Login. If successfull WinSCP will open on the left side your local computer folder structure and on the right side the folder strucutre of your VM. (If you followed Option 2 and its not initially working. Stop your instance, refresh the website, reopen the WinSCP field. Afterwards your your Login should be successfull) If you had struggle with the above steps, you could also try `this video `_. .. note:: Double check the External IP of your VM before you try to login with WinSCP. It's often a cause for an error. - + Step 5 - Extra. Copying your instance with all its data and paths included -------------------------------------------------------------------------- Especially if you think about operating several instance for quicker simulations, you can create a so called `"image" `_ of the virtual machine. -The "image" includes all the data and software set-ups from your VM. Afterwards you can create a VM from an image and avoid all the installation steps above. +The "image" includes all the data and software set-ups from your VM. Afterwards you can create a VM from an image and avoid all the installation steps above. Important points when to solve networks in PyPSA ------------------------------------------------ @@ -126,4 +126,4 @@ If you use the GCP with the default PyPSA-Eur settings, your budget will be used - Always test using low resolution networks; i.e. a single country at 5 nodes and 24h resolution for 2 month of weather data. - Adjust your solver in the ``config.yaml`` file. Set ``solving: skip_iterations: true``. - This will lead to a single solver iteration which is often precise enough. + This will lead to a single solver iteration which is often precise enough. diff --git a/doc/configtables/atlite.csv b/doc/configtables/atlite.csv index b60b15e5..5f21bb05 100644 --- a/doc/configtables/atlite.csv +++ b/doc/configtables/atlite.csv @@ -5,4 +5,4 @@ cutouts,,, -- -- module,--,"One of {'era5','sarah'}","Source of the reanalysis weather dataset (e.g. `ERA5 `_ or `SARAH-2 `_)" -- -- xs,°,"Float interval within [-180, 180]","Range of longitudes to download weather data for." -- -- ys,°,"Float interval within [-90, 90]","Range of latitudes to download weather data for." --- -- years,--,"Integer interval within [1979,2018]","Range of years to download weather data for." \ No newline at end of file +-- -- years,--,"Integer interval within [1979,2018]","Range of years to download weather data for." diff --git a/doc/configtables/costs.csv b/doc/configtables/costs.csv index 383a6423..ed2d56e4 100644 --- a/doc/configtables/costs.csv +++ b/doc/configtables/costs.csv @@ -5,4 +5,4 @@ USD2013_to_EUR2013,--,float,"Exchange rate from USD :math:`_{2013}` to EUR :math capital_cost,EUR/MW,"Keys should be in the 'technology' column of ``data/costs.csv``. Values can be any float.","For the given technologies, assumptions about their capital investment costs are set to the corresponding value. Optional; overwrites cost assumptions from ``data/costs.csv``." marginal_cost,EUR/MWh,"Keys should be in the 'technology' column of ``data/costs.csv``. Values can be any float.","For the given technologies, assumptions about their marginal operating costs are set to the corresponding value. Optional; overwrites cost assumptions from ``data/costs.csv``." emission_prices,,,"Specify exogenous prices for emission types listed in ``network.carriers`` to marginal costs." --- co2,EUR/t,float,"Exogenous price of carbon-dioxide added to the marginal costs of fossil-fuelled generators according to their carbon intensity. Added through the keyword ``Ep`` in the ``{opts}`` wildcard only in the rule :mod:`prepare_network``." \ No newline at end of file +-- co2,EUR/t,float,"Exogenous price of carbon-dioxide added to the marginal costs of fossil-fuelled generators according to their carbon intensity. Added through the keyword ``Ep`` in the ``{opts}`` wildcard only in the rule :mod:`prepare_network``." diff --git a/doc/configtables/hydro.csv b/doc/configtables/hydro.csv index 801b27ff..fc53334e 100644 --- a/doc/configtables/hydro.csv +++ b/doc/configtables/hydro.csv @@ -3,4 +3,4 @@ cutout,--,"Must be 'europe-2013-era5'","Specifies the directory where the releva carriers,--,"Any subset of {'ror', 'PHS', 'hydro'}","Specifies the types of hydro power plants to build per-unit availability time series for. 'ror' stands for run-of-river plants, 'PHS' represents pumped-hydro storage, and 'hydro' stands for hydroelectric dams." PHS_max_hours,h,float,"Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom``. Cf. `PyPSA documentation `_." hydro_max_hours,h,"Any of {float, 'energy_capacity_totals_by_country', 'estimate_by_large_installations'}","Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom`` or heuristically determined. Cf. `PyPSA documentation `_." -clip_min_inflow,MW,float,"To avoid too small values in the inflow time series, values below this threshold are set to zero." \ No newline at end of file +clip_min_inflow,MW,float,"To avoid too small values in the inflow time series, values below this threshold are set to zero." diff --git a/doc/configtables/lines.csv b/doc/configtables/lines.csv index e5067867..59cc4fa3 100644 --- a/doc/configtables/lines.csv +++ b/doc/configtables/lines.csv @@ -2,4 +2,4 @@ types,--,"Values should specify a `line type in PyPSA `_. Keys should specify the corresponding voltage level (e.g. 220., 300. and 380. kV)","Specifies line types to assume for the different voltage levels of the ENTSO-E grid extraction. Should normally handle voltage levels 220, 300, and 380 kV" s_max_pu,--,"Value in [0.,1.]","Correction factor for line capacities (``s_nom``) to approximate :math:`N-1` security and reserve capacity for reactive power flows" length_factor,--,float,"Correction factor to account for the fact that buses are *not* connected by lines through air-line distance." -under_construction,--,"One of {'zero': set capacity to zero, 'remove': remove completely, 'keep': keep with full capacity}","Specifies how to handle lines which are currently under construction." \ No newline at end of file +under_construction,--,"One of {'zero': set capacity to zero, 'remove': remove completely, 'keep': keep with full capacity}","Specifies how to handle lines which are currently under construction." diff --git a/doc/configtables/links.csv b/doc/configtables/links.csv index d77c9ddd..96f6c2f5 100644 --- a/doc/configtables/links.csv +++ b/doc/configtables/links.csv @@ -1,4 +1,4 @@ ,Unit,Values,Description p_max_pu,--,"Value in [0.,1.]","Correction factor for link capacities ``p_nom``." include_tyndp,bool,"{'true', 'false'}","Specifies whether to add HVDC link projects from the `TYNDP 2018 `_ which are at least in permitting." -under_construction,--,"One of {'zero': set capacity to zero, 'remove': remove completely, 'keep': keep with full capacity}","Specifies how to handle lines which are currently under construction." \ No newline at end of file +under_construction,--,"One of {'zero': set capacity to zero, 'remove': remove completely, 'keep': keep with full capacity}","Specifies how to handle lines which are currently under construction." diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index 035b27a1..760f912c 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -1,2 +1,2 @@ ,Unit,Values,Description -scaling_factor,--,float,"Global correction factor for the load time series." \ No newline at end of file +scaling_factor,--,float,"Global correction factor for the load time series." diff --git a/doc/configtables/offwind-ac.csv b/doc/configtables/offwind-ac.csv index 02544506..e5bbc847 100644 --- a/doc/configtables/offwind-ac.csv +++ b/doc/configtables/offwind-ac.csv @@ -10,4 +10,4 @@ max_depth,m,float,"Maximum sea water depth at which wind turbines can be build. min_shore_distance,m,float,"Minimum distance to the shore below which wind turbines cannot be build. Such areas close to the shore are excluded in the process of calculating the AC-connected offshore wind potential." potential,--,"One of {'simple', 'conservative'}","Method to compute the maximal installable potential for a node; confer :ref:`renewableprofiles`" clip_p_max_pu,p.u.,float,"To avoid too small values in the renewables` per-unit availability time series values below this threshold are set to zero." -keep_all_available_areas,bool,"{'true', 'false'}","Use all availabe weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed." \ No newline at end of file +keep_all_available_areas,bool,"{'true', 'false'}","Use all availabe weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed." diff --git a/doc/configtables/offwind-dc.csv b/doc/configtables/offwind-dc.csv index 02544506..e5bbc847 100644 --- a/doc/configtables/offwind-dc.csv +++ b/doc/configtables/offwind-dc.csv @@ -10,4 +10,4 @@ max_depth,m,float,"Maximum sea water depth at which wind turbines can be build. min_shore_distance,m,float,"Minimum distance to the shore below which wind turbines cannot be build. Such areas close to the shore are excluded in the process of calculating the AC-connected offshore wind potential." potential,--,"One of {'simple', 'conservative'}","Method to compute the maximal installable potential for a node; confer :ref:`renewableprofiles`" clip_p_max_pu,p.u.,float,"To avoid too small values in the renewables` per-unit availability time series values below this threshold are set to zero." -keep_all_available_areas,bool,"{'true', 'false'}","Use all availabe weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed." \ No newline at end of file +keep_all_available_areas,bool,"{'true', 'false'}","Use all availabe weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed." diff --git a/doc/configtables/onwind.csv b/doc/configtables/onwind.csv index 11f05cfa..149dc0c4 100644 --- a/doc/configtables/onwind.csv +++ b/doc/configtables/onwind.csv @@ -11,4 +11,4 @@ corine,,, natura,bool,"{true, false}","Switch to exclude `Natura 2000 `_ natural protection areas. Area is excluded if ``true``." potential,--,"One of {'simple', 'conservative'}","Method to compute the maximal installable potential for a node; confer :ref:`renewableprofiles`" clip_p_max_pu,p.u.,float,"To avoid too small values in the renewables` per-unit availability time series values below this threshold are set to zero." -keep_all_available_areas,bool,"{'true', 'false'}","Use all availabe weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed." \ No newline at end of file +keep_all_available_areas,bool,"{'true', 'false'}","Use all availabe weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed." diff --git a/doc/configtables/opts.csv b/doc/configtables/opts.csv index 4d699034..427951e5 100644 --- a/doc/configtables/opts.csv +++ b/doc/configtables/opts.csv @@ -5,4 +5,4 @@ Trigger, Description, Definition, Status ``CCL``, Add minimum and maximum levels of generator nominal capacity per carrier for individual countries. These can be specified in the file linked at ``electricity: agg_p_nom_limits`` in the configuration. File defaults to ``data/agg_p_nom_minmax.csv``., ``solve_network``, In active use ``BAU``, Add a per-``carrier`` minimal overall capacity; i.e. at least ``40GW`` of ``OCGT`` in Europe; configured in ``electricity: BAU_mincapacities``, ``solve_network``: `add_opts_constraints() `_, Untested ``SAFE``, Add a capacity reserve margin of a certain fraction above the peak demand to which renewable generators and storage do *not* contribute. Ignores network., ``solve_network`` `add_opts_constraints() `_, Untested -``carrier+factor``, "Alter the capital cost of a carrier by a factor. Example: ``solar+0.5`` reduces the capital cost of solar to 50\% of original values.", ``prepare_network``, In active use \ No newline at end of file +``carrier+factor``, "Alter the capital cost of a carrier by a factor. Example: ``solar+0.5`` reduces the capital cost of solar to 50\% of original values.", ``prepare_network``, In active use diff --git a/doc/configtables/plotting.csv b/doc/configtables/plotting.csv index 754f2e83..f5910e16 100644 --- a/doc/configtables/plotting.csv +++ b/doc/configtables/plotting.csv @@ -11,4 +11,4 @@ energy_max,TWh,float,"Upper y-axis limit in energy bar plots." energy_min,TWh,float,"Lower y-axis limit in energy bar plots." energy_threshold,TWh,float,"Threshold below which technologies will not be shown in energy bar plots." tech_colors,--,"carrier -> HEX colour code","Mapping from network ``carrier`` to a colour (`HEX colour code `_)." -nice_names,--,"str -> str","Mapping from network ``carrier`` to a more readable name." \ No newline at end of file +nice_names,--,"str -> str","Mapping from network ``carrier`` to a more readable name." diff --git a/doc/configtables/scenario.csv b/doc/configtables/scenario.csv index 7a2d3bcd..a82462e4 100644 --- a/doc/configtables/scenario.csv +++ b/doc/configtables/scenario.csv @@ -2,4 +2,4 @@ simpl,--,cf. :ref:`simpl`,"List of ``{simpl}`` wildcards to run." clusters,--,cf. :ref:`clusters`,"List of ``{clusters}`` wildcards to run." ll,--,cf. :ref:`ll`,"List of ``{ll}`` wildcards to run." -opts,--,cf. :ref:`opts`,"List of ``{opts}`` wildcards to run." \ No newline at end of file +opts,--,cf. :ref:`opts`,"List of ``{opts}`` wildcards to run." diff --git a/doc/configtables/snapshots.csv b/doc/configtables/snapshots.csv index 14fd8001..4d917f4d 100644 --- a/doc/configtables/snapshots.csv +++ b/doc/configtables/snapshots.csv @@ -1,4 +1,4 @@ ,Unit,Values,Description 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" -closed,--,"One of {None, ‘left’, ‘right’}","Make the time interval closed to the ``left``, ``right``, or both sides ``None``." \ No newline at end of file +closed,--,"One of {None, ‘left’, ‘right’}","Make the time interval closed to the ``left``, ``right``, or both sides ``None``." diff --git a/doc/configtables/solar.csv b/doc/configtables/solar.csv index 93bfd04a..8e57e066 100644 --- a/doc/configtables/solar.csv +++ b/doc/configtables/solar.csv @@ -12,4 +12,4 @@ corine,--,"Any subset of the `CORINE Land Cover code list `_ natural protection areas. Area is excluded if ``true``." potential,--,"One of {'simple', 'conservative'}","Method to compute the maximal installable potential for a node; confer :ref:`renewableprofiles`" clip_p_max_pu,p.u.,float,"To avoid too small values in the renewables` per-unit availability time series values below this threshold are set to zero." -keep_all_available_areas,bool,"{'true', 'false'}","Use all availabe weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed." \ No newline at end of file +keep_all_available_areas,bool,"{'true', 'false'}","Use all availabe weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed." diff --git a/doc/configtables/solving-options.csv b/doc/configtables/solving-options.csv index 0c640684..f77eec24 100644 --- a/doc/configtables/solving-options.csv +++ b/doc/configtables/solving-options.csv @@ -7,4 +7,4 @@ max_iterations,--,int,"Maximum number of solving iterations in between which res nhours,--,int,"Specifies the :math:`n` first snapshots to take into account. Must be less than the total number of snapshots. Rather recommended only for debugging." clip_p_max_pu,p.u.,float,"To avoid too small values in the renewables` per-unit availability time series values below this threshold are set to zero." skip_iterations,bool,"{'true','false'}","Skip iterating, do not update impedances of branches." -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)" \ No newline at end of file +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)" diff --git a/doc/configtables/solving-solver.csv b/doc/configtables/solving-solver.csv index db16d867..3eae6310 100644 --- a/doc/configtables/solving-solver.csv +++ b/doc/configtables/solving-solver.csv @@ -1,3 +1,3 @@ ,Unit,Values,Description name,--,"One of {'gurobi', 'cplex', 'cbc', 'glpk', 'ipopt'}; potentially more possible","Solver to use for optimisation problems in the workflow; e.g. clustering and linear optimal power flow." -opts,--,"Parameter list for `Gurobi `_ and `CPLEX `_","Solver specific parameter settings." \ No newline at end of file +opts,--,"Parameter list for `Gurobi `_ and `CPLEX `_","Solver specific parameter settings." diff --git a/doc/configtables/toplevel.csv b/doc/configtables/toplevel.csv index 7eb7dd61..27df2344 100644 --- a/doc/configtables/toplevel.csv +++ b/doc/configtables/toplevel.csv @@ -13,4 +13,4 @@ enable,,, -- build_cutout,bool,"{true, false}","Switch to enable the building of cutouts via the rule :mod:`build_cutout`." -- retrieve_cutout,bool,"{true, false}","Switch to enable the retrieval of cutouts from zenodo with :mod:`retrieve_cutout`." -- build_natura_raster,bool,"{true, false}","Switch to enable the creation of the raster ``natura.tiff`` via the rule :mod:`build_natura_raster`." --- retrieve_natura_raster,bool,"{true, false}","Switch to enable the retrieval of ``natura.tiff`` from zenodo with :mod:`retrieve_natura_raster`." \ No newline at end of file +-- retrieve_natura_raster,bool,"{true, false}","Switch to enable the retrieval of ``natura.tiff`` from zenodo with :mod:`retrieve_natura_raster`." diff --git a/doc/configtables/transformers.csv b/doc/configtables/transformers.csv index b58ae8f3..0ccd8e87 100644 --- a/doc/configtables/transformers.csv +++ b/doc/configtables/transformers.csv @@ -1,4 +1,4 @@ ,Unit,Values,Description x,p.u.,float,"Series reactance (per unit, using ``s_nom`` as base power of the transformer. Overwritten if ``type`` is specified." s_nom,MVA,float,"Limit of apparent power which can pass through branch. Overwritten if ``type`` is specified." -type,--,"A `transformer type in PyPSA `_.","Specifies transformer types to assume for the transformers of the ENTSO-E grid extraction." \ No newline at end of file +type,--,"A `transformer type in PyPSA `_.","Specifies transformer types to assume for the transformers of the ENTSO-E grid extraction." diff --git a/doc/configuration.rst b/doc/configuration.rst index 265943e8..fa51b51a 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -36,10 +36,10 @@ investment changes as more ambitious greenhouse-gas emission reduction targets a The ``scenario`` section is an extraordinary section of the config file that is strongly connected to the :ref:`wildcards` and is designed to -facilitate running multiple scenarios through a single command +facilitate running multiple scenarios through a single command .. code:: bash - + snakemake -j 1 solve_all_elec_networks For each wildcard, a **list of values** is provided. The rule ``solve_all_elec_networks`` will trigger the rules for creating ``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc`` for **all combinations** of the provided wildcard values as defined by Python's `itertools.product(...) `_ function that snakemake's `expand(...) function `_ uses. diff --git a/doc/costs.rst b/doc/costs.rst index a51acb85..70bd12b8 100644 --- a/doc/costs.rst +++ b/doc/costs.rst @@ -50,4 +50,4 @@ Default Cost Assumptions .. csv-table:: :header-rows: 1 :widths: 10,3,5,4,6,8 - :file: ../data/costs.csv \ No newline at end of file + :file: ../data/costs.csv diff --git a/doc/index.rst b/doc/index.rst index d375cfac..4c15ddf5 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -8,7 +8,7 @@ PyPSA-Eur: An Open Optimisation Model of the European Transmission System .. image:: https://img.shields.io/github/v/release/pypsa/pypsa-eur?include_prereleases :alt: GitHub release (latest by date including pre-releases) - + .. image:: https://travis-ci.org/PyPSA/pypsa-eur.svg?branch=master :target: https://travis-ci.org/PyPSA/pypsa-eur @@ -101,9 +101,9 @@ Documentation simplification solving plotting - + **References** - + * :doc:`release_notes` * :doc:`limitations` * :doc:`contributing` @@ -183,7 +183,7 @@ There are pre-built networks available as a dataset on Zenodo as well for every The included ``.nc`` files are PyPSA network files which can be imported with PyPSA via: .. code:: python - + import pypsa filename = "elec_s_1024_ec.nc" # example @@ -202,7 +202,7 @@ PyPSA-Eur work is released under multiple licenses: See the individual files and the `dep5 <.reuse/dep5>`_ file for license details. Additionally, different licenses and terms of use also apply to the various input data, which are summarised below. -More details are included in +More details are included in `the description of the data bundles on zenodo `_. .. csv-table:: diff --git a/doc/installation.rst b/doc/installation.rst index f50083d3..e1de3f4b 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -1,6 +1,6 @@ .. SPDX-FileCopyrightText: 2019-2020 The PyPSA-Eur Authors - + SPDX-License-Identifier: CC-BY-4.0 .. _installation: @@ -37,12 +37,12 @@ We recommend using the package manager and environment management system ``conda Install `miniconda `_, which is a mini version of `Anaconda `_ that includes only ``conda`` and its dependencies or make sure ``conda`` is already installed on your system. For instructions for your operating system follow the ``conda`` `installation guide `_. -The python package requirements are curated in the `environment.yaml `_ file. +The python package requirements are curated in the `envs/environment.yaml `_ file. The environment can be installed and activated using .. code:: bash - .../pypsa-eur % conda env create -f environment.yaml + .../pypsa-eur % conda env create -f envs/environment.yaml .../pypsa-eur % conda activate pypsa-eur @@ -55,14 +55,14 @@ The environment can be installed and activated using `mamba `_ as a fast drop-in replacement via .. code:: bash - + conda install -c conda-forge mamba and then install the environment with .. code:: bash - mamba env create -f environment.yaml + mamba env create -f envs/environment.yaml Install a Solver ================ @@ -102,10 +102,10 @@ For installation instructions of these solvers for your operating system, follow and on Windows .. code:: bash - + conda activate pypsa-eur conda install -c conda-forge ipopt glpk - + .. _defaultconfig: @@ -113,7 +113,7 @@ Set Up the Default Configuration ================================ PyPSA-Eur has several configuration options that must be specified in a ``config.yaml`` file located in the root directory. -An example configuration ``config.default.yaml`` is maintained in the repository. +An example configuration ``config.default.yaml`` is maintained in the repository. More details on the configuration options are in :ref:`config`. Before first use, create a ``config.yaml`` by copying the example. diff --git a/doc/introduction.rst b/doc/introduction.rst index 96094a9f..9ca049e7 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -1,6 +1,6 @@ .. SPDX-FileCopyrightText: 2019-2020 The PyPSA-Eur Authors - + SPDX-License-Identifier: CC-BY-4.0 .. _intro: @@ -64,4 +64,4 @@ Folder Structure System Requirements =================== -Building the model with the scripts in this repository uses up to 20 GB of memory. Computing optimal investment and operation scenarios requires a strong interior-point solver compatible with the modelling library `Pyomo `_ like `Gurobi `_ or `CPLEX `_ with up to 100 GB of memory. \ No newline at end of file +Building the model with the scripts in this repository uses up to 20 GB of memory. Computing optimal investment and operation scenarios requires a strong interior-point solver compatible with the modelling library `Pyomo `_ like `Gurobi `_ or `CPLEX `_ with up to 100 GB of memory. diff --git a/doc/limitations.rst b/doc/limitations.rst index 16c57ac9..3b6c03d7 100644 --- a/doc/limitations.rst +++ b/doc/limitations.rst @@ -37,7 +37,7 @@ improving the approximations. not spatially disaggregated; assuming, as we have done, that the load time series shape is the same at each node within each country ignores local differences. -- **Currently installed renewable capacities:** +- **Currently installed renewable capacities:** Information on existing wind, solar and small hydro, geothermal, marine and biomass power plants are excluded from the dataset because of a lack of data availability in many countries. Approximate distributions of wind and solar @@ -56,4 +56,3 @@ improving the approximations. Belarus, Ukraine, Turkey and Morocco have not been taken into account; islands which are not connected to the main European system, such as Malta, Crete and Cyprus, are also excluded from the model. - \ No newline at end of file diff --git a/doc/plotting.rst b/doc/plotting.rst index 641d3962..cd404226 100644 --- a/doc/plotting.rst +++ b/doc/plotting.rst @@ -173,4 +173,4 @@ Rule ``plot_network`` .. automodule:: plot_network .. image:: img/tech-colors.png - :align: center \ No newline at end of file + :align: center diff --git a/doc/preparation/base_network.rst b/doc/preparation/base_network.rst index 464b003d..1afc4e05 100644 --- a/doc/preparation/base_network.rst +++ b/doc/preparation/base_network.rst @@ -2,7 +2,7 @@ SPDX-FileCopyrightText: 2019-2020 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 - + .. _base: Rule ``base_network`` @@ -51,4 +51,4 @@ Rule ``base_network`` | -.. automodule:: base_network \ No newline at end of file +.. automodule:: base_network diff --git a/doc/preparation/build_bus_regions.rst b/doc/preparation/build_bus_regions.rst index 6935832e..16aab725 100644 --- a/doc/preparation/build_bus_regions.rst +++ b/doc/preparation/build_bus_regions.rst @@ -48,4 +48,4 @@ Rule ``build_bus_regions`` | -.. automodule:: build_bus_regions \ No newline at end of file +.. automodule:: build_bus_regions diff --git a/doc/preparation/build_cutout.rst b/doc/preparation/build_cutout.rst index 5ad29a97..da2c04d1 100644 --- a/doc/preparation/build_cutout.rst +++ b/doc/preparation/build_cutout.rst @@ -39,4 +39,4 @@ Rule ``build_cutout`` | -.. automodule:: build_cutout \ No newline at end of file +.. automodule:: build_cutout diff --git a/doc/release_notes.rst b/doc/release_notes.rst index f5e3c377..1cae0807 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -23,7 +23,7 @@ Upcoming Release * Corrected setting of exogenous emission price (in config -> cost -> emission price). This was not weighted by the efficiency and effective emission of the generators. Fixed in `#171 `_. -* Don't remove capital costs from lines and links, when imposing a line volume limit (wildcard ``lv``) or a line cost limit (``lc``). Previously, these were removed to move the expansion in direction of the limit. +* Don't remove capital costs from lines and links, when imposing a line volume limit (wildcard ``lv``) or a line cost limit (``lc``). Previously, these were removed to move the expansion in direction of the limit. PyPSA-Eur 0.2.0 (8th June 2020) ================================== @@ -86,7 +86,7 @@ This is the first release of PyPSA-Eur, a model of the European power system at * Hydrogen pipelines (including cost assumptions) can now be added alongside clustered network connections in the rule :mod:`add_extra_components` . Set ``electricity: extendable_carriers: Link: [H2 pipeline]`` and ensure hydrogen storage is modelled as a ``Store``. This is a first simplified stage (`#108 `_). -* Logfiles for all rules of the ``snakemake`` workflow are now written in the folder ``log/`` (`#102 `_). +* Logfiles for all rules of the ``snakemake`` workflow are now written in the folder ``log/`` (`#102 `_). * The new function ``_helpers.mock_snakemake`` creates a ``snakemake`` object which mimics the actual ``snakemake`` object produced by workflow by parsing the ``Snakefile`` and setting all paths for inputs, outputs, and logs. This allows running all scripts within a (I)python terminal (or just by calling ``python ``) and thereby facilitates developing and debugging scripts significantly (`#107 `_). @@ -97,8 +97,8 @@ Release Process * Finalise release notes at ``doc/release_notes.rst``. -* Update ``environment.fixedversions.yaml`` via - ``conda env export -n pypsa-eur -f environment.fixedversions.yaml --no-builds`` +* Update ``envs/environment.fixed.yaml`` via + ``conda env export -n pypsa-eur -f envs/environment.fixed.yaml --no-builds`` from an up-to-date `pypsa-eur` environment. * Update version number in ``doc/conf.py`` and ``*config.*.yaml``. diff --git a/doc/simplification.rst b/doc/simplification.rst index 11d4867f..280b1da0 100644 --- a/doc/simplification.rst +++ b/doc/simplification.rst @@ -22,7 +22,7 @@ After simplification and clustering of the network, additional components may be .. toctree:: :caption: Overview - + simplification/simplify_network simplification/cluster_network simplification/add_extra_components diff --git a/doc/tutorial.rst b/doc/tutorial.rst index eca7dd05..2e96eb5c 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -1,6 +1,6 @@ .. SPDX-FileCopyrightText: 2019-2020 The PyPSA-Eur Authors - + SPDX-License-Identifier: CC-BY-4.0 .. _tutorial: @@ -48,7 +48,7 @@ The model can be adapted to only include selected countries (e.g. Germany) inste .. literalinclude:: ../config.tutorial.yaml :language: yaml :lines: 16 - + Likewise, the example's temporal scope can be restricted (e.g. to a single month). .. literalinclude:: ../config.tutorial.yaml @@ -132,7 +132,7 @@ orders ``snakemake`` to run the script ``solve_network`` that produces the solve Windows users should add the option ``--keep-target-files`` to the command or instead run ``snakemake -j 1 solve_all_elec_networks``. This triggers a workflow of multiple preceding jobs that depend on each rule's inputs and outputs: - + .. graphviz:: :align: center @@ -184,7 +184,7 @@ This triggers a workflow of multiple preceding jobs that depend on each rule's i 7 -> 11 5 -> 11 12 -> 11 - } + } | @@ -229,8 +229,8 @@ A job (here ``simplify_network``) will display its attributes and normally some INFO:__main__:Mapping all network lines onto a single 380kV layer INFO:__main__:Simplifying connected link components INFO:__main__:Removing stubs - INFO:__main__:Displacing offwind-ac generator(s) and adding connection costs to capital_costs: 20128 Eur/MW/a for `5718 offwind-ac` - INFO:__main__:Displacing offwind-dc generator(s) and adding connection costs to capital_costs: 14994 Eur/MW/a for `5718 offwind-dc`, 26939 Eur/MW/a for `5724 offwind-dc`, 29621 Eur/MW/a for `5725 offwind-dc` + INFO:__main__:Displacing offwind-ac generator(s) and adding connection costs to capital_costs: 20128 Eur/MW/a for `5718 offwind-ac` + INFO:__main__:Displacing offwind-dc generator(s) and adding connection costs to capital_costs: 14994 Eur/MW/a for `5718 offwind-dc`, 26939 Eur/MW/a for `5724 offwind-dc`, 29621 Eur/MW/a for `5725 offwind-dc` INFO:pypsa.io:Exported network elec_s.nc has lines, carriers, links, storage_units, loads, buses, generators [] Finished job 3. @@ -293,5 +293,5 @@ For inspiration, read the `examples section in the PyPSA documentation =0.17.1 - atlite=0.0.3 # Dependencies of the workflow itself - #- xlrd - scikit-learn - pycountry - seaborn - #- snakemake-minimal - memory_profiler - yaml - pytables @@ -25,28 +21,19 @@ dependencies: # Second order dependencies which should really be deps of atlite - xarray - #- netcdf4 - #- bottleneck - #- toolz - #- dask - progressbar2 - pyyaml>=5.1.0 - # Include ipython so that one does not inadvertently drop out of the conda - # environment by calling ipython - # - ipython - # GIS dependencies have to come all from conda-forge - - conda-forge::cartopy - - conda-forge::fiona - - conda-forge::proj - - conda-forge::pyshp - - conda-forge::geopandas - - conda-forge::rasterio - - conda-forge::shapely - - conda-forge::libgdal + - cartopy + - fiona + - proj + - pyshp + - geopandas + - rasterio + - shapely + - libgdal - # The FRESNA/KIT stuff is not packaged for conda yet - pip: - vresutils==0.3.1 - git+https://github.com/PyPSA/glaes.git#egg=glaes diff --git a/environment.fixedversions.yaml b/envs/environment.fixed.yaml similarity index 100% rename from environment.fixedversions.yaml rename to envs/environment.fixed.yaml diff --git a/environment.yaml b/envs/environment.yaml similarity index 100% rename from environment.yaml rename to envs/environment.yaml diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 14667679..c11c27f5 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -373,7 +373,7 @@ def attach_hydro(n, costs, ppl): .where(lambda df: df<=1., other=1.))) if 'PHS' in carriers and not phs.empty: - # fill missing max hours to config value and + # fill missing max hours to config value and # assume no natural inflow due to lack of data phs = phs.replace({'max_hours': {0: c['PHS_max_hours']}}) n.madd('StorageUnit', phs.index, diff --git a/scripts/base_network.py b/scripts/base_network.py index 034eeb2f..d2ceccf1 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -312,18 +312,18 @@ def _set_electrical_parameters_links(links): links['p_min_pu'] = -p_max_pu links_p_nom = pd.read_csv(snakemake.input.links_p_nom) - - # filter links that are not in operation anymore + + # filter links that are not in operation anymore removed_b = links_p_nom.Remarks.str.contains('Shut down|Replaced', na=False) links_p_nom = links_p_nom[~removed_b] - - # find closest link for all links in links_p_nom + + # find closest link for all links in links_p_nom links_p_nom['j'] = _find_closest_links(links, links_p_nom) - - links_p_nom = links_p_nom.groupby(['j'],as_index=False).agg({'Power (MW)': 'sum'}) - + + links_p_nom = links_p_nom.groupby(['j'],as_index=False).agg({'Power (MW)': 'sum'}) + p_nom = links_p_nom.dropna(subset=["j"]).set_index("j")["Power (MW)"] - + # Don't update p_nom if it's already set p_nom_unset = p_nom.drop(links.index[links.p_nom.notnull()], errors='ignore') if "p_nom" in links else p_nom links.loc[p_nom_unset.index, "p_nom"] = p_nom_unset diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 2c384926..fc054a10 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -115,7 +115,7 @@ Exemplary unsolved network clustered to 37 nodes: .. image:: ../img/elec_s_37.png :scale: 40 % - :align: center + :align: center """ diff --git a/scripts/make_summary.py b/scripts/make_summary.py index ac0119ab..ada3fa8a 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -307,7 +307,7 @@ def calculate_prices(n,label,prices): def calculate_weighted_prices(n,label,weighted_prices): - + logger.warning("Weighted prices don't include storage units as loads") weighted_prices = weighted_prices.reindex(pd.Index(["electricity","heat","space heat","urban heat","space urban heat","gas","H2"])) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index bb7640be..f790db8f 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -131,7 +131,7 @@ def set_transmission_limit(n, ll_type, factor, Nyears=1): n.add('GlobalConstraint', f'l{ll_type}_limit', type=f'transmission_{con_type}_limit', sense='<=', constant=rhs, carrier_attribute='AC, DC') - + return n diff --git a/test/config.test1.yaml b/test/config.test1.yaml index 048b0ed3..5276adfb 100755 --- a/test/config.test1.yaml +++ b/test/config.test1.yaml @@ -186,4 +186,3 @@ solving: # solutiontype: 2 # non basic solution, ie no crossover # barrier_convergetol: 1.e-5 # feasopt_tolerance: 1.e-6 - From dd4621095210445b72cf1136fc88ab9d4aea4f5b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 11 Sep 2020 15:34:03 +0200 Subject: [PATCH 003/591] pre-commit: limit large files --- .pre-commit-config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c5d05ee9..d04178b6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,4 +5,6 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml + - id: check-merge-conflict - id: check-added-large-files + args: ['--maxkb=2000'] From 570154fa78fdc77056e6bec8d8dd1a3cf365e9e2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 11 Sep 2020 15:41:23 +0200 Subject: [PATCH 004/591] add license to .pre-commit --- .pre-commit-config.yaml | 8 ++++++++ {.licenses => LICENSES}/CC-BY-4.0.txt | 0 {.licenses => LICENSES}/CC0-1.0.txt | 0 {.licenses => LICENSES}/GPL-3.0-or-later.txt | 0 4 files changed, 8 insertions(+) rename {.licenses => LICENSES}/CC-BY-4.0.txt (100%) rename {.licenses => LICENSES}/CC0-1.0.txt (100%) rename {.licenses => LICENSES}/GPL-3.0-or-later.txt (100%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d04178b6..f590f447 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: : 2017-2020 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: CC0-1.0 + repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.4.0 @@ -8,3 +12,7 @@ repos: - id: check-merge-conflict - id: check-added-large-files args: ['--maxkb=2000'] +- repo: https://github.com/fsfe/reuse-tool + rev: latest + hooks: + - id: reuse diff --git a/.licenses/CC-BY-4.0.txt b/LICENSES/CC-BY-4.0.txt similarity index 100% rename from .licenses/CC-BY-4.0.txt rename to LICENSES/CC-BY-4.0.txt diff --git a/.licenses/CC0-1.0.txt b/LICENSES/CC0-1.0.txt similarity index 100% rename from .licenses/CC0-1.0.txt rename to LICENSES/CC0-1.0.txt diff --git a/.licenses/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt similarity index 100% rename from .licenses/GPL-3.0-or-later.txt rename to LICENSES/GPL-3.0-or-later.txt From 098448668b650b922fc8efa268f2dd34a2efb3bb Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 11 Sep 2020 15:43:14 +0200 Subject: [PATCH 005/591] add pre-commit to env --- envs/environment.docs.yaml | 1 + envs/environment.yaml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/envs/environment.docs.yaml b/envs/environment.docs.yaml index 11597d92..fc141a02 100755 --- a/envs/environment.docs.yaml +++ b/envs/environment.docs.yaml @@ -9,6 +9,7 @@ dependencies: - pip - pypsa>=0.17.1 - atlite=0.0.3 + - pre-commit # Dependencies of the workflow itself - scikit-learn diff --git a/envs/environment.yaml b/envs/environment.yaml index ce49420f..fb4019a3 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -11,6 +11,7 @@ channels: dependencies: - python - pip + - pre-commit - pypsa>=0.17.1 - atlite=0.0.3 @@ -36,8 +37,7 @@ dependencies: - progressbar2 - pyyaml>=5.1.0 - # Include ipython so that one does not inadvertently drop out of the conda - # environment by calling ipython + # Keep in conda environment when calling ipython - ipython # GIS dependencies: From 78ca48c602a10470a2220eda7aac0f7eed628e51 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 11 Sep 2020 15:44:25 +0200 Subject: [PATCH 006/591] solve: tidy memory logger --- scripts/solve_network.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 5ec515c3..ace8575f 100755 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -254,8 +254,8 @@ if __name__ == "__main__": opts = snakemake.wildcards.opts.split('-') solve_opts = snakemake.config['solving']['options'] - with memory_logger(filename=getattr(snakemake.log, 'memory', None), - interval=30.) as mem: + fn = getattr(snakemake.log, 'memory', None) + with memory_logger(filename=fn, interval=30.) as mem: n = pypsa.Network(snakemake.input[0]) n = prepare_network(n, solve_opts) n = solve_network(n, config=snakemake.config, solver_dir=tmpdir, From 1e4f6f9568b1049c4da45d70356dd446a45723c0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 25 Sep 2020 12:45:43 +0200 Subject: [PATCH 007/591] travis: add conda list for easier debugging --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 75c5d524..011753f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,9 @@ before_install: # install open-source solver - mamba install -c conda-forge ipopt glpk + # list packages for easier debugging + - conda list + script: - cp ./test/config.test1.yaml ./config.yaml - snakemake -j all solve_all_elec_networks From f3b1d3d5133e1d9a635d72c6d35cafceaddae74b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 3 Oct 2020 11:38:51 +0200 Subject: [PATCH 008/591] undo config test/tutorial without plotting, rm matplotlibrc, .licenses --- config.tutorial.yaml | 80 ++++++++++++++++++++++++++++++++++++++++++ doc/index.rst | 8 ++--- matplotlibrc | 1 + test/config.test1.yaml | 80 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 matplotlibrc diff --git a/config.tutorial.yaml b/config.tutorial.yaml index 3f4b6853..174708cb 100755 --- a/config.tutorial.yaml +++ b/config.tutorial.yaml @@ -172,3 +172,83 @@ solving: track_iterations: false solver: name: cbc + +plotting: + map: + figsize: [7, 7] + boundaries: [-10.2, 29, 35, 72] + p_nom: + bus_size_factor: 5.e+4 + linewidth_factor: 3.e+3 + + costs_max: 800 + costs_threshold: 1 + + energy_max: 15000. + energy_min: -10000. + energy_threshold: 50. + + vre_techs: ["onwind", "offwind-ac", "offwind-dc", "solar", "ror"] + conv_techs: ["OCGT", "CCGT", "Nuclear", "Coal"] + storage_techs: ["hydro+PHS", "battery", "H2"] + load_carriers: ["AC load"] + AC_carriers: ["AC line", "AC transformer"] + link_carriers: ["DC line", "Converter AC-DC"] + tech_colors: + "onwind" : "#235ebc" + "onshore wind" : "#235ebc" + 'offwind' : "#6895dd" + 'offwind-ac' : "#6895dd" + 'offshore wind' : "#6895dd" + 'offshore wind ac' : "#6895dd" + 'offwind-dc' : "#74c6f2" + 'offshore wind dc' : "#74c6f2" + "hydro" : "#08ad97" + "hydro+PHS" : "#08ad97" + "PHS" : "#08ad97" + "hydro reservoir" : "#08ad97" + 'hydroelectricity' : '#08ad97' + "ror" : "#4adbc8" + "run of river" : "#4adbc8" + 'solar' : "#f9d002" + 'solar PV' : "#f9d002" + 'solar thermal' : '#ffef60' + 'biomass' : '#0c6013' + 'solid biomass' : '#06540d' + 'biogas' : '#23932d' + 'waste' : '#68896b' + 'geothermal' : '#ba91b1' + "OCGT" : "#d35050" + "gas" : "#d35050" + "natural gas" : "#d35050" + "CCGT" : "#b20101" + "nuclear" : "#ff9000" + "coal" : "#707070" + "lignite" : "#9e5a01" + "oil" : "#262626" + "H2" : "#ea048a" + "hydrogen storage" : "#ea048a" + "battery" : "#b8ea04" + "Electric load" : "#f9d002" + "electricity" : "#f9d002" + "lines" : "#70af1d" + "transmission lines" : "#70af1d" + "AC-AC" : "#70af1d" + "AC line" : "#70af1d" + "links" : "#8a1caf" + "HVDC links" : "#8a1caf" + "DC-DC" : "#8a1caf" + "DC link" : "#8a1caf" + 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" diff --git a/doc/index.rst b/doc/index.rst index 4c15ddf5..d8d9c852 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -194,10 +194,10 @@ Licence PyPSA-Eur work is released under multiple licenses: -* All original source code is licensed as free software under `GPL-3.0-or-later <.licenses/GPL-3.0-or-later.txt>`_. -* The documentation is licensed under `CC-BY-4.0 <.licenses/CC-BY-4.0.txt>`_. -* Configuration files are mostly licensed under `CC0-1.0 <.licenses/CC0-1.0.txt>`_. -* Data files are licensed under `CC-BY-4.0 <.licenses/CC-BY-4.0.txt>`_. +* All original source code is licensed as free software under `GPL-3.0-or-later `_. +* The documentation is licensed under `CC-BY-4.0 `_. +* Configuration files are mostly licensed under `CC0-1.0 `_. +* Data files are licensed under `CC-BY-4.0 `_. See the individual files and the `dep5 <.reuse/dep5>`_ file for license details. diff --git a/matplotlibrc b/matplotlibrc new file mode 100644 index 00000000..13468274 --- /dev/null +++ b/matplotlibrc @@ -0,0 +1 @@ +backend : Agg diff --git a/test/config.test1.yaml b/test/config.test1.yaml index 011169b9..84d551e6 100755 --- a/test/config.test1.yaml +++ b/test/config.test1.yaml @@ -188,3 +188,83 @@ solving: # solutiontype: 2 # non basic solution, ie no crossover # barrier_convergetol: 1.e-5 # feasopt_tolerance: 1.e-6 + +plotting: + map: + figsize: [7, 7] + boundaries: [-10.2, 29, 35, 72] + p_nom: + bus_size_factor: 5.e+4 + linewidth_factor: 3.e+3 + + costs_max: 800 + costs_threshold: 1 + + energy_max: 15000. + energy_min: -10000. + energy_threshold: 50. + + vre_techs: ["onwind", "offwind-ac", "offwind-dc", "solar", "ror"] + conv_techs: ["OCGT", "CCGT", "Nuclear", "Coal"] + storage_techs: ["hydro+PHS", "battery", "H2"] + load_carriers: ["AC load"] + AC_carriers: ["AC line", "AC transformer"] + link_carriers: ["DC line", "Converter AC-DC"] + tech_colors: + "onwind" : "#235ebc" + "onshore wind" : "#235ebc" + 'offwind' : "#6895dd" + 'offwind-ac' : "#6895dd" + 'offshore wind' : "#6895dd" + 'offshore wind ac' : "#6895dd" + 'offwind-dc' : "#74c6f2" + 'offshore wind dc' : "#74c6f2" + "hydro" : "#08ad97" + "hydro+PHS" : "#08ad97" + "PHS" : "#08ad97" + "hydro reservoir" : "#08ad97" + 'hydroelectricity' : '#08ad97' + "ror" : "#4adbc8" + "run of river" : "#4adbc8" + 'solar' : "#f9d002" + 'solar PV' : "#f9d002" + 'solar thermal' : '#ffef60' + 'biomass' : '#0c6013' + 'solid biomass' : '#06540d' + 'biogas' : '#23932d' + 'waste' : '#68896b' + 'geothermal' : '#ba91b1' + "OCGT" : "#d35050" + "gas" : "#d35050" + "natural gas" : "#d35050" + "CCGT" : "#b20101" + "nuclear" : "#ff9000" + "coal" : "#707070" + "lignite" : "#9e5a01" + "oil" : "#262626" + "H2" : "#ea048a" + "hydrogen storage" : "#ea048a" + "battery" : "#b8ea04" + "Electric load" : "#f9d002" + "electricity" : "#f9d002" + "lines" : "#70af1d" + "transmission lines" : "#70af1d" + "AC-AC" : "#70af1d" + "AC line" : "#70af1d" + "links" : "#8a1caf" + "HVDC links" : "#8a1caf" + "DC-DC" : "#8a1caf" + "DC link" : "#8a1caf" + 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" From bcd7f86b5c6928ce7c03c4a9b0cad27419e76040 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 9 Oct 2020 17:03:49 +0200 Subject: [PATCH 009/591] remove {networks} wildcard --- Snakefile | 104 ++++++++++++++-------------- doc/tutorial.rst | 4 +- scripts/add_extra_components.py | 4 +- scripts/cluster_network.py | 16 ++--- scripts/prepare_network.py | 4 +- scripts/simplify_network.py | 10 +-- scripts/solve_network.py | 4 +- scripts/solve_operations_network.py | 6 +- 8 files changed, 76 insertions(+), 76 deletions(-) diff --git a/Snakefile b/Snakefile index 7a532f30..cd42835e 100644 --- a/Snakefile +++ b/Snakefile @@ -222,17 +222,17 @@ rule add_electricity: rule simplify_network: input: - network='networks/{network}.nc', + network='networks/elec.nc', tech_costs=COSTS, regions_onshore="resources/regions_onshore.geojson", regions_offshore="resources/regions_offshore.geojson" output: - network='networks/{network}_s{simpl}.nc', - regions_onshore="resources/regions_onshore_{network}_s{simpl}.geojson", - regions_offshore="resources/regions_offshore_{network}_s{simpl}.geojson", - busmap='resources/busmap_{network}_s{simpl}.csv' - log: "logs/simplify_network/{network}_s{simpl}.log" - benchmark: "benchmarks/simplify_network/{network}_s{simpl}" + network='networks/elec_s{simpl}.nc', + regions_onshore="resources/regions_onshore_elec_s{simpl}.geojson", + regions_offshore="resources/regions_offshore_elec_s{simpl}.geojson", + busmap='resources/busmap_elec_s{simpl}.csv' + log: "logs/simplify_network/elec_s{simpl}.log" + benchmark: "benchmarks/simplify_network/elec_s{simpl}" threads: 1 resources: mem=4000 script: "scripts/simplify_network.py" @@ -240,19 +240,19 @@ rule simplify_network: rule cluster_network: input: - network='networks/{network}_s{simpl}.nc', - regions_onshore="resources/regions_onshore_{network}_s{simpl}.geojson", - regions_offshore="resources/regions_offshore_{network}_s{simpl}.geojson", - busmap=ancient('resources/busmap_{network}_s{simpl}.csv'), + network='networks/elec_s{simpl}.nc', + regions_onshore="resources/regions_onshore_elec_s{simpl}.geojson", + regions_offshore="resources/regions_offshore_elec_s{simpl}.geojson", + busmap=ancient('resources/busmap_elec_s{simpl}.csv'), tech_costs=COSTS output: - network='networks/{network}_s{simpl}_{clusters}.nc', - regions_onshore="resources/regions_onshore_{network}_s{simpl}_{clusters}.geojson", - regions_offshore="resources/regions_offshore_{network}_s{simpl}_{clusters}.geojson", - busmap="resources/busmap_{network}_s{simpl}_{clusters}.csv", - linemap="resources/linemap_{network}_s{simpl}_{clusters}.csv" - log: "logs/cluster_network/{network}_s{simpl}_{clusters}.log" - benchmark: "benchmarks/cluster_network/{network}_s{simpl}_{clusters}" + network='networks/elec_s{simpl}_{clusters}.nc', + regions_onshore="resources/regions_onshore_elec_s{simpl}_{clusters}.geojson", + regions_offshore="resources/regions_offshore_elec_s{simpl}_{clusters}.geojson", + busmap="resources/busmap_elec_s{simpl}_{clusters}.csv", + linemap="resources/linemap_elec_s{simpl}_{clusters}.csv" + log: "logs/cluster_network/elec_s{simpl}_{clusters}.log" + benchmark: "benchmarks/cluster_network/elec_s{simpl}_{clusters}" threads: 1 resources: mem=3000 script: "scripts/cluster_network.py" @@ -260,21 +260,21 @@ rule cluster_network: rule add_extra_components: input: - network='networks/{network}_s{simpl}_{clusters}.nc', + network='networks/elec_s{simpl}_{clusters}.nc', tech_costs=COSTS, - output: 'networks/{network}_s{simpl}_{clusters}_ec.nc' - log: "logs/add_extra_components/{network}_s{simpl}_{clusters}.log" - benchmark: "benchmarks/add_extra_components/{network}_s{simpl}_{clusters}_ec" + output: 'networks/elec_s{simpl}_{clusters}_ec.nc' + log: "logs/add_extra_components/elec_s{simpl}_{clusters}.log" + benchmark: "benchmarks/add_extra_components/elec_s{simpl}_{clusters}_ec" threads: 1 resources: mem=3000 script: "scripts/add_extra_components.py" rule prepare_network: - input: 'networks/{network}_s{simpl}_{clusters}_ec.nc', tech_costs=COSTS - output: 'networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc' - log: "logs/prepare_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" - benchmark: "benchmarks/prepare_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + input: 'networks/elec_s{simpl}_{clusters}_ec.nc', tech_costs=COSTS + output: 'networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc' + log: "logs/prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" + benchmark: "benchmarks/prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: 1 resources: mem=1000 script: "scripts/prepare_network.py" @@ -294,13 +294,13 @@ def memory(w): rule solve_network: - input: "networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - output: "results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + input: "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + output: "results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" log: - solver=normpath("logs/solve_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log"), - python="logs/solve_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", - memory="logs/solve_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_memory.log" - benchmark: "benchmarks/solve_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + solver=normpath("logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log"), + python="logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", + memory="logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_memory.log" + benchmark: "benchmarks/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: 4 resources: mem=memory shadow: "shallow" @@ -309,14 +309,14 @@ rule solve_network: rule solve_operations_network: input: - unprepared="networks/{network}_s{simpl}_{clusters}_ec.nc", - optimized="results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - output: "results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc" + unprepared="networks/elec_s{simpl}_{clusters}_ec.nc", + optimized="results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + output: "results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc" log: - solver=normpath("logs/solve_operations_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log"), - python="logs/solve_operations_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log", - memory="logs/solve_operations_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_memory.log" - benchmark: "benchmarks/solve_operations_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + solver=normpath("logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log"), + python="logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log", + memory="logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_memory.log" + benchmark: "benchmarks/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: 4 resources: mem=(lambda w: 5000 + 372 * int(w.clusters)) shadow: "shallow" @@ -325,12 +325,12 @@ rule solve_operations_network: rule plot_network: input: - network="results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network="results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", tech_costs=COSTS output: - only_map="results/plots/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}.{ext}", - ext="results/plots/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}_ext.{ext}" - log: "logs/plot_network/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}_{ext}.log" + only_map="results/plots/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}.{ext}", + ext="results/plots/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}_ext.{ext}" + log: "logs/plot_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}_{ext}.log" script: "scripts/plot_network.py" @@ -343,7 +343,7 @@ def input_make_summary(w): else: ll = w.ll return ([COSTS] + - expand("results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + expand("results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", network=w.network, ll=ll, **{k: config["scenario"][k] if getattr(w, k) == "all" else getattr(w, k) @@ -352,28 +352,28 @@ def input_make_summary(w): rule make_summary: input: input_make_summary - output: directory("results/summaries/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}") - log: "logs/make_summary/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.log", + output: directory("results/summaries/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}") + log: "logs/make_summary/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.log", script: "scripts/make_summary.py" rule plot_summary: - input: "results/summaries/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}" - output: "results/plots/summary_{summary}_{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.{ext}" - log: "logs/plot_summary/{summary}_{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}_{ext}.log" + input: "results/summaries/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}" + output: "results/plots/summary_{summary}_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.{ext}" + log: "logs/plot_summary/{summary}_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}_{ext}.log" script: "scripts/plot_summary.py" def input_plot_p_nom_max(w): - return [("networks/{network}_s{simpl}{maybe_cluster}.nc" + return [("networks/elec_s{simpl}{maybe_cluster}.nc" .format(maybe_cluster=('' if c == 'full' else ('_' + c)), **w)) for c in w.clusts.split(",")] rule plot_p_nom_max: input: input_plot_p_nom_max - output: "results/plots/{network}_s{simpl}_cum_p_nom_max_{clusts}_{techs}_{country}.{ext}" - log: "logs/plot_p_nom_max/{network}_s{simpl}_{clusts}_{techs}_{country}_{ext}.log" + output: "results/plots/elec_s{simpl}_cum_p_nom_max_{clusts}_{techs}_{country}.{ext}" + log: "logs/plot_p_nom_max/elec_s{simpl}_{clusts}_{techs}_{country}_{ext}.log" script: "scripts/plot_p_nom_max.py" diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 67dab57c..3772bc43 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -119,8 +119,8 @@ orders ``snakemake`` to run the script ``solve_network`` that produces the solve .. code:: rule solve_network: - input: "networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - output: "results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + input: "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + output: "results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" [...] script: "scripts/solve_network.py" diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index d0b627a3..a7814ac6 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -37,13 +37,13 @@ Inputs Outputs ------- -- ``networks/{network}_s{simpl}_{clusters}_ec.nc``: +- ``networks/elec_s{simpl}_{clusters}_ec.nc``: Description ----------- -The rule :mod:`add_extra_components` attaches additional extendable components to the clustered and simplified network. These can be configured in the ``config.yaml`` at ``electricity: extendable_carriers: ``. It processes ``networks/{network}_s{simpl}_{clusters}.nc`` to build ``networks/{network}_s{simpl}_{clusters}_ec.nc``, which in contrast to the former (depending on the configuration) contain with **zero** initial capacity +The rule :mod:`add_extra_components` attaches additional extendable components to the clustered and simplified network. These can be configured in the ``config.yaml`` at ``electricity: extendable_carriers: ``. It processes ``networks/elec_s{simpl}_{clusters}.nc`` to build ``networks/elec_s{simpl}_{clusters}_ec.nc``, which in contrast to the former (depending on the configuration) contain with **zero** initial capacity - ``StorageUnits`` of carrier 'H2' and/or 'battery'. If this option is chosen, every bus is given an extendable ``StorageUnit`` of the corresponding carrier. The energy and power capacities are linked through a parameter that specifies the energy capacity as maximum hours at full dispatch power and is configured in ``electricity: max_hours:``. This linkage leads to one investment variable per storage unit. The default ``max_hours`` lead to long-term hydrogen and short-term battery storage units. diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 948b7cf3..47da0b24 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -31,26 +31,26 @@ Relevant Settings Inputs ------ -- ``resources/regions_onshore_{network}_s{simpl}.geojson``: confer :ref:`simplify` -- ``resources/regions_offshore_{network}_s{simpl}.geojson``: confer :ref:`simplify` -- ``resources/clustermaps_{network}_s{simpl}.h5``: confer :ref:`simplify` -- ``networks/{network}_s{simpl}.nc``: confer :ref:`simplify` +- ``resources/regions_onshore_elec_s{simpl}.geojson``: confer :ref:`simplify` +- ``resources/regions_offshore_elec_s{simpl}.geojson``: confer :ref:`simplify` +- ``resources/clustermaps_elec_s{simpl}.h5``: confer :ref:`simplify` +- ``networks/elec_s{simpl}.nc``: confer :ref:`simplify` Outputs ------- -- ``resources/regions_onshore_{network}_s{simpl}_{clusters}.geojson``: +- ``resources/regions_onshore_elec_s{simpl}_{clusters}.geojson``: .. image:: ../img/regions_onshore_elec_s_X.png :scale: 33 % -- ``resources/regions_offshore_{network}_s{simpl}_{clusters}.geojson``: +- ``resources/regions_offshore_elec_s{simpl}_{clusters}.geojson``: .. image:: ../img/regions_offshore_elec_s_X.png :scale: 33 % -- ``resources/clustermaps_{network}_s{simpl}_{clusters}.h5``: Mapping of buses and lines from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; has keys ['/busmap', '/busmap_s', '/linemap', '/linemap_negative', '/linemap_positive'] -- ``networks/{network}_s{simpl}_{clusters}.nc``: +- ``resources/clustermaps_elec_s{simpl}_{clusters}.h5``: Mapping of buses and lines from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; has keys ['/busmap', '/busmap_s', '/linemap', '/linemap_negative', '/linemap_positive'] +- ``networks/elec_s{simpl}_{clusters}.nc``: .. image:: ../img/elec_s_X.png :scale: 40 % diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 7baab77f..a98c63fa 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -37,12 +37,12 @@ Inputs ------ - ``data/costs.csv``: The database of cost assumptions for all included technologies for specific years from various sources; e.g. discount rate, lifetime, investment (CAPEX), fixed operation and maintenance (FOM), variable operation and maintenance (VOM), fuel costs, efficiency, carbon-dioxide intensity. -- ``networks/{network}_s{simpl}_{clusters}.nc``: confer :ref:`cluster` +- ``networks/elec_s{simpl}_{clusters}.nc``: confer :ref:`cluster` Outputs ------- -- ``networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Complete PyPSA network that will be handed to the ``solve_network`` rule. +- ``networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Complete PyPSA network that will be handed to the ``solve_network`` rule. Description ----------- diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index a6d6e613..eb6dbe6b 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -47,23 +47,23 @@ Inputs - ``data/costs.csv``: The database of cost assumptions for all included technologies for specific years from various sources; e.g. discount rate, lifetime, investment (CAPEX), fixed operation and maintenance (FOM), variable operation and maintenance (VOM), fuel costs, efficiency, carbon-dioxide intensity. - ``resources/regions_onshore.geojson``: confer :ref:`busregions` - ``resources/regions_offshore.geojson``: confer :ref:`busregions` -- ``networks/{network}.nc``: confer :ref:`electricity` +- ``networks/elec.nc``: confer :ref:`electricity` Outputs ------- -- ``resources/regions_onshore_{network}_s{simpl}.geojson``: +- ``resources/regions_onshore_elec_s{simpl}.geojson``: .. image:: ../img/regions_onshore_elec_s.png :scale: 33 % -- ``resources/regions_offshore_{network}_s{simpl}.geojson``: +- ``resources/regions_offshore_elec_s{simpl}.geojson``: .. image:: ../img/regions_offshore_elec_s .png :scale: 33 % -- ``resources/clustermaps_{network}_s{simpl}.h5``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec_s{simpl}.nc``; has keys ['/busmap_s'] -- ``networks/{network}_s{simpl}.nc``: +- ``resources/clustermaps_elec_s{simpl}.h5``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec_s{simpl}.nc``; has keys ['/busmap_s'] +- ``networks/elec_s{simpl}.nc``: .. image:: ../img/elec_s.png :scale: 33 % diff --git a/scripts/solve_network.py b/scripts/solve_network.py index d88b7007..e6936db6 100755 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -40,12 +40,12 @@ Relevant Settings Inputs ------ -- ``networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: confer :ref:`prepare` +- ``networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: confer :ref:`prepare` Outputs ------- -- ``results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Solved PyPSA network including optimisation results +- ``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Solved PyPSA network including optimisation results .. image:: ../img/results.png :scale: 40 % diff --git a/scripts/solve_operations_network.py b/scripts/solve_operations_network.py index 3b2089ca..c65e6889 100644 --- a/scripts/solve_operations_network.py +++ b/scripts/solve_operations_network.py @@ -32,13 +32,13 @@ Relevant Settings Inputs ------ -- ``networks/{network}_s{simpl}_{clusters}.nc``: confer :ref:`cluster` -- ``results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: confer :ref:`solve` +- ``networks/elec_s{simpl}_{clusters}.nc``: confer :ref:`cluster` +- ``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: confer :ref:`solve` Outputs ------- -- ``results/networks/{network}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc``: Solved PyPSA network for optimal dispatch including optimisation results +- ``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc``: Solved PyPSA network for optimal dispatch including optimisation results Description ----------- From cb2b78ad97f0ee876df963fbad59957485c4cfd7 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Oct 2020 14:25:12 +0200 Subject: [PATCH 010/591] first step towards sweeping through multiple weather years --- Snakefile | 139 ++++++++++++++-------------- config.default.yaml | 1 + config.tutorial.yaml | 1 + scripts/add_electricity.py | 6 ++ scripts/base_network.py | 7 +- scripts/build_country_flh.py | 4 +- scripts/build_cutout.py | 1 + scripts/build_renewable_profiles.py | 4 +- test/config.test1.yaml | 1 + 9 files changed, 87 insertions(+), 77 deletions(-) diff --git a/Snakefile b/Snakefile index cd42835e..fb04256b 100644 --- a/Snakefile +++ b/Snakefile @@ -15,26 +15,27 @@ ATLITE_NPROCESSES = config['atlite'].get('nprocesses', 4) wildcard_constraints: + year="[0-9]*", simpl="[a-zA-Z0-9]*|all", clusters="[0-9]+m?|all", ll="(v|c)([0-9\.]+|opt|all)|all", opts="[-+a-zA-Z0-9\.]*" -rule cluster_all_elec_networks: - input: expand("networks/elec_s{simpl}_{clusters}.nc", **config['scenario']) +rule cluster_all_networks: + input: expand("networks/elec{year}_s{simpl}_{clusters}.nc", **config['scenario']) -rule extra_components_all_elec_networks: - input: expand("networks/elec_s{simpl}_{clusters}_ec.nc", **config['scenario']) +rule extra_components_all_networks: + input: expand("networks/elec{year}_s{simpl}_{clusters}_ec.nc", **config['scenario']) -rule prepare_all_elec_networks: - input: expand("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config['scenario']) +rule prepare_all_networks: + input: expand("networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config['scenario']) -rule solve_all_elec_networks: - input: expand("results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config['scenario']) +rule solve_all_networks: + input: expand("results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config['scenario']) if config['enable'].get('prepare_links_p_nom', False): @@ -180,9 +181,9 @@ rule build_renewable_profiles: else "resources/regions_offshore.geojson"), cutout=lambda w: "cutouts/" + config["renewable"][w.technology]['cutout'] output: - profile="resources/profile_{technology}.nc", - log: "logs/build_renewable_profile_{technology}.log" - benchmark: "benchmarks/build_renewable_profiles_{technology}" + profile="resources/profile{year}_{technology}.nc", + log: "logs/build_renewable_profile{year}_{technology}.log" + benchmark: "benchmarks/build_renewable_profiles{year}_{technology}" threads: ATLITE_NPROCESSES resources: mem=ATLITE_NPROCESSES * 5000 script: "scripts/build_renewable_profiles.py" @@ -194,8 +195,8 @@ if 'hydro' in config['renewable'].keys(): country_shapes='resources/country_shapes.geojson', eia_hydro_generation='data/bundle/EIA_hydro_generation_2000_2014.csv', cutout="cutouts/" + config["renewable"]['hydro']['cutout'] - output: 'resources/profile_hydro.nc' - log: "logs/build_hydro_profile.log" + output: 'resources/profile{year}_hydro.nc' + log: "logs/build_hydro_profile{year}.log" resources: mem=5000 script: 'scripts/build_hydro_profile.py' @@ -210,11 +211,11 @@ rule add_electricity: geth_hydro_capacities='data/geth2015_hydro_capacities.csv', opsd_load='data/bundle/time_series_60min_singleindex_filtered.csv', nuts3_shapes='resources/nuts3_shapes.geojson', - **{f"profile_{tech}": f"resources/profile_{tech}.nc" + **{f"profile_{tech}": "resources/profile{year}_" + f"{tech}.nc" for tech in config['renewable']} - output: "networks/elec.nc" - log: "logs/add_electricity.log" - benchmark: "benchmarks/add_electricity" + output: "networks/elec{year}.nc" + log: "logs/add_electricity{year}.log" + benchmark: "benchmarks/add_electricity{year}" threads: 1 resources: mem=3000 script: "scripts/add_electricity.py" @@ -222,17 +223,17 @@ rule add_electricity: rule simplify_network: input: - network='networks/elec.nc', + network='networks/elec{year}.nc', tech_costs=COSTS, regions_onshore="resources/regions_onshore.geojson", regions_offshore="resources/regions_offshore.geojson" output: - network='networks/elec_s{simpl}.nc', - regions_onshore="resources/regions_onshore_elec_s{simpl}.geojson", - regions_offshore="resources/regions_offshore_elec_s{simpl}.geojson", - busmap='resources/busmap_elec_s{simpl}.csv' - log: "logs/simplify_network/elec_s{simpl}.log" - benchmark: "benchmarks/simplify_network/elec_s{simpl}" + network='networks/elec{year}_s{simpl}.nc', + regions_onshore="resources/regions_onshore_elec{year}_s{simpl}.geojson", + regions_offshore="resources/regions_offshore_elec{year}_s{simpl}.geojson", + busmap='resources/busmap_elec{year}_s{simpl}.csv' + log: "logs/simplify_network/elec{year}_s{simpl}.log" + benchmark: "benchmarks/simplify_network/elec{year}_s{simpl}" threads: 1 resources: mem=4000 script: "scripts/simplify_network.py" @@ -240,19 +241,19 @@ rule simplify_network: rule cluster_network: input: - network='networks/elec_s{simpl}.nc', - regions_onshore="resources/regions_onshore_elec_s{simpl}.geojson", - regions_offshore="resources/regions_offshore_elec_s{simpl}.geojson", - busmap=ancient('resources/busmap_elec_s{simpl}.csv'), + network='networks/elec{year}_s{simpl}.nc', + regions_onshore="resources/regions_onshore_elec{year}_s{simpl}.geojson", + regions_offshore="resources/regions_offshore_elec{year}_s{simpl}.geojson", + busmap=ancient('resources/busmap_elec{year}_s{simpl}.csv'), tech_costs=COSTS output: - network='networks/elec_s{simpl}_{clusters}.nc', - regions_onshore="resources/regions_onshore_elec_s{simpl}_{clusters}.geojson", - regions_offshore="resources/regions_offshore_elec_s{simpl}_{clusters}.geojson", - busmap="resources/busmap_elec_s{simpl}_{clusters}.csv", - linemap="resources/linemap_elec_s{simpl}_{clusters}.csv" - log: "logs/cluster_network/elec_s{simpl}_{clusters}.log" - benchmark: "benchmarks/cluster_network/elec_s{simpl}_{clusters}" + network='networks/elec{year}_s{simpl}_{clusters}.nc', + regions_onshore="resources/regions_onshore_elec{year}_s{simpl}_{clusters}.geojson", + regions_offshore="resources/regions_offshore_elec{year}_s{simpl}_{clusters}.geojson", + busmap="resources/busmap_elec{year}_s{simpl}_{clusters}.csv", + linemap="resources/linemap_elec{year}_s{simpl}_{clusters}.csv" + log: "logs/cluster_network/elec{year}_s{simpl}_{clusters}.log" + benchmark: "benchmarks/cluster_network/elec{year}_s{simpl}_{clusters}" threads: 1 resources: mem=3000 script: "scripts/cluster_network.py" @@ -260,21 +261,21 @@ rule cluster_network: rule add_extra_components: input: - network='networks/elec_s{simpl}_{clusters}.nc', + network='networks/elec{year}_s{simpl}_{clusters}.nc', tech_costs=COSTS, - output: 'networks/elec_s{simpl}_{clusters}_ec.nc' - log: "logs/add_extra_components/elec_s{simpl}_{clusters}.log" - benchmark: "benchmarks/add_extra_components/elec_s{simpl}_{clusters}_ec" + output: 'networks/elec{year}_s{simpl}_{clusters}_ec.nc' + log: "logs/add_extra_components/elec{year}_s{simpl}_{clusters}.log" + benchmark: "benchmarks/add_extra_components/elec{year}_s{simpl}_{clusters}_ec" threads: 1 resources: mem=3000 script: "scripts/add_extra_components.py" rule prepare_network: - input: 'networks/elec_s{simpl}_{clusters}_ec.nc', tech_costs=COSTS - output: 'networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc' - log: "logs/prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" - benchmark: "benchmarks/prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" + input: 'networks/elec{year}_s{simpl}_{clusters}_ec.nc', tech_costs=COSTS + output: 'networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc' + log: "logs/prepare_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" + benchmark: "benchmarks/prepare_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: 1 resources: mem=1000 script: "scripts/prepare_network.py" @@ -294,13 +295,13 @@ def memory(w): rule solve_network: - input: "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - output: "results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + input: "networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + output: "results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" log: - solver=normpath("logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log"), - python="logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", - memory="logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_memory.log" - benchmark: "benchmarks/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" + solver=normpath("logs/solve_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log"), + python="logs/solve_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", + memory="logs/solve_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_memory.log" + benchmark: "benchmarks/solve_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: 4 resources: mem=memory shadow: "shallow" @@ -309,14 +310,14 @@ rule solve_network: rule solve_operations_network: input: - unprepared="networks/elec_s{simpl}_{clusters}_ec.nc", - optimized="results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - output: "results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc" + unprepared="networks/elec{year}_s{simpl}_{clusters}_ec.nc", + optimized="results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + output: "results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc" log: - solver=normpath("logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log"), - python="logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log", - memory="logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_memory.log" - benchmark: "benchmarks/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" + solver=normpath("logs/solve_operations_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log"), + python="logs/solve_operations_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log", + memory="logs/solve_operations_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_memory.log" + benchmark: "benchmarks/solve_operations_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: 4 resources: mem=(lambda w: 5000 + 372 * int(w.clusters)) shadow: "shallow" @@ -325,12 +326,12 @@ rule solve_operations_network: rule plot_network: input: - network="results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network="results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", tech_costs=COSTS output: - only_map="results/plots/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}.{ext}", - ext="results/plots/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}_ext.{ext}" - log: "logs/plot_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}_{ext}.log" + only_map="results/plots/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}.{ext}", + ext="results/plots/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}_ext.{ext}" + log: "logs/plot_network/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{attr}_{ext}.log" script: "scripts/plot_network.py" @@ -343,7 +344,7 @@ def input_make_summary(w): else: ll = w.ll return ([COSTS] + - expand("results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + expand("results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", network=w.network, ll=ll, **{k: config["scenario"][k] if getattr(w, k) == "all" else getattr(w, k) @@ -352,28 +353,28 @@ def input_make_summary(w): rule make_summary: input: input_make_summary - output: directory("results/summaries/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}") - log: "logs/make_summary/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.log", + output: directory("results/summaries/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}") + log: "logs/make_summary/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.log", script: "scripts/make_summary.py" rule plot_summary: - input: "results/summaries/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}" - output: "results/plots/summary_{summary}_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.{ext}" - log: "logs/plot_summary/{summary}_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}_{ext}.log" + input: "results/summaries/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}" + output: "results/plots/{year}/summary_{summary}_elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.{ext}" + log: "logs/plot_summary/{summary}_elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}_{ext}.log" script: "scripts/plot_summary.py" def input_plot_p_nom_max(w): - return [("networks/elec_s{simpl}{maybe_cluster}.nc" + return [("networks/elec{year}_s{simpl}{maybe_cluster}.nc" .format(maybe_cluster=('' if c == 'full' else ('_' + c)), **w)) for c in w.clusts.split(",")] rule plot_p_nom_max: input: input_plot_p_nom_max - output: "results/plots/elec_s{simpl}_cum_p_nom_max_{clusts}_{techs}_{country}.{ext}" - log: "logs/plot_p_nom_max/elec_s{simpl}_{clusts}_{techs}_{country}_{ext}.log" + output: "results/plots/elec{year}_s{simpl}_cum_p_nom_max_{clusts}_{techs}_{country}.{ext}" + log: "logs/plot_p_nom_max/elec{year}_s{simpl}_{clusts}_{techs}_{country}_{ext}.log" script: "scripts/plot_p_nom_max.py" diff --git a/config.default.yaml b/config.default.yaml index b46432c6..0ba49caf 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -12,6 +12,7 @@ logging: summary_dir: results scenario: + year: [''] # for backwards compatibility simpl: [''] ll: ['copt'] clusters: [37, 128, 256, 512, 1024] diff --git a/config.tutorial.yaml b/config.tutorial.yaml index 174708cb..52b5b866 100755 --- a/config.tutorial.yaml +++ b/config.tutorial.yaml @@ -11,6 +11,7 @@ logging: summary_dir: results scenario: + year: [''] simpl: [''] ll: ['copt'] clusters: [5] diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index c11c27f5..a13cdb15 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -212,6 +212,7 @@ def attach_load(n): substation_lv_i = n.buses.index[n.buses['substation_lv']] regions = (gpd.read_file(snakemake.input.regions).set_index('name') .reindex(substation_lv_i)) + # TODO: is there a fallback if year not in timeseries_opsd? opsd_load = (timeseries_opsd(slice(*n.snapshots[[0,-1]].year.astype(str)), snakemake.input.opsd_load) * snakemake.config.get('load', {}).get('scaling_factor', 1.0)) @@ -522,6 +523,11 @@ if __name__ == "__main__": configure_logging(snakemake) n = pypsa.Network(snakemake.input.base_network) + + year = int(snakemake.wildcards.year) + snapshots = dict(start=str(year), end=str(year+1), closed="left") if year else snakememake.config['snapshots'] + n.set_snapshots(pd.date_range(freq='h', **snapshots)) + n.snapshot_weightings[:] *= 8760. / n.snapshot_weightings.sum() Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears) diff --git a/scripts/base_network.py b/scripts/base_network.py index d2ceccf1..0b535218 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -11,8 +11,6 @@ Relevant Settings .. code:: yaml - snapshots: - countries: electricity: @@ -35,7 +33,7 @@ Relevant Settings .. seealso:: Documentation of the configuration file ``config.yaml`` at - :ref:`snapshots_cf`, :ref:`toplevel_cf`, :ref:`electricity_cf`, :ref:`load_cf`, + :ref:`toplevel_cf`, :ref:`electricity_cf`, :ref:`load_cf`, :ref:`lines_cf`, :ref:`links_cf`, :ref:`transformers_cf` Inputs @@ -554,9 +552,6 @@ def base_network(): n = pypsa.Network() n.name = 'PyPSA-Eur' - n.set_snapshots(pd.date_range(freq='h', **snakemake.config['snapshots'])) - n.snapshot_weightings[:] *= 8760. / n.snapshot_weightings.sum() - n.import_components_from_dataframe(buses, "Bus") n.import_components_from_dataframe(lines, "Line") n.import_components_from_dataframe(transformers, "Transformer") diff --git a/scripts/build_country_flh.py b/scripts/build_country_flh.py index 459b8f38..345d1d09 100644 --- a/scripts/build_country_flh.py +++ b/scripts/build_country_flh.py @@ -165,7 +165,9 @@ if __name__ == '__main__': config = snakemake.config['renewable'][snakemake.wildcards.technology] - time = pd.date_range(freq='m', **snakemake.config['snapshots']) + year = int(snakemake.wildcards.year) + snapshots = dict(start=str(year), end=str(year+1), closed="left") if year else snakememake.config['snapshots'] + time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) cutout = atlite.Cutout(config['cutout'], diff --git a/scripts/build_cutout.py b/scripts/build_cutout.py index 1e55faf5..dc909c09 100644 --- a/scripts/build_cutout.py +++ b/scripts/build_cutout.py @@ -105,6 +105,7 @@ if __name__ == "__main__": snakemake = mock_snakemake('build_cutout', cutout='europe-2013-era5') configure_logging(snakemake) + # TODO make it accept year independent config cutout_params = snakemake.config['atlite']['cutouts'][snakemake.wildcards.cutout] for p in ('xs', 'ys', 'years', 'months'): if p in cutout_params: diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 71adb66e..9b477625 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -284,7 +284,9 @@ if __name__ == '__main__': config = snakemake.config['renewable'][snakemake.wildcards.technology] - time = pd.date_range(freq='m', **snakemake.config['snapshots']) + year = int(snakemake.wildcards.year) + snapshots = dict(start=str(year), end=str(year+1), closed="left") if year else snakememake.config['snapshots'] + time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) cutout = atlite.Cutout(config['cutout'], diff --git a/test/config.test1.yaml b/test/config.test1.yaml index 84d551e6..a1fc59ba 100755 --- a/test/config.test1.yaml +++ b/test/config.test1.yaml @@ -11,6 +11,7 @@ logging: summary_dir: results scenario: + year: [''] simpl: [''] ll: ['copt'] clusters: [5] From ca0ad084381d3ffdda99433cfc4e9663fbc597f0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Oct 2020 14:47:46 +0200 Subject: [PATCH 011/591] reflect filename changes in documentation --- .travis.yml | 2 +- doc/cloudcomputing.rst | 2 +- doc/configuration.rst | 4 ++-- doc/release_notes.rst | 2 +- doc/solving.rst | 2 +- doc/tutorial.rst | 6 +++--- scripts/add_electricity.py | 4 ++-- scripts/add_extra_components.py | 4 ++-- scripts/build_country_flh.py | 4 ++-- scripts/build_renewable_profiles.py | 4 ++-- scripts/cluster_network.py | 16 ++++++++-------- scripts/prepare_network.py | 4 ++-- scripts/simplify_network.py | 8 ++++---- scripts/solve_network.py | 4 ++-- scripts/solve_operations_network.py | 6 +++--- 15 files changed, 36 insertions(+), 36 deletions(-) diff --git a/.travis.yml b/.travis.yml index a6a29a39..b7b8c4d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,6 @@ before_install: script: - cp ./test/config.test1.yaml ./config.yaml - - snakemake -j all solve_all_elec_networks + - snakemake -j all solve_all_networks - rm -rf resources/*.nc resources/*.geojson resources/*.h5 networks results # could repeat for more configurations in future diff --git a/doc/cloudcomputing.rst b/doc/cloudcomputing.rst index f91441a5..95bfa2c7 100644 --- a/doc/cloudcomputing.rst +++ b/doc/cloudcomputing.rst @@ -60,7 +60,7 @@ Now a window with the machine details will open. You have to configure the follo You can edit your machine configuration later. So use a cheap machine type configuration to transfer data and only when everything is ready and tested, your expensive machine type, for instance a custom 8 vCPU with 160 GB memory. Solvers do not parallelise well, so we recommend not to choose more than 8 vCPU. - Check ``snakemake -j -n 1 solve_all_elec_networks`` as a dry run to see how much memory is required. + Check ``snakemake -j -n 1 solve_all_networks`` as a dry run to see how much memory is required. The memory requirements will vary depending on the spatial and temporal resoulution of your optimisation. Example: for an hourly, 181 node full European network, set 8 vCPU and 150 GB memory since the dry-run calculated a 135 GB memory requirement.) - Boot disk: As default, your VM is created with 10 GB. Depending on how much you want to handle on one VM you should increase the disk size. diff --git a/doc/configuration.rst b/doc/configuration.rst index b065290b..95d7af31 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -40,9 +40,9 @@ facilitate running multiple scenarios through a single command .. code:: bash - snakemake -j 1 solve_all_elec_networks + snakemake -j 1 solve_all_networks -For each wildcard, a **list of values** is provided. The rule ``solve_all_elec_networks`` will trigger the rules for creating ``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc`` for **all combinations** of the provided wildcard values as defined by Python's `itertools.product(...) `_ function that snakemake's `expand(...) function `_ uses. +For each wildcard, a **list of values** is provided. The rule ``solve_all_networks`` will trigger the rules for creating ``results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc`` for **all combinations** of the provided wildcard values as defined by Python's `itertools.product(...) `_ function that snakemake's `expand(...) function `_ uses. An exemplary dependency graph (starting from the simplification rules) then looks like this: diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 9fc72206..5d2e0f05 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -124,7 +124,7 @@ Release Process * Upload code to `zenodo code repository `_ with `GNU GPL 3.0 `_ license. -* Create pre-built networks for ``config.default.yaml`` by running ``snakemake -j 1 extra_components_all_elec_networks``. +* Create pre-built networks for ``config.default.yaml`` by running ``snakemake -j 1 extra_components_all_networks``. * Upload pre-built networks to `zenodo data repository `_ with `CC BY 4.0 `_ license. diff --git a/doc/solving.rst b/doc/solving.rst index 2cc8eb57..87fdc040 100644 --- a/doc/solving.rst +++ b/doc/solving.rst @@ -7,7 +7,7 @@ Solving Networks ########################################## -After generating and simplifying the networks they can be solved through the rule :mod:`solve_network` by using the collection rule :mod:`solve_all_elec_networks`. Moreover, networks can be solved for another focus with the derivative rules :mod:`solve_network` by using the collection rule :mod:`solve_operations_network` for dispatch-only analyses on an already solved network. +After generating and simplifying the networks they can be solved through the rule :mod:`solve_network` by using the collection rule :mod:`solve_all_networks`. Moreover, networks can be solved for another focus with the derivative rules :mod:`solve_network` by using the collection rule :mod:`solve_operations_network` for dispatch-only analyses on an already solved network. .. toctree:: :caption: Overview diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 3772bc43..53252ff8 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -119,8 +119,8 @@ orders ``snakemake`` to run the script ``solve_network`` that produces the solve .. code:: rule solve_network: - input: "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - output: "results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + input: "networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + output: "results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" [...] script: "scripts/solve_network.py" @@ -129,7 +129,7 @@ orders ``snakemake`` to run the script ``solve_network`` that produces the solve .. warning:: On Windows the previous command may currently cause a ``MissingRuleException`` due to problems with output files in subfolders. This is an `open issue `_ at `snakemake `_. - Windows users should add the option ``--keep-target-files`` to the command or instead run ``snakemake -j 1 solve_all_elec_networks``. + Windows users should add the option ``--keep-target-files`` to the command or instead run ``snakemake -j 1 solve_all_networks``. This triggers a workflow of multiple preceding jobs that depend on each rule's inputs and outputs: diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index a13cdb15..8ac455f7 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -524,8 +524,8 @@ if __name__ == "__main__": n = pypsa.Network(snakemake.input.base_network) - year = int(snakemake.wildcards.year) - snapshots = dict(start=str(year), end=str(year+1), closed="left") if year else snakememake.config['snapshots'] + year = snakemake.wildcards.year + snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakememake.config['snapshots'] n.set_snapshots(pd.date_range(freq='h', **snapshots)) n.snapshot_weightings[:] *= 8760. / n.snapshot_weightings.sum() Nyears = n.snapshot_weightings.sum() / 8760. diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index a7814ac6..c3af5c68 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -37,13 +37,13 @@ Inputs Outputs ------- -- ``networks/elec_s{simpl}_{clusters}_ec.nc``: +- ``networks/elec{year}_s{simpl}_{clusters}_ec.nc``: Description ----------- -The rule :mod:`add_extra_components` attaches additional extendable components to the clustered and simplified network. These can be configured in the ``config.yaml`` at ``electricity: extendable_carriers: ``. It processes ``networks/elec_s{simpl}_{clusters}.nc`` to build ``networks/elec_s{simpl}_{clusters}_ec.nc``, which in contrast to the former (depending on the configuration) contain with **zero** initial capacity +The rule :mod:`add_extra_components` attaches additional extendable components to the clustered and simplified network. These can be configured in the ``config.yaml`` at ``electricity: extendable_carriers: ``. It processes ``networks/elec{year}_s{simpl}_{clusters}.nc`` to build ``networks/elec{year}_s{simpl}_{clusters}_ec.nc``, which in contrast to the former (depending on the configuration) contain with **zero** initial capacity - ``StorageUnits`` of carrier 'H2' and/or 'battery'. If this option is chosen, every bus is given an extendable ``StorageUnit`` of the corresponding carrier. The energy and power capacities are linked through a parameter that specifies the energy capacity as maximum hours at full dispatch power and is configured in ``electricity: max_hours:``. This linkage leads to one investment variable per storage unit. The default ``max_hours`` lead to long-term hydrogen and short-term battery storage units. diff --git a/scripts/build_country_flh.py b/scripts/build_country_flh.py index 345d1d09..de78749c 100644 --- a/scripts/build_country_flh.py +++ b/scripts/build_country_flh.py @@ -165,8 +165,8 @@ if __name__ == '__main__': config = snakemake.config['renewable'][snakemake.wildcards.technology] - year = int(snakemake.wildcards.year) - snapshots = dict(start=str(year), end=str(year+1), closed="left") if year else snakememake.config['snapshots'] + year = snakemake.wildcards.year + snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakememake.config['snapshots'] time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 9b477625..a02d397b 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -284,8 +284,8 @@ if __name__ == '__main__': config = snakemake.config['renewable'][snakemake.wildcards.technology] - year = int(snakemake.wildcards.year) - snapshots = dict(start=str(year), end=str(year+1), closed="left") if year else snakememake.config['snapshots'] + year = snakemake.wildcards.year + snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakememake.config['snapshots'] time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 47da0b24..e48cb919 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -31,26 +31,26 @@ Relevant Settings Inputs ------ -- ``resources/regions_onshore_elec_s{simpl}.geojson``: confer :ref:`simplify` -- ``resources/regions_offshore_elec_s{simpl}.geojson``: confer :ref:`simplify` -- ``resources/clustermaps_elec_s{simpl}.h5``: confer :ref:`simplify` -- ``networks/elec_s{simpl}.nc``: confer :ref:`simplify` +- ``resources/regions_onshore_elec{year}_s{simpl}.geojson``: confer :ref:`simplify` +- ``resources/regions_offshore_elec{year}_s{simpl}.geojson``: confer :ref:`simplify` +- ``resources/clustermaps_elec{year}_s{simpl}.h5``: confer :ref:`simplify` +- ``networks/elec{year}_s{simpl}.nc``: confer :ref:`simplify` Outputs ------- -- ``resources/regions_onshore_elec_s{simpl}_{clusters}.geojson``: +- ``resources/regions_onshore_elec{year}_s{simpl}_{clusters}.geojson``: .. image:: ../img/regions_onshore_elec_s_X.png :scale: 33 % -- ``resources/regions_offshore_elec_s{simpl}_{clusters}.geojson``: +- ``resources/regions_offshore_elec{year}_s{simpl}_{clusters}.geojson``: .. image:: ../img/regions_offshore_elec_s_X.png :scale: 33 % -- ``resources/clustermaps_elec_s{simpl}_{clusters}.h5``: Mapping of buses and lines from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; has keys ['/busmap', '/busmap_s', '/linemap', '/linemap_negative', '/linemap_positive'] -- ``networks/elec_s{simpl}_{clusters}.nc``: +- ``resources/clustermaps_elec{year}_s{simpl}_{clusters}.h5``: Mapping of buses and lines from ``networks/elec{year}_s{simpl}.nc`` to ``networks/elec{year}_s{simpl}_{clusters}.nc``; has keys ['/busmap', '/busmap_s', '/linemap', '/linemap_negative', '/linemap_positive'] +- ``networks/elec{year}_s{simpl}_{clusters}.nc``: .. image:: ../img/elec_s_X.png :scale: 40 % diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index a98c63fa..a93f8679 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -37,12 +37,12 @@ Inputs ------ - ``data/costs.csv``: The database of cost assumptions for all included technologies for specific years from various sources; e.g. discount rate, lifetime, investment (CAPEX), fixed operation and maintenance (FOM), variable operation and maintenance (VOM), fuel costs, efficiency, carbon-dioxide intensity. -- ``networks/elec_s{simpl}_{clusters}.nc``: confer :ref:`cluster` +- ``networks/elec{year}_s{simpl}_{clusters}.nc``: confer :ref:`cluster` Outputs ------- -- ``networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Complete PyPSA network that will be handed to the ``solve_network`` rule. +- ``networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Complete PyPSA network that will be handed to the ``solve_network`` rule. Description ----------- diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index eb6dbe6b..780a794d 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -52,18 +52,18 @@ Inputs Outputs ------- -- ``resources/regions_onshore_elec_s{simpl}.geojson``: +- ``resources/regions_onshore_elec{year}_s{simpl}.geojson``: .. image:: ../img/regions_onshore_elec_s.png :scale: 33 % -- ``resources/regions_offshore_elec_s{simpl}.geojson``: +- ``resources/regions_offshore_elec{year}_s{simpl}.geojson``: .. image:: ../img/regions_offshore_elec_s .png :scale: 33 % -- ``resources/clustermaps_elec_s{simpl}.h5``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec_s{simpl}.nc``; has keys ['/busmap_s'] -- ``networks/elec_s{simpl}.nc``: +- ``resources/clustermaps_elec{year}_s{simpl}.h5``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec{year}_s{simpl}.nc``; has keys ['/busmap_s'] +- ``networks/elec{year}_s{simpl}.nc``: .. image:: ../img/elec_s.png :scale: 33 % diff --git a/scripts/solve_network.py b/scripts/solve_network.py index e6936db6..6e733cd8 100755 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -40,12 +40,12 @@ Relevant Settings Inputs ------ -- ``networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: confer :ref:`prepare` +- ``networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: confer :ref:`prepare` Outputs ------- -- ``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Solved PyPSA network including optimisation results +- ``results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Solved PyPSA network including optimisation results .. image:: ../img/results.png :scale: 40 % diff --git a/scripts/solve_operations_network.py b/scripts/solve_operations_network.py index c65e6889..7355bf40 100644 --- a/scripts/solve_operations_network.py +++ b/scripts/solve_operations_network.py @@ -32,13 +32,13 @@ Relevant Settings Inputs ------ -- ``networks/elec_s{simpl}_{clusters}.nc``: confer :ref:`cluster` -- ``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: confer :ref:`solve` +- ``networks/elec{year}_s{simpl}_{clusters}.nc``: confer :ref:`cluster` +- ``results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: confer :ref:`solve` Outputs ------- -- ``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc``: Solved PyPSA network for optimal dispatch including optimisation results +- ``results/networks/elec{year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc``: Solved PyPSA network for optimal dispatch including optimisation results Description ----------- From dacfc8a9a4c3d175297f73bba84ca72c8ad3b87f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 20 Oct 2020 13:53:43 +0200 Subject: [PATCH 012/591] multiyear: fallbacks for hydro and load profiles --- Snakefile | 2 ++ config.default.yaml | 1 + config.tutorial.yaml | 1 + scripts/add_electricity.py | 21 +++++++++++++++++++-- scripts/build_hydro_profile.py | 10 +++++++++- scripts/build_renewable_profiles.py | 8 +++++--- test/config.test1.yaml | 1 + 7 files changed, 38 insertions(+), 6 deletions(-) diff --git a/Snakefile b/Snakefile index fb04256b..b8bc284a 100644 --- a/Snakefile +++ b/Snakefile @@ -166,6 +166,8 @@ if config['enable'].get('retrieve_natura_raster', True): script: 'scripts/retrieve_natura_raster.py' +ruleorder: build_hydro_profile > build_renewable_profiles + rule build_renewable_profiles: input: base_network="networks/base.nc", diff --git a/config.default.yaml b/config.default.yaml index 0ba49caf..9f096fff 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -169,6 +169,7 @@ transformers: load: scaling_factor: 1.0 + fallback_year: 2013 costs: year: 2030 diff --git a/config.tutorial.yaml b/config.tutorial.yaml index 52b5b866..e74a2967 100755 --- a/config.tutorial.yaml +++ b/config.tutorial.yaml @@ -147,6 +147,7 @@ transformers: load: scaling_factor: 1.0 + fallback_year: 2013 costs: year: 2030 diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 8ac455f7..98893010 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -212,11 +212,28 @@ def attach_load(n): substation_lv_i = n.buses.index[n.buses['substation_lv']] regions = (gpd.read_file(snakemake.input.regions).set_index('name') .reindex(substation_lv_i)) - # TODO: is there a fallback if year not in timeseries_opsd? - opsd_load = (timeseries_opsd(slice(*n.snapshots[[0,-1]].year.astype(str)), + + available_years = range(2011,2016) + requested_years = n.snapshots.year[[0,-1]] + use_fallback = any(year not in available_years for year in requested_years) + + if use_fallback: + fallback_year = str(snakemake.config["load"]["fallback_year"]) + load_years = [fallback_year, fallback_year] + logger.warning(f"Requested years {list(requested_years.unique().values)} " + f"for load time series not in available years {list(available_years)}. " + f"Falling back to year {fallback_year}.") + else: + load_years = requested_years.astype(str) + + opsd_load = (timeseries_opsd(slice(*load_years), snakemake.input.opsd_load) * snakemake.config.get('load', {}).get('scaling_factor', 1.0)) + if use_fallback: + assert len(requested_years.unique()) == 1, "Fallback for load time series requires single year!" + opsd_load.index = opsd_load.index.map(lambda t: t.replace(year=requested_years[0])) + # Convert to naive UTC (has to be explicit since pandas 0.24) opsd_load.index = opsd_load.index.tz_localize(None) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 339fccaf..46911363 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -75,15 +75,23 @@ if __name__ == "__main__": snakemake = mock_snakemake('build_hydro_profile') configure_logging(snakemake) + year = snakemake.wildcards.year config = snakemake.config['renewable']['hydro'] cutout_dir = os.path.dirname(snakemake.input.cutout) - cutout = atlite.Cutout(config['cutout'], cutout_dir=cutout_dir) + cutout_config = config['cutout'] + if year: cutout_config = cutout_config.format(year=year) + + cutout = atlite.Cutout(cutout_config, cutout_dir=cutout_dir) countries = snakemake.config['countries'] country_shapes = gpd.read_file(snakemake.input.country_shapes).set_index('name')['geometry'].reindex(countries) country_shapes.index.name = 'countries' eia_stats = vhydro.get_eia_annual_hydro_generation(snakemake.input.eia_hydro_generation).reindex(columns=countries) + + if year not in eia_stats.index: + eia_stats.loc[year] = eia_stats.mean() + inflow = cutout.runoff(shapes=country_shapes, smooth=True, lower_threshold_quantile=True, diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index a02d397b..7b838725 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -282,14 +282,16 @@ if __name__ == '__main__': pgb.streams.wrap_stderr() - config = snakemake.config['renewable'][snakemake.wildcards.technology] - year = snakemake.wildcards.year + config = snakemake.config['renewable'][snakemake.wildcards.technology] + cutout_name = config['cutout'] + if year: cutout_name = cutout_name.format(year=year) + snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakememake.config['snapshots'] time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) - cutout = atlite.Cutout(config['cutout'], + cutout = atlite.Cutout(cutout_name, cutout_dir=os.path.dirname(snakemake.input.cutout), **params) diff --git a/test/config.test1.yaml b/test/config.test1.yaml index a1fc59ba..2774be8a 100755 --- a/test/config.test1.yaml +++ b/test/config.test1.yaml @@ -147,6 +147,7 @@ transformers: load: scaling_factor: 1.0 + fallback_year: 2013 costs: year: 2030 From 4d2f379ae1dbdff666fa5443a215a4dffad86d68 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 27 Oct 2020 11:30:25 +0100 Subject: [PATCH 013/591] build_hydro: handle empty year wildcard --- scripts/build_hydro_profile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 46911363..7e1bd212 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -89,7 +89,7 @@ if __name__ == "__main__": eia_stats = vhydro.get_eia_annual_hydro_generation(snakemake.input.eia_hydro_generation).reindex(columns=countries) - if year not in eia_stats.index: + if len(year) > 0 and year not in eia_stats.index: eia_stats.loc[year] = eia_stats.mean() inflow = cutout.runoff(shapes=country_shapes, From 5442d541b4ca5ebd27d67e710c909041c7e72308 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 27 Oct 2020 11:42:18 +0100 Subject: [PATCH 014/591] build_renewables: fix snakemake typo --- scripts/build_renewable_profiles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 7b838725..3201d20b 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -287,7 +287,7 @@ if __name__ == '__main__': cutout_name = config['cutout'] if year: cutout_name = cutout_name.format(year=year) - snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakememake.config['snapshots'] + snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) From eed314ef057dad9baf959d2672e6e41cc5490faf Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 27 Oct 2020 13:40:34 +0100 Subject: [PATCH 015/591] add_electricity: fix snakemake typo --- scripts/add_electricity.py | 2 +- scripts/build_country_flh.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 98893010..a5495585 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -542,7 +542,7 @@ if __name__ == "__main__": n = pypsa.Network(snakemake.input.base_network) year = snakemake.wildcards.year - snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakememake.config['snapshots'] + snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] n.set_snapshots(pd.date_range(freq='h', **snapshots)) n.snapshot_weightings[:] *= 8760. / n.snapshot_weightings.sum() Nyears = n.snapshot_weightings.sum() / 8760. diff --git a/scripts/build_country_flh.py b/scripts/build_country_flh.py index de78749c..0b65f136 100644 --- a/scripts/build_country_flh.py +++ b/scripts/build_country_flh.py @@ -166,7 +166,7 @@ if __name__ == '__main__': config = snakemake.config['renewable'][snakemake.wildcards.technology] year = snakemake.wildcards.year - snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakememake.config['snapshots'] + snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) From 4fef5616e887c0c9e0cdbee484bf665c763e27bb Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 10 Nov 2020 09:48:13 +0100 Subject: [PATCH 016/591] scripts: change mock snakemake defaults --- scripts/add_brownfield.py | 12 ++++++------ scripts/add_existing_baseyear.py | 14 +++++++------- scripts/prepare_sector_network.py | 24 ++++++++++++------------ scripts/solve_network.py | 8 ++++---- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index a0b8d97b..a3624395 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -86,16 +86,16 @@ if __name__ == "__main__": if 'snakemake' not in globals(): from vresutils.snakemake import MockSnakemake snakemake = MockSnakemake( - wildcards=dict(network='elec', simpl='', clusters='37', lv='1.0', + wildcards=dict(simpl='', clusters='37', lv='1.0', sector_opts='Co2L0-168H-T-H-B-I-solar3-dist1', co2_budget_name='go', planning_horizons='2030'), - input=dict(network='pypsa-eur-sec/results/test/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', - network_p='pypsa-eur-sec/results/test/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_2020.nc', + input=dict(network='pypsa-eur-sec/results/test/prenetworks/elec_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', + network_p='pypsa-eur-sec/results/test/postnetworks/elec_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_2020.nc', costs='pypsa-eur-sec/data/costs/costs_{planning_horizons}.csv', - cop_air_total="pypsa-eur-sec/resources/cop_air_total_{network}_s{simpl}_{clusters}.nc", - cop_soil_total="pypsa-eur-sec/resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc"), - output=['pypsa-eur-sec/results/test/prenetworks_brownfield/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{planning_horizons}.nc'] + cop_air_total="pypsa-eur-sec/resources/cop_air_total_elec_s{simpl}_{clusters}.nc", + cop_soil_total="pypsa-eur-sec/resources/cop_soil_total_elec_s{simpl}_{clusters}.nc"), + output=['pypsa-eur-sec/results/test/prenetworks_brownfield/elec_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{planning_horizons}.nc'] ) import yaml with open('config.yaml', encoding='utf8') as f: diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index cfef2e5e..9eb2ae3a 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -408,18 +408,18 @@ if __name__ == "__main__": if 'snakemake' not in globals(): from vresutils.snakemake import MockSnakemake snakemake = MockSnakemake( - wildcards=dict(network='elec', simpl='', clusters='39', lv='1.0', + wildcards=dict(simpl='', clusters='39', lv='1.0', sector_opts='Co2L0-168H-T-H-B-I-solar3-dist1', co2_budget_name='b30b3', planning_horizons='2020'), - input=dict(network='pypsa-eur-sec/results/test/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', + input=dict(network='pypsa-eur-sec/results/test/prenetworks/elec_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', powerplants='pypsa-eur/resources/powerplants.csv', - busmap_s='pypsa-eur/resources/busmap_{network}_s{simpl}.csv', - busmap='pypsa-eur/resources/busmap_{network}_s{simpl}_{clusters}.csv', + busmap_s='pypsa-eur/resources/busmap_elec_s{simpl}.csv', + busmap='pypsa-eur/resources/busmap_elec_s{simpl}_{clusters}.csv', costs='pypsa-eur-sec/data/costs/costs_{planning_horizons}.csv', - cop_air_total="pypsa-eur-sec/resources/cop_air_total_{network}_s{simpl}_{clusters}.nc", - cop_soil_total="pypsa-eur-sec/resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc"), - output=['pypsa-eur-sec/results/test/prenetworks_brownfield/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{planning_horizons}.nc'], + cop_air_total="pypsa-eur-sec/resources/cop_air_total_elec_s{simpl}_{clusters}.nc", + cop_soil_total="pypsa-eur-sec/resources/cop_soil_total_elec_s{simpl}_{clusters}.nc"), + output=['pypsa-eur-sec/results/test/prenetworks_brownfield/elec_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{planning_horizons}.nc'], ) import yaml with open('config.yaml', encoding='utf8') as f: diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index f6e8a7be..990b6710 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1745,31 +1745,31 @@ if __name__ == "__main__": if 'snakemake' not in globals(): from vresutils.snakemake import MockSnakemake snakemake = MockSnakemake( - wildcards=dict(network='elec', simpl='', clusters='37', lv='1.0', + wildcards=dict(simpl='', clusters='37', lv='1.0', opts='', planning_horizons='2020', co2_budget_name='go', sector_opts='Co2L0-168H-T-H-B-I-solar3-dist1'), - input=dict(network='pypsa-eur/networks/{network}_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc', + input=dict(network='pypsa-eur/networks/elec_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc', timezone_mappings='pypsa-eur-sec/data/timezone_mappings.csv', co2_budget='pypsa-eur-sec/data/co2_budget.csv', - clustered_pop_layout='pypsa-eur-sec/resources/pop_layout_{network}_s{simpl}_{clusters}.csv', + clustered_pop_layout='pypsa-eur-sec/resources/pop_layout_elec_s{simpl}_{clusters}.csv', costs='technology-data/outputs/costs_{planning_horizons}.csv', profile_offwind_ac='pypsa-eur/resources/profile_offwind-ac.nc', profile_offwind_dc='pypsa-eur/resources/profile_offwind-dc.nc', - busmap_s='pypsa-eur/resources/busmap_{network}_s{simpl}.csv', - busmap='pypsa-eur/resources/busmap_{network}_s{simpl}_{clusters}.csv', - cop_air_total='pypsa-eur-sec/resources/cop_air_total_{network}_s{simpl}_{clusters}.nc', - cop_soil_total='pypsa-eur-sec/resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc', - solar_thermal_total='pypsa-eur-sec/resources/solar_thermal_total_{network}_s{simpl}_{clusters}.nc', + busmap_s='pypsa-eur/resources/busmap_elec_s{simpl}.csv', + busmap='pypsa-eur/resources/busmap_elec_s{simpl}_{clusters}.csv', + cop_air_total='pypsa-eur-sec/resources/cop_air_total_elec_s{simpl}_{clusters}.nc', + cop_soil_total='pypsa-eur-sec/resources/cop_soil_total_elec_s{simpl}_{clusters}.nc', + solar_thermal_total='pypsa-eur-sec/resources/solar_thermal_total_elec_s{simpl}_{clusters}.nc', energy_totals_name='pypsa-eur-sec/data/energy_totals.csv', - heat_demand_total='pypsa-eur-sec/resources/heat_demand_total_{network}_s{simpl}_{clusters}.nc', + heat_demand_total='pypsa-eur-sec/resources/heat_demand_total_elec_s{simpl}_{clusters}.nc', heat_profile='pypsa-eur-sec/data/heat_load_profile_BDEW.csv', transport_name='pypsa-eur-sec/data/transport_data.csv', - temp_air_total='pypsa-eur-sec/resources/temp_air_total_{network}_s{simpl}_{clusters}.nc', + temp_air_total='pypsa-eur-sec/resources/temp_air_total_elec_s{simpl}_{clusters}.nc', co2_totals_name='pypsa-eur-sec/data/co2_totals.csv', biomass_potentials='pypsa-eur-sec/data/biomass_potentials.csv', - industrial_demand='pypsa-eur-sec/resources/industrial_demand_{network}_s{simpl}_{clusters}.csv',), - output=['pypsa-eur-sec/results/test/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc'] + industrial_demand='pypsa-eur-sec/resources/industrial_demand_elec_s{simpl}_{clusters}.csv',), + output=['pypsa-eur-sec/results/test/prenetworks/elec_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc'] ) import yaml with open('config.yaml', encoding='utf8') as f: diff --git a/scripts/solve_network.py b/scripts/solve_network.py index a7078433..b2c56d54 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -369,13 +369,13 @@ if __name__ == "__main__": if 'snakemake' not in globals(): from vresutils.snakemake import MockSnakemake, Dict snakemake = MockSnakemake( - wildcards=dict(network='elec', simpl='', clusters='39', lv='1.0', + wildcards=dict(simpl='', clusters='39', lv='1.0', sector_opts='Co2L0-168H-T-H-B-I-solar3-dist1', co2_budget_name='b30b3', planning_horizons='2050'), - input=dict(network="pypsa-eur-sec/results/test/prenetworks_brownfield/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc"), + input=dict(network="pypsa-eur-sec/results/test/prenetworks_brownfield/elec_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc"), output=["results/networks/s{simpl}_{clusters}_lv{lv}_{sector_opts}_{co2_budget_name}_{planning_horizons}-test.nc"], - log=dict(gurobi="logs/{network}_s{simpl}_{clusters}_lv{lv}_{sector_opts}_{co2_budget_name}_{planning_horizons}_gurobi-test.log", - python="logs/{network}_s{simpl}_{clusters}_lv{lv}_{sector_opts}_{co2_budget_name}_{planning_horizons}_python-test.log") + log=dict(gurobi="logs/elec_s{simpl}_{clusters}_lv{lv}_{sector_opts}_{co2_budget_name}_{planning_horizons}_gurobi-test.log", + python="logs/elec_s{simpl}_{clusters}_lv{lv}_{sector_opts}_{co2_budget_name}_{planning_horizons}_python-test.log") ) import yaml with open('config.yaml', encoding='utf8') as f: From 723afc32e9b292f5cc543c04c28bd2302f17176c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 10 Nov 2020 09:51:02 +0100 Subject: [PATCH 017/591] scripts: step towards support for subset of countries --- config.default.yaml | 3 +++ config.myopic.yaml | 3 +++ scripts/build_industrial_energy_demand_per_country_today.py | 2 ++ scripts/build_industrial_production_per_country.py | 1 + 4 files changed, 9 insertions(+) diff --git a/config.default.yaml b/config.default.yaml index 7aa23901..ead33e2b 100644 --- a/config.default.yaml +++ b/config.default.yaml @@ -11,6 +11,7 @@ foresight: 'overnight' #options are overnight, myopic, perfect (perfect is not y scenario: sectors: [E] # ignore this legacy setting + year: [''] # weather year simpl: [''] # only relevant for PyPSA-Eur lv: [1.0,1.5] # allowed transmission line volume expansion, can be any float >= 1.0 (today) or "opt" clusters: [45,50] # number of nodes in Europe, any integer between 37 (1 node per country-zone) and several hundred @@ -34,6 +35,8 @@ snapshots: end: "2014-01-01" closed: 'left' # end is not inclusive +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'] + atlite: cutout_dir: '../pypsa-eur/cutouts' cutout_name: "europe-2013-era5" diff --git a/config.myopic.yaml b/config.myopic.yaml index c7f5ac1e..0dc4cdf3 100644 --- a/config.myopic.yaml +++ b/config.myopic.yaml @@ -11,6 +11,7 @@ foresight: 'myopic' #options are overnight, myopic, perfect (perfect is not yet scenario: sectors: [E] # ignore this legacy setting + year: [''] # weather year simpl: [''] # only relevant for PyPSA-Eur lv: [1.0,1.5] # allowed transmission line volume expansion, can be any float >= 1.0 (today) or "opt" clusters: [45,50] # number of nodes in Europe, any integer between 37 (1 node per country-zone) and several hundred @@ -34,6 +35,8 @@ snapshots: end: "2014-01-01" closed: 'left' # end is not inclusive +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'] + atlite: cutout_dir: '../pypsa-eur/cutouts' cutout_name: "europe-2013-era5" diff --git a/scripts/build_industrial_energy_demand_per_country_today.py b/scripts/build_industrial_energy_demand_per_country_today.py index 7593477b..00611318 100644 --- a/scripts/build_industrial_energy_demand_per_country_today.py +++ b/scripts/build_industrial_energy_demand_per_country_today.py @@ -61,6 +61,8 @@ eu28 = ['FR', 'DE', 'GB', 'IT', 'ES', 'PL', 'SE', 'NL', 'BE', 'FI', 'DK', 'PT', 'RO', 'AT', 'BG', 'EE', 'GR', 'LV', 'CZ', 'HU', 'IE', 'SK', 'LT', 'HR', 'LU', 'SI', 'CY', 'MT'] +eu28 = list(set(eu28).intersection(snakemake.config["countries"])) + jrc_names = {"GR" : "EL", "GB" : "UK"} diff --git a/scripts/build_industrial_production_per_country.py b/scripts/build_industrial_production_per_country.py index c8fa6910..4a993a91 100644 --- a/scripts/build_industrial_production_per_country.py +++ b/scripts/build_industrial_production_per_country.py @@ -39,6 +39,7 @@ eu28 = ['FR', 'DE', 'GB', 'IT', 'ES', 'PL', 'SE', 'NL', 'BE', 'FI', countries = non_EU + eu28 +countries = list(set(countries).intersection(snakemake.config["countries"])) sectors = ['Iron and steel','Chemicals Industry','Non-metallic mineral products', 'Pulp, paper and printing', 'Food, beverages and tobacco', 'Non Ferrous Metals', From 59cb0361222dbd457307baf68b62d58075b46537 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 10 Nov 2020 09:51:32 +0100 Subject: [PATCH 018/591] energy_totals: only fix 'BA' if in list of countries --- scripts/build_energy_totals.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 1682ac40..0cfa709b 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -378,12 +378,12 @@ def build_energy_totals(): clean_df.loc[missing,"total aviation passenger"] = clean_df.loc[missing,["total domestic aviation passenger","total international aviation passenger"]].sum(axis=1) clean_df.loc[missing,"total aviation freight"] = clean_df.loc[missing,["total domestic aviation freight","total international aviation freight"]].sum(axis=1) + if "BA" in clean_df.index: + #fix missing data for BA (services and road energy data) + missing = (clean_df.loc["BA"] == 0.) - #fix missing data for BA (services and road energy data) - missing = (clean_df.loc["BA"] == 0.) - - #add back in proportional to RS with ratio of total residential demand - clean_df.loc["BA",missing] = clean_df.loc["BA","total residential"]/clean_df.loc["RS","total residential"]*clean_df.loc["RS",missing] + #add back in proportional to RS with ratio of total residential demand + clean_df.loc["BA",missing] = clean_df.loc["BA","total residential"]/clean_df.loc["RS","total residential"]*clean_df.loc["RS",missing] clean_df.to_csv(snakemake.output.energy_name) From df94ea1c8bce3f97d696a08ae202585a32f26dee Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 10 Nov 2020 09:52:06 +0100 Subject: [PATCH 019/591] add multiyear support --- Snakefile | 244 +++++++++--------- scripts/build_clustered_population_layouts.py | 5 +- scripts/build_heat_demand.py | 10 +- scripts/build_population_layouts.py | 6 +- scripts/build_solar_thermal_profiles.py | 9 +- scripts/build_temperature_profiles.py | 9 +- 6 files changed, 153 insertions(+), 130 deletions(-) diff --git a/Snakefile b/Snakefile index f003bd5e..2d5564a8 100644 --- a/Snakefile +++ b/Snakefile @@ -2,8 +2,8 @@ configfile: "config.yaml" wildcard_constraints: + year="[0-9]*", lv="[a-z0-9\.]+", - network="[a-zA-Z0-9]*", simpl="[a-zA-Z0-9]*", clusters="[0-9]+m?", sectors="[+a-zA-Z0-9]+", @@ -25,17 +25,17 @@ rule all: rule solve_all_networks: input: - expand(config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", + expand(config['results_dir'] + config['run'] + "/postnetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", **config['scenario']) rule test_script: input: - expand("resources/heat_demand_urban_elec_s_{clusters}.nc", + expand("resources/heat_demand_urban_elec{year}_s_{clusters}.nc", **config['scenario']) rule prepare_sector_networks: input: - expand(config['results_dir'] + config['run'] + "/prenetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", + expand(config['results_dir'] + config['run'] + "/prenetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", **config['scenario']) @@ -44,96 +44,96 @@ rule build_population_layouts: nuts3_shapes=pypsaeur('resources/nuts3_shapes.geojson'), urban_percent="data/urban_percent.csv" output: - pop_layout_total="resources/pop_layout_total.nc", - pop_layout_urban="resources/pop_layout_urban.nc", - pop_layout_rural="resources/pop_layout_rural.nc" + pop_layout_total="resources/pop_layout{year}_total.nc", + pop_layout_urban="resources/pop_layout{year}_urban.nc", + pop_layout_rural="resources/pop_layout{year}_rural.nc" resources: mem_mb=20000 script: "scripts/build_population_layouts.py" rule build_clustered_population_layouts: input: - pop_layout_total="resources/pop_layout_total.nc", - pop_layout_urban="resources/pop_layout_urban.nc", - pop_layout_rural="resources/pop_layout_rural.nc", - regions_onshore=pypsaeur('resources/regions_onshore_{network}_s{simpl}_{clusters}.geojson') + pop_layout_total="resources/pop_layout{year}_total.nc", + pop_layout_urban="resources/pop_layout{year}_urban.nc", + pop_layout_rural="resources/pop_layout{year}_rural.nc", + regions_onshore=pypsaeur('resources/regions_onshore_elec{year}_s{simpl}_{clusters}.geojson') output: - clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv" + clustered_pop_layout="resources/pop_layout_elec{year}_s{simpl}_{clusters}.csv" resources: mem_mb=10000 script: "scripts/build_clustered_population_layouts.py" rule build_simplified_population_layouts: input: - pop_layout_total="resources/pop_layout_total.nc", - pop_layout_urban="resources/pop_layout_urban.nc", - pop_layout_rural="resources/pop_layout_rural.nc", - regions_onshore=pypsaeur('resources/regions_onshore_{network}_s{simpl}.geojson') + pop_layout_total="resources/pop_layout{year}_total.nc", + pop_layout_urban="resources/pop_layout{year}_urban.nc", + pop_layout_rural="resources/pop_layout{year}_rural.nc", + regions_onshore=pypsaeur('resources/regions_onshore_elec{year}_s{simpl}.geojson') output: - clustered_pop_layout="resources/pop_layout_{network}_s{simpl}.csv" + clustered_pop_layout="resources/pop_layout_elec{year}_s{simpl}.csv" resources: mem_mb=10000 script: "scripts/build_clustered_population_layouts.py" rule build_heat_demands: input: - pop_layout_total="resources/pop_layout_total.nc", - pop_layout_urban="resources/pop_layout_urban.nc", - pop_layout_rural="resources/pop_layout_rural.nc", - regions_onshore=pypsaeur("resources/regions_onshore_{network}_s{simpl}_{clusters}.geojson") + pop_layout_total="resources/pop_layout{year}_total.nc", + pop_layout_urban="resources/pop_layout{year}_urban.nc", + pop_layout_rural="resources/pop_layout{year}_rural.nc", + regions_onshore=pypsaeur("resources/regions_onshore_elec{year}_s{simpl}_{clusters}.geojson") output: - heat_demand_urban="resources/heat_demand_urban_{network}_s{simpl}_{clusters}.nc", - heat_demand_rural="resources/heat_demand_rural_{network}_s{simpl}_{clusters}.nc", - heat_demand_total="resources/heat_demand_total_{network}_s{simpl}_{clusters}.nc" + heat_demand_urban="resources/heat_demand_urban_elec{year}_s{simpl}_{clusters}.nc", + heat_demand_rural="resources/heat_demand_rural_elec{year}_s{simpl}_{clusters}.nc", + heat_demand_total="resources/heat_demand_total_elec{year}_s{simpl}_{clusters}.nc" resources: mem_mb=20000 script: "scripts/build_heat_demand.py" rule build_temperature_profiles: input: - pop_layout_total="resources/pop_layout_total.nc", - pop_layout_urban="resources/pop_layout_urban.nc", - pop_layout_rural="resources/pop_layout_rural.nc", - regions_onshore=pypsaeur("resources/regions_onshore_{network}_s{simpl}_{clusters}.geojson") + pop_layout_total="resources/pop_layout{year}_total.nc", + pop_layout_urban="resources/pop_layout{year}_urban.nc", + pop_layout_rural="resources/pop_layout{year}_rural.nc", + regions_onshore=pypsaeur("resources/regions_onshore_elec{year}_s{simpl}_{clusters}.geojson") output: - temp_soil_total="resources/temp_soil_total_{network}_s{simpl}_{clusters}.nc", - temp_soil_rural="resources/temp_soil_rural_{network}_s{simpl}_{clusters}.nc", - temp_soil_urban="resources/temp_soil_urban_{network}_s{simpl}_{clusters}.nc", - temp_air_total="resources/temp_air_total_{network}_s{simpl}_{clusters}.nc", - temp_air_rural="resources/temp_air_rural_{network}_s{simpl}_{clusters}.nc", - temp_air_urban="resources/temp_air_urban_{network}_s{simpl}_{clusters}.nc" + temp_soil_total="resources/temp_soil_total_elec{year}_s{simpl}_{clusters}.nc", + temp_soil_rural="resources/temp_soil_rural_elec{year}_s{simpl}_{clusters}.nc", + temp_soil_urban="resources/temp_soil_urban_elec{year}_s{simpl}_{clusters}.nc", + temp_air_total="resources/temp_air_total_elec{year}_s{simpl}_{clusters}.nc", + temp_air_rural="resources/temp_air_rural_elec{year}_s{simpl}_{clusters}.nc", + temp_air_urban="resources/temp_air_urban_elec{year}_s{simpl}_{clusters}.nc" resources: mem_mb=20000 script: "scripts/build_temperature_profiles.py" rule build_cop_profiles: input: - temp_soil_total="resources/temp_soil_total_{network}_s{simpl}_{clusters}.nc", - temp_soil_rural="resources/temp_soil_rural_{network}_s{simpl}_{clusters}.nc", - temp_soil_urban="resources/temp_soil_urban_{network}_s{simpl}_{clusters}.nc", - temp_air_total="resources/temp_air_total_{network}_s{simpl}_{clusters}.nc", - temp_air_rural="resources/temp_air_rural_{network}_s{simpl}_{clusters}.nc", - temp_air_urban="resources/temp_air_urban_{network}_s{simpl}_{clusters}.nc" + temp_soil_total="resources/temp_soil_total_elec{year}_s{simpl}_{clusters}.nc", + temp_soil_rural="resources/temp_soil_rural_elec{year}_s{simpl}_{clusters}.nc", + temp_soil_urban="resources/temp_soil_urban_elec{year}_s{simpl}_{clusters}.nc", + temp_air_total="resources/temp_air_total_elec{year}_s{simpl}_{clusters}.nc", + temp_air_rural="resources/temp_air_rural_elec{year}_s{simpl}_{clusters}.nc", + temp_air_urban="resources/temp_air_urban_elec{year}_s{simpl}_{clusters}.nc" output: - cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc", - cop_soil_rural="resources/cop_soil_rural_{network}_s{simpl}_{clusters}.nc", - cop_soil_urban="resources/cop_soil_urban_{network}_s{simpl}_{clusters}.nc", - cop_air_total="resources/cop_air_total_{network}_s{simpl}_{clusters}.nc", - cop_air_rural="resources/cop_air_rural_{network}_s{simpl}_{clusters}.nc", - cop_air_urban="resources/cop_air_urban_{network}_s{simpl}_{clusters}.nc" + cop_soil_total="resources/cop_soil_total_elec{year}_s{simpl}_{clusters}.nc", + cop_soil_rural="resources/cop_soil_rural_elec{year}_s{simpl}_{clusters}.nc", + cop_soil_urban="resources/cop_soil_urban_elec{year}_s{simpl}_{clusters}.nc", + cop_air_total="resources/cop_air_total_elec{year}_s{simpl}_{clusters}.nc", + cop_air_rural="resources/cop_air_rural_elec{year}_s{simpl}_{clusters}.nc", + cop_air_urban="resources/cop_air_urban_elec{year}_s{simpl}_{clusters}.nc" resources: mem_mb=20000 script: "scripts/build_cop_profiles.py" rule build_solar_thermal_profiles: input: - pop_layout_total="resources/pop_layout_total.nc", - pop_layout_urban="resources/pop_layout_urban.nc", - pop_layout_rural="resources/pop_layout_rural.nc", - regions_onshore=pypsaeur("resources/regions_onshore_{network}_s{simpl}_{clusters}.geojson") + pop_layout_total="resources/pop_layout{year}_total.nc", + pop_layout_urban="resources/pop_layout{year}_urban.nc", + pop_layout_rural="resources/pop_layout{year}_rural.nc", + regions_onshore=pypsaeur("resources/regions_onshore_elec{year}_s{simpl}_{clusters}.geojson") output: - solar_thermal_total="resources/solar_thermal_total_{network}_s{simpl}_{clusters}.nc", - solar_thermal_urban="resources/solar_thermal_urban_{network}_s{simpl}_{clusters}.nc", - solar_thermal_rural="resources/solar_thermal_rural_{network}_s{simpl}_{clusters}.nc" + solar_thermal_total="resources/solar_thermal_total_elec{year}_s{simpl}_{clusters}.nc", + solar_thermal_urban="resources/solar_thermal_urban_elec{year}_s{simpl}_{clusters}.nc", + solar_thermal_rural="resources/solar_thermal_rural_elec{year}_s{simpl}_{clusters}.nc" resources: mem_mb=20000 script: "scripts/build_solar_thermal_profiles.py" @@ -204,12 +204,12 @@ rule build_industrial_production_per_country_tomorrow: rule build_industrial_distribution_key: input: - clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv", + clustered_pop_layout="resources/pop_layout_elec{year}_s{simpl}_{clusters}.csv", europe_shape=pypsaeur('resources/europe_shape.geojson'), hotmaps_industrial_database="data/Industrial_Database.csv", - network=pypsaeur('networks/{network}_s{simpl}_{clusters}.nc') + network=pypsaeur('networks/elec{year}_s{simpl}_{clusters}.nc') output: - industrial_distribution_key="resources/industrial_distribution_key_{network}_s{simpl}_{clusters}.csv" + industrial_distribution_key="resources/industrial_distribution_key_elec{year}_s{simpl}_{clusters}.csv" threads: 1 resources: mem_mb=1000 script: 'scripts/build_industrial_distribution_key.py' @@ -218,10 +218,10 @@ rule build_industrial_distribution_key: rule build_industrial_production_per_node: input: - industrial_distribution_key="resources/industrial_distribution_key_{network}_s{simpl}_{clusters}.csv", + industrial_distribution_key="resources/industrial_distribution_key_elec{year}_s{simpl}_{clusters}.csv", industrial_production_per_country_tomorrow="resources/industrial_production_per_country_tomorrow.csv" output: - industrial_production_per_node="resources/industrial_production_{network}_s{simpl}_{clusters}.csv" + industrial_production_per_node="resources/industrial_production_elec{year}_s{simpl}_{clusters}.csv" threads: 1 resources: mem_mb=1000 script: 'scripts/build_industrial_production_per_node.py' @@ -230,10 +230,10 @@ rule build_industrial_production_per_node: rule build_industrial_energy_demand_per_node: input: industry_sector_ratios="resources/industry_sector_ratios.csv", - industrial_production_per_node="resources/industrial_production_{network}_s{simpl}_{clusters}.csv", - industrial_energy_demand_per_node_today="resources/industrial_energy_demand_today_{network}_s{simpl}_{clusters}.csv" + industrial_production_per_node="resources/industrial_production_elec{year}_s{simpl}_{clusters}.csv", + industrial_energy_demand_per_node_today="resources/industrial_energy_demand_today_elec{year}_s{simpl}_{clusters}.csv" output: - industrial_energy_demand_per_node="resources/industrial_energy_demand_{network}_s{simpl}_{clusters}.csv" + industrial_energy_demand_per_node="resources/industrial_energy_demand_elec{year}_s{simpl}_{clusters}.csv" threads: 1 resources: mem_mb=1000 script: 'scripts/build_industrial_energy_demand_per_node.py' @@ -252,10 +252,10 @@ rule build_industrial_energy_demand_per_country_today: rule build_industrial_energy_demand_per_node_today: input: - industrial_distribution_key="resources/industrial_distribution_key_{network}_s{simpl}_{clusters}.csv", + industrial_distribution_key="resources/industrial_distribution_key_elec{year}_s{simpl}_{clusters}.csv", industrial_energy_demand_per_country_today="resources/industrial_energy_demand_per_country_today.csv" output: - industrial_energy_demand_per_node_today="resources/industrial_energy_demand_today_{network}_s{simpl}_{clusters}.csv" + industrial_energy_demand_per_node_today="resources/industrial_energy_demand_today_elec{year}_s{simpl}_{clusters}.csv" threads: 1 resources: mem_mb=1000 script: 'scripts/build_industrial_energy_demand_per_node_today.py' @@ -275,10 +275,10 @@ rule build_industrial_energy_demand_per_country: rule build_industrial_demand: input: - clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv", + clustered_pop_layout="resources/pop_layout_elec{year}_s{simpl}_{clusters}.csv", industrial_demand_per_country="resources/industrial_energy_demand_per_country.csv" output: - industrial_demand="resources/industrial_demand_{network}_s{simpl}_{clusters}.csv" + industrial_demand="resources/industrial_demand_elec{year}_s{simpl}_{clusters}.csv" threads: 1 resources: mem_mb=1000 script: 'scripts/build_industrial_demand.py' @@ -286,7 +286,7 @@ rule build_industrial_demand: rule prepare_sector_network: input: - network=pypsaeur('networks/{network}_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc'), + network=pypsaeur('networks/elec{year}_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc'), energy_totals_name='resources/energy_totals.csv', co2_totals_name='resources/co2_totals.csv', transport_name='resources/transport_data.csv', @@ -296,45 +296,45 @@ rule prepare_sector_network: costs=config['costs_dir'] + "costs_{planning_horizons}.csv", h2_cavern = "data/hydrogen_salt_cavern_potentials.csv", co2_budget="data/co2_budget.csv", - profile_offwind_ac=pypsaeur("resources/profile_offwind-ac.nc"), - profile_offwind_dc=pypsaeur("resources/profile_offwind-dc.nc"), - busmap_s=pypsaeur("resources/busmap_{network}_s{simpl}.csv"), - busmap=pypsaeur("resources/busmap_{network}_s{simpl}_{clusters}.csv"), - clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv", - simplified_pop_layout="resources/pop_layout_{network}_s{simpl}.csv", - industrial_demand="resources/industrial_energy_demand_{network}_s{simpl}_{clusters}.csv", - heat_demand_urban="resources/heat_demand_urban_{network}_s{simpl}_{clusters}.nc", - heat_demand_rural="resources/heat_demand_rural_{network}_s{simpl}_{clusters}.nc", - heat_demand_total="resources/heat_demand_total_{network}_s{simpl}_{clusters}.nc", - temp_soil_total="resources/temp_soil_total_{network}_s{simpl}_{clusters}.nc", - temp_soil_rural="resources/temp_soil_rural_{network}_s{simpl}_{clusters}.nc", - temp_soil_urban="resources/temp_soil_urban_{network}_s{simpl}_{clusters}.nc", - temp_air_total="resources/temp_air_total_{network}_s{simpl}_{clusters}.nc", - temp_air_rural="resources/temp_air_rural_{network}_s{simpl}_{clusters}.nc", - temp_air_urban="resources/temp_air_urban_{network}_s{simpl}_{clusters}.nc", - cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc", - cop_soil_rural="resources/cop_soil_rural_{network}_s{simpl}_{clusters}.nc", - cop_soil_urban="resources/cop_soil_urban_{network}_s{simpl}_{clusters}.nc", - cop_air_total="resources/cop_air_total_{network}_s{simpl}_{clusters}.nc", - cop_air_rural="resources/cop_air_rural_{network}_s{simpl}_{clusters}.nc", - cop_air_urban="resources/cop_air_urban_{network}_s{simpl}_{clusters}.nc", - solar_thermal_total="resources/solar_thermal_total_{network}_s{simpl}_{clusters}.nc", - solar_thermal_urban="resources/solar_thermal_urban_{network}_s{simpl}_{clusters}.nc", - solar_thermal_rural="resources/solar_thermal_rural_{network}_s{simpl}_{clusters}.nc" - output: config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc' + profile_offwind_ac=pypsaeur("resources/profile{year}_offwind-ac.nc"), + profile_offwind_dc=pypsaeur("resources/profile{year}_offwind-dc.nc"), + busmap_s=pypsaeur("resources/busmap_elec{year}_s{simpl}.csv"), + busmap=pypsaeur("resources/busmap_elec{year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout="resources/pop_layout_elec{year}_s{simpl}_{clusters}.csv", + simplified_pop_layout="resources/pop_layout_elec{year}_s{simpl}.csv", + industrial_demand="resources/industrial_energy_demand_elec{year}_s{simpl}_{clusters}.csv", + heat_demand_urban="resources/heat_demand_urban_elec{year}_s{simpl}_{clusters}.nc", + heat_demand_rural="resources/heat_demand_rural_elec{year}_s{simpl}_{clusters}.nc", + heat_demand_total="resources/heat_demand_total_elec{year}_s{simpl}_{clusters}.nc", + temp_soil_total="resources/temp_soil_total_elec{year}_s{simpl}_{clusters}.nc", + temp_soil_rural="resources/temp_soil_rural_elec{year}_s{simpl}_{clusters}.nc", + temp_soil_urban="resources/temp_soil_urban_elec{year}_s{simpl}_{clusters}.nc", + temp_air_total="resources/temp_air_total_elec{year}_s{simpl}_{clusters}.nc", + temp_air_rural="resources/temp_air_rural_elec{year}_s{simpl}_{clusters}.nc", + temp_air_urban="resources/temp_air_urban_elec{year}_s{simpl}_{clusters}.nc", + cop_soil_total="resources/cop_soil_total_elec{year}_s{simpl}_{clusters}.nc", + cop_soil_rural="resources/cop_soil_rural_elec{year}_s{simpl}_{clusters}.nc", + cop_soil_urban="resources/cop_soil_urban_elec{year}_s{simpl}_{clusters}.nc", + cop_air_total="resources/cop_air_total_elec{year}_s{simpl}_{clusters}.nc", + cop_air_rural="resources/cop_air_rural_elec{year}_s{simpl}_{clusters}.nc", + cop_air_urban="resources/cop_air_urban_elec{year}_s{simpl}_{clusters}.nc", + solar_thermal_total="resources/solar_thermal_total_elec{year}_s{simpl}_{clusters}.nc", + solar_thermal_urban="resources/solar_thermal_urban_elec{year}_s{simpl}_{clusters}.nc", + solar_thermal_rural="resources/solar_thermal_rural_elec{year}_s{simpl}_{clusters}.nc" + output: config['results_dir'] + config['run'] + '/prenetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc' threads: 1 resources: mem_mb=2000 - benchmark: config['results_dir'] + config['run'] + "/benchmarks/prepare_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}" + benchmark: config['results_dir'] + config['run'] + "/benchmarks/prepare_network/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}" script: "scripts/prepare_sector_network.py" rule plot_network: input: - network=config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" + network=config['results_dir'] + config['run'] + "/postnetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" output: - map=config['results_dir'] + config['run'] + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{co2_budget_name}_{planning_horizons}.pdf", - today=config['results_dir'] + config['run'] + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}-today.pdf" + map=config['results_dir'] + config['run'] + "/maps/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{co2_budget_name}_{planning_horizons}.pdf", + today=config['results_dir'] + config['run'] + "/maps/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}-today.pdf" threads: 2 resources: mem_mb=10000 script: "scripts/plot_network.py" @@ -351,10 +351,10 @@ rule copy_config: rule make_summary: input: - networks=expand(config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", + networks=expand(config['results_dir'] + config['run'] + "/postnetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", **config['scenario']), costs=config['costs_dir'] + "costs_{}.csv".format(config['scenario']['planning_horizons'][0]), - plots=expand(config['results_dir'] + config['run'] + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{co2_budget_name}_{planning_horizons}.pdf", + plots=expand(config['results_dir'] + config['run'] + "/maps/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{co2_budget_name}_{planning_horizons}.pdf", **config['scenario']) #heat_demand_name='data/heating/daily_heat_demand.h5' output: @@ -397,16 +397,16 @@ if config["foresight"] == "overnight": rule solve_network: input: - network=config['results_dir'] + config['run'] + "/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", + network=config['results_dir'] + config['run'] + "/prenetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", costs=config['costs_dir'] + "costs_{planning_horizons}.csv", config=config['summary_dir'] + '/' + config['run'] + '/configs/config.yaml' - output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" + output: config['results_dir'] + config['run'] + "/postnetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" shadow: "shallow" log: - solver=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_solver.log", - python=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_python.log", - memory=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_memory.log" - benchmark: config['results_dir'] + config['run'] + "/benchmarks/solve_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}" + solver=config['results_dir'] + config['run'] + "/logs/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_solver.log", + python=config['results_dir'] + config['run'] + "/logs/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_python.log", + memory=config['results_dir'] + config['run'] + "/logs/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_memory.log" + benchmark: config['results_dir'] + config['run'] + "/benchmarks/solve_network/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}" threads: 4 resources: mem_mb=config['solving']['mem'] # group: "solve" # with group, threads is ignored https://bitbucket.org/snakemake/snakemake/issues/971/group-job-description-does-not-contain @@ -417,15 +417,15 @@ if config["foresight"] == "myopic": rule add_existing_baseyear: input: - network=config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', + network=config['results_dir'] + config['run'] + '/prenetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', powerplants=pypsaeur('resources/powerplants.csv'), - busmap_s=pypsaeur("resources/busmap_{network}_s{simpl}.csv"), - busmap=pypsaeur("resources/busmap_{network}_s{simpl}_{clusters}.csv"), - clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv", + busmap_s=pypsaeur("resources/busmap_elec{year}_s{simpl}.csv"), + busmap=pypsaeur("resources/busmap_elec{year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout="resources/pop_layout_elec{year}_s{simpl}_{clusters}.csv", costs=config['costs_dir'] + "costs_{}.csv".format(config['scenario']['planning_horizons'][0]), - cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc", - cop_air_total="resources/cop_air_total_{network}_s{simpl}_{clusters}.nc" - output: config['results_dir'] + config['run'] + '/prenetworks-brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc' + cop_soil_total="resources/cop_soil_total_elec{year}_s{simpl}_{clusters}.nc", + cop_air_total="resources/cop_air_total_elec{year}_s{simpl}_{clusters}.nc" + output: config['results_dir'] + config['run'] + '/prenetworks-brownfield/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc' wildcard_constraints: planning_horizons=config['scenario']['planning_horizons'][0] #only applies to baseyear threads: 1 @@ -434,18 +434,18 @@ if config["foresight"] == "myopic": def process_input(wildcards): i = config["scenario"]["planning_horizons"].index(int(wildcards.planning_horizons)) - return config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_" + str(config["scenario"]["planning_horizons"][i-1]) + ".nc" + return config['results_dir'] + config['run'] + "/postnetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_" + str(config["scenario"]["planning_horizons"][i-1]) + ".nc" rule add_brownfield: input: - network=config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', + network=config['results_dir'] + config['run'] + '/prenetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', network_p=process_input, #solved network at previous time step costs=config['costs_dir'] + "costs_{planning_horizons}.csv", - cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc", - cop_air_total="resources/cop_air_total_{network}_s{simpl}_{clusters}.nc" + cop_soil_total="resources/cop_soil_total_elec{year}_s{simpl}_{clusters}.nc", + cop_air_total="resources/cop_air_total_elec{year}_s{simpl}_{clusters}.nc" - output: config['results_dir'] + config['run'] + "/prenetworks-brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" + output: config['results_dir'] + config['run'] + "/prenetworks-brownfield/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" threads: 4 resources: mem_mb=2000 script: "scripts/add_brownfield.py" @@ -454,16 +454,16 @@ if config["foresight"] == "myopic": rule solve_network_myopic: input: - network=config['results_dir'] + config['run'] + "/prenetworks-brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", + network=config['results_dir'] + config['run'] + "/prenetworks-brownfield/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", costs=config['costs_dir'] + "costs_{planning_horizons}.csv", config=config['summary_dir'] + '/' + config['run'] + '/configs/config.yaml' - output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" + output: config['results_dir'] + config['run'] + "/postnetworks/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" shadow: "shallow" log: - solver=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_solver.log", - python=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_python.log", - memory=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_memory.log" - benchmark: config['results_dir'] + config['run'] + "/benchmarks/solve_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}" + solver=config['results_dir'] + config['run'] + "/logs/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_solver.log", + python=config['results_dir'] + config['run'] + "/logs/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_python.log", + memory=config['results_dir'] + config['run'] + "/logs/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_memory.log" + benchmark: config['results_dir'] + config['run'] + "/benchmarks/solve_network/elec{year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}" threads: 4 resources: mem_mb=config['solving']['mem'] script: "scripts/solve_network.py" diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index 94cbd133..85543afc 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -5,8 +5,11 @@ import pandas as pd import atlite import helper +year = snakemake.wildcards.year +cutout_name = snakemake.config['atlite']['cutout_name'] +if year: cutout_name = cutout_name.format(year=year) -cutout = atlite.Cutout(snakemake.config['atlite']['cutout_name'], +cutout = atlite.Cutout(cutout_name, cutout_dir=snakemake.config['atlite']['cutout_dir']) diff --git a/scripts/build_heat_demand.py b/scripts/build_heat_demand.py index 865f12bd..0e6cdbd7 100644 --- a/scripts/build_heat_demand.py +++ b/scripts/build_heat_demand.py @@ -15,10 +15,16 @@ if 'snakemake' not in globals(): snakemake.input = Dict() snakemake.output = Dict() -time = pd.date_range(freq='m', **snakemake.config['snapshots']) +year = snakemake.wildcards.year + +snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] +time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) -cutout = atlite.Cutout(snakemake.config['atlite']['cutout_name'], +cutout_name = snakemake.config['atlite']['cutout_name'] +if year: cutout_name = cutout_name.format(year=year) + +cutout = atlite.Cutout(cutout_name, cutout_dir=snakemake.config['atlite']['cutout_dir'], **params) diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index 5093e1b4..15804576 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -21,7 +21,11 @@ if 'snakemake' not in globals(): snakemake.input["urban_percent"] = "data/urban_percent.csv" -cutout = atlite.Cutout(snakemake.config['atlite']['cutout_name'], +year = snakemake.wildcards.year +cutout_name = snakemake.config['atlite']['cutout_name'] +if year: cutout_name = cutout_name.format(year=year) + +cutout = atlite.Cutout(cutout_name, cutout_dir=snakemake.config['atlite']['cutout_dir']) grid_cells = cutout.grid_cells() diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index c26266aa..7d4199d5 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -15,12 +15,17 @@ if 'snakemake' not in globals(): snakemake.input = Dict() snakemake.output = Dict() -time = pd.date_range(freq='m', **snakemake.config['snapshots']) +year = snakemake.wildcards.year + +snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] +time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) +cutout_name = snakemake.config['atlite']['cutout_name'] +if year: cutout_name = cutout_name.format(year=year) -cutout = atlite.Cutout(snakemake.config['atlite']['cutout_name'], +cutout = atlite.Cutout(cutout_name, cutout_dir=snakemake.config['atlite']['cutout_dir'], **params) diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index a55bd606..2cad501c 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -15,11 +15,16 @@ if 'snakemake' not in globals(): snakemake.input = Dict() snakemake.output = Dict() -time = pd.date_range(freq='m', **snakemake.config['snapshots']) +year = snakemake.wildcards.year + +snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] +time = pd.date_range(freq='m', **snapshots) params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) +cutout_name = snakemake.config['atlite']['cutout_name'] +if year: cutout_name = cutout_name.format(year=year) -cutout = atlite.Cutout(snakemake.config['atlite']['cutout_name'], +cutout = atlite.Cutout(cutout_name, cutout_dir=snakemake.config['atlite']['cutout_dir'], **params) From ce03353ac3fbd66c95156e1cd241baf01681f89d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 18 Feb 2022 10:27:10 +0100 Subject: [PATCH 020/591] change year to weather_year --- config.default.yaml | 2 +- config.tutorial.yaml | 2 +- test/config.test1.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.default.yaml b/config.default.yaml index 2c2e151f..9c986494 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -12,7 +12,7 @@ logging: summary_dir: results scenario: - year: [''] # for backwards compatibility + weather_year: [''] # for backwards compatibility simpl: [''] ll: ['copt'] clusters: [37, 128, 256, 512, 1024] diff --git a/config.tutorial.yaml b/config.tutorial.yaml index feee6366..6ff1237d 100755 --- a/config.tutorial.yaml +++ b/config.tutorial.yaml @@ -12,7 +12,7 @@ logging: summary_dir: results scenario: - year: [''] + weather_year: [''] simpl: [''] ll: ['copt'] clusters: [5] diff --git a/test/config.test1.yaml b/test/config.test1.yaml index 9de59e7c..c73e59fb 100755 --- a/test/config.test1.yaml +++ b/test/config.test1.yaml @@ -11,7 +11,7 @@ logging: summary_dir: results scenario: - year: [''] + weather_year: [''] simpl: [''] ll: ['copt'] clusters: [5] From f26cdc132b9bf20c31fdabe3a815c828415cce5c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 18 Feb 2022 11:21:05 +0100 Subject: [PATCH 021/591] add wildcard constraint for weather year --- Snakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index b4b5b98f..fe6242a1 100644 --- a/Snakefile +++ b/Snakefile @@ -18,7 +18,7 @@ ATLITE_NPROCESSES = config['atlite'].get('nprocesses', 4) wildcard_constraints: - year="[0-9]*", + weather_year="[0-9]*", simpl="[a-zA-Z0-9]*|all", clusters="[0-9]+m?|all", ll="(v|c)([0-9\.]+|opt|all)|all", From 8d1047380a406d0724e964cc8cdec7f0030e89e6 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 18 Feb 2022 11:27:07 +0100 Subject: [PATCH 022/591] remove myopic config file --- config.myopic.yaml | 346 --------------------------------------------- 1 file changed, 346 deletions(-) delete mode 100644 config.myopic.yaml diff --git a/config.myopic.yaml b/config.myopic.yaml deleted file mode 100644 index 0dc4cdf3..00000000 --- a/config.myopic.yaml +++ /dev/null @@ -1,346 +0,0 @@ -version: 0.3.0 - -logging_level: INFO - -results_dir: 'results/' -summary_dir: results -costs_dir: '../technology-data/outputs/' -run: 'your-run-name' # use this to keep track of runs with different settings -foresight: 'myopic' #options are overnight, myopic, perfect (perfect is not yet implemented) - - -scenario: - sectors: [E] # ignore this legacy setting - year: [''] # weather year - simpl: [''] # only relevant for PyPSA-Eur - lv: [1.0,1.5] # allowed transmission line volume expansion, can be any float >= 1.0 (today) or "opt" - clusters: [45,50] # number of nodes in Europe, any integer between 37 (1 node per country-zone) and several hundred - opts: [''] # only relevant for PyPSA-Eur - sector_opts: [Co2L0-3H-H-B-solar3-dist1] # this is where the main scenario settings are - # to really understand the options here, look in scripts/prepare_sector_network.py - # Co2Lx specifies the CO2 target in x% of the 1990 values; default will give default (5%); - # Co2L0p25 will give 25% CO2 emissions; Co2Lm0p05 will give 5% negative emissions - # xH is the temporal resolution; 3H is 3-hourly, i.e. one snapshot every 3 hours - # single letters are sectors: T for land transport, H for building heating, - # B for biomass supply, I for industry, shipping and aviation - # solarx or onwindx changes the available installable potential by factor x - # dist{n} includes distribution grids with investment cost of n times cost in data/costs.csv - planning_horizons : [2020, 2030, 2040, 2050] #investment years for myopic and perfect; or costs year for overnight - co2_budget_name: ['go'] #gives shape of CO2 budgets over planning horizon - -# snapshots are originally set in PyPSA-Eur/config.yaml but used again by PyPSA-Eur-Sec -snapshots: - # arguments to pd.date_range - start: "2013-01-01" - end: "2014-01-01" - closed: 'left' # end is not inclusive - -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'] - -atlite: - cutout_dir: '../pypsa-eur/cutouts' - cutout_name: "europe-2013-era5" - -# this information is NOT used but needed as an argument for -# pypsa-eur/scripts/add_electricity.py/load_costs in make_summary.py -electricity: - max_hours: - battery: 6 - H2: 168 - -biomass: - year: 2030 - scenario: "Med" - classes: - solid biomass: ['Primary agricultural residues', 'Forestry energy residue', 'Secondary forestry residues', 'Secondary Forestry residues – sawdust', 'Forestry residues from landscape care biomass', 'Municipal waste'] - not included: ['Bioethanol sugar beet biomass', 'Rapeseeds for biodiesel', 'sunflower and soya for Biodiesel', 'Starchy crops biomass', 'Grassy crops biomass', 'Willow biomass', 'Poplar biomass potential', 'Roundwood fuelwood', 'Roundwood Chips & Pellets'] - biogas: ['Manure biomass potential', 'Sludge biomass'] - -# only relevant for foresight = myopic or perfect -existing_capacities: - grouping_years: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2019] - threshold_capacity: 10 - conventional_carriers: ['lignite', 'coal', 'oil', 'uranium'] - -sector: - 'central' : True - 'central_fraction' : 0.6 - 'dsm_restriction_value' : 0.75 #Set to 0 for no restriction on BEV DSM - 'dsm_restriction_time' : 7 #Time at which SOC of BEV has to be dsm_restriction_value - 'transport_heating_deadband_upper' : 20. - 'transport_heating_deadband_lower' : 15. - 'ICE_lower_degree_factor' : 0.375 #in per cent increase in fuel consumption per degree above deadband - 'ICE_upper_degree_factor' : 1.6 - 'EV_lower_degree_factor' : 0.98 - 'EV_upper_degree_factor' : 0.63 - 'district_heating_loss' : 0.15 - 'bev' : True #turns on EV battery - 'bev_availability' : 0.5 #How many cars do smart charging - 'v2g' : True #allows feed-in to grid from EV battery - 'transport_fuel_cell_share' : 0. #0 means all EVs, 1 means all FCs - 'shipping_average_efficiency' : 0.4 #For conversion of fuel oil to propulsion in 2011 - 'time_dep_hp_cop' : True - 'space_heating_fraction' : 1.0 #fraction of space heating active - 'retrofitting' : False - 'retroI-fraction' : 0.25 - 'retroII-fraction' : 0.55 - 'retrofitting-cost_factor' : 1.0 - 'tes' : True - 'tes_tau' : 3. - 'boilers' : True - 'oil_boilers': False - 'chp' : True - 'micro_chp' : False - 'solar_thermal' : True - 'solar_cf_correction': 0.788457 # = >>> 1/1.2683 - 'marginal_cost_storage' : 0. #1e-4 - 'methanation' : True - 'helmeth' : True - 'dac' : True - 'co2_vent' : True - 'SMR' : True - 'ccs_fraction' : 0.9 - 'hydrogen_underground_storage' : True - 'use_fischer_tropsch_waste_heat' : True - 'use_fuel_cell_waste_heat' : True - 'electricity_distribution_grid' : False - 'electricity_distribution_grid_cost_factor' : 1.0 #multiplies cost in data/costs.csv - 'electricity_grid_connection' : True # only applies to onshore wind and utility PV - 'gas_distribution_grid' : True - 'gas_distribution_grid_cost_factor' : 1.0 #multiplies cost in data/costs.csv - -costs: - year: 2030 - lifetime: 25 #default lifetime - # From a Lion Hirth paper, also reflects average of Noothout et al 2016 - discountrate: 0.07 - # [EUR/USD] ECB: https://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html # noqa: E501 - USD2013_to_EUR2013: 0.7532 - - # Marginal and capital costs can be overwritten - # capital_cost: - # Wind: Bla - marginal_cost: # - solar: 0.01 - onwind: 0.015 - offwind: 0.015 - hydro: 0. - H2: 0. - battery: 0. - - emission_prices: # only used with the option Ep (emission prices) - co2: 0. - - lines: - length_factor: 1.25 #to estimate offwind connection costs - - -solving: - #tmpdir: "path/to/tmp" - options: - formulation: kirchhoff - clip_p_max_pu: 1.e-2 - load_shedding: false - noisy_costs: true - - min_iterations: 1 - max_iterations: 1 - # nhours: 1 - - solver: - name: gurobi - threads: 4 - method: 2 # barrier - crossover: 0 - BarConvTol: 1.e-5 - Seed: 123 - AggFill: 0 - PreDual: 0 - GURO_PAR_BARDENSETHRESH: 200 - #FeasibilityTol: 1.e-6 - - #name: cplex - #threads: 4 - #lpmethod: 4 # barrier - #solutiontype: 2 # non basic solution, ie no crossover - #barrier_convergetol: 1.e-5 - #feasopt_tolerance: 1.e-6 - mem: 30000 #memory in MB; 20 GB enough for 50+B+I+H2; 100 GB for 181+B+I+H2 - -industry: - 'St_primary_fraction' : 0.3 # fraction of steel produced via primary route (DRI + EAF) versus secondary route (EAF); today fraction is 0.6 - 'H2_DRI' : 1.7 #H2 consumption in Direct Reduced Iron (DRI), MWh_H2,LHV/ton_Steel from Vogl et al (2018) doi:10.1016/j.jclepro.2018.08.279 - 'elec_DRI' : 0.322 #electricity consumption in Direct Reduced Iron (DRI) shaft, MWh/tSt HYBRIT brochure https://ssabwebsitecdn.azureedge.net/-/media/hybrit/files/hybrit_brochure.pdf - 'Al_primary_fraction' : 0.2 # fraction of aluminium produced via the primary route versus scrap; today fraction is 0.4 - 'MWh_CH4_per_tNH3_SMR' : 10.8 # 2012's demand from https://ec.europa.eu/docsroom/documents/4165/attachments/1/translations/en/renditions/pdf - 'MWh_elec_per_tNH3_SMR' : 0.7 # same source, assuming 94-6% split methane-elec of total energy demand 11.5 MWh/tNH3 - 'MWh_H2_per_tNH3_electrolysis' : 6.5 # from https://doi.org/10.1016/j.joule.2018.04.017, around 0.197 tH2/tHN3 (>3/17 since some H2 lost and used for energy) - 'MWh_elec_per_tNH3_electrolysis' : 1.17 # from https://doi.org/10.1016/j.joule.2018.04.017 Table 13 (air separation and HB) - 'NH3_process_emissions' : 24.5 # in MtCO2/a from SMR for H2 production for NH3 from UNFCCC for 2015 for EU28 - 'petrochemical_process_emissions' : 25.5 # in MtCO2/a for petrochemical and other from UNFCCC for 2015 for EU28 - 'HVC_primary_fraction' : 1.0 #fraction of current non-ammonia basic chemicals produced via primary route - -plotting: - map: - figsize: [7, 7] - boundaries: [-10.2, 29, 35, 72] - p_nom: - bus_size_factor: 5.e+4 - linewidth_factor: 3.e+3 # 1.e+3 #3.e+3 - - costs_max: 1200 - costs_threshold: 1 - - - energy_max: 20000. - energy_min: -15000. - energy_threshold: 50. - - - vre_techs: ["onwind", "offwind-ac", "offwind-dc", "solar", "ror"] - renewable_storage_techs: ["PHS","hydro"] - conv_techs: ["OCGT", "CCGT", "Nuclear", "Coal"] - storage_techs: ["hydro+PHS", "battery", "H2"] - # store_techs: ["Li ion", "water tanks"] - load_carriers: ["AC load"] #, "heat load", "Li ion load"] - AC_carriers: ["AC line", "AC transformer"] - link_carriers: ["DC line", "Converter AC-DC"] - heat_links: ["heat pump", "resistive heater", "CHP heat", "CHP electric", - "gas boiler", "central heat pump", "central resistive heater", "central CHP heat", - "central CHP electric", "central gas boiler"] - heat_generators: ["gas boiler", "central gas boiler", "solar thermal collector", "central solar thermal collector"] - tech_colors: - "onwind" : "b" - "onshore wind" : "b" - 'offwind' : "c" - 'offshore wind' : "c" - 'offwind-ac' : "c" - 'offshore wind (AC)' : "c" - 'offwind-dc' : "#009999" - 'offshore wind (DC)' : "#009999" - 'wave' : "#004444" - "hydro" : "#3B5323" - "hydro reservoir" : "#3B5323" - "ror" : "#78AB46" - "run of river" : "#78AB46" - 'hydroelectricity' : '#006400' - 'solar' : "y" - 'solar PV' : "y" - 'solar thermal' : 'coral' - 'solar rooftop' : '#e6b800' - "OCGT" : "wheat" - "OCGT marginal" : "sandybrown" - "OCGT-heat" : "orange" - "gas boiler" : "orange" - "gas boilers" : "orange" - "gas boiler marginal" : "orange" - "gas-to-power/heat" : "orange" - "gas" : "brown" - "natural gas" : "brown" - "SMR" : "#4F4F2F" - "oil" : "#B5A642" - "oil boiler" : "#B5A677" - "lines" : "k" - "transmission lines" : "k" - "H2" : "m" - "hydrogen storage" : "m" - "battery" : "slategray" - "battery storage" : "slategray" - "home battery" : "#614700" - "home battery storage" : "#614700" - "Nuclear" : "r" - "Nuclear marginal" : "r" - "nuclear" : "r" - "uranium" : "r" - "Coal" : "k" - "coal" : "k" - "Coal marginal" : "k" - "Lignite" : "grey" - "lignite" : "grey" - "Lignite marginal" : "grey" - "CCGT" : "orange" - "CCGT marginal" : "orange" - "heat pumps" : "#76EE00" - "heat pump" : "#76EE00" - "air heat pump" : "#76EE00" - "ground heat pump" : "#40AA00" - "power-to-heat" : "#40AA00" - "resistive heater" : "pink" - "Sabatier" : "#FF1493" - "methanation" : "#FF1493" - "power-to-gas" : "#FF1493" - "power-to-liquid" : "#FFAAE9" - "helmeth" : "#7D0552" - "helmeth" : "#7D0552" - "DAC" : "#E74C3C" - "co2 stored" : "#123456" - "CO2 sequestration" : "#123456" - "CCS" : "k" - "co2" : "#123456" - "co2 vent" : "#654321" - "solid biomass for industry co2 from atmosphere" : "#654321" - "solid biomass for industry co2 to stored": "#654321" - "gas for industry co2 to atmosphere": "#654321" - "gas for industry co2 to stored": "#654321" - "Fischer-Tropsch" : "#44DD33" - "kerosene for aviation": "#44BB11" - "naphtha for industry" : "#44FF55" - "water tanks" : "#BBBBBB" - "hot water storage" : "#BBBBBB" - "hot water charging" : "#BBBBBB" - "hot water discharging" : "#999999" - "CHP" : "r" - "CHP heat" : "r" - "CHP electric" : "r" - "PHS" : "g" - "Ambient" : "k" - "Electric load" : "b" - "Heat load" : "r" - "Transport load" : "grey" - "heat" : "darkred" - "rural heat" : "#880000" - "central heat" : "#b22222" - "decentral heat" : "#800000" - "low-temperature heat for industry" : "#991111" - "process heat" : "#FF3333" - "heat demand" : "darkred" - "electric demand" : "k" - "Li ion" : "grey" - "district heating" : "#CC4E5C" - "retrofitting" : "purple" - "building retrofitting" : "purple" - "BEV charger" : "grey" - "V2G" : "grey" - "transport" : "grey" - "electricity" : "k" - "gas for industry" : "#333333" - "solid biomass for industry" : "#555555" - "industry electricity" : "#222222" - "industry new electricity" : "#222222" - "process emissions to stored" : "#444444" - "process emissions to atmosphere" : "#888888" - "process emissions" : "#222222" - "transport fuel cell" : "#AAAAAA" - "biogas" : "#800000" - "solid biomass" : "#DAA520" - "today" : "#D2691E" - "shipping" : "#6495ED" - "electricity distribution grid" : "#333333" - nice_names: - # OCGT: "Gas" - # OCGT marginal: "Gas (marginal)" - offwind: "offshore wind" - onwind: "onshore wind" - battery: "Battery storage" - lines: "Transmission lines" - AC line: "AC lines" - AC-AC: "DC lines" - ror: "Run of river" - nice_names_n: - offwind: "offshore\nwind" - onwind: "onshore\nwind" - # OCGT: "Gas" - H2: "Hydrogen\nstorage" - # OCGT marginal: "Gas (marginal)" - lines: "transmission\nlines" - ror: "run of river" From 4397f1fd0c52cc4454b231720d92cfdfeb29c1f3 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 18 Feb 2022 11:32:06 +0100 Subject: [PATCH 023/591] minor fixes --- Snakefile | 2 +- config.default.yaml | 2 -- scripts/build_population_layouts.py | 5 ++++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Snakefile b/Snakefile index c0c1c7fa..4efb15f1 100644 --- a/Snakefile +++ b/Snakefile @@ -12,7 +12,7 @@ configfile: "config.yaml" wildcard_constraints: - year="[0-9]*", + weather_year="[0-9]*", lv="[a-z0-9\.]+", simpl="[a-zA-Z0-9]*", clusters="[0-9]+m?", diff --git a/config.default.yaml b/config.default.yaml index 010c31d3..63dcab51 100644 --- a/config.default.yaml +++ b/config.default.yaml @@ -65,8 +65,6 @@ snapshots: end: "2014-01-01" closed: left # end is not inclusive -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'] - atlite: cutout: ../pypsa-eur/cutouts/europe-2013-era5.nc diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index e83dd5f3..a5ae2ebf 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -12,7 +12,10 @@ from vresutils import shapes as vshapes if __name__ == '__main__': if 'snakemake' not in globals(): from helper import mock_snakemake - snakemake = mock_snakemake('build_population_layouts', year='') + snakemake = mock_snakemake( + 'build_population_layouts', + weather_year='', + ) year = snakemake.wildcards.weather_year cutout_config = snakemake.config['atlite']['cutout'] From cd2078849a45aca70eb43257df57e1fbda99709d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 18 Feb 2022 11:33:30 +0100 Subject: [PATCH 024/591] remove misplaced code snippet --- scripts/build_clustered_population_layouts.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index e9ef7398..7a8de88b 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -5,10 +5,6 @@ import xarray as xr import pandas as pd import atlite -year = snakemake.wildcards.weather_year -cutout_name = snakemake.config['atlite']['cutout_name'] -if year: cutout_name = cutout_name.format(year=year) - if __name__ == '__main__': if 'snakemake' not in globals(): from helper import mock_snakemake From a71552eb1b1ecf20eb4c2cb54b5b25b51a6968d0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 09:30:52 +0200 Subject: [PATCH 025/591] fix parameter correcitons --- data/parameter_corrections.yaml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/data/parameter_corrections.yaml b/data/parameter_corrections.yaml index d16d5d24..b50fc03a 100644 --- a/data/parameter_corrections.yaml +++ b/data/parameter_corrections.yaml @@ -38,22 +38,6 @@ Link: "T23": "6355" # bus0 == bus1 to remove link in remove_unconnected_components (NordBalt) bus1: index: -<<<<<<< HEAD - "11511": "6240" # fix wrong bus allocation from 6241 - "14559": "6240" # fix wrong bus allocation from 6241 - "12998": "1333" # combine link 12998 + 12997 in 12998 - "5627": '2309' # combine link 5627 + 5628 in 5627 - "8068": "5819" # fix GB location of Anglo-Scottish interconnector - length: - index: - "12998": 409.0 - "5627": 26.39 - bus0: - index: - "14552": "5819" # fix GB location of GB-IE interconnector - "5628": "7276" # bus0 == bus1 to remove link in remove_unconnected_components - "12997": "7276" # bus0 == bus1 to remove link in remove_unconnected_components -======= "12931": "8152" # BorWin3 "5582": "2382" # combine link 5583 + 5582 in 5582 (Sardinia) "13589": "1349" # combine link 13589 + 13588 in 13589 (Sardinia) @@ -72,4 +56,3 @@ Line: v_nom: index: "14573": 220 # 220/380kV issue of substation in PT ->>>>>>> master From 6d260435a633d18e049715b741ae1e0e4a4e7c65 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 13:49:37 +0200 Subject: [PATCH 026/591] allow fixed load data year deviating from snapshots --- Snakefile | 4 ++-- config.default.yaml | 2 +- scripts/build_load_data.py | 20 ++++++++++++++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Snakefile b/Snakefile index 518f5619..94ad7926 100644 --- a/Snakefile +++ b/Snakefile @@ -77,8 +77,8 @@ rule retrieve_load_data: rule build_load_data: input: "data/load_raw.csv" - output: "resources/load.csv" - log: "logs/build_load_data.log" + output: "resources/load{weather_year}.csv" + log: "logs/build_load_data{weather_year}.log" script: 'scripts/build_load_data.py' diff --git a/config.default.yaml b/config.default.yaml index 9c986494..c1dbd8b7 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -196,7 +196,7 @@ load: time_shift_for_large_gaps: 1w # data gaps up until this size are copied by copying from manual_adjustments: true # false scaling_factor: 1.0 - fallback_year: 2013 + fixed_year: false # false or year costs: year: 2030 diff --git a/scripts/build_load_data.py b/scripts/build_load_data.py index 10921782..0cad8ddf 100755 --- a/scripts/build_load_data.py +++ b/scripts/build_load_data.py @@ -196,11 +196,23 @@ if __name__ == "__main__": configure_logging(snakemake) + weather_year = snakemake.wildcard.weather_year + if weather_year: + snapshots = dict( + start=weather_year, + end=str(int(weather_year)+1), + closed="left" + ) + else: + snapshots = snakemake.config['snapshots'] + snapshots = pd.date_range(freq='h', **snapshots) + + fixed_year = snakemake.config["load"].get("fixed_year", False) + years = slice(fixed_year, fixed_year) if fixed_year else slice(snapshots[0], snapshots[-1]) + powerstatistics = snakemake.config['load']['power_statistics'] interpolate_limit = snakemake.config['load']['interpolate_limit'] countries = snakemake.config['countries'] - snapshots = pd.date_range(freq='h', **snakemake.config['snapshots']) - years = slice(snapshots[0], snapshots[-1]) time_shift = snakemake.config['load']['time_shift_for_large_gaps'] load = load_timeseries(snakemake.input[0], years, countries, powerstatistics) @@ -220,5 +232,9 @@ if __name__ == "__main__": '`time_shift_for_large_gaps` or modify the `manual_adjustment` function ' 'for implementing the needed load data modifications.') + # need to reindex load time series to target year + if fixed_year: + load.index = load.index.map(lambda t: t.replace(year=snapshots.year[0])) + load.to_csv(snakemake.output[0]) From 2b43f43006a026bd6ee70233a9844b5c5013533f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 13:51:08 +0200 Subject: [PATCH 027/591] add more versatile cutout building with weather years --- Snakefile | 13 ++++++++++++- scripts/build_cutout.py | 16 +++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Snakefile b/Snakefile index 94ad7926..9a65d5df 100644 --- a/Snakefile +++ b/Snakefile @@ -18,7 +18,7 @@ ATLITE_NPROCESSES = config['atlite'].get('nprocesses', 4) wildcard_constraints: - weather_year="[0-9]*", + weather_year="[0-9]{4}|$", simpl="[a-zA-Z0-9]*|all", clusters="[0-9]+m?|all", ll="(v|c)([0-9\.]+|opt|all)|all", @@ -148,6 +148,9 @@ rule build_bus_regions: script: "scripts/build_bus_regions.py" if config['enable'].get('build_cutout', False): + + ruleorder: build_cutout_year > build_cutout + rule build_cutout: input: regions_onshore="resources/regions_onshore.geojson", @@ -159,6 +162,14 @@ if config['enable'].get('build_cutout', False): resources: mem_mb=ATLITE_NPROCESSES * 1000 script: "scripts/build_cutout.py" + rule build_cutout_year: + input: rules.build_cutout.input + output: "cutouts/{cutout}-{weather_year}.nc" + log: "logs/build_cutout/{cutout}-{weather_year}.log" + benchmark: "benchmarks/build_cutout_{cutout}-{weather_year}" + threads: ATLITE_NPROCESSES + resources: mem_mb=ATLITE_NPROCESSES * 1000 + script: "scripts/build_cutout.py" if config['enable'].get('retrieve_cutout', True): rule retrieve_cutout: diff --git a/scripts/build_cutout.py b/scripts/build_cutout.py index 2722a62b..a5681b00 100644 --- a/scripts/build_cutout.py +++ b/scripts/build_cutout.py @@ -103,15 +103,21 @@ logger = logging.getLogger(__name__) if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('build_cutout', cutout='europe-2013-era5') + # snakemake = mock_snakemake('build_cutout_year', cutout='europe-era5', weather_year=2011) + snakemake = mock_snakemake('build_cutout', cutout='europe-era5') configure_logging(snakemake) - # TODO make it accept year independent config cutout_params = snakemake.config['atlite']['cutouts'][snakemake.wildcards.cutout] - snapshots = pd.date_range(freq='h', **snakemake.config['snapshots']) - time = [snapshots[0], snapshots[-1]] - cutout_params['time'] = slice(*cutout_params.get('time', time)) + if hasattr(snakemake.wildcards, 'weather_year'): + time = snakemake.wildcards.weather_year + cutout_params["time"] = [time, time] + + if "time" not in cutout_params: + snapshots = pd.date_range(freq='h', **snakemake.config['snapshots']) + cutout_params["time"] = [snapshots[0], snapshots[-1]] + + cutout_params['time'] = slice(*cutout_params['time']) if {'x', 'y', 'bounds'}.isdisjoint(cutout_params): # Determine the bounds from bus regions with a buffer of two grid cells From 4a44c45ace3732c3723d13d3dceabdd31c97237a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 13:51:56 +0200 Subject: [PATCH 028/591] add option to cut Feb 29 in leap years --- config.default.yaml | 1 + scripts/add_electricity.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/config.default.yaml b/config.default.yaml index c1dbd8b7..9e7841e8 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -37,6 +37,7 @@ enable: build_natura_raster: false retrieve_natura_raster: true custom_busmap: false + drop_leap_days: true electricity: voltages: [220., 300., 380.] diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index bd6a5e46..a035f437 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -625,4 +625,8 @@ if __name__ == "__main__": add_nice_carrier_names(n, snakemake.config) + if snakemake.config['enable'].get('drop_leap_days', True): + leap_days = (n.snapshots.day == 29) & (n.snapshots.month == 2) + n.set_snapshots(n.snapshots[~leap_days]) + n.export_to_netcdf(snakemake.output[0]) From 91ca07d72f66b2796ef948928883db269505119d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 14:00:47 +0200 Subject: [PATCH 029/591] add option to specify deviating norm year for hydro --- config.default.yaml | 1 + scripts/build_hydro_profile.py | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/config.default.yaml b/config.default.yaml index 9e7841e8..010631e4 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -169,6 +169,7 @@ renewable: 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 clip_min_inflow: 1.0 + norm_year: 2013 lines: types: diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 70c8380e..fdd028e9 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -84,8 +84,12 @@ if __name__ == "__main__": eia_stats = vhydro.get_eia_annual_hydro_generation(snakemake.input.eia_hydro_generation).reindex(columns=countries) - if len(year) > 0 and year not in eia_stats.index: - eia_stats.loc[year] = eia_stats.mean() + weather_year = snakemake.wildcards.weather_year + norm_year = snakemake.config['renewable']['hydro'].get('norm_year') + if norm_year: + eia_stats.loc[weather_year] = eia_stats.loc[norm_year] + elif weather_year and weather_year not in eia_stats.index: + eia_stats.loc[weather_year] = eia_stats.median() inflow = cutout.runoff(shapes=country_shapes, smooth=True, From ff2de7066f477f8af13f8eea29906d038ed0d8f4 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 14:01:27 +0200 Subject: [PATCH 030/591] remove upstream deleted build_country_flh --- scripts/build_country_flh.py | 245 ----------------------------------- 1 file changed, 245 deletions(-) delete mode 100644 scripts/build_country_flh.py diff --git a/scripts/build_country_flh.py b/scripts/build_country_flh.py deleted file mode 100644 index 0b65f136..00000000 --- a/scripts/build_country_flh.py +++ /dev/null @@ -1,245 +0,0 @@ -#!/usr/bin/env python - -# SPDX-FileCopyrightText: : 2017-2020 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: GPL-3.0-or-later - -""" -Create ``.csv`` files and plots for comparing per country full load hours of renewable time series. - -Relevant Settings ------------------ - -.. code:: yaml - - snapshots: - - renewable: - {technology}: - cutout: - resource: - correction_factor: - -.. seealso:: - Documentation of the configuration file ``config.yaml`` at - :ref:`snapshots_cf`, :ref:`renewable_cf` - -Inputs ------- - -- ``data/bundle/corine/g250_clc06_V18_5.tif``: `CORINE Land Cover (CLC) `_ inventory on `44 classes `_ of land use (e.g. forests, arable land, industrial, urban areas). - - .. image:: img/corine.png - :scale: 33 % - -- ``data/bundle/GEBCO_2014_2D.nc``: A `bathymetric `_ data set with a global terrain model for ocean and land at 15 arc-second intervals by the `General Bathymetric Chart of the Oceans (GEBCO) `_. - - .. image:: img/gebco_2019_grid_image.jpg - :scale: 50 % - - **Source:** `GEBCO `_ - -- ``data/pietzker2014.xlsx``: `Supplementary material 2 `_ from `Pietzcker et al. `_; not part of the data bundle; download and place here yourself. -- ``resources/natura.tiff``: confer :ref:`natura` -- ``resources/country_shapes.geojson``: confer :ref:`shapes` -- ``resources/offshore_shapes.geojson``: confer :ref:`shapes` -- ``resources/regions_onshore.geojson``: (if not offshore wind), confer :ref:`busregions` -- ``resources/regions_offshore.geojson``: (if offshore wind), :ref:`busregions` -- ``"cutouts/" + config["renewable"][{technology}]['cutout']``: :ref:`cutout` -- ``networks/base.nc``: :ref:`base` - -Outputs -------- - -- ``resources/country_flh_area_{technology}.csv``: -- ``resources/country_flh_aggregated_{technology}.csv``: -- ``resources/country_flh_uncorrected_{technology}.csv``: -- ``resources/country_flh_{technology}.pdf``: -- ``resources/country_exclusion_{technology}``: - -Description ------------ - -""" - -import logging -from _helpers import configure_logging - -import os -import atlite -import numpy as np -import xarray as xr -import pandas as pd - -import geokit as gk -from scipy.sparse import vstack -import pycountry as pyc -import matplotlib.pyplot as plt - -from vresutils import landuse as vlanduse -from vresutils.array import spdiag - -import progressbar as pgb - -from build_renewable_profiles import init_globals, calculate_potential - -logger = logging.getLogger(__name__) - - -def build_area(flh, countries, areamatrix, breaks, fn): - area_unbinned = xr.DataArray(areamatrix.todense(), [countries, capacity_factor.coords['spatial']]) - bins = xr.DataArray(pd.cut(flh.to_series(), bins=breaks), flh.coords, name="bins") - area = area_unbinned.groupby(bins).sum(dim="spatial").to_pandas() - area.loc[:,slice(*area.sum()[lambda s: s > 0].index[[0,-1]])].to_csv(fn) - area.columns = area.columns.map(lambda s: s.left) - return area - - -def plot_area_not_solar(area, countries): - # onshore wind/offshore wind - a = area.T - - fig, axes = plt.subplots(nrows=len(countries), sharex=True) - for c, ax in zip(countries, axes): - d = a[[c]] / 1e3 - d.plot.bar(ax=ax, legend=False, align='edge', width=1.) - ax.set_ylabel(f"Potential {c} / GW") - ax.set_title(c) - ax.legend() - ax.set_xlabel("Full-load hours") - fig.savefig(snakemake.output.plot, transparent=True, bbox_inches='tight') - -def plot_area_solar(area, p_area, countries): - # onshore wind/offshore wind - p = p_area.T - a = area.T - - fig, axes = plt.subplots(nrows=len(countries), sharex=True, squeeze=False) - for c, ax in zip(countries, axes.flat): - d = pd.concat([a[c], p[c]], keys=['PyPSA-Eur', 'Pietzker'], axis=1) / 1e3 - d.plot.bar(ax=ax, legend=False, align='edge', width=1.) - # ax.set_ylabel(f"Potential {c} / GW") - ax.set_title(c) - ax.legend() - ax.set_xlabel("Full-load hours") - - fig.savefig(snakemake.output.plot, transparent=True, bbox_inches='tight') - - -def build_aggregate(flh, countries, areamatrix, breaks, p_area, fn): - agg_a = pd.Series(np.ravel((areamatrix / areamatrix.sum(axis=1)).dot(flh.values)), - countries, name="PyPSA-Eur") - - if p_area is None: - agg_a['Overall'] = float((np.asarray((areamatrix.sum(axis=0) / areamatrix.sum()) - .dot(flh.values)).squeeze())) - - agg = pd.DataFrame({'PyPSA-Eur': agg_a}) - else: - # Determine indices of countries which are also in Pietzcker - inds = pd.Index(countries).get_indexer(p_area.index) - areamatrix = areamatrix[inds] - - agg_a['Overall'] = float((np.asarray((areamatrix.sum(axis=0) / areamatrix.sum()) - .dot(flh.values)).squeeze())) - - midpoints = (breaks[1:] + breaks[:-1])/2. - p = p_area.T - - # Per-country FLH comparison - agg_p = pd.Series((p / p.sum()).multiply(midpoints, axis=0).sum(), name="Pietzker") - agg_p['Overall'] = float((p.sum(axis=1) / p.sum().sum()).multiply(midpoints, axis=0).sum()) - - agg = pd.DataFrame({'PyPSA-Eur': agg_a, 'Pietzcker': agg_p, 'Ratio': agg_p / agg_a}) - - agg.to_csv(fn) - -if __name__ == '__main__': - if 'snakemake' not in globals(): - from _helpers import mock_snakemake - snakemake = mock_snakemake('build_country_flh', technology='solar') - configure_logging(snakemake) - - pgb.streams.wrap_stderr() - - - config = snakemake.config['renewable'][snakemake.wildcards.technology] - - year = snakemake.wildcards.year - snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] - time = pd.date_range(freq='m', **snapshots) - params = dict(years=slice(*time.year[[0, -1]]), months=slice(*time.month[[0, -1]])) - - cutout = atlite.Cutout(config['cutout'], - cutout_dir=os.path.dirname(snakemake.input.cutout), - **params) - - minx, maxx, miny, maxy = cutout.extent - dx = (maxx - minx) / (cutout.shape[1] - 1) - dy = (maxy - miny) / (cutout.shape[0] - 1) - bounds = gk.Extent.from_xXyY((minx - dx/2., maxx + dx/2., - miny - dy/2., maxy + dy/2.)) - - # Use GLAES to compute available potentials and the transition matrix - paths = dict(snakemake.input) - - init_globals(bounds.xXyY, dx, dy, config, paths) - regions = gk.vector.extractFeatures(paths["regions"], onlyAttr=True) - countries = pd.Index(regions["name"], name="country") - - widgets = [ - pgb.widgets.Percentage(), - ' ', pgb.widgets.SimpleProgress(format='(%s)' % pgb.widgets.SimpleProgress.DEFAULT_FORMAT), - ' ', pgb.widgets.Bar(), - ' ', pgb.widgets.Timer(), - ' ', pgb.widgets.ETA() - ] - progressbar = pgb.ProgressBar(prefix='Compute GIS potentials: ', widgets=widgets, max_value=len(countries)) - - if not os.path.isdir(snakemake.output.exclusion): - os.makedirs(snakemake.output.exclusion) - - matrix = vstack([calculate_potential(i, save_map=os.path.join(snakemake.output.exclusion, countries[i])) - for i in progressbar(regions.index)]) - - areamatrix = matrix * spdiag(vlanduse._cutout_cell_areas(cutout).ravel()) - areamatrix.data[areamatrix.data < 1.] = 0 # ignore weather cells where only less than 1 km^2 can be installed - areamatrix.eliminate_zeros() - - resource = config['resource'] - func = getattr(cutout, resource.pop('method')) - correction_factor = config.get('correction_factor', 1.) - - capacity_factor = func(capacity_factor=True, show_progress='Compute capacity factors: ', **resource).stack(spatial=('y', 'x')) - flh_uncorr = capacity_factor * 8760 - flh_corr = correction_factor * flh_uncorr - - if snakemake.wildcards.technology == 'solar': - pietzcker = pd.read_excel(snakemake.input.pietzker, sheet_name="PV on all area", skiprows=2, header=[0,1]).iloc[1:177] - p_area1_50 = pietzcker['Usable Area at given FLh in 1-50km distance to settlement '].dropna(axis=1) - p_area1_50.columns = p_area1_50.columns.str.split(' ').str[0] - - p_area50_100 = pietzcker['Usable Area at given FLh in 50-100km distance to settlement '] - - p_area = p_area1_50 + p_area50_100 - cols = p_area.columns - breaks = cols.str.split('-').str[0].append(pd.Index([cols[-1].split('-')[1]])).astype(int) - p_area.columns = breaks[:-1] - - p_area = p_area.reindex(countries.map(lambda c: pyc.countries.get(alpha_2=c).name)) - p_area.index = countries - p_area = p_area.dropna() # Pietzcker does not have data for CZ and MK - else: - breaks = np.r_[0:8000:50] - p_area = None - - - area = build_area(flh_corr, countries, areamatrix, breaks, snakemake.output.area) - - if snakemake.wildcards.technology == 'solar': - plot_area_solar(area, p_area, p_area.index) - else: - plot_area_not_solar(area, countries) - - build_aggregate(flh_uncorr, countries, areamatrix, breaks, p_area, snakemake.output.uncorrected) - build_aggregate(flh_corr, countries, areamatrix, breaks, p_area, snakemake.output.aggregated) From e9b3cb7558b42c3e70e8518e3447820aa716dbae Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 14:02:19 +0200 Subject: [PATCH 031/591] add_electricity: remove unused load data handling --- scripts/add_electricity.py | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index a035f437..76aa7fa1 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -207,37 +207,11 @@ def attach_load(n, regions, load, nuts3_shapes, countries, scaling=1.): regions = (gpd.read_file(regions).set_index('name') .reindex(substation_lv_i)) -# ------------- TO MERGE -------------- - available_years = range(2011,2016) - requested_years = n.snapshots.year[[0,-1]] - use_fallback = any(year not in available_years for year in requested_years) - - if use_fallback: - fallback_year = str(snakemake.config["load"]["fallback_year"]) - load_years = [fallback_year, fallback_year] - logger.warning(f"Requested years {list(requested_years.unique().values)} " - f"for load time series not in available years {list(available_years)}. " - f"Falling back to year {fallback_year}.") - else: - load_years = requested_years.astype(str) - - opsd_load = (timeseries_opsd(slice(*load_years), - snakemake.input.opsd_load) * - snakemake.config.get('load', {}).get('scaling_factor', 1.0)) - - if use_fallback: - assert len(requested_years.unique()) == 1, "Fallback for load time series requires single year!" - opsd_load.index = opsd_load.index.map(lambda t: t.replace(year=requested_years[0])) - - # Convert to naive UTC (has to be explicit since pandas 0.24) - opsd_load.index = opsd_load.index.tz_localize(None) - opsd_load = (pd.read_csv(load, index_col=0, parse_dates=True) .filter(items=countries)) logger.info(f"Load data scaled with scalling factor {scaling}.") opsd_load *= scaling -# ------------- TO MERGE -------------- nuts3 = gpd.read_file(nuts3_shapes).set_index('index') From 500890b6af5c1068a9f514d430723a42e33ddf17 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 14:02:40 +0200 Subject: [PATCH 032/591] Snakefile: remove duplicate use of weather year wildcard --- Snakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index 9a65d5df..8e138228 100644 --- a/Snakefile +++ b/Snakefile @@ -398,7 +398,7 @@ rule make_summary: rule plot_summary: input: "results/summaries/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}" - output: "results/plots/{weather_year}/summary_{summary}_elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.{ext}" + output: "results/plots/summary_{summary}_elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.{ext}" log: "logs/plot_summary/{summary}_elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}_{ext}.log" script: "scripts/plot_summary.py" From 5cc6e9e18a71098d3a4c20978a641fca13c71c4f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 14:07:48 +0200 Subject: [PATCH 033/591] doc: add reference to new config settings --- doc/configtables/hydro.csv | 1 + doc/configtables/load.csv | 1 + doc/configtables/toplevel.csv | 1 + 3 files changed, 3 insertions(+) diff --git a/doc/configtables/hydro.csv b/doc/configtables/hydro.csv index fc53334e..8148b256 100644 --- a/doc/configtables/hydro.csv +++ b/doc/configtables/hydro.csv @@ -4,3 +4,4 @@ carriers,--,"Any subset of {'ror', 'PHS', 'hydro'}","Specifies the types of hydr PHS_max_hours,h,float,"Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom``. Cf. `PyPSA documentation `_." hydro_max_hours,h,"Any of {float, 'energy_capacity_totals_by_country', 'estimate_by_large_installations'}","Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom`` or heuristically determined. Cf. `PyPSA documentation `_." clip_min_inflow,MW,float,"To avoid too small values in the inflow time series, values below this threshold are set to zero." +norm_year,--,"Year in EIA hydro generation dataset; or False to disable","To specify a specific year by which hydro inflow is normed that deviates from the snapshots' year" \ No newline at end of file diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index d6cfa686..6162940a 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -5,3 +5,4 @@ interpolate_limit,hours,integer,"Maximum gap size (consecutive nans) which inter time_shift_for_large_gaps,string,string,"Periods which are used for copying time-slices in order to fill large gaps of nans. Have to be valid ``pandas`` period strings." manual_adjustments,bool,"{true, false}","Whether to adjust the load data manually according to the function in :func:`manual_adjustment`." scaling_factor,--,float,"Global correction factor for the load time series." +fixed_year,--,Year or False,"To specify a fixed year for the load time series that deviates from the snapshots' year" \ No newline at end of file diff --git a/doc/configtables/toplevel.csv b/doc/configtables/toplevel.csv index 0270c0bd..842f72fd 100644 --- a/doc/configtables/toplevel.csv +++ b/doc/configtables/toplevel.csv @@ -15,3 +15,4 @@ enable,,, -- build_natura_raster,bool,"{true, false}","Switch to enable the creation of the raster ``natura.tiff`` via the rule :mod:`build_natura_raster`." -- retrieve_natura_raster,bool,"{true, false}","Switch to enable the retrieval of ``natura.tiff`` from zenodo with :mod:`retrieve_natura_raster`." -- custom_busmap,bool,"{true, false}","Switch to enable the use of custom busmaps in rule :mod:`cluster_network`. If activated the rule looks for provided busmaps at ``data/custom_busmap_elec{weather_year}_s{simpl}_{clusters}.csv`` which should have the same format as ``resources/busmap_elec{weather_year}_s{simpl}_{clusters}.csv``, i.e. the index should contain the buses of ``networks/elec_s{simpl}.nc``." +-- drop_leap_days,bool,"{true, false}","Switch to drop February 29 from all time-dependent data in leap years" \ No newline at end of file From 95b01735c83049abad8090ddd320b148b4132fa5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 14:14:36 +0200 Subject: [PATCH 034/591] Snakefile: fix regex for weather year to allow empty --- Snakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index 8e138228..1c161bb6 100644 --- a/Snakefile +++ b/Snakefile @@ -18,7 +18,7 @@ ATLITE_NPROCESSES = config['atlite'].get('nprocesses', 4) wildcard_constraints: - weather_year="[0-9]{4}|$", + weather_year="[0-9]{4}|", simpl="[a-zA-Z0-9]*|all", clusters="[0-9]+m?|all", ll="(v|c)([0-9\.]+|opt|all)|all", From 0b27e407104b0deb0fed8609a4270ac722dcc639 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 14:15:00 +0200 Subject: [PATCH 035/591] Snakefile: load data is weather-year dependent --- Snakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index 1c161bb6..ee824eda 100644 --- a/Snakefile +++ b/Snakefile @@ -240,7 +240,7 @@ rule add_electricity: powerplants='resources/powerplants.csv', hydro_capacities='data/bundle/hydro_capacities.csv', geth_hydro_capacities='data/geth2015_hydro_capacities.csv', - load='resources/load.csv', + load='resources/load{weather_year}.csv', nuts3_shapes='resources/nuts3_shapes.geojson', **{f"profile_{tech}": "resources/profile{weather_year}_" + f"{tech}.nc" for tech in config['renewable']} From 8055e45b6807160f957b41cb212619e672e378b6 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 14:56:46 +0200 Subject: [PATCH 036/591] combine time selection with weather year --- Snakefile | 7 ++++- config.default.yaml | 3 ++- scripts/build_clustered_population_layouts.py | 6 ++--- scripts/build_heat_demand.py | 27 +++++++++---------- scripts/build_population_layouts.py | 6 ++--- scripts/build_solar_thermal_profiles.py | 27 +++++++++---------- scripts/build_temperature_profiles.py | 18 +++++++++---- 7 files changed, 53 insertions(+), 41 deletions(-) diff --git a/Snakefile b/Snakefile index e2c1a881..0ca4e7c8 100644 --- a/Snakefile +++ b/Snakefile @@ -12,7 +12,7 @@ configfile: "config.yaml" wildcard_constraints: - weather_year="[0-9]*", + weather_year="[0-9]{4}|", lv="[a-z0-9\.]+", simpl="[a-zA-Z0-9]*", clusters="[0-9]+m?", @@ -68,6 +68,7 @@ if config.get('retrieve_sector_databundle', True): rule build_population_layouts: input: + cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), nuts3_shapes=pypsaeur('resources/nuts3_shapes.geojson'), urban_percent="data/urban_percent.csv" output: @@ -82,6 +83,7 @@ rule build_population_layouts: rule build_clustered_population_layouts: input: + cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), pop_layout_total="resources/pop_layout_total{weather_year}.nc", pop_layout_urban="resources/pop_layout_urban{weather_year}.nc", pop_layout_rural="resources/pop_layout_rural{weather_year}.nc", @@ -163,6 +165,7 @@ else: rule build_heat_demands: input: + cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), pop_layout_total="resources/pop_layout_total{weather_year}.nc", pop_layout_urban="resources/pop_layout_urban{weather_year}.nc", pop_layout_rural="resources/pop_layout_rural{weather_year}.nc", @@ -178,6 +181,7 @@ rule build_heat_demands: rule build_temperature_profiles: input: + cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), pop_layout_total="resources/pop_layout_total{weather_year}.nc", pop_layout_urban="resources/pop_layout_urban{weather_year}.nc", pop_layout_rural="resources/pop_layout_rural{weather_year}.nc", @@ -216,6 +220,7 @@ rule build_cop_profiles: rule build_solar_thermal_profiles: input: + cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), pop_layout_total="resources/pop_layout_total{weather_year}.nc", pop_layout_urban="resources/pop_layout_urban{weather_year}.nc", pop_layout_rural="resources/pop_layout_rural{weather_year}.nc", diff --git a/config.default.yaml b/config.default.yaml index 3ed14371..7f137515 100644 --- a/config.default.yaml +++ b/config.default.yaml @@ -66,7 +66,8 @@ snapshots: closed: left # end is not inclusive atlite: - cutout: ../pypsa-eur/cutouts/europe-2013-era5.nc + cutout: europe-era5-{weather_year} + drop_leap_day: false # this information is NOT used but needed as an argument for # pypsa-eur/scripts/add_electricity.py/load_costs in make_summary.py diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index 7a8de88b..ca50db51 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -15,10 +15,10 @@ if __name__ == '__main__': clusters=48, ) + cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - cutout_config = snakemake.config['atlite']['cutout'] - if year: cutout_name = cutout_config.format(weather_year=year) - cutout = atlite.Cutout(cutout_config) + if year: cutout_name = cutout_name.format(weather_year=year) + cutout = atlite.Cutout(cutout_name) clustered_regions = gpd.read_file( snakemake.input.regions_onshore).set_index('name').buffer(0).squeeze() diff --git a/scripts/build_heat_demand.py b/scripts/build_heat_demand.py index 1640379c..23eeae27 100644 --- a/scripts/build_heat_demand.py +++ b/scripts/build_heat_demand.py @@ -16,22 +16,21 @@ if __name__ == '__main__': clusters=48, ) - if 'snakemake' not in globals(): - from vresutils import Dict - import yaml - snakemake = Dict() - with open('config.yaml') as f: - snakemake.config = yaml.safe_load(f) - snakemake.input = Dict() - snakemake.output = Dict() - + cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] - time = pd.date_range(freq='m', **snapshots) + drop_leap_day = snakemake.config["atlite"].get("drop_leap_day", False) - cutout_config = snakemake.config['atlite']['cutout'] - if year: cutout_name = cutout_config.format(weather_year=year) - cutout = atlite.Cutout(cutout_config).sel(time=time) + if year: + snapshots = dict(start=year, end=str(int(year)+1), closed="left") + cutout_name = cutout_name.format(weather_year=year) + else: + snapshots = snakemake.config['snapshots'] + + time = pd.date_range(freq='m', **snapshots) + if drop_leap_day: + time = time[~((time.month == 2) & (time.day == 29))] + + cutout = atlite.Cutout(cutout_name).sel(time=time) clustered_regions = gpd.read_file( snakemake.input.regions_onshore).set_index('name').buffer(0).squeeze() diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index e6dc767d..01727777 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -17,10 +17,10 @@ if __name__ == '__main__': weather_year='', ) + cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - cutout_config = snakemake.config['atlite']['cutout'] - if year: cutout_name = cutout_config.format(weather_year=year) - cutout = atlite.Cutout(cutout_config) + if year: cutout_name = cutout_name.format(weather_year=year) + cutout = atlite.Cutout(cutout_name) grid_cells = cutout.grid_cells() diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index 6ae522eb..e87c9a1e 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -16,24 +16,23 @@ if __name__ == '__main__': clusters=48, ) - if 'snakemake' not in globals(): - from vresutils import Dict - import yaml - snakemake = Dict() - with open('config.yaml') as f: - snakemake.config = yaml.safe_load(f) - snakemake.input = Dict() - snakemake.output = Dict() - config = snakemake.config['solar_thermal'] + cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] - time = pd.date_range(freq='m', **snapshots) + drop_leap_day = snakemake.config["atlite"].get("drop_leap_day", False) - cutout_config = snakemake.config['atlite']['cutout'] - if year: cutout_name = cutout_config.format(weather_year=year) - cutout = atlite.Cutout(cutout_config).sel(time=time) + if year: + snapshots = dict(start=year, end=str(int(year)+1), closed="left") + cutout_name = cutout_name.format(weather_year=year) + else: + snapshots = snakemake.config['snapshots'] + + time = pd.date_range(freq='m', **snapshots) + if drop_leap_day: + time = time[~((time.month == 2) & (time.day == 29))] + + cutout = atlite.Cutout(cutout_name).sel(time=time) clustered_regions = gpd.read_file( snakemake.input.regions_onshore).set_index('name').buffer(0).squeeze() diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index 75fc9ca1..02cae24c 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -16,13 +16,21 @@ if __name__ == '__main__': clusters=48, ) + cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] - time = pd.date_range(freq='m', **snapshots) + drop_leap_day = snakemake.config["atlite"].get("drop_leap_day", False) - cutout_config = snakemake.config['atlite']['cutout'] - if year: cutout_name = cutout_config.format(weather_year=year) - cutout = atlite.Cutout(cutout_config).sel(time=time) + if year: + snapshots = dict(start=year, end=str(int(year)+1), closed="left") + cutout_name = cutout_name.format(weather_year=year) + else: + snapshots = snakemake.config['snapshots'] + + time = pd.date_range(freq='m', **snapshots) + if drop_leap_day: + time = time[~((time.month == 2) & (time.day == 29))] + + cutout = atlite.Cutout(cutout_name).sel(time=time) clustered_regions = gpd.read_file( snakemake.input.regions_onshore).set_index('name').buffer(0).squeeze() From ec4a45b46bcbc5943266f9fd0e7b2f7f60ebc081 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 15:03:17 +0200 Subject: [PATCH 037/591] add weather_year wildcard to mock_snakemake objects --- scripts/add_electricity.py | 2 +- scripts/add_extra_components.py | 2 +- scripts/build_hydro_profile.py | 2 +- scripts/build_load_data.py | 4 ++-- scripts/build_renewable_profiles.py | 2 +- scripts/cluster_network.py | 2 +- scripts/make_summary.py | 4 ++-- scripts/plot_network.py | 4 ++-- scripts/plot_p_nom_max.py | 4 ++-- scripts/plot_summary.py | 4 ++-- scripts/prepare_links_p_nom.py | 2 +- scripts/prepare_network.py | 2 +- scripts/simplify_network.py | 2 +- scripts/solve_network.py | 2 +- scripts/solve_operations_network.py | 2 +- 15 files changed, 20 insertions(+), 20 deletions(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 76aa7fa1..f092c563 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -550,7 +550,7 @@ def add_nice_carrier_names(n, config): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('add_electricity') + snakemake = mock_snakemake('add_electricity', weather_year='') configure_logging(snakemake) n = pypsa.Network(snakemake.input.base_network) diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index 9ab413d3..44f94ff7 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -189,7 +189,7 @@ def attach_hydrogen_pipelines(n, costs, elec_opts): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('add_extra_components', network='elec', + snakemake = mock_snakemake('add_extra_components', weather_year='', simpl='', clusters=5) configure_logging(snakemake) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index fdd028e9..a6676228 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -71,7 +71,7 @@ logger = logging.getLogger(__name__) if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('build_hydro_profile') + snakemake = mock_snakemake('build_hydro_profile', weather_year='') configure_logging(snakemake) config_hydro = snakemake.config['renewable']['hydro'] diff --git a/scripts/build_load_data.py b/scripts/build_load_data.py index 0cad8ddf..e1a20b14 100755 --- a/scripts/build_load_data.py +++ b/scripts/build_load_data.py @@ -192,11 +192,11 @@ if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('build_load_data') + snakemake = mock_snakemake('build_load_data', weather_year='') configure_logging(snakemake) - weather_year = snakemake.wildcard.weather_year + weather_year = snakemake.wildcards.weather_year if weather_year: snapshots = dict( start=weather_year, diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 70cadab4..87db7d0e 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -198,7 +198,7 @@ logger = logging.getLogger(__name__) if __name__ == '__main__': if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('build_renewable_profiles', technology='solar') + snakemake = mock_snakemake('build_renewable_profiles', technology='solar', weather_year='') configure_logging(snakemake) pgb.streams.wrap_stderr() diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index ea24c356..d4da9833 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -329,7 +329,7 @@ def plot_busmap_for_n_clusters(n, n_clusters, fn=None): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('cluster_network', network='elec', simpl='', clusters='5') + snakemake = mock_snakemake('cluster_network', simpl='', clusters='5', weather_year='') configure_logging(snakemake) n = pypsa.Network(snakemake.input.network) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index c070d33f..8e0debb1 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -426,8 +426,8 @@ def to_csv(dfs, dir): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('make_summary', network='elec', simpl='', - clusters='5', ll='copt', opts='Co2L-24H', country='all') + snakemake = mock_snakemake('make_summary', simpl='', + clusters='5', ll='copt', opts='Co2L-24H', country='all', weather_year='') network_dir = os.path.join('..', 'results', 'networks') else: network_dir = os.path.join('results', 'networks') diff --git a/scripts/plot_network.py b/scripts/plot_network.py index 71a6e627..25a81a22 100755 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -251,9 +251,9 @@ def plot_total_cost_bar(n, opts, ax=None): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('plot_network', network='elec', simpl='', + snakemake = mock_snakemake('plot_network', simpl='', clusters='5', ll='copt', opts='Co2L-24H', - attr='p_nom', ext="pdf") + attr='p_nom', ext="pdf", weather_year='') configure_logging(snakemake) set_plot_style() diff --git a/scripts/plot_p_nom_max.py b/scripts/plot_p_nom_max.py index e79ad274..2a8b1bbd 100644 --- a/scripts/plot_p_nom_max.py +++ b/scripts/plot_p_nom_max.py @@ -48,9 +48,9 @@ def cum_p_nom_max(net, tech, country=None): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('plot_p_nom_max', network='elec', simpl='', + snakemake = mock_snakemake('plot_p_nom_max', simpl='', techs='solar,onwind,offwind-dc', ext='png', - clusts= '5,full', country= 'all') + clusts= '5,full', country= 'all', weather_year='') configure_logging(snakemake) plot_kwds = dict(drawstyle="steps-post") diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index bc2bd30c..6c7f3926 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -165,9 +165,9 @@ def plot_energy(infn, config, fn=None): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('plot_summary', summary='energy', network='elec', + snakemake = mock_snakemake('plot_summary', summary='energy', simpl='', clusters=5, ll='copt', opts='Co2L-24H', - attr='', ext='png', country='all') + attr='', ext='png', country='all', weather_year='') configure_logging(snakemake) config = snakemake.config diff --git a/scripts/prepare_links_p_nom.py b/scripts/prepare_links_p_nom.py index b83089d6..417e04d7 100644 --- a/scripts/prepare_links_p_nom.py +++ b/scripts/prepare_links_p_nom.py @@ -60,7 +60,7 @@ def extract_coordinates(s): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake #rule must be enabled in config - snakemake = mock_snakemake('prepare_links_p_nom', simpl='', network='elec') + snakemake = mock_snakemake('prepare_links_p_nom', simpl='', weather_year='') configure_logging(snakemake) links_p_nom = pd.read_html('https://en.wikipedia.org/wiki/List_of_HVDC_projects', header=0, match="SwePol")[0] diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index ffe48fd0..6f982986 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -202,7 +202,7 @@ def set_line_nom_max(n, s_nom_max_set=np.inf, p_nom_max_set=np.inf): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('prepare_network', network='elec', simpl='', + snakemake = mock_snakemake('prepare_network', weather_year='', simpl='', clusters='40', ll='v0.3', opts='Co2L-24H') configure_logging(snakemake) diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 8c3bdad3..b5c1a1d8 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -384,7 +384,7 @@ def cluster(n, n_clusters, config): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('simplify_network', simpl='', network='elec') + snakemake = mock_snakemake('simplify_network', weather_year='', simpl='') configure_logging(snakemake) n = pypsa.Network(snakemake.input.network) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 39f2119e..ad7da9c5 100755 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -274,7 +274,7 @@ def solve_network(n, config, opts='', **kwargs): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('solve_network', network='elec', simpl='', + snakemake = mock_snakemake('solve_network', weather_year='', simpl='', clusters='5', ll='copt', opts='Co2L-BAU-CCL-24H') configure_logging(snakemake) diff --git a/scripts/solve_operations_network.py b/scripts/solve_operations_network.py index 717cba46..bac866c2 100644 --- a/scripts/solve_operations_network.py +++ b/scripts/solve_operations_network.py @@ -96,7 +96,7 @@ def set_parameters_from_optimized(n, n_optim): if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('solve_operations_network', network='elec', + snakemake = mock_snakemake('solve_operations_network', weather_year='', simpl='', clusters='5', ll='copt', opts='Co2L-BAU-24H') configure_logging(snakemake) From 9f9e65afb1433d35809bb9e431ef33ab10dbe5e3 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 15:18:07 +0200 Subject: [PATCH 038/591] add missing handling of weather_year wildcard --- Snakefile | 28 ++++++++++++------------- scripts/build_heat_demand.py | 3 +-- scripts/build_solar_thermal_profiles.py | 3 +-- scripts/build_temperature_profiles.py | 3 +-- scripts/build_transport_demand.py | 8 ++++++- 5 files changed, 24 insertions(+), 21 deletions(-) diff --git a/Snakefile b/Snakefile index 0ca4e7c8..fa78641b 100644 --- a/Snakefile +++ b/Snakefile @@ -440,8 +440,8 @@ else: rule build_population_weighted_energy_totals: input: energy_totals='resources/energy_totals.csv', - clustered_pop_layout="resources/pop_layout_elec_s{simpl}_{clusters}.csv" - output: "resources/pop_weighted_energy_totals_s{simpl}_{clusters}.csv" + clustered_pop_layout="resources/pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + output: "resources/pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv" threads: 1 resources: mem_mb=2000 script: "scripts/build_population_weighted_energy_totals.py" @@ -449,17 +449,17 @@ rule build_population_weighted_energy_totals: rule build_transport_demand: input: - clustered_pop_layout="resources/pop_layout_elec_s{simpl}_{clusters}.csv", - pop_weighted_energy_totals="resources/pop_weighted_energy_totals_s{simpl}_{clusters}.csv", + clustered_pop_layout="resources/pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", + pop_weighted_energy_totals="resources/pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv", transport_data='resources/transport_data.csv', traffic_data_KFZ="data/emobility/KFZ__count", traffic_data_Pkw="data/emobility/Pkw__count", - temp_air_total="resources/temp_air_total_elec_s{simpl}_{clusters}.nc", + temp_air_total="resources/temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", output: - transport_demand="resources/transport_demand_s{simpl}_{clusters}.csv", - transport_data="resources/transport_data_s{simpl}_{clusters}.csv", - avail_profile="resources/avail_profile_s{simpl}_{clusters}.csv", - dsm_profile="resources/dsm_profile_s{simpl}_{clusters}.csv" + transport_demand="resources/transport_demand{weather_year}_s{simpl}_{clusters}.csv", + transport_data="resources/transport_data{weather_year}_s{simpl}_{clusters}.csv", + avail_profile="resources/avail_profile{weather_year}_s{simpl}_{clusters}.csv", + dsm_profile="resources/dsm_profile{weather_year}_s{simpl}_{clusters}.csv" threads: 1 resources: mem_mb=2000 script: "scripts/build_transport_demand.py" @@ -470,11 +470,11 @@ rule prepare_sector_network: overrides="data/override_component_attrs", network=pypsaeur('networks/elec{weather_year}_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc'), energy_totals_name='resources/energy_totals.csv', - pop_weighted_energy_totals="resources/pop_weighted_energy_totals_s{simpl}_{clusters}.csv", - transport_demand="resources/transport_demand_s{simpl}_{clusters}.csv", - transport_data="resources/transport_data_s{simpl}_{clusters}.csv", - avail_profile="resources/avail_profile_s{simpl}_{clusters}.csv", - dsm_profile="resources/dsm_profile_s{simpl}_{clusters}.csv", + pop_weighted_energy_totals="resources/pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv", + transport_demand="resources/transport_demand{weather_year}_s{simpl}_{clusters}.csv", + transport_data="resources/transport_data{weather_year}_s{simpl}_{clusters}.csv", + avail_profile="resources/avail_profile{weather_year}_s{simpl}_{clusters}.csv", + dsm_profile="resources/dsm_profile{weather_year}_s{simpl}_{clusters}.csv", co2_totals_name='resources/co2_totals.csv', biomass_potentials='resources/biomass_potentials_s{simpl}_{clusters}.csv', heat_profile="data/heat_load_profile_BDEW.csv", diff --git a/scripts/build_heat_demand.py b/scripts/build_heat_demand.py index 23eeae27..fe44de16 100644 --- a/scripts/build_heat_demand.py +++ b/scripts/build_heat_demand.py @@ -18,7 +18,6 @@ if __name__ == '__main__': cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - drop_leap_day = snakemake.config["atlite"].get("drop_leap_day", False) if year: snapshots = dict(start=year, end=str(int(year)+1), closed="left") @@ -27,7 +26,7 @@ if __name__ == '__main__': snapshots = snakemake.config['snapshots'] time = pd.date_range(freq='m', **snapshots) - if drop_leap_day: + if snakemake.config["atlite"].get("drop_leap_day", False): time = time[~((time.month == 2) & (time.day == 29))] cutout = atlite.Cutout(cutout_name).sel(time=time) diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index e87c9a1e..8bdc07c5 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -20,7 +20,6 @@ if __name__ == '__main__': cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - drop_leap_day = snakemake.config["atlite"].get("drop_leap_day", False) if year: snapshots = dict(start=year, end=str(int(year)+1), closed="left") @@ -29,7 +28,7 @@ if __name__ == '__main__': snapshots = snakemake.config['snapshots'] time = pd.date_range(freq='m', **snapshots) - if drop_leap_day: + if snakemake.config["atlite"].get("drop_leap_day", False): time = time[~((time.month == 2) & (time.day == 29))] cutout = atlite.Cutout(cutout_name).sel(time=time) diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index 02cae24c..ab006409 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -18,7 +18,6 @@ if __name__ == '__main__': cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - drop_leap_day = snakemake.config["atlite"].get("drop_leap_day", False) if year: snapshots = dict(start=year, end=str(int(year)+1), closed="left") @@ -27,7 +26,7 @@ if __name__ == '__main__': snapshots = snakemake.config['snapshots'] time = pd.date_range(freq='m', **snapshots) - if drop_leap_day: + if snakemake.config["atlite"].get("drop_leap_day", False): time = time[~((time.month == 2) & (time.day == 29))] cutout = atlite.Cutout(cutout_name).sel(time=time) diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index a5aabc31..a9d6e440 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -159,6 +159,7 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_transport_demand", + weather_year='', simpl="", clusters=48, ) @@ -173,7 +174,12 @@ if __name__ == "__main__": options = snakemake.config["sector"] - snapshots = pd.date_range(freq='h', **snakemake.config["snapshots"], tz="UTC") + year = snakemake.wildcards.weather_year + snapshots = dict(start=year, end=str(int(year)+1), closed="left") if year else snakemake.config['snapshots'] + snapshots = pd.date_range(freq='h', **snapshots, tz="UTC") + if snakemake.config["atlite"].get("drop_leap_day", False): + leap_day = (snapshots.month == 2) & (snapshots.day == 29) + snapshots = snapshots[~leap_day] Nyears = 1 From a2e26004d7b2026a61cc17683323b2673ad40649 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 15 Jun 2022 15:36:37 +0200 Subject: [PATCH 039/591] add further missing handling of weather_year wildcard --- Snakefile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Snakefile b/Snakefile index fa78641b..852e924f 100644 --- a/Snakefile +++ b/Snakefile @@ -68,7 +68,7 @@ if config.get('retrieve_sector_databundle', True): rule build_population_layouts: input: - cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), + cutout=pypsaeur("cutouts/" + config['atlite']['cutout'] + ".nc"), nuts3_shapes=pypsaeur('resources/nuts3_shapes.geojson'), urban_percent="data/urban_percent.csv" output: @@ -83,7 +83,7 @@ rule build_population_layouts: rule build_clustered_population_layouts: input: - cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), + cutout=pypsaeur("cutouts/" + config['atlite']['cutout'] + ".nc"), pop_layout_total="resources/pop_layout_total{weather_year}.nc", pop_layout_urban="resources/pop_layout_urban{weather_year}.nc", pop_layout_rural="resources/pop_layout_rural{weather_year}.nc", @@ -138,8 +138,8 @@ if config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]: entry="data/gas_network/scigrid-gas/data/IGGIELGN_BorderPoints.geojson", production="data/gas_network/scigrid-gas/data/IGGIELGN_Productions.geojson", planned_lng="data/gas_network/planned_LNGs.csv", - regions_onshore=pypsaeur("resources/regions_onshore_elec_s{simpl}_{clusters}.geojson"), - regions_offshore=pypsaeur('resources/regions_offshore_elec_s{simpl}_{clusters}.geojson') + regions_onshore=pypsaeur("resources/regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_offshore=pypsaeur('resources/regions_offshore{weather_year}_elec_s{simpl}_{clusters}.geojson') output: gas_input_nodes="resources/gas_input_locations_s{simpl}_{clusters}.geojson", gas_input_nodes_simplified="resources/gas_input_locations_s{simpl}_{clusters}_simplified.csv" @@ -150,8 +150,8 @@ if config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]: rule cluster_gas_network: input: cleaned_gas_network="resources/gas_network.csv", - regions_onshore=pypsaeur("resources/regions_onshore_elec_s{simpl}_{clusters}.geojson"), - regions_offshore=pypsaeur("resources/regions_offshore_elec_s{simpl}_{clusters}.geojson") + regions_onshore=pypsaeur("resources/regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_offshore=pypsaeur("resources/regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson") output: clustered_gas_network="resources/gas_network_elec_s{simpl}_{clusters}.csv" resources: mem_mb=4000 @@ -165,7 +165,7 @@ else: rule build_heat_demands: input: - cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), + cutout=pypsaeur("cutouts/" + config['atlite']['cutout'] + ".nc"), pop_layout_total="resources/pop_layout_total{weather_year}.nc", pop_layout_urban="resources/pop_layout_urban{weather_year}.nc", pop_layout_rural="resources/pop_layout_rural{weather_year}.nc", @@ -181,7 +181,7 @@ rule build_heat_demands: rule build_temperature_profiles: input: - cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), + cutout=pypsaeur("cutouts/" + config['atlite']['cutout'] + ".nc"), pop_layout_total="resources/pop_layout_total{weather_year}.nc", pop_layout_urban="resources/pop_layout_urban{weather_year}.nc", pop_layout_rural="resources/pop_layout_rural{weather_year}.nc", @@ -220,7 +220,7 @@ rule build_cop_profiles: rule build_solar_thermal_profiles: input: - cutout=pypsaeur("cutouts/" + snakemake.config['atlite']['cutout'] + ".nc"), + cutout=pypsaeur("cutouts/" + config['atlite']['cutout'] + ".nc"), pop_layout_total="resources/pop_layout_total{weather_year}.nc", pop_layout_urban="resources/pop_layout_urban{weather_year}.nc", pop_layout_rural="resources/pop_layout_rural{weather_year}.nc", @@ -476,7 +476,7 @@ rule prepare_sector_network: avail_profile="resources/avail_profile{weather_year}_s{simpl}_{clusters}.csv", dsm_profile="resources/dsm_profile{weather_year}_s{simpl}_{clusters}.csv", co2_totals_name='resources/co2_totals.csv', - biomass_potentials='resources/biomass_potentials_s{simpl}_{clusters}.csv', + biomass_potentials='resources/biomass_potentials{weather_year}_s{simpl}_{clusters}.csv', heat_profile="data/heat_load_profile_BDEW.csv", costs=CDIR + "costs_{planning_horizons}.csv", profile_offwind_ac=pypsaeur("resources/profile{weather_year}_offwind-ac.nc"), From 6713317bbea94156d3e7166115ab709e54530f70 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 16 Jun 2022 08:46:47 +0200 Subject: [PATCH 040/591] add_electricity: fix missing variable assignment --- scripts/add_electricity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index f092c563..b86e8a9e 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -563,7 +563,7 @@ if __name__ == "__main__": closed="left" ) else: - snakemake.config['snapshots'] + snapshots = snakemake.config['snapshots'] n.set_snapshots(pd.date_range(freq='h', **snapshots)) Nyears = n.snapshot_weightings.objective.sum() / 8760. From cb0554f609f5e2318542e73eb7b9dfda2f3a84e2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 16 Jun 2022 08:51:06 +0200 Subject: [PATCH 041/591] config: add fixed_year parameter for load --- config.tutorial.yaml | 2 +- test/config.test1.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.tutorial.yaml b/config.tutorial.yaml index c9638260..7e161ef2 100755 --- a/config.tutorial.yaml +++ b/config.tutorial.yaml @@ -157,7 +157,7 @@ load: time_shift_for_large_gaps: 1w # data gaps up until this size are copied by copying from manual_adjustments: true # false scaling_factor: 1.0 - fallback_year: 2013 + fixed_year: 2013 costs: year: 2030 diff --git a/test/config.test1.yaml b/test/config.test1.yaml index 95a8f85a..86451646 100755 --- a/test/config.test1.yaml +++ b/test/config.test1.yaml @@ -155,7 +155,7 @@ load: time_shift_for_large_gaps: 1w # data gaps up until this size are copied by copying from manual_adjustments: true # false scaling_factor: 1.0 - fallback_year: 2013 + fixed_year: false costs: year: 2030 From b4c819c7573a08e46e46ec99cf68163491105738 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 16 Jun 2022 08:51:06 +0200 Subject: [PATCH 042/591] config: add fixed_year parameter for load --- config.tutorial.yaml | 2 +- test/config.test1.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.tutorial.yaml b/config.tutorial.yaml index c9638260..f0e24822 100755 --- a/config.tutorial.yaml +++ b/config.tutorial.yaml @@ -157,7 +157,7 @@ load: time_shift_for_large_gaps: 1w # data gaps up until this size are copied by copying from manual_adjustments: true # false scaling_factor: 1.0 - fallback_year: 2013 + fixed_year: false costs: year: 2030 diff --git a/test/config.test1.yaml b/test/config.test1.yaml index 95a8f85a..86451646 100755 --- a/test/config.test1.yaml +++ b/test/config.test1.yaml @@ -155,7 +155,7 @@ load: time_shift_for_large_gaps: 1w # data gaps up until this size are copied by copying from manual_adjustments: true # false scaling_factor: 1.0 - fallback_year: 2013 + fixed_year: false costs: year: 2030 From 173ab7b318e1d0e38bbab96b6bc3f103ccbf2abf Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 16 Jun 2022 09:00:33 +0200 Subject: [PATCH 043/591] add_electricity: make drop_leap_year own function --- scripts/add_electricity.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index b86e8a9e..9158ce33 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -547,6 +547,15 @@ def add_nice_carrier_names(n, config): logger.warning(f'tech_colors for carriers {missing_i} not defined in config.') n.carriers['color'] = colors + +def drop_leap_day(n): + if not n.snapshots.is_leap_year.any(): return + leap_days = (n.snapshots.day == 29) & (n.snapshots.month == 2) + n.set_snapshots(n.snapshots[~leap_days]) + n.snapshot_weightings[:] = 8760/len(n.snapshots) + logger.info("Dropped February 29 from leap year.") + + if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake @@ -600,7 +609,6 @@ if __name__ == "__main__": add_nice_carrier_names(n, snakemake.config) if snakemake.config['enable'].get('drop_leap_days', True): - leap_days = (n.snapshots.day == 29) & (n.snapshots.month == 2) - n.set_snapshots(n.snapshots[~leap_days]) + drop_leap_day(n) n.export_to_netcdf(snakemake.output[0]) From b171614feaa87b15e4d4d25b3d6f95f3e76f97c7 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 20 Jul 2022 16:37:22 +0200 Subject: [PATCH 044/591] must parse fixed_year to string --- scripts/build_load_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_load_data.py b/scripts/build_load_data.py index c1419c5d..d7cd91a4 100755 --- a/scripts/build_load_data.py +++ b/scripts/build_load_data.py @@ -220,7 +220,7 @@ if __name__ == "__main__": snapshots = pd.date_range(freq='h', **snapshots) fixed_year = snakemake.config["load"].get("fixed_year", False) - years = slice(fixed_year, fixed_year) if fixed_year else slice(snapshots[0], snapshots[-1]) + years = slice(str(fixed_year), str(fixed_year)) if fixed_year else slice(snapshots[0], snapshots[-1]) powerstatistics = snakemake.config['load']['power_statistics'] interpolate_limit = snakemake.config['load']['interpolate_limit'] From af96af1329ea046cb384cf9b69ba27fbd2dd4524 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 22 Jul 2022 15:03:54 +0200 Subject: [PATCH 045/591] hydro: approximation routine for missing eia years and correction by capacity --- Snakefile | 6 ++- config.default.yaml | 4 +- data/eia_hydro_annual_capacity.csv | 50 +++++++++++++++++++++ data/era5-annual-runoff-per-country.csv | 34 ++++++++++++++ envs/environment.yaml | 1 + scripts/build_hydro_profile.py | 59 +++++++++++++++++++++++-- 6 files changed, 147 insertions(+), 7 deletions(-) create mode 100644 data/eia_hydro_annual_capacity.csv create mode 100644 data/era5-annual-runoff-per-country.csv diff --git a/Snakefile b/Snakefile index 691566c2..e02b911b 100644 --- a/Snakefile +++ b/Snakefile @@ -154,7 +154,7 @@ if config['enable'].get('build_cutout', False): input: regions_onshore="resources/regions_onshore.geojson", regions_offshore="resources/regions_offshore.geojson" - output: "cutouts/{cutout}.nc" + output: protected("cutouts/{cutout}.nc") log: "logs/build_cutout/{cutout}.log" benchmark: "benchmarks/build_cutout_{cutout}" threads: ATLITE_NPROCESSES @@ -163,7 +163,7 @@ if config['enable'].get('build_cutout', False): rule build_cutout_year: input: rules.build_cutout.input - output: "cutouts/{cutout}-{weather_year}.nc" + output: protected("cutouts/{cutout}-{weather_year}.nc") log: "logs/build_cutout/{cutout}-{weather_year}.log" benchmark: "benchmarks/build_cutout_{cutout}-{weather_year}" threads: ATLITE_NPROCESSES @@ -226,6 +226,8 @@ rule build_hydro_profile: input: country_shapes='resources/country_shapes.geojson', eia_hydro_generation='data/eia_hydro_annual_generation.csv', + eia_hydro_capacity='data/eia_hydro_annual_capacity.csv', + era5_runoff='data/era5-annual-runoff-per-country.csv', cutout=f"cutouts/{config['renewable']['hydro']['cutout']}.nc" if "hydro" in config["renewable"] else "config['renewable']['hydro']['cutout'] not configured", output: 'resources/profile{weather_year}_hydro.nc' log: "logs/build_hydro_profile{weather_year}.log" diff --git a/config.default.yaml b/config.default.yaml index 1e1b7dfc..aa2d64d0 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -184,7 +184,9 @@ renewable: 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 clip_min_inflow: 1.0 - norm_year: 2013 + eia_norm_year: 2013 + eia_correct_by_capacity: false + eia_approximate_missing: false conventional: nuclear: diff --git a/data/eia_hydro_annual_capacity.csv b/data/eia_hydro_annual_capacity.csv new file mode 100644 index 00000000..a95d71a4 --- /dev/null +++ b/data/eia_hydro_annual_capacity.csv @@ -0,0 +1,50 @@ +# https://www.eia.gov/international/data/world/electricity/electricity-generation?pd=2&p=00000000000000000000008&u=1&f=A&v=mapbubble&a=-&i=none&vo=value&t=R&g=000000000000002&l=73-1028i008017kg6368g80a4k000e0ag00gg0004g8g0ho00g000400008&s=315532800000&e=1577836800000&ev=false& +Report generated on: 07-21-2022 16:15:18 +"API","","1980","1981","1982","1983","1984","1985","1986","1987","1988","1989","1990","1991","1992","1993","1994","1995","1996","1997","1998","1999","2000","2001","2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012","2013","2014","2015","2016","2017","2018","2019","2020" +"","hydroelectricity installed capacity (million kW)","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","" +"INTL.33-7-EURO-MK.A"," Europe","136.143","137.425","141.734","143.763","142.894","144.738","147.631","150.428","153.428","153.345","139.346","134.524","137.463","138.338","139.688","141.47","142.121","143.595","143.957","146.4204","147.3512","147.736","152.173","152.938","150.4894","151.424","152.276","154.198","155.405","156.988","159.495","162.112","165.452","170.146","171.588","174.906","176.998","178.221","180.846","181.68","184.909" +"INTL.33-7-ALB-MK.A"," Albania","0.5","0.525","0.55","0.6","0.625","0.65","0.675","0.68","0.69","0.69","1.668","1.668","1.668","1.668","1.668","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.432","1.432","1.432","1.45","1.45","1.461","1.508","1.628","1.781","1.725","1.798","1.913","2.047","2.105","2.193","2.39" +"INTL.33-7-AUT-MK.A"," Austria","8.206","9.157","9.51","9.582","10.034","10.171","10.423","10.691","10.762","10.858","7.028","7.129","7.204","7.202","7.245","7.323","7.385","7.54","7.685","7.669","7.676","7.703","7.567","7.607","7.613","7.667","7.684","7.845","7.848","7.827","7.913","7.947","7.97","8.272","8.321","8.457","8.493","8.506","8.591","8.63","9.001" +"INTL.33-7-BEL-MK.A"," Belgium","0.073","0.08","0.086","0.086","0.086","0.087","0.089","0.09","0.093","0.095","0.094","0.094","0.094","0.095","0.095","0.096","0.096","0.096","0.097","0.103","0.103","0.111","0.111","0.11","0.115","0.105","0.107","0.11","0.111","0.11","0.118","0.119","0.12","0.119","0.121","0.112","0.115","0.107","0.108","0.108","0.12" +"INTL.33-7-BIH-MK.A"," Bosnia and Herzegovina","--","--","--","--","--","--","--","--","--","--","--","--","1.2","1.2","1.139","1.219","1.219","1.219","1.624","1.983","1.983","1.993","2.38","2.38","2.38","2.38","2.411","2.411","2.117","2.117","2.117","2.117","2.12","2.12","2.049","2.055","2.084","2.084","2.09","2.09","2.093" +"INTL.33-7-BGR-MK.A"," Bulgaria","1.895","1.895","1.895","1.975","1.975","1.975","1.975","1.975","1.975","1.973","1.973","1.401","1.401","1.401","1.401","1.401","1.401","1.803","1.803","1.803","1.881","1.706","1.948","1.984","1.984","1.984","1.984","2.012","2.12","2.137","2.184","2.035","2.095","2.165","2.19","2.206","2.206","2.21","2.359","2.366","1.725" +"INTL.33-7-HRV-MK.A"," Croatia","--","--","--","--","--","--","--","--","--","--","--","--","1.769","1.77","1.77","1.781","1.785","1.785","1.785","1.785","1.785","1.785","1.775","1.783","1.79","1.804","1.804","1.782","1.782","1.799","1.848","1.848","1.848","1.897","1.9","1.915","1.912","1.912","1.913","1.913","1.848" +"INTL.33-7-CYP-MK.A"," Cyprus","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" +"INTL.33-7-CZE-MK.A"," Czech Republic","--","--","--","--","--","--","--","--","--","--","--","--","--","0.911","0.906","0.908","0.868","0.905","0.888","1.008","0.952","1","1","1.004","1.015","1.02","1.016","1.024","1.029","1.037","1.049","1.05","1.065","1.08","1.08","1.088","1.09","1.093","1.094","1.096","1.097" +"INTL.33-7-DNK-MK.A"," Denmark","0.008","0.008","0.01","0.009","0.009","0.009","0.009","0.009","0.009","0.011","0.01","0.01","0.01","0.01","0.008","0.01","0.01","0.01","0.011","0.011","0.01","0.011","0.011","0.011","0.011","0.011","0.009","0.009","0.009","0.009","0.009","0.009","0.009","0.009","0.009","0.007","0.009","0.009","0.009","0.009","0.009" +"INTL.33-7-EST-MK.A"," Estonia","--","--","--","--","--","--","--","--","--","--","--","--","0.001","0.001","0.001","0.001","0.001","0.001","0.001","0.0012","0.0012","0.003","0.003","0.004","0.004","0.005","0.005","0.005","0.005","0.007","0.006","0.005","0.008","0.008","0.005","0.006","0.006","0.007","0.007","0.007","0.008" +"INTL.33-7-FRO-MK.A"," Faroe Islands","0.018","0.018","0.018","0.018","0.018","0.018","0.018","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.0314","0.032","0.032","0.032","0.032","0.0314","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.039","0.039","0.04","0.04","0.04","0.04","0.04","0.04","0.039" +"INTL.33-7-FIN-MK.A"," Finland","2.42","2.467","2.474","2.503","2.497","2.505","2.555","2.586","2.597","2.586","2.621","2.648","2.679","2.731","2.736","2.777","2.785","2.861","2.881","2.881","2.882","2.926","2.964","2.966","2.999","3.035","3.062","3.102","3.122","3.145","3.155","3.196","3.196","3.224","3.248","3.249","3.249","3.272","3.287","3.287","3.263" +"INTL.33-7-CSK-MK.A"," Former Czechoslovakia","2.578","2.832","2.84","2.84","2.875","2.897","2.89","2.975","2.988","3.042","3.036","3.061","3.061","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-SCG-MK.A"," Former Serbia and Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","2.25","2.25","2.25","2.25","2.25","2.25","2.25","2.296","2.296","2.296","2.296","2.296","2.206","2.206","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-YUG-MK.A"," Former Yugoslavia","6.2","6.25","5.886","5.886","6.386","6.736","7.086","7.386","7.625","7.686","7.386","7.386","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-FRA-MK.A"," France","17.431","17.63","18.247","18.4","18.661","19.034","19.786","19.991","20.174","20.338","17.717","17.655","17.767","17.837","17.902","17.898","18","18.018","18.024","17.947","17.646","17.674","17.775","17.927","17.812","17.808","17.82","17.832","17.922","18.009","18.156","18.373","18.388","18.379","18.392","18.415","18.486","18.561","18.857","18.88","19.671" +"INTL.33-7-DEU-MK.A"," Germany","--","--","--","--","--","--","--","--","--","--","--","3.31","3.317","3.385","3.471","3.624","3.563","3.569","3.642","3.802","4.086","4.101","4.193","4.088","4.209","4.134","4.117","4.083","4.104","4.283","4.252","4.469","4.451","4.433","4.424","4.433","4.442","4.449","4.456","4.456","4.658" +"INTL.33-7-DDR-MK.A"," Germany, East","1.852","1.845","1.852","1.851","1.845","1.844","1.844","1.844","1.844","1.844","1.844","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-DEUW-MK.A"," Germany, West","6.45","6.509","6.531","6.631","6.668","6.71","6.71","6.71","6.85","6.86","6.86","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-GIB-MK.A"," Gibraltar","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" +"INTL.33-7-GRC-MK.A"," Greece","1.415","1.714","1.714","1.714","1.714","1.822","1.822","1.822","1.836","1.986","2.093","2.197","2.208","2.208","2.208","2.208","2.207","2.412","2.241","2.344","2.373","2.377","2.379","2.38","2.4","2.407","2.435","2.451","2.477","2.502","2.516","2.525","2.537","2.539","2.69","2.693","2.693","2.693","2.71","2.71","2.697" +"INTL.33-7-HUN-MK.A"," Hungary","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.054","0.049","0.049","0.049","0.049","0.051","0.053","0.053","0.055","0.056","0.057","0.057","0.057","0.057","0.057","0.057","0.057","0.056" +"INTL.33-7-ISL-MK.A"," Iceland","0.545","0.615","0.755","0.755","0.755","0.755","0.756","0.756","0.756","0.756","0.756","0.779","0.879","0.879","0.884","0.884","0.884","0.923","0.956","1.016","1.064","1.109","1.155","1.155","1.163","1.163","1.163","1.758","1.879","1.875","1.883","1.884","1.877","1.984","1.984","1.987","1.987","1.995","2.099","2.099","2.086" +"INTL.33-7-IRL-MK.A"," Ireland","0.224","0.224","0.225","0.225","0.226","0.226","0.221","0.222","0.222","0.222","0.223","0.226","0.226","0.226","0.227","0.227","0.232","0.233","0.233","0.236","0.236","0.238","0.24","0.24","0.24","0.234","0.234","0.234","0.234","0.234","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237" +"INTL.33-7-ITA-MK.A"," Italy","15.826","15.766","16.877","17.125","12.166","12.16","12.419","12.435","12.495","12.547","12.582","12.692","12.718","12.788","12.864","12.964","12.999","13.06","13.058","13.417","13.389","13.456","13.557","13.703","13.789","13.89","13.528","13.573","13.732","13.827","13.976","14.193","14.325","14.454","14.506","14.628","14.991","15.109","15.182","15.583","14.908" +"INTL.33-7-XKS-MK.A"," Kosovo","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","0.043","0.043","0.045","0.046","0.046","0.046","0.046","0.046","0.078","0.08","0.096","0.096","0.092" +"INTL.33-7-LVA-MK.A"," Latvia","--","--","--","--","--","--","--","--","--","--","--","--","1.499","1.504","1.506","1.521","1.521","1.487","1.517","1.523","1.523","1.565","1.565","1.537","1.536","1.536","1.536","1.536","1.536","1.536","1.576","1.576","1.576","1.587","1.588","1.588","1.564","1.564","1.565","1.565","1.576" +"INTL.33-7-LTU-MK.A"," Lithuania","--","--","--","--","--","--","--","--","--","--","--","--","0.106","0.106","0.108","0.108","0.108","0.108","0.108","0.112","0.112","0.113","0.103","0.109","0.11","0.117","0.117","0.115","0.115","0.116","0.116","0.116","0.116","0.116","0.117","0.117","0.117","0.117","0.117","0.117","0.116" +"INTL.33-7-LUX-MK.A"," Luxembourg","0.029","0.029","0.029","0.032","0.032","0.032","0.032","0.032","0.032","0.032","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.039","0.039","0.039","0.039","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.035","0.034","0.034","0.034" +"INTL.33-7-MLT-MK.A"," Malta","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" +"INTL.33-7-MNE-MK.A"," Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","0.658","0.658","0.658","0.658","0.658","0.658","0.658","0.651","0.651","0.651","0.651","0.652","0.652","0.652","0.658" +"INTL.33-7-NLD-MK.A"," Netherlands","0","0","0","0","0","0.002","0.002","0.002","0.002","0.025","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.038" +"INTL.33-7-MKD-MK.A"," North Macedonia","--","--","--","--","--","--","--","--","--","--","--","--","0.426","0.426","0.413","0.423","0.423","0.434","0.434","0.4338","0.434","0.436","0.436","0.448","0.516","0.54","0.545","0.546","0.552","0.553","0.555","0.556","0.595","0.603","0.617","0.632","0.66","0.674","0.674","0.674","0.674" +"INTL.33-7-NOR-MK.A"," Norway","19.443","20.963","21.789","22.37","22.628","23.076","23.555","24.358","24.453","25.728","25.817","25.823","25.963","25.983","26.215","27.379","27.494","27.327","26.982","27.54","26.766","26.319","26.604","26.947","26.721","27.222","27.398","27.647","28.062","28.188","28.367","28.618","29.158","29.682","29.889","29.939","30.281","30.382","31.12","31.182","31.556" +"INTL.33-7-POL-MK.A"," Poland","0.647","0.647","0.647","0.647","0.645","0.646","0.646","0.646","0.772","0.647","0.467","0.467","0.468","0.475","0.489","0.482","0.492","0.495","0.501","0.505","0.509","0.517","0.517","0.524","0.535","0.542","0.549","0.546","0.553","0.556","0.56","0.564","0.569","0.573","0.582","0.588","0.597","0.591","0.592","0.592","0.605" +"INTL.33-7-PRT-MK.A"," Portugal","2.516","2.615","2.854","2.944","3.016","2.721","2.818","2.82","2.722","2.799","2.783","2.772","3.146","3.613","3.697","3.848","3.867","3.877","3.94","3.93","3.918","3.943","3.966","3.966","3.974","3.968","4.004","4.012","4.009","4.042","4.057","4.49","4.414","4.363","4.368","4.446","4.458","4.462","4.484","4.484","4.373" +"INTL.33-7-ROU-MK.A"," Romania","3.455","3.533","3.734","3.885","4.062","4.42","4.706","5.057","5.421","5.583","5.666","5.723","5.687","5.872","5.938","6.011","6.038","6.074","6.081","6.082","6.12","6.122","6.242","6.248","6.279","6.289","6.282","6.331","6.362","6.358","6.382","6.391","6.456","6.249","6.256","6.359","6.377","6.328","6.328","6.328","6.221" +"INTL.33-7-SRB-MK.A"," Serbia","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","2.206","2.206","2.206","2.221","2.293","2.322","2.352","2.317","2.403","2.408","2.416","2.424","2.424","2.424","2.484" +"INTL.33-7-SVK-MK.A"," Slovakia","--","--","--","--","--","--","--","--","--","--","--","--","--","0.925","1.208","1.525","1.655","1.664","1.682","1.684","1.685","1.586","1.586","1.588","1.602","1.596","1.597","1.599","1.632","1.571","1.6","1.607","1.606","1.607","1.607","1.606","1.608","1.607","1.612","1.612","1.505" +"INTL.33-7-SVN-MK.A"," Slovenia","--","--","--","--","--","--","--","--","--","--","--","--","0.755","0.755","0.756","0.757","0.734","0.734","0.861","0.846","0.846","0.839","0.983","0.974","0.974","0.979","1.009","1.018","1.027","1.07","1.074","1.073","1.074","1.119","1.116","1.115","1.113","1.167","1.163","1.163","1.344" +"INTL.33-7-ESP-MK.A"," Spain","13.473","10.869","10.945","10.917","10.935","10.959","11.153","10.556","10.984","11.597","11.32","11.429","11.484","11.484","11.545","11.689","11.793","11.596","11.537","11.802","12.672","12.744","15.55","15.525","12.82","12.808","12.907","12.961","13.04","13.069","13.275","13.283","13.293","14.076","14.081","14.086","14.053","14.052","14.053","14.053","14.292" +"INTL.33-7-SWE-MK.A"," Sweden","14.859","14.919","15.215","15.29","15.445","15.69","15.813","15.996","16.112","15.759","15.904","15.891","16.021","15.867","16.072","15.725","15.776","16.371","16.169","16.432","16.506","16.523","16.187","16.098","16.302","16.302","16.234","16.592","16.352","16.544","16.624","16.478","16.315","16.395","15.897","16.23","16.367","16.403","16.332","16.332","16.379" +"INTL.33-7-CHE-MK.A"," Switzerland","11.45","11.46","11.47","11.47","11.48","11.48","11.51","11.51","11.52","11.58","3.474","3.484","3.504","3.509","3.526","3.541","3.55","3.553","3.584","3.614","3.636","3.642","3.653","3.669","3.65","3.682","3.694","3.7","3.709","3.749","3.81","3.852","3.882","3.896","3.948","3.996","4.06","4.112","4.193","4.193","4.193" +"INTL.33-7-TUR-MK.A"," Turkey","2.131","2.356","3.082","3.239","3.875","3.875","3.878","5.003","6.219","6.598","6.764","7.114","8.379","9.682","9.865","9.863","9.935","10.102","10.307","10.537","11.175","11.673","12.241","12.579","12.645","12.906","13.063","13.395","13.829","14.553","15.831","17.137","19.609","22.289","23.643","25.868","26.681","27.273","28.291","28.503","30.984" +"INTL.33-7-GBR-MK.A"," United Kingdom","2.451","2.451","2.451","2.721","4.188","4.19","4.192","4.197","4.196","1.424","1.11","1.415","1.423","1.425","1.425","1.432","1.455","1.488","1.475","1.477","1.485","1.629","1.59","1.486","1.499","1.501","1.515","1.522","1.626","1.638","1.637","1.673","1.693","1.709","1.73","1.777","1.836","1.873","1.878","1.878","1.879" \ No newline at end of file diff --git a/data/era5-annual-runoff-per-country.csv b/data/era5-annual-runoff-per-country.csv new file mode 100644 index 00000000..44055ee7 --- /dev/null +++ b/data/era5-annual-runoff-per-country.csv @@ -0,0 +1,34 @@ +name,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021 +AL,9921.845743062182,13900.722955927391,9710.931748556879,10574.663320350839,19341.246363906943,17818.135264440367,11442.713887022777,18086.801216289034,15090.128262650946,21363.26299103702,9091.698545327283,15645.252953546536,26744.08978638467,15193.032691775385,15984.127347228396,21350.165383112253,12855.252167834218,13420.929958145927,18491.92173822311,23127.97840031047,15647.322475185589,18621.138651647332,15899.845988546795,17394.46706381624,9941.517004312835,15056.517227865626,13546.145796746823,19078.487245825123,21734.889469128113,18681.018783118114,17330.7404590047,11854.58505075189,8621.019687739607,10958.633158319248,11928.114867207425,14053.437518158384,11478.547049310142,9794.162917024925,9309.704198107493,7531.383319836307,13417.032891488734,9396.693750356952,9409.269914411027,9602.245346872442,13721.093186096236,18546.848247572612,10075.274288997707,13160.130634381218,14979.3178626011,11173.442130939595,10656.167120597063,11333.102860367679,12218.649211273396,16968.134523176956,13531.444805168734,12351.485474236735,7777.709342414358,9395.578415692386,13162.74078695902,21279.522933687273,7131.262505063414,9979.8596278608,14852.708775826433,10550.911120633964,9976.081734060937,14930.01135394502,8322.107101243482,14871.511785547276,8735.240828081134,9201.521447196284,15965.927842545672 +AT,82083.36248472283,77811.80736180999,72623.28291775129,92135.9214601233,96990.37023646115,85097.60090834703,90540.2512560922,87926.80279582532,87840.33332785149,95771.51050456028,80100.0597367668,89961.83970292915,94250.95465501286,83836.27750897587,127502.64206362939,114305.16098508416,109841.9915507258,94950.56912780282,78607.44609072198,109558.29937241938,70075.51296406337,91798.91825728992,87743.39136454638,99172.3185471974,112079.92282492586,77403.35720896415,141634.05110901658,127491.44958971704,103513.31397365611,94072.4808516721,90719.06004331182,74178.70850428617,71954.43763473642,75430.93523721115,83080.51606488624,68680.54577957527,88997.37641681913,78365.83036558417,88108.35920540475,70055.7892534604,83590.790849829,80943.05621285089,88054.73669568839,64323.72991620271,76516.31784700113,88537.52869871816,74980.7275243927,76703.23963260197,90699.65433828124,82618.46892777775,70279.06284438398,76864.90473420777,38883.771847486016,64333.37459685728,71147.24783545699,61897.64030624322,56722.92181769331,64364.47029441406,80300.64217575881,73731.45518976511,60840.309523971024,77575.9681355992,74925.98195655535,87076.27014563217,55659.14157544586,71826.27744178762,65790.17399828041,62758.61938425757,63451.07652587882,63443.71962749899,60531.78695214822 +BE,2265.3933295931465,2299.7187477495568,1601.6287456097295,903.9162052526016,1681.6717933948885,1553.0826978024484,2040.8513201770277,2596.453742857211,1572.1256345899858,1777.5813929080084,2626.96550179367,2109.9419394561014,1095.552430877252,1153.3090754765356,2926.2047527605378,3273.3444811813465,2455.1462895729287,2709.4254348359373,2044.223080485547,3206.6821776003253,1403.4368531879622,1739.01009962226,1509.0861879549796,2489.4865224203572,2440.1073430603583,1152.6261514941527,2218.937185944037,2759.156597708309,2657.6330859359005,2904.764428136616,3657.83503348807,2493.2486286738635,2917.270148862828,2660.3113890881846,1897.0141168954808,2027.0116832611525,2822.5902787959144,2964.8457470488684,1943.761175974426,1192.1713008070133,1419.0119225208746,1475.2557281855488,1769.9742186132778,2647.8931490311224,2842.9882619071104,880.5015070232031,1197.5019163599245,2093.4616667083587,2614.387699318041,2455.605567526133,2964.8707630509653,2512.265466519676,1585.2842393930487,929.2255532772314,1281.2863306004592,1121.936801130382,2183.018089275124,2209.175694512598,1603.8823576630593,1544.7801250586733,1495.8450265096008,1698.4561860883377,1826.3476500921734,1803.4120415623293,1828.4613155494794,2424.4009518987536,1091.1596112517386,1814.2183897620703,1171.4609814371709,2056.8674333110275,2031.8962335362714 +BG,7806.165358407907,7617.879584469116,9313.915986883927,12665.103843530671,18165.703005314856,20925.111917073817,12315.95137614649,14307.215196342033,11652.743586791588,16042.778215050708,15000.011504505326,15411.367697482856,23959.284980030086,13749.537818599603,14477.782616320155,19301.913180173906,18779.64649297375,14471.754083245778,21905.976678210158,20337.934359162857,20009.368056844236,22642.8256575709,23291.544303799303,14596.266505770593,16672.574320967968,18465.93977853061,15123.0740003407,16401.953223276385,17509.31598177905,19228.19892146255,14599.539868168713,16192.551398587811,14129.882713144674,15395.87601647586,11853.583066311567,12273.885630367266,13296.879487675578,12962.17913948413,10178.141531948864,10101.748861881337,17833.95419276747,11290.360773903032,7050.797194092144,7109.831367133397,12879.727662239184,15849.231621819281,14036.330428384765,14600.701492135015,14377.532715491632,7705.7385359122845,8414.14109970378,12768.14503989922,11390.56673556146,10492.153643864705,15665.526881990423,13518.231074072748,9896.670696858979,8514.724851169687,10495.74229946015,14331.982881842356,7228.669024198985,6779.132502990354,8418.829006301234,16447.848686603495,15740.35987338571,11179.883037182273,8789.581276892988,11591.504961624405,6993.71096793164,8046.946588923506,10797.966046345515 +BA,23467.52324346034,27732.028396263388,21355.39127202247,21518.57483169428,38198.02048713121,26864.382517947488,20815.045478598513,30820.77172304343,26041.454718573805,32434.848569531026,20613.68138756547,29427.6067241259,33216.04695823398,35126.00882914745,35434.02869793576,33198.240125653894,27292.13451964922,28870.288475787063,34855.527471322755,40158.11721181478,26000.45986387781,30818.815452611776,25386.059210704487,29741.547122355205,28211.934365516674,30030.474291377286,28262.88980319508,36551.088477619196,29006.131913946814,27659.528119372964,23600.138376555304,18313.888493525537,16009.416242480263,24722.92263318226,19189.890721764787,24683.705818314953,20989.732351804592,20569.866983400992,18470.90664070533,14851.755901997987,25891.954823722892,19819.186826010166,18921.820235243023,20522.576037546467,27525.961934821684,30713.034955646464,21412.918614981576,21344.870107122344,26543.94285666588,19942.69654945001,23180.52553450498,25225.421682786062,17217.841128593398,25342.758536033023,22647.27040540609,20311.586220306715,13360.715771642963,18725.9052067595,21814.111731615874,31110.03238839381,11170.209355889527,11624.972537489217,20618.808518471225,26321.87815471064,18023.46871599901,20293.60245322545,15351.515268991054,23732.8659965382,19641.494693119246,14018.69083089969,18476.061736021245 +CH,96134.70662377033,78280.50065735803,75567.82823680741,75624.52378636891,84437.3353706146,82858.22758683441,70824.92066589095,89311.09471805945,65693.73271567532,95736.9646979805,81823.38979168108,71941.93730231738,93291.72439376163,67130.87226350856,103459.16116112942,100678.84780651607,97724.23622167954,103707.47043615916,84031.35407618036,103162.60292359442,67550.72288370335,80436.85045155323,87045.62560332651,91431.67032188186,103676.61542793321,68303.04781353423,112322.8911282786,90003.61666202937,91028.65800738563,79435.56403729375,84362.27602442491,71967.17653868764,71356.17066607098,70327.74412176231,72852.24726422041,60501.17532436925,83372.98013161327,74234.0349385613,61890.14596593614,54336.52856303606,58271.018596959824,62644.46734396249,75790.31562737533,69637.43067630196,63290.99710001813,60360.96649160057,57476.7610131337,62343.013781750116,78693.52307555292,73667.98513148604,75122.7031133837,70327.33051388402,33043.59766466136,48968.55545142022,47632.62274536815,48588.59714178414,58398.342285916435,57742.38347363473,42559.51792407362,59408.23894223828,57129.80243604273,71163.63652517287,70858.4268509181,119263.66699527185,55000.17388464577,60563.73895679769,51249.64855691976,45607.547672961526,60542.786248766475,50488.945849740405,62587.04259357905 +CZ,5741.811363153907,6430.8701452824125,6608.002211449021,5547.98412657507,11139.03676570244,9975.869136026628,10340.80877548634,13532.930674695574,7705.735677184478,7812.801872929193,10964.355351867012,10646.504003233118,9719.560436989883,9722.51782291833,19015.37334991238,15549.667939948402,15927.255735311868,12882.876953226223,10353.403919517015,11853.576269226234,10677.61771918624,10413.95103805089,6895.283030051313,9424.903567027312,12922.392855988994,9137.874616036986,17532.348544152504,18533.830228515635,15250.542039808313,10190.043701741004,11537.335951365127,9452.574932230946,5833.228549596612,5329.206957903766,7580.6976645678615,7069.4638232187235,11641.01844987317,9790.145937530902,7320.767578365769,5406.873869997462,5625.637231646826,7239.835546851702,6440.471526964078,10089.617439184036,12468.55796361433,12603.058166229213,11520.381274473184,9364.18293733304,10411.740148030329,8903.525346614548,9434.353552398077,14463.707947162726,8297.335864348554,6305.0428212307515,9383.102792968806,9420.905095490103,7053.530866655102,7934.504156979587,9131.766698685136,11027.709419784474,7973.011990884055,6406.065926850977,10728.184944007047,6645.433895571247,6345.82145823084,6499.675988954033,7016.463805946017,5619.135413529,4807.786670051716,5785.96568493957,7986.497102061061 +DE,37514.09293381361,41854.44001450301,38958.042582957896,35908.26729908446,54302.825387264325,53900.0627595872,49537.22949846474,58655.764340031456,37627.8257805545,42967.11131060519,58392.899587658314,47246.42956098116,36543.949785170116,36184.44504543948,76454.75505815547,77563.28089874369,65706.46393994696,62713.75591115003,50646.052126013274,74501.93068438585,33965.80961685558,36936.195615288314,42537.597915180464,56616.68921207296,56744.68927682596,34807.98202654087,56642.02192030585,72249.78534694383,61866.53633607989,55155.47864420242,60392.13262306467,54016.67652252674,53772.61604029787,44957.681101902934,45340.54136937088,48213.458592237475,66703.44582319073,60862.17019199549,41014.24992391146,32890.656129618095,33561.7114818598,35496.398391557115,43529.12222860253,55750.09930602895,59293.24549493131,37708.06634825865,37073.71374151417,42227.76427477898,55642.269571505705,50261.32889407123,50099.1653624443,63663.80803911536,33932.84222448403,24148.0930626651,39327.588161226195,34424.75266875371,37774.7468462978,39904.36386097259,38761.37664135111,43371.39725264248,35879.97041420226,37163.99533546333,50391.241894760955,37073.97568394232,36139.75677566728,42435.96482981362,34097.15586833773,36767.50341472353,28228.762854078665,31841.550922412007,39703.58319343355 +DK,540.6494487174206,225.87222027671936,240.57818634617777,370.37587945377,297.48979685029366,176.69208006156848,208.79213770008658,418.4554011794129,292.8102234525168,354.1220188699609,405.97396851309696,497.6042583966885,394.062076725445,291.3295691524654,304.5438623304028,591.4756757289098,629.1912050409122,479.19182164984767,353.75286712188796,454.0799499391422,338.48620130918835,357.676218196066,271.5200039604648,288.04880490856954,389.1757124784286,200.03398963977796,391.555913715114,397.29527898061724,379.8043799580585,514.7861201159348,505.7304478209306,381.57816134966373,489.3522161731293,301.717309458533,340.1024114463131,377.00536197863613,349.05617800662674,489.4227950883326,223.23589869898433,269.17110101837187,288.12441629799764,229.5796362727797,293.635637901186,464.89056739838395,386.583686695923,100.62743648672041,155.50324274468716,357.89273417380645,451.04208007822723,403.3432275318107,376.8995908622044,395.3896113505339,169.30459202493293,211.16687292699712,238.87912856891634,225.9981737610454,469.5229598902774,334.5021223766927,213.88993390188736,267.6283833775911,319.04746406617295,376.09256801086406,317.617725512616,353.26516627601364,404.2285931109035,408.5235836651241,351.86517079981496,305.15203377590285,361.8170659996248,441.45504335438466,312.14518786073575 +ES,49381.7181466273,42506.42487287232,29823.22966835847,33520.89863652133,42189.87541544434,45018.59980204108,27387.4917761516,45602.58407624375,62626.425244916936,94141.56249288519,66884.65469167147,67115.06386526441,82553.38984370838,62483.82642486853,54633.78478265801,97009.71651609142,47073.863176177474,55800.125131342014,85746.55555964066,72028.42027117872,75395.28981871007,97165.39237066667,52196.13272216457,55183.75674414718,44434.367388636274,45688.29479796517,107175.1885102772,376352.4882722023,122222.92956502433,46652.32256081546,42283.296882354574,45745.627884904505,49745.69531403085,62249.891346371536,58920.93920695715,48705.91089393512,49506.55303300167,60104.870297070986,41417.79510072781,40561.22111509541,48584.70074175896,41980.59062088254,40901.640882458836,43899.80095828514,42846.07384845135,68844.74333042726,58684.98840324564,44556.941393617584,38670.78308215774,46815.51322723987,68212.19494117319,35011.91030341564,50475.76713743041,37227.78564631605,21874.579431867896,35771.95151620915,29462.81813629621,28957.890173503936,32351.242924601538,48787.03990347552,31409.59113067243,24367.630996980257,54440.48961905899,50212.19464108009,33563.81874118821,47043.00929278407,21662.04001863739,49011.344970588914,40719.843457258816,40971.905822060144,45241.676643808205 +EE,1013.5168183220601,680.8524541483096,896.074617741102,657.0814978199126,1138.8891299468455,1033.2360728791764,1360.240006093535,1004.6950457068739,934.8774758153143,610.9977141696028,1048.0576885162222,1477.5046721309996,819.8347754595931,595.9919701101757,664.1717649435486,1178.672290642306,1112.7122616720162,1003.3658496852601,739.8499843054013,970.7396668771637,1156.5986195943308,988.0643633892423,963.0153554345143,973.0118510683724,980.7669857762866,637.7376743732589,1121.0664931638019,1485.3090062847518,1014.4287893275732,701.3843644468006,1196.8127434491068,1136.1215677919786,956.0911286121622,761.6620263988196,1109.6559596693944,945.8137139982223,1246.4435124663337,1081.0063689141978,1180.9951778617858,1433.4526339800395,1044.4962572791317,875.9289554452553,699.3911738148247,770.5276589427534,923.6083617038047,353.16555295606884,572.4961222214871,770.5595680360855,811.3520528619258,480.6204379373417,526.2783934002991,624.0252970776874,317.7449195254128,502.6073570248072,523.2149143909173,201.10844695565802,516.5064948459781,787.1638506300568,929.6905631193786,943.6792182991617,682.831069893961,933.1072250631543,692.097322772721,449.72254117947216,392.4173074585239,635.9676582877272,753.2897252561945,692.2577760060705,496.359994444626,685.8431112730673,512.1207984775516 +FI,37605.30609105331,44212.92045299994,43354.55443946037,40909.90249435943,45502.4817028443,31224.476747778986,41198.39417754888,37433.6293362709,28205.152814527217,22733.614552593714,36790.55908786393,45364.155643266684,28818.806516416316,35920.468538637644,43898.27049057533,41064.81684006838,48740.383821508905,37939.33952866352,30918.72594548001,32676.177851908644,33754.05667642144,33605.2810320407,40213.26757169686,46999.65997165162,40988.91471061698,26205.15827640759,41167.74001571865,25866.031354509407,34538.39918373158,28474.82496101674,52752.27216474974,31970.598763267328,35752.18054352296,34628.515223969094,27958.317625583102,31764.196982878522,30015.16030263079,26346.04561795855,37548.80632649389,27745.021972655202,27337.35846234453,42346.93155636462,32896.698992597754,22520.879762748657,23208.41547315833,19884.31515309925,22475.195958848508,33947.011695157635,26939.65172877202,32198.274008146243,28319.0878193112,25068.601753935876,16735.56947336933,29510.104024439464,31518.153863523567,22455.334677451585,28461.18834411878,38706.997170480194,29619.48059832548,29700.763598820195,30127.95453034573,45678.82538666528,31580.034602099753,29256.819253905658,43076.06538538077,49489.04536337738,37281.852766328535,33818.560580958125,35465.53242057822,41410.545080415,41567.72109759498 +FR,135094.49763612094,106772.95460342853,80280.31347296045,74490.3783289433,106687.24245156738,78827.6552216503,82482.11027901788,110101.24506868717,102231.57173723538,134019.59611286796,107848.78158188045,101612.59295931137,120079.53146371644,89568.66448178052,139585.30725052828,153772.55334552698,108799.90779570332,132530.25240249874,145056.24077647954,157344.40874499045,121182.68180087653,135378.15307040678,100408.75538533325,132164.7891142495,122382.6612084835,103706.50937621434,174240.52624537304,149853.10658224527,139992.58441391244,124892.14391178945,138893.07653615897,136102.17909683278,136298.85434619425,112484.75227834118,103842.75366698352,105453.40277549413,121935.76619549586,138379.45234918175,71924.60006455882,68830.14474115185,82603.77634528138,113556.04015089742,104293.46882473862,133822.28230897718,106263.7222156586,102481.34621013676,87080.48957235571,78895.08319488679,105735.9820525235,105626.7734987112,124313.3006359069,92144.11932119,73537.29646152578,78137.60525599915,58286.814348802,68928.05802270533,75743.7796112372,83489.37862547796,61518.93775410048,71311.23184506799,58810.65089438103,62581.66694545332,108566.1756738168,106810.3035898108,64981.51870529863,80829.27869961815,55203.39988738071,99034.47679069567,69318.43286028007,80169.78942387344,91015.86505778233 +GB,30949.55733300973,26701.9428167181,24834.423901258084,36292.29933386541,21223.79048684261,23695.358277919488,25987.57619398849,29907.138025215598,20532.262685247148,29689.355990879158,29755.7349738537,26456.609914217806,26827.642866860373,23873.145060634775,28779.074240844395,32368.78110647752,35977.394307138864,31071.326823875082,26446.212227329706,32888.07880400224,26015.735528737063,30161.596277105604,23017.874991984525,33287.290870143,28286.810808036254,25581.658649545065,33234.01349421005,31886.616851943854,36147.13303532815,34133.94123938026,36553.158784009356,34512.41082508442,31536.090754720717,28572.314934249887,33275.60304522956,33665.001595891976,29575.879486696827,34513.91395990196,28917.71257427291,33609.176553253485,26240.381135352633,32589.192149993025,28862.78621634025,32807.4074928576,28488.125666145854,20034.93309228305,23116.389736102017,36396.90134863421,35532.192401610075,39288.48780281492,29384.81519197965,36157.931892943554,21622.405196644995,32040.743170655453,30471.91526631006,28610.855281883465,33870.42864117695,37281.10394972126,33227.13302814586,22275.90424618414,30588.672790028984,34121.358436958675,27706.739428180073,37230.134388487466,33699.78058075289,31403.25713954576,26791.643973463473,25928.83232662774,30294.933954035565,36884.703709615125,29006.326905891798 +GR,10056.853784361187,12820.948661755581,12880.09713386794,18009.367077161973,21378.182658177288,29473.438101212807,11770.791493072751,17561.986308683798,14068.336209442465,21036.22984593777,10600.651816726047,19253.94027167335,33903.71393281602,18899.558983910043,17444.093386496537,23383.013428670623,15695.74724949063,19981.88173635776,22837.72155515553,20477.278624856677,21882.21250746782,25630.65513791745,23207.036995448034,22044.998521881807,12010.599831751206,19432.667576547075,10483.216379681078,17709.119022396855,23856.615736538963,24868.152661457774,21212.948012018598,19349.21918097175,12988.230031417628,16765.76278511076,15711.921661553248,14768.388537620414,15953.652684601051,12434.694106124754,8265.22849298033,8609.897588471382,14667.4570613014,8511.641075667938,10022.119539267658,13526.966234241496,13788.166042309897,20514.65575034389,13890.655920759986,13637.35506363307,17713.539092926785,10603.937587040999,9085.188935046803,13431.534902143163,18237.093734480102,15007.784707319466,15322.74478671021,15189.508916238075,9627.363919501071,7964.610286111404,17730.814440852053,21625.83796282357,10692.331430067703,11630.957871879938,16037.311332863352,13770.795305947142,17211.823293162783,14042.921372422215,9179.230226001768,15781.789228215457,11036.807907632012,8148.5700551254695,17837.056638784255 +HR,11579.119396857217,11616.785819262946,7841.411279590863,7071.274416413621,12992.083400898755,8164.444623202054,7347.788717816701,10332.483465428491,10537.238741811467,14479.677080073134,8479.661662510043,11787.072656273116,12862.758623825672,13371.003032039336,15990.668161905827,14470.61427957732,10644.752476691014,11929.91211438134,13611.162472968235,14159.968181810045,8748.9998436583,15752.17883640428,8576.387915317433,13121.48137750286,9754.915357083264,10574.934113880938,12339.192872828058,13526.82683401755,12407.125261525374,13314.467203516846,10589.407510915647,8240.264291214513,7438.667886688274,10422.72691638502,8167.94266416981,9179.047407118169,8517.079324039581,8574.526688740114,7000.526114186264,6044.501432950472,8424.638032244015,7640.079353180473,8493.38568955205,7673.466816227631,10113.96973112034,10475.583854629525,8161.447547783003,7730.598307694147,9688.392563588315,7721.732973546704,8547.91442119075,9110.630144082634,5654.409914846469,10449.908940883637,8544.776426500835,7703.363550389989,5356.181480736791,7888.76450496884,7981.496673656482,12159.302077747214,4232.3935344941665,4890.509308451722,11184.320641158047,12936.9950624162,6984.475921997467,9245.055929521772,6446.204647314787,9728.03403894923,7468.897556955247,6117.536838412799,7342.634549696792 +HU,455.56009955160323,446.6314758325084,756.8984035642842,450.9800559529234,596.2398492658431,618.0772176598714,433.5306920564666,626.6699838105968,736.6623236995524,901.6628598550868,955.0588428000881,1010.9577650474141,1739.1969813800204,989.7527773708749,1794.409065735425,2141.779921355298,1587.224990709883,671.8419282109866,1725.8355118081338,2716.2211930211206,1024.7764676942138,1478.4297579371664,1174.856199808959,1380.70450266654,1412.5023358393119,740.4722294240396,2077.892875467242,1382.2122922975911,1644.3319455706533,1323.8387691522125,1268.4319727220777,1050.1561979992803,938.7640185853782,701.18673897032,1176.2218406698482,1296.5341770126697,1360.4975641937087,1113.61620590335,686.0888933448485,340.9577501900905,585.7771480398817,710.4671894364953,683.5190908209308,901.0768559915952,882.6855336512624,1696.8667744778322,1072.391017559335,1091.9628754375356,1986.255314199332,1224.1891103332646,723.3105004079888,525.4091579835733,484.84230756145246,965.526984284363,1182.1048527111184,1188.8833398485922,413.588170351592,480.2721461089437,695.3047160171476,1875.1966820116616,1424.9690036241302,335.4105482008909,1504.9089491398734,1485.372787096725,1238.0161031995012,1379.3214547239281,769.0933902263423,1164.4795232335282,401.1056623458921,586.967649321741,686.5594518266915 +IE,4646.742323576806,3498.3840852321937,2544.6578209214726,5419.077105100732,3195.826410242899,2135.0862825425293,3896.6031468108818,5166.0575828547335,3059.5430902455864,4420.523688067632,3920.565970045664,2677.658691610785,3238.0778129090736,2814.899041865502,4169.640537659651,4975.659864222032,4131.237385306254,4051.6063579500055,3501.9810380506974,4162.222738923252,3277.97066925379,4149.907266073347,3535.126191101705,5127.397347805918,3672.8392481603883,3233.4968306810615,4670.955668853978,4602.662496185422,5486.794576286672,5974.860239294209,4958.279351735843,5539.220771177308,4814.939874910363,4704.080605250908,5214.372862088697,5579.052373684467,4424.669817520398,5645.170219782959,4099.107666436778,4291.534915722901,4394.7348113611615,4474.842169491055,4574.431496810677,5809.6920444413845,4586.044007664658,4500.049573188483,4158.002042556449,5864.151573833777,5389.317421868625,5602.682945402753,3910.7950042057882,5664.313605042361,3809.963053559503,4119.424688220842,4183.3641097691625,4756.243128847813,4885.19842669336,5839.576896771334,6529.030637616166,3851.468550158534,4739.247453475783,5116.873230654843,4346.868803644192,5780.6460718128965,5283.18966576195,5253.677788447396,4182.318532051922,4579.528423701424,5332.55258145869,6160.501534866154,5064.7000821427855 +IT,172598.9057049173,100312.33974168803,109683.21050744873,113141.95504995789,104153.60992530867,105687.75931391625,108887.88674499927,120408.08444781008,120463.4718424679,176044.98820314519,110983.47718210719,108661.3888675,154479.99952596257,116866.21274767391,140970.07450678368,148795.1431459142,123467.91624840492,141856.2012294592,135145.74559391223,121025.70232844367,123064.2692081519,158675.8479818625,126408.22188494769,122698.61897984576,134048.90222163082,141351.40587318933,183551.69201916258,152672.0987165877,152463.24070715246,129214.69623803807,126406.52003570941,111266.52387106014,105493.22493839792,124930.0152276459,118811.00097800085,107475.13484215035,108705.61617459086,105553.12911266208,89696.47047566871,79022.57929325203,102862.21537887226,110384.19134436303,114736.91039530469,100806.28542965792,84803.88252804938,120635.19844583895,89284.70639754581,91327.36842742827,112272.49254052607,121214.98394688763,100240.69732658492,110327.24980482439,67667.3134977533,93496.05161894935,74054.55044130566,77775.69469931335,75858.44303177306,92083.61659880447,94760.12813659209,130298.81027721112,113068.08204604911,102862.27823880903,124544.42911673438,173919.9577739064,87247.90399947706,91232.2769509342,68511.40136893332,110593.38607511377,103785.63569256017,87869.12433673623,92697.61009264145 +LT,3126.90226977831,1475.6787373817235,2475.307120672793,1105.461669987713,2895.355169108127,2328.291848466701,2773.100951693534,3565.1300060634676,1726.340017569786,2441.2869150017605,2739.255286641479,3393.627534013301,1948.972938917477,1503.9304931932238,2081.2181025571476,2387.4356286402945,2953.7202011167815,2442.643404228762,1575.9037853337413,3106.077653607497,2438.6998492607095,2321.3335398002305,2455.4955733417105,2703.979150849733,2983.428649152806,1271.81865757996,2291.2165997279003,3624.3054978962264,3066.52482874976,2692.4730181815085,3077.131323187848,2583.193918114293,2346.227785803459,1679.5438811966314,3224.9829735377853,3118.546035682447,2841.2519919875017,2793.689370450914,2688.2457239306805,3241.443663108373,2559.3234295762136,1702.002348908642,2110.46892607847,2728.2093372090403,2507.383271401867,987.8894968242066,1210.6320667482842,2619.0625969612056,2041.7494156189375,1077.1024719580128,1501.0630179433206,2093.0805484121715,761.1714789679556,1438.6161577229564,2052.75406588365,780.7629955514127,1806.053023318598,1637.6952437203324,1294.75789506843,2045.7605537026564,2014.9263059368886,1513.2399919084748,1700.3251444304037,1310.6134461272318,707.068706016363,991.8607300754669,2210.5243412620116,1945.761381971759,656.9514438734058,938.7049363615082,1091.9224609932446 +LU,418.42920407960173,402.65326898169104,245.66041042705334,140.5213247873591,281.65083355306945,239.8578158452654,369.22101543741394,483.78479198242695,296.9130979040409,276.1232951910135,459.8791399297912,360.88050800564,165.48000564979304,183.08661927563494,549.4327262552889,615.540914852196,430.5724249074097,464.9649192455573,366.43220700786026,562.8555247965114,228.93628708423907,211.2546971696525,190.68337965968735,337.11947715404034,376.86900759463407,153.06162250371963,361.9412034686643,457.17182659872975,474.4467062976349,501.35146460886807,586.4359860050876,446.87720467222556,554.4763793156474,495.34599197145104,293.22338952418016,311.9404169698979,470.26963100793296,539.1966800252237,318.1508533879876,216.80440341571304,213.96493869659722,161.79868975175182,244.05142665329072,449.452274496719,514.0163752203341,140.3179752581265,173.96942733863747,312.73695003201067,389.83220575942556,401.09422881834865,533.6829497064967,363.9324325652479,243.9448809708681,141.83825708815394,174.8785415794147,180.93947242990794,337.92060394534246,342.3576188750888,243.21751195509597,234.05807708972188,220.32797632404777,264.38928306703747,336.6463620917912,349.32621250528973,289.85643977541105,421.5786735040934,195.16848080033785,348.6723038250213,181.01976524286118,391.4073725411393,335.53788814460387 +LV,2742.6556866506367,1837.8325027812643,2554.170761349389,1408.345733539928,2983.189997195677,2825.061612760662,3252.3974243255384,2886.2924715658505,1956.4363533791625,2047.5738516633846,2396.823663944175,4066.8157610189646,1865.1937720377932,1213.3814003625498,1799.0008428733133,2700.1570058485836,2685.678969351212,2489.884608424664,1643.1417843905015,2409.13500668555,2592.9272177648704,2235.207139152776,2147.227486416904,2582.289866216919,2592.1022950383003,1400.2389662856958,2360.0229699498527,4017.8529783072768,2384.614549536931,2229.7220033855633,3208.439621353169,2678.7332051326716,2668.5315414635693,1705.3124319563372,2816.1467857724074,2779.7212753206704,2548.8356765576805,2583.5815153824487,2861.3233286998366,3801.9993997175525,2885.329135114707,2265.350140707051,1837.2956559244064,2087.5337557102102,2249.8356476827344,853.5386928200795,1689.684828383291,2653.3751344813045,2109.0096432617606,1182.3316650686795,1487.9132295244858,1974.1178903388873,1027.3242775723352,1736.361793878124,1741.9204323497202,701.3946960765046,1526.0106468283361,1844.9956663852768,1722.690767934754,2194.735679264339,1757.0892689497684,1974.9007736328324,1883.6056453393867,1405.6090440523008,1355.4439688992024,1295.7921755717964,2182.9434502570357,1620.95881111662,955.2966396067089,1490.1655775988,1270.5915407733335 +MK,3934.258904454459,3692.0813330320566,3668.815892166788,5481.091007849558,8488.277349663611,8514.814821434962,4861.071723840239,6878.625964986481,6399.572820343104,7510.160197503697,3410.068805763449,5394.1653784487335,11852.098687247973,6238.562291909563,5957.282159254423,7239.168545674971,6704.994620967638,5343.254672711665,7690.122171456297,7543.1707758996035,6080.923842798452,9518.22452251825,7931.36999814296,7898.373553315725,5296.06496225987,7158.993856907015,5568.700579027411,6653.618095140364,7658.60790313609,7384.3372015299765,6359.355811805509,6311.4116310067075,4303.248848133382,4384.047563174607,4091.082807237865,4939.915122052565,4226.085259691547,2768.0039025432975,3428.9467644601264,2294.222990992098,4834.495252793617,3325.6396521134557,2522.690466358069,2976.927612194815,4721.490759581051,6218.919122814915,3840.4729075548557,4211.680380445357,5623.802967061423,3683.311545054556,3010.5387111938044,4030.600677147787,3746.016920616422,4369.907262961726,4375.170573617275,4171.022704527618,2702.082556773276,2500.5709190188645,4370.4076446296785,5204.859735574909,2501.3689966568136,2522.4142074268602,3898.568577966785,4120.496629723428,4145.529030725163,3980.5145191045517,2967.8383253548755,4325.530795978238,2351.320803369623,2869.298937488066,4644.825806471018 +ME,11787.036249138713,18552.496612764233,11097.228684668844,11567.930061084586,19293.29710814638,13959.20571478613,13046.18440612437,18177.491235848003,15681.709335959564,19349.950981118494,11658.5954682407,15979.557715971854,21966.784229466284,16319.44299708603,17409.40677448169,19267.118980997075,14169.834731486397,15882.152400499632,19649.60512617265,23317.326436161944,15993.83236649745,16724.197023812518,13680.494674103275,16947.38155713745,13396.216553276576,17144.464963358845,16187.204710073258,20417.876685607593,22530.120155126962,16197.908505488407,14818.545420474018,12719.274460270883,9622.464989039141,13369.875886578782,13078.849292203078,14951.85122042927,13681.691957367619,12435.207850184568,11885.89235643587,9516.042262408026,16926.063160570764,13462.909968102742,10042.999218445517,11916.714437943356,15158.632522247093,19735.53511234594,11491.695345503264,14075.890065382568,13952.132515246369,11677.32833931845,13022.018989752623,13358.031703205903,11534.177624564669,17635.48411958614,14124.491791464301,12392.738752899031,9187.905148236658,11106.432128782126,13780.482580236776,19889.70854314474,7004.765863876614,8204.168680103983,13925.208337027952,12712.182323875111,8528.030231315688,13924.890575378206,9037.809310147335,13972.095665379566,11360.358971424077,10280.43536084397,13775.545442858487 +NL,132.53876435280281,105.25304624029256,97.45390390948565,59.629996943856206,126.17294913858377,100.92785922135535,110.87608266899032,166.47617616014315,115.03831975395074,102.21679880589629,222.71184206736731,164.32395798051633,88.95057195947412,70.61286255591416,116.64203846425596,229.2598570422647,176.71083656110923,163.34614915846544,135.23541074052787,153.03725726999411,84.2996330000842,75.50229060079856,87.79575328623356,149.0911400069578,185.89892961221338,65.86854604814957,122.15247506918442,163.86971747802477,177.38160465294413,173.97671792234624,210.94537197363266,138.15528852664815,157.7989701791954,164.8431327190436,156.27033317337316,144.7881412408737,172.55396177597567,195.57239229094031,113.32208112175368,57.91841778157319,69.80575559844598,81.95247611107445,154.25504072397393,213.16593963287744,185.6861094126344,50.88580789479815,88.6770750590963,180.59511129061775,175.09641999581325,134.73866646771805,175.89672487625361,170.10222446753016,112.93557838603432,69.46018341018433,89.82211025011819,57.645723008783136,122.86182387892966,128.20825436811367,82.72980960226074,90.07937846739043,113.22245968360778,109.86527486394354,113.13774281842522,111.87536788688416,113.53271254663122,140.01537175074324,68.64291161119651,101.90820271032081,52.313311323047174,116.8375292031251,120.98114114085548 +NO,268338.23623559956,311516.6976002237,354741.82081862347,287750.3093395867,277336.7794878445,277384.3177020413,343804.7636848019,309909.39898200217,279870.8316011512,240316.6988310159,337135.04130569333,320967.163231472,302346.276731951,373063.16157364036,335043.0981929385,271478.1367425455,378240.8226290755,318135.4534804216,235625.6466770364,244547.82624561962,342177.033729037,330660.24479289196,373161.4848287328,318697.1789732917,345399.49658985186,314419.8189439592,230963.73709983748,236070.00307120252,312676.53469423676,195102.01076090848,231756.2941107393,196457.66930311252,255890.52889680286,207980.18388759278,250218.19793663023,221472.83820330602,212315.28230042476,222774.69138098884,210372.25250462766,210846.3448041017,177438.35447152023,214108.95671057343,190417.02324135366,175558.31404488848,199041.30532793878,154342.13931409398,175902.47007757265,215120.2640019617,216733.8944940455,261370.58822336013,212333.63219332727,174324.40313248086,166539.1770850326,202012.88317391058,238213.58919108333,170401.06338583003,217109.81457913358,185684.48673203168,210764.408869451,180452.94255978477,359959.68381729786,220133.80814962948,201815.91045998363,193256.2376798832,225141.35101977925,194502.14845672756,241700.45583039062,203049.47691663646,189440.21996991744,241270.48318453485,196628.83730256284 +PL,10323.210329129464,10102.880830361863,15243.556644277647,6316.576710839603,13844.440254769646,15125.266765937784,15697.445163802722,20547.692524530372,11483.751822471613,12736.801698643669,14242.313560202334,19975.533453959804,14197.61841088385,13385.258603233342,17555.946503015533,19526.389852009346,24990.22970093532,18554.95543612019,10610.557656768206,19356.459381427685,19657.930603206125,18732.50311338716,16842.606570419066,21220.5523273715,24157.44207211756,15607.0096942104,21677.41127186343,21298.26291533998,22732.35472759213,23096.919661671975,20539.587419825057,15690.593097829358,10514.527177352287,9757.003902443616,18214.127020951153,14743.470132504332,14160.372458977477,15574.81487531224,12340.373515759937,8851.92371521615,10791.411372967183,10330.247763133175,10795.54750377256,14738.227630388099,14374.438386354948,12177.648415014886,14450.3889852054,16473.394758962142,14491.781691174727,11650.64866730713,13724.64695911459,14468.081620316902,7425.533290488975,8039.550610683221,9468.54351850099,6656.34004885665,7842.310345436549,9593.638690519654,8828.256800239144,15874.058827778785,13537.338641985261,6174.396712827303,9509.500411581042,9436.102173346171,5360.954908688417,6309.399306468634,12402.024613286878,10602.512257049677,4725.103685514244,6963.3130148445025,9124.964758601689 +PT,8372.129135066036,5969.31083523099,2397.6586063764958,3916.9962424030286,9654.699566273128,9603.363148222781,4163.162870337118,9179.465624121007,12131.854156488425,23406.646477036124,10635.077955993413,11029.404714084018,16475.917880350513,12087.55769685171,9804.492049893286,26178.184180984652,5669.820254013018,7559.528320921835,15405.930172416956,11163.387795923936,7088.025310785357,10191.330496756716,7128.069257230898,9335.631563569985,5236.13128329125,4572.251664471752,32605.577182903042,149323.86523586328,34294.81803755196,6061.11721308257,5836.654497517657,4843.7020037722705,7814.782411245904,9395.759000250582,14057.157961109715,8192.288977642056,7655.760207241933,9203.645337709624,7637.7450966202805,7971.812432879156,7421.37678917759,2935.2871895485287,6329.939163930326,8820.796560748415,8944.109217212255,14719.27363438586,11050.779819799696,8379.75073967695,5590.525909815882,10485.131539563748,20476.028147427794,7715.162648805314,11939.81827695821,5116.2596877306005,3047.0903835389504,9273.489011971804,5135.313604526994,3331.418010762715,6338.048693933388,12105.616460835923,7097.468638389797,3348.213951094401,11773.920694867731,13465.586888738457,4379.602415677836,11394.463621230614,3104.8789319036796,7216.150544702967,6653.765864361187,5720.580737490315,6685.493238874142 +RO,19346.344374357534,19295.50358149612,27702.617554877004,24644.67023787785,52797.882559506776,42262.7162454671,34689.01143849651,42583.74114324521,28973.147767939397,36882.64868179707,29063.471368254675,39575.626278602576,31898.858414072816,36283.98261870408,42207.50410750205,41714.957670180156,43270.313090823794,40474.54716426176,53565.91349208634,74865.02611452111,48190.11154819992,57257.26135564704,46523.80416861758,44300.83791323246,54901.1701096736,47361.27151969814,49156.09266449866,56461.30009557872,56062.45724028393,58506.511677323855,48499.732173446595,45901.64074770707,33171.12855766741,38310.49272614435,39377.41586450999,28638.803870927226,29424.553978129992,39429.14347226504,39300.73151290347,27525.04968129815,47095.77682827757,30948.90232192865,32939.14262154816,30155.99148400138,35067.04977301419,35592.25066656211,45790.67404045973,42596.77718301701,39223.35618808953,25767.93476452563,30963.38609617001,30034.908201595936,23323.05819720473,28517.276888551194,41560.85308154171,43999.15897330077,21427.19650317167,25084.131072037453,18450.764512377853,38182.39266803458,20422.517191285966,14090.243196787245,21998.55223596247,30809.187151501046,22071.90474198888,31906.454754357772,20763.073093214778,25620.747974742615,19248.368008063957,23289.011422937554,26669.846131314298 +RS,5968.673897869134,7450.873145908507,8457.218084424714,10466.134979346216,18700.932768467817,18783.264457747777,9647.157790116991,14650.396388121844,12360.14810912279,11640.673528541236,8882.446980807292,14762.619600006037,18399.930168952076,13646.806400326906,14489.119148714197,14104.804002759012,15462.34970923992,10894.228431882033,15095.088711819322,17853.281396922546,12916.46431873845,14207.379133135786,14418.834370720482,12752.5957180177,15544.588217112372,15820.904121022999,13534.055257847373,15215.146639151637,12996.626380040323,13029.919161637963,10196.668003968522,10284.440766030819,7022.693160251435,8401.249663323453,8435.803252725058,10265.915943082338,8623.546341166757,7782.429841191159,9309.259412625106,4849.32865233776,9480.40891035497,8237.330612702019,6688.9341497267815,7113.796951355988,8945.392918392941,11391.406447517316,8770.78174795334,7797.074404297926,11205.567652241964,7490.638744688466,6890.626375097134,8721.152535625733,6986.899718851523,10014.515393386338,11863.685949406314,12576.12226693591,6930.903954576986,6933.68818306879,8436.351253425808,11680.836931112251,5673.257881932308,4512.930178739657,6094.8735580904795,11616.485592765608,8423.704814584986,9582.260510301834,6280.960312130538,10196.683253538626,5869.428152205924,6637.126459584064,8223.324863109141 +SK,6885.47211985414,6956.591212284293,7116.928783228905,4573.269245439668,8169.130903254093,6799.092645889461,7190.199390340817,8819.311158887818,6679.080394471699,8681.76846617681,6714.688996801623,8780.135433744465,9674.052829336924,7510.89080672348,12315.672504913706,11551.288938768861,10658.095118642217,7760.467099195778,7334.701885838525,11743.053621084162,9101.455526104724,11252.254293590808,7089.2297957961755,11692.575497480175,11870.620362608648,8320.411050776946,12664.612697391287,10840.053026355938,9544.145158945727,8285.851845920657,6554.955003499832,6014.385824757616,5119.229272436076,5566.197178944401,8283.751441606055,4576.739002618681,5529.727054286627,4884.285979430572,7030.767074231632,6380.185010419688,6092.06334940043,4789.6919845964085,3988.728835990378,6100.445127127096,6174.336930810738,5839.492530664778,6739.897695678873,6073.547495791424,6239.663814901599,5985.626769812626,5946.910319392802,5350.4706690989715,2897.742723724252,3812.447551889599,5110.734824948982,5466.7571969447445,3822.1224333717755,4189.745228198809,3608.9397299109723,8925.718578619328,5520.297117401385,2338.023634704523,3634.014208205775,5079.021357670912,3789.3939110245783,3599.858750509022,4222.707040620564,3096.1701009538024,2158.8092391216674,4542.203594136759,4220.210061470592 +SI,11752.798116380785,9378.602450871665,7169.30972105447,8221.267552376507,10568.142173580174,7705.119699907013,8559.440940655051,9496.2682906945,10641.418485889739,13644.09405840664,8756.865265119286,10877.994032024846,13095.473005855994,10408.222250010325,17110.767148034232,13257.44359305617,10163.420442559087,10743.809603872312,11213.570708968457,12419.028940460184,8518.188189494229,14975.496301661744,10217.449212514946,10521.007791805137,10759.209828867228,9699.803414833696,14530.647692616923,14530.715084460895,12439.143395173185,11990.046930204517,9001.647305603035,10111.423546501868,6824.172499114327,10267.968760960974,10233.709492652128,9562.175707725224,11231.941186997657,8178.692540046128,8568.526412713521,8103.883097000008,9639.895318751553,9157.43571368136,6814.50158997294,8089.913064615838,8170.645053083449,10765.044719853075,6713.170108103339,8936.8362631332,9542.147586182518,8964.110093884974,8653.114721452737,8353.75428643612,4558.589088593759,9432.405903987477,6927.92152111369,7408.760392367348,5834.871486466167,9336.912851251047,8839.494837985663,10766.693939731143,5073.937522450624,6475.598951785893,9482.419717110955,13414.771212079502,5906.5584945059145,9942.151265372298,7696.092255607837,9521.835825354157,8476.124990692872,6361.010018809483,7504.908031281684 +SE,134822.12256461562,136958.6213484757,175679.6273876132,133962.36617697845,126787.36233921513,130861.49290945902,151133.2982760823,140247.52694114187,130508.52271890236,137421.63579450184,164132.0529341604,142467.57286064525,135886.87305352974,163762.3962091317,161128.38161511483,148196.28633931337,167892.87677861055,132017.696130452,105953.99289036485,119407.22923207263,147139.6039546916,151309.55114963037,164893.61323375857,137608.18237925606,149284.78771947857,108749.15747050248,131859.531763871,117290.48017785426,131751.97960784068,111117.27409251402,110551.615114603,81550.1135393761,114677.940027603,102356.46697333359,128977.80283219383,94483.98267503879,114937.96457142044,93256.91327642264,96751.29026217168,91074.34139788701,87931.96567208324,96560.83822983531,116746.94389793588,64626.25905820224,75156.91767736348,51489.37512699482,74729.26978432719,134673.01513808029,110440.65771030058,149033.9827088587,143576.83069821307,93040.02354987273,64075.160200006496,102493.08906248632,106664.82884715112,90351.43771324471,94801.81222609026,92445.93458012305,88919.20770998915,108111.72872590217,127440.80298482065,124444.06618883039,98961.91573013023,87913.90602563386,115956.48217115598,95526.84265190935,103459.08985036932,86058.90377748368,99040.9103276256,110493.22773914765,94182.7249029169 diff --git a/envs/environment.yaml b/envs/environment.yaml index 8bd7428f..f5cb9aae 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -39,6 +39,7 @@ dependencies: - proj - fiona <= 1.18.20 # Till issue https://github.com/Toblerity/Fiona/issues/1085 is not solved - country_converter + - scikit-learn # Keep in conda environment when calling ipython - ipython diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index c1400d28..f56cb9e3 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -66,13 +66,16 @@ import atlite import geopandas as gpd import pandas as pd +from sklearn.linear_model import LinearRegression + import country_converter as coco cc = coco.CountryConverter() -def get_eia_annual_hydro_generation(fn, countries): +def get_eia_annual_hydro_generation(fn, countries, capacities=False): - # in billion kWh/a = TWh/a + # energy: in billion kWh/a = TWh/a + # capacity: in billion kW = GW df = pd.read_csv(fn, skiprows=2, index_col=1, na_values=[u' ','--']).iloc[1:, 1:] df.index = df.index.str.strip() @@ -106,11 +109,51 @@ def get_eia_annual_hydro_generation(fn, countries): df.index = cc.convert(df.index, to='iso2') df.index.name = 'countries' - df = df.T[countries] * 1e6 # in MWh/a + # convert to MW of MWh/a + factor = 1e3 if capacities else 1e6 + df = df.T[countries] * factor return df +def correct_eia_stats_by_capacity(eia_stats, fn, countries, baseyear=2019): + cap = get_eia_annual_hydro_generation(fn, countries, capacities=True) + ratio = cap / cap.loc[str(baseyear)] + eia_stats_corrected = eia_stats / ratio + to_keep = ["AL", "AT", "CH", "DE", "GB", "NL", "RS", "RO", "SK"] + to_correct = eia_stats_corrected.columns.difference(to_keep) + eia_stats.loc[:,to_correct] = eia_stats_corrected.loc[:,to_correct] + + +def approximate_missing_eia_stats(eia_stats, runoff_fn, countries): + + runoff = pd.read_csv(runoff_fn, index_col=0).T[countries] + + # fix ES, PT data points + runoff.loc["1978", ["ES", "PT"]] = runoff.loc["1979", ["ES", "PT"]] + + runoff_eia = runoff.loc[eia_stats.index] + + eia_stats_approximated = {} + + for c in countries: + + X = runoff_eia[c].values.reshape(-1, 1) + Y = eia_stats[c].values.reshape(-1, 1) + + to_predict = runoff.index.difference(eia_stats.index) + X_pred = runoff.loc[to_predict, c].values.reshape(-1, 1) + + linear_regressor = LinearRegression() + linear_regressor.fit(X, Y) + Y_pred = linear_regressor.predict(X_pred) + + eia_stats_approximated[c] = pd.Series(Y_pred.T[0], index=to_predict) + + eia_stats_approximated = pd.DataFrame(eia_stats_approximated) + return pd.concat([eia_stats, eia_stats_approximated]).sort_index() + + logger = logging.getLogger(__name__) if __name__ == "__main__": @@ -130,8 +173,16 @@ if __name__ == "__main__": fn = snakemake.input.eia_hydro_generation eia_stats = get_eia_annual_hydro_generation(fn, countries) + if config_hydro.get('eia_correct_by_capacity'): + fn = snakemake.input.eia_hydro_capacity + correct_eia_stats_by_capacity(eia_stats, fn, countries) + + if config_hydro.get('eia_approximate_missing'): + fn = snakemake.input.era5_runoff + eia_stats = approximate_missing_eia_stats(eia_stats, fn, countries) + weather_year = snakemake.wildcards.weather_year - norm_year = snakemake.config['renewable']['hydro'].get('norm_year') + norm_year = config_hydro.get('eia_norm_year') if norm_year: eia_stats.loc[weather_year] = eia_stats.loc[norm_year] elif weather_year and weather_year not in eia_stats.index: From 5bb432141dd1067910d54b808364c66d86285f0e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 22 Jul 2022 18:34:16 +0200 Subject: [PATCH 046/591] hydro: add documentation for eia approximation/correction options --- doc/configtables/hydro.csv | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/configtables/hydro.csv b/doc/configtables/hydro.csv index 8148b256..6016e6f1 100644 --- a/doc/configtables/hydro.csv +++ b/doc/configtables/hydro.csv @@ -4,4 +4,6 @@ carriers,--,"Any subset of {'ror', 'PHS', 'hydro'}","Specifies the types of hydr PHS_max_hours,h,float,"Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom``. Cf. `PyPSA documentation `_." hydro_max_hours,h,"Any of {float, 'energy_capacity_totals_by_country', 'estimate_by_large_installations'}","Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom`` or heuristically determined. Cf. `PyPSA documentation `_." clip_min_inflow,MW,float,"To avoid too small values in the inflow time series, values below this threshold are set to zero." -norm_year,--,"Year in EIA hydro generation dataset; or False to disable","To specify a specific year by which hydro inflow is normed that deviates from the snapshots' year" \ No newline at end of file +eia_norm_year,--,"Year in EIA hydro generation dataset; or False to disable","To specify a specific year by which hydro inflow is normed that deviates from the snapshots' year" +eia_correct_by_capacity,--,boolean,"Correct EIA annual hydro generation data by installed capacity." +eia_approximate_missing,--,boolean,"Approximate hydro generation data for years not included in EIA dataset through a regression based on annual runoff." \ No newline at end of file From 16bd4b6c2cbe4f2f3b315b19ed27b4f8c804ca27 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 22 Jul 2022 19:14:00 +0200 Subject: [PATCH 047/591] fix snapshot creation based on weather year --- scripts/build_heat_demand.py | 6 +++--- scripts/build_solar_thermal_profiles.py | 2 +- scripts/build_temperature_profiles.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/build_heat_demand.py b/scripts/build_heat_demand.py index fe44de16..1e165c69 100644 --- a/scripts/build_heat_demand.py +++ b/scripts/build_heat_demand.py @@ -11,9 +11,9 @@ if __name__ == '__main__': from helper import mock_snakemake snakemake = mock_snakemake( 'build_heat_demands', - weather_year='', + weather_year='1969', simpl='', - clusters=48, + clusters=37, ) cutout_name = snakemake.input.cutout @@ -25,7 +25,7 @@ if __name__ == '__main__': else: snapshots = snakemake.config['snapshots'] - time = pd.date_range(freq='m', **snapshots) + time = pd.date_range(freq='h', **snapshots) if snakemake.config["atlite"].get("drop_leap_day", False): time = time[~((time.month == 2) & (time.day == 29))] diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index 8bdc07c5..ec9e59c4 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -27,7 +27,7 @@ if __name__ == '__main__': else: snapshots = snakemake.config['snapshots'] - time = pd.date_range(freq='m', **snapshots) + time = pd.date_range(freq='h', **snapshots) if snakemake.config["atlite"].get("drop_leap_day", False): time = time[~((time.month == 2) & (time.day == 29))] diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index ab006409..3e690cca 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -25,7 +25,7 @@ if __name__ == '__main__': else: snapshots = snakemake.config['snapshots'] - time = pd.date_range(freq='m', **snapshots) + time = pd.date_range(freq='h', **snapshots) if snakemake.config["atlite"].get("drop_leap_day", False): time = time[~((time.month == 2) & (time.day == 29))] From 6e47c711952ab94ac098f62d922420e27a27c3e0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 22 Jul 2022 20:48:24 +0200 Subject: [PATCH 048/591] clustered_population: add missing cutout input --- Snakefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Snakefile b/Snakefile index 68d32443..54829b6a 100644 --- a/Snakefile +++ b/Snakefile @@ -97,6 +97,7 @@ rule build_clustered_population_layouts: rule build_simplified_population_layouts: input: + cutout=pypsaeur("cutouts/" + config['atlite']['cutout'] + ".nc"), pop_layout_total="resources/pop_layout_total{weather_year}.nc", pop_layout_urban="resources/pop_layout_urban{weather_year}.nc", pop_layout_rural="resources/pop_layout_rural{weather_year}.nc", From d47a9aac72309420b8e941132ccf1c30169343c5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 23 Jul 2022 10:37:32 +0200 Subject: [PATCH 049/591] energy_totals: update eurostat to 2021 --- Snakefile | 10 +-- scripts/build_energy_totals.py | 153 ++++++++++++++------------------- 2 files changed, 68 insertions(+), 95 deletions(-) diff --git a/Snakefile b/Snakefile index 54829b6a..fa2323f8 100644 --- a/Snakefile +++ b/Snakefile @@ -54,8 +54,7 @@ datafiles = [ "data/emobility/KFZ__count", "data/emobility/Pkw__count", "data/h2_salt_caverns_GWh_per_sqkm.geojson", - directory("data/eurostat-energy_balances-june_2016_edition"), - directory("data/eurostat-energy_balances-may_2018_edition"), + directory("data/eurostat-energy_balances-april_2022_edition"), directory("data/jrc-idees-2015"), ] @@ -235,11 +234,6 @@ rule build_solar_thermal_profiles: script: "scripts/build_solar_thermal_profiles.py" -def input_eurostat(w): - # 2016 includes BA, 2017 does not - report_year = config["energy"]["eurostat_report_year"] - return f"data/eurostat-energy_balances-june_{report_year}_edition" - rule build_energy_totals: input: nuts3_shapes=pypsaeur('resources/nuts3_shapes.geojson'), @@ -247,7 +241,7 @@ rule build_energy_totals: swiss="data/switzerland-sfoe/switzerland-new_format.csv", idees="data/jrc-idees-2015", district_heat_share='data/district_heat_share.csv', - eurostat=input_eurostat + eurostat=directory("data/eurostat-energy_balances-june_2021_edition"), output: energy_name='resources/energy_totals.csv', co2_name='resources/co2_totals.csv', diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 3f376b0c..f2e565e1 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -17,55 +17,6 @@ def reverse(dictionary): """reverses a keys and values of a dictionary""" return {v: k for k, v in dictionary.items()} - -# translations for Eurostat -eurostat_country_to_alpha2 = { - "EU28": "EU", - "EA19": "EA", - "Belgium": "BE", - "Bulgaria": "BG", - "Czech Republic": "CZ", - "Denmark": "DK", - "Germany": "DE", - "Estonia": "EE", - "Ireland": "IE", - "Greece": "GR", - "Spain": "ES", - "France": "FR", - "Croatia": "HR", - "Italy": "IT", - "Cyprus": "CY", - "Latvia": "LV", - "Lithuania": "LT", - "Luxembourg": "LU", - "Hungary": "HU", - "Malta": "MA", - "Netherlands": "NL", - "Austria": "AT", - "Poland": "PL", - "Portugal": "PT", - "Romania": "RO", - "Slovenia": "SI", - "Slovakia": "SK", - "Finland": "FI", - "Sweden": "SE", - "United Kingdom": "GB", - "Iceland": "IS", - "Norway": "NO", - "Montenegro": "ME", - "FYR of Macedonia": "MK", - "Albania": "AL", - "Serbia": "RS", - "Turkey": "TU", - "Bosnia and Herzegovina": "BA", - "Kosovo\n(UNSCR 1244/99)": "KO", # 2017 version - # 2016 version - "Kosovo\n(under United Nations Security Council Resolution 1244/99)": "KO", - "Moldova": "MO", - "Ukraine": "UK", - "Switzerland": "CH", -} - non_EU = ["NO", "CH", "ME", "MK", "RS", "BA", "AL"] idees_rename = {"GR": "EL", "GB": "UK"} @@ -127,47 +78,68 @@ to_ipcc = { } -def build_eurostat(countries, year): - """Return multi-index for all countries' energy data in TWh/a.""" +def eurostat_per_country(country): + + country_fn = idees_rename.get(country, country) + fn = snakemake.input.eurostat + f"/{country_fn}-Energy-balance-sheets-June-2021-edition.xlsb" - report_year = snakemake.config["energy"]["eurostat_report_year"] - filenames = { - 2016: f"/{year}-Energy-Balances-June2016edition.xlsx", - 2017: f"/{year}-ENERGY-BALANCES-June2017edition.xlsx" - } - - dfs = pd.read_excel( - snakemake.input.eurostat + filenames[report_year], + df = pd.read_excel( + fn, sheet_name=None, - skiprows=1, - index_col=list(range(4)), + skiprows=4, + index_col=list(range(3)), + na_values=["+", "-", "=", "Z", ":"], ) - # sorted_index necessary for slicing - lookup = eurostat_country_to_alpha2 - labelled_dfs = {lookup[df.columns[0]]: df - for df in dfs.values() - if lookup[df.columns[0]] in countries} - df = pd.concat(labelled_dfs, sort=True).sort_index() + df.pop("Cover") - # drop non-numeric and country columns - non_numeric_cols = df.columns[df.dtypes != float] - country_cols = df.columns.intersection(lookup.keys()) - to_drop = non_numeric_cols.union(country_cols) - df.drop(to_drop, axis=1, inplace=True) + return pd.concat(df) + + +def build_eurostat(countries, year=None): + """Return multi-index for all countries' energy data in TWh/a.""" + + nprocesses = snakemake.threads + tqdm_kwargs = dict(ascii=False, unit=' country', total=len(countries), + desc='Build from eurostat database') + with mp.Pool(processes=nprocesses) as pool: + dfs = list(tqdm(pool.imap(eurostat_per_country, countries), **tqdm_kwargs)) + + index_names = ['country', 'year', 'lvl1', 'lvl2', 'lvl3'] + df = pd.concat(dfs, keys=countries, names=index_names) + + df.dropna(how='all', axis=0, inplace=True) + df.dropna(how='all', axis=1, inplace=True) + df = df[df.index.get_level_values('lvl1') != 'ktoe'] + + i = df.index.to_frame(index=False) + i.loc[i.lvl2 == 'Primary production', ['lvl1', 'lvl3']] = 'Main' + i.loc[i.lvl2 == 'Gross electricity production', 'lvl1'] = "Gross production" + i.ffill(inplace=True) + df.index = pd.MultiIndex.from_frame(i) + + df.drop(list(range(1990, 2020)), axis=1, inplace=True) + df.drop("Unnamed: 7", axis=1, inplace=True) + df.fillna(0., inplace=True) # convert ktoe/a to TWh/a df *= 11.63 / 1e3 + if year: + df = df.xs(str(year), level='year') + return df -def build_swiss(year): +def build_swiss(year=None): """Return a pd.Series of Swiss energy data in TWh/a""" fn = snakemake.input.swiss - df = pd.read_csv(fn, index_col=[0,1]).loc["CH", str(year)] + df = pd.read_csv(fn, index_col=[0,1]).loc["CH"] + + if year: + df = df[str(year)] # convert PJ/a to TWh/a df /= 3.6 @@ -406,8 +378,17 @@ def build_idees(countries, year): def build_energy_totals(countries, eurostat, swiss, idees): - eurostat_fuels = {"electricity": "Electricity", - "total": "Total all products"} + eurostat_fuels = dict( + electricity="Electricity", + total="Total" + ) + + eurostat_sectors = dict( + residential="Households", + services="Commercial & public services", + road="Road", + rail="Rail" + ) to_drop = ["passenger cars", "passenger car efficiency"] df = idees.reindex(countries).drop(to_drop, axis=1) @@ -417,8 +398,8 @@ def build_energy_totals(countries, eurostat, swiss, idees): # add international navigation - slicer = idx[in_eurostat, :, "Bunkers", :] - fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() + slicer = idx[in_eurostat, :, "International maritime bunkers", :] + fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum() df.loc[in_eurostat, "total international navigation"] = fill_values # add swiss energy data @@ -434,12 +415,10 @@ def build_energy_totals(countries, eurostat, swiss, idees): for sector in ["residential", "services", "road", "rail"]: - eurostat_sector = sector.capitalize() - # fuel use for fuel in ["electricity", "total"]: - slicer = idx[to_fill, :, :, eurostat_sector] + slicer = idx[to_fill, :, :, eurostat_sectors[sector]] fill_values = eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=0).sum() df.loc[to_fill, f"{fuel} {sector}"] = fill_values @@ -489,17 +468,17 @@ def build_energy_totals(countries, eurostat, swiss, idees): # Missing aviation slicer = idx[to_fill, :, :, "Domestic aviation"] - fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() + fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum() df.loc[to_fill, "total domestic aviation"] = fill_values - slicer = idx[to_fill, :, :, "International aviation"] - fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() + slicer = idx[to_fill, :, "International aviation", :] + fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum() df.loc[to_fill, "total international aviation"] = fill_values # missing domestic navigation - slicer = idx[to_fill, :, :, "Domestic Navigation"] - fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() + slicer = idx[to_fill, :, :, "Domestic navigation"] + fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum() df.loc[to_fill, "total domestic navigation"] = fill_values # split road traffic for non-IDEES @@ -702,7 +681,7 @@ if __name__ == "__main__": idees_countries = countries.intersection(eu28) data_year = config["energy_totals_year"] - eurostat = build_eurostat(countries, data_year) + eurostat = build_eurostat(countries.difference(['CH']), data_year) swiss = build_swiss(data_year) idees = build_idees(idees_countries, data_year) From eee6651d12ff8ae87e4bf3a30119541c870decc1 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 23 Jul 2022 11:19:37 +0200 Subject: [PATCH 050/591] energy_totals: fetch all years 2000-2015 from IDEES --- scripts/build_energy_totals.py | 158 ++++++++++++++++----------------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index f2e565e1..1845c93c 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -147,90 +147,89 @@ def build_swiss(year=None): return df -def idees_per_country(ct, year): +def idees_per_country(country): base_dir = snakemake.input.idees ct_totals = {} - ct_idees = idees_rename.get(ct, ct) + ct_idees = idees_rename.get(country, country) fn_residential = f"{base_dir}/JRC-IDEES-2015_Residential_{ct_idees}.xlsx" fn_tertiary = f"{base_dir}/JRC-IDEES-2015_Tertiary_{ct_idees}.xlsx" fn_transport = f"{base_dir}/JRC-IDEES-2015_Transport_{ct_idees}.xlsx" # residential - df = pd.read_excel(fn_residential, "RES_hh_fec", index_col=0)[year] + df = pd.read_excel(fn_residential, "RES_hh_fec", index_col=0) - ct_totals["total residential space"] = df["Space heating"] + ct_totals["total residential space"] = df.loc["Space heating"] rows = ["Advanced electric heating", "Conventional electric heating"] - ct_totals["electricity residential space"] = df[rows].sum() + ct_totals["electricity residential space"] = df.loc[rows].sum() - ct_totals["total residential water"] = df.at["Water heating"] + ct_totals["total residential water"] = df.loc["Water heating"] assert df.index[23] == "Electricity" - ct_totals["electricity residential water"] = df[23] + ct_totals["electricity residential water"] = df.iloc[23] - ct_totals["total residential cooking"] = df["Cooking"] + ct_totals["total residential cooking"] = df.loc["Cooking"] assert df.index[30] == "Electricity" - ct_totals["electricity residential cooking"] = df[30] + ct_totals["electricity residential cooking"] = df.iloc[30] - df = pd.read_excel(fn_residential, "RES_summary", index_col=0)[year] + df = pd.read_excel(fn_residential, "RES_summary", index_col=0) row = "Energy consumption by fuel - Eurostat structure (ktoe)" - ct_totals["total residential"] = df[row] + ct_totals["total residential"] = df.loc[row] assert df.index[47] == "Electricity" - ct_totals["electricity residential"] = df[47] + ct_totals["electricity residential"] = df.iloc[47] assert df.index[46] == "Derived heat" - ct_totals["derived heat residential"] = df[46] + ct_totals["derived heat residential"] = df.iloc[46] assert df.index[50] == 'Thermal uses' - ct_totals["thermal uses residential"] = df[50] + ct_totals["thermal uses residential"] = df.iloc[50] # services - df = pd.read_excel(fn_tertiary, "SER_hh_fec", index_col=0)[year] + df = pd.read_excel(fn_tertiary, "SER_hh_fec", index_col=0) - ct_totals["total services space"] = df["Space heating"] + ct_totals["total services space"] = df.loc["Space heating"] rows = ["Advanced electric heating", "Conventional electric heating"] - ct_totals["electricity services space"] = df[rows].sum() + ct_totals["electricity services space"] = df.loc[rows].sum() - ct_totals["total services water"] = df["Hot water"] + ct_totals["total services water"] = df.loc["Hot water"] assert df.index[24] == "Electricity" - ct_totals["electricity services water"] = df[24] + ct_totals["electricity services water"] = df.iloc[24] - ct_totals["total services cooking"] = df["Catering"] + ct_totals["total services cooking"] = df.loc["Catering"] assert df.index[31] == "Electricity" - ct_totals["electricity services cooking"] = df[31] + ct_totals["electricity services cooking"] = df.iloc[31] - df = pd.read_excel(fn_tertiary, "SER_summary", index_col=0)[year] + df = pd.read_excel(fn_tertiary, "SER_summary", index_col=0) row = "Energy consumption by fuel - Eurostat structure (ktoe)" - ct_totals["total services"] = df[row] + ct_totals["total services"] = df.loc[row] assert df.index[50] == "Electricity" - ct_totals["electricity services"] = df[50] + ct_totals["electricity services"] = df.iloc[50] assert df.index[49] == "Derived heat" - ct_totals["derived heat services"] = df[49] + ct_totals["derived heat services"] = df.iloc[49] assert df.index[53] == 'Thermal uses' - ct_totals["thermal uses services"] = df[53] - + ct_totals["thermal uses services"] = df.iloc[53] # agriculture, forestry and fishing start = "Detailed split of energy consumption (ktoe)" end = "Market shares of energy uses (%)" - df = pd.read_excel(fn_tertiary, "AGR_fec", index_col=0).loc[start:end, year] + df = pd.read_excel(fn_tertiary, "AGR_fec", index_col=0).loc[start:end] rows = [ "Lighting", @@ -238,142 +237,143 @@ def idees_per_country(ct, year): "Specific electricity uses", "Pumping devices (electric)" ] - ct_totals["total agriculture electricity"] = df[rows].sum() + ct_totals["total agriculture electricity"] = df.loc[rows].sum() rows = ["Specific heat uses", "Low enthalpy heat"] - ct_totals["total agriculture heat"] = df[rows].sum() + ct_totals["total agriculture heat"] = df.loc[rows].sum() rows = [ "Motor drives", "Farming machine drives (diesel oil incl. biofuels)", "Pumping devices (diesel oil incl. biofuels)", ] - ct_totals["total agriculture machinery"] = df[rows].sum() + ct_totals["total agriculture machinery"] = df.loc[rows].sum() row = "Agriculture, forestry and fishing" - ct_totals["total agriculture"] = df[row] + ct_totals["total agriculture"] = df.loc[row] # transport - df = pd.read_excel(fn_transport, "TrRoad_ene", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrRoad_ene", index_col=0) - ct_totals["total road"] = df["by fuel (EUROSTAT DATA)"] + ct_totals["total road"] = df.loc["by fuel (EUROSTAT DATA)"] - ct_totals["electricity road"] = df["Electricity"] + ct_totals["electricity road"] = df.loc["Electricity"] - ct_totals["total two-wheel"] = df["Powered 2-wheelers (Gasoline)"] + ct_totals["total two-wheel"] = df.loc["Powered 2-wheelers (Gasoline)"] assert df.index[19] == "Passenger cars" - ct_totals["total passenger cars"] = df[19] + ct_totals["total passenger cars"] = df.iloc[19] assert df.index[30] == "Battery electric vehicles" - ct_totals["electricity passenger cars"] = df[30] + ct_totals["electricity passenger cars"] = df.iloc[30] assert df.index[31] == "Motor coaches, buses and trolley buses" - ct_totals["total other road passenger"] = df[31] + ct_totals["total other road passenger"] = df.iloc[31] assert df.index[39] == "Battery electric vehicles" - ct_totals["electricity other road passenger"] = df[39] + ct_totals["electricity other road passenger"] = df.iloc[39] assert df.index[41] == "Light duty vehicles" - ct_totals["total light duty road freight"] = df[41] + ct_totals["total light duty road freight"] = df.iloc[41] assert df.index[49] == "Battery electric vehicles" - ct_totals["electricity light duty road freight"] = df[49] + ct_totals["electricity light duty road freight"] = df.iloc[49] row = "Heavy duty vehicles (Diesel oil incl. biofuels)" - ct_totals["total heavy duty road freight"] = df[row] + ct_totals["total heavy duty road freight"] = df.loc[row] assert df.index[61] == "Passenger cars" - ct_totals["passenger car efficiency"] = df[61] + ct_totals["passenger car efficiency"] = df.iloc[61] - df = pd.read_excel(fn_transport, "TrRail_ene", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrRail_ene", index_col=0) - ct_totals["total rail"] = df["by fuel (EUROSTAT DATA)"] + ct_totals["total rail"] = df.loc["by fuel (EUROSTAT DATA)"] - ct_totals["electricity rail"] = df["Electricity"] + ct_totals["electricity rail"] = df.loc["Electricity"] assert df.index[15] == "Passenger transport" - ct_totals["total rail passenger"] = df[15] + ct_totals["total rail passenger"] = df.iloc[15] assert df.index[16] == "Metro and tram, urban light rail" assert df.index[19] == "Electric" assert df.index[20] == "High speed passenger trains" - ct_totals["electricity rail passenger"] = df[[16, 19, 20]].sum() + ct_totals["electricity rail passenger"] = df.iloc[[16, 19, 20]].sum() assert df.index[21] == "Freight transport" - ct_totals["total rail freight"] = df[21] + ct_totals["total rail freight"] = df.iloc[21] assert df.index[23] == "Electric" - ct_totals["electricity rail freight"] = df[23] + ct_totals["electricity rail freight"] = df.iloc[23] - df = pd.read_excel(fn_transport, "TrAvia_ene", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrAvia_ene", index_col=0) assert df.index[6] == "Passenger transport" - ct_totals["total aviation passenger"] = df[6] + ct_totals["total aviation passenger"] = df.iloc[6] assert df.index[10] == "Freight transport" - ct_totals["total aviation freight"] = df[10] + ct_totals["total aviation freight"] = df.iloc[10] assert df.index[7] == "Domestic" - ct_totals["total domestic aviation passenger"] = df[7] + ct_totals["total domestic aviation passenger"] = df.iloc[7] assert df.index[8] == "International - Intra-EU" assert df.index[9] == "International - Extra-EU" - ct_totals["total international aviation passenger"] = df[[8,9]].sum() + ct_totals["total international aviation passenger"] = df.iloc[[8,9]].sum() assert df.index[11] == "Domestic and International - Intra-EU" - ct_totals["total domestic aviation freight"] = df[11] + ct_totals["total domestic aviation freight"] = df.iloc[11] assert df.index[12] == "International - Extra-EU" - ct_totals["total international aviation freight"] = df[12] + ct_totals["total international aviation freight"] = df.iloc[12] ct_totals["total domestic aviation"] = ct_totals["total domestic aviation freight"] \ - + ct_totals["total domestic aviation passenger"] + + ct_totals["total domestic aviation passenger"] ct_totals["total international aviation"] = ct_totals["total international aviation freight"] \ - + ct_totals["total international aviation passenger"] + + ct_totals["total international aviation passenger"] - df = pd.read_excel(fn_transport, "TrNavi_ene", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrNavi_ene", index_col=0) # coastal and inland - ct_totals["total domestic navigation"] = df["by fuel (EUROSTAT DATA)"] + ct_totals["total domestic navigation"] = df.loc["by fuel (EUROSTAT DATA)"] - df = pd.read_excel(fn_transport, "TrRoad_act", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrRoad_act", index_col=0) assert df.index[85] == "Passenger cars" - ct_totals["passenger cars"] = df[85] + ct_totals["passenger cars"] = df.iloc[85] - return pd.Series(ct_totals, name=ct) + return pd.DataFrame(ct_totals) -def build_idees(countries, year): +def build_idees(countries, year=None): nprocesses = snakemake.threads - func = partial(idees_per_country, year=year) tqdm_kwargs = dict(ascii=False, unit=' country', total=len(countries), desc='Build from IDEES database') with mp.Pool(processes=nprocesses) as pool: - totals_list = list(tqdm(pool.imap(func, countries), **tqdm_kwargs)) + dfs = list(tqdm(pool.imap(idees_per_country, countries), **tqdm_kwargs)) - - totals = pd.concat(totals_list, axis=1) + df = pd.concat(dfs, keys=countries, names=['country', 'year']) # convert ktoe to TWh - exclude = totals.index.str.fullmatch("passenger cars") - totals.loc[~exclude] *= 11.63 / 1e3 + exclude = df.columns.str.fullmatch("passenger cars") + df.loc[:,~exclude] *= 11.63 / 1e3 # convert TWh/100km to kWh/km - totals.loc["passenger car efficiency"] *= 10 + df["passenger car efficiency"] *= 10 # district heating share - district_heat = totals.loc[["derived heat residential", - "derived heat services"]].sum() - total_heat = totals.loc[["thermal uses residential", - "thermal uses services"]].sum() - totals.loc["district heat share"] = district_heat.div(total_heat) + subset = ["derived heat residential", "derived heat services"] + district_heat = df[subset].sum(axis=1) + subset = ["thermal uses residential", "thermal uses services"] + total_heat = df[subset].sum(axis=1) + df["district heat share"] = district_heat.div(total_heat) - return totals.T + if year: + df = df.xs(int(year), level='year') + + return df def build_energy_totals(countries, eurostat, swiss, idees): From ba8b3f9ce71ab40a610d6c03c39986ad47e877f0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 23 Jul 2022 17:05:07 +0200 Subject: [PATCH 051/591] energy_totals: combined energy totals for all years --- Snakefile | 1 + scripts/build_energy_totals.py | 87 +++++++++++++++++++++------------- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/Snakefile b/Snakefile index fa2323f8..04356842 100644 --- a/Snakefile +++ b/Snakefile @@ -243,6 +243,7 @@ rule build_energy_totals: district_heat_share='data/district_heat_share.csv', eurostat=directory("data/eurostat-energy_balances-june_2021_edition"), output: + energy_name_full='resources/energy_totals_full.csv', energy_name='resources/energy_totals.csv', co2_name='resources/co2_totals.csv', transport_name='resources/transport_data.csv' diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 1845c93c..18f9ee6e 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -125,21 +125,25 @@ def build_eurostat(countries, year=None): # convert ktoe/a to TWh/a df *= 11.63 / 1e3 + df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1) + if year: - df = df.xs(str(year), level='year') + df = df.xs(year, level='year') return df def build_swiss(year=None): - """Return a pd.Series of Swiss energy data in TWh/a""" + """Return a pd.DataFrame of Swiss energy data in TWh/a""" fn = snakemake.input.swiss - df = pd.read_csv(fn, index_col=[0,1]).loc["CH"] + df = pd.read_csv(fn, index_col=[0,1]).stack().unstack('item') + df.index.names = ["country", "year"] + df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1) if year: - df = df[str(year)] + df = df.xs(year, level='year') # convert PJ/a to TWh/a df /= 3.6 @@ -373,6 +377,8 @@ def build_idees(countries, year=None): if year: df = df.xs(int(year), level='year') + df.columns.name = 'item' + return df @@ -391,15 +397,21 @@ def build_energy_totals(countries, eurostat, swiss, idees): ) to_drop = ["passenger cars", "passenger car efficiency"] - df = idees.reindex(countries).drop(to_drop, axis=1) + + new_index = pd.MultiIndex.from_product( + [countries, eurostat.index.levels[1]], + names=["country", "year"] + ) + + df = idees.reindex(new_index).drop(to_drop, axis=1) eurostat_countries = eurostat.index.levels[0] - in_eurostat = df.index.intersection(eurostat_countries) + in_eurostat = df.index.levels[0].intersection(eurostat_countries) # add international navigation - slicer = idx[in_eurostat, :, "International maritime bunkers", :] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum() + slicer = idx[in_eurostat, :, :, "International maritime bunkers", :] + fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum() df.loc[in_eurostat, "total international navigation"] = fill_values # add swiss energy data @@ -409,17 +421,20 @@ def build_energy_totals(countries, eurostat, swiss, idees): # get values for missing countries based on Eurostat EnergyBalances # divide cooking/space/water according to averages in EU28 - missing = df.index[df["total residential"].isna()] - to_fill = missing.intersection(eurostat_countries) + to_fill = df.index[df["total residential"].isna() & df.index.get_level_values('country').isin(eurostat_countries)] uses = ["space", "cooking", "water"] + c = to_fill.get_level_values('country') + y = to_fill.get_level_values('year') + for sector in ["residential", "services", "road", "rail"]: # fuel use for fuel in ["electricity", "total"]: - slicer = idx[to_fill, :, :, eurostat_sectors[sector]] - fill_values = eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=0).sum() + + slicer = idx[c, y, :, :, eurostat_sectors[sector]] + fill_values = eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=[0,1]).sum() df.loc[to_fill, f"{fuel} {sector}"] = fill_values for sector in ["residential", "services"]: @@ -462,28 +477,28 @@ def build_energy_totals(countries, eurostat, swiss, idees): nonelectric_use = no_norway[f"total {sector} {use}"] - no_norway[f"electricity {sector} {use}"] nonelectric = no_norway[f"total {sector}"] - no_norway[f"electricity {sector}"] fraction = nonelectric_use.div(nonelectric).mean() - df.loc["NO", f"total {sector} {use}"] = total_heating * fraction - df.loc["NO", f"electricity {sector} {use}"] = total_heating * fraction * elec_fraction + df.loc["NO", f"total {sector} {use}"] = (total_heating * fraction).values + df.loc["NO", f"electricity {sector} {use}"] = (total_heating * fraction * elec_fraction).values # Missing aviation - slicer = idx[to_fill, :, :, "Domestic aviation"] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum() + slicer = idx[c, y, :, :, "Domestic aviation"] + fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum() df.loc[to_fill, "total domestic aviation"] = fill_values - slicer = idx[to_fill, :, "International aviation", :] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum() + slicer = idx[c, y, :, "International aviation", :] + fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum() df.loc[to_fill, "total international aviation"] = fill_values # missing domestic navigation - slicer = idx[to_fill, :, :, "Domestic navigation"] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum() + slicer = idx[c, y, :, :, "Domestic navigation"] + fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum() df.loc[to_fill, "total domestic navigation"] = fill_values # split road traffic for non-IDEES missing = df.index[df["total passenger cars"].isna()] - for fuel in ["total", "electricity"]: + for fuel in ["electricity", "total"]: selection = [ f"{fuel} passenger cars", f"{fuel} other road passenger", @@ -525,19 +540,20 @@ def build_energy_totals(countries, eurostat, swiss, idees): df.loc[missing, f"total aviation {purpose}"] = df.loc[missing, attrs].sum(axis=1) if "BA" in df.index: - # fill missing data for BA (services and road energy data) - # proportional to RS with ratio of total residential demand - missing = df.loc["BA"] == 0.0 - ratio = df.at["BA", "total residential"] / df.at["RS", "total residential"] - df.loc['BA', missing] = ratio * df.loc["RS", missing] + # fill missing data for BA proportional to RS + ratio = (df.loc["BA"].loc[2014:2020] / df.loc["RS"].loc[2014:2020]).mean() + df.loc["BA"] = (ratio * df.loc["RS"]).values # Missing district heating share dh_share = pd.read_csv(snakemake.input.district_heat_share, - index_col=0, usecols=[0, 1]) + index_col=0, usecols=[0, 1]) + + dh_share = pd.concat({y: dh_share for y in range(1990, 2021)}, names=["year", "country"]).swaplevel() + dh_share = dh_share.div(100).reindex(df.index) + # make conservative assumption and take minimum from both data sets - df["district heat share"] = (pd.concat([df["district heat share"], - dh_share.reindex(index=df.index)/100], - axis=1).min(axis=1)) + item = "district heat share" + df[item] = pd.concat([dh_share, df[item]], axis=1).min(axis=1) return df @@ -673,6 +689,7 @@ if __name__ == "__main__": snakemake = mock_snakemake('build_energy_totals') config = snakemake.config["energy"] + data_year = int(config["energy_totals_year"]) nuts3 = gpd.read_file(snakemake.input.nuts3_shapes).set_index("index") population = nuts3["pop"].groupby(nuts3.country).sum() @@ -680,12 +697,14 @@ if __name__ == "__main__": countries = population.index idees_countries = countries.intersection(eu28) - data_year = config["energy_totals_year"] - eurostat = build_eurostat(countries.difference(['CH']), data_year) - swiss = build_swiss(data_year) - idees = build_idees(idees_countries, data_year) + eurostat = build_eurostat(countries.difference(['CH'])) + swiss = build_swiss() + idees = build_idees(idees_countries) energy = build_energy_totals(countries, eurostat, swiss, idees) + energy.to_csv(snakemake.output.energy_name_full) + + energy = energy.xs(data_year, level='year') energy.to_csv(snakemake.output.energy_name) base_year_emissions = config["base_emissions_year"] From f70f006a47d65bcef63ef62b569dc7bd9a9032c0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 23 Jul 2022 17:05:56 +0200 Subject: [PATCH 052/591] energy_totals: co2 calculation with eurostat 2021 data --- scripts/build_energy_totals.py | 41 ++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 18f9ee6e..5482ec3b 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -606,23 +606,26 @@ def build_eea_co2(year=1990): return emissions / 1e3 -def build_eurostat_co2(countries, year=1990): +def build_eurostat_co2(countries, eurostat=None, year=1990): - eurostat = build_eurostat(countries, year) + if eurostat is None: + df = build_eurostat(countries, year) + else: + df = eurostat.xs(year, level='year') - specific_emissions = pd.Series(index=eurostat.columns, dtype=float) + specific_emissions = pd.Series(index=df.columns, dtype=float) # emissions in tCO2_equiv per MWh_th - specific_emissions["Solid fuels"] = 0.36 # Approximates coal - specific_emissions["Oil (total)"] = 0.285 # Average of distillate and residue - specific_emissions["Gas"] = 0.2 # For natural gas + specific_emissions["Solid fossil fuels"] = 0.36 # Approximates coal + specific_emissions["Oil and petroleum products"] = 0.285 # Average of distillate and residue + specific_emissions["Natural gas"] = 0.2 # For natural gas # oil values from https://www.eia.gov/tools/faqs/faq.cfm?id=74&t=11 # Distillate oil (No. 2) 0.276 # Residual oil (No. 6) 0.298 # https://www.eia.gov/electricity/annual/html/epa_a_03.html - return eurostat.multiply(specific_emissions).sum(axis=1) + return df.multiply(specific_emissions).sum(axis=1) def build_co2_totals(countries, eea_co2, eurostat_co2): @@ -632,19 +635,19 @@ def build_co2_totals(countries, eea_co2, eurostat_co2): for ct in countries.intersection(["BA", "RS", "AL", "ME", "MK"]): mappings = { - "electricity": (ct, "+", "Conventional Thermal Power Stations", "of which From Coal"), - "residential non-elec": (ct, "+", "+", "Residential"), - "services non-elec": (ct, "+", "+", "Services"), - "road non-elec": (ct, "+", "+", "Road"), - "rail non-elec": (ct, "+", "+", "Rail"), - "domestic navigation": (ct, "+", "+", "Domestic Navigation"), - "international navigation": (ct, "-", "Bunkers"), - "domestic aviation": (ct, "+", "+", "Domestic aviation"), - "international aviation": (ct, "+", "+", "International aviation"), + "electricity": (ct, "Transformation input", "Electricity & heat generation", "Main"), + "residential non-elec": (ct, "Final energy consumption", "Other sectors", "Households"), + "services non-elec": (ct, "Final energy consumption", "Other sectors", "Commercial & public services"), + "road non-elec": (ct, "Final energy consumption", "Transport sector", "Road"), + "rail non-elec": (ct, "Final energy consumption", "Transport sector", "Rail"), + "domestic navigation": (ct, "Final energy consumption", "Transport sector", "Domestic navigation"), + "international navigation": (ct, "Main", "International maritime bunkers"), + "domestic aviation": (ct, "Final energy consumption", "Transport sector", "Domestic aviation"), + "international aviation": (ct, "Main", "International aviation"), # does not include industrial process emissions or fuel processing/refining - "industrial non-elec": (ct, "+", "Industry"), + "industrial non-elec": (ct, "Final energy consumption", "Industry sector", "Non-energy use in industry sector"), # does not include non-energy emissions - "agriculture": (eurostat_co2.index.get_level_values(0) == ct) & eurostat_co2.index.isin(["Agriculture / Forestry", "Fishing"], level=3), + "agriculture": (eurostat_co2.index.get_level_values(0) == ct) & eurostat_co2.index.isin(["Agriculture & forestry", "Fishing"], level=3), } for i, mi in mappings.items(): @@ -709,7 +712,7 @@ if __name__ == "__main__": base_year_emissions = config["base_emissions_year"] eea_co2 = build_eea_co2(base_year_emissions) - eurostat_co2 = build_eurostat_co2(countries, base_year_emissions) + eurostat_co2 = build_eurostat_co2(countries, eurostat, base_year_emissions) co2 = build_co2_totals(countries, eea_co2, eurostat_co2) co2.to_csv(snakemake.output.co2_name) From 614909201ac3ae2a725d23e54c54e90f09345e77 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 23 Jul 2022 17:06:14 +0200 Subject: [PATCH 053/591] energy_totals: transport sector requires specific year --- scripts/build_energy_totals.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 5482ec3b..04147bb8 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -717,5 +717,6 @@ if __name__ == "__main__": co2 = build_co2_totals(countries, eea_co2, eurostat_co2) co2.to_csv(snakemake.output.co2_name) - transport = build_transport_data(countries, population, idees) + idees_transport = idees.xs(data_year, level='year') + transport = build_transport_data(countries, population, idees_transport) transport.to_csv(snakemake.output.transport_name) From 96b599aedd291e2888f05c52209278e22291c3d2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 25 Jul 2022 11:52:51 +0200 Subject: [PATCH 054/591] use numpy instead of sklearn for regressino --- envs/environment.yaml | 1 - scripts/build_hydro_profile.py | 15 +++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/envs/environment.yaml b/envs/environment.yaml index f5cb9aae..8bd7428f 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -39,7 +39,6 @@ dependencies: - proj - fiona <= 1.18.20 # Till issue https://github.com/Toblerity/Fiona/issues/1085 is not solved - country_converter - - scikit-learn # Keep in conda environment when calling ipython - ipython diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index f56cb9e3..b8d2eec8 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -66,7 +66,7 @@ import atlite import geopandas as gpd import pandas as pd -from sklearn.linear_model import LinearRegression +from numpy.polynomial import Polynomial import country_converter as coco cc = coco.CountryConverter() @@ -138,17 +138,16 @@ def approximate_missing_eia_stats(eia_stats, runoff_fn, countries): for c in countries: - X = runoff_eia[c].values.reshape(-1, 1) - Y = eia_stats[c].values.reshape(-1, 1) + X = runoff_eia[c] + Y = eia_stats[c] to_predict = runoff.index.difference(eia_stats.index) - X_pred = runoff.loc[to_predict, c].values.reshape(-1, 1) + X_pred = runoff.loc[to_predict, c] - linear_regressor = LinearRegression() - linear_regressor.fit(X, Y) - Y_pred = linear_regressor.predict(X_pred) + p = Polynomial.fit(X, Y, 1) + Y_pred = p(X_pred) - eia_stats_approximated[c] = pd.Series(Y_pred.T[0], index=to_predict) + eia_stats_approximated[c] = pd.Series(Y_pred, index=to_predict) eia_stats_approximated = pd.DataFrame(eia_stats_approximated) return pd.concat([eia_stats, eia_stats_approximated]).sort_index() From 0bad2097b051c2bd34a00893ec30c04cd06b3372 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 25 Jul 2022 14:35:54 +0200 Subject: [PATCH 055/591] interpolate heat demands for years outside 2007-2015 --- Snakefile | 19 ++++-- data/era5-annual-HDD-per-country.csv | 34 ++++++++++ scripts/build_energy_totals.py | 3 - scripts/build_heat_totals.py | 63 +++++++++++++++++++ ...build_population_weighted_energy_totals.py | 21 ++++--- scripts/prepare_sector_network.py | 2 + 6 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 data/era5-annual-HDD-per-country.csv create mode 100644 scripts/build_heat_totals.py diff --git a/Snakefile b/Snakefile index 04356842..617d30f2 100644 --- a/Snakefile +++ b/Snakefile @@ -243,7 +243,6 @@ rule build_energy_totals: district_heat_share='data/district_heat_share.csv', eurostat=directory("data/eurostat-energy_balances-june_2021_edition"), output: - energy_name_full='resources/energy_totals_full.csv', energy_name='resources/energy_totals.csv', co2_name='resources/co2_totals.csv', transport_name='resources/transport_data.csv' @@ -253,6 +252,18 @@ rule build_energy_totals: script: 'scripts/build_energy_totals.py' +rule build_heat_totals: + input: + hdd="data/era5-annual-HDD-per-country.csv", + energy_totals="resources/energy_totals.csv", + output: + heat_totals="resources/heat_totals.csv" + threads: 1 + resources: mem_mb=2000 + benchmark: "benchmarks/build_heat_totals" + script: "scripts/build_heat_totals.py" + + rule build_biomass_potentials: input: enspreso_biomass=HTTP.remote("https://cidportal.jrc.ec.europa.eu/ftp/jrc-opendata/ENSPRESO/ENSPRESO_BIOMASS.xlsx", keep_local=True), @@ -435,9 +446,9 @@ else: rule build_population_weighted_energy_totals: input: - energy_totals='resources/energy_totals.csv', + totals='resources/{kind}_totals.csv', clustered_pop_layout="resources/pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" - output: "resources/pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv" + output: "resources/pop_weighted_{kind}_totals{weather_year}_s{simpl}_{clusters}.csv" threads: 1 resources: mem_mb=2000 script: "scripts/build_population_weighted_energy_totals.py" @@ -465,8 +476,8 @@ rule prepare_sector_network: input: overrides="data/override_component_attrs", network=pypsaeur('networks/elec{weather_year}_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc'), - energy_totals_name='resources/energy_totals.csv', pop_weighted_energy_totals="resources/pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv", + pop_weighted_heat_totals="resources/pop_weighted_heat_totals{weather_year}_s{simpl}_{clusters}.csv", transport_demand="resources/transport_demand{weather_year}_s{simpl}_{clusters}.csv", transport_data="resources/transport_data{weather_year}_s{simpl}_{clusters}.csv", avail_profile="resources/avail_profile{weather_year}_s{simpl}_{clusters}.csv", diff --git a/data/era5-annual-HDD-per-country.csv b/data/era5-annual-HDD-per-country.csv new file mode 100644 index 00000000..472257c6 --- /dev/null +++ b/data/era5-annual-HDD-per-country.csv @@ -0,0 +1,34 @@ +name,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021 +AL,56,58,65,67,55,70,58,59,61,54,54,62,62,62,68,59,60,57,57,58,61,57,64,60,61,61,54,63,57,65,63,58,61,57,57,58,61,62,56,53,67,62,62,53,61,61,60,60,56,58,57,53,61,58,65,64,55,55,54,53,58,58,50,46,54,50,54,47,49,50,54 +AT,374,416,379,422,419,449,387,393,378,389,367,437,425,406,424,376,385,400,409,413,394,407,408,379,384,400,380,414,405,428,397,384,377,411,420,406,409,378,369,372,415,373,383,334,380,416,371,373,368,343,371,337,370,370,384,362,333,340,351,388,337,353,358,302,324,336,347,315,320,322,358 +BE,95,105,94,102,109,113,91,97,88,89,84,111,114,100,100,91,94,101,102,101,96,102,101,90,97,97,92,103,108,105,99,94,96,99,112,107,108,85,84,83,101,92,94,82,89,110,90,89,84,79,89,78,89,90,87,86,76,87,87,107,75,90,99,69,81,88,82,81,80,71,89 +BG,283,294,334,367,295,363,306,283,320,268,277,303,324,313,323,259,297,292,320,286,300,306,323,303,296,314,287,310,293,326,301,312,295,306,326,313,333,320,276,272,332,303,318,266,307,335,325,303,273,275,284,272,322,277,298,296,259,266,266,273,313,295,258,250,261,265,281,261,232,250,277 +BA,144,164,167,183,158,194,157,157,152,143,141,173,180,176,176,155,162,157,165,165,163,154,170,156,153,168,145,170,153,176,163,154,157,159,167,160,166,158,146,139,174,152,162,143,157,171,156,158,147,132,145,130,156,146,164,148,134,132,139,147,144,147,133,113,137,134,144,128,125,127,141 +CH,214,225,210,226,221,240,211,215,203,214,200,234,231,214,229,213,217,219,225,227,217,221,224,213,216,220,208,219,220,229,216,208,208,227,224,217,217,200,202,200,217,204,208,183,206,217,195,205,203,192,200,189,199,204,209,193,187,194,193,213,179,196,204,178,181,189,191,174,184,176,197 +CZ,297,344,307,351,350,377,313,322,301,314,294,358,361,345,351,297,296,320,342,336,319,326,322,282,296,315,299,330,328,347,316,308,298,323,350,326,346,297,280,283,333,299,316,279,312,364,319,296,288,265,309,285,308,302,311,300,269,275,289,338,281,298,306,242,261,283,287,262,255,259,302 +DE,1254,1428,1237,1416,1484,1567,1282,1342,1229,1266,1183,1486,1528,1390,1399,1269,1211,1341,1447,1429,1300,1388,1356,1184,1258,1339,1221,1377,1433,1433,1348,1288,1273,1384,1492,1425,1491,1201,1156,1135,1367,1241,1312,1155,1295,1548,1288,1220,1172,1085,1250,1168,1269,1236,1239,1198,1072,1159,1202,1459,1112,1232,1305,992,1095,1188,1148,1092,1070,1019,1230 +DK,160,176,152,175,186,190,163,178,154,169,154,184,194,176,182,181,153,170,182,186,159,166,159,147,147,172,161,171,190,177,175,164,155,162,191,181,190,151,137,132,160,147,166,154,162,191,162,154,147,134,161,148,158,151,150,144,134,137,150,193,144,159,160,125,138,145,139,142,134,125,150 +ES,962,911,927,948,785,1092,934,848,821,890,742,952,981,967,949,878,890,839,933,899,971,961,943,931,928,928,797,906,887,911,793,787,807,920,860,891,781,783,684,767,911,852,889,724,627,759,605,735,796,750,757,677,746,813,856,714,776,785,736,856,673,810,830,649,684,722,688,768,708,672,728 +EE,297,310,283,297,321,336,278,310,281,305,253,298,323,292,306,324,283,310,333,317,285,285,289,256,245,327,302,324,299,313,289,278,260,271,328,294,332,281,232,240,257,257,285,288,265,306,281,278,262,235,273,271,278,270,270,260,250,230,268,315,253,286,259,254,225,261,255,254,235,209,270 +FI,3285,3442,3085,3179,3880,3819,3296,3626,3180,3386,3065,3513,3467,3329,3526,3873,3284,3693,3640,3494,3572,3178,3458,2963,3074,3691,3490,3743,3419,3607,3572,3331,3296,3192,3894,3516,3793,3402,2888,3075,3209,3163,3319,3341,3213,3343,3302,3468,3259,2915,3303,3307,3231,3159,2998,3101,3018,3009,3219,3604,2961,3351,2985,2983,2795,3030,3127,3061,3116,2726,3260 +FR,1430,1480,1422,1489,1396,1633,1338,1378,1240,1332,1196,1584,1630,1499,1471,1331,1408,1412,1473,1469,1475,1453,1545,1356,1462,1445,1312,1454,1502,1545,1396,1315,1424,1484,1599,1518,1520,1269,1237,1227,1501,1375,1389,1168,1280,1454,1222,1337,1263,1190,1299,1132,1294,1346,1376,1263,1199,1301,1277,1522,1060,1300,1408,1034,1143,1266,1236,1150,1165,1043,1279 +GB,906,934,809,901,925,935,813,890,787,849,825,1000,1046,912,970,917,839,874,894,869,805,880,862,842,838,851,863,873,972,880,896,823,824,838,923,944,903,801,764,746,859,824,857,793,794,886,738,752,745,771,816,726,751,743,748,734,706,790,777,930,707,832,841,683,759,769,720,764,750,725,764 +GR,166,162,210,211,160,215,184,169,196,164,172,182,184,192,199,162,185,176,171,164,184,185,195,186,188,190,160,186,172,191,184,192,190,179,174,180,194,193,176,165,206,197,195,161,179,191,192,180,167,177,174,164,191,172,184,189,161,158,155,143,188,179,148,136,165,150,164,139,146,148,156 +HR,116,140,140,155,137,166,131,132,122,119,114,149,158,152,144,124,133,129,143,138,137,131,144,124,124,139,121,140,130,149,133,132,130,133,148,141,144,128,118,114,143,123,138,115,126,145,132,129,124,106,120,109,135,127,140,123,109,110,116,130,123,123,118,92,114,116,119,111,102,105,119 +HU,236,291,282,321,289,333,272,273,246,248,235,288,321,309,298,244,272,268,293,283,276,264,283,244,255,281,267,287,271,311,272,282,265,274,313,294,305,274,243,238,299,262,288,240,271,310,291,272,267,232,269,243,300,267,289,265,229,230,243,275,267,259,250,198,235,251,255,234,211,228,259 +IE,216,215,191,208,213,211,190,204,184,205,195,234,250,208,232,210,216,213,222,214,190,226,204,213,198,211,210,205,239,212,209,204,201,211,229,241,217,200,192,192,209,209,213,201,195,219,180,186,191,204,206,189,192,193,187,188,173,202,204,241,192,205,210,186,205,199,184,200,191,194,189 +IT,652,683,660,700,615,778,640,653,616,631,587,715,726,674,710,665,655,656,682,672,678,639,695,659,655,670,604,681,675,729,684,645,657,695,688,671,676,630,616,610,712,626,650,555,623,639,578,618,619,563,585,546,629,612,675,597,548,568,590,637,562,602,587,481,541,528,570,529,540,520,577 +LT,344,371,342,368,368,405,318,353,329,346,303,355,386,362,371,354,322,365,401,372,330,345,339,312,289,388,348,370,370,382,342,326,301,326,393,352,397,335,275,272,313,311,336,329,325,377,335,325,306,274,323,313,328,324,325,316,299,277,316,366,305,332,314,298,273,308,296,302,267,252,327 +LU,8,9,8,9,10,10,8,9,8,8,7,10,10,9,9,8,8,9,9,9,9,9,9,8,9,9,8,9,10,10,9,9,9,9,10,10,10,8,8,8,9,8,9,8,8,10,8,8,8,7,8,7,8,8,8,8,7,8,8,9,7,8,9,6,7,8,8,7,7,7,8 +LV,383,402,372,394,407,439,351,391,361,384,326,386,420,385,402,401,360,401,434,407,361,372,371,337,316,424,385,411,392,411,372,357,330,354,425,379,428,362,300,301,334,337,366,366,348,402,365,358,334,302,353,346,357,352,354,337,324,300,346,402,330,365,342,329,297,337,330,328,297,272,351 +MK,64,66,74,79,66,79,67,66,71,63,64,72,73,70,77,66,69,66,67,67,70,67,75,69,70,69,62,72,66,73,71,69,70,67,69,67,70,71,65,63,76,68,69,59,69,70,71,68,64,65,65,62,69,64,70,68,60,59,61,59,67,66,56,53,61,58,62,54,55,57,63 +ME,40,43,45,48,41,50,42,42,42,39,39,44,45,45,48,43,43,42,42,43,43,41,44,43,42,45,39,45,42,46,45,41,43,42,42,41,44,44,42,39,47,43,43,38,43,44,42,43,39,39,40,37,42,41,45,43,38,38,38,38,39,40,36,32,37,36,39,34,35,35,39 +NL,113,126,110,121,130,137,108,118,107,107,104,132,141,121,120,114,105,119,124,122,111,120,116,104,111,116,107,120,133,122,118,112,110,118,134,127,130,99,99,94,119,106,113,102,109,138,111,102,97,93,106,98,109,103,100,100,87,102,103,131,93,108,117,82,95,104,96,98,93,85,105 +NO,3339,3541,3020,3307,3639,3731,3315,3547,3122,3353,3400,3807,3641,3496,3783,3951,3259,3533,3425,3431,3339,3128,3312,3028,3094,3405,3369,3436,3457,3380,3502,3181,3141,3117,3541,3359,3449,3200,2890,2848,3057,3032,3196,3207,3170,3301,3060,3203,3062,2878,3166,3028,2983,2943,2874,2828,2918,2954,3018,3442,2796,3157,2946,2754,2793,2859,2963,2930,2981,2711,3035 +PL,1249,1438,1294,1478,1446,1586,1279,1349,1269,1305,1215,1435,1527,1450,1467,1280,1193,1321,1504,1431,1293,1347,1314,1200,1184,1419,1270,1393,1431,1491,1336,1265,1178,1304,1494,1377,1507,1255,1077,1078,1312,1252,1310,1197,1302,1512,1326,1249,1171,1052,1268,1192,1296,1230,1262,1244,1117,1092,1220,1426,1177,1274,1251,1068,1063,1163,1158,1120,1019,1017,1252 +PT,107,103,99,109,80,131,106,93,93,97,78,106,104,115,103,98,103,97,112,110,115,116,106,109,109,109,99,139,107,102,89,90,95,104,99,108,85,89,75,87,104,96,104,85,66,88,62,82,96,90,90,78,87,97,103,90,91,91,84,96,80,101,100,81,79,87,79,96,81,72,78 +RO,736,811,883,948,822,968,810,789,826,731,744,826,890,867,873,706,791,776,858,792,787,798,838,782,752,855,772,836,780,880,801,811,763,807,917,815,882,827,710,700,846,801,848,701,806,869,842,805,740,710,760,721,844,754,799,780,684,695,695,757,793,781,709,662,681,721,720,690,624,648,740 +RS,222,252,273,300,249,313,248,249,254,231,226,270,283,271,274,233,253,243,267,254,251,246,272,242,243,265,233,265,241,273,251,255,244,253,275,256,268,254,231,220,275,243,263,223,250,270,259,250,237,217,234,217,262,238,265,247,217,214,222,229,251,244,214,192,222,223,232,211,197,212,234 +SK,178,210,195,217,208,228,192,193,185,185,178,208,213,211,219,179,187,192,203,200,192,188,195,178,178,197,188,204,193,215,191,190,180,193,212,198,207,187,172,173,202,186,191,171,186,204,193,184,177,162,184,174,190,184,191,182,163,161,170,188,175,179,174,142,161,170,176,157,152,158,180 +SI,61,72,67,73,69,78,65,66,62,61,59,75,75,73,73,62,65,67,71,69,67,68,71,62,61,69,62,71,68,74,67,65,65,69,73,71,71,63,59,58,70,61,63,55,61,71,63,62,62,54,59,55,65,63,67,61,54,57,57,65,58,59,59,46,55,57,58,53,52,53,61 +SE,3891,4219,3560,3919,4426,4488,3950,4223,3662,3988,3814,4451,4260,4021,4358,4613,3929,4280,4255,4254,4043,3806,3975,3634,3625,4238,4132,4314,4246,4287,4301,3913,3840,3819,4588,4139,4376,3931,3476,3446,3785,3695,3893,3991,3916,4073,3757,3950,3781,3446,3898,3778,3755,3769,3632,3561,3606,3590,3806,4397,3474,3935,3675,3452,3421,3635,3693,3705,3689,3247,3807 diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 04147bb8..d9763779 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -705,9 +705,6 @@ if __name__ == "__main__": idees = build_idees(idees_countries) energy = build_energy_totals(countries, eurostat, swiss, idees) - energy.to_csv(snakemake.output.energy_name_full) - - energy = energy.xs(data_year, level='year') energy.to_csv(snakemake.output.energy_name) base_year_emissions = config["base_emissions_year"] diff --git a/scripts/build_heat_totals.py b/scripts/build_heat_totals.py new file mode 100644 index 00000000..34d5dcdf --- /dev/null +++ b/scripts/build_heat_totals.py @@ -0,0 +1,63 @@ +"""Approximate heat demand for all weather years.""" + +import pandas as pd + +from itertools import product +from numpy.polynomial import Polynomial + +idx = pd.IndexSlice + + +def approximate_heat_demand(energy_totals, hdd): + + if isinstance(hdd, str): + hdd = pd.read_csv(hdd, index_col=0).T + hdd.index = hdd.index.astype(int) + + demands = {} + + for kind, sector in product(["total", "electricity"], ["services", "residential"]): + + row = idx[:, 2007:2015] + col = f"{kind} {sector} space" + demand = energy_totals.loc[row, col].unstack(0) + + demand_approx = {} + + for c in countries: + + Y = demand[c].dropna() + X = hdd.loc[Y.index, c] + + to_predict = hdd.index.difference(Y.index) + X_pred = hdd.loc[to_predict, c] + + p = Polynomial.fit(X, Y, 1) + Y_pred = p(X_pred) + + demand_approx[c] = pd.Series(Y_pred, index=to_predict) + + demand_approx = pd.DataFrame(demand_approx) + demand_approx = pd.concat([demand, demand_approx]).sort_index() + demands[f"{kind} {sector} space"] = demand_approx.groupby(demand_approx.index).sum() + + demands = pd.concat(demands).unstack().T.clip(lower=0) + demands.index.names = ["country", "year"] + + return demands + + +if __name__ == "__main__": + if 'snakemake' not in globals(): + from helper import mock_snakemake + snakemake = mock_snakemake('build_energy_totals') + + hdd = pd.read_csv(snakemake.input.hdd, index_col=0).T + + energy_totals = pd.read_csv(snakemake.input.energy_totals, index_col=[0,1]) + + countries = hdd.columns + + heat_demand = approximate_heat_demand(energy_totals, hdd) + + heat_demand.to_csv(snakemake.output.heat_totals) diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 938983d5..933a0417 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -1,4 +1,4 @@ -"""Build population-weighted energy totals.""" +"""Build population-weighted energy and heat totals.""" import pandas as pd @@ -7,16 +7,23 @@ if __name__ == '__main__': from helper import mock_snakemake snakemake = mock_snakemake( 'build_population_weighted_energy_totals', + weather_year='', simpl='', - clusters=48, + clusters=37, ) + config = snakemake.config["energy"] + data_year = int(config["energy_totals_year"]) + if snakemake.wildcards.weather_year and snakemake.wildcards.kind == 'heat': + data_year = int(snakemake.wildcards.weather_year) + pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) - energy_totals = pd.read_csv(snakemake.input.energy_totals, index_col=0) + totals = pd.read_csv(snakemake.input.totals, index_col=[0,1]) + totals = totals.xs(data_year, level='year') - nodal_energy_totals = energy_totals.loc[pop_layout.ct].fillna(0.) - nodal_energy_totals.index = pop_layout.index - nodal_energy_totals = nodal_energy_totals.multiply(pop_layout.fraction, axis=0) + nodal_totals = totals.loc[pop_layout.ct].fillna(0.) + nodal_totals.index = pop_layout.index + nodal_totals = nodal_totals.multiply(pop_layout.fraction, axis=0) - nodal_energy_totals.to_csv(snakemake.output[0]) + nodal_totals.to_csv(snakemake.output[0]) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 14e824c0..3f25251f 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -2359,6 +2359,8 @@ if __name__ == "__main__": snakemake.config['costs']['lifetime']) pop_weighted_energy_totals = pd.read_csv(snakemake.input.pop_weighted_energy_totals, index_col=0) + pop_weighted_heat_totals = pd.read_csv(snakemake.input.pop_weighted_heat_totals, index_col=0) + pop_weighted_energy_totals.update(pop_weighted_heat_totals) patch_electricity_network(n) From 88ec493b3ab405a3ba307075366490e844ba6723 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 25 Jul 2022 14:40:13 +0200 Subject: [PATCH 056/591] Snakefile: correct updated eurostat dataset publication year! --- Snakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index 617d30f2..1e53dc76 100644 --- a/Snakefile +++ b/Snakefile @@ -54,7 +54,7 @@ datafiles = [ "data/emobility/KFZ__count", "data/emobility/Pkw__count", "data/h2_salt_caverns_GWh_per_sqkm.geojson", - directory("data/eurostat-energy_balances-april_2022_edition"), + directory("data/eurostat-energy_balances-june_2021_edition"), directory("data/jrc-idees-2015"), ] From aff5e091957e87e793622402837368b15db2dc1b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 25 Jul 2022 17:04:56 +0200 Subject: [PATCH 057/591] hydro: store corrected eia stats --- Snakefile | 4 +++- scripts/build_hydro_profile.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Snakefile b/Snakefile index 34c77981..9e964115 100644 --- a/Snakefile +++ b/Snakefile @@ -234,7 +234,9 @@ rule build_hydro_profile: eia_hydro_capacity='data/eia_hydro_annual_capacity.csv', era5_runoff='data/era5-annual-runoff-per-country.csv', cutout=f"cutouts/{config['renewable']['hydro']['cutout']}.nc" if "hydro" in config["renewable"] else "config['renewable']['hydro']['cutout'] not configured", - output: 'resources/profile{weather_year}_hydro.nc' + output: + profile='resources/profile{weather_year}_hydro.nc', + eia_hydro='resources/eia_hydro_annual_generation.csv', log: "logs/build_hydro_profile{weather_year}.log" resources: mem_mb=5000 script: 'scripts/build_hydro_profile.py' diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index b8d2eec8..4a9fc409 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -180,6 +180,8 @@ if __name__ == "__main__": fn = snakemake.input.era5_runoff eia_stats = approximate_missing_eia_stats(eia_stats, fn, countries) + eia_stats.to_csv(snakemake.output.eia_hydro) + weather_year = snakemake.wildcards.weather_year norm_year = config_hydro.get('eia_norm_year') if norm_year: @@ -195,4 +197,4 @@ if __name__ == "__main__": if 'clip_min_inflow' in config_hydro: inflow = inflow.where(inflow > config_hydro['clip_min_inflow'], 0) - inflow.to_netcdf(snakemake.output[0]) + inflow.to_netcdf(snakemake.output.profile) From 4890277ea36dac6d03d27d6a97661439fb012f20 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 25 Jul 2022 17:47:22 +0200 Subject: [PATCH 058/591] hydro: add {weather_year} wildcard to all outputs --- Snakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index 9e964115..4674de2a 100644 --- a/Snakefile +++ b/Snakefile @@ -236,7 +236,7 @@ rule build_hydro_profile: cutout=f"cutouts/{config['renewable']['hydro']['cutout']}.nc" if "hydro" in config["renewable"] else "config['renewable']['hydro']['cutout'] not configured", output: profile='resources/profile{weather_year}_hydro.nc', - eia_hydro='resources/eia_hydro_annual_generation.csv', + eia_hydro='resources/eia_hydro_annual_generation{weather_year}.csv', log: "logs/build_hydro_profile{weather_year}.log" resources: mem_mb=5000 script: 'scripts/build_hydro_profile.py' From ea703d4588d52e11935d870af78f4bee20ad9dc7 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 26 Jul 2022 18:24:16 +0200 Subject: [PATCH 059/591] Snakefile: adjust memory requirements of jobs --- Snakefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Snakefile b/Snakefile index 4674de2a..91c48a00 100644 --- a/Snakefile +++ b/Snakefile @@ -88,7 +88,7 @@ rule build_powerplants: output: "resources/powerplants.csv" log: "logs/build_powerplants.log" threads: 1 - resources: mem_mb=500 + resources: mem_mb=2000 script: "scripts/build_powerplants.py" @@ -222,7 +222,7 @@ rule build_renewable_profiles: log: "logs/build_renewable_profile{weather_year}_{technology}.log" benchmark: "benchmarks/build_renewable_profiles{weather_year}_{technology}" threads: ATLITE_NPROCESSES - resources: mem_mb=ATLITE_NPROCESSES * 5000 + resources: mem_mb=ATLITE_NPROCESSES * 4000 wildcard_constraints: technology="(?!hydro).*" # Any technology other than hydro script: "scripts/build_renewable_profiles.py" @@ -238,7 +238,7 @@ rule build_hydro_profile: profile='resources/profile{weather_year}_hydro.nc', eia_hydro='resources/eia_hydro_annual_generation{weather_year}.csv', log: "logs/build_hydro_profile{weather_year}.log" - resources: mem_mb=5000 + resources: mem_mb=2000 script: 'scripts/build_hydro_profile.py' From aa9f047abbb3b646b1881095d748d7937750c5bc Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 29 Jul 2022 13:38:21 +0200 Subject: [PATCH 060/591] add option for artificial load 1951-2021, rather than OPSD --- Snakefile | 29 ++++++++++++----- config.default.yaml | 2 ++ config.tutorial.yaml | 2 ++ scripts/build_artificial_load_data.py | 47 +++++++++++++++++++++++++++ test/config.test1.yaml | 2 ++ 5 files changed, 73 insertions(+), 9 deletions(-) create mode 100755 scripts/build_artificial_load_data.py diff --git a/Snakefile b/Snakefile index 91c48a00..55ae3d20 100644 --- a/Snakefile +++ b/Snakefile @@ -67,18 +67,29 @@ if config['enable'].get('retrieve_databundle', True): log: "logs/retrieve_databundle.log" script: 'scripts/retrieve_databundle.py' +if config["enable"].get('retrieve_opsd_load_data', True): + rule retrieve_load_data: + input: HTTP.remote("data.open-power-system-data.org/time_series/2019-06-05/time_series_60min_singleindex.csv", keep_local=True, static=True) + output: "data/load_raw.csv" + run: move(input[0], output[0]) -rule retrieve_load_data: - input: HTTP.remote("data.open-power-system-data.org/time_series/2019-06-05/time_series_60min_singleindex.csv", keep_local=True, static=True) - output: "data/load_raw.csv" - run: move(input[0], output[0]) + rule build_load_data: + input: "data/load_raw.csv" + output: "resources/load{weather_year}.csv" + log: "logs/build_load_data{weather_year}.log" + script: 'scripts/build_load_data.py' +if config["enable"].get('retrieve_artificial_load_data', False): + rule retrieve_artificial_load_data: + input: HTTP.remote("https://sandbox.zenodo.org/record/1089549/files/demand_hourly.csv", keep_local=True, static=True) + output: "data/load_artificial_raw.csv" + run: move(input[0], output[0]) -rule build_load_data: - input: "data/load_raw.csv" - output: "resources/load{weather_year}.csv" - log: "logs/build_load_data{weather_year}.log" - script: 'scripts/build_load_data.py' + rule build_artificial_load_data: + input: "data/load_artificial_raw.csv" + output: "resources/load{weather_year}.csv" + log: "logs/build_artificial_load_data{weather_year}.log" + script: "scripts/build_artificial_load_data.py" rule build_powerplants: diff --git a/config.default.yaml b/config.default.yaml index 45d664a2..b79f2559 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -29,6 +29,8 @@ enable: retrieve_cost_data: true build_cutout: false retrieve_cutout: true + retrieve_opsd_load_data: true + retrieve_artificial_load_data: false build_natura_raster: false retrieve_natura_raster: true custom_busmap: false diff --git a/config.tutorial.yaml b/config.tutorial.yaml index 2217f581..fcf53d46 100755 --- a/config.tutorial.yaml +++ b/config.tutorial.yaml @@ -30,6 +30,8 @@ enable: retrieve_cost_data: true build_cutout: false retrieve_cutout: true + retrieve_opsd_load_data: true + retrieve_artificial_load_data: false build_natura_raster: false retrieve_natura_raster: true custom_busmap: false diff --git a/scripts/build_artificial_load_data.py b/scripts/build_artificial_load_data.py new file mode 100755 index 00000000..c03bf9da --- /dev/null +++ b/scripts/build_artificial_load_data.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2022 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT + +"""This rule downloads the load data""" + +import logging +logger = logging.getLogger(__name__) +from _helpers import configure_logging + +import pandas as pd + +if __name__ == "__main__": + + if 'snakemake' not in globals(): + from _helpers import mock_snakemake + snakemake = mock_snakemake('build_artificial_load_data', weather_year='') + + configure_logging(snakemake) + + weather_year = snakemake.wildcards.weather_year + if weather_year: + snapshots = dict( + start=weather_year, + end=str(int(weather_year)+1), + closed="left" + ) + else: + snapshots = snakemake.config['snapshots'] + snapshots = pd.date_range(freq='h', **snapshots) + + fixed_year = snakemake.config["load"].get("fixed_year", False) + years = slice(str(fixed_year), str(fixed_year)) if fixed_year else slice(snapshots[0], snapshots[-1]) + countries = snakemake.config['countries'] + + load = pd.read_csv( + snakemake.input[0], + index_col=0, + parse_dates=True + ).loc[snapshots, countries] + + assert not load.isna().any().any(), 'Load data contains nans.' + + if fixed_year: + load.index = load.index.map(lambda t: t.replace(year=snapshots.year[0])) + + load.to_csv(snakemake.output[0]) diff --git a/test/config.test1.yaml b/test/config.test1.yaml index 48b8216a..cfe7cf57 100755 --- a/test/config.test1.yaml +++ b/test/config.test1.yaml @@ -29,6 +29,8 @@ enable: retrieve_cost_data: true build_cutout: false retrieve_cutout: true + retrieve_opsd_load_data: true + retrieve_artificial_load_data: false build_natura_raster: false retrieve_natura_raster: true custom_busmap: false From ce8d50813313614a1df51609808b4629a992dba4 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 29 Jul 2022 14:06:07 +0200 Subject: [PATCH 061/591] reenable custom busmap --- Snakefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Snakefile b/Snakefile index 55ae3d20..0de698c9 100644 --- a/Snakefile +++ b/Snakefile @@ -299,6 +299,8 @@ rule cluster_network: regions_onshore="resources/regions_onshore_elec{weather_year}_s{simpl}.geojson", regions_offshore="resources/regions_offshore_elec{weather_year}_s{simpl}.geojson", busmap=ancient('resources/busmap_elec{weather_year}_s{simpl}.csv'), + custom_busmap=("data/custom_busmap_elec_s{simpl}_{clusters}.csv" + if config["enable"].get("custom_busmap", False) else []), tech_costs=COSTS output: network='networks/elec{weather_year}_s{simpl}_{clusters}.nc', From ee0c69727ffe365e6262e6683ec4f1e2346239a0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 29 Jul 2022 20:29:35 +0200 Subject: [PATCH 062/591] leap_days need to be filtered for daily data too in heat --- scripts/build_heat_demand.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/build_heat_demand.py b/scripts/build_heat_demand.py index 1e165c69..73e67633 100644 --- a/scripts/build_heat_demand.py +++ b/scripts/build_heat_demand.py @@ -25,9 +25,12 @@ if __name__ == '__main__': else: snapshots = snakemake.config['snapshots'] + drop_leap_day = snakemake.config["atlite"].get("drop_leap_day", False) time = pd.date_range(freq='h', **snapshots) - if snakemake.config["atlite"].get("drop_leap_day", False): + daily = pd.date_range(freq='D', **snapshots) + if drop_leap_day: time = time[~((time.month == 2) & (time.day == 29))] + daily = daily[~((daily.month == 2) & (daily.day == 29))] cutout = atlite.Cutout(cutout_name).sel(time=time) @@ -44,6 +47,6 @@ if __name__ == '__main__': M = I.T.dot(np.diag(I.dot(stacked_pop))) heat_demand = cutout.heat_demand( - matrix=M.T, index=clustered_regions.index) + matrix=M.T, index=clustered_regions.index).sel(time=daily) heat_demand.to_netcdf(snakemake.output[f"heat_demand_{area}"]) From d4fa922a2a6af9abb8df01f03de58661de0fe3f7 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 29 Jul 2022 21:19:26 +0200 Subject: [PATCH 063/591] drop_leap_days when aggregating snapshots --- scripts/prepare_sector_network.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 3f25251f..45bd9abb 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -571,7 +571,7 @@ def add_co2limit(n, Nyears=1., limit=0.): ) # TODO PyPSA-Eur merge issue -def average_every_nhours(n, offset): +def average_every_nhours(n, offset, drop_leap_day=False): logger.info(f'Resampling the network to {offset}') m = n.copy(with_time=False) @@ -590,6 +590,10 @@ def average_every_nhours(n, offset): else: pnl[k] = df.resample(offset).mean() + if drop_leap_day: + sns = m.snapshots[~((m.snapshots.month == 2) & (m.snapshots.day == 29))] + m.set_snapshots(sns) + return m @@ -2428,7 +2432,8 @@ if __name__ == "__main__": for o in opts: m = re.match(r'^\d+h$', o, re.IGNORECASE) if m is not None: - n = average_every_nhours(n, m.group(0)) + drop_leap_day = snakemake.config["atlite"].get("drop_leap_day", False) + n = average_every_nhours(n, m.group(0), drop_leap_day) break limit_type = "config" From 64e1ef895d894262dc722004b8d40259a184adeb Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 1 Aug 2022 11:55:31 +0200 Subject: [PATCH 064/591] add rules to solve operations with perfect and myopic foresight --- Snakefile | 37 ++++++ scripts/solve_network.py | 13 +- scripts/solve_operations_network.py | 126 ++++++++++++++++++ scripts/solve_operations_network_myopic.py | 143 +++++++++++++++++++++ 4 files changed, 314 insertions(+), 5 deletions(-) create mode 100644 scripts/solve_operations_network.py create mode 100644 scripts/solve_operations_network_myopic.py diff --git a/Snakefile b/Snakefile index 1e53dc76..981c340d 100644 --- a/Snakefile +++ b/Snakefile @@ -13,6 +13,7 @@ configfile: "config.yaml" wildcard_constraints: weather_year="[0-9]{4}|", + capacity_year="[0-9]{4}|", lv="[a-z0-9\.]+", simpl="[a-zA-Z0-9]*", clusters="[0-9]+m?", @@ -680,3 +681,39 @@ if config["foresight"] == "myopic": resources: mem_mb=config['solving']['mem'] benchmark: RDIR + "/benchmarks/solve_network/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}" script: "scripts/solve_network.py" + + +rule solve_operations_network: + input: + pre=RDIR + "/prenetworks/elec{weather_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + post=RDIR + "/postnetworks/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + output: "elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}.nc" + shadow: "shallow" + log: + solver=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", + python=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", + threads: 4 + resources: mem_mb=10000 + benchmark: RDIR + "/benchmarks/solve_operations_network/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" + script: "scripts/solve_operations_network.py" + + +def solved_previous_year(wildcards): + previous_year = int(wildcards.weather_year) - 1 + return RDIR + "/postnetworks/elec" + previous_year + "_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc" + + +rule solve_operations_network_myopic: + input: + pre=RDIR + "/prenetworks/elec{weather_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + post=RDIR + "/postnetworks/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + previous=solved_previous_year + output: "elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc" + shadow: "shallow" + log: + solver=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", + python=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", + threads: 4 + resources: mem_mb=10000 + benchmark: RDIR + "/benchmarks/solve_operations_network_myopic/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" + script: "scripts/solve_operations_network_myopic.py" diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 19ef5f52..4dd4d969 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -71,7 +71,7 @@ def prepare_network(n, solve_opts=None): df.where(df>solve_opts['clip_p_max_pu'], other=0., inplace=True) if solve_opts.get('load_shedding'): - n.add("Carrier", "Load") + n.add("Carrier", "load") n.madd("Generator", n.buses.index, " load", bus=n.buses.index, carrier='load', @@ -246,7 +246,7 @@ def extra_functionality(n, snapshots): add_co2_sequestration_limit(n, snapshots) -def solve_network(n, config, opts='', **kwargs): +def solve_network(n, config, opts='', snapshots=None, **kwargs): solver_options = config['solving']['solver'].copy() solver_name = solver_options.pop('name') cf_solving = config['solving']['options'] @@ -259,12 +259,15 @@ def solve_network(n, config, opts='', **kwargs): n.config = config n.opts = opts + if snapshots is None: + snapshots = n.snapshots + if cf_solving.get('skip_iterations', False): - network_lopf(n, solver_name=solver_name, solver_options=solver_options, + network_lopf(n, snapshots, solver_name=solver_name, solver_options=solver_options, extra_functionality=extra_functionality, keep_shadowprices=keep_shadowprices, **kwargs) else: - ilopf(n, solver_name=solver_name, solver_options=solver_options, + ilopf(n, snapshots, solver_name=solver_name, solver_options=solver_options, track_iterations=track_iterations, min_iterations=min_iterations, max_iterations=max_iterations, @@ -295,7 +298,7 @@ if __name__ == "__main__": if tmpdir is not None: from pathlib import Path Path(tmpdir).mkdir(parents=True, exist_ok=True) - opts = snakemake.wildcards.opts.split('-') + opts = snakemake.wildcards.sector_opts.split('-') solve_opts = snakemake.config['solving']['options'] fn = getattr(snakemake.log, 'memory', None) diff --git a/scripts/solve_operations_network.py b/scripts/solve_operations_network.py new file mode 100644 index 00000000..2021c7c9 --- /dev/null +++ b/scripts/solve_operations_network.py @@ -0,0 +1,126 @@ +"""Solve operations network.""" + + +import pypsa +import numpy as np + +from solve_network import solve_network, prepare_network +from helper import override_component_attrs + +import logging +logger = logging.getLogger(__name__) +pypsa.pf.logger.setLevel(logging.WARNING) + + +def set_parameters_from_optimized(n, n_optim): + lines_typed_i = n.lines.index[n.lines.type != ''] + n.lines.loc[lines_typed_i, 'num_parallel'] = \ + n_optim.lines['num_parallel'].reindex(lines_typed_i, fill_value=0.) + n.lines.loc[lines_typed_i, 's_nom'] = ( + np.sqrt(3) * n.lines['type'].map(n.line_types.i_nom) * + n.lines.bus0.map(n.buses.v_nom) * n.lines.num_parallel) + + lines_untyped_i = n.lines.index[n.lines.type == ''] + for attr in ('s_nom', 'r', 'x'): + n.lines.loc[lines_untyped_i, attr] = \ + n_optim.lines[attr].reindex(lines_untyped_i, fill_value=0.) + n.lines['s_nom_extendable'] = False + + links_dc_i = n.links.index[n.links.p_nom_extendable] + n.links.loc[links_dc_i, 'p_nom'] = \ + n_optim.links['p_nom_opt'].reindex(links_dc_i, fill_value=0.) + n.links.loc[links_dc_i, 'p_nom_extendable'] = False + + gen_extend_i = n.generators.index[n.generators.p_nom_extendable] + n.generators.loc[gen_extend_i, 'p_nom'] = \ + n_optim.generators['p_nom_opt'].reindex(gen_extend_i, fill_value=0.) + n.generators.loc[gen_extend_i, 'p_nom_extendable'] = False + + stor_units_extend_i = n.storage_units.index[n.storage_units.p_nom_extendable] + n.storage_units.loc[stor_units_extend_i, 'p_nom'] = \ + n_optim.storage_units['p_nom_opt'].reindex(stor_units_extend_i, fill_value=0.) + n.storage_units.loc[stor_units_extend_i, 'p_nom_extendable'] = False + + stor_extend_i = n.stores.index[n.stores.e_nom_extendable] + n.stores.loc[stor_extend_i, 'e_nom'] = \ + n_optim.stores['e_nom_opt'].reindex(stor_extend_i, fill_value=0.) + n.stores.loc[stor_extend_i, 'e_nom_extendable'] = False + + return n + + +def remove_unused_components(n, threshold=50): + logger.info("Remove assets that are barely used to speed things up.") + + for c in n.iterate_components({"Store", "Link", "Generator"}): + attr = "e_nom" if c.name == "Store" else "p_nom" + to_remove = c.df.loc[c.df[attr] < threshold].index + logger.info(f"Removing barely used {c.name}s:\n{to_remove}") + n.mremove(c.name, to_remove) + + return n + + +def add_load_shedding(n, voll=1e4): + logger.info("Add load shedding to all buses.") + + if "load" in n.generators.carrier.unique(): + to_remove = n.generators.query("carrier == 'load'").index + logger.info(f"Removing pre-existing load shedding:\n{to_remove}") + n.mremove("Generator", to_remove) + + n.madd("Generator", n.buses.index, + suffix=" load", + bus=n.buses.index, + carrier='load', + marginal_cost=voll, + p_nom=1e6 + ) + + return n + + +if __name__ == "__main__": + if 'snakemake' not in globals(): + from helper import mock_snakemake + snakemake = mock_snakemake( + 'solve_operations_network', + capacity_year=1952, + simpl='', + opts='', + clusters=37, + lv=2.0, + sector_opts='Co2L0-25H-T-H-B-I-A', + planning_horizons=2030, + weather_year=2013 + ) + + logging.basicConfig(filename=snakemake.log.python, + level=snakemake.config['logging_level']) + + tmpdir = snakemake.config['solving'].get('tmpdir') + if tmpdir is not None: + from pathlib import Path + Path(tmpdir).mkdir(parents=True, exist_ok=True) + + overrides = override_component_attrs(snakemake.input.overrides) + + n = pypsa.Network(snakemake.input.pre, override_component_attrs=overrides) + n_post = pypsa.Network(snakemake.input.post, override_component_attrs=overrides) + n = set_parameters_from_optimized(n, n_post) + del n_post + + n = remove_unused_components(n) + n = add_load_shedding(n) + + opts = snakemake.wildcards.sector_opts.split('-') + solve_opts = snakemake.config['solving']['options'] + solve_opts['skip_iterations'] = True + + n = prepare_network(n, solve_opts) + + n = solve_network(n, config=snakemake.config, opts=opts, + solver_dir=tmpdir, + solver_logfile=snakemake.log.solver) + + n.export_to_netcdf(snakemake.output[0]) diff --git a/scripts/solve_operations_network_myopic.py b/scripts/solve_operations_network_myopic.py new file mode 100644 index 00000000..a0e30b0a --- /dev/null +++ b/scripts/solve_operations_network_myopic.py @@ -0,0 +1,143 @@ +"""Solve myopic operations network.""" + + +import pypsa +import pandas as pd + +from solve_network import solve_network, prepare_network +from solve_operations_network import set_parameters_from_optimized, remove_unused_components, add_load_shedding +from helper import override_component_attrs + +import logging +logger = logging.getLogger(__name__) +pypsa.pf.logger.setLevel(logging.WARNING) + + +def prepare_myopic(n, config, store_soc, storage_unit_soc): + + n.stores.e_cyclic = False + n.storage_units.cyclic_state_of_charge = False + + biomass_stores = n.stores.carrier.str.isin(["solid biomass", "biogas"]) + biomass_potential = n.stores.loc[biomass_stores, "e_initial"] + + n.stores.e_initial = store_soc + n.storage_units.state_of_charge_initial = storage_unit_soc + + n.remove("GlobalConstraint", "CO2Limit") + n.stores.at["co2 atmosphere", "marginal_cost"] = -config["co2_price"] + + # handle co2 sequestration + assert sum(n.stores.carriers == "co2 stored") == 1, "Myopic operation not implemented for spatially resolved CO2 sequestration." + n.stores.at["co2 stored", 'e_nom'] = config['co2_sequestration_limit'] * 1e6 # t/a + + # reset co2 emissions + n.stores.loc[n.stores.carrier == 'co2 stored', "e_initial"] = 0. + n.stores.at["co2 atmosphere", "e_initial"] = 0. + + # replenish fossil gas and oil with 1000 TWh each + fossil_stores = n.stores.carrier.str.isin(["gas", "oil"]) + n.stores.loc[fossil_stores, 'e_initial'] = 1e9 + n.stores.loc[fossil_stores, 'e_nom'] = 10e9 + + # replenish annual solid biomass and biogas potentials + n.stores.loc[biomass_stores, "e_initial"] = biomass_potential + + # set storage bidding prices + # TODO bidding prices for Fischer-Tropsch, Methanation for H2? + bidding_prices = config["bidding_prices"] + for c in n.iterate_components({"Store", "Link", "StorageUnit"}): + c.df.marginal_cost.update(c.df.carrier.map(bidding_prices).dropna()) + + # deduct industry solid biomass + assert sum(n.stores.carriers == "solid biomass") == 1, "Myopic operation not implemented for spatially resolved solid biomass." + n.stores.at["EU solid biomass", "e_initial"] -= n.loads.at["solid biomass for industry", "p_set"] * 8760 + n.remove("Load", "solid biomass for industry") + + return n + + +def solve_network_myopic(n, config, opts='', **kwargs): + + rolling_horizon = config["operations"]["rolling_horizon"] + + freq = int(pd.infer_freq(n.snapshots)[:-1]) + window = rolling_horizon["window"] * 24 // freq + overlap = rolling_horizon["overlap"] * 24 // freq + kept = window - overlap + length = len(n.snapshots) + + assert kept > 0, f"Overlap ({overlap} days) must be smaller than windows ({window} days)." + + for i in range(length // kept): + + snapshots = n.snapshots[i * kept:(i + 1) * kept + overlap] + logger.info(f"Optimising operations from {snapshots[0]} to {snapshots[-1]}") + + n = solve_network(n, config, opts=opts, snapshots=snapshots, **kwargs) + + last_kept = n.snapshots[(i + 1) * kept - 1] + logger.info(f"Setting initial SOCs from {last_kept} for next iteration.\n") + + n.stores.e_initial = n.stores_t.e.loc[last_kept] + n.storage_units.state_of_charge_initial = n.storage_units_t.state_of_charge.loc[last_kept] + + return n + + +if __name__ == "__main__": + if 'snakemake' not in globals(): + from helper import mock_snakemake + snakemake = mock_snakemake( + 'solve_operations_network_myopic', + capacity_year=1952, + simpl='', + opts='', + clusters=37, + lv=2.0, + sector_opts='Co2L0-25H-T-H-B-I-A', + planning_horizons=2030, + weather_year=2013 + ) + + logging.basicConfig(filename=snakemake.log.python, + level=snakemake.config['logging_level']) + + tmpdir = snakemake.config['solving'].get('tmpdir') + if tmpdir is not None: + from pathlib import Path + Path(tmpdir).mkdir(parents=True, exist_ok=True) + + config = snakemake.config["operations"] + overrides = override_component_attrs(snakemake.input.overrides) + + n = pypsa.Network(snakemake.input.pre, override_component_attrs=overrides) + + n_post = pypsa.Network(snakemake.input.post, override_component_attrs=overrides) + n = set_parameters_from_optimized(n, n_post) + del n_post + + n_previous = pypsa.Network(snakemake.input.previous, override_component_attrs=overrides) + store_soc = n_previous.stores_t.e.iloc[-1] + storage_unit_soc = n_previous.storage_units_t.state_of_charge.iloc[-1] + del n_previous + + n = remove_unused_components(n) + n = add_load_shedding(n) + n = prepare_myopic(n, config, store_soc, storage_unit_soc) + + opts = snakemake.wildcards.sector_opts.split('-') + solve_opts = snakemake.config['solving']['options'] + solve_opts['skip_iterations'] = True + + n = prepare_network(n, solve_opts) + + n = solve_network_myopic( + n, + config=snakemake.config, + opts=opts, + solver_dir=tmpdir, + solver_logfile=snakemake.log.solver + ) + + n.export_to_netcdf(snakemake.output[0]) From 7554e4f47203fc7a8affea99ec83d0d45feacde4 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 1 Aug 2022 11:58:20 +0200 Subject: [PATCH 065/591] operations: adjust output file path --- Snakefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Snakefile b/Snakefile index 981c340d..79d78274 100644 --- a/Snakefile +++ b/Snakefile @@ -687,7 +687,7 @@ rule solve_operations_network: input: pre=RDIR + "/prenetworks/elec{weather_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", post=RDIR + "/postnetworks/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - output: "elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}.nc" + output: RDIR + "/operations/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}.nc" shadow: "shallow" log: solver=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", @@ -708,7 +708,7 @@ rule solve_operations_network_myopic: pre=RDIR + "/prenetworks/elec{weather_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", post=RDIR + "/postnetworks/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", previous=solved_previous_year - output: "elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc" + output: RDIR + "/operations/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc" shadow: "shallow" log: solver=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", From a58d67c6c12bb9389b79eb6102a49320c4a9d2af Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 1 Aug 2022 11:59:57 +0200 Subject: [PATCH 066/591] operations: add config options to config.default.yaml --- config.default.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/config.default.yaml b/config.default.yaml index 3e6f76a0..3f1637bf 100644 --- a/config.default.yaml +++ b/config.default.yaml @@ -385,6 +385,20 @@ solving: #feasopt_tolerance: 1.e-6 mem: 30000 #memory in MB; 20 GB enough for 50+B+I+H2; 100 GB for 181+B+I+H2 +operations: + rolling_horizon: + window: 10 # days + overlap: 8 # days + bidding_prices: # EUR/MW + H2 Electrolysis: -10 + H2 Fuel Cell: 200 + urban central water tanks charger: -10 + urban central water tanks discharger: 10 + hydro: 70 + solid biomass: 150 + biogas: 100 + co2_price: 500 # EUR/t + co2_sequestation_limit: 200 # Mt/a plotting: map: From 26b21144c67cb0f14ba1b9b3a50ab13973c7d483 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 1 Aug 2022 12:03:24 +0200 Subject: [PATCH 067/591] operations: add some comments on multiyear contiguity --- scripts/solve_operations_network_myopic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/solve_operations_network_myopic.py b/scripts/solve_operations_network_myopic.py index a0e30b0a..fae86cb7 100644 --- a/scripts/solve_operations_network_myopic.py +++ b/scripts/solve_operations_network_myopic.py @@ -21,9 +21,11 @@ def prepare_myopic(n, config, store_soc, storage_unit_soc): biomass_stores = n.stores.carrier.str.isin(["solid biomass", "biogas"]) biomass_potential = n.stores.loc[biomass_stores, "e_initial"] + # storage level contiguity across years n.stores.e_initial = store_soc n.storage_units.state_of_charge_initial = storage_unit_soc + # replace co2 limit with co2 price n.remove("GlobalConstraint", "CO2Limit") n.stores.at["co2 atmosphere", "marginal_cost"] = -config["co2_price"] @@ -44,7 +46,6 @@ def prepare_myopic(n, config, store_soc, storage_unit_soc): n.stores.loc[biomass_stores, "e_initial"] = biomass_potential # set storage bidding prices - # TODO bidding prices for Fischer-Tropsch, Methanation for H2? bidding_prices = config["bidding_prices"] for c in n.iterate_components({"Store", "Link", "StorageUnit"}): c.df.marginal_cost.update(c.df.carrier.map(bidding_prices).dropna()) From 574b77fcc3dcd7f97bbccc71917a14ad2fc7695f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 1 Aug 2022 12:11:41 +0200 Subject: [PATCH 068/591] operations: add final iteration until end-of-year --- scripts/solve_operations_network_myopic.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/solve_operations_network_myopic.py b/scripts/solve_operations_network_myopic.py index fae86cb7..c403465f 100644 --- a/scripts/solve_operations_network_myopic.py +++ b/scripts/solve_operations_network_myopic.py @@ -83,6 +83,10 @@ def solve_network_myopic(n, config, opts='', **kwargs): n.stores.e_initial = n.stores_t.e.loc[last_kept] n.storage_units.state_of_charge_initial = n.storage_units_t.state_of_charge.loc[last_kept] + # final segment until end of year + snapshots = n.snapshots[(i + 1) * kept - 1:] + n = solve_network(n, config, opts=opts, snapshots=snapshots, **kwargs) + return n From 26e7e1246b7e748f1a3d3093d1fa9160ab925f9f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 1 Aug 2022 12:14:45 +0200 Subject: [PATCH 069/591] operations: final iteration one step later --- scripts/solve_operations_network_myopic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/solve_operations_network_myopic.py b/scripts/solve_operations_network_myopic.py index c403465f..0591ee70 100644 --- a/scripts/solve_operations_network_myopic.py +++ b/scripts/solve_operations_network_myopic.py @@ -84,7 +84,7 @@ def solve_network_myopic(n, config, opts='', **kwargs): n.storage_units.state_of_charge_initial = n.storage_units_t.state_of_charge.loc[last_kept] # final segment until end of year - snapshots = n.snapshots[(i + 1) * kept - 1:] + snapshots = n.snapshots[(i + 1) * kept:] n = solve_network(n, config, opts=opts, snapshots=snapshots, **kwargs) return n From a65cf7cac48c62371723c6d28d2dc8bef8370bcd Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 5 Aug 2022 17:44:08 +0200 Subject: [PATCH 070/591] make_summary: add weather_year wildcard to multiindex --- scripts/make_summary.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 8d5f4e48..358b7b5c 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -528,7 +528,7 @@ def make_summaries(networks_dict): columns = pd.MultiIndex.from_tuples( networks_dict.keys(), - names=["cluster", "lv", "opt", "planning_horizon"] + names=["weather_year", "cluster", "lv", "opt", "planning_horizon"] ) df = {} @@ -562,8 +562,9 @@ if __name__ == "__main__": snakemake = mock_snakemake('make_summary') networks_dict = { - (cluster, lv, opt+sector_opt, planning_horizon) : - snakemake.config['results_dir'] + snakemake.config['run'] + f'/postnetworks/elec_s{simpl}_{cluster}_lv{lv}_{opt}_{sector_opt}_{planning_horizon}.nc' \ + (weather_year, cluster, lv, opt+sector_opt, planning_horizon) : + snakemake.config['results_dir'] + snakemake.config['run'] + f'/postnetworks/elec{weather_year}_s{simpl}_{cluster}_lv{lv}_{opt}_{sector_opt}_{planning_horizon}.nc' \ + for weather_year in snakemake.config['scenario']['weather_year'] for simpl in snakemake.config['scenario']['simpl'] \ for cluster in snakemake.config['scenario']['clusters'] \ for opt in snakemake.config['scenario']['opts'] \ From c1a7a5476f0255716e2895bbf1849a4889d126c3 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 5 Aug 2022 17:44:31 +0200 Subject: [PATCH 071/591] plot_network: geomap for PyPSA 0.20 --- scripts/plot_network.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/plot_network.py b/scripts/plot_network.py index b9dd4567..9643cc44 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -307,7 +307,7 @@ def plot_h2_map(network): ) n.plot( - geomap=False, + # geomap=False, bus_sizes=0, link_colors='#72d3d6', link_widths=link_widths_retro, @@ -441,7 +441,7 @@ def plot_ch4_map(network): ) n.plot( - geomap=False, + # geomap=False, ax=ax, bus_sizes=0., link_colors='#e8d1d1', @@ -451,7 +451,7 @@ def plot_ch4_map(network): ) n.plot( - geomap=False, + # geomap=False, ax=ax, bus_sizes=0., link_colors=link_color_used, From b962f133d8d845b163c9f59f6ef4ad58c64d3df6 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 31 Aug 2022 15:19:44 +0200 Subject: [PATCH 072/591] add simpl wildcard to operation rules --- Snakefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Snakefile b/Snakefile index 79d78274..ee7c5815 100644 --- a/Snakefile +++ b/Snakefile @@ -685,9 +685,9 @@ if config["foresight"] == "myopic": rule solve_operations_network: input: - pre=RDIR + "/prenetworks/elec{weather_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - post=RDIR + "/postnetworks/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - output: RDIR + "/operations/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}.nc" + pre=RDIR + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + post=RDIR + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + output: RDIR + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}.nc" shadow: "shallow" log: solver=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", @@ -705,10 +705,10 @@ def solved_previous_year(wildcards): rule solve_operations_network_myopic: input: - pre=RDIR + "/prenetworks/elec{weather_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - post=RDIR + "/postnetworks/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + pre=RDIR + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + post=RDIR + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", previous=solved_previous_year - output: RDIR + "/operations/elec{capacity_year}_s_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc" + output: RDIR + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc" shadow: "shallow" log: solver=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", From 7a7c7f0344f6d92230599e170845ab3075438791 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 10 Sep 2022 19:48:40 +0200 Subject: [PATCH 073/591] add missing overrides to snakemake.input for operational rules --- Snakefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Snakefile b/Snakefile index ee7c5815..c11fba06 100644 --- a/Snakefile +++ b/Snakefile @@ -685,6 +685,7 @@ if config["foresight"] == "myopic": rule solve_operations_network: input: + overrides="data/override_component_attrs", pre=RDIR + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", post=RDIR + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", output: RDIR + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}.nc" @@ -705,6 +706,7 @@ def solved_previous_year(wildcards): rule solve_operations_network_myopic: input: + overrides="data/override_component_attrs", pre=RDIR + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", post=RDIR + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", previous=solved_previous_year From bb7e2e7dc9e5c49bbe611c6320bdc3e3bfe469ae Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Sep 2022 11:28:06 +0200 Subject: [PATCH 074/591] add reference to demand_hourly.csv on zenodo --- Snakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index 0de698c9..161da8a9 100644 --- a/Snakefile +++ b/Snakefile @@ -81,7 +81,7 @@ if config["enable"].get('retrieve_opsd_load_data', True): if config["enable"].get('retrieve_artificial_load_data', False): rule retrieve_artificial_load_data: - input: HTTP.remote("https://sandbox.zenodo.org/record/1089549/files/demand_hourly.csv", keep_local=True, static=True) + input: HTTP.remote("https://zenodo.org/record/7070438/files/demand_hourly.csv", keep_local=True, static=True) output: "data/load_artificial_raw.csv" run: move(input[0], output[0]) From e16fa286ec505cb18c1e9cad23034dffc16e9fd2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 29 Apr 2023 12:41:37 +0200 Subject: [PATCH 075/591] merge master --- doc/configtables/load.csv | 2 +- rules/collect.smk | 14 ++++++++++---- scripts/add_electricity.py | 23 +++++++++++------------ scripts/add_extra_components.py | 6 ++++-- scripts/build_cutout.py | 8 ++++---- scripts/build_electricity_demand.py | 16 +++++++++------- scripts/build_hydro_profile.py | 16 +++++++--------- scripts/build_renewable_profiles.py | 4 +++- scripts/cluster_network.py | 4 +++- scripts/prepare_network.py | 7 ++++++- 10 files changed, 58 insertions(+), 42 deletions(-) diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index 3eeb3a65..a206cc23 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -8,4 +8,4 @@ interpolate_limit,hours,integer,"Maximum gap size (consecutive nans) which inter time_shift_for_large_gaps,string,string,"Periods which are used for copying time-slices in order to fill large gaps of nans. Have to be valid ``pandas`` period strings." manual_adjustments,bool,"{true, false}","Whether to adjust the load data manually according to the function in :func:`manual_adjustment`." scaling_factor,--,float,"Global correction factor for the load time series." -fixed_year,--,Year or False,"To specify a fixed year for the load time series that deviates from the snapshots' year" \ No newline at end of file +fixed_year,--,Year or False,"To specify a fixed year for the load time series that deviates from the snapshots' year" diff --git a/rules/collect.smk b/rules/collect.smk index 603e665e..5092d67e 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -22,20 +22,25 @@ rule all: rule cluster_networks: input: - expand(RESOURCES + "networks/elec{weather_year}_s{simpl}_{clusters}.nc", **config["scenario"]), + expand( + RESOURCES + "networks/elec{weather_year}_s{simpl}_{clusters}.nc", + **config["scenario"] + ), rule extra_components_networks: input: expand( - RESOURCES + "networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc", **config["scenario"] + RESOURCES + "networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc", + **config["scenario"] ), rule prepare_elec_networks: input: expand( - RESOURCES + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + RESOURCES + + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config["scenario"] ), @@ -52,7 +57,8 @@ rule prepare_sector_networks: rule solve_elec_networks: input: expand( - RESULTS + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + RESULTS + + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config["scenario"] ), diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 0ecd415b..87c06aaf 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -701,19 +701,20 @@ def add_nice_carrier_names(n, config): n.carriers["color"] = colors - def drop_leap_day(n): - if not n.snapshots.is_leap_year.any(): return + if not n.snapshots.is_leap_year.any(): + return leap_days = (n.snapshots.day == 29) & (n.snapshots.month == 2) n.set_snapshots(n.snapshots[~leap_days]) - n.snapshot_weightings[:] = 8760/len(n.snapshots) + n.snapshot_weightings[:] = 8760 / len(n.snapshots) logger.info("Dropped February 29 from leap year.") if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('add_electricity', weather_year='') + + snakemake = mock_snakemake("add_electricity", weather_year="") configure_logging(snakemake) n = pypsa.Network(snakemake.input.base_network) @@ -721,15 +722,13 @@ if __name__ == "__main__": weather_year = snakemake.wildcards.weather_year if weather_year: snapshots = dict( - start=weather_year, - end=str(int(weather_year)+1), - closed="left" + start=weather_year, end=str(int(weather_year) + 1), closed="left" ) else: - snapshots = snakemake.config['snapshots'] - n.set_snapshots(pd.date_range(freq='h', **snapshots)) - - Nyears = n.snapshot_weightings.objective.sum() / 8760. + snapshots = snakemake.config["snapshots"] + n.set_snapshots(pd.date_range(freq="h", **snapshots)) + + Nyears = n.snapshot_weightings.objective.sum() / 8760.0 costs = load_costs( snakemake.input.tech_costs, @@ -855,7 +854,7 @@ if __name__ == "__main__": add_nice_carrier_names(n, snakemake.config) - if snakemake.config['enable'].get('drop_leap_days', True): + if snakemake.config["enable"].get("drop_leap_days", True): drop_leap_day(n) n.meta = snakemake.config diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index 8a3496e2..91abbad6 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -230,8 +230,10 @@ def attach_hydrogen_pipelines(n, costs, elec_opts): if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('add_extra_components', weather_year='', - simpl='', clusters=5) + + snakemake = mock_snakemake( + "add_extra_components", weather_year="", simpl="", clusters=5 + ) configure_logging(snakemake) n = pypsa.Network(snakemake.input.network) diff --git a/scripts/build_cutout.py b/scripts/build_cutout.py index 3ce15bc9..60da4f55 100644 --- a/scripts/build_cutout.py +++ b/scripts/build_cutout.py @@ -108,15 +108,15 @@ if __name__ == "__main__": cutout_params = snakemake.config["atlite"]["cutouts"][snakemake.wildcards.cutout] - if hasattr(snakemake.wildcards, 'weather_year'): + if hasattr(snakemake.wildcards, "weather_year"): time = snakemake.wildcards.weather_year cutout_params["time"] = [time, time] if "time" not in cutout_params: - snapshots = pd.date_range(freq='h', **snakemake.config['snapshots']) - cutout_params["time"] = [snapshots[0], snapshots[-1]] + snapshots = pd.date_range(freq="h", **snakemake.config["snapshots"]) + cutout_params["time"] = [snapshots[0], snapshots[-1]] - cutout_params['time'] = slice(*cutout_params['time']) + cutout_params["time"] = slice(*cutout_params["time"]) if {"x", "y", "bounds"}.isdisjoint(cutout_params): # Determine the bounds from bus regions with a buffer of two grid cells diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 6f16d336..4be46014 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -275,23 +275,25 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_electricity_demand", weather_year='') + snakemake = mock_snakemake("build_electricity_demand", weather_year="") configure_logging(snakemake) weather_year = snakemake.wildcards.weather_year if weather_year: snapshots = dict( - start=weather_year, - end=str(int(weather_year)+1), - closed="left" + start=weather_year, end=str(int(weather_year) + 1), closed="left" ) else: - snapshots = snakemake.config['snapshots'] - snapshots = pd.date_range(freq='h', **snapshots) + snapshots = snakemake.config["snapshots"] + snapshots = pd.date_range(freq="h", **snapshots) fixed_year = snakemake.config["load"].get("fixed_year", False) - years = slice(str(fixed_year), str(fixed_year)) if fixed_year else slice(snapshots[0], snapshots[-1]) + years = ( + slice(str(fixed_year), str(fixed_year)) + if fixed_year + else slice(snapshots[0], snapshots[-1]) + ) powerstatistics = snakemake.config["load"]["power_statistics"] interpolate_limit = snakemake.config["load"]["interpolate_limit"] diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 4996c501..708c0c8d 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -65,9 +65,8 @@ import atlite import country_converter as coco import geopandas as gpd import pandas as pd -from numpy.polynomial import Polynomial from _helpers import configure_logging - +from numpy.polynomial import Polynomial cc = coco.CountryConverter() @@ -132,11 +131,10 @@ def correct_eia_stats_by_capacity(eia_stats, fn, countries, baseyear=2019): eia_stats_corrected = eia_stats / ratio to_keep = ["AL", "AT", "CH", "DE", "GB", "NL", "RS", "RO", "SK"] to_correct = eia_stats_corrected.columns.difference(to_keep) - eia_stats.loc[:,to_correct] = eia_stats_corrected.loc[:,to_correct] + eia_stats.loc[:, to_correct] = eia_stats_corrected.loc[:, to_correct] def approximate_missing_eia_stats(eia_stats, runoff_fn, countries): - runoff = pd.read_csv(runoff_fn, index_col=0).T[countries] # fix ES, PT data points @@ -147,7 +145,6 @@ def approximate_missing_eia_stats(eia_stats, runoff_fn, countries): eia_stats_approximated = {} for c in countries: - X = runoff_eia[c] Y = eia_stats[c] @@ -168,7 +165,8 @@ logger = logging.getLogger(__name__) if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('build_hydro_profile', weather_year='') + + snakemake = mock_snakemake("build_hydro_profile", weather_year="") configure_logging(snakemake) config_hydro = snakemake.config["renewable"]["hydro"] @@ -185,18 +183,18 @@ if __name__ == "__main__": fn = snakemake.input.eia_hydro_generation eia_stats = get_eia_annual_hydro_generation(fn, countries) - if config_hydro.get('eia_correct_by_capacity'): + if config_hydro.get("eia_correct_by_capacity"): fn = snakemake.input.eia_hydro_capacity correct_eia_stats_by_capacity(eia_stats, fn, countries) - if config_hydro.get('eia_approximate_missing'): + if config_hydro.get("eia_approximate_missing"): fn = snakemake.input.era5_runoff eia_stats = approximate_missing_eia_stats(eia_stats, fn, countries) eia_stats.to_csv(snakemake.output.eia_hydro) weather_year = snakemake.wildcards.weather_year - norm_year = config_hydro.get('eia_norm_year') + norm_year = config_hydro.get("eia_norm_year") if norm_year: eia_stats.loc[weather_year] = eia_stats.loc[norm_year] elif weather_year and weather_year not in eia_stats.index: diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 43bc05a1..acdc46de 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -199,7 +199,9 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_renewable_profiles", technology="solar", weather_year="") + snakemake = mock_snakemake( + "build_renewable_profiles", technology="solar", weather_year="" + ) configure_logging(snakemake) nprocesses = int(snakemake.threads) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 0cb70069..95445caf 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -457,7 +457,9 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("cluster_network", simpl="", clusters="5", weather_year="") + snakemake = mock_snakemake( + "cluster_network", simpl="", clusters="5", weather_year="" + ) configure_logging(snakemake) n = pypsa.Network(snakemake.input.network) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index eba20033..72d13d2d 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -243,7 +243,12 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "prepare_network", weather_year="", simpl="", clusters="40", ll="v0.3", opts="Co2L-24H" + "prepare_network", + weather_year="", + simpl="", + clusters="40", + ll="v0.3", + opts="Co2L-24H", ) configure_logging(snakemake) From add135fe0527c2bf29cbfcbcf1639931fee057bb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 30 Apr 2023 08:52:58 +0000 Subject: [PATCH 076/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data/eia_hydro_annual_capacity.csv | 2 +- doc/configtables/hydro.csv | 2 +- rules/build_sector.smk | 2 +- scripts/build_artificial_load_data.py | 42 +++--- scripts/build_biomass_potentials.py | 4 +- scripts/build_clustered_population_layouts.py | 3 +- scripts/build_energy_totals.py | 16 ++- scripts/build_heat_demand.py | 11 +- scripts/build_heat_totals.py | 25 ++-- scripts/build_population_layouts.py | 6 +- ...build_population_weighted_energy_totals.py | 8 +- scripts/build_solar_thermal_profiles.py | 12 +- scripts/build_temperature_profiles.py | 8 +- scripts/build_transport_demand.py | 10 +- scripts/cluster_gas_network.py | 4 +- scripts/make_summary.py | 5 +- scripts/prepare_sector_network.py | 8 +- .../solve_operations_network_other_year.py | 125 ++++++++++-------- ...ve_operations_network_other_year_myopic.py | 103 +++++++++------ 19 files changed, 230 insertions(+), 166 deletions(-) diff --git a/data/eia_hydro_annual_capacity.csv b/data/eia_hydro_annual_capacity.csv index a95d71a4..e14697bc 100644 --- a/data/eia_hydro_annual_capacity.csv +++ b/data/eia_hydro_annual_capacity.csv @@ -47,4 +47,4 @@ Report generated on: 07-21-2022 16:15:18 "INTL.33-7-SWE-MK.A"," Sweden","14.859","14.919","15.215","15.29","15.445","15.69","15.813","15.996","16.112","15.759","15.904","15.891","16.021","15.867","16.072","15.725","15.776","16.371","16.169","16.432","16.506","16.523","16.187","16.098","16.302","16.302","16.234","16.592","16.352","16.544","16.624","16.478","16.315","16.395","15.897","16.23","16.367","16.403","16.332","16.332","16.379" "INTL.33-7-CHE-MK.A"," Switzerland","11.45","11.46","11.47","11.47","11.48","11.48","11.51","11.51","11.52","11.58","3.474","3.484","3.504","3.509","3.526","3.541","3.55","3.553","3.584","3.614","3.636","3.642","3.653","3.669","3.65","3.682","3.694","3.7","3.709","3.749","3.81","3.852","3.882","3.896","3.948","3.996","4.06","4.112","4.193","4.193","4.193" "INTL.33-7-TUR-MK.A"," Turkey","2.131","2.356","3.082","3.239","3.875","3.875","3.878","5.003","6.219","6.598","6.764","7.114","8.379","9.682","9.865","9.863","9.935","10.102","10.307","10.537","11.175","11.673","12.241","12.579","12.645","12.906","13.063","13.395","13.829","14.553","15.831","17.137","19.609","22.289","23.643","25.868","26.681","27.273","28.291","28.503","30.984" -"INTL.33-7-GBR-MK.A"," United Kingdom","2.451","2.451","2.451","2.721","4.188","4.19","4.192","4.197","4.196","1.424","1.11","1.415","1.423","1.425","1.425","1.432","1.455","1.488","1.475","1.477","1.485","1.629","1.59","1.486","1.499","1.501","1.515","1.522","1.626","1.638","1.637","1.673","1.693","1.709","1.73","1.777","1.836","1.873","1.878","1.878","1.879" \ No newline at end of file +"INTL.33-7-GBR-MK.A"," United Kingdom","2.451","2.451","2.451","2.721","4.188","4.19","4.192","4.197","4.196","1.424","1.11","1.415","1.423","1.425","1.425","1.432","1.455","1.488","1.475","1.477","1.485","1.629","1.59","1.486","1.499","1.501","1.515","1.522","1.626","1.638","1.637","1.673","1.693","1.709","1.73","1.777","1.836","1.873","1.878","1.878","1.879" diff --git a/doc/configtables/hydro.csv b/doc/configtables/hydro.csv index 6016e6f1..482671ad 100644 --- a/doc/configtables/hydro.csv +++ b/doc/configtables/hydro.csv @@ -6,4 +6,4 @@ hydro_max_hours,h,"Any of {float, 'energy_capacity_totals_by_country', 'estimate clip_min_inflow,MW,float,"To avoid too small values in the inflow time series, values below this threshold are set to zero." eia_norm_year,--,"Year in EIA hydro generation dataset; or False to disable","To specify a specific year by which hydro inflow is normed that deviates from the snapshots' year" eia_correct_by_capacity,--,boolean,"Correct EIA annual hydro generation data by installed capacity." -eia_approximate_missing,--,boolean,"Approximate hydro generation data for years not included in EIA dataset through a regression based on annual runoff." \ No newline at end of file +eia_approximate_missing,--,boolean,"Approximate hydro generation data for years not included in EIA dataset through a regression based on annual runoff." diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 30ce4095..38d5406f 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -262,7 +262,7 @@ rule build_heat_totals: resources: mem_mb=2000 log: LOGS + "build_heat_totals.log", - benchmark: + benchmark: BENCHMARKS + "build_heat_totals", conda: "../envs/environment.yaml" diff --git a/scripts/build_artificial_load_data.py b/scripts/build_artificial_load_data.py index d4d6449e..7703ff28 100755 --- a/scripts/build_artificial_load_data.py +++ b/scripts/build_artificial_load_data.py @@ -1,45 +1,47 @@ +# -*- coding: utf-8 -*- # SPDX-FileCopyrightText: 2022 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT - -"""This rule downloads the load data""" +""" +This rule downloads the load data. +""" import logging + logger = logging.getLogger(__name__) +import pandas as pd from _helpers import configure_logging -import pandas as pd - if __name__ == "__main__": - - if 'snakemake' not in globals(): + if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake('build_artificial_load_data', weather_year='') + + snakemake = mock_snakemake("build_artificial_load_data", weather_year="") configure_logging(snakemake) weather_year = snakemake.wildcards.weather_year if weather_year: snapshots = dict( - start=weather_year, - end=str(int(weather_year)+1), - inclusive="left" + start=weather_year, end=str(int(weather_year) + 1), inclusive="left" ) else: - snapshots = snakemake.config['snapshots'] - snapshots = pd.date_range(freq='h', **snapshots) + snapshots = snakemake.config["snapshots"] + snapshots = pd.date_range(freq="h", **snapshots) fixed_year = snakemake.config["load"].get("fixed_year", False) - years = slice(str(fixed_year), str(fixed_year)) if fixed_year else slice(snapshots[0], snapshots[-1]) - countries = snakemake.config['countries'] + years = ( + slice(str(fixed_year), str(fixed_year)) + if fixed_year + else slice(snapshots[0], snapshots[-1]) + ) + countries = snakemake.config["countries"] - load = pd.read_csv( - snakemake.input[0], - index_col=0, - parse_dates=True - ).loc[snapshots, countries] + load = pd.read_csv(snakemake.input[0], index_col=0, parse_dates=True).loc[ + snapshots, countries + ] - assert not load.isna().any().any(), 'Load data contains nans.' + assert not load.isna().any().any(), "Load data contains nans." if fixed_year: load.index = load.index.map(lambda t: t.replace(year=snapshots.year[0])) diff --git a/scripts/build_biomass_potentials.py b/scripts/build_biomass_potentials.py index dd22eed9..f87263b5 100644 --- a/scripts/build_biomass_potentials.py +++ b/scripts/build_biomass_potentials.py @@ -208,7 +208,9 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_biomass_potentials", weather_year="", simpl="", clusters="5") + snakemake = mock_snakemake( + "build_biomass_potentials", weather_year="", simpl="", clusters="5" + ) config = snakemake.config["biomass"] year = config["year"] diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index 174e9771..886f2489 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -25,7 +25,8 @@ if __name__ == "__main__": cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - if year: cutout_name = cutout_name.format(weather_year=year) + if year: + cutout_name = cutout_name.format(weather_year=year) cutout = atlite.Cutout(cutout_name) clustered_regions = ( diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 82a6cdb1..0eb5665c 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -73,7 +73,7 @@ to_ipcc = { def eurostat_per_country(country): - + country_fn = idees_rename.get(country, country) fn = snakemake.input.eurostat + f"/{country_fn}-Energy-balance-sheets-June-2021-edition.xlsb" @@ -91,7 +91,9 @@ def eurostat_per_country(country): def build_eurostat(countries, year=None): - """Return multi-index for all countries' energy data in TWh/a.""" + """ + Return multi-index for all countries' energy data in TWh/a. + """ nprocesses = snakemake.threads tqdm_kwargs = dict(ascii=False, unit=' country', total=len(countries), @@ -128,7 +130,9 @@ def build_eurostat(countries, year=None): def build_swiss(year=None): - """Return a pd.DataFrame of Swiss energy data in TWh/a""" + """ + Return a pd.DataFrame of Swiss energy data in TWh/a. + """ fn = snakemake.input.swiss @@ -350,7 +354,7 @@ def build_idees(countries, year=None): nprocesses = snakemake.threads disable_progress = snakemake.config["run"].get("disable_progressbar", False) - + func = partial(idees_per_country, year=year, base_dir=snakemake.input.idees) tqdm_kwargs = dict( ascii=False, @@ -359,7 +363,7 @@ def build_idees(countries, year=None): desc="Build from IDEES database", disable=disable_progress ) - + with mute_print(): with mp.Pool(processes=nprocesses) as pool: dfs = list(tqdm(pool.imap(func, countries), **tqdm_kwargs)) @@ -438,7 +442,7 @@ def build_energy_totals(countries, eurostat, swiss, idees): # fuel use for fuel in ["electricity", "total"]: - + slicer = idx[c, y, :, :, eurostat_sectors[sector]] fill_values = eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=[0,1]).sum() df.loc[to_fill, f"{fuel} {sector}"] = fill_values diff --git a/scripts/build_heat_demand.py b/scripts/build_heat_demand.py index fe039187..a52ad3d1 100644 --- a/scripts/build_heat_demand.py +++ b/scripts/build_heat_demand.py @@ -28,19 +28,18 @@ if __name__ == "__main__": cluster = LocalCluster(n_workers=nprocesses, threads_per_worker=1) client = Client(cluster, asynchronous=True) - cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year if year: - snapshots = dict(start=year, end=str(int(year)+1), inclusive="left") + snapshots = dict(start=year, end=str(int(year) + 1), inclusive="left") cutout_name = cutout_name.format(weather_year=year) else: - snapshots = snakemake.config['snapshots'] - + snapshots = snakemake.config["snapshots"] + drop_leap_day = snakemake.config["atlite"].get("drop_leap_day", False) - time = pd.date_range(freq='h', **snapshots) - daily = pd.date_range(freq='D', **snapshots) + time = pd.date_range(freq="h", **snapshots) + daily = pd.date_range(freq="D", **snapshots) if drop_leap_day: time = time[~((time.month == 2) & (time.day == 29))] daily = daily[~((daily.month == 2) & (daily.day == 29))] diff --git a/scripts/build_heat_totals.py b/scripts/build_heat_totals.py index 34d5dcdf..80f0fb30 100644 --- a/scripts/build_heat_totals.py +++ b/scripts/build_heat_totals.py @@ -1,15 +1,17 @@ -"""Approximate heat demand for all weather years.""" - -import pandas as pd +# -*- coding: utf-8 -*- +""" +Approximate heat demand for all weather years. +""" from itertools import product + +import pandas as pd from numpy.polynomial import Polynomial idx = pd.IndexSlice def approximate_heat_demand(energy_totals, hdd): - if isinstance(hdd, str): hdd = pd.read_csv(hdd, index_col=0).T hdd.index = hdd.index.astype(int) @@ -17,7 +19,6 @@ def approximate_heat_demand(energy_totals, hdd): demands = {} for kind, sector in product(["total", "electricity"], ["services", "residential"]): - row = idx[:, 2007:2015] col = f"{kind} {sector} space" demand = energy_totals.loc[row, col].unstack(0) @@ -25,7 +26,6 @@ def approximate_heat_demand(energy_totals, hdd): demand_approx = {} for c in countries: - Y = demand[c].dropna() X = hdd.loc[Y.index, c] @@ -39,22 +39,25 @@ def approximate_heat_demand(energy_totals, hdd): demand_approx = pd.DataFrame(demand_approx) demand_approx = pd.concat([demand, demand_approx]).sort_index() - demands[f"{kind} {sector} space"] = demand_approx.groupby(demand_approx.index).sum() + demands[f"{kind} {sector} space"] = demand_approx.groupby( + demand_approx.index + ).sum() demands = pd.concat(demands).unstack().T.clip(lower=0) demands.index.names = ["country", "year"] - + return demands if __name__ == "__main__": - if 'snakemake' not in globals(): + if "snakemake" not in globals(): from helper import mock_snakemake - snakemake = mock_snakemake('build_energy_totals') + + snakemake = mock_snakemake("build_energy_totals") hdd = pd.read_csv(snakemake.input.hdd, index_col=0).T - energy_totals = pd.read_csv(snakemake.input.energy_totals, index_col=[0,1]) + energy_totals = pd.read_csv(snakemake.input.energy_totals, index_col=[0, 1]) countries = hdd.columns diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index 62146443..40f313c6 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -20,8 +20,9 @@ import xarray as xr if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake + snakemake = mock_snakemake( - 'build_population_layouts', + "build_population_layouts", weather_year="", ) @@ -29,7 +30,8 @@ if __name__ == "__main__": cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year - if year: cutout_name = cutout_name.format(weather_year=year) + if year: + cutout_name = cutout_name.format(weather_year=year) cutout = atlite.Cutout(cutout_name) grid_cells = cutout.grid.geometry diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 607b9869..bc5f2d19 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -21,15 +21,15 @@ if __name__ == "__main__": config = snakemake.config["energy"] data_year = int(config["energy_totals_year"]) - if snakemake.wildcards.weather_year and snakemake.wildcards.kind == 'heat': + if snakemake.wildcards.weather_year and snakemake.wildcards.kind == "heat": data_year = int(snakemake.wildcards.weather_year) pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) - totals = pd.read_csv(snakemake.input.totals, index_col=[0,1]) - totals = totals.xs(data_year, level='year') + totals = pd.read_csv(snakemake.input.totals, index_col=[0, 1]) + totals = totals.xs(data_year, level="year") - nodal_totals = totals.loc[pop_layout.ct].fillna(0.) + nodal_totals = totals.loc[pop_layout.ct].fillna(0.0) nodal_totals.index = pop_layout.index nodal_totals = nodal_totals.multiply(pop_layout.fraction, axis=0) diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index 547074c3..dbca9b73 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -28,18 +28,18 @@ if __name__ == "__main__": cluster = LocalCluster(n_workers=nprocesses, threads_per_worker=1) client = Client(cluster, asynchronous=True) - config = snakemake.config['solar_thermal'] - + config = snakemake.config["solar_thermal"] + cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year if year: - snapshots = dict(start=year, end=str(int(year)+1), inclusive="left") + snapshots = dict(start=year, end=str(int(year) + 1), inclusive="left") cutout_name = cutout_name.format(weather_year=year) else: - snapshots = snakemake.config['snapshots'] - - time = pd.date_range(freq='h', **snapshots) + snapshots = snakemake.config["snapshots"] + + time = pd.date_range(freq="h", **snapshots) if snakemake.config["atlite"].get("drop_leap_day", False): time = time[~((time.month == 2) & (time.day == 29))] diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index 890a6a80..d5b58a94 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -31,12 +31,12 @@ if __name__ == "__main__": year = snakemake.wildcards.weather_year if year: - snapshots = dict(start=year, end=str(int(year)+1), inclusive="left") + snapshots = dict(start=year, end=str(int(year) + 1), inclusive="left") cutout_name = cutout_name.format(weather_year=year) else: - snapshots = snakemake.config['snapshots'] - - time = pd.date_range(freq='h', **snapshots) + snapshots = snakemake.config["snapshots"] + + time = pd.date_range(freq="h", **snapshots) if snakemake.config["atlite"].get("drop_leap_day", False): time = time[~((time.month == 2) & (time.day == 29))] diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index 3e059d91..a6a745de 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -163,7 +163,7 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_transport_demand", - weather_year='', + weather_year="", simpl="", clusters=48, ) @@ -179,8 +179,12 @@ if __name__ == "__main__": options = snakemake.config["sector"] year = snakemake.wildcards.weather_year - snapshots = dict(start=year, end=str(int(year)+1), inclusive="left") if year else snakemake.config['snapshots'] - snapshots = pd.date_range(freq='h', **snapshots, tz="UTC") + snapshots = ( + dict(start=year, end=str(int(year) + 1), inclusive="left") + if year + else snakemake.config["snapshots"] + ) + snapshots = pd.date_range(freq="h", **snapshots, tz="UTC") if snakemake.config["atlite"].get("drop_leap_day", False): leap_day = (snapshots.month == 2) & (snapshots.day == 29) snapshots = snapshots[~leap_day] diff --git a/scripts/cluster_gas_network.py b/scripts/cluster_gas_network.py index 1fd9d4f1..f1149ed5 100755 --- a/scripts/cluster_gas_network.py +++ b/scripts/cluster_gas_network.py @@ -108,7 +108,9 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("cluster_gas_network", weather_year="", simpl="", clusters="37") + snakemake = mock_snakemake( + "cluster_gas_network", weather_year="", simpl="", clusters="37" + ) logging.basicConfig(level=snakemake.config["logging"]["level"]) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index f0f614a2..1130f036 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -648,7 +648,8 @@ def make_summaries(networks_dict): ] columns = pd.MultiIndex.from_tuples( - networks_dict.keys(), names=["weather_year", "cluster", "ll", "opt", "planning_horizon"] + networks_dict.keys(), + names=["weather_year", "cluster", "ll", "opt", "planning_horizon"], ) df = {} @@ -688,7 +689,7 @@ if __name__ == "__main__": (weather_year, cluster, ll, opt + sector_opt, planning_horizon): "results/" + snakemake.params.RDIR + f"/postnetworks/elec_s{simpl}_{cluster}_l{ll}_{opt}_{sector_opt}_{planning_horizon}.nc" - for weather_year in snakemake.config['scenario']['weather_year'] + for weather_year in snakemake.config["scenario"]["weather_year"] for simpl in snakemake.config["scenario"]["simpl"] for cluster in snakemake.config["scenario"]["clusters"] for opt in snakemake.config["scenario"]["opts"] diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 85a16124..055fd57b 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3272,8 +3272,12 @@ if __name__ == "__main__": nyears, ) - pop_weighted_energy_totals = pd.read_csv(snakemake.input.pop_weighted_energy_totals, index_col=0) * nyears - pop_weighted_heat_totals = pd.read_csv(snakemake.input.pop_weighted_heat_totals, index_col=0) * nyears + pop_weighted_energy_totals = ( + pd.read_csv(snakemake.input.pop_weighted_energy_totals, index_col=0) * nyears + ) + pop_weighted_heat_totals = ( + pd.read_csv(snakemake.input.pop_weighted_heat_totals, index_col=0) * nyears + ) pop_weighted_energy_totals.update(pop_weighted_heat_totals) patch_electricity_network(n) diff --git a/scripts/solve_operations_network_other_year.py b/scripts/solve_operations_network_other_year.py index 643db050..9b4d853f 100644 --- a/scripts/solve_operations_network_other_year.py +++ b/scripts/solve_operations_network_other_year.py @@ -1,50 +1,62 @@ -"""Solve operations network.""" +# -*- coding: utf-8 -*- +""" +Solve operations network. +""" -import pypsa -import numpy as np - -from solve_network import solve_network, prepare_network -from helper import override_component_attrs - import logging + +import numpy as np +import pypsa +from helper import override_component_attrs +from solve_network import prepare_network, solve_network + logger = logging.getLogger(__name__) pypsa.pf.logger.setLevel(logging.WARNING) def set_parameters_from_optimized(n, n_optim): - lines_typed_i = n.lines.index[n.lines.type != ''] - n.lines.loc[lines_typed_i, 'num_parallel'] = \ - n_optim.lines['num_parallel'].reindex(lines_typed_i, fill_value=0.) - n.lines.loc[lines_typed_i, 's_nom'] = ( - np.sqrt(3) * n.lines['type'].map(n.line_types.i_nom) * - n.lines.bus0.map(n.buses.v_nom) * n.lines.num_parallel) + lines_typed_i = n.lines.index[n.lines.type != ""] + n.lines.loc[lines_typed_i, "num_parallel"] = n_optim.lines["num_parallel"].reindex( + lines_typed_i, fill_value=0.0 + ) + n.lines.loc[lines_typed_i, "s_nom"] = ( + np.sqrt(3) + * n.lines["type"].map(n.line_types.i_nom) + * n.lines.bus0.map(n.buses.v_nom) + * n.lines.num_parallel + ) - lines_untyped_i = n.lines.index[n.lines.type == ''] - for attr in ('s_nom', 'r', 'x'): - n.lines.loc[lines_untyped_i, attr] = \ - n_optim.lines[attr].reindex(lines_untyped_i, fill_value=0.) - n.lines['s_nom_extendable'] = False + lines_untyped_i = n.lines.index[n.lines.type == ""] + for attr in ("s_nom", "r", "x"): + n.lines.loc[lines_untyped_i, attr] = n_optim.lines[attr].reindex( + lines_untyped_i, fill_value=0.0 + ) + n.lines["s_nom_extendable"] = False links_dc_i = n.links.index[n.links.p_nom_extendable] - n.links.loc[links_dc_i, 'p_nom'] = \ - n_optim.links['p_nom_opt'].reindex(links_dc_i, fill_value=0.) - n.links.loc[links_dc_i, 'p_nom_extendable'] = False + n.links.loc[links_dc_i, "p_nom"] = n_optim.links["p_nom_opt"].reindex( + links_dc_i, fill_value=0.0 + ) + n.links.loc[links_dc_i, "p_nom_extendable"] = False gen_extend_i = n.generators.index[n.generators.p_nom_extendable] - n.generators.loc[gen_extend_i, 'p_nom'] = \ - n_optim.generators['p_nom_opt'].reindex(gen_extend_i, fill_value=0.) - n.generators.loc[gen_extend_i, 'p_nom_extendable'] = False + n.generators.loc[gen_extend_i, "p_nom"] = n_optim.generators["p_nom_opt"].reindex( + gen_extend_i, fill_value=0.0 + ) + n.generators.loc[gen_extend_i, "p_nom_extendable"] = False stor_units_extend_i = n.storage_units.index[n.storage_units.p_nom_extendable] - n.storage_units.loc[stor_units_extend_i, 'p_nom'] = \ - n_optim.storage_units['p_nom_opt'].reindex(stor_units_extend_i, fill_value=0.) - n.storage_units.loc[stor_units_extend_i, 'p_nom_extendable'] = False + n.storage_units.loc[stor_units_extend_i, "p_nom"] = n_optim.storage_units[ + "p_nom_opt" + ].reindex(stor_units_extend_i, fill_value=0.0) + n.storage_units.loc[stor_units_extend_i, "p_nom_extendable"] = False stor_extend_i = n.stores.index[n.stores.e_nom_extendable] - n.stores.loc[stor_extend_i, 'e_nom'] = \ - n_optim.stores['e_nom_opt'].reindex(stor_extend_i, fill_value=0.) - n.stores.loc[stor_extend_i, 'e_nom_extendable'] = False + n.stores.loc[stor_extend_i, "e_nom"] = n_optim.stores["e_nom_opt"].reindex( + stor_extend_i, fill_value=0.0 + ) + n.stores.loc[stor_extend_i, "e_nom_extendable"] = False return n @@ -68,39 +80,44 @@ def add_load_shedding(n, voll=1e4): to_remove = n.generators.query("carrier == 'load'").index logger.info(f"Removing pre-existing load shedding:\n{to_remove}") n.mremove("Generator", to_remove) - - n.madd("Generator", n.buses.index, + + n.madd( + "Generator", + n.buses.index, suffix=" load", bus=n.buses.index, - carrier='load', + carrier="load", marginal_cost=voll, - p_nom=1e6 + p_nom=1e6, ) return n if __name__ == "__main__": - if 'snakemake' not in globals(): + if "snakemake" not in globals(): from helper import mock_snakemake + snakemake = mock_snakemake( - 'solve_operations_network', + "solve_operations_network", capacity_year=1952, - simpl='', - opts='', + simpl="", + opts="", clusters=37, lv=2.0, - sector_opts='Co2L0-25H-T-H-B-I-A', + sector_opts="Co2L0-25H-T-H-B-I-A", planning_horizons=2030, - weather_year=2013 + weather_year=2013, ) - logging.basicConfig(filename=snakemake.log.python, - level=snakemake.config['logging_level']) + logging.basicConfig( + filename=snakemake.log.python, level=snakemake.config["logging_level"] + ) - tmpdir = snakemake.config['solving'].get('tmpdir') + tmpdir = snakemake.config["solving"].get("tmpdir") if tmpdir is not None: from pathlib import Path + Path(tmpdir).mkdir(parents=True, exist_ok=True) overrides = override_component_attrs(snakemake.input.overrides) @@ -113,14 +130,18 @@ if __name__ == "__main__": n = remove_unused_components(n) n = add_load_shedding(n) - opts = snakemake.wildcards.sector_opts.split('-') - solve_opts = snakemake.config['solving']['options'] - solve_opts['skip_iterations'] = True + opts = snakemake.wildcards.sector_opts.split("-") + solve_opts = snakemake.config["solving"]["options"] + solve_opts["skip_iterations"] = True n = prepare_network(n, solve_opts) - - n = solve_network(n, config=snakemake.config, opts=opts, - solver_dir=tmpdir, - solver_logfile=snakemake.log.solver) - - n.export_to_netcdf(snakemake.output[0]) \ No newline at end of file + + n = solve_network( + n, + config=snakemake.config, + opts=opts, + solver_dir=tmpdir, + solver_logfile=snakemake.log.solver, + ) + + n.export_to_netcdf(snakemake.output[0]) diff --git a/scripts/solve_operations_network_other_year_myopic.py b/scripts/solve_operations_network_other_year_myopic.py index 0591ee70..093b94eb 100644 --- a/scripts/solve_operations_network_other_year_myopic.py +++ b/scripts/solve_operations_network_other_year_myopic.py @@ -1,20 +1,26 @@ -"""Solve myopic operations network.""" +# -*- coding: utf-8 -*- +""" +Solve myopic operations network. +""" -import pypsa -import pandas as pd - -from solve_network import solve_network, prepare_network -from solve_operations_network import set_parameters_from_optimized, remove_unused_components, add_load_shedding -from helper import override_component_attrs - import logging + +import pandas as pd +import pypsa +from helper import override_component_attrs +from solve_network import prepare_network, solve_network +from solve_operations_network import ( + add_load_shedding, + remove_unused_components, + set_parameters_from_optimized, +) + logger = logging.getLogger(__name__) pypsa.pf.logger.setLevel(logging.WARNING) def prepare_myopic(n, config, store_soc, storage_unit_soc): - n.stores.e_cyclic = False n.storage_units.cyclic_state_of_charge = False @@ -30,17 +36,19 @@ def prepare_myopic(n, config, store_soc, storage_unit_soc): n.stores.at["co2 atmosphere", "marginal_cost"] = -config["co2_price"] # handle co2 sequestration - assert sum(n.stores.carriers == "co2 stored") == 1, "Myopic operation not implemented for spatially resolved CO2 sequestration." - n.stores.at["co2 stored", 'e_nom'] = config['co2_sequestration_limit'] * 1e6 # t/a + assert ( + sum(n.stores.carriers == "co2 stored") == 1 + ), "Myopic operation not implemented for spatially resolved CO2 sequestration." + n.stores.at["co2 stored", "e_nom"] = config["co2_sequestration_limit"] * 1e6 # t/a # reset co2 emissions - n.stores.loc[n.stores.carrier == 'co2 stored', "e_initial"] = 0. - n.stores.at["co2 atmosphere", "e_initial"] = 0. + n.stores.loc[n.stores.carrier == "co2 stored", "e_initial"] = 0.0 + n.stores.at["co2 atmosphere", "e_initial"] = 0.0 # replenish fossil gas and oil with 1000 TWh each fossil_stores = n.stores.carrier.str.isin(["gas", "oil"]) - n.stores.loc[fossil_stores, 'e_initial'] = 1e9 - n.stores.loc[fossil_stores, 'e_nom'] = 10e9 + n.stores.loc[fossil_stores, "e_initial"] = 1e9 + n.stores.loc[fossil_stores, "e_nom"] = 10e9 # replenish annual solid biomass and biogas potentials n.stores.loc[biomass_stores, "e_initial"] = biomass_potential @@ -51,15 +59,18 @@ def prepare_myopic(n, config, store_soc, storage_unit_soc): c.df.marginal_cost.update(c.df.carrier.map(bidding_prices).dropna()) # deduct industry solid biomass - assert sum(n.stores.carriers == "solid biomass") == 1, "Myopic operation not implemented for spatially resolved solid biomass." - n.stores.at["EU solid biomass", "e_initial"] -= n.loads.at["solid biomass for industry", "p_set"] * 8760 + assert ( + sum(n.stores.carriers == "solid biomass") == 1 + ), "Myopic operation not implemented for spatially resolved solid biomass." + n.stores.at["EU solid biomass", "e_initial"] -= ( + n.loads.at["solid biomass for industry", "p_set"] * 8760 + ) n.remove("Load", "solid biomass for industry") return n -def solve_network_myopic(n, config, opts='', **kwargs): - +def solve_network_myopic(n, config, opts="", **kwargs): rolling_horizon = config["operations"]["rolling_horizon"] freq = int(pd.infer_freq(n.snapshots)[:-1]) @@ -68,11 +79,12 @@ def solve_network_myopic(n, config, opts='', **kwargs): kept = window - overlap length = len(n.snapshots) - assert kept > 0, f"Overlap ({overlap} days) must be smaller than windows ({window} days)." + assert ( + kept > 0 + ), f"Overlap ({overlap} days) must be smaller than windows ({window} days)." - for i in range(length // kept): - - snapshots = n.snapshots[i * kept:(i + 1) * kept + overlap] + for i in range(length // kept): + snapshots = n.snapshots[i * kept : (i + 1) * kept + overlap] logger.info(f"Optimising operations from {snapshots[0]} to {snapshots[-1]}") n = solve_network(n, config, opts=opts, snapshots=snapshots, **kwargs) @@ -81,36 +93,41 @@ def solve_network_myopic(n, config, opts='', **kwargs): logger.info(f"Setting initial SOCs from {last_kept} for next iteration.\n") n.stores.e_initial = n.stores_t.e.loc[last_kept] - n.storage_units.state_of_charge_initial = n.storage_units_t.state_of_charge.loc[last_kept] + n.storage_units.state_of_charge_initial = n.storage_units_t.state_of_charge.loc[ + last_kept + ] # final segment until end of year - snapshots = n.snapshots[(i + 1) * kept:] + snapshots = n.snapshots[(i + 1) * kept :] n = solve_network(n, config, opts=opts, snapshots=snapshots, **kwargs) return n if __name__ == "__main__": - if 'snakemake' not in globals(): + if "snakemake" not in globals(): from helper import mock_snakemake + snakemake = mock_snakemake( - 'solve_operations_network_myopic', + "solve_operations_network_myopic", capacity_year=1952, - simpl='', - opts='', + simpl="", + opts="", clusters=37, lv=2.0, - sector_opts='Co2L0-25H-T-H-B-I-A', + sector_opts="Co2L0-25H-T-H-B-I-A", planning_horizons=2030, - weather_year=2013 + weather_year=2013, ) - logging.basicConfig(filename=snakemake.log.python, - level=snakemake.config['logging_level']) + logging.basicConfig( + filename=snakemake.log.python, level=snakemake.config["logging_level"] + ) - tmpdir = snakemake.config['solving'].get('tmpdir') + tmpdir = snakemake.config["solving"].get("tmpdir") if tmpdir is not None: from pathlib import Path + Path(tmpdir).mkdir(parents=True, exist_ok=True) config = snakemake.config["operations"] @@ -121,8 +138,10 @@ if __name__ == "__main__": n_post = pypsa.Network(snakemake.input.post, override_component_attrs=overrides) n = set_parameters_from_optimized(n, n_post) del n_post - - n_previous = pypsa.Network(snakemake.input.previous, override_component_attrs=overrides) + + n_previous = pypsa.Network( + snakemake.input.previous, override_component_attrs=overrides + ) store_soc = n_previous.stores_t.e.iloc[-1] storage_unit_soc = n_previous.storage_units_t.state_of_charge.iloc[-1] del n_previous @@ -131,18 +150,18 @@ if __name__ == "__main__": n = add_load_shedding(n) n = prepare_myopic(n, config, store_soc, storage_unit_soc) - opts = snakemake.wildcards.sector_opts.split('-') - solve_opts = snakemake.config['solving']['options'] - solve_opts['skip_iterations'] = True + opts = snakemake.wildcards.sector_opts.split("-") + solve_opts = snakemake.config["solving"]["options"] + solve_opts["skip_iterations"] = True n = prepare_network(n, solve_opts) - + n = solve_network_myopic( n, config=snakemake.config, opts=opts, solver_dir=tmpdir, - solver_logfile=snakemake.log.solver + solver_logfile=snakemake.log.solver, ) - + n.export_to_netcdf(snakemake.output[0]) From e8772c33401d8e5ba4290678d820b18004f0d6d4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 30 Apr 2023 08:54:48 +0000 Subject: [PATCH 077/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 70 +++++++++++++++++++++++++------------ rules/postprocess.smk | 3 +- rules/solve_electricity.smk | 20 +++++++---- rules/solve_myopic.smk | 15 +++++--- rules/solve_overnight.smk | 64 +++++++++++++++++++++++---------- 5 files changed, 119 insertions(+), 53 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 6a67a0da..fdaedab9 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -17,7 +17,8 @@ if config["enable"].get("prepare_links_p_nom", False): script: "../scripts/prepare_links_p_nom.py" -if config["enable"].get('retrieve_opsd_load_data', True): + +if config["enable"].get("retrieve_opsd_load_data", True): rule build_electricity_demand: input: @@ -33,15 +34,23 @@ if config["enable"].get('retrieve_opsd_load_data', True): script: "../scripts/build_electricity_demand.py" -if config["enable"].get('retrieve_artificial_load_data', False): + +if config["enable"].get("retrieve_artificial_load_data", False): rule build_artificial_load_data: - input: ancient("data/load_artificial_raw.csv") - output: RESOURCES + "load{weather_year}.csv" - log: LOGS + "build_artificial_load_data{weather_year}.log" - resources: mem_mb=5000, - conda: "../envs/environment.yaml" - script: "../scripts/build_artificial_load_data.py" + input: + ancient("data/load_artificial_raw.csv"), + output: + RESOURCES + "load{weather_year}.csv", + log: + LOGS + "build_artificial_load_data{weather_year}.log", + resources: + mem_mb=5000, + conda: + "../envs/environment.yaml" + script: + "../scripts/build_artificial_load_data.py" + rule build_powerplants: input: @@ -155,15 +164,22 @@ if config["enable"].get("build_cutout", False): "../scripts/build_cutout.py" rule build_cutout_year: - input: rules.build_cutout.input - output: protected("cutouts/" + CDIR + "{cutout}-{weather_year}.nc") - log: "logs/" + CDIR + "build_cutout/{cutout}-{weather_year}.log" - benchmark: "benchmarks/" + CDIR + "build_cutout_{cutout}-{weather_year}" + input: + rules.build_cutout.input, + output: + protected("cutouts/" + CDIR + "{cutout}-{weather_year}.nc"), + log: + "logs/" + CDIR + "build_cutout/{cutout}-{weather_year}.log", + benchmark: + "benchmarks/" + CDIR + "build_cutout_{cutout}-{weather_year}" threads: ATLITE_NPROCESSES - resources: mem_mb=ATLITE_NPROCESSES * 1000 + resources: + mem_mb=ATLITE_NPROCESSES * 1000, conda: "../envs/environment.yaml" - script: "../scripts/build_cutout.py" + script: + "../scripts/build_cutout.py" + if config["enable"].get("build_natura_raster", False): @@ -319,8 +335,10 @@ rule simplify_network: regions_offshore=RESOURCES + "regions_offshore.geojson", output: network=RESOURCES + "networks/elec{weather_year}_s{simpl}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}.geojson", - regions_offshore=RESOURCES + "regions_offshore_elec{weather_year}_s{simpl}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}.geojson", + regions_offshore=RESOURCES + + "regions_offshore_elec{weather_year}_s{simpl}.geojson", busmap=RESOURCES + "busmap_elec{weather_year}_s{simpl}.csv", connection_costs=RESOURCES + "connection_costs{weather_year}_s{simpl}.csv", log: @@ -339,8 +357,10 @@ rule simplify_network: rule cluster_network: input: network=RESOURCES + "networks/elec{weather_year}_s{simpl}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}.geojson", - regions_offshore=RESOURCES + "regions_offshore_elec{weather_year}_s{simpl}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}.geojson", + regions_offshore=RESOURCES + + "regions_offshore_elec{weather_year}_s{simpl}.geojson", busmap=ancient(RESOURCES + "busmap_elec{weather_year}_s{simpl}.csv"), custom_busmap=( "data/custom_busmap_elec_s{simpl}_{clusters}.csv" @@ -350,8 +370,10 @@ rule cluster_network: tech_costs=COSTS, output: network=RESOURCES + "networks/elec{weather_year}_s{simpl}_{clusters}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", - regions_offshore=RESOURCES + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions_offshore=RESOURCES + + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson", busmap=RESOURCES + "busmap_elec{weather_year}_s{simpl}_{clusters}.csv", linemap=RESOURCES + "linemap_elec{weather_year}_s{simpl}_{clusters}.csv", log: @@ -393,9 +415,13 @@ rule prepare_network: output: RESOURCES + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", log: - LOGS + "prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.log", + LOGS + + "prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.log", benchmark: - (BENCHMARKS + "prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}") + ( + BENCHMARKS + + "prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + ) threads: 1 resources: mem_mb=4000, diff --git a/rules/postprocess.smk b/rules/postprocess.smk index c855b022..0a3260eb 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -13,7 +13,8 @@ rule plot_network: overrides="data/override_component_attrs", network=RESULTS + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", output: map=RESULTS + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index b530f1d7..c63879aa 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -5,19 +5,25 @@ rule solve_network: input: - network=RESOURCES + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=RESOURCES + + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", output: - network=RESULTS + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=RESULTS + + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", log: solver=normpath( - LOGS + "solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log" + LOGS + + "solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log" ), python=LOGS + "solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", memory=LOGS + "solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_memory.log", benchmark: - BENCHMARKS + "solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + ( + BENCHMARKS + + "solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + ) threads: 4 resources: mem_mb=memory, @@ -31,9 +37,11 @@ rule solve_network: rule solve_operations_network: input: - network=RESULTS + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=RESULTS + + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", output: - network=RESULTS + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc", + network=RESULTS + + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc", log: solver=normpath( LOGS diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 8fff7d21..ef9a5ade 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -11,10 +11,13 @@ rule add_existing_baseyear: powerplants=RESOURCES + "powerplants.csv", busmap_s=RESOURCES + "busmap_elec{weather_year}_s{simpl}.csv", busmap=RESOURCES + "busmap_elec{weather_year}_s{simpl}_{clusters}.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", + clustered_pop_layout=RESOURCES + + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", costs="data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), - cop_soil_total=RESOURCES + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_soil_total=RESOURCES + + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_air_total=RESOURCES + + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", existing_heating="data/existing_infrastructure/existing_heating_raw.csv", existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", @@ -48,8 +51,10 @@ rule add_brownfield: + "prenetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", network_p=solved_previous_horizon, #solved network at previous time step costs="data/costs_{planning_horizons}.csv", - cop_soil_total=RESOURCES + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_soil_total=RESOURCES + + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_air_total=RESOURCES + + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", output: RESULTS + "prenetworks-brownfield/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index 0829ce6a..e79efca2 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -41,31 +41,57 @@ rule solve_sector_network: rule solve_operations_network_other_year: input: overrides="data/override_component_attrs", - pre=RDIR + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - post=RDIR + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - output: RDIR + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}.nc" - shadow: "shallow" + pre=RDIR + + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + post=RDIR + + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + output: + RDIR + + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}.nc", + shadow: + "shallow" log: - solver=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", - python=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", + solver=RDIR + + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", + python=RDIR + + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", threads: 4 - resources: mem_mb=10000 - benchmark: RDIR + "/benchmarks/solve_operations_network/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" - script: "../scripts/solve_operations_network_other_year.py" + resources: + mem_mb=10000, + benchmark: + ( + RDIR + + "/benchmarks/solve_operations_network/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" + ) + script: + "../scripts/solve_operations_network_other_year.py" rule solve_operations_network_other_year_myopic: input: overrides="data/override_component_attrs", - pre=RDIR + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - post=RDIR + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - previous=solved_previous_year - output: RDIR + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc" - shadow: "shallow" + pre=RDIR + + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + post=RDIR + + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", + previous=solved_previous_year, + output: + RDIR + + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc", + shadow: + "shallow" log: - solver=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", - python=RDIR + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", + solver=RDIR + + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", + python=RDIR + + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", threads: 4 - resources: mem_mb=10000 - benchmark: RDIR + "/benchmarks/solve_operations_network_myopic/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" - script: "../scripts/solve_operations_network_other_year_myopic.py" + resources: + mem_mb=10000, + benchmark: + ( + RDIR + + "/benchmarks/solve_operations_network_myopic/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" + ) + script: + "../scripts/solve_operations_network_other_year_myopic.py" From d527797dc3edee0bfdf9656a2435751b93843035 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 26 Jul 2023 08:24:01 +0000 Subject: [PATCH 078/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 1 - 1 file changed, 1 deletion(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 8c16b058..d56484a9 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -56,7 +56,6 @@ if config["enable"].get("retrieve_artificial_load_data", False): "../scripts/build_artificial_load_data.py" - rule build_powerplants: params: powerplants_filter=config["electricity"]["powerplants_filter"], From 16eb4e644a9d6e1fd40feb4ddd7ee10f5207334f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 26 Jul 2023 10:52:58 +0200 Subject: [PATCH 079/591] small fixes to weather_year wildcard handling --- config/test/config.electricity.yaml | 2 ++ config/test/config.myopic.yaml | 2 ++ config/test/config.overnight.yaml | 2 ++ rules/build_electricity.smk | 2 +- rules/build_sector.smk | 2 +- rules/solve_overnight.smk | 56 ++++++++++++++--------------- 6 files changed, 36 insertions(+), 30 deletions(-) diff --git a/config/test/config.electricity.yaml b/config/test/config.electricity.yaml index 6798e38c..e491a767 100644 --- a/config/test/config.electricity.yaml +++ b/config/test/config.electricity.yaml @@ -12,6 +12,8 @@ run: shared_cutouts: true scenario: + weather_year: + - "" clusters: - 5 opts: diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index 0bb85ec6..edaccd61 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -13,6 +13,8 @@ run: foresight: myopic scenario: + weather_year: + - "" ll: - v1.5 clusters: diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index a2a0f5a4..3ceda43b 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -12,6 +12,8 @@ run: scenario: + weather_year: + - "" ll: - v1.5 clusters: diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index d56484a9..4ecdddae 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -326,7 +326,7 @@ rule add_electricity: costs=config["costs"], input: **{ - f"profile_{tech}": RESOURCES + f"profile{weather_year}_{tech}.nc" + f"profile_{tech}": RESOURCES + "profile{weather_year}" + f"_{tech}.nc" for tech in config["electricity"]["renewable_carriers"] }, **{ diff --git a/rules/build_sector.smk b/rules/build_sector.smk index c430a2ac..26adea50 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -748,7 +748,7 @@ rule prepare_sector_network: pop_weighted_energy_totals=RESOURCES + "pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv", pop_weighted_heat_totals=RESOURCES - + "pop_weighted_heat_totals{weather_year}_s{simpl}_{clusters}.csv" + + "pop_weighted_heat_totals{weather_year}_s{simpl}_{clusters}.csv", shipping_demand=RESOURCES + "shipping_demand{weather_year}_s{simpl}_{clusters}.csv", transport_demand=RESOURCES + "transport_demand{weather_year}_s{simpl}_{clusters}.csv", transport_data=RESOURCES + "transport_data{weather_year}_s{simpl}_{clusters}.csv", diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index 86f0724d..6a4c7f7c 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -71,31 +71,31 @@ rule solve_operations_network_other_year: "../scripts/solve_operations_network_other_year.py" -rule solve_operations_network_other_year_myopic: - input: - overrides="data/override_component_attrs", - pre=RDIR - + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - post=RDIR - + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - previous=solved_previous_year, - output: - RDIR - + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc", - shadow: - "shallow" - log: - solver=RDIR - + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", - python=RDIR - + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", - threads: 4 - resources: - mem_mb=10000, - benchmark: - ( - RDIR - + "/benchmarks/solve_operations_network_myopic/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" - ) - script: - "../scripts/solve_operations_network_other_year_myopic.py" +# rule solve_operations_network_other_year_myopic: +# input: +# overrides="data/override_component_attrs", +# pre=RDIR +# + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", +# post=RDIR +# + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", +# previous=solved_previous_year, +# output: +# RDIR +# + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc", +# shadow: +# "shallow" +# log: +# solver=RDIR +# + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", +# python=RDIR +# + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", +# threads: 4 +# resources: +# mem_mb=10000, +# benchmark: +# ( +# RDIR +# + "/benchmarks/solve_operations_network_myopic/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" +# ) +# script: +# "../scripts/solve_operations_network_other_year_myopic.py" From e7836246ceb6e5ded89dfcf1404bc5466786b9be Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Apr 2023 12:02:59 +0200 Subject: [PATCH 080/591] scenario management: draft scenario yaml creator --- config/create_scenarios.py | 31 +++++++++++++++++++++++++++++++ config/scenarios.yaml | 0 2 files changed, 31 insertions(+) create mode 100644 config/create_scenarios.py create mode 100644 config/scenarios.yaml diff --git a/config/create_scenarios.py b/config/create_scenarios.py new file mode 100644 index 00000000..9a5f9a98 --- /dev/null +++ b/config/create_scenarios.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT + +import itertools + +# Insert your config values that should be altered in the template. +template = """ +scenario{scenario_number}: + sector: + carbon_: {config_value} + + config_section2: + config_key2: {config_value2} +""" + +# Define all possible combinations of config values. +# This must define all config values that are used in the template. +config_values = dict(config_values=["true", "false"], config_values2=[1, 2, 3, 4, 5]) + +combinations = [ + dict(zip(config_values.keys(), values)) + for values in itertools.product(*config_values.values()) +] + +# write the scenarios to a file +filename = "scenarios.yaml" +with open(filename, "w") as f: + for i, config in enumerate(combinations): + f.write(template.format(scenario_number=i, **config)) diff --git a/config/scenarios.yaml b/config/scenarios.yaml new file mode 100644 index 00000000..e69de29b From e28ae59375e9561304905bec34460f8aa87a4568 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 15 Aug 2023 15:02:41 +0200 Subject: [PATCH 081/591] introduce scenario-management --- .github/workflows/ci.yaml | 1 + .gitignore | 17 +-- Snakefile | 19 ++- config/config.default.yaml | 2 + config/create_scenarios.py | 31 ----- config/scenarios.yaml | 12 ++ config/test/config.scenarios.electricity.yaml | 89 ++++++++++++++ config/test/scenarios.electricity.yaml | 14 +++ doc/configtables/run.csv | 3 +- doc/configtables/toplevel.csv | 1 + rules/build_electricity.smk | 110 +++++++++--------- rules/build_sector.smk | 78 +++++++------ rules/collect.smk | 29 +++-- rules/common.smk | 51 ++++++++ rules/postprocess.smk | 28 ++--- rules/retrieve.smk | 16 +-- scripts/_helpers.py | 8 ++ scripts/add_electricity.py | 3 +- scripts/add_extra_components.py | 3 +- scripts/base_network.py | 3 +- scripts/build_bus_regions.py | 3 +- scripts/build_cross_border_flows.py | 3 +- scripts/build_cutout.py | 3 +- scripts/build_electricity_demand.py | 3 +- scripts/build_electricity_prices.py | 3 +- scripts/build_electricity_production.py | 3 +- scripts/build_hydro_profile.py | 3 +- scripts/build_line_rating.py | 3 +- scripts/build_monthly_prices.py | 3 +- scripts/build_natura_raster.py | 3 +- scripts/build_powerplants.py | 3 +- scripts/build_renewable_profiles.py | 3 +- scripts/build_shapes.py | 3 +- scripts/build_ship_raster.py | 20 ++-- scripts/cluster_network.py | 3 +- scripts/plot_statistics.py | 3 +- scripts/plot_validation_cross_border_flows.py | 3 +- scripts/plot_validation_electricity_prices.py | 3 +- .../plot_validation_electricity_production.py | 3 +- scripts/prepare_links_p_nom.py | 3 +- scripts/prepare_network.py | 3 +- scripts/retrieve_databundle.py | 2 +- scripts/retrieve_monthly_fuel_prices.py | 3 +- scripts/retrieve_sector_databundle.py | 3 +- scripts/simplify_network.py | 3 +- scripts/solve_network.py | 7 +- scripts/solve_operations_network.py | 7 +- 47 files changed, 419 insertions(+), 204 deletions(-) delete mode 100644 config/create_scenarios.py create mode 100644 config/test/config.scenarios.electricity.yaml create mode 100644 config/test/scenarios.electricity.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c2be3909..ff481b46 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -83,6 +83,7 @@ jobs: snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime + snakemake -call all --configfile config/test/config.electricity.scenario.yaml - name: Upload artifacts uses: actions/upload-artifact@v3 diff --git a/.gitignore b/.gitignore index 0adf0ae6..67cab0c9 100644 --- a/.gitignore +++ b/.gitignore @@ -19,10 +19,15 @@ gurobi.log /notebooks /data /cutouts - +/tmp doc/_build +/scripts/old +/scripts/create_scenarios.py + config.yaml +config/scenario.yaml + dconf /data/links_p_nom.csv @@ -51,25 +56,15 @@ publications.jrc.ec.europa.eu/ *.nc *~ -/scripts/old *.pyc -/cutouts -/tmp -/pypsa *.xlsx -config.yaml - -doc/_build - *.xls *.geojson *.ipynb -data/costs_* - merger-todos.md diff --git a/Snakefile b/Snakefile index 0e783beb..e495e7d3 100644 --- a/Snakefile +++ b/Snakefile @@ -4,14 +4,13 @@ from os.path import normpath, exists from shutil import copyfile, move, rmtree - +from pathlib import Path +import yaml from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider - -HTTP = HTTPRemoteProvider() - from snakemake.utils import min_version min_version("7.7") +HTTP = HTTPRemoteProvider() if not exists("config/config.yaml"): @@ -24,8 +23,16 @@ configfile: "config/config.yaml" COSTS = f"data/costs_{config['costs']['year']}.csv" ATLITE_NPROCESSES = config["atlite"].get("nprocesses", 4) -run = config.get("run", {}) -RDIR = run["name"] + "/" if run.get("name") else "" +run = config["run"] +if run.get("scenarios", False): + if run["shared_resources"]: + raise ValueError("Cannot use shared resources with scenarios") + scenarios = yaml.safe_load(Path(config["scenariofile"]).read_text()) + RDIR = "{run}/" +elif run["name"]: + RDIR = run["name"] + "/" +else: + RDIR = "" CDIR = RDIR if not run.get("shared_cutouts") else "" LOGS = "logs/" + RDIR diff --git a/config/config.default.yaml b/config/config.default.yaml index b162b75d..5357db8d 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -5,6 +5,7 @@ # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#top-level-configuration version: 0.8.1 tutorial: false +scenariofile: config/scenarios.yaml logging: level: INFO @@ -21,6 +22,7 @@ remote: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#run run: name: "" + scenarios: false disable_progressbar: false shared_resources: false shared_cutouts: true diff --git a/config/create_scenarios.py b/config/create_scenarios.py deleted file mode 100644 index 9a5f9a98..00000000 --- a/config/create_scenarios.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT - -import itertools - -# Insert your config values that should be altered in the template. -template = """ -scenario{scenario_number}: - sector: - carbon_: {config_value} - - config_section2: - config_key2: {config_value2} -""" - -# Define all possible combinations of config values. -# This must define all config values that are used in the template. -config_values = dict(config_values=["true", "false"], config_values2=[1, 2, 3, 4, 5]) - -combinations = [ - dict(zip(config_values.keys(), values)) - for values in itertools.product(*config_values.values()) -] - -# write the scenarios to a file -filename = "scenarios.yaml" -with open(filename, "w") as f: - for i, config in enumerate(combinations): - f.write(template.format(scenario_number=i, **config)) diff --git a/config/scenarios.yaml b/config/scenarios.yaml index e69de29b..37d32243 100644 --- a/config/scenarios.yaml +++ b/config/scenarios.yaml @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT + +# This file is used to define the scenarios that are run by snakemake. Each entry on the first level is a scenario. Each scenario can contain configuration overrides with respect to the config/config.yaml settings. +# +# Example +# +# custom-scenario: # name of the scenario +# electricity: +# renewable_carriers: [wind, solar] # override the list of renewable carriers diff --git a/config/test/config.scenarios.electricity.yaml b/config/test/config.scenarios.electricity.yaml new file mode 100644 index 00000000..0e4ced04 --- /dev/null +++ b/config/test/config.scenarios.electricity.yaml @@ -0,0 +1,89 @@ +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: CC0-1.0 + +tutorial: true +scenariofile: "config/test/scenarios.electricity.yaml" + +run: + name: + - test-elec-no-offshore-wind + - test-elec-no-onshore-wind + scenarios: true + disable_progressbar: true + shared_resources: false # cannot be true if scenarios is true + shared_cutouts: true + +scenario: + clusters: + - 5 + opts: + - Co2L-24H + +countries: ['BE'] + +snapshots: + start: "2013-03-01" + end: "2013-03-08" + +electricity: + co2limit: 100.e+6 + + extendable_carriers: + Generator: [OCGT] + StorageUnit: [battery] + Store: [H2] + Link: [H2 pipeline] + + renewable_carriers: [solar, onwind, offwind-ac, offwind-dc] + + +atlite: + default_cutout: be-03-2013-era5 + cutouts: + be-03-2013-era5: + module: era5 + x: [4., 15.] + y: [46., 56.] + time: ["2013-03-01", "2013-03-08"] + +renewable: + onwind: + cutout: be-03-2013-era5 + offwind-ac: + cutout: be-03-2013-era5 + max_depth: false + offwind-dc: + cutout: be-03-2013-era5 + max_depth: false + solar: + cutout: be-03-2013-era5 + + +clustering: + exclude_carriers: ["OCGT", "offwind-ac", "coal"] + +lines: + dynamic_line_rating: + activate: true + cutout: be-03-2013-era5 + max_line_rating: 1.3 + + +solving: + solver: + name: glpk + options: "glpk-default" + + +plotting: + map: + boundaries: + eu_node_location: + x: -5.5 + y: 46. + costs_max: 1000 + costs_threshold: 0.0000001 + energy_max: + energy_min: + energy_threshold: 0.000001 diff --git a/config/test/scenarios.electricity.yaml b/config/test/scenarios.electricity.yaml new file mode 100644 index 00000000..e9893479 --- /dev/null +++ b/config/test/scenarios.electricity.yaml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: CC0-1.0 + +test-elec-no-offshore-wind: + electricity: + renewable_carriers: [solar, onwind] + + +test-elec-no-onshore-wind: + electricity: + extendable_carriers: + Generator: [OCGT] + renewable_carriers: [solar, offwind-ac, offwind-dc] diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index 90cf65ad..2d5cf5d9 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -1,5 +1,6 @@ ,Unit,Values,Description -name,--,"any string","Specify a name for your run. Results will be stored under this name." +name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenarios`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenariofile``." +scenarios,--,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``scenariofile``." disable_progrssbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." shared_resources,bool,"{true, false}","Switch to select whether resources should be shared across runs." shared_cutouts,bool,"{true, false}","Switch to select whether cutouts should be shared across runs." diff --git a/doc/configtables/toplevel.csv b/doc/configtables/toplevel.csv index 67954389..8cbb3e56 100644 --- a/doc/configtables/toplevel.csv +++ b/doc/configtables/toplevel.csv @@ -1,6 +1,7 @@ ,Unit,Values,Description version,--,0.x.x,Version of PyPSA-Eur. Descriptive only. tutorial,bool,"{true, false}",Switch to retrieve the tutorial data set instead of the full data set. +scenariofile,str,,Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``create_scenarios.py`` script in ``scripts``. logging,,, -- level,--,"Any of {'INFO', 'WARNING', 'ERROR'}","Restrict console outputs to all infos, warning or errors only" -- format,--,,Custom format for log messages. See `LogRecord `_ attributes. diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 383951bd..4d59c058 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -20,9 +20,9 @@ if config["enable"].get("prepare_links_p_nom", False): rule build_electricity_demand: params: - snapshots=config["snapshots"], - countries=config["countries"], - load=config["load"], + snapshots=config_provider("snapshots"), + countries=config_provider("countries"), + load=config_provider("load"), input: ancient("data/load_raw.csv"), output: @@ -39,9 +39,9 @@ rule build_electricity_demand: rule build_powerplants: params: - powerplants_filter=config["electricity"]["powerplants_filter"], - custom_powerplants=config["electricity"]["custom_powerplants"], - countries=config["countries"], + powerplants_filter=config_provider("electricity", "powerplants_filter"), + custom_powerplants=config_provider("electricity", "custom_powerplants"), + countries=config_provider("countries"), input: base_network=RESOURCES + "networks/base.nc", custom_powerplants="data/custom_powerplants.csv", @@ -60,11 +60,11 @@ rule build_powerplants: rule base_network: params: - countries=config["countries"], - snapshots=config["snapshots"], - lines=config["lines"], - links=config["links"], - transformers=config["transformers"], + countries=config_provider("countries"), + snapshots=config_provider("snapshots"), + lines=config_provider("lines"), + links=config_provider("links"), + transformers=config_provider("transformers"), input: eg_buses="data/entsoegridkit/buses.csv", eg_lines="data/entsoegridkit/lines.csv", @@ -94,7 +94,7 @@ rule base_network: rule build_shapes: params: - countries=config["countries"], + countries=config_provider("countries"), input: naturalearth=ancient("data/bundle/naturalearth/ne_10m_admin_0_countries.shp"), eez=ancient("data/bundle/eez/World_EEZ_v8_2014.shp"), @@ -121,7 +121,7 @@ rule build_shapes: rule build_bus_regions: params: - countries=config["countries"], + countries=config_provider("countries"), input: country_shapes=RESOURCES + "country_shapes.geojson", offshore_shapes=RESOURCES + "offshore_shapes.geojson", @@ -144,8 +144,8 @@ if config["enable"].get("build_cutout", False): rule build_cutout: params: - snapshots=config["snapshots"], - cutouts=config["atlite"]["cutouts"], + snapshots=config_provider("snapshots"), + cutouts=config_provider("atlite", "cutouts"), input: regions_onshore=RESOURCES + "regions_onshore.geojson", regions_offshore=RESOURCES + "regions_offshore.geojson", @@ -208,7 +208,7 @@ rule build_ship_raster: rule build_renewable_profiles: params: - renewable=config["renewable"], + renewable=config_provider("renewable"), input: base_network=RESOURCES + "networks/base.nc", corine=ancient("data/bundle/corine/g250_clc06_V18_5.tif"), @@ -277,8 +277,8 @@ rule build_monthly_prices: rule build_hydro_profile: params: - hydro=config["renewable"]["hydro"], - countries=config["countries"], + hydro=config_provider("renewable", "hydro"), + countries=config_provider("countries"), input: country_shapes=RESOURCES + "country_shapes.geojson", eia_hydro_generation="data/eia_hydro_annual_generation.csv", @@ -321,13 +321,13 @@ if config["lines"]["dynamic_line_rating"]["activate"]: rule add_electricity: params: - length_factor=config["lines"]["length_factor"], - scaling_factor=config["load"]["scaling_factor"], - countries=config["countries"], - renewable=config["renewable"], - electricity=config["electricity"], - conventional=config["conventional"], - costs=config["costs"], + length_factor=config_provider("lines", "length_factor"), + scaling_factor=config_provider("load", "scaling_factor"), + countries=config_provider("countries"), + renewable=config_provider("renewable"), + electricity=config_provider("electricity"), + conventional=config_provider("conventional"), + costs=config_provider("costs"), input: **{ f"profile_{tech}": RESOURCES + f"profile_{tech}.nc" @@ -370,14 +370,16 @@ rule add_electricity: rule simplify_network: params: - simplify_network=config["clustering"]["simplify_network"], - aggregation_strategies=config["clustering"].get("aggregation_strategies", {}), - focus_weights=config.get("focus_weights", None), - renewable_carriers=config["electricity"]["renewable_carriers"], - max_hours=config["electricity"]["max_hours"], - length_factor=config["lines"]["length_factor"], - p_max_pu=config["links"].get("p_max_pu", 1.0), - costs=config["costs"], + simplify_network=config_provider("clustering", "simplify_network"), + aggregation_strategies=config_provider( + "clustering", "aggregation_strategies", default={} + ), + focus_weights=config_provider("focus_weights", default=None), + renewable_carriers=config_provider("electricity", "renewable_carriers"), + max_hours=config_provider("electricity", "max_hours"), + length_factor=config_provider("lines", "length_factor"), + p_max_pu=config_provider("links", "p_max_pu", default=1.0), + costs=config_provider("costs"), input: network=RESOURCES + "networks/elec.nc", tech_costs=COSTS, @@ -404,15 +406,19 @@ rule simplify_network: rule cluster_network: params: - cluster_network=config["clustering"]["cluster_network"], - aggregation_strategies=config["clustering"].get("aggregation_strategies", {}), - custom_busmap=config["enable"].get("custom_busmap", False), - focus_weights=config.get("focus_weights", None), - renewable_carriers=config["electricity"]["renewable_carriers"], - conventional_carriers=config["electricity"].get("conventional_carriers", []), - max_hours=config["electricity"]["max_hours"], - length_factor=config["lines"]["length_factor"], - costs=config["costs"], + cluster_network=config_provider("clustering", "cluster_network"), + aggregation_strategies=config_provider( + "clustering", "aggregation_strategies", default={} + ), + custom_busmap=config_provider("enable", "custom_busmap", default=False), + focus_weights=config_provider("focus_weights", default=None), + renewable_carriers=config_provider("electricity", "renewable_carriers"), + conventional_carriers=config_provider( + "electricity", "conventional_carriers", default=[] + ), + max_hours=config_provider("electricity", "max_hours"), + length_factor=config_provider("lines", "length_factor"), + costs=config_provider("costs"), input: network=RESOURCES + "networks/elec_s{simpl}.nc", regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}.geojson", @@ -445,9 +451,9 @@ rule cluster_network: rule add_extra_components: params: - extendable_carriers=config["electricity"]["extendable_carriers"], - max_hours=config["electricity"]["max_hours"], - costs=config["costs"], + extendable_carriers=config_provider("electricity", "extendable_carriers"), + max_hours=config_provider("electricity", "max_hours"), + costs=config_provider("costs"), input: network=RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", tech_costs=COSTS, @@ -468,13 +474,13 @@ rule add_extra_components: rule prepare_network: params: - links=config["links"], - lines=config["lines"], - co2base=config["electricity"]["co2base"], - co2limit=config["electricity"]["co2limit"], - gaslimit=config["electricity"].get("gaslimit"), - max_hours=config["electricity"]["max_hours"], - costs=config["costs"], + links=config_provider("links"), + lines=config_provider("lines"), + co2base=config_provider("electricity", "co2base"), + co2limit=config_provider("electricity", "co2limit"), + gaslimit=config_provider("electricity", "gaslimit"), + max_hours=config_provider("electricity", "max_hours"), + costs=config_provider("costs"), input: RESOURCES + "networks/elec_s{simpl}_{clusters}_ec.nc", tech_costs=COSTS, diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 356abdc5..cc80ab64 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -141,7 +141,7 @@ if not (config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]): rule build_heat_demands: params: - snapshots=config["snapshots"], + snapshots=config_provider("snapshots"), input: pop_layout=RESOURCES + "pop_layout_{scope}.nc", regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", @@ -163,7 +163,7 @@ rule build_heat_demands: rule build_temperature_profiles: params: - snapshots=config["snapshots"], + snapshots=config_provider("snapshots"), input: pop_layout=RESOURCES + "pop_layout_{scope}.nc", regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", @@ -186,7 +186,7 @@ rule build_temperature_profiles: rule build_cop_profiles: params: - heat_pump_sink_T=config["sector"]["heat_pump_sink_T"], + heat_pump_sink_T=config_provider("sector", "heat_pump_sink_T"), input: temp_soil_total=RESOURCES + "temp_soil_total_elec_s{simpl}_{clusters}.nc", temp_soil_rural=RESOURCES + "temp_soil_rural_elec_s{simpl}_{clusters}.nc", @@ -215,8 +215,8 @@ rule build_cop_profiles: rule build_solar_thermal_profiles: params: - snapshots=config["snapshots"], - solar_thermal=config["solar_thermal"], + snapshots=config_provider("snapshots"), + solar_thermal=config_provider("solar_thermal"), input: pop_layout=RESOURCES + "pop_layout_{scope}.nc", regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", @@ -238,8 +238,8 @@ rule build_solar_thermal_profiles: rule build_energy_totals: params: - countries=config["countries"], - energy=config["energy"], + countries=config_provider("countries"), + energy=config_provider("energy"), input: nuts3_shapes=RESOURCES + "nuts3_shapes.geojson", co2="data/eea/UNFCCC_v23.csv", @@ -266,7 +266,7 @@ rule build_energy_totals: rule build_biomass_potentials: params: - biomass=config["biomass"], + biomass=config_provider("biomass"), input: enspreso_biomass=HTTP.remote( "https://cidportal.jrc.ec.europa.eu/ftp/jrc-opendata/ENSPRESO/ENSPRESO_BIOMASS.xlsx", @@ -329,9 +329,9 @@ if config["sector"]["regional_co2_sequestration_potential"]["enable"]: rule build_sequestration_potentials: params: - sequestration_potential=config["sector"][ - "regional_co2_sequestration_potential" - ], + sequestration_potential=config_provider( + "sector", "regional_co2_sequestration_potential" + ), input: sequestration_potential=HTTP.remote( "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", @@ -386,7 +386,7 @@ rule build_salt_cavern_potentials: rule build_ammonia_production: params: - countries=config["countries"], + countries=config_provider("countries"), input: usgs="data/myb1-2017-nitro.xls", output: @@ -406,8 +406,8 @@ rule build_ammonia_production: rule build_industry_sector_ratios: params: - industry=config["industry"], - ammonia=config["sector"].get("ammonia", False), + industry=config_provider("industry"), + ammonia=config_provider("sector", "ammonia", default=False), input: ammonia_production=RESOURCES + "ammonia_production.csv", idees="data/jrc-idees-2015", @@ -428,8 +428,8 @@ rule build_industry_sector_ratios: rule build_industrial_production_per_country: params: - industry=config["industry"], - countries=config["countries"], + industry=config_provider("industry"), + countries=config_provider("countries"), input: ammonia_production=RESOURCES + "ammonia_production.csv", jrc="data/jrc-idees-2015", @@ -452,7 +452,7 @@ rule build_industrial_production_per_country: rule build_industrial_production_per_country_tomorrow: params: - industry=config["industry"], + industry=config_provider("industry"), input: industrial_production_per_country=RESOURCES + "industrial_production_per_country.csv", @@ -478,8 +478,10 @@ rule build_industrial_production_per_country_tomorrow: rule build_industrial_distribution_key: params: - hotmaps_locate_missing=config["industry"].get("hotmaps_locate_missing", False), - countries=config["countries"], + hotmaps_locate_missing=config_provider( + "industry", "hotmaps_locate_missing", default=False + ), + countries=config_provider("countries"), input: regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", @@ -555,8 +557,8 @@ rule build_industrial_energy_demand_per_node: rule build_industrial_energy_demand_per_country_today: params: - countries=config["countries"], - industry=config["industry"], + countries=config_provider("countries"), + industry=config_provider("industry"), input: jrc="data/jrc-idees-2015", ammonia_production=RESOURCES + "ammonia_production.csv", @@ -604,8 +606,8 @@ if config["sector"]["retrofitting"]["retro_endogen"]: rule build_retro_cost: params: - retrofitting=config["sector"]["retrofitting"], - countries=config["countries"], + retrofitting=config_provider("sector", "retrofitting"), + countries=config_provider("countries"), input: building_stock="data/retro/data_building_stock.csv", data_tabula="data/retro/tabula-calculator-calcsetbuilding.csv", @@ -677,8 +679,8 @@ rule build_shipping_demand: rule build_transport_demand: params: - snapshots=config["snapshots"], - sector=config["sector"], + snapshots=config_provider("snapshots"), + sector=config_provider("sector"), input: clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", pop_weighted_energy_totals=RESOURCES @@ -705,18 +707,20 @@ rule build_transport_demand: rule prepare_sector_network: params: - co2_budget=config["co2_budget"], - conventional_carriers=config["existing_capacities"]["conventional_carriers"], - foresight=config["foresight"], - costs=config["costs"], - sector=config["sector"], - industry=config["industry"], - pypsa_eur=config["pypsa_eur"], - length_factor=config["lines"]["length_factor"], - planning_horizons=config["scenario"]["planning_horizons"], - countries=config["countries"], - emissions_scope=config["energy"]["emissions"], - eurostat_report_year=config["energy"]["eurostat_report_year"], + co2_budget=config_provider("co2_budget"), + conventional_carriers=config_provider( + "existing_capacities", "conventional_carriers" + ), + foresight=config_provider("foresight"), + costs=config_provider("costs"), + sector=config_provider("sector"), + industry=config_provider("industry"), + pypsa_eur=config_provider("pypsa_eur"), + length_factor=config_provider("lines", "length_factor"), + planning_horizons=config_provider("scenario", "planning_horizons"), + countries=config_provider("countries"), + emissions_scope=config_provider("energy", "emissions"), + eurostat_report_year=config_provider("energy", "eurostat_report_year"), RDIR=RDIR, input: **build_retro_cost_output, diff --git a/rules/collect.smk b/rules/collect.smk index 74f26ccb..a29aa715 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -22,13 +22,19 @@ rule all: rule cluster_networks: input: - expand(RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", **config["scenario"]), + expand( + RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", + **config["scenario"], + run=config["run"]["name"] + ), rule extra_components_networks: input: expand( - RESOURCES + "networks/elec_s{simpl}_{clusters}_ec.nc", **config["scenario"] + RESOURCES + "networks/elec_s{simpl}_{clusters}_ec.nc", + **config["scenario"], + run=config["run"]["name"] ), @@ -36,7 +42,8 @@ rule prepare_elec_networks: input: expand( RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - **config["scenario"] + **config["scenario"], + run=config["run"]["name"] ), @@ -45,7 +52,8 @@ rule prepare_sector_networks: expand( RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - **config["scenario"] + **config["scenario"], + run=config["run"]["name"] ), @@ -53,7 +61,8 @@ rule solve_elec_networks: input: expand( RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - **config["scenario"] + **config["scenario"], + run=config["run"]["name"] ), @@ -62,7 +71,8 @@ rule solve_sector_networks: expand( RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - **config["scenario"] + **config["scenario"], + run=config["run"]["name"] ), @@ -71,7 +81,8 @@ rule plot_networks: expand( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", - **config["scenario"] + **config["scenario"], + run=config["run"]["name"] ), @@ -80,11 +91,13 @@ rule validate_elec_networks: expand( RESULTS + "figures/.statistics_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", - **config["scenario"] + **config["scenario"], + run=config["run"]["name"] ), expand( RESULTS + "figures/.validation_{kind}_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", **config["scenario"], + run=config["run"]["name"], kind=["production", "prices", "cross_border"] ), diff --git a/rules/common.smk b/rules/common.smk index ec5be355..5677f577 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -2,6 +2,57 @@ # # SPDX-License-Identifier: MIT +import copy + + +def get_config(keys, config, default=None): + """Retrieve a nested value from a dictionary using a tuple of keys.""" + value = config + for key in keys: + value = value.get(key, default) + if value == default: + return default + return value + + +def merge_configs(base_config, scenario_config): + """Merge base config with a specific scenario without modifying the original.""" + merged = copy.deepcopy(base_config) + for key, value in scenario_config.items(): + if key in merged and isinstance(merged[key], dict): + merged[key] = merge_configs(merged[key], value) + else: + merged[key] = value + return merged + + +def config_provider(*keys, default=None): + """Dynamically provide config values based on 'run' -> 'name'. + + Usage in Snakemake rules would look something like: + params: + my_param=config_provider("key1", "key2", default="some_default_value") + """ + + def static_getter(wildcards): + """Getter function for static config values.""" + return get_config(keys, config, default) + + def dynamic_getter(wildcards): + """Getter function for dynamic config values based on scenario.""" + scenario_name = wildcards.run + if scenario_name not in scenarios: + raise ValueError( + f"Scenario {scenario_name} not found in file {config['scenariofile']}." + ) + merged_config = merge_configs(config, scenarios[scenario_name]) + return get_config(keys, merged_config, default) + + if config["run"].get("scenarios", False): + return dynamic_getter + else: + return static_getter + def memory(w): factor = 3.0 diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 2618680e..fccda6e4 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -10,8 +10,8 @@ localrules: rule plot_network: params: - foresight=config["foresight"], - plotting=config["plotting"], + foresight=config_provider("foresight"), + plotting=config_provider("plotting"), input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -53,16 +53,17 @@ rule copy_config: rule make_summary: params: - foresight=config["foresight"], - costs=config["costs"], - snapshots=config["snapshots"], - scenario=config["scenario"], + foresight=config_provider("foresight"), + costs=config_provider("costs"), + snapshots=config_provider("snapshots"), + scenario=config_provider("scenario"), RDIR=RDIR, input: networks=expand( RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - **config["scenario"] + **config["scenario"], + run=config["run"]["name"] ), costs="data/costs_{}.csv".format(config["costs"]["year"]) if config["foresight"] == "overnight" @@ -70,7 +71,8 @@ rule make_summary: plots=expand( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", - **config["scenario"] + **config["scenario"], + run=config["run"]["name"] ), output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", @@ -103,10 +105,10 @@ rule make_summary: rule plot_summary: params: - countries=config["countries"], - planning_horizons=config["scenario"]["planning_horizons"], - sector_opts=config["scenario"]["sector_opts"], - plotting=config["plotting"], + countries=config_provider("countries"), + planning_horizons=config_provider("scenario", "planning_horizons"), + sector_opts=config_provider("scenario", "sector_opts"), + plotting=config_provider("plotting"), RDIR=RDIR, input: costs=RESULTS + "csvs/costs.csv", @@ -145,7 +147,7 @@ STATISTICS_BARPLOTS = [ rule plot_elec_statistics: params: - plotting=config["plotting"], + plotting=config_provider("plotting"), barplots=STATISTICS_BARPLOTS, input: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 0b60ee2e..4b9e9542 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -29,7 +29,7 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_databundle", output: expand("data/bundle/{file}", file=datafiles), log: - LOGS + "retrieve_databundle.log", + "logs/retrieve_databundle.log", resources: mem_mb=1000, retries: 2 @@ -72,7 +72,7 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_cost_data", T output: "data/costs_{year}.csv", log: - LOGS + "retrieve_cost_data_{year}.log", + "logs/retrieve_cost_data_{year}.log", resources: mem_mb=1000, retries: 2 @@ -123,7 +123,7 @@ if config["enable"]["retrieve"] and config["enable"].get( output: *datafiles, log: - LOGS + "retrieve_sector_databundle.log", + "logs/retrieve_sector_databundle.log", retries: 2 conda: "../envs/environment.yaml" @@ -145,7 +145,7 @@ if config["enable"]["retrieve"] and ( output: expand("data/gas_network/scigrid-gas/data/{files}", files=datafiles), log: - LOGS + "retrieve_gas_infrastructure_data.log", + "logs/retrieve_gas_infrastructure_data.log", retries: 2 conda: "../envs/environment.yaml" @@ -169,7 +169,7 @@ if config["enable"]["retrieve"]: output: "data/load_raw.csv", log: - LOGS + "retrieve_electricity_demand.log", + "logs/retrieve_electricity_demand.log", resources: mem_mb=5000, retries: 2 @@ -189,7 +189,7 @@ if config["enable"]["retrieve"]: output: "data/shipdensity_global.zip", log: - LOGS + "retrieve_ship_raster.log", + "logs/retrieve_ship_raster.log", resources: mem_mb=5000, retries: 2 @@ -209,7 +209,7 @@ if config["enable"]["retrieve"]: output: "data/validation/emission-spot-primary-market-auction-report-2019-data.xls", log: - LOGS + "retrieve_monthly_co2_prices.log", + "logs/retrieve_monthly_co2_prices.log", resources: mem_mb=5000, retries: 2 @@ -223,7 +223,7 @@ if config["enable"]["retrieve"]: output: "data/validation/energy-price-trends-xlsx-5619002.xlsx", log: - LOGS + "retrieve_monthly_fuel_prices.log", + "logs/retrieve_monthly_fuel_prices.log", resources: mem_mb=5000, retries: 2 diff --git a/scripts/_helpers.py b/scripts/_helpers.py index fc7bc9e0..c66d708e 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -14,6 +14,7 @@ import pytz import yaml from pypsa.components import component_attrs, components from pypsa.descriptors import Dict +from snakemake.utils import update_config from tqdm import tqdm logger = logging.getLogger(__name__) @@ -29,6 +30,13 @@ def mute_print(): yield +def set_scenario_config(snakemake): + if "scenario_config" in snakemake.input: + with open(snakemake.input.scenario_config, "r") as f: + scenario_config = yaml.safe_load(f) + update_config(snakemake.config, scenario_config) + + def configure_logging(snakemake, skip_handlers=False): """ Configure the basic behaviour for the logging module. diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 56375800..ff5e950e 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -92,7 +92,7 @@ import powerplantmatching as pm import pypsa import scipy.sparse as sparse import xarray as xr -from _helpers import configure_logging, update_p_nom_max +from _helpers import configure_logging, set_scenario_config, update_p_nom_max from powerplantmatching.export import map_country_bus from shapely.prepared import prep @@ -809,6 +809,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("add_electricity") configure_logging(snakemake) + set_scenario_config(snakemake) params = snakemake.params diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index e00e1e5f..9fe20066 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -55,7 +55,7 @@ import logging import numpy as np import pandas as pd import pypsa -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from add_electricity import load_costs, sanitize_carriers idx = pd.IndexSlice @@ -231,6 +231,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("add_extra_components", simpl="", clusters=5) configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.network) extendable_carriers = snakemake.params.extendable_carriers diff --git a/scripts/base_network.py b/scripts/base_network.py index b4ac1d8c..b5304109 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -77,7 +77,7 @@ import shapely import shapely.prepared import shapely.wkt import yaml -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from scipy import spatial from scipy.sparse import csgraph from shapely.geometry import LineString, Point @@ -745,6 +745,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("base_network") configure_logging(snakemake) + set_scenario_config(snakemake) n = base_network( snakemake.input.eg_buses, diff --git a/scripts/build_bus_regions.py b/scripts/build_bus_regions.py index a6500bb0..76a57f5e 100644 --- a/scripts/build_bus_regions.py +++ b/scripts/build_bus_regions.py @@ -47,7 +47,7 @@ import geopandas as gpd import numpy as np import pandas as pd import pypsa -from _helpers import REGION_COLS, configure_logging +from _helpers import REGION_COLS, configure_logging, set_scenario_config from scipy.spatial import Voronoi from shapely.geometry import Polygon @@ -115,6 +115,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_bus_regions") configure_logging(snakemake) + set_scenario_config(snakemake) countries = snakemake.params.countries diff --git a/scripts/build_cross_border_flows.py b/scripts/build_cross_border_flows.py index b9fc3fe8..743f1742 100644 --- a/scripts/build_cross_border_flows.py +++ b/scripts/build_cross_border_flows.py @@ -8,7 +8,7 @@ import logging import pandas as pd import pypsa -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from entsoe import EntsoePandasClient from entsoe.exceptions import InvalidBusinessParameterError, NoMatchingDataError from requests import HTTPError @@ -21,6 +21,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_cross_border_flows") configure_logging(snakemake) + set_scenario_config(snakemake) api_key = snakemake.config["private"]["keys"]["entsoe_api"] client = EntsoePandasClient(api_key=api_key) diff --git a/scripts/build_cutout.py b/scripts/build_cutout.py index 9a7f9e00..f9f951b5 100644 --- a/scripts/build_cutout.py +++ b/scripts/build_cutout.py @@ -95,7 +95,7 @@ import logging import atlite import geopandas as gpd import pandas as pd -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) @@ -105,6 +105,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_cutout", cutout="europe-2013-era5") configure_logging(snakemake) + set_scenario_config(snakemake) cutout_params = snakemake.params.cutouts[snakemake.wildcards.cutout] diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 38c75544..60d40e1e 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -45,7 +45,7 @@ logger = logging.getLogger(__name__) import dateutil import numpy as np import pandas as pd -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from pandas import Timedelta as Delta @@ -288,6 +288,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_electricity_demand") configure_logging(snakemake) + set_scenario_config(snakemake) powerstatistics = snakemake.params.load["power_statistics"] interpolate_limit = snakemake.params.load["interpolate_limit"] diff --git a/scripts/build_electricity_prices.py b/scripts/build_electricity_prices.py index 353ea7e3..48361afe 100644 --- a/scripts/build_electricity_prices.py +++ b/scripts/build_electricity_prices.py @@ -7,7 +7,7 @@ import logging import pandas as pd -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from entsoe import EntsoePandasClient from entsoe.exceptions import NoMatchingDataError @@ -19,6 +19,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_cross_border_flows") configure_logging(snakemake) + set_scenario_config(snakemake) api_key = snakemake.config["private"]["keys"]["entsoe_api"] client = EntsoePandasClient(api_key=api_key) diff --git a/scripts/build_electricity_production.py b/scripts/build_electricity_production.py index beb859bd..38be2ba0 100644 --- a/scripts/build_electricity_production.py +++ b/scripts/build_electricity_production.py @@ -7,7 +7,7 @@ import logging import pandas as pd -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from entsoe import EntsoePandasClient from entsoe.exceptions import NoMatchingDataError @@ -39,6 +39,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_electricity_production") configure_logging(snakemake) + set_scenario_config(snakemake) api_key = snakemake.config["private"]["keys"]["entsoe_api"] client = EntsoePandasClient(api_key=api_key) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index bed666f2..883f33d2 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -65,7 +65,7 @@ import atlite import country_converter as coco import geopandas as gpd import pandas as pd -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config cc = coco.CountryConverter() @@ -129,6 +129,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_hydro_profile") configure_logging(snakemake) + set_scenario_config(snakemake) params_hydro = snakemake.params.hydro cutout = atlite.Cutout(snakemake.input.cutout) diff --git a/scripts/build_line_rating.py b/scripts/build_line_rating.py index 7f842d43..abc6b286 100755 --- a/scripts/build_line_rating.py +++ b/scripts/build_line_rating.py @@ -59,7 +59,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from shapely.geometry import LineString as Line from shapely.geometry import Point @@ -147,6 +147,7 @@ if __name__ == "__main__": opts="Co2L-4H", ) configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.base_network) time = pd.date_range(freq="h", **snakemake.config["snapshots"]) diff --git a/scripts/build_monthly_prices.py b/scripts/build_monthly_prices.py index c2e88972..89edde79 100644 --- a/scripts/build_monthly_prices.py +++ b/scripts/build_monthly_prices.py @@ -46,7 +46,7 @@ Data was accessed at 16.5.2023 import logging import pandas as pd -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) @@ -114,6 +114,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_monthly_prices") configure_logging(snakemake) + set_scenario_config(snakemake) fuel_price = get_fuel_price() fuel_price.to_csv(snakemake.output.fuel_price) diff --git a/scripts/build_natura_raster.py b/scripts/build_natura_raster.py index 8fdb4ea3..79418d5c 100644 --- a/scripts/build_natura_raster.py +++ b/scripts/build_natura_raster.py @@ -46,7 +46,7 @@ import logging import atlite import geopandas as gpd import rasterio as rio -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from rasterio.features import geometry_mask from rasterio.warp import transform_bounds @@ -92,6 +92,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_natura_raster") configure_logging(snakemake) + set_scenario_config(snakemake) cutouts = snakemake.input.cutouts xs, Xs, ys, Ys = zip(*(determine_cutout_xXyY(cutout) for cutout in cutouts)) diff --git a/scripts/build_powerplants.py b/scripts/build_powerplants.py index cbe94505..2ad1e010 100755 --- a/scripts/build_powerplants.py +++ b/scripts/build_powerplants.py @@ -80,7 +80,7 @@ import logging import pandas as pd import powerplantmatching as pm import pypsa -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from powerplantmatching.export import map_country_bus logger = logging.getLogger(__name__) @@ -115,6 +115,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_powerplants") configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.base_network) countries = snakemake.params.countries diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 7b08325b..40b3151d 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -188,7 +188,7 @@ import geopandas as gpd import numpy as np import pandas as pd import xarray as xr -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from dask.distributed import Client from pypsa.geo import haversine from shapely.geometry import LineString @@ -202,6 +202,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_renewable_profiles", technology="solar") configure_logging(snakemake) + set_scenario_config(snakemake) nprocesses = int(snakemake.threads) noprogress = snakemake.config["run"].get("disable_progressbar", True) diff --git a/scripts/build_shapes.py b/scripts/build_shapes.py index eb837409..571a7282 100644 --- a/scripts/build_shapes.py +++ b/scripts/build_shapes.py @@ -77,7 +77,7 @@ import geopandas as gpd import numpy as np import pandas as pd import pycountry as pyc -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from shapely.geometry import MultiPolygon, Polygon logger = logging.getLogger(__name__) @@ -254,6 +254,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_shapes") configure_logging(snakemake) + set_scenario_config(snakemake) country_shapes = countries(snakemake.input.naturalearth, snakemake.params.countries) country_shapes.reset_index().to_file(snakemake.output.country_shapes) diff --git a/scripts/build_ship_raster.py b/scripts/build_ship_raster.py index 90e006b0..25bebcca 100644 --- a/scripts/build_ship_raster.py +++ b/scripts/build_ship_raster.py @@ -44,9 +44,10 @@ Description import logging import os import zipfile +from pathlib import Path import rioxarray -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from build_natura_raster import determine_cutout_xXyY logger = logging.getLogger(__name__) @@ -57,16 +58,19 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_ship_raster") configure_logging(snakemake) + set_scenario_config(snakemake) cutouts = snakemake.input.cutouts xs, Xs, ys, Ys = zip(*(determine_cutout_xXyY(cutout) for cutout in cutouts)) with zipfile.ZipFile(snakemake.input.ship_density) as zip_f: - zip_f.extract("shipdensity_global.tif") - with rioxarray.open_rasterio("shipdensity_global.tif") as ship_density: - ship_density = ship_density.drop(["band"]).sel( - x=slice(min(xs), max(Xs)), y=slice(max(Ys), min(ys)) - ) - ship_density.rio.to_raster(snakemake.output[0]) + resources = Path(snakemake.output[0]).parent + fn = "shipdensity_global.tif" + zip_f.extract(fn, resources) + with rioxarray.open_rasterio(resources / fn) as ship_density: + ship_density = ship_density.drop(["band"]).sel( + x=slice(min(xs), max(Xs)), y=slice(max(Ys), min(ys)) + ) + ship_density.rio.to_raster(snakemake.output[0]) - os.remove("shipdensity_global.tif") + (resources / fn).unlink() diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 884b6a2b..b0ce4796 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -133,7 +133,7 @@ import pandas as pd import pyomo.environ as po import pypsa import seaborn as sns -from _helpers import configure_logging, update_p_nom_max +from _helpers import configure_logging, set_scenario_config, update_p_nom_max from pypsa.clustering.spatial import ( busmap_by_greedy_modularity, busmap_by_hac, @@ -463,6 +463,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("cluster_network", simpl="", clusters="37") configure_logging(snakemake) + set_scenario_config(snakemake) params = snakemake.params solver_name = snakemake.config["solving"]["solver"]["name"] diff --git a/scripts/plot_statistics.py b/scripts/plot_statistics.py index 1e75203f..a0a3e71d 100644 --- a/scripts/plot_statistics.py +++ b/scripts/plot_statistics.py @@ -7,7 +7,7 @@ import matplotlib.pyplot as plt import pypsa import seaborn as sns -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config sns.set_theme("paper", style="whitegrid") @@ -24,6 +24,7 @@ if __name__ == "__main__": ll="v1.0", ) configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.network) diff --git a/scripts/plot_validation_cross_border_flows.py b/scripts/plot_validation_cross_border_flows.py index 43ed45e9..8b063d8c 100644 --- a/scripts/plot_validation_cross_border_flows.py +++ b/scripts/plot_validation_cross_border_flows.py @@ -9,7 +9,7 @@ import matplotlib.pyplot as plt import pandas as pd import pypsa import seaborn as sns -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config sns.set_theme("paper", style="whitegrid") @@ -195,6 +195,7 @@ if __name__ == "__main__": ll="v1.0", ) configure_logging(snakemake) + set_scenario_config(snakemake) countries = snakemake.params.countries diff --git a/scripts/plot_validation_electricity_prices.py b/scripts/plot_validation_electricity_prices.py index 2a187b9f..c229e382 100644 --- a/scripts/plot_validation_electricity_prices.py +++ b/scripts/plot_validation_electricity_prices.py @@ -8,7 +8,7 @@ import matplotlib.pyplot as plt import pandas as pd import pypsa import seaborn as sns -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from pypsa.statistics import get_bus_and_carrier sns.set_theme("paper", style="whitegrid") @@ -25,6 +25,7 @@ if __name__ == "__main__": ll="v1.0", ) configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.network) n.loads.carrier = "load" diff --git a/scripts/plot_validation_electricity_production.py b/scripts/plot_validation_electricity_production.py index 5c5569d0..3e81faff 100644 --- a/scripts/plot_validation_electricity_production.py +++ b/scripts/plot_validation_electricity_production.py @@ -8,7 +8,7 @@ import matplotlib.pyplot as plt import pandas as pd import pypsa import seaborn as sns -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from pypsa.statistics import get_bus_and_carrier sns.set_theme("paper", style="whitegrid") @@ -35,6 +35,7 @@ if __name__ == "__main__": ll="v1.0", ) configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.network) n.loads.carrier = "load" diff --git a/scripts/prepare_links_p_nom.py b/scripts/prepare_links_p_nom.py index 4b915d22..450f3227 100644 --- a/scripts/prepare_links_p_nom.py +++ b/scripts/prepare_links_p_nom.py @@ -40,7 +40,7 @@ Description import logging import pandas as pd -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) @@ -69,6 +69,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("prepare_links_p_nom", simpl="") configure_logging(snakemake) + set_scenario_config(snakemake) links_p_nom = pd.read_html( "https://en.wikipedia.org/wiki/List_of_HVDC_projects", header=0, match="SwePol" diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index a5a00a3c..a7f1ddf3 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -63,7 +63,7 @@ import re import numpy as np import pandas as pd import pypsa -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from add_electricity import load_costs, update_transmission_costs from pypsa.descriptors import expand_series @@ -283,6 +283,7 @@ if __name__ == "__main__": "prepare_network", simpl="", clusters="37", ll="v1.0", opts="Ept" ) configure_logging(snakemake) + set_scenario_config(snakemake) opts = snakemake.wildcards.opts.split("-") diff --git a/scripts/retrieve_databundle.py b/scripts/retrieve_databundle.py index 75d8519e..cb3bdc11 100644 --- a/scripts/retrieve_databundle.py +++ b/scripts/retrieve_databundle.py @@ -36,7 +36,7 @@ import logging import tarfile from pathlib import Path -from _helpers import configure_logging, progress_retrieve +from _helpers import configure_logging, progress_retrieve, set_scenario_config logger = logging.getLogger(__name__) diff --git a/scripts/retrieve_monthly_fuel_prices.py b/scripts/retrieve_monthly_fuel_prices.py index 11e351ce..887014cc 100644 --- a/scripts/retrieve_monthly_fuel_prices.py +++ b/scripts/retrieve_monthly_fuel_prices.py @@ -12,7 +12,7 @@ logger = logging.getLogger(__name__) from pathlib import Path -from _helpers import configure_logging, progress_retrieve +from _helpers import configure_logging, progress_retrieve, set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): @@ -23,6 +23,7 @@ if __name__ == "__main__": else: rootpath = "." configure_logging(snakemake) + set_scenario_config(snakemake) url = "https://www.destatis.de/EN/Themes/Economy/Prices/Publications/Downloads-Energy-Price-Trends/energy-price-trends-xlsx-5619002.xlsx?__blob=publicationFile" diff --git a/scripts/retrieve_sector_databundle.py b/scripts/retrieve_sector_databundle.py index 0d172c8d..1beed478 100644 --- a/scripts/retrieve_sector_databundle.py +++ b/scripts/retrieve_sector_databundle.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) import tarfile from pathlib import Path -from _helpers import configure_logging, progress_retrieve +from _helpers import configure_logging, progress_retrieve, set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): @@ -24,6 +24,7 @@ if __name__ == "__main__": else: rootpath = "." configure_logging(snakemake) + set_scenario_config(snakemake) url = "https://zenodo.org/record/5824485/files/pypsa-eur-sec-data-bundle.tar.gz" diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index cac25647..440145ff 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -92,7 +92,7 @@ import numpy as np import pandas as pd import pypsa import scipy as sp -from _helpers import configure_logging, update_p_nom_max +from _helpers import configure_logging, set_scenario_config, update_p_nom_max from add_electricity import load_costs from cluster_network import cluster_regions, clustering_for_n_clusters from pypsa.clustering.spatial import ( @@ -531,6 +531,7 @@ if __name__ == "__main__": snakemake = mock_snakemake("simplify_network", simpl="") configure_logging(snakemake) + set_scenario_config(snakemake) params = snakemake.params solver_name = snakemake.config["solving"]["solver"]["name"] diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 8eccef19..37b05286 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -33,7 +33,11 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import configure_logging, update_config_with_sector_opts +from _helpers import ( + configure_logging, + set_scenario_config, + update_config_with_sector_opts, +) logger = logging.getLogger(__name__) pypsa.pf.logger.setLevel(logging.WARNING) @@ -657,6 +661,7 @@ if __name__ == "__main__": planning_horizons="2020", ) configure_logging(snakemake) + set_scenario_config(snakemake) if "sector_opts" in snakemake.wildcards.keys(): update_config_with_sector_opts( snakemake.config, snakemake.wildcards.sector_opts diff --git a/scripts/solve_operations_network.py b/scripts/solve_operations_network.py index 1a3855a9..064d735a 100644 --- a/scripts/solve_operations_network.py +++ b/scripts/solve_operations_network.py @@ -11,7 +11,11 @@ import logging import numpy as np import pypsa -from _helpers import configure_logging, update_config_with_sector_opts +from _helpers import ( + configure_logging, + set_scenario_config, + update_config_with_sector_opts, +) from solve_network import prepare_network, solve_network logger = logging.getLogger(__name__) @@ -33,6 +37,7 @@ if __name__ == "__main__": ) configure_logging(snakemake) + set_scenario_config(snakemake) update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) opts = (snakemake.wildcards.opts + "-" + snakemake.wildcards.sector_opts).split("-") From 1f38c69b7634e6facbfe6dcb3d0dcd19caca3ee0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 15 Aug 2023 15:07:34 +0200 Subject: [PATCH 082/591] untrack scenarios.yaml --- config/scenarios.yaml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 config/scenarios.yaml diff --git a/config/scenarios.yaml b/config/scenarios.yaml deleted file mode 100644 index 37d32243..00000000 --- a/config/scenarios.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT - -# This file is used to define the scenarios that are run by snakemake. Each entry on the first level is a scenario. Each scenario can contain configuration overrides with respect to the config/config.yaml settings. -# -# Example -# -# custom-scenario: # name of the scenario -# electricity: -# renewable_carriers: [wind, solar] # override the list of renewable carriers From 56fe245eb4ae03839f3fd61b33a7319237a596b0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 15 Aug 2023 15:08:22 +0200 Subject: [PATCH 083/591] gitignore: fix typo --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 67cab0c9..e79d129d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,7 @@ doc/_build /scripts/create_scenarios.py config.yaml -config/scenario.yaml +config/scenarios.yaml dconf From 6df2742cb996fb62a97851dd671ec00861e88fc2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 15 Aug 2023 15:14:55 +0200 Subject: [PATCH 084/591] update release notes --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 70a73e2f..918bb6dd 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -11,6 +11,8 @@ Upcoming Release ================ * Updated Global Energy Monitor LNG terminal data to March 2023 version. +* PyPSA-EUR now supports the simultaneous execution of multiple scenarios. For this purpose, a scenarios.yaml file has been introduced which contains customizable scenario names with corresponding configuration overrides. To enable it, set the ``run: scenarios:`` key to ``True`` and define the scenario names to run under ``run: name:`` in the configuration file. The latter must be a subset of toplevel keys in the scenario file. + PyPSA-Eur 0.8.1 (27th July 2023) ================================ From 16d08ec100ee334daf729dcd5dc1bdb93feba1d1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 15 Aug 2023 15:29:43 +0200 Subject: [PATCH 085/591] CI: fix config scenarios file spec --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ff481b46..c09d05c2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -83,7 +83,7 @@ jobs: snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime - snakemake -call all --configfile config/test/config.electricity.scenario.yaml + snakemake -call all --configfile config/test/config.scenarios.electricity.yaml - name: Upload artifacts uses: actions/upload-artifact@v3 From 3462080b896ba71b04653b73453024b750de7721 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 15 Aug 2023 15:44:54 +0200 Subject: [PATCH 086/591] ci: adjust scenario test run --- .github/workflows/ci.yaml | 2 +- rules/collect.smk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c09d05c2..6cbee85c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -83,7 +83,7 @@ jobs: snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime - snakemake -call all --configfile config/test/config.scenarios.electricity.yaml + snakemake -call solve_elec_networks --configfile config/test/config.scenarios.electricity.yaml - name: Upload artifacts uses: actions/upload-artifact@v3 diff --git a/rules/collect.smk b/rules/collect.smk index a29aa715..8a64b577 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -16,7 +16,7 @@ localrules: rule all: input: - RESULTS + "graphs/costs.pdf", + expand(RESULTS + "graphs/costs.pdf", run=config["run"]["name"]), default_target: True From 5036964dbea41eaabf3695bdad1fad089ca8ef62 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 15 Aug 2023 15:49:57 +0200 Subject: [PATCH 087/591] copy_config: ensure to store updated config --- scripts/copy_config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/copy_config.py b/scripts/copy_config.py index a549d893..40025342 100644 --- a/scripts/copy_config.py +++ b/scripts/copy_config.py @@ -13,10 +13,12 @@ import yaml if __name__ == "__main__": if "snakemake" not in globals(): - from _helpers import mock_snakemake + from _helpers import mock_snakemake, set_scenario_config snakemake = mock_snakemake("copy_config") + set_scenario_config(snakemake) + with open(snakemake.output[0], "w") as yaml_file: yaml.dump( snakemake.config, From b40a8926ff06fbcd501d2fdef8cd33407d8cba50 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 15 Aug 2023 16:51:35 +0200 Subject: [PATCH 088/591] copy_config: fix import --- scripts/copy_config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/copy_config.py b/scripts/copy_config.py index 40025342..d6908a62 100644 --- a/scripts/copy_config.py +++ b/scripts/copy_config.py @@ -10,10 +10,11 @@ from pathlib import Path from shutil import copy import yaml +from _helpers import set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): - from _helpers import mock_snakemake, set_scenario_config + from _helpers import mock_snakemake snakemake = mock_snakemake("copy_config") From b9f3df385611d8f7c1f22575b8222cda1951c7b3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 15 Aug 2023 17:28:12 +0200 Subject: [PATCH 089/591] ci: only dry-run scenarios --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6cbee85c..68bffc4c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -83,7 +83,7 @@ jobs: snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime - snakemake -call solve_elec_networks --configfile config/test/config.scenarios.electricity.yaml + snakemake -call solve_elec_networks --configfile config/test/config.scenarios.electricity.yaml -n - name: Upload artifacts uses: actions/upload-artifact@v3 From b3a6e2c2816087b2b22eb05877ac2ec82d93084f Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 16 Aug 2023 10:50:09 +0200 Subject: [PATCH 090/591] common: make cache config_getter, use partial functions --- rules/common.smk | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/rules/common.smk b/rules/common.smk index 5677f577..f24301c8 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -3,9 +3,10 @@ # SPDX-License-Identifier: MIT import copy +from functools import partial, lru_cache -def get_config(keys, config, default=None): +def get_config(config, keys, default=None): """Retrieve a nested value from a dictionary using a tuple of keys.""" value = config for key in keys: @@ -26,6 +27,27 @@ def merge_configs(base_config, scenario_config): return merged +@lru_cache +def scenario_config(scenario_name): + """Retrieve a scenario config based on the overrides from the scenario file.""" + return merge_configs(config, scenarios[scenario_name]) + + +def static_getter(wildcards, keys, default): + """Getter function for static config values.""" + return get_config(config, keys, default) + + +def dynamic_getter(wildcards, keys, default): + """Getter function for dynamic config values based on scenario.""" + scenario_name = wildcards.run + if scenario_name not in scenarios: + raise ValueError( + f"Scenario {scenario_name} not found in file {config['scenariofile']}." + ) + return get_config(scenario_config(scenario_name), keys, default) + + def config_provider(*keys, default=None): """Dynamically provide config values based on 'run' -> 'name'. @@ -33,25 +55,11 @@ def config_provider(*keys, default=None): params: my_param=config_provider("key1", "key2", default="some_default_value") """ - - def static_getter(wildcards): - """Getter function for static config values.""" - return get_config(keys, config, default) - - def dynamic_getter(wildcards): - """Getter function for dynamic config values based on scenario.""" - scenario_name = wildcards.run - if scenario_name not in scenarios: - raise ValueError( - f"Scenario {scenario_name} not found in file {config['scenariofile']}." - ) - merged_config = merge_configs(config, scenarios[scenario_name]) - return get_config(keys, merged_config, default) - + # Using functools.partial to freeze certain arguments in our getter functions. if config["run"].get("scenarios", False): - return dynamic_getter + return partial(dynamic_getter, keys=keys, default=default) else: - return static_getter + return partial(static_getter, keys=keys, default=default) def memory(w): From 750b74db46bc6ac656145df2802b62cfa8fb801d Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 16 Aug 2023 10:51:03 +0200 Subject: [PATCH 091/591] build_electricity: optionally download dynamic fuel prices --- rules/build_electricity.smk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 4d59c058..b359868f 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -350,7 +350,9 @@ rule add_electricity: hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), geth_hydro_capacities="data/geth2015_hydro_capacities.csv", unit_commitment="data/unit_commitment.csv", - fuel_price=RESOURCES + "monthly_fuel_price.csv", + fuel_price=RESOURCES + "monthly_fuel_price.csv" + if config["conventional"]["dynamic_fuel_price"] + else [], load=RESOURCES + "load.csv", nuts3_shapes=RESOURCES + "nuts3_shapes.geojson", output: From 9cd449cf3c24bc935b43c0bb1dcb3ff80015822e Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 16 Aug 2023 11:41:48 +0200 Subject: [PATCH 092/591] retrieve electricity demand: use script in order to concat time-series --- rules/postprocess.smk | 1 - rules/retrieve.smk | 14 ++-------- scripts/retrieve_electricity_demand.py | 37 ++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 scripts/retrieve_electricity_demand.py diff --git a/rules/postprocess.smk b/rules/postprocess.smk index fccda6e4..4c833b4f 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -5,7 +5,6 @@ localrules: copy_config, - copy_conda_env, rule plot_network: diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 4b9e9542..d7e22e71 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -156,16 +156,6 @@ if config["enable"]["retrieve"] and ( if config["enable"]["retrieve"]: rule retrieve_electricity_demand: - input: - HTTP.remote( - "data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv".format( - version="2019-06-05" - if config["snapshots"]["end"] < "2019" - else "2020-10-06" - ), - keep_local=True, - static=True, - ), output: "data/load_raw.csv", log: @@ -173,8 +163,8 @@ if config["enable"]["retrieve"]: resources: mem_mb=5000, retries: 2 - run: - move(input[0], output[0]) + script: + "../scripts/retrieve_electricity_demand.py" if config["enable"]["retrieve"]: diff --git a/scripts/retrieve_electricity_demand.py b/scripts/retrieve_electricity_demand.py new file mode 100644 index 00000000..58615755 --- /dev/null +++ b/scripts/retrieve_electricity_demand.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Retrieve monthly fuel prices from Destatis. +""" + +import logging + +import pandas as pd + +logger = logging.getLogger(__name__) + +from pathlib import Path + +from _helpers import configure_logging, set_scenario_config + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake("retrieve_eletricity_demand") + rootpath = ".." + else: + rootpath = "." + configure_logging(snakemake) + set_scenario_config(snakemake) + + versions = ["2019-06-05", "2020-10-06"] + url = "https://data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv" + + df1, df2 = [ + pd.read_csv(url.format(version=version), index_col=0) for version in versions + ] + res = pd.concat([df1, df2[df2.index > df1.index[-1]]], join="inner") + res.to_csv(snakemake.output[0]) From 32eb114b613d8e0c88c3c992d0b1ddb4ecf71b4c Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 16 Aug 2023 11:47:27 +0200 Subject: [PATCH 093/591] retrieve electricity demand: make online version snakemake params --- rules/retrieve.smk | 2 ++ scripts/build_industrial_distribution_key.py | 4 ++-- scripts/retrieve_electricity_demand.py | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index d7e22e71..5af0ffb5 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -156,6 +156,8 @@ if config["enable"]["retrieve"] and ( if config["enable"]["retrieve"]: rule retrieve_electricity_demand: + params: + versions=["2019-06-05", "2020-10-06"], output: "data/load_raw.csv", log: diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index 979a1493..24cb6fa0 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -116,7 +116,7 @@ def build_nodal_distribution_key(hotmaps, regions, countries): if not facilities.empty: emissions = facilities["Emissions_ETS_2014"].fillna( - hotmaps["Emissions_EPRTR_2014"] + hotmaps["Emissions_EPRTR_2014"].dropna() ) if emissions.sum() == 0: key = pd.Series(1 / len(facilities), facilities.index) @@ -140,7 +140,7 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_industrial_distribution_key", simpl="", - clusters=48, + clusters=128, ) logging.basicConfig(level=snakemake.config["logging"]["level"]) diff --git a/scripts/retrieve_electricity_demand.py b/scripts/retrieve_electricity_demand.py index 58615755..58511857 100644 --- a/scripts/retrieve_electricity_demand.py +++ b/scripts/retrieve_electricity_demand.py @@ -27,11 +27,11 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - versions = ["2019-06-05", "2020-10-06"] url = "https://data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv" df1, df2 = [ - pd.read_csv(url.format(version=version), index_col=0) for version in versions + pd.read_csv(url.format(version=version), index_col=0) + for version in snakemake.params.versions ] res = pd.concat([df1, df2[df2.index > df1.index[-1]]], join="inner") res.to_csv(snakemake.output[0]) From 59fe66561651ff64730b27cf0647c78caea9030d Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 16 Aug 2023 13:25:52 +0200 Subject: [PATCH 094/591] add exemplary scenarios.yaml add create_scenarios.py --- config/scenarios.yaml | 12 ++++++++++++ scripts/create_scenarios.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 config/scenarios.yaml create mode 100644 scripts/create_scenarios.py diff --git a/config/scenarios.yaml b/config/scenarios.yaml new file mode 100644 index 00000000..37d32243 --- /dev/null +++ b/config/scenarios.yaml @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT + +# This file is used to define the scenarios that are run by snakemake. Each entry on the first level is a scenario. Each scenario can contain configuration overrides with respect to the config/config.yaml settings. +# +# Example +# +# custom-scenario: # name of the scenario +# electricity: +# renewable_carriers: [wind, solar] # override the list of renewable carriers diff --git a/scripts/create_scenarios.py b/scripts/create_scenarios.py new file mode 100644 index 00000000..40a3c331 --- /dev/null +++ b/scripts/create_scenarios.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT + +# This script helps to generate a scenarios.yaml file for PyPSA-Eur. +# You can modify the template to your needs and define all possible combinations of config values that should be considered. + + +import itertools + +# Insert your config values that should be altered in the template. +# Change `config_section` and `config_section2` to the actual config sections. +template = """ +scenario{scenario_number}: + config_section: + config_value: {config_value} + + config_section2: + config_key2: {config_value2} +""" + +# Define all possible combinations of config values. +# This must define all config values that are used in the template. +config_values = dict(config_values=["true", "false"], config_values2=[1, 2, 3, 4, 5]) + +combinations = [ + dict(zip(config_values.keys(), values)) + for values in itertools.product(*config_values.values()) +] + +# write the scenarios to a file +filename = "../config/scenarios.yaml" +with open(filename, "w") as f: + for i, config in enumerate(combinations): + f.write(template.format(scenario_number=i, **config)) From af2fb1a82e728c7d0de2a73c1222ba5479fb6540 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 16 Aug 2023 13:37:10 +0200 Subject: [PATCH 095/591] uptrack changes in scenarios.yaml/create_scenarios.py --- config/scenarios.yaml | 12 ------------ scripts/create_scenarios.py | 36 ------------------------------------ 2 files changed, 48 deletions(-) delete mode 100644 config/scenarios.yaml delete mode 100644 scripts/create_scenarios.py diff --git a/config/scenarios.yaml b/config/scenarios.yaml deleted file mode 100644 index 37d32243..00000000 --- a/config/scenarios.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT - -# This file is used to define the scenarios that are run by snakemake. Each entry on the first level is a scenario. Each scenario can contain configuration overrides with respect to the config/config.yaml settings. -# -# Example -# -# custom-scenario: # name of the scenario -# electricity: -# renewable_carriers: [wind, solar] # override the list of renewable carriers diff --git a/scripts/create_scenarios.py b/scripts/create_scenarios.py deleted file mode 100644 index 40a3c331..00000000 --- a/scripts/create_scenarios.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT - -# This script helps to generate a scenarios.yaml file for PyPSA-Eur. -# You can modify the template to your needs and define all possible combinations of config values that should be considered. - - -import itertools - -# Insert your config values that should be altered in the template. -# Change `config_section` and `config_section2` to the actual config sections. -template = """ -scenario{scenario_number}: - config_section: - config_value: {config_value} - - config_section2: - config_key2: {config_value2} -""" - -# Define all possible combinations of config values. -# This must define all config values that are used in the template. -config_values = dict(config_values=["true", "false"], config_values2=[1, 2, 3, 4, 5]) - -combinations = [ - dict(zip(config_values.keys(), values)) - for values in itertools.product(*config_values.values()) -] - -# write the scenarios to a file -filename = "../config/scenarios.yaml" -with open(filename, "w") as f: - for i, config in enumerate(combinations): - f.write(template.format(scenario_number=i, **config)) From 672d7b9538ed9c1ad811a43dd056ff7cb60d202a Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 16 Aug 2023 13:45:59 +0200 Subject: [PATCH 096/591] force add scenarios.yaml / create_scenarios --- config/scenarios.yaml | 12 ++++++++++++ scripts/create_scenarios.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 config/scenarios.yaml create mode 100644 scripts/create_scenarios.py diff --git a/config/scenarios.yaml b/config/scenarios.yaml new file mode 100644 index 00000000..37d32243 --- /dev/null +++ b/config/scenarios.yaml @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT + +# This file is used to define the scenarios that are run by snakemake. Each entry on the first level is a scenario. Each scenario can contain configuration overrides with respect to the config/config.yaml settings. +# +# Example +# +# custom-scenario: # name of the scenario +# electricity: +# renewable_carriers: [wind, solar] # override the list of renewable carriers diff --git a/scripts/create_scenarios.py b/scripts/create_scenarios.py new file mode 100644 index 00000000..40a3c331 --- /dev/null +++ b/scripts/create_scenarios.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT + +# This script helps to generate a scenarios.yaml file for PyPSA-Eur. +# You can modify the template to your needs and define all possible combinations of config values that should be considered. + + +import itertools + +# Insert your config values that should be altered in the template. +# Change `config_section` and `config_section2` to the actual config sections. +template = """ +scenario{scenario_number}: + config_section: + config_value: {config_value} + + config_section2: + config_key2: {config_value2} +""" + +# Define all possible combinations of config values. +# This must define all config values that are used in the template. +config_values = dict(config_values=["true", "false"], config_values2=[1, 2, 3, 4, 5]) + +combinations = [ + dict(zip(config_values.keys(), values)) + for values in itertools.product(*config_values.values()) +] + +# write the scenarios to a file +filename = "../config/scenarios.yaml" +with open(filename, "w") as f: + for i, config in enumerate(combinations): + f.write(template.format(scenario_number=i, **config)) From 9d4ce430cc6abc73941ab9acebb35d9b0db919c4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 17 Aug 2023 10:17:12 +0200 Subject: [PATCH 097/591] electricity demand: remove powerstastics flag, merge sources in retrieve_electricity_demand --- doc/configtables/load.csv | 1 - doc/retrieve.rst | 2 +- rules/build_electricity.smk | 2 +- rules/retrieve.smk | 2 +- scripts/build_electricity_demand.py | 172 ++++++++++--------------- scripts/retrieve_electricity_demand.py | 16 ++- 6 files changed, 85 insertions(+), 110 deletions(-) diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index 6e98f881..ac666947 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -1,5 +1,4 @@ ,Unit,Values,Description -power_statistics,bool,"{true, false}",Whether to load the electricity consumption data of the ENTSOE power statistics (only for files from 2019 and before) or from the ENTSOE transparency data (only has load data from 2015 onwards). interpolate_limit,hours,integer,"Maximum gap size (consecutive nans) which interpolated linearly." time_shift_for_large_gaps,string,string,"Periods which are used for copying time-slices in order to fill large gaps of nans. Have to be valid ``pandas`` period strings." manual_adjustments,bool,"{true, false}","Whether to adjust the load data manually according to the function in :func:`manual_adjustment`." diff --git a/doc/retrieve.rst b/doc/retrieve.rst index 4786581e..66c996f5 100644 --- a/doc/retrieve.rst +++ b/doc/retrieve.rst @@ -91,7 +91,7 @@ None. **Outputs** -- ``data/load_raw.csv`` +- ``data/electricity_demand.csv`` Rule ``retrieve_cost_data`` diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index b359868f..2e7a0c30 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -24,7 +24,7 @@ rule build_electricity_demand: countries=config_provider("countries"), load=config_provider("load"), input: - ancient("data/load_raw.csv"), + ancient("data/electricity_demand.csv"), output: RESOURCES + "load.csv", log: diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 5af0ffb5..34e2eb7c 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -159,7 +159,7 @@ if config["enable"]["retrieve"]: params: versions=["2019-06-05", "2020-10-06"], output: - "data/load_raw.csv", + "data/electricity_demand.csv", log: "logs/retrieve_electricity_demand.log", resources: diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 60d40e1e..3fd9d605 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -31,7 +31,7 @@ Relevant Settings Inputs ------ -- ``data/load_raw.csv``: +- ``data/electricity_demand.csv``: Outputs ------- @@ -49,7 +49,7 @@ from _helpers import configure_logging, set_scenario_config from pandas import Timedelta as Delta -def load_timeseries(fn, years, countries, powerstatistics=True): +def load_timeseries(fn, years, countries): """ Read load data from OPSD time-series package version 2020-10-06. @@ -62,10 +62,6 @@ def load_timeseries(fn, years, countries, powerstatistics=True): File name or url location (file format .csv) countries : listlike Countries for which to read load data. - powerstatistics: bool - Whether the electricity consumption data of the ENTSOE power - statistics (if true) or of the ENTSOE transparency map (if false) - should be parsed. Returns ------- @@ -74,17 +70,9 @@ def load_timeseries(fn, years, countries, powerstatistics=True): """ logger.info(f"Retrieving load data from '{fn}'.") - pattern = "power_statistics" if powerstatistics else "transparency" - pattern = f"_load_actual_entsoe_{pattern}" - - def rename(s): - return s[: -len(pattern)] - return ( pd.read_csv(fn, index_col=0, parse_dates=[0]) .tz_localize(None) - .filter(like=pattern) - .rename(columns=rename) .dropna(how="all", axis=0) .rename(columns={"GB_UKM": "GB"}) .filter(items=countries) @@ -149,17 +137,18 @@ def copy_timeslice(load, cntry, start, stop, delta, fn_load=None): ].values elif fn_load is not None: duration = pd.date_range(freq="h", start=start - delta, end=stop - delta) - load_raw = load_timeseries(fn_load, duration, [cntry], powerstatistics) + load_raw = load_timeseries(fn_load, duration, [cntry]) load.loc[start:stop, cntry] = load_raw.loc[ start - delta : stop - delta, cntry ].values -def manual_adjustment(load, fn_load, powerstatistics): +def manual_adjustment(load, fn_load): """ Adjust gaps manual for load data from OPSD time-series package. - 1. For the ENTSOE power statistics load data (if powerstatistics is True) + 1. For years later than 2015 for which the load data is mainly taken from the + ENTSOE power statistics Kosovo (KV) and Albania (AL) do not exist in the data set. Kosovo gets the same load curve as Serbia and Albania the same as Macdedonia, both scaled @@ -167,7 +156,8 @@ def manual_adjustment(load, fn_load, powerstatistics): IEA Data browser [0] for the year 2013. - 2. For the ENTSOE transparency load data (if powerstatistics is False) + 2. For years earlier than 2015 for which the load data is mainly taken from the + ENTSOE transparency platforms Albania (AL) and Macedonia (MK) do not exist in the data set. Both get the same load curve as Montenegro, scaled by the corresponding ratio of total energy @@ -183,9 +173,6 @@ def manual_adjustment(load, fn_load, powerstatistics): ---------- load : pd.DataFrame Load time-series with UTC timestamps x ISO-2 countries - powerstatistics: bool - Whether argument load comprises the electricity consumption data of - the ENTSOE power statistics or of the ENTSOE transparency map load_fn: str File name or url location (file format .csv) @@ -195,88 +182,66 @@ def manual_adjustment(load, fn_load, powerstatistics): Manual adjusted and interpolated load time-series with UTC timestamps x ISO-2 countries """ - if powerstatistics: - if "MK" in load.columns: - if "AL" not in load.columns or load.AL.isnull().values.all(): - load["AL"] = load["MK"] * (4.1 / 7.4) - if "RS" in load.columns: - if "KV" not in load.columns or load.KV.isnull().values.all(): - load["KV"] = load["RS"] * (4.8 / 27.0) + if "MK" in load: + if "AL" not in load or load.AL.isnull().values.all(): + load["AL"] = load["MK"] * (4.1 / 7.4) + if "RS" in load: + if "KV" not in load or load.KV.isnull().values.all(): + load["KV"] = load["RS"] * (4.8 / 27.0) + if "ME" in load: + if "AL" not in load and "AL" in countries: + load["AL"] = load.ME * (5.7 / 2.9) + if "MK" not in load and "MK" in countries: + load["MK"] = load.ME * (6.7 / 2.9) + if "BA" not in load and "BA" in countries: + load["BA"] = load.HR * (11.0 / 16.2) - copy_timeslice( - load, "GR", "2015-08-11 21:00", "2015-08-15 20:00", Delta(weeks=1) - ) - copy_timeslice( - load, "AT", "2018-12-31 22:00", "2019-01-01 22:00", Delta(days=2) - ) - copy_timeslice( - load, "CH", "2010-01-19 07:00", "2010-01-19 22:00", Delta(days=1) - ) - copy_timeslice( - load, "CH", "2010-03-28 00:00", "2010-03-28 21:00", Delta(days=1) - ) - # is a WE, so take WE before - copy_timeslice( - load, "CH", "2010-10-08 13:00", "2010-10-10 21:00", Delta(weeks=1) - ) - copy_timeslice( - load, "CH", "2010-11-04 04:00", "2010-11-04 22:00", Delta(days=1) - ) - copy_timeslice( - load, "NO", "2010-12-09 11:00", "2010-12-09 18:00", Delta(days=1) - ) - # whole january missing - copy_timeslice( - load, - "GB", - "2010-01-01 00:00", - "2010-01-31 23:00", - Delta(days=-365), - fn_load, - ) - # 1.1. at midnight gets special treatment - copy_timeslice( - load, - "IE", - "2016-01-01 00:00", - "2016-01-01 01:00", - Delta(days=-366), - fn_load, - ) - copy_timeslice( - load, - "PT", - "2016-01-01 00:00", - "2016-01-01 01:00", - Delta(days=-366), - fn_load, - ) - copy_timeslice( - load, - "GB", - "2016-01-01 00:00", - "2016-01-01 01:00", - Delta(days=-366), - fn_load, - ) + copy_timeslice(load, "GR", "2015-08-11 21:00", "2015-08-15 20:00", Delta(weeks=1)) + copy_timeslice(load, "AT", "2018-12-31 22:00", "2019-01-01 22:00", Delta(days=2)) + copy_timeslice(load, "CH", "2010-01-19 07:00", "2010-01-19 22:00", Delta(days=1)) + copy_timeslice(load, "CH", "2010-03-28 00:00", "2010-03-28 21:00", Delta(days=1)) + # is a WE, so take WE before + copy_timeslice(load, "CH", "2010-10-08 13:00", "2010-10-10 21:00", Delta(weeks=1)) + copy_timeslice(load, "CH", "2010-11-04 04:00", "2010-11-04 22:00", Delta(days=1)) + copy_timeslice(load, "NO", "2010-12-09 11:00", "2010-12-09 18:00", Delta(days=1)) + # whole january missing + copy_timeslice( + load, + "GB", + "2010-01-01 00:00", + "2010-01-31 23:00", + Delta(days=-365), + fn_load, + ) + # 1.1. at midnight gets special treatment + copy_timeslice( + load, + "IE", + "2016-01-01 00:00", + "2016-01-01 01:00", + Delta(days=-366), + fn_load, + ) + copy_timeslice( + load, + "PT", + "2016-01-01 00:00", + "2016-01-01 01:00", + Delta(days=-366), + fn_load, + ) + copy_timeslice( + load, + "GB", + "2016-01-01 00:00", + "2016-01-01 01:00", + Delta(days=-366), + fn_load, + ) - else: - if "ME" in load: - if "AL" not in load and "AL" in countries: - load["AL"] = load.ME * (5.7 / 2.9) - if "MK" not in load and "MK" in countries: - load["MK"] = load.ME * (6.7 / 2.9) - if "BA" not in load and "BA" in countries: - load["BA"] = load.HR * (11.0 / 16.2) - copy_timeslice( - load, "BG", "2018-10-27 21:00", "2018-10-28 22:00", Delta(weeks=1) - ) - copy_timeslice( - load, "LU", "2019-01-02 11:00", "2019-01-05 05:00", Delta(weeks=-1) - ) - copy_timeslice( - load, "LU", "2019-02-05 20:00", "2019-02-06 19:00", Delta(weeks=-1) - ) + copy_timeslice(load, "BG", "2018-10-27 21:00", "2018-10-28 22:00", Delta(weeks=1)) + copy_timeslice(load, "LU", "2019-01-02 11:00", "2019-01-05 05:00", Delta(weeks=-1)) + copy_timeslice(load, "LU", "2019-02-05 20:00", "2019-02-06 19:00", Delta(weeks=-1)) return load @@ -290,17 +255,16 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - powerstatistics = snakemake.params.load["power_statistics"] interpolate_limit = snakemake.params.load["interpolate_limit"] countries = snakemake.params.countries snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) years = slice(snapshots[0], snapshots[-1]) time_shift = snakemake.params.load["time_shift_for_large_gaps"] - load = load_timeseries(snakemake.input[0], years, countries, powerstatistics) + load = load_timeseries(snakemake.input[0], years, countries) if snakemake.params.load["manual_adjustments"]: - load = manual_adjustment(load, snakemake.input[0], powerstatistics) + load = manual_adjustment(load, snakemake.input[0]) if load.empty: logger.warning("Build electricity demand time series is empty.") diff --git a/scripts/retrieve_electricity_demand.py b/scripts/retrieve_electricity_demand.py index 58511857..01dc4aa8 100644 --- a/scripts/retrieve_electricity_demand.py +++ b/scripts/retrieve_electricity_demand.py @@ -20,7 +20,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("retrieve_eletricity_demand") + snakemake = mock_snakemake("retrieve_electricity_demand") rootpath = ".." else: rootpath = "." @@ -33,5 +33,17 @@ if __name__ == "__main__": pd.read_csv(url.format(version=version), index_col=0) for version in snakemake.params.versions ] - res = pd.concat([df1, df2[df2.index > df1.index[-1]]], join="inner") + combined = pd.concat([df1, df2[df2.index > df1.index[-1]]]) + + pattern = "_load_actual_entsoe_transparency" + transparency = combined.filter(like=pattern).rename( + columns=lambda x: x.replace(pattern, "") + ) + pattern = "_load_actual_entsoe_power_statistics" + powerstatistics = combined.filter(like=pattern).rename( + columns=lambda x: x.replace(pattern, "") + ) + + res = transparency.fillna(powerstatistics) + res.to_csv(snakemake.output[0]) From 91eff472a7748dc617d19cd9ad788bf81144c356 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 17 Aug 2023 12:31:07 +0200 Subject: [PATCH 098/591] scenario-management: fix set_scenario_config function; apply config_provider to some direct inputs --- rules/build_electricity.smk | 8 ++++---- scripts/_helpers.py | 8 +++++--- scripts/base_network.py | 2 +- scripts/build_electricity_demand.py | 32 ++++++++++++++++------------- scripts/build_renewable_profiles.py | 4 +++- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 2e7a0c30..5f44d2ef 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -214,19 +214,19 @@ rule build_renewable_profiles: corine=ancient("data/bundle/corine/g250_clc06_V18_5.tif"), natura=lambda w: ( RESOURCES + "natura.tiff" - if config["renewable"][w.technology]["natura"] + if config_provider("renewable", w.technology, "natura")(w) else [] ), gebco=ancient( lambda w: ( "data/bundle/GEBCO_2014_2D.nc" - if config["renewable"][w.technology].get("max_depth") + if config_provider("renewable", w.technology)(w).get("max_depth") else [] ) ), ship_density=lambda w: ( RESOURCES + "shipdensity_raster.tif" - if "ship_threshold" in config["renewable"][w.technology].keys() + if "ship_threshold" in config_provider("renewable", w.technology)(w).keys() else [] ), country_shapes=RESOURCES + "country_shapes.geojson", @@ -238,7 +238,7 @@ rule build_renewable_profiles: ), cutout=lambda w: "cutouts/" + CDIR - + config["renewable"][w.technology]["cutout"] + + config_provider("renewable", w.technology, "cutout")(w) + ".nc", output: profile=RESOURCES + "profile_{technology}.nc", diff --git a/scripts/_helpers.py b/scripts/_helpers.py index c66d708e..7a356a44 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -31,10 +31,12 @@ def mute_print(): def set_scenario_config(snakemake): - if "scenario_config" in snakemake.input: - with open(snakemake.input.scenario_config, "r") as f: + if snakemake.config["run"]["scenarios"]: + script_dir = Path(__file__).parent.resolve() + root_dir = script_dir.parent + with open(root_dir / snakemake.config["scenariofile"], "r") as f: scenario_config = yaml.safe_load(f) - update_config(snakemake.config, scenario_config) + update_config(snakemake.config, scenario_config[snakemake.wildcards.run]) def configure_logging(snakemake, skip_handlers=False): diff --git a/scripts/base_network.py b/scripts/base_network.py index b5304109..32b54d28 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -743,7 +743,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("base_network") + snakemake = mock_snakemake("base_network", run="network2019") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 3fd9d605..376af247 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -68,8 +68,6 @@ def load_timeseries(fn, years, countries): load : pd.DataFrame Load time-series with UTC timestamps x ISO-2 countries """ - logger.info(f"Retrieving load data from '{fn}'.") - return ( pd.read_csv(fn, index_col=0, parse_dates=[0]) .tz_localize(None) @@ -182,20 +180,26 @@ def manual_adjustment(load, fn_load): Manual adjusted and interpolated load time-series with UTC timestamps x ISO-2 countries """ - if "MK" in load: - if "AL" not in load or load.AL.isnull().values.all(): - load["AL"] = load["MK"] * (4.1 / 7.4) - if "RS" in load: - if "KV" not in load or load.KV.isnull().values.all(): - load["KV"] = load["RS"] * (4.8 / 27.0) - if "ME" in load: - if "AL" not in load and "AL" in countries: + + if "AL" not in load and "AL" in countries: + if "ME" in load: load["AL"] = load.ME * (5.7 / 2.9) - if "MK" not in load and "MK" in countries: - load["MK"] = load.ME * (6.7 / 2.9) - if "BA" not in load and "BA" in countries: + elif "MK" in load: + load["AL"] = load["MK"] * (4.1 / 7.4) + + if "MK" in countries: + if "MK" not in load or load.MK.isnull().sum() > len(load) / 2: + if "ME" in load: + load["MK"] = load.ME * (6.7 / 2.9) + + if "BA" not in load and "BA" in countries: + if "ME" in load: load["BA"] = load.HR * (11.0 / 16.2) + if "KV" not in load or load.KV.isnull().values.all(): + if "RS" in load: + load["KV"] = load["RS"] * (4.8 / 27.0) + copy_timeslice(load, "GR", "2015-08-11 21:00", "2015-08-15 20:00", Delta(weeks=1)) copy_timeslice(load, "AT", "2018-12-31 22:00", "2019-01-01 22:00", Delta(days=2)) copy_timeslice(load, "CH", "2010-01-19 07:00", "2010-01-19 22:00", Delta(days=1)) @@ -250,7 +254,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_electricity_demand") + snakemake = mock_snakemake("build_electricity_demand", run="network2019") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 40b3151d..c6d42e6b 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -200,7 +200,9 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_renewable_profiles", technology="solar") + snakemake = mock_snakemake( + "build_renewable_profiles", technology="solar", run="network2019" + ) configure_logging(snakemake) set_scenario_config(snakemake) From ebb5da655ef8627d534e1995df18fdeac93b54b2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 17 Aug 2023 12:56:34 +0200 Subject: [PATCH 099/591] scenarios: add collect function plot_elec_networks --- rules/collect.smk | 10 ++++++++++ scripts/plot_statistics.py | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/rules/collect.smk b/rules/collect.smk index 8a64b577..70dc4641 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -76,6 +76,16 @@ rule solve_sector_networks: ), +rule plot_elec_networks: + input: + expand( + RESULTS + + "figures/.statistics_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", + **config["scenario"], + run=config["run"]["name"] + ), + + rule plot_networks: input: expand( diff --git a/scripts/plot_statistics.py b/scripts/plot_statistics.py index a0a3e71d..11293c08 100644 --- a/scripts/plot_statistics.py +++ b/scripts/plot_statistics.py @@ -61,7 +61,7 @@ if __name__ == "__main__": fig, ax = plt.subplots() ds = n.statistics.installed_capacity().dropna() ds = ds.drop("Line") - ds = ds.drop(("Generator", "Load")) + ds = ds.drop(("Generator", "Load"), errors="ignore") ds = ds / 1e3 ds.attrs["unit"] = "GW" plot_static_per_carrier(ds, ax) @@ -70,7 +70,7 @@ if __name__ == "__main__": fig, ax = plt.subplots() ds = n.statistics.optimal_capacity() ds = ds.drop("Line") - ds = ds.drop(("Generator", "Load")) + ds = ds.drop(("Generator", "Load"), errors="ignore") ds = ds / 1e3 ds.attrs["unit"] = "GW" plot_static_per_carrier(ds, ax) From 1810bbd4b3243ffbf516ccaa58fe5b92adf463d1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 21 Aug 2023 12:24:27 +0200 Subject: [PATCH 100/591] make set_scenario_config robust against mock_snakemake and subworkflow --- scripts/_helpers.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 7a356a44..b41ed60d 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -31,11 +31,16 @@ def mute_print(): def set_scenario_config(snakemake): - if snakemake.config["run"]["scenarios"]: - script_dir = Path(__file__).parent.resolve() - root_dir = script_dir.parent - with open(root_dir / snakemake.config["scenariofile"], "r") as f: - scenario_config = yaml.safe_load(f) + if snakemake.config["run"]["scenarios"] and "run" in snakemake.wildcards: + try: + with open(snakemake.config["scenariofile"], "r") as f: + scenario_config = yaml.safe_load(f) + except FileNotFoundError: + # fallback for mock_snakemake + script_dir = Path(__file__).parent.resolve() + root_dir = script_dir.parent + with open(root_dir / snakemake.config["scenariofile"], "r") as f: + scenario_config = yaml.safe_load(f) update_config(snakemake.config, scenario_config[snakemake.wildcards.run]) From 7b9ab155f47f156f2900b711e9a6ebd893a512c0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 22 Aug 2023 18:15:50 +0200 Subject: [PATCH 101/591] helpers: fix condition in set_scenario_config prepare_sector: insert set_scenario_config --- scripts/_helpers.py | 2 +- scripts/prepare_sector_network.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index b41ed60d..3951be18 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -31,7 +31,7 @@ def mute_print(): def set_scenario_config(snakemake): - if snakemake.config["run"]["scenarios"] and "run" in snakemake.wildcards: + if snakemake.config["run"]["scenarios"] and "run" in snakemake.wildcards.keys(): try: with open(snakemake.config["scenariofile"], "r") as f: scenario_config = yaml.safe_load(f) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 0c1faacc..1ee42a72 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -17,7 +17,12 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import generate_periodic_profiles, update_config_with_sector_opts +from _helpers import ( + configure_logging, + generate_periodic_profiles, + set_scenario_config, + update_config_with_sector_opts, +) from add_electricity import calculate_annuity, sanitize_carriers from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement @@ -3286,6 +3291,7 @@ if __name__ == "__main__": ) logging.basicConfig(level=snakemake.config["logging"]["level"]) + set_scenario_config(snakemake) update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) From 62c61438636494a9dc2a917e1706ae0df25e2d8c Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 23 Aug 2023 17:14:57 +0200 Subject: [PATCH 102/591] scenario-management: reenable shared resources, make shared resources wildcards dependent --- .github/workflows/ci.yaml | 2 +- Snakefile | 26 +- config/config.default.yaml | 5 +- config/scenarios.yaml | 26 + config/test/config.scenarios.electricity.yaml | 7 +- doc/configtables/run.csv | 8 +- doc/configtables/toplevel.csv | 1 - rules/build_electricity.smk | 184 +++---- rules/build_sector.smk | 483 ++++++++++-------- rules/collect.smk | 6 +- rules/common.smk | 4 +- rules/postprocess.smk | 2 +- rules/retrieve.smk | 4 +- rules/solve_electricity.smk | 2 +- rules/solve_myopic.smk | 16 +- rules/solve_overnight.smk | 3 +- rules/validate.smk | 20 +- scripts/__init__.py | 4 + scripts/_helpers.py | 47 +- 19 files changed, 479 insertions(+), 371 deletions(-) create mode 100644 scripts/__init__.py diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 68bffc4c..6cbee85c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -83,7 +83,7 @@ jobs: snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime - snakemake -call solve_elec_networks --configfile config/test/config.scenarios.electricity.yaml -n + snakemake -call solve_elec_networks --configfile config/test/config.scenarios.electricity.yaml - name: Upload artifacts uses: actions/upload-artifact@v3 diff --git a/Snakefile b/Snakefile index e495e7d3..55b90d5d 100644 --- a/Snakefile +++ b/Snakefile @@ -8,6 +8,7 @@ from pathlib import Path import yaml from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider from snakemake.utils import min_version +from scripts._helpers import path_provider min_version("7.7") HTTP = HTTPRemoteProvider() @@ -24,20 +25,23 @@ COSTS = f"data/costs_{config['costs']['year']}.csv" ATLITE_NPROCESSES = config["atlite"].get("nprocesses", 4) run = config["run"] -if run.get("scenarios", False): - if run["shared_resources"]: - raise ValueError("Cannot use shared resources with scenarios") - scenarios = yaml.safe_load(Path(config["scenariofile"]).read_text()) +scenario = run.get("scenario", {}) +if run["name"]: + if scenario.get("enable"): + fn = Path(scenario["file"]) + scenarios = yaml.safe_load(fn.read_text()) RDIR = "{run}/" -elif run["name"]: - RDIR = run["name"] + "/" else: RDIR = "" -CDIR = RDIR if not run.get("shared_cutouts") else "" +# for possibly shared resources +logs = path_provider("logs/", RDIR, run["shared_resources"]) +benchmarks = path_provider("benchmarks/", RDIR, run["shared_resources"]) +resources = path_provider("resources/", RDIR, run["shared_resources"]) + +CDIR = "" if run["shared_cutouts"] else RDIR LOGS = "logs/" + RDIR BENCHMARKS = "benchmarks/" + RDIR -RESOURCES = "resources/" + RDIR if not run.get("shared_resources") else "resources/" RESULTS = "results/" + RDIR @@ -86,9 +90,9 @@ rule dag: message: "Creating DAG of workflow." output: - dot=RESOURCES + "dag.dot", - pdf=RESOURCES + "dag.pdf", - png=RESOURCES + "dag.png", + dot=resources("dag.dot"), + pdf=resources("dag.pdf"), + png=resources("dag.png"), conda: "envs/environment.yaml" shell: diff --git a/config/config.default.yaml b/config/config.default.yaml index 5357db8d..238c3d41 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -5,7 +5,6 @@ # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#top-level-configuration version: 0.8.1 tutorial: false -scenariofile: config/scenarios.yaml logging: level: INFO @@ -22,7 +21,9 @@ remote: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#run run: name: "" - scenarios: false + scenarios: + enable: false + file: config/scenarios.yaml disable_progressbar: false shared_resources: false shared_cutouts: true diff --git a/config/scenarios.yaml b/config/scenarios.yaml index 37d32243..c493311f 100644 --- a/config/scenarios.yaml +++ b/config/scenarios.yaml @@ -10,3 +10,29 @@ # custom-scenario: # name of the scenario # electricity: # renewable_carriers: [wind, solar] # override the list of renewable carriers + + +network2013: + snapshots: + start: "2013-01-01" + end: "2014-01-01" + inclusive: 'left' + + +network2019: + snapshots: + start: "2019-01-01" + end: "2020-01-01" + inclusive: 'left' + + renewable: + onwind: + cutout: europe-2019-era5 + offwind-ac: + cutout: europe-2019-era5 + offwind-dc: + cutout: europe-2019-era5 + solar: + cutout: europe-2019-era5 + hydro: + cutout: europe-2019-era5 diff --git a/config/test/config.scenarios.electricity.yaml b/config/test/config.scenarios.electricity.yaml index 0e4ced04..63b1892b 100644 --- a/config/test/config.scenarios.electricity.yaml +++ b/config/test/config.scenarios.electricity.yaml @@ -3,15 +3,16 @@ # SPDX-License-Identifier: CC0-1.0 tutorial: true -scenariofile: "config/test/scenarios.electricity.yaml" run: name: - test-elec-no-offshore-wind - test-elec-no-onshore-wind - scenarios: true + scenario: + enable: true + file: "config/test/scenarios.electricity.yaml" disable_progressbar: true - shared_resources: false # cannot be true if scenarios is true + shared_resources: base shared_cutouts: true scenario: diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index 2d5cf5d9..3d8e4e8c 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -1,6 +1,8 @@ ,Unit,Values,Description -name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenarios`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenariofile``." -scenarios,--,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``scenariofile``." +name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenario: enable`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenario: file``." +scenario,,, +-- enable,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``file``." +-- file,str,,Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``create_scenarios.py`` script in ``scripts``. disable_progrssbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." -shared_resources,bool,"{true, false}","Switch to select whether resources should be shared across runs." +shared_resources,bool/str,,"Switch to select whether resources should be shared across runs. If a string is passed, it is assumed to be a wildcard or 'base' that indicates the cutoff after which resources are no longer shared. If 'base' is passed, resources before creating the elec.nc file are shared." shared_cutouts,bool,"{true, false}","Switch to select whether cutouts should be shared across runs." diff --git a/doc/configtables/toplevel.csv b/doc/configtables/toplevel.csv index 8cbb3e56..67954389 100644 --- a/doc/configtables/toplevel.csv +++ b/doc/configtables/toplevel.csv @@ -1,7 +1,6 @@ ,Unit,Values,Description version,--,0.x.x,Version of PyPSA-Eur. Descriptive only. tutorial,bool,"{true, false}",Switch to retrieve the tutorial data set instead of the full data set. -scenariofile,str,,Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``create_scenarios.py`` script in ``scripts``. logging,,, -- level,--,"Any of {'INFO', 'WARNING', 'ERROR'}","Restrict console outputs to all infos, warning or errors only" -- format,--,,Custom format for log messages. See `LogRecord `_ attributes. diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 5f44d2ef..be72be6d 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -8,7 +8,7 @@ if config["enable"].get("prepare_links_p_nom", False): output: "data/links_p_nom.csv", log: - LOGS + "prepare_links_p_nom.log", + logs("prepare_links_p_nom.log"), threads: 1 resources: mem_mb=1500, @@ -26,9 +26,9 @@ rule build_electricity_demand: input: ancient("data/electricity_demand.csv"), output: - RESOURCES + "load.csv", + resources("load.csv"), log: - LOGS + "build_electricity_demand.log", + logs("build_electricity_demand.log"), resources: mem_mb=5000, conda: @@ -43,12 +43,12 @@ rule build_powerplants: custom_powerplants=config_provider("electricity", "custom_powerplants"), countries=config_provider("countries"), input: - base_network=RESOURCES + "networks/base.nc", + base_network=resources("networks/base.nc"), custom_powerplants="data/custom_powerplants.csv", output: - RESOURCES + "powerplants.csv", + resources("powerplants.csv"), log: - LOGS + "build_powerplants.log", + logs("build_powerplants.log"), threads: 1 resources: mem_mb=5000, @@ -74,15 +74,15 @@ rule base_network: parameter_corrections="data/parameter_corrections.yaml", links_p_nom="data/links_p_nom.csv", links_tyndp="data/links_tyndp.csv", - country_shapes=RESOURCES + "country_shapes.geojson", - offshore_shapes=RESOURCES + "offshore_shapes.geojson", - europe_shape=RESOURCES + "europe_shape.geojson", + country_shapes=resources("country_shapes.geojson"), + offshore_shapes=resources("offshore_shapes.geojson"), + europe_shape=resources("europe_shape.geojson"), output: - RESOURCES + "networks/base.nc", + resources("networks/base.nc"), log: - LOGS + "base_network.log", + logs("base_network.log"), benchmark: - BENCHMARKS + "base_network" + benchmarks("base_network") threads: 1 resources: mem_mb=1500, @@ -104,12 +104,12 @@ rule build_shapes: ch_cantons=ancient("data/bundle/ch_cantons.csv"), ch_popgdp=ancient("data/bundle/je-e-21.03.02.xls"), output: - country_shapes=RESOURCES + "country_shapes.geojson", - offshore_shapes=RESOURCES + "offshore_shapes.geojson", - europe_shape=RESOURCES + "europe_shape.geojson", - nuts3_shapes=RESOURCES + "nuts3_shapes.geojson", + country_shapes=resources("country_shapes.geojson"), + offshore_shapes=resources("offshore_shapes.geojson"), + europe_shape=resources("europe_shape.geojson"), + nuts3_shapes=resources("nuts3_shapes.geojson"), log: - LOGS + "build_shapes.log", + logs("build_shapes.log"), threads: 1 resources: mem_mb=1500, @@ -123,14 +123,14 @@ rule build_bus_regions: params: countries=config_provider("countries"), input: - country_shapes=RESOURCES + "country_shapes.geojson", - offshore_shapes=RESOURCES + "offshore_shapes.geojson", - base_network=RESOURCES + "networks/base.nc", + country_shapes=resources("country_shapes.geojson"), + offshore_shapes=resources("offshore_shapes.geojson"), + base_network=resources("networks/base.nc"), output: - regions_onshore=RESOURCES + "regions_onshore.geojson", - regions_offshore=RESOURCES + "regions_offshore.geojson", + regions_onshore=resources("regions_onshore.geojson"), + regions_offshore=resources("regions_offshore.geojson"), log: - LOGS + "build_bus_regions.log", + logs("build_bus_regions.log"), threads: 1 resources: mem_mb=1000, @@ -147,8 +147,8 @@ if config["enable"].get("build_cutout", False): snapshots=config_provider("snapshots"), cutouts=config_provider("atlite", "cutouts"), input: - regions_onshore=RESOURCES + "regions_onshore.geojson", - regions_offshore=RESOURCES + "regions_offshore.geojson", + regions_onshore=resources("regions_onshore.geojson"), + regions_offshore=resources("regions_offshore.geojson"), output: protected("cutouts/" + CDIR + "{cutout}.nc"), log: @@ -171,11 +171,11 @@ if config["enable"].get("build_natura_raster", False): natura=ancient("data/bundle/natura/Natura2000_end2015.shp"), cutouts=expand("cutouts/" + CDIR + "{cutouts}.nc", **config["atlite"]), output: - RESOURCES + "natura.tiff", + resources("natura.tiff"), resources: mem_mb=5000, log: - LOGS + "build_natura_raster.log", + logs("build_natura_raster.log"), conda: "../envs/environment.yaml" script: @@ -193,13 +193,13 @@ rule build_ship_raster: ], ), output: - RESOURCES + "shipdensity_raster.tif", + resources("shipdensity_raster.tif"), log: - LOGS + "build_ship_raster.log", + logs("build_ship_raster.log"), resources: mem_mb=5000, benchmark: - BENCHMARKS + "build_ship_raster" + benchmarks("build_ship_raster") conda: "../envs/environment.yaml" script: @@ -210,10 +210,10 @@ rule build_renewable_profiles: params: renewable=config_provider("renewable"), input: - base_network=RESOURCES + "networks/base.nc", + base_network=resources("networks/base.nc"), corine=ancient("data/bundle/corine/g250_clc06_V18_5.tif"), natura=lambda w: ( - RESOURCES + "natura.tiff" + resources("natura.tiff") if config_provider("renewable", w.technology, "natura")(w) else [] ), @@ -225,27 +225,27 @@ rule build_renewable_profiles: ) ), ship_density=lambda w: ( - RESOURCES + "shipdensity_raster.tif" + resources("shipdensity_raster.tif") if "ship_threshold" in config_provider("renewable", w.technology)(w).keys() else [] ), - country_shapes=RESOURCES + "country_shapes.geojson", - offshore_shapes=RESOURCES + "offshore_shapes.geojson", + country_shapes=resources("country_shapes.geojson"), + offshore_shapes=resources("offshore_shapes.geojson"), regions=lambda w: ( - RESOURCES + "regions_onshore.geojson" + resources("regions_onshore.geojson") if w.technology in ("onwind", "solar") - else RESOURCES + "regions_offshore.geojson" + else resources("regions_offshore.geojson") ), cutout=lambda w: "cutouts/" + CDIR + config_provider("renewable", w.technology, "cutout")(w) + ".nc", output: - profile=RESOURCES + "profile_{technology}.nc", + profile=resources("profile_{technology}.nc"), log: - LOGS + "build_renewable_profile_{technology}.log", + logs("build_renewable_profile_{technology}.log"), benchmark: - BENCHMARKS + "build_renewable_profiles_{technology}" + benchmarks("build_renewable_profiles_{technology}") threads: ATLITE_NPROCESSES resources: mem_mb=ATLITE_NPROCESSES * 5000, @@ -262,10 +262,10 @@ rule build_monthly_prices: co2_price_raw="data/validation/emission-spot-primary-market-auction-report-2019-data.xls", fuel_price_raw="data/validation/energy-price-trends-xlsx-5619002.xlsx", output: - co2_price=RESOURCES + "co2_price.csv", - fuel_price=RESOURCES + "monthly_fuel_price.csv", + co2_price=resources("co2_price.csv"), + fuel_price=resources("monthly_fuel_price.csv"), log: - LOGS + "build_monthly_prices.log", + logs("build_monthly_prices.log"), threads: 1 resources: mem_mb=5000, @@ -280,13 +280,13 @@ rule build_hydro_profile: hydro=config_provider("renewable", "hydro"), countries=config_provider("countries"), input: - country_shapes=RESOURCES + "country_shapes.geojson", + country_shapes=resources("country_shapes.geojson"), eia_hydro_generation="data/eia_hydro_annual_generation.csv", cutout=f"cutouts/" + CDIR + config["renewable"]["hydro"]["cutout"] + ".nc", output: - RESOURCES + "profile_hydro.nc", + resources("profile_hydro.nc"), log: - LOGS + "build_hydro_profile.log", + logs("build_hydro_profile.log"), resources: mem_mb=5000, conda: @@ -299,17 +299,17 @@ if config["lines"]["dynamic_line_rating"]["activate"]: rule build_line_rating: input: - base_network=RESOURCES + "networks/base.nc", + base_network=resources("networks/base.nc"), cutout="cutouts/" + CDIR + config["lines"]["dynamic_line_rating"]["cutout"] + ".nc", output: - output=RESOURCES + "networks/line_rating.nc", + output=resources("networks/line_rating.nc"), log: - LOGS + "build_line_rating.log", + logs("build_line_rating.log"), benchmark: - BENCHMARKS + "build_line_rating" + benchmarks("build_line_rating") threads: ATLITE_NPROCESSES resources: mem_mb=ATLITE_NPROCESSES * 1000, @@ -330,7 +330,7 @@ rule add_electricity: costs=config_provider("costs"), input: **{ - f"profile_{tech}": RESOURCES + f"profile_{tech}.nc" + f"profile_{tech}": resources(f"profile_{tech}.nc") for tech in config["electricity"]["renewable_carriers"] }, **{ @@ -340,27 +340,27 @@ rule add_electricity: for attr, fn in d.items() if str(fn).startswith("data/") }, - base_network=RESOURCES + "networks/base.nc", - line_rating=RESOURCES + "networks/line_rating.nc" + base_network=resources("networks/base.nc"), + line_rating=resources("networks/line_rating.nc") if config["lines"]["dynamic_line_rating"]["activate"] - else RESOURCES + "networks/base.nc", + else resources("networks/base.nc"), tech_costs=COSTS, - regions=RESOURCES + "regions_onshore.geojson", - powerplants=RESOURCES + "powerplants.csv", + regions=resources("regions_onshore.geojson"), + powerplants=resources("powerplants.csv"), hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), geth_hydro_capacities="data/geth2015_hydro_capacities.csv", unit_commitment="data/unit_commitment.csv", - fuel_price=RESOURCES + "monthly_fuel_price.csv" + fuel_price=resources("monthly_fuel_price.csv") if config["conventional"]["dynamic_fuel_price"] else [], - load=RESOURCES + "load.csv", - nuts3_shapes=RESOURCES + "nuts3_shapes.geojson", + load=resources("load.csv"), + nuts3_shapes=resources("nuts3_shapes.geojson"), output: - RESOURCES + "networks/elec.nc", + resources("networks/elec.nc"), log: - LOGS + "add_electricity.log", + logs("add_electricity.log"), benchmark: - BENCHMARKS + "add_electricity" + benchmarks("add_electricity") threads: 1 resources: mem_mb=10000, @@ -383,20 +383,20 @@ rule simplify_network: p_max_pu=config_provider("links", "p_max_pu", default=1.0), costs=config_provider("costs"), input: - network=RESOURCES + "networks/elec.nc", + network=resources("networks/elec.nc"), tech_costs=COSTS, - regions_onshore=RESOURCES + "regions_onshore.geojson", - regions_offshore=RESOURCES + "regions_offshore.geojson", + regions_onshore=resources("regions_onshore.geojson"), + regions_offshore=resources("regions_offshore.geojson"), output: - network=RESOURCES + "networks/elec_s{simpl}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}.geojson", - regions_offshore=RESOURCES + "regions_offshore_elec_s{simpl}.geojson", - busmap=RESOURCES + "busmap_elec_s{simpl}.csv", - connection_costs=RESOURCES + "connection_costs_s{simpl}.csv", + network=resources("networks/elec_s{simpl}.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}.geojson"), + busmap=resources("busmap_elec_s{simpl}.csv"), + connection_costs=resources("connection_costs_s{simpl}.csv"), log: - LOGS + "simplify_network/elec_s{simpl}.log", + logs("simplify_network/elec_s{simpl}.log"), benchmark: - BENCHMARKS + "simplify_network/elec_s{simpl}" + benchmarks("simplify_network/elec_s{simpl}") threads: 1 resources: mem_mb=12000, @@ -422,10 +422,10 @@ rule cluster_network: length_factor=config_provider("lines", "length_factor"), costs=config_provider("costs"), input: - network=RESOURCES + "networks/elec_s{simpl}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}.geojson", - regions_offshore=RESOURCES + "regions_offshore_elec_s{simpl}.geojson", - busmap=ancient(RESOURCES + "busmap_elec_s{simpl}.csv"), + network=resources("networks/elec_s{simpl}.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}.geojson"), + busmap=ancient(resources("busmap_elec_s{simpl}.csv")), custom_busmap=( "data/custom_busmap_elec_s{simpl}_{clusters}.csv" if config["enable"].get("custom_busmap", False) @@ -433,15 +433,15 @@ rule cluster_network: ), tech_costs=COSTS, output: - network=RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", - regions_offshore=RESOURCES + "regions_offshore_elec_s{simpl}_{clusters}.geojson", - busmap=RESOURCES + "busmap_elec_s{simpl}_{clusters}.csv", - linemap=RESOURCES + "linemap_elec_s{simpl}_{clusters}.csv", + network=resources("networks/elec_s{simpl}_{clusters}.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), + busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), + linemap=resources("linemap_elec_s{simpl}_{clusters}.csv"), log: - LOGS + "cluster_network/elec_s{simpl}_{clusters}.log", + logs("cluster_network/elec_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "cluster_network/elec_s{simpl}_{clusters}" + benchmarks("cluster_network/elec_s{simpl}_{clusters}") threads: 1 resources: mem_mb=10000, @@ -457,14 +457,14 @@ rule add_extra_components: max_hours=config_provider("electricity", "max_hours"), costs=config_provider("costs"), input: - network=RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", + network=resources("networks/elec_s{simpl}_{clusters}.nc"), tech_costs=COSTS, output: - RESOURCES + "networks/elec_s{simpl}_{clusters}_ec.nc", + resources("networks/elec_s{simpl}_{clusters}_ec.nc"), log: - LOGS + "add_extra_components/elec_s{simpl}_{clusters}.log", + logs("add_extra_components/elec_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "add_extra_components/elec_s{simpl}_{clusters}_ec" + benchmarks("add_extra_components/elec_s{simpl}_{clusters}_ec") threads: 1 resources: mem_mb=4000, @@ -484,15 +484,15 @@ rule prepare_network: max_hours=config_provider("electricity", "max_hours"), costs=config_provider("costs"), input: - RESOURCES + "networks/elec_s{simpl}_{clusters}_ec.nc", + resources("networks/elec_s{simpl}_{clusters}_ec.nc"), tech_costs=COSTS, - co2_price=RESOURCES + "co2_price.csv", + co2_price=resources("co2_price.csv"), output: - RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), log: - LOGS + "prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.log", + logs("prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.log"), benchmark: - (BENCHMARKS + "prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}") + (benchmarks("prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}")) threads: 1 resources: mem_mb=4000, diff --git a/rules/build_sector.smk b/rules/build_sector.smk index cc80ab64..483dcdb7 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -5,19 +5,19 @@ rule build_population_layouts: input: - nuts3_shapes=RESOURCES + "nuts3_shapes.geojson", + nuts3_shapes=resources("nuts3_shapes.geojson"), urban_percent="data/urban_percent.csv", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - pop_layout_total=RESOURCES + "pop_layout_total.nc", - pop_layout_urban=RESOURCES + "pop_layout_urban.nc", - pop_layout_rural=RESOURCES + "pop_layout_rural.nc", + pop_layout_total=resources("pop_layout_total.nc"), + pop_layout_urban=resources("pop_layout_urban.nc"), + pop_layout_rural=resources("pop_layout_rural.nc"), log: - LOGS + "build_population_layouts.log", + logs("build_population_layouts.log"), resources: mem_mb=20000, benchmark: - BENCHMARKS + "build_population_layouts" + benchmarks("build_population_layouts") threads: 8 conda: "../envs/environment.yaml" @@ -27,19 +27,19 @@ rule build_population_layouts: rule build_clustered_population_layouts: input: - pop_layout_total=RESOURCES + "pop_layout_total.nc", - pop_layout_urban=RESOURCES + "pop_layout_urban.nc", - pop_layout_rural=RESOURCES + "pop_layout_rural.nc", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + pop_layout_total=resources("pop_layout_total.nc"), + pop_layout_urban=resources("pop_layout_urban.nc"), + pop_layout_rural=resources("pop_layout_rural.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), log: - LOGS + "build_clustered_population_layouts_{simpl}_{clusters}.log", + logs("build_clustered_population_layouts_{simpl}_{clusters}.log"), resources: mem_mb=10000, benchmark: - BENCHMARKS + "build_clustered_population_layouts/s{simpl}_{clusters}" + benchmarks("build_clustered_population_layouts/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -48,19 +48,19 @@ rule build_clustered_population_layouts: rule build_simplified_population_layouts: input: - pop_layout_total=RESOURCES + "pop_layout_total.nc", - pop_layout_urban=RESOURCES + "pop_layout_urban.nc", - pop_layout_rural=RESOURCES + "pop_layout_rural.nc", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}.geojson", + pop_layout_total=resources("pop_layout_total.nc"), + pop_layout_urban=resources("pop_layout_urban.nc"), + pop_layout_rural=resources("pop_layout_rural.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}.csv", + clustered_pop_layout=resources("pop_layout_elec_s{simpl}.csv"), resources: mem_mb=10000, log: - LOGS + "build_simplified_population_layouts_{simpl}", + logs("build_simplified_population_layouts_{simpl}"), benchmark: - BENCHMARKS + "build_simplified_population_layouts/s{simpl}" + benchmarks("build_simplified_population_layouts/s{simpl}") conda: "../envs/environment.yaml" script: @@ -73,11 +73,11 @@ if config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]: input: gas_network="data/gas_network/scigrid-gas/data/IGGIELGN_PipeSegments.geojson", output: - cleaned_gas_network=RESOURCES + "gas_network.csv", + cleaned_gas_network=resources("gas_network.csv"), resources: mem_mb=4000, log: - LOGS + "build_gas_network.log", + logs("build_gas_network.log"), conda: "../envs/environment.yaml" script: @@ -91,19 +91,21 @@ if config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]: ), entry="data/gas_network/scigrid-gas/data/IGGIELGN_BorderPoints.geojson", production="data/gas_network/scigrid-gas/data/IGGIELGN_Productions.geojson", - regions_onshore=RESOURCES - + "regions_onshore_elec_s{simpl}_{clusters}.geojson", - regions_offshore=RESOURCES - + "regions_offshore_elec_s{simpl}_{clusters}.geojson", + regions_onshore=resources( + "regions_onshore_elec_s{simpl}_{clusters}.geojson" + ), + regions_offshore=resources( + "regions_offshore_elec_s{simpl}_{clusters}.geojson" + ), output: - gas_input_nodes=RESOURCES - + "gas_input_locations_s{simpl}_{clusters}.geojson", - gas_input_nodes_simplified=RESOURCES - + "gas_input_locations_s{simpl}_{clusters}_simplified.csv", + gas_input_nodes=resources("gas_input_locations_s{simpl}_{clusters}.geojson"), + gas_input_nodes_simplified=resources( + "gas_input_locations_s{simpl}_{clusters}_simplified.csv" + ), resources: mem_mb=2000, log: - LOGS + "build_gas_input_locations_s{simpl}_{clusters}.log", + logs("build_gas_input_locations_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -111,17 +113,19 @@ if config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]: rule cluster_gas_network: input: - cleaned_gas_network=RESOURCES + "gas_network.csv", - regions_onshore=RESOURCES - + "regions_onshore_elec_s{simpl}_{clusters}.geojson", - regions_offshore=RESOURCES - + "regions_offshore_elec_s{simpl}_{clusters}.geojson", + cleaned_gas_network=resources("gas_network.csv"), + regions_onshore=resources( + "regions_onshore_elec_s{simpl}_{clusters}.geojson" + ), + regions_offshore=resources( + "regions_offshore_elec_s{simpl}_{clusters}.geojson" + ), output: - clustered_gas_network=RESOURCES + "gas_network_elec_s{simpl}_{clusters}.csv", + clustered_gas_network=resources("gas_network_elec_s{simpl}_{clusters}.csv"), resources: mem_mb=4000, log: - LOGS + "cluster_gas_network_s{simpl}_{clusters}.log", + logs("cluster_gas_network_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -143,18 +147,18 @@ rule build_heat_demands: params: snapshots=config_provider("snapshots"), input: - pop_layout=RESOURCES + "pop_layout_{scope}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + pop_layout=resources("pop_layout_{scope}.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - heat_demand=RESOURCES + "heat_demand_{scope}_elec_s{simpl}_{clusters}.nc", + heat_demand=resources("heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, threads: 8 log: - LOGS + "build_heat_demands_{scope}_{simpl}_{clusters}.loc", + logs("build_heat_demands_{scope}_{simpl}_{clusters}.loc"), benchmark: - BENCHMARKS + "build_heat_demands/{scope}_s{simpl}_{clusters}" + benchmarks("build_heat_demands/{scope}_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -165,19 +169,19 @@ rule build_temperature_profiles: params: snapshots=config_provider("snapshots"), input: - pop_layout=RESOURCES + "pop_layout_{scope}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + pop_layout=resources("pop_layout_{scope}.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - temp_soil=RESOURCES + "temp_soil_{scope}_elec_s{simpl}_{clusters}.nc", - temp_air=RESOURCES + "temp_air_{scope}_elec_s{simpl}_{clusters}.nc", + temp_soil=resources("temp_soil_{scope}_elec_s{simpl}_{clusters}.nc"), + temp_air=resources("temp_air_{scope}_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, threads: 8 log: - LOGS + "build_temperature_profiles_{scope}_{simpl}_{clusters}.log", + logs("build_temperature_profiles_{scope}_{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "build_temperature_profiles/{scope}_s{simpl}_{clusters}" + benchmarks("build_temperature_profiles/{scope}_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -188,25 +192,25 @@ rule build_cop_profiles: params: heat_pump_sink_T=config_provider("sector", "heat_pump_sink_T"), input: - temp_soil_total=RESOURCES + "temp_soil_total_elec_s{simpl}_{clusters}.nc", - temp_soil_rural=RESOURCES + "temp_soil_rural_elec_s{simpl}_{clusters}.nc", - temp_soil_urban=RESOURCES + "temp_soil_urban_elec_s{simpl}_{clusters}.nc", - temp_air_total=RESOURCES + "temp_air_total_elec_s{simpl}_{clusters}.nc", - temp_air_rural=RESOURCES + "temp_air_rural_elec_s{simpl}_{clusters}.nc", - temp_air_urban=RESOURCES + "temp_air_urban_elec_s{simpl}_{clusters}.nc", + temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"), + temp_soil_rural=resources("temp_soil_rural_elec_s{simpl}_{clusters}.nc"), + temp_soil_urban=resources("temp_soil_urban_elec_s{simpl}_{clusters}.nc"), + temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), + temp_air_rural=resources("temp_air_rural_elec_s{simpl}_{clusters}.nc"), + temp_air_urban=resources("temp_air_urban_elec_s{simpl}_{clusters}.nc"), output: - cop_soil_total=RESOURCES + "cop_soil_total_elec_s{simpl}_{clusters}.nc", - cop_soil_rural=RESOURCES + "cop_soil_rural_elec_s{simpl}_{clusters}.nc", - cop_soil_urban=RESOURCES + "cop_soil_urban_elec_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec_s{simpl}_{clusters}.nc", - cop_air_rural=RESOURCES + "cop_air_rural_elec_s{simpl}_{clusters}.nc", - cop_air_urban=RESOURCES + "cop_air_urban_elec_s{simpl}_{clusters}.nc", + cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), + cop_soil_rural=resources("cop_soil_rural_elec_s{simpl}_{clusters}.nc"), + cop_soil_urban=resources("cop_soil_urban_elec_s{simpl}_{clusters}.nc"), + cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), + cop_air_rural=resources("cop_air_rural_elec_s{simpl}_{clusters}.nc"), + cop_air_urban=resources("cop_air_urban_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, log: - LOGS + "build_cop_profiles_s{simpl}_{clusters}.log", + logs("build_cop_profiles_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "build_cop_profiles/s{simpl}_{clusters}" + benchmarks("build_cop_profiles/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -218,18 +222,18 @@ rule build_solar_thermal_profiles: snapshots=config_provider("snapshots"), solar_thermal=config_provider("solar_thermal"), input: - pop_layout=RESOURCES + "pop_layout_{scope}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + pop_layout=resources("pop_layout_{scope}.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - solar_thermal=RESOURCES + "solar_thermal_{scope}_elec_s{simpl}_{clusters}.nc", + solar_thermal=resources("solar_thermal_{scope}_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, threads: 16 log: - LOGS + "build_solar_thermal_profiles_{scope}_s{simpl}_{clusters}.log", + logs("build_solar_thermal_profiles_{scope}_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "build_solar_thermal_profiles/{scope}_s{simpl}_{clusters}" + benchmarks("build_solar_thermal_profiles/{scope}_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -241,23 +245,23 @@ rule build_energy_totals: countries=config_provider("countries"), energy=config_provider("energy"), input: - nuts3_shapes=RESOURCES + "nuts3_shapes.geojson", + nuts3_shapes=resources("nuts3_shapes.geojson"), co2="data/eea/UNFCCC_v23.csv", swiss="data/switzerland-sfoe/switzerland-new_format.csv", idees="data/jrc-idees-2015", district_heat_share="data/district_heat_share.csv", eurostat=input_eurostat, output: - energy_name=RESOURCES + "energy_totals.csv", - co2_name=RESOURCES + "co2_totals.csv", - transport_name=RESOURCES + "transport_data.csv", + energy_name=resources("energy_totals.csv"), + co2_name=resources("co2_totals.csv"), + transport_name=resources("transport_data.csv"), threads: 16 resources: mem_mb=10000, log: - LOGS + "build_energy_totals.log", + logs("build_energy_totals.log"), benchmark: - BENCHMARKS + "build_energy_totals" + benchmarks("build_energy_totals") conda: "../envs/environment.yaml" script: @@ -273,22 +277,23 @@ rule build_biomass_potentials: keep_local=True, ), nuts2="data/nuts/NUTS_RG_10M_2013_4326_LEVL_2.geojson", # https://gisco-services.ec.europa.eu/distribution/v2/nuts/download/#nuts21 - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), nuts3_population=ancient("data/bundle/nama_10r_3popgdp.tsv.gz"), swiss_cantons=ancient("data/bundle/ch_cantons.csv"), swiss_population=ancient("data/bundle/je-e-21.03.02.xls"), - country_shapes=RESOURCES + "country_shapes.geojson", + country_shapes=resources("country_shapes.geojson"), output: - biomass_potentials_all=RESOURCES - + "biomass_potentials_all_s{simpl}_{clusters}.csv", - biomass_potentials=RESOURCES + "biomass_potentials_s{simpl}_{clusters}.csv", + biomass_potentials_all=resources( + "biomass_potentials_all_s{simpl}_{clusters}.csv" + ), + biomass_potentials=resources("biomass_potentials_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=1000, log: - LOGS + "build_biomass_potentials_s{simpl}_{clusters}.log", + logs("build_biomass_potentials_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "build_biomass_potentials_s{simpl}_{clusters}" + benchmarks("build_biomass_potentials_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -304,14 +309,14 @@ if config["sector"]["biomass_transport"] or config["sector"]["biomass_spatial"]: keep_local=True, ), output: - biomass_transport_costs=RESOURCES + "biomass_transport_costs.csv", + biomass_transport_costs=resources("biomass_transport_costs.csv"), threads: 1 resources: mem_mb=1000, log: - LOGS + "build_biomass_transport_costs.log", + logs("build_biomass_transport_costs.log"), benchmark: - BENCHMARKS + "build_biomass_transport_costs" + benchmarks("build_biomass_transport_costs") conda: "../envs/environment.yaml" script: @@ -337,20 +342,23 @@ if config["sector"]["regional_co2_sequestration_potential"]["enable"]: "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", keep_local=True, ), - regions_onshore=RESOURCES - + "regions_onshore_elec_s{simpl}_{clusters}.geojson", - regions_offshore=RESOURCES - + "regions_offshore_elec_s{simpl}_{clusters}.geojson", + regions_onshore=resources( + "regions_onshore_elec_s{simpl}_{clusters}.geojson" + ), + regions_offshore=resources( + "regions_offshore_elec_s{simpl}_{clusters}.geojson" + ), output: - sequestration_potential=RESOURCES - + "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv", + sequestration_potential=resources( + "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv" + ), threads: 1 resources: mem_mb=4000, log: - LOGS + "build_sequestration_potentials_s{simpl}_{clusters}.log", + logs("build_sequestration_potentials_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "build_sequestration_potentials_s{simpl}_{clusters}" + benchmarks("build_sequestration_potentials_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -367,17 +375,17 @@ if not config["sector"]["regional_co2_sequestration_potential"]["enable"]: rule build_salt_cavern_potentials: input: salt_caverns="data/h2_salt_caverns_GWh_per_sqkm.geojson", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", - regions_offshore=RESOURCES + "regions_offshore_elec_s{simpl}_{clusters}.geojson", + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), output: - h2_cavern_potential=RESOURCES + "salt_cavern_potentials_s{simpl}_{clusters}.csv", + h2_cavern_potential=resources("salt_cavern_potentials_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, log: - LOGS + "build_salt_cavern_potentials_s{simpl}_{clusters}.log", + logs("build_salt_cavern_potentials_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "build_salt_cavern_potentials_s{simpl}_{clusters}" + benchmarks("build_salt_cavern_potentials_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -390,14 +398,14 @@ rule build_ammonia_production: input: usgs="data/myb1-2017-nitro.xls", output: - ammonia_production=RESOURCES + "ammonia_production.csv", + ammonia_production=resources("ammonia_production.csv"), threads: 1 resources: mem_mb=1000, log: - LOGS + "build_ammonia_production.log", + logs("build_ammonia_production.log"), benchmark: - BENCHMARKS + "build_ammonia_production" + benchmarks("build_ammonia_production") conda: "../envs/environment.yaml" script: @@ -409,17 +417,17 @@ rule build_industry_sector_ratios: industry=config_provider("industry"), ammonia=config_provider("sector", "ammonia", default=False), input: - ammonia_production=RESOURCES + "ammonia_production.csv", + ammonia_production=resources("ammonia_production.csv"), idees="data/jrc-idees-2015", output: - industry_sector_ratios=RESOURCES + "industry_sector_ratios.csv", + industry_sector_ratios=resources("industry_sector_ratios.csv"), threads: 1 resources: mem_mb=1000, log: - LOGS + "build_industry_sector_ratios.log", + logs("build_industry_sector_ratios.log"), benchmark: - BENCHMARKS + "build_industry_sector_ratios" + benchmarks("build_industry_sector_ratios") conda: "../envs/environment.yaml" script: @@ -431,19 +439,20 @@ rule build_industrial_production_per_country: industry=config_provider("industry"), countries=config_provider("countries"), input: - ammonia_production=RESOURCES + "ammonia_production.csv", + ammonia_production=resources("ammonia_production.csv"), jrc="data/jrc-idees-2015", eurostat="data/eurostat-energy_balances-may_2018_edition", output: - industrial_production_per_country=RESOURCES - + "industrial_production_per_country.csv", + industrial_production_per_country=resources( + "industrial_production_per_country.csv" + ), threads: 8 resources: mem_mb=1000, log: - LOGS + "build_industrial_production_per_country.log", + logs("build_industrial_production_per_country.log"), benchmark: - BENCHMARKS + "build_industrial_production_per_country" + benchmarks("build_industrial_production_per_country") conda: "../envs/environment.yaml" script: @@ -454,21 +463,23 @@ rule build_industrial_production_per_country_tomorrow: params: industry=config_provider("industry"), input: - industrial_production_per_country=RESOURCES - + "industrial_production_per_country.csv", + industrial_production_per_country=resources( + "industrial_production_per_country.csv" + ), output: - industrial_production_per_country_tomorrow=RESOURCES - + "industrial_production_per_country_tomorrow_{planning_horizons}.csv", + industrial_production_per_country_tomorrow=resources( + "industrial_production_per_country_tomorrow_{planning_horizons}.csv" + ), threads: 1 resources: mem_mb=1000, log: - LOGS - + "build_industrial_production_per_country_tomorrow_{planning_horizons}.log", + logs("build_industrial_production_per_country_tomorrow_{planning_horizons}.log"), benchmark: ( - BENCHMARKS - + "build_industrial_production_per_country_tomorrow_{planning_horizons}" + benchmarks( + "build_industrial_production_per_country_tomorrow_{planning_horizons}" + ) ) conda: "../envs/environment.yaml" @@ -483,19 +494,20 @@ rule build_industrial_distribution_key: ), countries=config_provider("countries"), input: - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), hotmaps_industrial_database="data/Industrial_Database.csv", output: - industrial_distribution_key=RESOURCES - + "industrial_distribution_key_elec_s{simpl}_{clusters}.csv", + industrial_distribution_key=resources( + "industrial_distribution_key_elec_s{simpl}_{clusters}.csv" + ), threads: 1 resources: mem_mb=1000, log: - LOGS + "build_industrial_distribution_key_s{simpl}_{clusters}.log", + logs("build_industrial_distribution_key_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "build_industrial_distribution_key/s{simpl}_{clusters}" + benchmarks("build_industrial_distribution_key/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -504,23 +516,28 @@ rule build_industrial_distribution_key: rule build_industrial_production_per_node: input: - industrial_distribution_key=RESOURCES - + "industrial_distribution_key_elec_s{simpl}_{clusters}.csv", - industrial_production_per_country_tomorrow=RESOURCES - + "industrial_production_per_country_tomorrow_{planning_horizons}.csv", + industrial_distribution_key=resources( + "industrial_distribution_key_elec_s{simpl}_{clusters}.csv" + ), + industrial_production_per_country_tomorrow=resources( + "industrial_production_per_country_tomorrow_{planning_horizons}.csv" + ), output: - industrial_production_per_node=RESOURCES - + "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + industrial_production_per_node=resources( + "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), threads: 1 resources: mem_mb=1000, log: - LOGS - + "build_industrial_production_per_node_s{simpl}_{clusters}_{planning_horizons}.log", + logs( + "build_industrial_production_per_node_s{simpl}_{clusters}_{planning_horizons}.log" + ), benchmark: ( - BENCHMARKS - + "build_industrial_production_per_node/s{simpl}_{clusters}_{planning_horizons}" + benchmarks( + "build_industrial_production_per_node/s{simpl}_{clusters}_{planning_horizons}" + ) ) conda: "../envs/environment.yaml" @@ -530,24 +547,29 @@ rule build_industrial_production_per_node: rule build_industrial_energy_demand_per_node: input: - industry_sector_ratios=RESOURCES + "industry_sector_ratios.csv", - industrial_production_per_node=RESOURCES - + "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv", - industrial_energy_demand_per_node_today=RESOURCES - + "industrial_energy_demand_today_elec_s{simpl}_{clusters}.csv", + industry_sector_ratios=resources("industry_sector_ratios.csv"), + industrial_production_per_node=resources( + "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), + industrial_energy_demand_per_node_today=resources( + "industrial_energy_demand_today_elec_s{simpl}_{clusters}.csv" + ), output: - industrial_energy_demand_per_node=RESOURCES - + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + industrial_energy_demand_per_node=resources( + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), threads: 1 resources: mem_mb=1000, log: - LOGS - + "build_industrial_energy_demand_per_node_s{simpl}_{clusters}_{planning_horizons}.log", + logs( + "build_industrial_energy_demand_per_node_s{simpl}_{clusters}_{planning_horizons}.log" + ), benchmark: ( - BENCHMARKS - + "build_industrial_energy_demand_per_node/s{simpl}_{clusters}_{planning_horizons}" + benchmarks( + "build_industrial_energy_demand_per_node/s{simpl}_{clusters}_{planning_horizons}" + ) ) conda: "../envs/environment.yaml" @@ -561,19 +583,21 @@ rule build_industrial_energy_demand_per_country_today: industry=config_provider("industry"), input: jrc="data/jrc-idees-2015", - ammonia_production=RESOURCES + "ammonia_production.csv", - industrial_production_per_country=RESOURCES - + "industrial_production_per_country.csv", + ammonia_production=resources("ammonia_production.csv"), + industrial_production_per_country=resources( + "industrial_production_per_country.csv" + ), output: - industrial_energy_demand_per_country_today=RESOURCES - + "industrial_energy_demand_per_country_today.csv", + industrial_energy_demand_per_country_today=resources( + "industrial_energy_demand_per_country_today.csv" + ), threads: 8 resources: mem_mb=1000, log: - LOGS + "build_industrial_energy_demand_per_country_today.log", + logs("build_industrial_energy_demand_per_country_today.log"), benchmark: - BENCHMARKS + "build_industrial_energy_demand_per_country_today" + benchmarks("build_industrial_energy_demand_per_country_today") conda: "../envs/environment.yaml" script: @@ -582,20 +606,23 @@ rule build_industrial_energy_demand_per_country_today: rule build_industrial_energy_demand_per_node_today: input: - industrial_distribution_key=RESOURCES - + "industrial_distribution_key_elec_s{simpl}_{clusters}.csv", - industrial_energy_demand_per_country_today=RESOURCES - + "industrial_energy_demand_per_country_today.csv", + industrial_distribution_key=resources( + "industrial_distribution_key_elec_s{simpl}_{clusters}.csv" + ), + industrial_energy_demand_per_country_today=resources( + "industrial_energy_demand_per_country_today.csv" + ), output: - industrial_energy_demand_per_node_today=RESOURCES - + "industrial_energy_demand_today_elec_s{simpl}_{clusters}.csv", + industrial_energy_demand_per_node_today=resources( + "industrial_energy_demand_today_elec_s{simpl}_{clusters}.csv" + ), threads: 1 resources: mem_mb=1000, log: - LOGS + "build_industrial_energy_demand_per_node_today_s{simpl}_{clusters}.log", + logs("build_industrial_energy_demand_per_node_today_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "build_industrial_energy_demand_per_node_today/s{simpl}_{clusters}" + benchmarks("build_industrial_energy_demand_per_node_today/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -611,23 +638,23 @@ if config["sector"]["retrofitting"]["retro_endogen"]: input: building_stock="data/retro/data_building_stock.csv", data_tabula="data/retro/tabula-calculator-calcsetbuilding.csv", - air_temperature=RESOURCES + "temp_air_total_elec_s{simpl}_{clusters}.nc", + air_temperature=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), u_values_PL="data/retro/u_values_poland.csv", tax_w="data/retro/electricity_taxes_eu.csv", construction_index="data/retro/comparative_level_investment.csv", floor_area_missing="data/retro/floor_area_missing.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), cost_germany="data/retro/retro_cost_germany.csv", window_assumptions="data/retro/window_assumptions.csv", output: - retro_cost=RESOURCES + "retro_cost_elec_s{simpl}_{clusters}.csv", - floor_area=RESOURCES + "floor_area_elec_s{simpl}_{clusters}.csv", + retro_cost=resources("retro_cost_elec_s{simpl}_{clusters}.csv"), + floor_area=resources("floor_area_elec_s{simpl}_{clusters}.csv"), resources: mem_mb=1000, log: - LOGS + "build_retro_cost_s{simpl}_{clusters}.log", + logs("build_retro_cost_s{simpl}_{clusters}.log"), benchmark: - BENCHMARKS + "build_retro_cost/s{simpl}_{clusters}" + benchmarks("build_retro_cost/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -643,15 +670,15 @@ if not config["sector"]["retrofitting"]["retro_endogen"]: rule build_population_weighted_energy_totals: input: - energy_totals=RESOURCES + "energy_totals.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", + energy_totals=resources("energy_totals.csv"), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), output: - RESOURCES + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv", + resources("pop_weighted_energy_totals_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, log: - LOGS + "build_population_weighted_energy_totals_s{simpl}_{clusters}.log", + logs("build_population_weighted_energy_totals_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -661,16 +688,16 @@ rule build_population_weighted_energy_totals: rule build_shipping_demand: input: ports="data/attributed_ports.json", - scope=RESOURCES + "europe_shape.geojson", - regions=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", - demand=RESOURCES + "energy_totals.csv", + scope=resources("europe_shape.geojson"), + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + demand=resources("energy_totals.csv"), output: - RESOURCES + "shipping_demand_s{simpl}_{clusters}.csv", + resources("shipping_demand_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, log: - LOGS + "build_shipping_demand_s{simpl}_{clusters}.log", + logs("build_shipping_demand_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -682,23 +709,24 @@ rule build_transport_demand: snapshots=config_provider("snapshots"), sector=config_provider("sector"), input: - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", - pop_weighted_energy_totals=RESOURCES - + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv", - transport_data=RESOURCES + "transport_data.csv", + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), + pop_weighted_energy_totals=resources( + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" + ), + transport_data=resources("transport_data.csv"), traffic_data_KFZ="data/emobility/KFZ__count", traffic_data_Pkw="data/emobility/Pkw__count", - temp_air_total=RESOURCES + "temp_air_total_elec_s{simpl}_{clusters}.nc", + temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), output: - transport_demand=RESOURCES + "transport_demand_s{simpl}_{clusters}.csv", - transport_data=RESOURCES + "transport_data_s{simpl}_{clusters}.csv", - avail_profile=RESOURCES + "avail_profile_s{simpl}_{clusters}.csv", - dsm_profile=RESOURCES + "dsm_profile_s{simpl}_{clusters}.csv", + transport_demand=resources("transport_demand_s{simpl}_{clusters}.csv"), + transport_data=resources("transport_data_s{simpl}_{clusters}.csv"), + avail_profile=resources("avail_profile_s{simpl}_{clusters}.csv"), + dsm_profile=resources("dsm_profile_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, log: - LOGS + "build_transport_demand_s{simpl}_{clusters}.log", + logs("build_transport_demand_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -727,57 +755,62 @@ rule prepare_sector_network: **build_biomass_transport_costs_output, **gas_infrastructure, **build_sequestration_potentials_output, - network=RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - energy_totals_name=RESOURCES + "energy_totals.csv", + network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), + energy_totals_name=resources("energy_totals.csv"), eurostat=input_eurostat, - pop_weighted_energy_totals=RESOURCES - + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv", - shipping_demand=RESOURCES + "shipping_demand_s{simpl}_{clusters}.csv", - transport_demand=RESOURCES + "transport_demand_s{simpl}_{clusters}.csv", - transport_data=RESOURCES + "transport_data_s{simpl}_{clusters}.csv", - avail_profile=RESOURCES + "avail_profile_s{simpl}_{clusters}.csv", - dsm_profile=RESOURCES + "dsm_profile_s{simpl}_{clusters}.csv", - co2_totals_name=RESOURCES + "co2_totals.csv", + pop_weighted_energy_totals=resources( + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" + ), + shipping_demand=resources("shipping_demand_s{simpl}_{clusters}.csv"), + transport_demand=resources("transport_demand_s{simpl}_{clusters}.csv"), + transport_data=resources("transport_data_s{simpl}_{clusters}.csv"), + avail_profile=resources("avail_profile_s{simpl}_{clusters}.csv"), + dsm_profile=resources("dsm_profile_s{simpl}_{clusters}.csv"), + co2_totals_name=resources("co2_totals.csv"), co2="data/eea/UNFCCC_v23.csv", - biomass_potentials=RESOURCES + "biomass_potentials_s{simpl}_{clusters}.csv", + biomass_potentials=resources("biomass_potentials_s{simpl}_{clusters}.csv"), heat_profile="data/heat_load_profile_BDEW.csv", costs="data/costs_{}.csv".format(config["costs"]["year"]) if config["foresight"] == "overnight" else "data/costs_{planning_horizons}.csv", - profile_offwind_ac=RESOURCES + "profile_offwind-ac.nc", - profile_offwind_dc=RESOURCES + "profile_offwind-dc.nc", - h2_cavern=RESOURCES + "salt_cavern_potentials_s{simpl}_{clusters}.csv", - busmap_s=RESOURCES + "busmap_elec_s{simpl}.csv", - busmap=RESOURCES + "busmap_elec_s{simpl}_{clusters}.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", - simplified_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}.csv", - industrial_demand=RESOURCES - + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv", - heat_demand_urban=RESOURCES + "heat_demand_urban_elec_s{simpl}_{clusters}.nc", - heat_demand_rural=RESOURCES + "heat_demand_rural_elec_s{simpl}_{clusters}.nc", - heat_demand_total=RESOURCES + "heat_demand_total_elec_s{simpl}_{clusters}.nc", - temp_soil_total=RESOURCES + "temp_soil_total_elec_s{simpl}_{clusters}.nc", - temp_soil_rural=RESOURCES + "temp_soil_rural_elec_s{simpl}_{clusters}.nc", - temp_soil_urban=RESOURCES + "temp_soil_urban_elec_s{simpl}_{clusters}.nc", - temp_air_total=RESOURCES + "temp_air_total_elec_s{simpl}_{clusters}.nc", - temp_air_rural=RESOURCES + "temp_air_rural_elec_s{simpl}_{clusters}.nc", - temp_air_urban=RESOURCES + "temp_air_urban_elec_s{simpl}_{clusters}.nc", - cop_soil_total=RESOURCES + "cop_soil_total_elec_s{simpl}_{clusters}.nc", - cop_soil_rural=RESOURCES + "cop_soil_rural_elec_s{simpl}_{clusters}.nc", - cop_soil_urban=RESOURCES + "cop_soil_urban_elec_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec_s{simpl}_{clusters}.nc", - cop_air_rural=RESOURCES + "cop_air_rural_elec_s{simpl}_{clusters}.nc", - cop_air_urban=RESOURCES + "cop_air_urban_elec_s{simpl}_{clusters}.nc", - solar_thermal_total=RESOURCES - + "solar_thermal_total_elec_s{simpl}_{clusters}.nc" + profile_offwind_ac=resources("profile_offwind-ac.nc"), + profile_offwind_dc=resources("profile_offwind-dc.nc"), + h2_cavern=resources("salt_cavern_potentials_s{simpl}_{clusters}.csv"), + busmap_s=resources("busmap_elec_s{simpl}.csv"), + busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), + simplified_pop_layout=resources("pop_layout_elec_s{simpl}.csv"), + industrial_demand=resources( + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), + heat_demand_urban=resources("heat_demand_urban_elec_s{simpl}_{clusters}.nc"), + heat_demand_rural=resources("heat_demand_rural_elec_s{simpl}_{clusters}.nc"), + heat_demand_total=resources("heat_demand_total_elec_s{simpl}_{clusters}.nc"), + temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"), + temp_soil_rural=resources("temp_soil_rural_elec_s{simpl}_{clusters}.nc"), + temp_soil_urban=resources("temp_soil_urban_elec_s{simpl}_{clusters}.nc"), + temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), + temp_air_rural=resources("temp_air_rural_elec_s{simpl}_{clusters}.nc"), + temp_air_urban=resources("temp_air_urban_elec_s{simpl}_{clusters}.nc"), + cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), + cop_soil_rural=resources("cop_soil_rural_elec_s{simpl}_{clusters}.nc"), + cop_soil_urban=resources("cop_soil_urban_elec_s{simpl}_{clusters}.nc"), + cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), + cop_air_rural=resources("cop_air_rural_elec_s{simpl}_{clusters}.nc"), + cop_air_urban=resources("cop_air_urban_elec_s{simpl}_{clusters}.nc"), + solar_thermal_total=resources( + "solar_thermal_total_elec_s{simpl}_{clusters}.nc" + ) if config["sector"]["solar_thermal"] else [], - solar_thermal_urban=RESOURCES - + "solar_thermal_urban_elec_s{simpl}_{clusters}.nc" + solar_thermal_urban=resources( + "solar_thermal_urban_elec_s{simpl}_{clusters}.nc" + ) if config["sector"]["solar_thermal"] else [], - solar_thermal_rural=RESOURCES - + "solar_thermal_rural_elec_s{simpl}_{clusters}.nc" + solar_thermal_rural=resources( + "solar_thermal_rural_elec_s{simpl}_{clusters}.nc" + ) if config["sector"]["solar_thermal"] else [], output: diff --git a/rules/collect.smk b/rules/collect.smk index 70dc4641..e0f19a4c 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -23,7 +23,7 @@ rule all: rule cluster_networks: input: expand( - RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", + resources("networks/elec_s{simpl}_{clusters}.nc"), **config["scenario"], run=config["run"]["name"] ), @@ -32,7 +32,7 @@ rule cluster_networks: rule extra_components_networks: input: expand( - RESOURCES + "networks/elec_s{simpl}_{clusters}_ec.nc", + resources("networks/elec_s{simpl}_{clusters}_ec.nc"), **config["scenario"], run=config["run"]["name"] ), @@ -41,7 +41,7 @@ rule extra_components_networks: rule prepare_elec_networks: input: expand( - RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), **config["scenario"], run=config["run"]["name"] ), diff --git a/rules/common.smk b/rules/common.smk index f24301c8..0467d560 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -40,10 +40,12 @@ def static_getter(wildcards, keys, default): def dynamic_getter(wildcards, keys, default): """Getter function for dynamic config values based on scenario.""" + if "run" not in wildcards: + return get_config(config, keys, default) scenario_name = wildcards.run if scenario_name not in scenarios: raise ValueError( - f"Scenario {scenario_name} not found in file {config['scenariofile']}." + f"Scenario {scenario_name} not found in file {config['run']['scenario']['file']}." ) return get_config(scenario_config(scenario_name), keys, default) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 4c833b4f..e09103cc 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -14,7 +14,7 @@ rule plot_network: input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: map=RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 34e2eb7c..1c454633 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -92,9 +92,9 @@ if config["enable"]["retrieve"] and config["enable"].get( static=True, ), output: - RESOURCES + "natura.tiff", + resources("natura.tiff"), log: - LOGS + "retrieve_natura_raster.log", + logs("retrieve_natura_raster.log"), resources: mem_mb=5000, retries: 2 diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index c396ebd5..cfdb1da0 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -12,7 +12,7 @@ rule solve_network: "co2_sequestration_potential", 200 ), input: - network=RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), config=RESULTS + "config.yaml", output: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 8a93d24a..214733b7 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -12,13 +12,13 @@ rule add_existing_baseyear: input: network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - powerplants=RESOURCES + "powerplants.csv", - busmap_s=RESOURCES + "busmap_elec_s{simpl}.csv", - busmap=RESOURCES + "busmap_elec_s{simpl}_{clusters}.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", + powerplants=resources("powerplants.csv"), + busmap_s=resources("busmap_elec_s{simpl}.csv"), + busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), costs="data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), - cop_soil_total=RESOURCES + "cop_soil_total_elec_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec_s{simpl}_{clusters}.nc", + cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), + cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), existing_heating="data/existing_infrastructure/existing_heating_raw.csv", existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", @@ -55,8 +55,8 @@ rule add_brownfield: + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", network_p=solved_previous_horizon, #solved network at previous time step costs="data/costs_{planning_horizons}.csv", - cop_soil_total=RESOURCES + "cop_soil_total_elec_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec_s{simpl}_{clusters}.nc", + cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), + cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), output: RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index c7700760..d8476868 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -31,8 +31,7 @@ rule solve_sector_network: walltime=config["solving"].get("walltime", "12:00:00"), benchmark: ( - RESULTS - + BENCHMARKS + BENCHMARKS + "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: diff --git a/rules/validate.smk b/rules/validate.smk index cfb8c959..09344673 100644 --- a/rules/validate.smk +++ b/rules/validate.smk @@ -20,9 +20,9 @@ rule build_electricity_production: snapshots=config["snapshots"], countries=config["countries"], output: - RESOURCES + "historical_electricity_production.csv", + resources("historical_electricity_production.csv"), log: - LOGS + "build_electricity_production.log", + logs("build_electricity_production.log"), resources: mem_mb=5000, script: @@ -38,11 +38,11 @@ rule build_cross_border_flows: snapshots=config["snapshots"], countries=config["countries"], input: - network=RESOURCES + "networks/base.nc", + network=resources("networks/base.nc"), output: - RESOURCES + "historical_cross_border_flows.csv", + resources("historical_cross_border_flows.csv"), log: - LOGS + "build_cross_border_flows.log", + logs("build_cross_border_flows.log"), resources: mem_mb=5000, script: @@ -58,9 +58,9 @@ rule build_electricity_prices: snapshots=config["snapshots"], countries=config["countries"], output: - RESOURCES + "historical_electricity_prices.csv", + resources("historical_electricity_prices.csv"), log: - LOGS + "build_electricity_prices.log", + logs("build_electricity_prices.log"), resources: mem_mb=5000, script: @@ -70,7 +70,7 @@ rule build_electricity_prices: rule plot_validation_electricity_production: input: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - electricity_production=RESOURCES + "historical_electricity_production.csv", + electricity_production=resources("historical_electricity_production.csv"), output: **{ plot: RESULTS @@ -88,7 +88,7 @@ rule plot_validation_cross_border_flows: countries=config["countries"], input: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - cross_border_flows=RESOURCES + "historical_cross_border_flows.csv", + cross_border_flows=resources("historical_cross_border_flows.csv"), output: **{ plot: RESULTS @@ -104,7 +104,7 @@ rule plot_validation_cross_border_flows: rule plot_validation_electricity_prices: input: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - electricity_prices=RESOURCES + "historical_electricity_prices.csv", + electricity_prices=resources("historical_electricity_prices.csv"), output: **{ plot: RESULTS diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 00000000..fc781c2f --- /dev/null +++ b/scripts/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 3951be18..c166c61c 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -6,14 +6,13 @@ import contextlib import logging import os +import re import urllib from pathlib import Path import pandas as pd import pytz import yaml -from pypsa.components import component_attrs, components -from pypsa.descriptors import Dict from snakemake.utils import update_config from tqdm import tqdm @@ -22,6 +21,43 @@ logger = logging.getLogger(__name__) REGION_COLS = ["geometry", "name", "x", "y", "country"] +def path_provider(dir, rdir, shared_resources): + """ + Dynamically provide paths based on shared resources. + + Use this function whenever there is an input or output to a + snakemake rule that should, optionally, be either shared across runs + or created individually for each run. If shared_resources is a + string, it is assumed to be the wildcard that indicates the cutoff + after which resources are no longer shared. The function returns a + function which takes a filename and returns a path that is either + shared or individual to each run. + """ + + def path(fn): + pattern = r"\{([^{}]+)\}" + existing_wildcards = list(re.findall(pattern, fn)) + if shared_resources == "base": + # special case for shared "base" resources + no_relevant_wildcards = not len(set(existing_wildcards) - {"technology"}) + no_elec_rule = not fn.startswith("networks/elec") and not fn.startswith( + "add_electricity" + ) + is_shared = no_relevant_wildcards and no_elec_rule + elif isinstance(shared_resources, str): + final_wildcard = shared_resources + is_shared = final_wildcard not in existing_wildcards[:-1] + else: + is_shared = shared_resources + + if is_shared: + return f"{dir}{fn}" + else: + return f"{dir}{rdir}{fn}" + + return path + + # Define a context manager to temporarily mute print statements @contextlib.contextmanager def mute_print(): @@ -31,15 +67,16 @@ def mute_print(): def set_scenario_config(snakemake): - if snakemake.config["run"]["scenarios"] and "run" in snakemake.wildcards.keys(): + scenario = snakemake.config["run"].get("scenario", {}) + if scenario.get("enable") and "run" in snakemake.wildcards.keys(): try: - with open(snakemake.config["scenariofile"], "r") as f: + with open(scenario["file"], "r") as f: scenario_config = yaml.safe_load(f) except FileNotFoundError: # fallback for mock_snakemake script_dir = Path(__file__).parent.resolve() root_dir = script_dir.parent - with open(root_dir / snakemake.config["scenariofile"], "r") as f: + with open(root_dir / scenario["file"], "r") as f: scenario_config = yaml.safe_load(f) update_config(snakemake.config, scenario_config[snakemake.wildcards.run]) From b91a7b9c514f6a380f7cea758325156f095cf8c7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 08:19:38 +0000 Subject: [PATCH 103/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/add_existing_baseyear.py | 7 +++++-- scripts/build_industrial_distribution_key.py | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 269705a7..08810470 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -447,8 +447,11 @@ def add_heating_capacities_installed_before_baseyear( ) # if rural heating demand for one of the nodes doesn't exist, # then columns were dropped before and heating demand share should be 0.0 - if all(f"{node} {service} rural heat" in p_set_sum.index for service in ["residential", "services"]) - else 0. + if all( + f"{node} {service} rural heat" in p_set_sum.index + for service in ["residential", "services"] + ) + else 0.0 for node in nodal_df.index ], index=nodal_df.index, diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index c5cbd19c..e6d515b0 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -13,13 +13,14 @@ logger = logging.getLogger(__name__) import uuid from itertools import product +import country_converter as coco import geopandas as gpd import pandas as pd from packaging.version import Version, parse -import country_converter as coco cc = coco.CountryConverter() + def locate_missing_industrial_sites(df): """ Locate industrial sites without valid locations based on city and From 04a2bea176475c64efc15a85923996311c9af437 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 24 Aug 2023 13:17:44 +0200 Subject: [PATCH 104/591] scenario-management: use list for including wildcards with shared resource --- Snakefile | 6 +- config/test/config.scenarios.electricity.yaml | 2 +- doc/configtables/run.csv | 4 +- rules/common.smk | 2 +- scripts/_helpers.py | 96 ++++++++++++------- 5 files changed, 71 insertions(+), 39 deletions(-) diff --git a/Snakefile b/Snakefile index 55b90d5d..c9fdbb34 100644 --- a/Snakefile +++ b/Snakefile @@ -25,10 +25,10 @@ COSTS = f"data/costs_{config['costs']['year']}.csv" ATLITE_NPROCESSES = config["atlite"].get("nprocesses", 4) run = config["run"] -scenario = run.get("scenario", {}) +scenarios = run.get("scenarios", {}) if run["name"]: - if scenario.get("enable"): - fn = Path(scenario["file"]) + if scenarios.get("enable"): + fn = Path(scenarios["file"]) scenarios = yaml.safe_load(fn.read_text()) RDIR = "{run}/" else: diff --git a/config/test/config.scenarios.electricity.yaml b/config/test/config.scenarios.electricity.yaml index 63b1892b..185dcda4 100644 --- a/config/test/config.scenarios.electricity.yaml +++ b/config/test/config.scenarios.electricity.yaml @@ -8,7 +8,7 @@ run: name: - test-elec-no-offshore-wind - test-elec-no-onshore-wind - scenario: + scenarios: enable: true file: "config/test/scenarios.electricity.yaml" disable_progressbar: true diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index 3d8e4e8c..718867a6 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -1,8 +1,8 @@ ,Unit,Values,Description name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenario: enable`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenario: file``." -scenario,,, +scenarios,,, -- enable,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``file``." -- file,str,,Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``create_scenarios.py`` script in ``scripts``. disable_progrssbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." -shared_resources,bool/str,,"Switch to select whether resources should be shared across runs. If a string is passed, it is assumed to be a wildcard or 'base' that indicates the cutoff after which resources are no longer shared. If 'base' is passed, resources before creating the elec.nc file are shared." +shared_resources,bool/str/list,,"Switch to select whether resources should be shared across runs. If a string or list is passed, it is assumed to be wildcard(s) which indicates up to which set of wildcards the resource folder should be shared. If set to 'base', only resources before creating the elec.nc file are shared." shared_cutouts,bool,"{true, false}","Switch to select whether cutouts should be shared across runs." diff --git a/rules/common.smk b/rules/common.smk index 0467d560..dab15c0d 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -58,7 +58,7 @@ def config_provider(*keys, default=None): my_param=config_provider("key1", "key2", default="some_default_value") """ # Using functools.partial to freeze certain arguments in our getter functions. - if config["run"].get("scenarios", False): + if config["run"].get("scenarios", {}).get("enable", False): return partial(dynamic_getter, keys=keys, default=default) else: return partial(static_getter, keys=keys, default=default) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index c166c61c..ed46db77 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -8,6 +8,7 @@ import logging import os import re import urllib +from functools import partial from pathlib import Path import pandas as pd @@ -21,41 +22,72 @@ logger = logging.getLogger(__name__) REGION_COLS = ["geometry", "name", "x", "y", "country"] +def get_run_path(fn, dir, rdir, shared_resources): + """ + Dynamically provide paths based on shared resources and filename. + + Use this function for snakemake rule inputs or outputs that should be + optionally shared across runs or created individually for each run. + + Parameters + ---------- + fn : str + The filename for the path to be generated. + dir : str + The base directory. + rdir : str + Relative directory for non-shared resources. + shared_resources : str, list, or bool + Specifies which resources should be shared. + - If string or list, assumed to be superset of wildcards for sharing. + - If "base", special handling for shared "base" resources. + - If boolean, directly specifies if the resource is shared. + + Returns + ------- + str + Full path where the resource should be stored. + + Notes + ----- + Special case for "base" allows no wildcards other than + "technology" and excludes filenames starting with "networks/elec" or + "add_electricity". + """ + pattern = r"\{([^{}]+)\}" + existing_wildcards = list(re.findall(pattern, fn)) + if shared_resources == "base": + # special case for shared "base" resources + no_relevant_wildcards = not len(set(existing_wildcards) - {"technology"}) + no_elec_rule = not fn.startswith("networks/elec") and not fn.startswith( + "add_electricity" + ) + is_shared = no_relevant_wildcards and no_elec_rule + elif isinstance(shared_resources, (str, list)): + if isinstance(shared_resources, str): + shared_resources = [shared_resources] + is_shared = set(existing_wildcards).issubset(shared_resources) + else: + is_shared = shared_resources + + if is_shared: + return f"{dir}{fn}" + else: + return f"{dir}{rdir}{fn}" + + def path_provider(dir, rdir, shared_resources): """ - Dynamically provide paths based on shared resources. + Returns a partial function that dynamically provides paths based on shared + resources and the filename. - Use this function whenever there is an input or output to a - snakemake rule that should, optionally, be either shared across runs - or created individually for each run. If shared_resources is a - string, it is assumed to be the wildcard that indicates the cutoff - after which resources are no longer shared. The function returns a - function which takes a filename and returns a path that is either - shared or individual to each run. + Returns + ------- + partial function + A partial function that takes a filename as input and + returns the path to the file based on the shared_resources parameter. """ - - def path(fn): - pattern = r"\{([^{}]+)\}" - existing_wildcards = list(re.findall(pattern, fn)) - if shared_resources == "base": - # special case for shared "base" resources - no_relevant_wildcards = not len(set(existing_wildcards) - {"technology"}) - no_elec_rule = not fn.startswith("networks/elec") and not fn.startswith( - "add_electricity" - ) - is_shared = no_relevant_wildcards and no_elec_rule - elif isinstance(shared_resources, str): - final_wildcard = shared_resources - is_shared = final_wildcard not in existing_wildcards[:-1] - else: - is_shared = shared_resources - - if is_shared: - return f"{dir}{fn}" - else: - return f"{dir}{rdir}{fn}" - - return path + return partial(get_run_path, dir=dir, rdir=rdir, shared_resources=shared_resources) # Define a context manager to temporarily mute print statements @@ -67,7 +99,7 @@ def mute_print(): def set_scenario_config(snakemake): - scenario = snakemake.config["run"].get("scenario", {}) + scenario = snakemake.config["run"].get("scenarios", {}) if scenario.get("enable") and "run" in snakemake.wildcards.keys(): try: with open(scenario["file"], "r") as f: From c7e6d36014ef7e16aafadb0b3eaa8a69900e3240 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 24 Aug 2023 13:33:26 +0200 Subject: [PATCH 105/591] fix separators in run.csv --- doc/configtables/run.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index 718867a6..925c2dea 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -2,7 +2,7 @@ name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenario: enable`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenario: file``." scenarios,,, -- enable,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``file``." --- file,str,,Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``create_scenarios.py`` script in ``scripts``. +-- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``create_scenarios.py`` script in ``scripts``." disable_progrssbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." shared_resources,bool/str/list,,"Switch to select whether resources should be shared across runs. If a string or list is passed, it is assumed to be wildcard(s) which indicates up to which set of wildcards the resource folder should be shared. If set to 'base', only resources before creating the elec.nc file are shared." shared_cutouts,bool,"{true, false}","Switch to select whether cutouts should be shared across runs." From f96c2d05899bb8d51087223f54a384410e4579df Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 22 Sep 2023 13:58:08 +0200 Subject: [PATCH 106/591] update solve smk files to properly consider scenanrios --- rules/common.smk | 7 +++++-- rules/solve_electricity.smk | 16 ++++++++-------- rules/solve_myopic.smk | 36 ++++++++++++++++++++---------------- rules/solve_overnight.smk | 14 +++++++------- scripts/solve_network.py | 8 ++++---- 5 files changed, 44 insertions(+), 37 deletions(-) diff --git a/rules/common.smk b/rules/common.smk index dab15c0d..c4b8e6d2 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -10,7 +10,10 @@ def get_config(config, keys, default=None): """Retrieve a nested value from a dictionary using a tuple of keys.""" value = config for key in keys: - value = value.get(key, default) + if isinstance(value, list): + value = value[key] + else: + value = value.get(key, default) if value == default: return default return value @@ -40,7 +43,7 @@ def static_getter(wildcards, keys, default): def dynamic_getter(wildcards, keys, default): """Getter function for dynamic config values based on scenario.""" - if "run" not in wildcards: + if "run" not in wildcards.keys(): return get_config(config, keys, default) scenario_name = wildcards.run if scenario_name not in scenarios: diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index cfdb1da0..424748e2 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -5,11 +5,11 @@ rule solve_network: params: - solving=config["solving"], - foresight=config["foresight"], - planning_horizons=config["scenario"]["planning_horizons"], - co2_sequestration_potential=config["sector"].get( - "co2_sequestration_potential", 200 + solving=config_provider("solving"), + foresight=config_provider("foresight"), + planning_horizons=config_provider("scenario", "planning_horizons"), + co2_sequestration_potential=config_provider( + "sector", "co2_sequestration_potential", default=200 ), input: network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), @@ -27,7 +27,7 @@ rule solve_network: threads: 4 resources: mem_mb=memory, - walltime=config["solving"].get("walltime", "12:00:00"), + walltime=config_provider("solving", "walltime", default="12:00:00"), shadow: "minimal" conda: @@ -38,7 +38,7 @@ rule solve_network: rule solve_operations_network: params: - options=config["solving"]["options"], + options=config_provider("solving", "options"), input: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", output: @@ -58,7 +58,7 @@ rule solve_operations_network: threads: 4 resources: mem_mb=(lambda w: 10000 + 372 * int(w.clusters)), - walltime=config["solving"].get("walltime", "12:00:00"), + walltime=config_provider("solving", "walltime", default="12:00:00"), shadow: "minimal" conda: diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 214733b7..7f851326 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -5,10 +5,10 @@ rule add_existing_baseyear: params: - baseyear=config["scenario"]["planning_horizons"][0], - sector=config["sector"], - existing_capacities=config["existing_capacities"], - costs=config["costs"], + baseyear=config_provider("scenario", "planning_horizons", 0), + sector=config_provider("sector"), + existing_capacities=config_provider("existing_capacities"), + costs=config_provider("costs"), input: network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -16,7 +16,9 @@ rule add_existing_baseyear: busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - costs="data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), + costs=lambda w: "data/costs_{}.csv".format( + config_provider("scenario", "planning_horizons", 0)(w) + ), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), existing_heating="data/existing_infrastructure/existing_heating_raw.csv", @@ -27,7 +29,7 @@ rule add_existing_baseyear: RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", wildcard_constraints: - planning_horizons=config["scenario"]["planning_horizons"][0], #only applies to baseyear + planning_horizons=config_provider("scenario", "planning_horizons", 0), #only applies to baseyear threads: 1 resources: mem_mb=2000, @@ -47,9 +49,11 @@ rule add_existing_baseyear: rule add_brownfield: params: - H2_retrofit=config["sector"]["H2_retrofit"], - H2_retrofit_capacity_per_CH4=config["sector"]["H2_retrofit_capacity_per_CH4"], - threshold_capacity=config["existing_capacities"]["threshold_capacity"], + H2_retrofit=config_provider("sector", "H2_retrofit"), + H2_retrofit_capacity_per_CH4=config_provider( + "sector", "H2_retrofit_capacity_per_CH4" + ), + threshold_capacity=config_provider("existing_capacities", " threshold_capacity"), input: network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -82,11 +86,11 @@ ruleorder: add_existing_baseyear > add_brownfield rule solve_sector_network_myopic: params: - solving=config["solving"], - foresight=config["foresight"], - planning_horizons=config["scenario"]["planning_horizons"], - co2_sequestration_potential=config["sector"].get( - "co2_sequestration_potential", 200 + solving=config_provider("solving"), + foresight=config_provider("foresight"), + planning_horizons=config_provider("scenario", "planning_horizons"), + co2_sequestration_potential=config_provider( + "sector", "co2_sequestration_potential", default=200 ), input: network=RESULTS @@ -105,8 +109,8 @@ rule solve_sector_network_myopic: + "elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", threads: 4 resources: - mem_mb=config["solving"]["mem"], - walltime=config["solving"].get("walltime", "12:00:00"), + mem_mb=config_provider("solving", "mem"), + walltime=config_provider("solving", "walltime", default="12:00:00"), benchmark: ( BENCHMARKS diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index d8476868..8f2ff139 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -5,11 +5,11 @@ rule solve_sector_network: params: - solving=config["solving"], - foresight=config["foresight"], - planning_horizons=config["scenario"]["planning_horizons"], - co2_sequestration_potential=config["sector"].get( - "co2_sequestration_potential", 200 + solving=config_provider("solving"), + foresight=config_provider("foresight"), + planning_horizons=config_provider("scenario", "planning_horizons"), + co2_sequestration_potential=config_provider( + "sector", "co2_sequestration_potential", default=200 ), input: network=RESULTS @@ -27,8 +27,8 @@ rule solve_sector_network: + "elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", threads: config["solving"]["solver"].get("threads", 4) resources: - mem_mb=config["solving"]["mem"], - walltime=config["solving"].get("walltime", "12:00:00"), + mem_mb=config_provider("solving", "mem"), + walltime=config_provider("solving", "walltime", default="12:00:00"), benchmark: ( BENCHMARKS diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 1e1e738b..bf860054 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -137,10 +137,10 @@ def add_co2_sequestration_limit(n, limit=200): n.add( "GlobalConstraint", "co2_sequestration_limit", - sense="<=", - constant=limit, - type="primary_energy", - carrier_attribute="co2_absorptions", + sense=">=", + constant=-limit, + type="operational_limit", + carrier_attribute="co2 sequestered", ) From 7e290d3e5281c6580efc25af4d33ed402f74186a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 8 Oct 2023 09:55:36 +0000 Subject: [PATCH 107/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/configtables/hydro.csv | 16 +-- doc/configtables/toplevel.csv | 24 ++-- rules/build_sector.smk | 240 +++++++++++++++++++++++----------- 3 files changed, 184 insertions(+), 96 deletions(-) diff --git a/doc/configtables/hydro.csv b/doc/configtables/hydro.csv index ad4bd7aa..f9c8f0d5 100644 --- a/doc/configtables/hydro.csv +++ b/doc/configtables/hydro.csv @@ -9,12 +9,12 @@ eia_norm_year,--,"Year in EIA hydro generation dataset; or False to disable","To eia_correct_by_capacity,--,boolean,"Correct EIA annual hydro generation data by installed capacity." eia_approximate_missing,--,boolean,"Approximate hydro generation data for years not included in EIA dataset through a regression based on annual runoff." ======= -,Unit,Values,Description -cutout,--,Must be 'europe-2013-era5',Specifies the directory where the relevant weather data ist stored. -carriers,--,"Any subset of {'ror', 'PHS', 'hydro'}","Specifies the types of hydro power plants to build per-unit availability time series for. 'ror' stands for run-of-river plants, 'PHS' represents pumped-hydro storage, and 'hydro' stands for hydroelectric dams." -PHS_max_hours,h,float,Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom``. Cf. `PyPSA documentation `_. -hydro_max_hours,h,"Any of {float, 'energy_capacity_totals_by_country', 'estimate_by_large_installations'}",Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom`` or heuristically determined. Cf. `PyPSA documentation `_. -flatten_dispatch,bool,"{true, false}",Consider an upper limit for the hydro dispatch. The limit is given by the average capacity factor plus the buffer given in ``flatten_dispatch_buffer`` -flatten_dispatch_buffer,--,float,"If ``flatten_dispatch`` is true, specify the value added above the average capacity factor." -clip_min_inflow,MW,float,"To avoid too small values in the inflow time series, values below this threshold are set to zero." +,Unit,Values,Description +cutout,--,Must be 'europe-2013-era5',Specifies the directory where the relevant weather data ist stored. +carriers,--,"Any subset of {'ror', 'PHS', 'hydro'}","Specifies the types of hydro power plants to build per-unit availability time series for. 'ror' stands for run-of-river plants, 'PHS' represents pumped-hydro storage, and 'hydro' stands for hydroelectric dams." +PHS_max_hours,h,float,Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom``. Cf. `PyPSA documentation `_. +hydro_max_hours,h,"Any of {float, 'energy_capacity_totals_by_country', 'estimate_by_large_installations'}",Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom`` or heuristically determined. Cf. `PyPSA documentation `_. +flatten_dispatch,bool,"{true, false}",Consider an upper limit for the hydro dispatch. The limit is given by the average capacity factor plus the buffer given in ``flatten_dispatch_buffer`` +flatten_dispatch_buffer,--,float,"If ``flatten_dispatch`` is true, specify the value added above the average capacity factor." +clip_min_inflow,MW,float,"To avoid too small values in the inflow time series, values below this threshold are set to zero." >>>>>>> master diff --git a/doc/configtables/toplevel.csv b/doc/configtables/toplevel.csv index 28c37206..877b234b 100644 --- a/doc/configtables/toplevel.csv +++ b/doc/configtables/toplevel.csv @@ -25,16 +25,16 @@ co2_budget,--,"Dictionary with planning horizons as keys.","CO2 budget as a frac ======= >>>>>>> origin/master ======= -,Unit,Values,Description -version,--,0.x.x,Version of PyPSA-Eur. Descriptive only. -tutorial,bool,"{true, false}",Switch to retrieve the tutorial data set instead of the full data set. -logging,,, --- level,--,"Any of {'INFO', 'WARNING', 'ERROR'}","Restrict console outputs to all infos, warning or errors only" --- format,--,,Custom format for log messages. See `LogRecord `_ attributes. -private,,, --- keys,,, --- -- entsoe_api,--,,Optionally specify the ENTSO-E API key. See the guidelines to get `ENTSO-E API key `_ -remote,,, --- ssh,--,,Optionally specify the SSH of a remote cluster to be synchronized. --- path,--,,Optionally specify the file path within the remote cluster to be synchronized. +,Unit,Values,Description +version,--,0.x.x,Version of PyPSA-Eur. Descriptive only. +tutorial,bool,"{true, false}",Switch to retrieve the tutorial data set instead of the full data set. +logging,,, +-- level,--,"Any of {'INFO', 'WARNING', 'ERROR'}","Restrict console outputs to all infos, warning or errors only" +-- format,--,,Custom format for log messages. See `LogRecord `_ attributes. +private,,, +-- keys,,, +-- -- entsoe_api,--,,Optionally specify the ENTSO-E API key. See the guidelines to get `ENTSO-E API key `_ +remote,,, +-- ssh,--,,Optionally specify the SSH of a remote cluster to be synchronized. +-- path,--,,Optionally specify the file path within the remote cluster to be synchronized. >>>>>>> master diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 3c859b3c..1cc54ec0 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -30,16 +30,21 @@ rule build_clustered_population_layouts: pop_layout_total=RESOURCES + "pop_layout_total{weather_year}.nc", pop_layout_urban=RESOURCES + "pop_layout_urban{weather_year}.nc", pop_layout_rural=RESOURCES + "pop_layout_rural{weather_year}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - clustered_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", + clustered_pop_layout=RESOURCES + + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", log: LOGS + "build_clustered_population_layouts{weather_year}_{simpl}_{clusters}.log", resources: mem_mb=10000, benchmark: - BENCHMARKS + "build_clustered_population_layouts/{weather_year}_s{simpl}_{clusters}" + ( + BENCHMARKS + + "build_clustered_population_layouts/{weather_year}_s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -51,7 +56,8 @@ rule build_simplified_population_layouts: pop_layout_total=RESOURCES + "pop_layout_total{weather_year}.nc", pop_layout_urban=RESOURCES + "pop_layout_urban{weather_year}.nc", pop_layout_rural=RESOURCES + "pop_layout_rural{weather_year}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}.geojson", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: clustered_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}.csv", @@ -117,7 +123,8 @@ if config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]: regions_offshore=RESOURCES + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson", output: - clustered_gas_network=RESOURCES + "gas_network_elec{weather_year}_s{simpl}_{clusters}.csv", + clustered_gas_network=RESOURCES + + "gas_network_elec{weather_year}_s{simpl}_{clusters}.csv", resources: mem_mb=4000, log: @@ -144,10 +151,12 @@ rule build_heat_demands: snapshots=config["snapshots"], input: pop_layout=RESOURCES + "pop_layout{weather_year}_{scope}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - heat_demand=RESOURCES + "heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc", + heat_demand=RESOURCES + + "heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc", resources: mem_mb=20000, threads: 8 @@ -166,18 +175,25 @@ rule build_temperature_profiles: snapshots=config["snapshots"], input: pop_layout=RESOURCES + "pop_layout{weather_year}_{scope}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - temp_soil=RESOURCES + "temp_soil_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_air=RESOURCES + "temp_air_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_soil=RESOURCES + + "temp_soil_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_air=RESOURCES + + "temp_air_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc", resources: mem_mb=20000, threads: 8 log: - LOGS + "build_temperature_profiles_{scope}_{weather_year}_{simpl}_{clusters}.log", + LOGS + + "build_temperature_profiles_{scope}_{weather_year}_{simpl}_{clusters}.log", benchmark: - BENCHMARKS + "build_temperature_profiles/{scope}_{weather_year}_s{simpl}_{clusters}" + ( + BENCHMARKS + + "build_temperature_profiles/{scope}_{weather_year}_s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -188,19 +204,31 @@ rule build_cop_profiles: params: heat_pump_sink_T=config["sector"]["heat_pump_sink_T"], input: - temp_soil_total=RESOURCES + "temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_soil_rural=RESOURCES + "temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_soil_urban=RESOURCES + "temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_air_total=RESOURCES + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_air_rural=RESOURCES + "temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_air_urban=RESOURCES + "temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_soil_total=RESOURCES + + "temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_soil_rural=RESOURCES + + "temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_soil_urban=RESOURCES + + "temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_air_total=RESOURCES + + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_air_rural=RESOURCES + + "temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_air_urban=RESOURCES + + "temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc", output: - cop_soil_total=RESOURCES + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_soil_rural=RESOURCES + "cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_soil_urban=RESOURCES + "cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_air_rural=RESOURCES + "cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_air_urban=RESOURCES + "cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_soil_total=RESOURCES + + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_soil_rural=RESOURCES + + "cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_soil_urban=RESOURCES + + "cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_air_total=RESOURCES + + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_air_rural=RESOURCES + + "cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_air_urban=RESOURCES + + "cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc", resources: mem_mb=20000, log: @@ -219,17 +247,23 @@ rule build_solar_thermal_profiles: solar_thermal=config["solar_thermal"], input: pop_layout=RESOURCES + "pop_layout{weather_year}_{scope}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - solar_thermal=RESOURCES + "solar_thermal_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc", + solar_thermal=RESOURCES + + "solar_thermal_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc", resources: mem_mb=20000, threads: 16 log: - LOGS + "build_solar_thermal_profiles_{scope}_{weather_year}_s{simpl}_{clusters}.log", + LOGS + + "build_solar_thermal_profiles_{scope}_{weather_year}_s{simpl}_{clusters}.log", benchmark: - BENCHMARKS + "build_solar_thermal_profiles/{scope}_{weather_year}_s{simpl}_{clusters}" + ( + BENCHMARKS + + "build_solar_thermal_profiles/{scope}_{weather_year}_s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -269,13 +303,14 @@ rule build_heat_totals: hdd="data/era5-annual-HDD-per-country.csv", energy_totals=RESOURCES + "energy_totals.csv", output: - heat_totals=RESOURCES + "heat_totals.csv" + heat_totals=RESOURCES + "heat_totals.csv", threads: 1 - resources: mem_mb=2000 + resources: + mem_mb=2000, log: LOGS + "build_heat_totals.log", benchmark: - BENCHMARKS + "build_heat_totals", + BENCHMARKS + "build_heat_totals" conda: "../envs/environment.yaml" script: @@ -291,7 +326,8 @@ rule build_biomass_potentials: keep_local=True, ), nuts2="data/bundle-sector/nuts/NUTS_RG_10M_2013_4326_LEVL_2.geojson", # https://gisco-services.ec.europa.eu/distribution/v2/nuts/download/#nuts21 - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", nuts3_population=ancient("data/bundle/nama_10r_3popgdp.tsv.gz"), swiss_cantons=ancient("data/bundle/ch_cantons.csv"), swiss_population=ancient("data/bundle/je-e-21.03.02.xls"), @@ -305,9 +341,13 @@ rule build_biomass_potentials: resources: mem_mb=1000, log: - LOGS + "build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log", + LOGS + + "build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log", benchmark: - BENCHMARKS + "build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}" + ( + BENCHMARKS + + "build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: @@ -367,9 +407,13 @@ if config["sector"]["regional_co2_sequestration_potential"]["enable"]: resources: mem_mb=4000, log: - LOGS + "build_sequestration_potentials{weather_year}_s{simpl}_{clusters}.log", + LOGS + + "build_sequestration_potentials{weather_year}_s{simpl}_{clusters}.log", benchmark: - BENCHMARKS + "build_sequestration_potentials{weather_year}_s{simpl}_{clusters}" + ( + BENCHMARKS + + "build_sequestration_potentials{weather_year}_s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -386,10 +430,13 @@ if not config["sector"]["regional_co2_sequestration_potential"]["enable"]: rule build_salt_cavern_potentials: input: salt_caverns="data/bundle-sector/h2_salt_caverns_GWh_per_sqkm.geojson", - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", - regions_offshore=RESOURCES + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions_offshore=RESOURCES + + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson", output: - h2_cavern_potential=RESOURCES + "salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv", + h2_cavern_potential=RESOURCES + + "salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv", threads: 1 resources: mem_mb=2000, @@ -500,8 +547,10 @@ rule build_industrial_distribution_key: hotmaps_locate_missing=config["industry"].get("hotmaps_locate_missing", False), countries=config["countries"], input: - regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", - clustered_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", + regions_onshore=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + clustered_pop_layout=RESOURCES + + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", hotmaps_industrial_database="data/bundle-sector/Industrial_Database.csv", output: industrial_distribution_key=RESOURCES @@ -512,7 +561,10 @@ rule build_industrial_distribution_key: log: LOGS + "build_industrial_distribution_key{weather_year}_s{simpl}_{clusters}.log", benchmark: - BENCHMARKS + "build_industrial_distribution_key/{weather_year}_s{simpl}_{clusters}" + ( + BENCHMARKS + + "build_industrial_distribution_key/{weather_year}_s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -610,9 +662,13 @@ rule build_industrial_energy_demand_per_node_today: resources: mem_mb=1000, log: - LOGS + "build_industrial_energy_demand_per_node_today{weather_year}_s{simpl}_{clusters}.log", + LOGS + + "build_industrial_energy_demand_per_node_today{weather_year}_s{simpl}_{clusters}.log", benchmark: - BENCHMARKS + "build_industrial_energy_demand_per_node_today/{weather_year}_s{simpl}_{clusters}" + ( + BENCHMARKS + + "build_industrial_energy_demand_per_node_today/{weather_year}_s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -628,17 +684,21 @@ if config["sector"]["retrofitting"]["retro_endogen"]: input: building_stock="data/retro/data_building_stock.csv", data_tabula="data/retro/tabula-calculator-calcsetbuilding.csv", - air_temperature=RESOURCES + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", + air_temperature=RESOURCES + + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", u_values_PL="data/retro/u_values_poland.csv", tax_w="data/retro/electricity_taxes_eu.csv", construction_index="data/retro/comparative_level_investment.csv", floor_area_missing="data/retro/floor_area_missing.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", + clustered_pop_layout=RESOURCES + + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", cost_germany="data/retro/retro_cost_germany.csv", window_assumptions="data/retro/window_assumptions.csv", output: - retro_cost=RESOURCES + "retro_cost_elec{weather_year}_s{simpl}_{clusters}.csv", - floor_area=RESOURCES + "floor_area_elec{weather_year}_s{simpl}_{clusters}.csv", + retro_cost=RESOURCES + + "retro_cost_elec{weather_year}_s{simpl}_{clusters}.csv", + floor_area=RESOURCES + + "floor_area_elec{weather_year}_s{simpl}_{clusters}.csv", resources: mem_mb=1000, log: @@ -661,14 +721,16 @@ if not config["sector"]["retrofitting"]["retro_endogen"]: rule build_population_weighted_energy_totals: input: energy_totals=RESOURCES + "{kind}}_totals.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", + clustered_pop_layout=RESOURCES + + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", output: RESOURCES + "pop_weighted_{kind}_totals{weather_year}_s{simpl}_{clusters}.csv", threads: 1 resources: mem_mb=2000, log: - LOGS + "build_population_weighted_{kind}_totals{weather_year}_s{simpl}_{clusters}.log", + LOGS + + "build_population_weighted_{kind}_totals{weather_year}_s{simpl}_{clusters}.log", conda: "../envs/environment.yaml" script: @@ -679,7 +741,8 @@ rule build_shipping_demand: input: ports="data/attributed_ports.json", scope=RESOURCES + "europe_shape.geojson", - regions=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", + regions=RESOURCES + + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", demand=RESOURCES + "energy_totals.csv", output: RESOURCES + "shipping_demand{weather_year}_s{simpl}_{clusters}.csv", @@ -699,16 +762,20 @@ rule build_transport_demand: snapshots=config["snapshots"], sector=config["sector"], input: - clustered_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", + clustered_pop_layout=RESOURCES + + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", pop_weighted_energy_totals=RESOURCES + "pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv", transport_data=RESOURCES + "transport_data.csv", traffic_data_KFZ="data/bundle-sector/emobility/KFZ__count", traffic_data_Pkw="data/bundle-sector/emobility/Pkw__count", - temp_air_total=RESOURCES + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_air_total=RESOURCES + + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", output: - transport_demand=RESOURCES + "transport_demand{weather_year}_s{simpl}_{clusters}.csv", - transport_data=RESOURCES + "transport_data{weather_year}_s{simpl}_{clusters}.csv", + transport_demand=RESOURCES + + "transport_demand{weather_year}_s{simpl}_{clusters}.csv", + transport_data=RESOURCES + + "transport_data{weather_year}_s{simpl}_{clusters}.csv", avail_profile=RESOURCES + "avail_profile{weather_year}_s{simpl}_{clusters}.csv", dsm_profile=RESOURCES + "dsm_profile{weather_year}_s{simpl}_{clusters}.csv", threads: 1 @@ -742,16 +809,20 @@ rule prepare_sector_network: **build_biomass_transport_costs_output, **gas_infrastructure, **build_sequestration_potentials_output, - network=RESOURCES + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=RESOURCES + + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", energy_totals_name=RESOURCES + "energy_totals.csv", eurostat=input_eurostat, pop_weighted_energy_totals=RESOURCES + "pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv", pop_weighted_heat_totals=RESOURCES + "pop_weighted_heat_totals{weather_year}_s{simpl}_{clusters}.csv", - shipping_demand=RESOURCES + "shipping_demand{weather_year}_s{simpl}_{clusters}.csv", - transport_demand=RESOURCES + "transport_demand{weather_year}_s{simpl}_{clusters}.csv", - transport_data=RESOURCES + "transport_data{weather_year}_s{simpl}_{clusters}.csv", + shipping_demand=RESOURCES + + "shipping_demand{weather_year}_s{simpl}_{clusters}.csv", + transport_demand=RESOURCES + + "transport_demand{weather_year}_s{simpl}_{clusters}.csv", + transport_data=RESOURCES + + "transport_data{weather_year}_s{simpl}_{clusters}.csv", avail_profile=RESOURCES + "avail_profile{weather_year}_s{simpl}_{clusters}.csv", dsm_profile=RESOURCES + "dsm_profile{weather_year}_s{simpl}_{clusters}.csv", co2_totals_name=RESOURCES + "co2_totals.csv", @@ -768,28 +839,45 @@ rule prepare_sector_network: else "data/costs_{planning_horizons}.csv", profile_offwind_ac=RESOURCES + "profile{weather_year}_offwind-ac.nc", profile_offwind_dc=RESOURCES + "profile{weather_year}_offwind-dc.nc", - h2_cavern=RESOURCES + "salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv", + h2_cavern=RESOURCES + + "salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv", busmap_s=RESOURCES + "busmap_elec{weather_year}_s{simpl}.csv", busmap=RESOURCES + "busmap_elec{weather_year}_s{simpl}_{clusters}.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", + clustered_pop_layout=RESOURCES + + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", simplified_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}.csv", industrial_demand=RESOURCES + "industrial_energy_demand_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv", - heat_demand_urban=RESOURCES + "heat_demand_urban_elec{weather_year}_s{simpl}_{clusters}.nc", - heat_demand_rural=RESOURCES + "heat_demand_rural_elec{weather_year}_s{simpl}_{clusters}.nc", - heat_demand_total=RESOURCES + "heat_demand_total_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_soil_total=RESOURCES + "temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_soil_rural=RESOURCES + "temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_soil_urban=RESOURCES + "temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_air_total=RESOURCES + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_air_rural=RESOURCES + "temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc", - temp_air_urban=RESOURCES + "temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_soil_total=RESOURCES + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_soil_rural=RESOURCES + "cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_soil_urban=RESOURCES + "cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_air_rural=RESOURCES + "cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc", - cop_air_urban=RESOURCES + "cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc", + heat_demand_urban=RESOURCES + + "heat_demand_urban_elec{weather_year}_s{simpl}_{clusters}.nc", + heat_demand_rural=RESOURCES + + "heat_demand_rural_elec{weather_year}_s{simpl}_{clusters}.nc", + heat_demand_total=RESOURCES + + "heat_demand_total_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_soil_total=RESOURCES + + "temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_soil_rural=RESOURCES + + "temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_soil_urban=RESOURCES + + "temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_air_total=RESOURCES + + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_air_rural=RESOURCES + + "temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc", + temp_air_urban=RESOURCES + + "temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_soil_total=RESOURCES + + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_soil_rural=RESOURCES + + "cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_soil_urban=RESOURCES + + "cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_air_total=RESOURCES + + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_air_rural=RESOURCES + + "cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc", + cop_air_urban=RESOURCES + + "cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc", solar_thermal_total=RESOURCES + "solar_thermal_total_elec{weather_year}_s{simpl}_{clusters}.nc" if config["sector"]["solar_thermal"] From 4349903a72c7dcf5848f9b8c7d6b68a8c1292dc0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 30 Dec 2023 14:36:18 +0100 Subject: [PATCH 108/591] env: remove snakemake upper version constraint --- envs/environment.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/envs/environment.yaml b/envs/environment.yaml index 535acbdb..b9f9ac99 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -20,8 +20,7 @@ dependencies: - openpyxl!=3.1.1 - pycountry - seaborn - # snakemake 8 introduced a number of breaking changes which the workflow has yet to be made compatible with -- snakemake-minimal>=7.7.0,<8.0.0 +- snakemake-minimal>=7.7.0 - memory_profiler - yaml - pytables From 48850431fbc296d4178933ea0f869bc515068b92 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 30 Dec 2023 14:37:45 +0100 Subject: [PATCH 109/591] Snakefile: switch to new storage providers --- Snakefile | 4 ---- envs/environment.yaml | 1 + rules/build_sector.smk | 14 +++++-------- rules/retrieve.smk | 47 ++++++++++++++---------------------------- 4 files changed, 21 insertions(+), 45 deletions(-) diff --git a/Snakefile b/Snakefile index 83530df7..42988ebc 100644 --- a/Snakefile +++ b/Snakefile @@ -5,10 +5,6 @@ from os.path import normpath, exists from shutil import copyfile, move, rmtree -from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider - -HTTP = HTTPRemoteProvider() - from snakemake.utils import min_version min_version("7.7") diff --git a/envs/environment.yaml b/envs/environment.yaml index b9f9ac99..ce733ed9 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -59,3 +59,4 @@ dependencies: - pip: - tsam>=2.3.1 + - snakemake-storage-plugin-http \ No newline at end of file diff --git a/rules/build_sector.smk b/rules/build_sector.smk index dd49fc6f..3f71ba72 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -85,9 +85,8 @@ if config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]: rule build_gas_input_locations: input: - lng=HTTP.remote( + lng=storage( "https://globalenergymonitor.org/wp-content/uploads/2023/07/Europe-Gas-Tracker-2023-03-v3.xlsx", - keep_local=True, ), entry="data/gas_network/scigrid-gas/data/IGGIELGN_BorderPoints.geojson", production="data/gas_network/scigrid-gas/data/IGGIELGN_Productions.geojson", @@ -268,9 +267,8 @@ rule build_biomass_potentials: params: biomass=config["biomass"], input: - enspreso_biomass=HTTP.remote( + enspreso_biomass=storage( "https://zenodo.org/records/10356004/files/ENSPRESO_BIOMASS.xlsx", - keep_local=True, ), nuts2="data/bundle-sector/nuts/NUTS_RG_10M_2013_4326_LEVL_2.geojson", # https://gisco-services.ec.europa.eu/distribution/v2/nuts/download/#nuts21 regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", @@ -300,9 +298,8 @@ if config["sector"]["biomass_transport"] or config["sector"]["biomass_spatial"]: rule build_biomass_transport_costs: input: - transport_cost_data=HTTP.remote( - "publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", - keep_local=True, + transport_cost_data=storage( + "https://publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", ), output: biomass_transport_costs=RESOURCES + "biomass_transport_costs.csv", @@ -334,9 +331,8 @@ if config["sector"]["regional_co2_sequestration_potential"]["enable"]: "regional_co2_sequestration_potential" ], input: - sequestration_potential=HTTP.remote( + sequestration_potential=storage( "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", - keep_local=True, ), regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 0483a833..a35cc53c 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -64,9 +64,8 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_cutout", True rule retrieve_cutout: input: - HTTP.remote( - "zenodo.org/record/6382570/files/{cutout}.nc", - static=True, + storage( + "https://zenodo.org/record/6382570/files/{cutout}.nc", ), output: protected("cutouts/" + CDIR + "{cutout}.nc"), @@ -83,12 +82,11 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_cost_data", T rule retrieve_cost_data: input: - HTTP.remote( - "raw.githubusercontent.com/PyPSA/technology-data/{}/outputs/".format( + storage( + "https://raw.githubusercontent.com/PyPSA/technology-data/{}/outputs/".format( config["costs"]["version"] ) + "costs_{year}.csv", - keep_local=True, ), output: "data/costs_{year}.csv", @@ -107,10 +105,8 @@ if config["enable"]["retrieve"] and config["enable"].get( rule retrieve_natura_raster: input: - HTTP.remote( - "zenodo.org/record/4706686/files/natura.tiff", - keep_local=True, - static=True, + storage( + "https://zenodo.org/record/4706686/files/natura.tiff", ), output: RESOURCES + "natura.tiff", @@ -188,14 +184,12 @@ if config["enable"]["retrieve"]: rule retrieve_electricity_demand: input: - HTTP.remote( - "data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv".format( + storage( + "https://data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv".format( version="2019-06-05" if config["snapshots"]["end"] < "2019" else "2020-10-06" ), - keep_local=True, - static=True, ), output: RESOURCES + "load_raw.csv", @@ -212,10 +206,8 @@ if config["enable"]["retrieve"]: rule retrieve_ship_raster: input: - HTTP.remote( + storage( "https://zenodo.org/record/6953563/files/shipdensity_global.zip", - keep_local=True, - static=True, ), output: protected("data/shipdensity_global.zip"), @@ -234,9 +226,8 @@ if config["enable"]["retrieve"]: # Website: https://land.copernicus.eu/global/products/lc rule download_copernicus_land_cover: input: - HTTP.remote( - "zenodo.org/record/3939050/files/PROBAV_LC100_global_v3.0.1_2019-nrt_Discrete-Classification-map_EPSG-4326.tif", - static=True, + storage( + "https://zenodo.org/record/3939050/files/PROBAV_LC100_global_v3.0.1_2019-nrt_Discrete-Classification-map_EPSG-4326.tif", ), output: "data/Copernicus_LC100_global_v3.0.1_2019-nrt_Discrete-Classification-map_EPSG-4326.tif", @@ -279,11 +270,7 @@ if config["enable"]["retrieve"]: # Website: https://www.protectedplanet.net/en/thematic-areas/wdpa rule download_wdpa: input: - HTTP.remote( - url, - static=True, - keep_local=True, - ), + storage(url), params: zip="data/WDPA_shp.zip", folder=directory("data/WDPA"), @@ -305,10 +292,8 @@ if config["enable"]["retrieve"]: # extract the main zip and then merge the contained 3 zipped shapefiles # Website: https://www.protectedplanet.net/en/thematic-areas/marine-protected-areas input: - HTTP.remote( - f"d1gam3xoknrgr2.cloudfront.net/current/WDPA_WDOECM_{bYYYY}_Public_marine_shp.zip", - static=True, - keep_local=True, + storage( + f"https://d1gam3xoknrgr2.cloudfront.net/current/WDPA_WDOECM_{bYYYY}_Public_marine_shp.zip", ), params: zip="data/WDPA_WDOECM_marine.zip", @@ -330,10 +315,8 @@ if config["enable"]["retrieve"]: rule retrieve_monthly_co2_prices: input: - HTTP.remote( + storage( "https://www.eex.com/fileadmin/EEX/Downloads/EUA_Emission_Spot_Primary_Market_Auction_Report/Archive_Reports/emission-spot-primary-market-auction-report-2019-data.xls", - keep_local=True, - static=True, ), output: "data/validation/emission-spot-primary-market-auction-report-2019-data.xls", From 98e47eab3cef408dca6a9fc19a6e972b280aaa9f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 31 Dec 2023 13:00:21 +0100 Subject: [PATCH 110/591] mock_snakemake: adjust to snakemake version 8 --- scripts/_helpers.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 398f3a30..c3066965 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -214,9 +214,17 @@ def mock_snakemake(rulename, root_dir=None, configfiles=[], **wildcards): import os import snakemake as sm - from packaging.version import Version, parse from pypsa.descriptors import Dict + from snakemake.api import Workflow + from snakemake.common import SNAKEFILE_CHOICES from snakemake.script import Snakemake + from snakemake.settings import ( + ConfigSettings, + DAGSettings, + ResourceSettings, + StorageSettings, + WorkflowSettings, + ) script_dir = Path(__file__).parent.resolve() if root_dir is None: @@ -233,17 +241,26 @@ def mock_snakemake(rulename, root_dir=None, configfiles=[], **wildcards): f" {root_dir} or scripts directory {script_dir}" ) try: - for p in sm.SNAKEFILE_CHOICES: + for p in SNAKEFILE_CHOICES: if os.path.exists(p): snakefile = p break - kwargs = ( - dict(rerun_triggers=[]) if parse(sm.__version__) > Version("7.7.0") else {} - ) if isinstance(configfiles, str): configfiles = [configfiles] - workflow = sm.Workflow(snakefile, overwrite_configfiles=configfiles, **kwargs) + resource_settings = ResourceSettings() + config_settings = ConfigSettings(configfiles=configfiles) + workflow_settings = WorkflowSettings() + storage_settings = StorageSettings() + dag_settings = DAGSettings(rerun_triggers=[]) + workflow = Workflow( + config_settings, + resource_settings, + workflow_settings, + storage_settings, + dag_settings, + storage_provider_settings=dict(), + ) workflow.include(snakefile) if configfiles: From ea95f2b38c15719944f9bf413ae8683702593c92 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 31 Dec 2023 13:01:17 +0100 Subject: [PATCH 111/591] bumb minimum snakemake version to v8 --- Snakefile | 2 +- envs/environment.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Snakefile b/Snakefile index 42988ebc..468d06f2 100644 --- a/Snakefile +++ b/Snakefile @@ -7,7 +7,7 @@ from shutil import copyfile, move, rmtree from snakemake.utils import min_version -min_version("7.7") +min_version("8") if not exists("config/config.yaml"): diff --git a/envs/environment.yaml b/envs/environment.yaml index ce733ed9..7da973c6 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -20,7 +20,7 @@ dependencies: - openpyxl!=3.1.1 - pycountry - seaborn -- snakemake-minimal>=7.7.0 +- snakemake-minimal>=8 - memory_profiler - yaml - pytables From 19a50fb8c5c72fab188e305a5a8159c129df9ddc Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 31 Dec 2023 14:07:45 +0100 Subject: [PATCH 112/591] rules: add keep_local=True back in for storage providers --- rules/build_sector.smk | 4 ++++ rules/retrieve.smk | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 3f71ba72..0fea3c99 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -87,6 +87,7 @@ if config["sector"]["gas_network"] or config["sector"]["H2_retrofit"]: input: lng=storage( "https://globalenergymonitor.org/wp-content/uploads/2023/07/Europe-Gas-Tracker-2023-03-v3.xlsx", + keep_local=True, ), entry="data/gas_network/scigrid-gas/data/IGGIELGN_BorderPoints.geojson", production="data/gas_network/scigrid-gas/data/IGGIELGN_Productions.geojson", @@ -269,6 +270,7 @@ rule build_biomass_potentials: input: enspreso_biomass=storage( "https://zenodo.org/records/10356004/files/ENSPRESO_BIOMASS.xlsx", + keep_local=True, ), nuts2="data/bundle-sector/nuts/NUTS_RG_10M_2013_4326_LEVL_2.geojson", # https://gisco-services.ec.europa.eu/distribution/v2/nuts/download/#nuts21 regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", @@ -300,6 +302,7 @@ if config["sector"]["biomass_transport"] or config["sector"]["biomass_spatial"]: input: transport_cost_data=storage( "https://publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", + keep_local=True, ), output: biomass_transport_costs=RESOURCES + "biomass_transport_costs.csv", @@ -333,6 +336,7 @@ if config["sector"]["regional_co2_sequestration_potential"]["enable"]: input: sequestration_potential=storage( "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", + keep_local=True, ), regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", diff --git a/rules/retrieve.smk b/rules/retrieve.smk index a35cc53c..13120640 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -87,6 +87,7 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_cost_data", T config["costs"]["version"] ) + "costs_{year}.csv", + keep_local=True, ), output: "data/costs_{year}.csv", @@ -107,6 +108,7 @@ if config["enable"]["retrieve"] and config["enable"].get( input: storage( "https://zenodo.org/record/4706686/files/natura.tiff", + keep_local=True, ), output: RESOURCES + "natura.tiff", @@ -190,6 +192,7 @@ if config["enable"]["retrieve"]: if config["snapshots"]["end"] < "2019" else "2020-10-06" ), + keep_local=True, ), output: RESOURCES + "load_raw.csv", @@ -208,6 +211,7 @@ if config["enable"]["retrieve"]: input: storage( "https://zenodo.org/record/6953563/files/shipdensity_global.zip", + keep_local=True, ), output: protected("data/shipdensity_global.zip"), @@ -270,7 +274,7 @@ if config["enable"]["retrieve"]: # Website: https://www.protectedplanet.net/en/thematic-areas/wdpa rule download_wdpa: input: - storage(url), + storage(url, keep_local=True), params: zip="data/WDPA_shp.zip", folder=directory("data/WDPA"), @@ -294,6 +298,7 @@ if config["enable"]["retrieve"]: input: storage( f"https://d1gam3xoknrgr2.cloudfront.net/current/WDPA_WDOECM_{bYYYY}_Public_marine_shp.zip", + keep_local=True, ), params: zip="data/WDPA_WDOECM_marine.zip", @@ -317,6 +322,7 @@ if config["enable"]["retrieve"]: input: storage( "https://www.eex.com/fileadmin/EEX/Downloads/EUA_Emission_Spot_Primary_Market_Auction_Report/Archive_Reports/emission-spot-primary-market-auction-report-2019-data.xls", + keep_local=True, ), output: "data/validation/emission-spot-primary-market-auction-report-2019-data.xls", From 27ee2666be6300ac6a07f2e74c5ec6e1d49e2f64 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 31 Dec 2023 13:13:08 +0000 Subject: [PATCH 113/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- envs/environment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/envs/environment.yaml b/envs/environment.yaml index 7da973c6..36dbfcae 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -59,4 +59,4 @@ dependencies: - pip: - tsam>=2.3.1 - - snakemake-storage-plugin-http \ No newline at end of file + - snakemake-storage-plugin-http From 725a0ef8c01d810a99f57b92469061e7755a7cc4 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 10 Jan 2024 16:17:16 +0100 Subject: [PATCH 114/591] maybe_adjust_cost_and_potentials: cover all flags --- scripts/prepare_sector_network.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 37d6f0d2..69c2d467 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3346,7 +3346,7 @@ def remove_h2_network(n): def maybe_adjust_costs_and_potentials(n, opts): for o in opts: - flags = ["+e", "+p", "+m"] + flags = ["+e", "+p", "+m", "+c"] if all(flag not in o for flag in flags): continue oo = o.split("+") @@ -3361,7 +3361,12 @@ def maybe_adjust_costs_and_potentials(n, opts): suptechs = map(lambda c: c.split("-", 2)[0], carrier_list) if oo[0].startswith(tuple(suptechs)): carrier = oo[0] - attr_lookup = {"p": "p_nom_max", "e": "e_nom_max", "c": "capital_cost"} + attr_lookup = { + "p": "p_nom_max", + "e": "e_nom_max", + "c": "capital_cost", + "m": "marginal_cost", + } attr = attr_lookup[oo[1][0]] factor = float(oo[1][1:]) # beware if factor is 0 and p_nom_max is np.inf, 0*np.inf is nan From a6edce58fbfbf049eb6f6726d8a9535754b00c9d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 11 Jan 2024 09:47:09 +0100 Subject: [PATCH 115/591] remove wave energy generator --- config/config.default.yaml | 1 - doc/configtables/licenses-sector.csv | 1 - doc/release_notes.rst | 3 ++ scripts/prepare_sector_network.py | 47 ---------------------------- 4 files changed, 3 insertions(+), 49 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 7ef08e2f..1d28223f 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -814,7 +814,6 @@ plotting: hydroelectricity: '#298c81' PHS: '#51dbcc' hydro+PHS: "#08ad97" - wave: '#a7d4cf' # solar solar: "#f9d002" solar PV: "#f9d002" diff --git a/doc/configtables/licenses-sector.csv b/doc/configtables/licenses-sector.csv index d65d3b36..a297b2f6 100644 --- a/doc/configtables/licenses-sector.csv +++ b/doc/configtables/licenses-sector.csv @@ -9,7 +9,6 @@ Swiss energy statistics from Swiss Federal Office of Energy,switzerland-sfoe/,un BASt emobility statistics,emobility/,unknown,http://www.bast.de/DE/Verkehrstechnik/Fachthemen/v2-verkehrszaehlung/Stundenwerte.html?nn=626916 BDEW heating profile,heat_load_profile_BDEW.csv,unknown,https://github.com/oemof/demandlib heating profiles for Aarhus,heat_load_profile_DK_AdamJensen.csv,unknown,Adam Jensen MA thesis at Aarhus University -George Lavidas wind/wave costs,WindWaveWEC_GLTB.xlsx,unknown,George Lavidas co2 budgets,co2_budget.csv,CC BY 4.0,https://arxiv.org/abs/2004.11009 existing heating potentials,existing_infrastructure/existing_heating_raw.csv,unknown,https://ec.europa.eu/energy/studies/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment_en?redir=1 IRENA existing VRE capacities,existing_infrastructure/{solar|onwind|offwind}_capcity_IRENA.csv,unknown,https://www.irena.org/Statistics/Download-Data diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 940a391c..be6be9fd 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -12,6 +12,9 @@ Upcoming Release * New configuration option ``everywhere_powerplants`` to build conventional powerplants everywhere, irrespective of existing powerplants locations, in the network (https://github.com/PyPSA/pypsa-eur/pull/850). +* Remove option for wave energy as technology data is not maintained. + + PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 69c2d467..b57b832c 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -913,47 +913,6 @@ def add_ammonia(n, costs): ) -def add_wave(n, wave_cost_factor): - # TODO: handle in Snakefile - wave_fn = "data/WindWaveWEC_GLTB.xlsx" - - # in kW - capacity = pd.Series({"Attenuator": 750, "F2HB": 1000, "MultiPA": 600}) - - # in EUR/MW - annuity_factor = calculate_annuity(25, 0.07) + 0.03 - costs = ( - 1e6 - * wave_cost_factor - * annuity_factor - * pd.Series({"Attenuator": 2.5, "F2HB": 2, "MultiPA": 1.5}) - ) - - sheets = pd.read_excel( - wave_fn, - sheet_name=["FirthForth", "Hebrides"], - usecols=["Attenuator", "F2HB", "MultiPA"], - index_col=0, - skiprows=[0], - parse_dates=True, - ) - - wave = pd.concat( - [sheets[l].divide(capacity, axis=1) for l in locations], keys=locations, axis=1 - ) - - for wave_type in costs.index: - n.add( - "Generator", - "Hebrides " + wave_type, - bus="GB4 0", # TODO this location is hardcoded - p_nom_extendable=True, - carrier="wave", - capital_cost=costs[wave_type], - p_max_pu=wave["Hebrides", wave_type], - ) - - def insert_electricity_distribution_grid(n, costs): # TODO pop_layout? # TODO options? @@ -3698,12 +3657,6 @@ if __name__ == "__main__": # TODO merge with opts cost adjustment below for o in opts: - if o[:4] == "wave": - wave_cost_factor = float(o[4:].replace("p", ".").replace("m", "-")) - logger.info( - f"Including wave generators with cost factor of {wave_cost_factor}" - ) - add_wave(n, wave_cost_factor) if o[:4] == "dist": options["electricity_distribution_grid"] = True options["electricity_distribution_grid_cost_factor"] = float( From cd8001116dcd2bb553c5f981a59b33a36b2769e3 Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Thu, 11 Jan 2024 14:11:25 +0100 Subject: [PATCH 116/591] Add warning when negative bev availability profile values --- doc/release_notes.rst | 3 ++- scripts/build_transport_demand.py | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index be6be9fd..a6a1b485 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -12,7 +12,8 @@ Upcoming Release * New configuration option ``everywhere_powerplants`` to build conventional powerplants everywhere, irrespective of existing powerplants locations, in the network (https://github.com/PyPSA/pypsa-eur/pull/850). -* Remove option for wave energy as technology data is not maintained. +* Remove option for wave energy as technology data is not maintained. +* Add warning when BEV availability weekly profile has negative values in `build_transport_demand`. PyPSA-Eur 0.9.0 (5th January 2024) diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index 0bcfb7ed..be8ad414 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -8,11 +8,17 @@ improvements due to drivetrain changes, time series for electric vehicle availability and demand-side management constraints. """ +import logging + import numpy as np import pandas as pd import xarray as xr + +from _helpers import configure_logging from _helpers import generate_periodic_profiles +logger = logging.getLogger(__name__) + def build_nodal_transport_data(fn, pop_layout): transport_data = pd.read_csv(fn, index_col=0) @@ -130,6 +136,10 @@ def bev_availability_profile(fn, snapshots, nodes, options): traffic.mean() - traffic.min() ) + if not avail[avail < 0].empty: + logger.warning("The BEV availability weekly profile has negative values which can " + "lead to infeasibility.") + return generate_periodic_profiles( dt_index=snapshots, nodes=nodes, @@ -160,6 +170,7 @@ if __name__ == "__main__": simpl="", clusters=48, ) + configure_logging(snakemake) pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) From a4802b701843062436d0f36562f562fb1c60bf24 Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Thu, 11 Jan 2024 17:23:25 +0100 Subject: [PATCH 117/591] initial implementation tech specific renewable profiles --- config/config.default.yaml | 17 ++++-- rules/build_electricity.smk | 1 + rules/solve_myopic.smk | 6 +++ scripts/add_brownfield.py | 80 +++++++++++++++++++++++++++++ scripts/build_renewable_profiles.py | 42 ++++++++++++++- 5 files changed, 141 insertions(+), 5 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 33078468..aed7c61b 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -153,11 +153,14 @@ atlite: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#renewable renewable: + year: 2020 onwind: cutout: europe-2013-era5 resource: method: wind - turbine: Vestas_V112_3MW + turbine: + 2020: Vestas_V112_3MW + 2030: NREL_ReferenceTurbine_2020ATB_5.5MW add_cutout_windspeed: true capacity_per_sqkm: 3 # correction_factor: 0.93 @@ -176,7 +179,9 @@ renewable: cutout: europe-2013-era5 resource: method: wind - turbine: NREL_ReferenceTurbine_2020ATB_5.5MW + turbine: + 2020: NREL_ReferenceTurbine_5MW_offshore.yaml + 2030: NREL_ReferenceTurbine_2020ATB_15MW_offshore add_cutout_windspeed: true capacity_per_sqkm: 2 correction_factor: 0.8855 @@ -192,7 +197,10 @@ renewable: cutout: europe-2013-era5 resource: method: wind - turbine: NREL_ReferenceTurbine_2020ATB_5.5MW + turbine: + 2020: Vestas_V164_7MW_offshore + 2025: NREL_ReferenceTurbine_2020ATB_15MW_offshore + 2030: NREL_ReferenceTurbine_2020ATB_18MW_offshore add_cutout_windspeed: true capacity_per_sqkm: 2 correction_factor: 0.8855 @@ -208,7 +216,8 @@ renewable: cutout: europe-2013-sarah resource: method: pv - panel: CSi + panel: + 2020: CSi orientation: slope: 35. azimuth: 180. diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 055cffca..95103c47 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -259,6 +259,7 @@ else: rule build_renewable_profiles: params: renewable=config["renewable"], + foresight=config["foresight"], input: **opt, base_network=RESOURCES + "networks/base.nc", diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 7ca8857d..a1bad5b1 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -51,6 +51,12 @@ rule add_brownfield: H2_retrofit_capacity_per_CH4=config["sector"]["H2_retrofit_capacity_per_CH4"], threshold_capacity=config["existing_capacities"]["threshold_capacity"], input: + **{ + f"profile_{tech}": RESOURCES + f"profile_{tech}.nc" + for tech in config["electricity"]["renewable_carriers"] + }, + simplify_busmap=RESOURCES + "busmap_elec_s{simpl}.csv", + cluster_busmap=RESOURCES + "busmap_elec_s{simpl}_{clusters}.csv", network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", network_p=solved_previous_horizon, #solved network at previous time step diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 9ddd3d99..4ce2bd4d 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -16,8 +16,10 @@ idx = pd.IndexSlice import numpy as np import pypsa +import xarray as xr from _helpers import update_config_with_sector_opts from add_existing_baseyear import add_build_year_to_new_assets +from pypsa.clustering.spatial import normed_or_uniform def add_brownfield(n, n_p, year): @@ -147,6 +149,82 @@ def disable_grid_expansion_if_LV_limit_hit(n): n.global_constraints.drop("lv_limit", inplace=True) +def adjust_renewable_profiles(n, input_profiles, config, year): + """ + Adjusts renewable profiles according to the renewable technology specified. + + If the planning horizon is not available, the closest year is used + instead. + """ + + cluster_busmap = pd.read_csv(snakemake.input.cluster_busmap, index_col=0).squeeze() + simplify_busmap = pd.read_csv( + snakemake.input.simplify_busmap, index_col=0 + ).squeeze() + clustermaps = simplify_busmap.map(cluster_busmap) + clustermaps.index = clustermaps.index.astype(str) + dr = pd.date_range(**config["snapshots"], freq="H") + snapshotmaps = ( + pd.Series(dr, index=dr).where(lambda x: x.isin(n.snapshots), pd.NA).ffill() + ) + + for carrier in config["electricity"]["renewable_carriers"]: + if carrier == "hydro": + continue + + clustermaps.index = clustermaps.index.astype(str) + dr = pd.date_range(**config["snapshots"], freq="H") + snapshotmaps = ( + pd.Series(dr, index=dr).where(lambda x: x.isin(n.snapshots), pd.NA).ffill() + ) + for carrier in config["electricity"]["renewable_carriers"]: + if carrier == "hydro": + continue + with xr.open_dataset(getattr(input_profiles, "profile_" + carrier)) as ds: + if ds.indexes["bus"].empty or "year" not in ds.indexes: + continue + if year in ds.indexes["year"]: + p_max_pu = ( + ds["year_profiles"] + .sel(year=year) + .transpose("time", "bus") + .to_pandas() + ) + else: + available_previous_years = [ + available_year + for available_year in ds.indexes["year"] + if available_year < year + ] + available_following_years = [ + available_year + for available_year in ds.indexes["year"] + if available_year > year + ] + if available_previous_years: + closest_year = max(available_previous_years) + if available_following_years: + closest_year = min(available_following_years) + logging.warning( + f"Planning horizon {year} not in {carrier} profiles. Using closest year {closest_year} instead." + ) + p_max_pu = ( + ds["year_profiles"] + .sel(year=closest_year) + .transpose("time", "bus") + .to_pandas() + ) + # spatial clustering + weight = ds["weight"].to_pandas() + weight = weight.groupby(clustermaps).transform(normed_or_uniform) + p_max_pu = (p_max_pu * weight).T.groupby(clustermaps).sum().T + p_max_pu.columns = p_max_pu.columns + f" {carrier}" + # temporal_clustering + p_max_pu = p_max_pu.groupby(snapshotmaps).mean() + # replace renewable time series + n.generators_t.p_max_pu.loc[:, p_max_pu.columns] = p_max_pu + + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -171,6 +249,8 @@ if __name__ == "__main__": n = pypsa.Network(snakemake.input.network) + adjust_renewable_profiles(n, snakemake.input, snakemake.config, year) + add_build_year_to_new_assets(n, year) n_p = pypsa.Network(snakemake.input.network_p) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index b736f68a..4b326da6 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -200,14 +200,25 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_renewable_profiles", technology="solar") + snakemake = mock_snakemake("build_renewable_profiles", technology="onwind") configure_logging(snakemake) nprocesses = int(snakemake.threads) noprogress = snakemake.config["run"].get("disable_progressbar", True) noprogress = noprogress or not snakemake.config["atlite"]["show_progress"] + year = snakemake.params.renewable["year"] + foresight = snakemake.params.foresight params = snakemake.params.renewable[snakemake.wildcards.technology] resource = params["resource"] # pv panel params / wind turbine params + + year_dependent_techs = { + k: resource.get(k) + for k in ["panel", "turbine"] + if isinstance(resource.get(k), dict) + } + for key, techs in year_dependent_techs.items(): + resource[key] = resource[key][year] + correction_factor = params.get("correction_factor", 1.0) capacity_per_sqkm = params["capacity_per_sqkm"] @@ -334,6 +345,29 @@ if __name__ == "__main__": **resource, ) + if year_dependent_techs and foresight != "overnight": + for key, techs in year_dependent_techs.items(): + year_profiles = list() + tech_profiles = dict() + tech_profiles[resource[key]] = profile + for year, tech in techs.items(): + resource[key] = tech + if tech not in tech_profiles: + tech_profiles[tech] = func( + matrix=availability.stack(spatial=["y", "x"]), + layout=layout, + index=buses, + per_unit=True, + return_capacity=False, + **resource, + ) + year_profile = tech_profiles[tech] + year_profile = year_profile.expand_dims({"year": [year]}).rename( + "year_profiles" + ) + year_profiles.append(year_profile) + year_profiles = xr.merge(year_profiles) + duration = time.time() - start logger.info( f"Completed weighted capacity factor time series calculation ({duration:2.2f}s)" @@ -372,6 +406,9 @@ if __name__ == "__main__": ] ) + if year_dependent_techs: + ds = xr.merge([ds, year_profiles * correction_factor]) + if snakemake.wildcards.technology.startswith("offwind"): logger.info("Calculate underwater fraction of connections.") offshore_shape = gpd.read_file(snakemake.input["offshore_shapes"]).unary_union @@ -395,6 +432,9 @@ if __name__ == "__main__": if "clip_p_max_pu" in params: min_p_max_pu = params["clip_p_max_pu"] ds["profile"] = ds["profile"].where(ds["profile"] >= min_p_max_pu, 0) + ds["year_profiles"] = ds["year_profiles"].where( + ds["year_profiles"] >= min_p_max_pu, 0 + ) ds.to_netcdf(snakemake.output.profile) From 5ef317ac399ac86efcd6b6c907f1a8c8426c757e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 16:27:29 +0000 Subject: [PATCH 118/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/release_notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index be6be9fd..52b2ddc2 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -12,7 +12,7 @@ Upcoming Release * New configuration option ``everywhere_powerplants`` to build conventional powerplants everywhere, irrespective of existing powerplants locations, in the network (https://github.com/PyPSA/pypsa-eur/pull/850). -* Remove option for wave energy as technology data is not maintained. +* Remove option for wave energy as technology data is not maintained. PyPSA-Eur 0.9.0 (5th January 2024) From 8565c124c034f90436c5b37c21424d456d7e5e00 Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Fri, 12 Jan 2024 16:50:17 +0100 Subject: [PATCH 119/591] fix bus filter for buses without countries --- scripts/base_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index eeb87bf5..340b6f36 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -560,7 +560,7 @@ def _set_countries_and_substations(n, config, country_shapes, offshore_shapes): ~buses["under_construction"] ) - c_nan_b = buses.country == "na" + c_nan_b = buses.country.isna() if c_nan_b.sum() > 0: c_tag = _get_country(buses.loc[c_nan_b]) c_tag.loc[~c_tag.isin(countries)] = np.nan From 7ebf3b186c5c5d9840208b755e955813e5d8f60f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 15:56:15 +0000 Subject: [PATCH 120/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/release_notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index be6be9fd..52b2ddc2 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -12,7 +12,7 @@ Upcoming Release * New configuration option ``everywhere_powerplants`` to build conventional powerplants everywhere, irrespective of existing powerplants locations, in the network (https://github.com/PyPSA/pypsa-eur/pull/850). -* Remove option for wave energy as technology data is not maintained. +* Remove option for wave energy as technology data is not maintained. PyPSA-Eur 0.9.0 (5th January 2024) From 1613299a031bb87bae68375c9e7b954a1e9f6291 Mon Sep 17 00:00:00 2001 From: lisazeyen Date: Fri, 22 Dec 2023 14:18:33 +0100 Subject: [PATCH 121/591] add more years to config.perfect.yaml --- config/config.perfect.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config/config.perfect.yaml b/config/config.perfect.yaml index f355763c..4dde8db9 100644 --- a/config/config.perfect.yaml +++ b/config/config.perfect.yaml @@ -24,8 +24,11 @@ scenario: - 2p0-4380H-T-H-B-I-A-solar+p3-dist1 planning_horizons: - 2020 + - 2025 - 2030 + - 2035 - 2040 + - 2045 - 2050 From f042c7792660b5fc7cc256fd815a11b1b1be30b0 Mon Sep 17 00:00:00 2001 From: lisazeyen Date: Fri, 12 Jan 2024 21:33:14 +0100 Subject: [PATCH 122/591] add new constraint on co2 atmoshpere store --- scripts/solve_network.py | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 1c0f6505..db842054 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -208,7 +208,7 @@ def add_co2_sequestration_limit(n, config, limit=200): def add_carbon_constraint(n, snapshots): - glcs = n.global_constraints.query('type == "co2_limit"') + glcs = n.global_constraints.query('type == "co2_atmosphere"') if glcs.empty: return for name, glc in glcs.iterrows(): @@ -795,6 +795,28 @@ def add_pipe_retrofit_constraint(n): n.model.add_constraints(lhs == rhs, name="Link-pipe_retrofit") +def add_co2_atmosphere_constraint(n, snapshots): + glcs = n.global_constraints[n.global_constraints.type=="co2_atmosphere"] + + if glcs.empty: + return + for name, glc in glcs.iterrows(): + carattr = glc.carrier_attribute + emissions = n.carriers.query(f"{carattr} != 0")[carattr] + + if emissions.empty: + continue + + # stores + n.stores["carrier"] = n.stores.bus.map(n.buses.carrier) + stores = n.stores.query("carrier in @emissions.index and not e_cyclic") + if not stores.empty: + last_i = snapshots[-1] + lhs = n.model["Store-e"].loc[last_i, stores.index] + rhs = glc.constant + + n.model.add_constraints(lhs <= rhs, name=f"GlobalConstraint-{name}") + def extra_functionality(n, snapshots): """ Collects supplementary constraints which will be passed to @@ -837,6 +859,8 @@ def extra_functionality(n, snapshots): add_carbon_constraint(n, snapshots) add_carbon_budget_constraint(n, snapshots) add_retrofit_gas_boiler_constraint(n, snapshots) + else: + add_co2_atmosphere_constraint(n, snapshots) if snakemake.params.custom_extra_functionality: source_path = snakemake.params.custom_extra_functionality @@ -910,13 +934,13 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "solve_sector_network_perfect", + "solve_sector_network", configfiles="../config/test/config.perfect.yaml", simpl="", opts="", - clusters="5", - ll="v1.5", - sector_opts="8760H-T-H-B-I-A-solar+p3-dist1", + clusters="37", + ll="v1.0", + sector_opts="CO2L0-1H-T-H-B-I-A-solar+p3-dist1", planning_horizons="2030", ) configure_logging(snakemake) From 0a789a22dc58876dfd11e873024ef1eeec593653 Mon Sep 17 00:00:00 2001 From: lisazeyen Date: Fri, 12 Jan 2024 21:33:38 +0100 Subject: [PATCH 123/591] change type of co2 constraint --- scripts/prepare_sector_network.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index b57b832c..35d98657 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -761,6 +761,7 @@ def add_co2limit(n, nyears=1.0, limit=0.0): "CO2Limit", carrier_attribute="co2_emissions", sense="<=", + type="co2_atmosphere", constant=co2_limit, ) @@ -3606,8 +3607,8 @@ if __name__ == "__main__": configfiles="test/config.overnight.yaml", simpl="", opts="", - clusters="5", - ll="v1.5", + clusters="37", + ll="v1.0", sector_opts="CO2L0-24H-T-H-B-I-A-solar+p3-dist1", planning_horizons="2030", ) From 0bac08934aa701e89887afe8085edf715deda22a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 20:34:54 +0000 Subject: [PATCH 124/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/release_notes.rst | 2 +- scripts/solve_network.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index be6be9fd..52b2ddc2 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -12,7 +12,7 @@ Upcoming Release * New configuration option ``everywhere_powerplants`` to build conventional powerplants everywhere, irrespective of existing powerplants locations, in the network (https://github.com/PyPSA/pypsa-eur/pull/850). -* Remove option for wave energy as technology data is not maintained. +* Remove option for wave energy as technology data is not maintained. PyPSA-Eur 0.9.0 (5th January 2024) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index db842054..0b503644 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -796,8 +796,8 @@ def add_pipe_retrofit_constraint(n): def add_co2_atmosphere_constraint(n, snapshots): - glcs = n.global_constraints[n.global_constraints.type=="co2_atmosphere"] - + glcs = n.global_constraints[n.global_constraints.type == "co2_atmosphere"] + if glcs.empty: return for name, glc in glcs.iterrows(): @@ -812,11 +812,12 @@ def add_co2_atmosphere_constraint(n, snapshots): stores = n.stores.query("carrier in @emissions.index and not e_cyclic") if not stores.empty: last_i = snapshots[-1] - lhs = n.model["Store-e"].loc[last_i, stores.index] + lhs = n.model["Store-e"].loc[last_i, stores.index] rhs = glc.constant - + n.model.add_constraints(lhs <= rhs, name=f"GlobalConstraint-{name}") + def extra_functionality(n, snapshots): """ Collects supplementary constraints which will be passed to From 97d51a63fe963bd22394aca6bb6e1f774e53a44f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:14:11 +0000 Subject: [PATCH 125/591] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/snakemake/snakefmt: v0.8.5 → v0.9.0](https://github.com/snakemake/snakefmt/compare/v0.8.5...v0.9.0) --- .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 78e70b57..02d360d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -74,7 +74,7 @@ repos: # Format Snakemake rule / workflow files - repo: https://github.com/snakemake/snakefmt - rev: v0.8.5 + rev: v0.9.0 hooks: - id: snakefmt From 68421e6aabbe676982b448ab2759b8f1f7691d31 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:14:31 +0000 Subject: [PATCH 126/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/release_notes.rst | 2 +- rules/retrieve.smk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index be6be9fd..52b2ddc2 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -12,7 +12,7 @@ Upcoming Release * New configuration option ``everywhere_powerplants`` to build conventional powerplants everywhere, irrespective of existing powerplants locations, in the network (https://github.com/PyPSA/pypsa-eur/pull/850). -* Remove option for wave energy as technology data is not maintained. +* Remove option for wave energy as technology data is not maintained. PyPSA-Eur 0.9.0 (5th January 2024) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 7a180e22..5e1e3e59 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 e51e405d6e7886220556b97ed6d444f2b41624dd Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Tue, 16 Jan 2024 11:51:55 +0100 Subject: [PATCH 127/591] add clipping for links --- scripts/solve_network.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 1c0f6505..9fbd1eaf 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -341,6 +341,8 @@ def prepare_network( for df in ( n.generators_t.p_max_pu, n.generators_t.p_min_pu, + n.links_t.p_max_pu, + n.links_t.p_min_pu, n.storage_units_t.inflow, ): df.where(df > solve_opts["clip_p_max_pu"], other=0.0, inplace=True) From 3f8a55992c76769a29362b29a5989c2a62293579 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Tue, 16 Jan 2024 16:50:54 +0100 Subject: [PATCH 128/591] locate project dir if pypsa-eur is a submodule --- scripts/_helpers.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 03bde840..70eb4df2 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -223,7 +223,12 @@ def progress_retrieve(url, file, disable=False): urllib.request.urlretrieve(url, file, reporthook=update_to) -def mock_snakemake(rulename, root_dir=None, configfiles=[], **wildcards): +def mock_snakemake( + rulename, + root_dir=None, + configfiles=[], + submodule_dir="workflow/submodules/pypsa-eur", + **wildcards): """ This function is expected to be executed from the 'scripts'-directory of ' the snakemake project. It returns a snakemake.script.Snakemake object, @@ -239,6 +244,9 @@ def mock_snakemake(rulename, root_dir=None, configfiles=[], **wildcards): path to the root directory of the snakemake project configfiles: list, str list of configfiles to be used to update the config + submodule_dir: str, Path + in case PyPSA-Eur is used as a submodule, submodule_dir is + the path of pypsa-eur relative to the project directory. **wildcards: keyword arguments fixing the wildcards. Only necessary if wildcards are needed. @@ -257,7 +265,10 @@ def mock_snakemake(rulename, root_dir=None, configfiles=[], **wildcards): root_dir = Path(root_dir).resolve() user_in_script_dir = Path.cwd().resolve() == script_dir - if user_in_script_dir: + if str(submodule_dir) in __file__: + # the submodule_dir path is only need to locate the project dir + os.chdir(Path(__file__[:__file__.find(str(submodule_dir))])) + elif user_in_script_dir: os.chdir(root_dir) elif Path.cwd().resolve() != root_dir: raise RuntimeError( From 21a223262f145476065e2dd9dd30943bfd24594e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 16 Jan 2024 15:53:15 +0000 Subject: [PATCH 129/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/_helpers.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 70eb4df2..e0982fd4 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -224,11 +224,12 @@ def progress_retrieve(url, file, disable=False): def mock_snakemake( - rulename, - root_dir=None, - configfiles=[], - submodule_dir="workflow/submodules/pypsa-eur", - **wildcards): + rulename, + root_dir=None, + configfiles=[], + submodule_dir="workflow/submodules/pypsa-eur", + **wildcards, +): """ This function is expected to be executed from the 'scripts'-directory of ' the snakemake project. It returns a snakemake.script.Snakemake object, @@ -245,7 +246,7 @@ def mock_snakemake( configfiles: list, str list of configfiles to be used to update the config submodule_dir: str, Path - in case PyPSA-Eur is used as a submodule, submodule_dir is + in case PyPSA-Eur is used as a submodule, submodule_dir is the path of pypsa-eur relative to the project directory. **wildcards: keyword arguments fixing the wildcards. Only necessary if wildcards are @@ -267,7 +268,7 @@ def mock_snakemake( user_in_script_dir = Path.cwd().resolve() == script_dir if str(submodule_dir) in __file__: # the submodule_dir path is only need to locate the project dir - os.chdir(Path(__file__[:__file__.find(str(submodule_dir))])) + os.chdir(Path(__file__[: __file__.find(str(submodule_dir))])) elif user_in_script_dir: os.chdir(root_dir) elif Path.cwd().resolve() != root_dir: From 55eddb6e1d0588ea8e6c2d335d0af52d44471d14 Mon Sep 17 00:00:00 2001 From: martacki Date: Tue, 16 Jan 2024 20:13:28 +0100 Subject: [PATCH 130/591] Norway currently ignored when building energy totals --- scripts/build_energy_totals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 67b86466..80c5d442 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -479,7 +479,7 @@ def build_energy_totals(countries, eurostat, swiss, idees): # The main heating source for about 73 per cent of the households is based on electricity # => 26% is non-electric - if "NO" in df: + if "NO" in df.index: elec_fraction = 0.73 no_norway = df.drop("NO") From a74c7b69c80d1c0b15c1203872e9799dbd69de6f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 17 Jan 2024 10:02:51 +0100 Subject: [PATCH 131/591] add release note --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 52b2ddc2..ee8858a4 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -14,6 +14,8 @@ Upcoming Release * Remove option for wave energy as technology data is not maintained. +* Bugfix: Assure entering of code block which corrects Norwegian heat demand. + PyPSA-Eur 0.9.0 (5th January 2024) ================================== From ec4e9aa548fce44109d851bf6f33070395d10787 Mon Sep 17 00:00:00 2001 From: JulianGeis Date: Wed, 17 Jan 2024 11:23:29 +0100 Subject: [PATCH 132/591] wasserstoff kernnetz --- scripts/prepare_sector_network.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index b57b832c..ba3f24c6 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1324,6 +1324,18 @@ def add_storage_and_grids(n, costs): n, "H2 pipeline ", carriers=["DC", "gas pipeline"] ) + h2_pipes["p_nom"] = 0. + + if snakemake.input.get("custom_h2_pipelines"): + fn = snakemake.input.custom_h2_pipelines + wkn = pd.read_csv(fn, index_col=0) + + h2_pipes = pd.concat([h2_pipes, wkn]) + + # drop duplicates according to buses (order can be different) and keep pipe with highest p_nom + h2_pipes['buses_sorted'] = h2_pipes.apply(lambda row: tuple(sorted([row['bus0'], row['bus1']])), axis=1) + h2_pipes = h2_pipes.sort_values('p_nom').drop_duplicates(subset=['buses_sorted'], keep='last').drop(columns = 'buses_sorted') + # TODO Add efficiency losses n.madd( "Link", @@ -1332,6 +1344,7 @@ def add_storage_and_grids(n, costs): bus1=h2_pipes.bus1.values + " H2", p_min_pu=-1, p_nom_extendable=True, + p_nom_min=h2_pipes.p_nom.values, length=h2_pipes.length.values, capital_cost=costs.at["H2 (g) pipeline", "fixed"] * h2_pipes.length.values, carrier="H2 pipeline", From 446b0b37227111e49fa3e4e566b68b031f558e28 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 10:36:13 +0000 Subject: [PATCH 133/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/build_transport_demand.py | 10 +++++----- scripts/prepare_sector_network.py | 12 +++++++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index be8ad414..33c8faae 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -13,9 +13,7 @@ import logging import numpy as np import pandas as pd import xarray as xr - -from _helpers import configure_logging -from _helpers import generate_periodic_profiles +from _helpers import configure_logging, generate_periodic_profiles logger = logging.getLogger(__name__) @@ -137,8 +135,10 @@ def bev_availability_profile(fn, snapshots, nodes, options): ) if not avail[avail < 0].empty: - logger.warning("The BEV availability weekly profile has negative values which can " - "lead to infeasibility.") + logger.warning( + "The BEV availability weekly profile has negative values which can " + "lead to infeasibility." + ) return generate_periodic_profiles( dt_index=snapshots, diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index ba3f24c6..8bb9089b 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1324,7 +1324,7 @@ def add_storage_and_grids(n, costs): n, "H2 pipeline ", carriers=["DC", "gas pipeline"] ) - h2_pipes["p_nom"] = 0. + h2_pipes["p_nom"] = 0.0 if snakemake.input.get("custom_h2_pipelines"): fn = snakemake.input.custom_h2_pipelines @@ -1333,8 +1333,14 @@ def add_storage_and_grids(n, costs): h2_pipes = pd.concat([h2_pipes, wkn]) # drop duplicates according to buses (order can be different) and keep pipe with highest p_nom - h2_pipes['buses_sorted'] = h2_pipes.apply(lambda row: tuple(sorted([row['bus0'], row['bus1']])), axis=1) - h2_pipes = h2_pipes.sort_values('p_nom').drop_duplicates(subset=['buses_sorted'], keep='last').drop(columns = 'buses_sorted') + h2_pipes["buses_sorted"] = h2_pipes.apply( + lambda row: tuple(sorted([row["bus0"], row["bus1"]])), axis=1 + ) + h2_pipes = ( + h2_pipes.sort_values("p_nom") + .drop_duplicates(subset=["buses_sorted"], keep="last") + .drop(columns="buses_sorted") + ) # TODO Add efficiency losses n.madd( From 228ff44f75de10d4174409776cca7328185815ab Mon Sep 17 00:00:00 2001 From: Thomas Kouroughli Date: Wed, 17 Jan 2024 13:50:32 +0000 Subject: [PATCH 134/591] :recycle: address pandas FutureWarning --- scripts/build_electricity_production.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_electricity_production.py b/scripts/build_electricity_production.py index beb859bd..e89ad78b 100644 --- a/scripts/build_electricity_production.py +++ b/scripts/build_electricity_production.py @@ -58,7 +58,7 @@ if __name__ == "__main__": gen = client.query_generation(country, start=start, end=end, nett=True) gen = gen.tz_localize(None).resample("1h").mean() gen = gen.loc[start.tz_localize(None) : end.tz_localize(None)] - gen = gen.rename(columns=carrier_grouper).groupby(level=0, axis=1).sum() + gen = gen.rename(columns=carrier_grouper).T.groupby(level=0).sum().T generation.append(gen) except NoMatchingDataError: unavailable_countries.append(country) From aaa587d34f84dc22f7662d7f5855ae1e1f2161fa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 13:51:03 +0000 Subject: [PATCH 135/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/build_transport_demand.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index be8ad414..33c8faae 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -13,9 +13,7 @@ import logging import numpy as np import pandas as pd import xarray as xr - -from _helpers import configure_logging -from _helpers import generate_periodic_profiles +from _helpers import configure_logging, generate_periodic_profiles logger = logging.getLogger(__name__) @@ -137,8 +135,10 @@ def bev_availability_profile(fn, snapshots, nodes, options): ) if not avail[avail < 0].empty: - logger.warning("The BEV availability weekly profile has negative values which can " - "lead to infeasibility.") + logger.warning( + "The BEV availability weekly profile has negative values which can " + "lead to infeasibility." + ) return generate_periodic_profiles( dt_index=snapshots, From 4cfb06c55f96c619a5ff18df1f435d75eb147e28 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Wed, 17 Jan 2024 17:07:19 +0100 Subject: [PATCH 136/591] group storage with duplicate labels --- scripts/plot_network.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/plot_network.py b/scripts/plot_network.py index 67481120..650a24ef 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -273,7 +273,7 @@ def plot_h2_map(network, regions): h2_storage = n.stores.query("carrier == 'H2'") regions["H2"] = h2_storage.rename( index=h2_storage.bus.map(n.buses.location) - ).e_nom_opt.div( + ).e_nom_opt.groupby(level=0).sum().div( 1e6 ) # TWh regions["H2"] = regions["H2"].where(regions["H2"] > 0.1) @@ -1068,9 +1068,10 @@ if __name__ == "__main__": "plot_network", simpl="", opts="", - clusters="37", - ll="v1.0", - sector_opts="4380H-T-H-B-I-A-solar+p3-dist1", + clusters="22", + ll="v1.2", + sector_opts="365H-T-H-B-I-A-solar+p3-linemaxext15", + planning_horizons="2040", ) logging.basicConfig(level=snakemake.config["logging"]["level"]) From e07f0e5c2b5bb34e8fcfb3b127ac9e30109beedc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 16:09:36 +0000 Subject: [PATCH 137/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/plot_network.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/plot_network.py b/scripts/plot_network.py index 650a24ef..31e72289 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -271,10 +271,11 @@ def plot_h2_map(network, regions): assign_location(n) h2_storage = n.stores.query("carrier == 'H2'") - regions["H2"] = h2_storage.rename( - index=h2_storage.bus.map(n.buses.location) - ).e_nom_opt.groupby(level=0).sum().div( - 1e6 + regions["H2"] = ( + h2_storage.rename(index=h2_storage.bus.map(n.buses.location)) + .e_nom_opt.groupby(level=0) + .sum() + .div(1e6) ) # TWh regions["H2"] = regions["H2"].where(regions["H2"] > 0.1) From fec871c1ccce766b8c710c67f35f4d407278a443 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Wed, 17 Jan 2024 18:28:37 +0100 Subject: [PATCH 138/591] eliminate a few future warnings --- scripts/make_summary.py | 15 +++++++-------- scripts/plot_summary.py | 6 +++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index fb13e91e..9da915ef 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -522,8 +522,8 @@ def calculate_weighted_prices(n, label, weighted_prices): if not names.empty: load += ( n.links_t.p0[names] - .groupby(n.links.loc[names, "bus0"], axis=1) - .sum() + .T.groupby(n.links.loc[names, "bus0"]) + .sum().T ) # Add H2 Store when charging @@ -560,14 +560,13 @@ def calculate_market_values(n, label, market_values): for tech in techs: gens = generators[n.generators.loc[generators, "carrier"] == tech] - + dispatch = ( n.generators_t.p[gens] - .groupby(n.generators.loc[gens, "bus"], axis=1) - .sum() + .T.groupby(n.generators.loc[gens, "bus"]) + .sum().T .reindex(columns=buses, fill_value=0.0) ) - revenue = dispatch * n.buses_t.marginal_price[buses] market_values.at[tech, label] = revenue.sum().sum() / dispatch.sum().sum() @@ -586,8 +585,8 @@ def calculate_market_values(n, label, market_values): dispatch = ( n.links_t["p" + i][links] - .groupby(n.links.loc[links, "bus" + i], axis=1) - .sum() + .T.groupby(n.links.loc[links, "bus" + i]) + .sum().T .reindex(columns=buses, fill_value=0.0) ) diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index 67ac9b55..e0067d7f 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -154,7 +154,7 @@ def plot_costs(): df = df.drop(to_drop) - logger.info(f"Total system cost of {round(df.sum()[0])} EUR billion per year") + logger.info(f"Total system cost of {round(df.sum().iloc[0])} EUR billion per year") new_index = preferred_order.intersection(df.index).append( df.index.difference(preferred_order) @@ -214,7 +214,7 @@ def plot_energy(): df = df.drop(to_drop) - logger.info(f"Total energy of {round(df.sum()[0])} TWh/a") + logger.info(f"Total energy of {round(df.sum().iloc[0])} TWh/a") if df.empty: fig, ax = plt.subplots(figsize=(12, 8)) @@ -304,7 +304,7 @@ def plot_balances(): df = df.drop(to_drop) - logger.debug(f"Total energy balance for {v} of {round(df.sum()[0],2)} {units}") + logger.debug(f"Total energy balance for {v} of {round(df.sum().iloc[0],2)} {units}") if df.empty: continue From 213c4b025e9b53a8ed56a4745e0410baa86dbb2f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 17:29:45 +0000 Subject: [PATCH 139/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/make_summary.py | 14 ++++++-------- scripts/plot_summary.py | 4 +++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 9da915ef..7223f4d5 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -521,9 +521,7 @@ def calculate_weighted_prices(n, label, weighted_prices): if not names.empty: load += ( - n.links_t.p0[names] - .T.groupby(n.links.loc[names, "bus0"]) - .sum().T + n.links_t.p0[names].T.groupby(n.links.loc[names, "bus0"]).sum().T ) # Add H2 Store when charging @@ -560,12 +558,12 @@ def calculate_market_values(n, label, market_values): for tech in techs: gens = generators[n.generators.loc[generators, "carrier"] == tech] - + dispatch = ( n.generators_t.p[gens] .T.groupby(n.generators.loc[gens, "bus"]) - .sum().T - .reindex(columns=buses, fill_value=0.0) + .sum() + .T.reindex(columns=buses, fill_value=0.0) ) revenue = dispatch * n.buses_t.marginal_price[buses] @@ -586,8 +584,8 @@ def calculate_market_values(n, label, market_values): dispatch = ( n.links_t["p" + i][links] .T.groupby(n.links.loc[links, "bus" + i]) - .sum().T - .reindex(columns=buses, fill_value=0.0) + .sum() + .T.reindex(columns=buses, fill_value=0.0) ) revenue = dispatch * n.buses_t.marginal_price[buses] diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index e0067d7f..2a6c9f15 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -304,7 +304,9 @@ def plot_balances(): df = df.drop(to_drop) - logger.debug(f"Total energy balance for {v} of {round(df.sum().iloc[0],2)} {units}") + logger.debug( + f"Total energy balance for {v} of {round(df.sum().iloc[0],2)} {units}" + ) if df.empty: continue From dd8db719accb6faf71fd194227211cedd1bb9950 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Thu, 18 Jan 2024 13:53:59 +0100 Subject: [PATCH 140/591] revert accidental changes --- scripts/plot_network.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/plot_network.py b/scripts/plot_network.py index 31e72289..63b5d848 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -1069,10 +1069,9 @@ if __name__ == "__main__": "plot_network", simpl="", opts="", - clusters="22", - ll="v1.2", - sector_opts="365H-T-H-B-I-A-solar+p3-linemaxext15", - planning_horizons="2040", + clusters="37", + ll="v1.0", + sector_opts="4380H-T-H-B-I-A-solar+p3-dist1", ) logging.basicConfig(level=snakemake.config["logging"]["level"]) From ecb0a1f79f97db73c49a225f9832c66b5cdab9cc Mon Sep 17 00:00:00 2001 From: euronion <42553970+euronion@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:12:17 +0100 Subject: [PATCH 141/591] Log unhandled exceptions stacktraces in log files --- doc/release_notes.rst | 2 ++ scripts/_helpers.py | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 44cea086..a48d1a4e 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -18,6 +18,8 @@ Upcoming Release * Add warning when BEV availability weekly profile has negative values in `build_transport_demand`. +* Stacktrace of uncaught exceptions should now be correctly included inside log files (via `configure_logging(..)`). + PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/scripts/_helpers.py b/scripts/_helpers.py index e0982fd4..beca3f4f 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -80,6 +80,7 @@ def configure_logging(snakemake, skip_handlers=False): Do (not) skip the default handlers created for redirecting output to STDERR and file. """ import logging + import sys kwargs = snakemake.config.get("logging", dict()).copy() kwargs.setdefault("level", "INFO") @@ -102,7 +103,15 @@ def configure_logging(snakemake, skip_handlers=False): } ) logging.basicConfig(**kwargs) + + # Setup a function to handle uncaught exceptions and include them with their stacktrace into logfiles + def handle_exception(exc_type, exc_value, exc_traceback): + # Log the exception + logger = logging.getLogger() + logger.error("Uncaught exception", + exc_info=(exc_type, exc_value, exc_traceback)) + sys.excepthook = handle_exception def update_p_nom_max(n): # if extendable carriers (solar/onwind/...) have capacity >= 0, From 35f1c06f75a4a4e540277bd760c96ec7b3bd4083 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 13:18:25 +0000 Subject: [PATCH 142/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/_helpers.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index beca3f4f..c5c96db9 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -103,16 +103,18 @@ def configure_logging(snakemake, skip_handlers=False): } ) logging.basicConfig(**kwargs) - + # Setup a function to handle uncaught exceptions and include them with their stacktrace into logfiles def handle_exception(exc_type, exc_value, exc_traceback): # Log the exception logger = logging.getLogger() - logger.error("Uncaught exception", - exc_info=(exc_type, exc_value, exc_traceback)) + logger.error( + "Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback) + ) sys.excepthook = handle_exception + def update_p_nom_max(n): # if extendable carriers (solar/onwind/...) have capacity >= 0, # e.g. existing assets from the OPSD project are included to the network, From 682d3d857b3ff9908b77c3ef57b562fa339a39bc Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 18 Jan 2024 17:25:05 +0100 Subject: [PATCH 143/591] cluster heat buses by default --- config/config.default.yaml | 2 +- doc/release_notes.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 1d28223f..661f855e 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -376,7 +376,7 @@ sector: 2045: 0.8 2050: 1.0 district_heating_loss: 0.15 - cluster_heat_buses: false + cluster_heat_buses: true bev_dsm_restriction_value: 0.75 bev_dsm_restriction_time: 7 transport_heating_deadband_upper: 20. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 44cea086..7b0b8c33 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -18,6 +18,7 @@ Upcoming Release * Add warning when BEV availability weekly profile has negative values in `build_transport_demand`. +* Cluster residential and services heat buses by default. Can be disabled with ``cluster_heat_buses: false``. PyPSA-Eur 0.9.0 (5th January 2024) ================================== From 7c23ef08c5a1b42017dc625e0cc20d555aee9720 Mon Sep 17 00:00:00 2001 From: Thomas Kouroughli Date: Thu, 18 Jan 2024 17:04:22 +0000 Subject: [PATCH 144/591] :bug: fix key_error in validation plots --- scripts/plot_validation_electricity_production.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/plot_validation_electricity_production.py b/scripts/plot_validation_electricity_production.py index 5c5569d0..e95a8126 100644 --- a/scripts/plot_validation_electricity_production.py +++ b/scripts/plot_validation_electricity_production.py @@ -45,6 +45,12 @@ if __name__ == "__main__": header=[0, 1], parse_dates=True, ) + subset_technologies = ["Geothermal", "Nuclear", "Biomass", "Lignite", "Oil", "Coal"] + lowercase_technologies = [ + technology.lower() if technology in subset_technologies else technology + for technology in historic.columns.levels[1] + ] + historic.columns = historic.columns.set_levels(lowercase_technologies, level=1) colors = n.carriers.set_index("nice_name").color.where( lambda s: s != "", "lightgrey" From 4d74be9588cac870c4341fc7e7f15cab5178df75 Mon Sep 17 00:00:00 2001 From: Thomas Kouroughli Date: Thu, 18 Jan 2024 17:12:39 +0000 Subject: [PATCH 145/591] :memo: add release notes for PR. --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 7b0b8c33..4cc89a7a 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,8 @@ Release Notes Upcoming Release ================ +* Bugfix: Correct technology keys for the electricity production plotting to work out the box. + * New configuration option ``everywhere_powerplants`` to build conventional powerplants everywhere, irrespective of existing powerplants locations, in the network (https://github.com/PyPSA/pypsa-eur/pull/850). * Remove option for wave energy as technology data is not maintained. From 498f3bffadba8d62139fbc8a3ec75a4aba41e12a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 18 Jan 2024 18:22:21 +0100 Subject: [PATCH 146/591] Update scripts/base_network.py Co-authored-by: Fabian Hofmann --- scripts/base_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index 340b6f36..2fa31f98 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -560,7 +560,7 @@ def _set_countries_and_substations(n, config, country_shapes, offshore_shapes): ~buses["under_construction"] ) - c_nan_b = buses.country.isna() + c_nan_b = buses.country.fillna("na") == "na" if c_nan_b.sum() > 0: c_tag = _get_country(buses.loc[c_nan_b]) c_tag.loc[~c_tag.isin(countries)] = np.nan From 333e99ed3bdc3e1a56fa0309b752d42b9cc0c010 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 18 Jan 2024 19:33:57 +0100 Subject: [PATCH 147/591] add release note --- doc/release_notes.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 52b2ddc2..914791a1 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -14,6 +14,9 @@ Upcoming Release * Remove option for wave energy as technology data is not maintained. +* Define global constraint for CO2 emissions on the final state of charge of the + CO2 atmosphere store. This gives a more sparse constraint that should improve + the performance of the solving process. PyPSA-Eur 0.9.0 (5th January 2024) ================================== From 88ba4af9ad4ee9d874416c3c4ddd69aa62730a27 Mon Sep 17 00:00:00 2001 From: Julian Geis Date: Fri, 19 Jan 2024 09:56:52 +0100 Subject: [PATCH 148/591] Update scripts/prepare_sector_network.py Co-authored-by: Fabian Neumann --- 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 8bb9089b..8648a4ce 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1326,7 +1326,7 @@ def add_storage_and_grids(n, costs): h2_pipes["p_nom"] = 0.0 - if snakemake.input.get("custom_h2_pipelines"): + if "custom_h2_pipelines" in snakemake.input: fn = snakemake.input.custom_h2_pipelines wkn = pd.read_csv(fn, index_col=0) From 9c56c1e929d8bd27c8d6ac10d45dbc4d7716f4f4 Mon Sep 17 00:00:00 2001 From: Julian Geis Date: Fri, 19 Jan 2024 09:57:26 +0100 Subject: [PATCH 149/591] Update scripts/prepare_sector_network.py Co-authored-by: Fabian Neumann --- scripts/prepare_sector_network.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 8648a4ce..292814b2 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1328,9 +1328,9 @@ def add_storage_and_grids(n, costs): if "custom_h2_pipelines" in snakemake.input: fn = snakemake.input.custom_h2_pipelines - wkn = pd.read_csv(fn, index_col=0) + custom_pipes = pd.read_csv(fn, index_col=0) - h2_pipes = pd.concat([h2_pipes, wkn]) + h2_pipes = pd.concat([h2_pipes, custom_pipes]) # drop duplicates according to buses (order can be different) and keep pipe with highest p_nom h2_pipes["buses_sorted"] = h2_pipes.apply( From 128e1afc0072ddb21d01ce58137e3823f81f7c4e Mon Sep 17 00:00:00 2001 From: Julian Geis Date: Fri, 19 Jan 2024 10:01:11 +0100 Subject: [PATCH 150/591] Update scripts/prepare_sector_network.py Co-authored-by: Fabian Neumann --- scripts/prepare_sector_network.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 292814b2..4c47b91a 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1333,9 +1333,7 @@ def add_storage_and_grids(n, costs): h2_pipes = pd.concat([h2_pipes, custom_pipes]) # drop duplicates according to buses (order can be different) and keep pipe with highest p_nom - h2_pipes["buses_sorted"] = h2_pipes.apply( - lambda row: tuple(sorted([row["bus0"], row["bus1"]])), axis=1 - ) + h2_pipes["buses_sorted"] = h2_pipes[["bus0", "bus1"]].apply(sorted, axis=1) h2_pipes = ( h2_pipes.sort_values("p_nom") .drop_duplicates(subset=["buses_sorted"], keep="last") From f876d78ed4cfbc2d14d424066b25a598abc8deb3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 19 Jan 2024 10:34:49 +0100 Subject: [PATCH 151/591] fix linting: run ruff --- scripts/_helpers.py | 2 -- scripts/add_brownfield.py | 4 ++-- scripts/build_electricity_demand.py | 1 - scripts/build_line_rating.py | 1 - scripts/build_renewable_profiles.py | 2 +- scripts/copy_config.py | 2 -- scripts/make_summary_perfect.py | 10 ++-------- scripts/plot_network.py | 1 - scripts/plot_summary.py | 1 - scripts/plot_validation_electricity_prices.py | 1 - scripts/prepare_network.py | 1 - scripts/simplify_network.py | 2 +- scripts/solve_network.py | 2 +- 13 files changed, 7 insertions(+), 23 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index c5c96db9..67b20877 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -15,8 +15,6 @@ import pandas as pd import pytz import requests import yaml -from pypsa.components import component_attrs, components -from pypsa.descriptors import Dict from tqdm import tqdm logger = logging.getLogger(__name__) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index cb1f51c8..229b8b07 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -121,7 +121,7 @@ def add_brownfield(n, n_p, year): def disable_grid_expansion_if_LV_limit_hit(n): - if not "lv_limit" in n.global_constraints.index: + if "lv_limit" not in n.global_constraints.index: return total_expansion = ( @@ -133,7 +133,7 @@ def disable_grid_expansion_if_LV_limit_hit(n): # allow small numerical differences if lv_limit - total_expansion < 1: - logger.info(f"LV is already reached, disabling expansion and LV limit") + logger.info("LV is already reached, disabling expansion and LV limit") extendable_acs = n.lines.query("s_nom_extendable").index n.lines.loc[extendable_acs, "s_nom_extendable"] = False n.lines.loc[extendable_acs, "s_nom"] = n.lines.loc[extendable_acs, "s_nom_min"] diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index d7d9927d..4706bf58 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -42,7 +42,6 @@ Outputs import logging logger = logging.getLogger(__name__) -import dateutil import numpy as np import pandas as pd from _helpers import configure_logging diff --git a/scripts/build_line_rating.py b/scripts/build_line_rating.py index 589f3656..4d45b910 100755 --- a/scripts/build_line_rating.py +++ b/scripts/build_line_rating.py @@ -50,7 +50,6 @@ With a heat balance considering the maximum temperature threshold of the transmi the maximal possible capacity factor "s_max_pu" for each transmission line at each time step is calculated. """ -import logging import re import atlite diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index f9db9271..6c450aca 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -340,7 +340,7 @@ if __name__ == "__main__": f"Completed weighted capacity factor time series calculation ({duration:2.2f}s)" ) - logger.info(f"Calculating maximal capacity per bus") + logger.info("Calculating maximal capacity per bus") p_nom_max = capacity_per_sqkm * availability @ area logger.info("Calculate average distances.") diff --git a/scripts/copy_config.py b/scripts/copy_config.py index a549d893..3dbee6a4 100644 --- a/scripts/copy_config.py +++ b/scripts/copy_config.py @@ -6,8 +6,6 @@ Copy used configuration files and important scripts for archiving. """ -from pathlib import Path -from shutil import copy import yaml diff --git a/scripts/make_summary_perfect.py b/scripts/make_summary_perfect.py index c387c6cf..93411a4c 100644 --- a/scripts/make_summary_perfect.py +++ b/scripts/make_summary_perfect.py @@ -12,15 +12,9 @@ other metrics. import numpy as np import pandas as pd import pypsa -from make_summary import ( - assign_carriers, - assign_locations, - calculate_cfs, - calculate_nodal_cfs, - calculate_nodal_costs, -) +from make_summary import assign_carriers, assign_locations from prepare_sector_network import prepare_costs -from pypsa.descriptors import get_active_assets, nominal_attrs +from pypsa.descriptors import get_active_assets from six import iteritems idx = pd.IndexSlice diff --git a/scripts/plot_network.py b/scripts/plot_network.py index 63b5d848..b34ba432 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -903,7 +903,6 @@ def plot_series(network, carrier="AC", name="test"): carrier, start, stop, - name, ), transparent=True, ) diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index 2a6c9f15..d29207af 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -12,7 +12,6 @@ logger = logging.getLogger(__name__) import matplotlib.gridspec as gridspec import matplotlib.pyplot as plt -import numpy as np import pandas as pd plt.style.use("ggplot") diff --git a/scripts/plot_validation_electricity_prices.py b/scripts/plot_validation_electricity_prices.py index 2a187b9f..38c9fe96 100644 --- a/scripts/plot_validation_electricity_prices.py +++ b/scripts/plot_validation_electricity_prices.py @@ -9,7 +9,6 @@ import pandas as pd import pypsa import seaborn as sns from _helpers import configure_logging -from pypsa.statistics import get_bus_and_carrier sns.set_theme("paper", style="whitegrid") diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 632e6078..75e5daba 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -58,7 +58,6 @@ Description """ import logging -import re import numpy as np import pandas as pd diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index f88d10d4..f8629ea7 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -86,7 +86,7 @@ The rule :mod:`simplify_network` does up to four things: """ import logging -from functools import partial, reduce +from functools import reduce import numpy as np import pandas as pd diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 55704d4d..c6c1b10c 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -690,7 +690,7 @@ def add_battery_constraints(n): def add_lossy_bidirectional_link_constraints(n): - if not n.links.p_nom_extendable.any() or not "reversed" in n.links.columns: + if not n.links.p_nom_extendable.any() or "reversed" not in n.links.columns: return n.links["reversed"] = n.links.reversed.fillna(0).astype(bool) From b1d21813af24c531025d55eee19e67b30ebe1200 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 19 Jan 2024 10:47:58 +0100 Subject: [PATCH 152/591] fix import order --- scripts/_benchmark.py | 6 +++--- scripts/add_brownfield.py | 10 ++++------ scripts/add_existing_baseyear.py | 11 +++-------- scripts/build_biomass_potentials.py | 2 +- scripts/build_electricity_demand.py | 3 ++- scripts/build_energy_totals.py | 5 +---- scripts/build_gas_input_locations.py | 4 ++-- scripts/build_gas_network.py | 4 ++-- scripts/build_industrial_distribution_key.py | 4 +--- scripts/build_industrial_production_per_country.py | 6 ++---- scripts/build_population_layouts.py | 5 ++--- scripts/cluster_gas_network.py | 4 ++-- scripts/make_summary.py | 5 +---- scripts/plot_network.py | 3 +-- scripts/plot_summary.py | 3 +-- scripts/prepare_sector_network.py | 10 +++------- scripts/retrieve_sector_databundle.py | 5 ++--- scripts/solve_network.py | 2 +- 18 files changed, 34 insertions(+), 58 deletions(-) diff --git a/scripts/_benchmark.py b/scripts/_benchmark.py index 4e3413e9..ced102ba 100644 --- a/scripts/_benchmark.py +++ b/scripts/_benchmark.py @@ -13,15 +13,15 @@ import os import sys import time +from memory_profiler import _get_memory, choose_backend + logger = logging.getLogger(__name__) # TODO: provide alternative when multiprocessing is not available try: from multiprocessing import Pipe, Process except ImportError: - from multiprocessing.dummy import Process, Pipe - -from memory_profiler import _get_memory, choose_backend + from multiprocessing.dummy import Pipe, Process # The memory logging facilities have been adapted from memory_profiler diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 229b8b07..ac58136a 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -8,17 +8,15 @@ Prepares brownfield data from previous planning horizon. import logging -logger = logging.getLogger(__name__) - -import pandas as pd - -idx = pd.IndexSlice - import numpy as np +import pandas as pd import pypsa from _helpers import update_config_with_sector_opts from add_existing_baseyear import add_build_year_to_new_assets +logger = logging.getLogger(__name__) +idx = pd.IndexSlice + def add_brownfield(n, n_p, year): logger.info(f"Preparing brownfield for the year {year}") diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index e7894324..c8486758 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -8,25 +8,20 @@ horizon. """ import logging - -logger = logging.getLogger(__name__) - -import pandas as pd - -idx = pd.IndexSlice - from types import SimpleNamespace import country_converter as coco import numpy as np +import pandas as pd import pypsa import xarray as xr from _helpers import update_config_with_sector_opts from add_electricity import sanitize_carriers from prepare_sector_network import cluster_heat_buses, define_spatial, prepare_costs +logger = logging.getLogger(__name__) cc = coco.CountryConverter() - +idx = pd.IndexSlice spatial = SimpleNamespace() diff --git a/scripts/build_biomass_potentials.py b/scripts/build_biomass_potentials.py index aae1fb98..b6cbbfbf 100644 --- a/scripts/build_biomass_potentials.py +++ b/scripts/build_biomass_potentials.py @@ -9,11 +9,11 @@ using data from JRC ENSPRESO. import logging -logger = logging.getLogger(__name__) import geopandas as gpd import numpy as np import pandas as pd +logger = logging.getLogger(__name__) AVAILABLE_BIOMASS_YEARS = [2010, 2020, 2030, 2040, 2050] diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 4706bf58..a08055ba 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -41,12 +41,13 @@ Outputs import logging -logger = logging.getLogger(__name__) import numpy as np import pandas as pd from _helpers import configure_logging from pandas import Timedelta as Delta +logger = logging.getLogger(__name__) + def load_timeseries(fn, years, countries, powerstatistics=True): """ diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 80c5d442..39b2a1be 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -7,9 +7,6 @@ Build total energy demands per country using JRC IDEES, eurostat, and EEA data. """ import logging - -logger = logging.getLogger(__name__) - import multiprocessing as mp from functools import partial @@ -21,7 +18,7 @@ from _helpers import mute_print from tqdm import tqdm cc = coco.CountryConverter() - +logger = logging.getLogger(__name__) idx = pd.IndexSlice diff --git a/scripts/build_gas_input_locations.py b/scripts/build_gas_input_locations.py index 9ad3760d..0c9e4c4b 100644 --- a/scripts/build_gas_input_locations.py +++ b/scripts/build_gas_input_locations.py @@ -9,12 +9,12 @@ production sites with data from SciGRID_gas and Global Energy Monitor. import logging -logger = logging.getLogger(__name__) - import geopandas as gpd import pandas as pd from cluster_gas_network import load_bus_regions +logger = logging.getLogger(__name__) + def read_scigrid_gas(fn): df = gpd.read_file(fn) diff --git a/scripts/build_gas_network.py b/scripts/build_gas_network.py index 92e686cd..8df7744d 100644 --- a/scripts/build_gas_network.py +++ b/scripts/build_gas_network.py @@ -9,13 +9,13 @@ Preprocess gas network based on data from bthe SciGRID_gas project import logging -logger = logging.getLogger(__name__) - import geopandas as gpd import pandas as pd from pypsa.geo import haversine_pts from shapely.geometry import Point +logger = logging.getLogger(__name__) + def diameter_to_capacity(pipe_diameter_mm): """ diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index e6d515b0..08de3bae 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -7,9 +7,6 @@ Build spatial distribution of industries from Hotmaps database. """ import logging - -logger = logging.getLogger(__name__) - import uuid from itertools import product @@ -18,6 +15,7 @@ import geopandas as gpd import pandas as pd from packaging.version import Version, parse +logger = logging.getLogger(__name__) cc = coco.CountryConverter() diff --git a/scripts/build_industrial_production_per_country.py b/scripts/build_industrial_production_per_country.py index 74cb1949..0aea4f15 100644 --- a/scripts/build_industrial_production_per_country.py +++ b/scripts/build_industrial_production_per_country.py @@ -7,11 +7,8 @@ Build industrial production per country. """ import logging -from functools import partial - -logger = logging.getLogger(__name__) - import multiprocessing as mp +from functools import partial import country_converter as coco import numpy as np @@ -19,6 +16,7 @@ import pandas as pd from _helpers import mute_print from tqdm import tqdm +logger = logging.getLogger(__name__) cc = coco.CountryConverter() tj_to_ktoe = 0.0238845 diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index e864d925..3e2b77d4 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -8,15 +8,14 @@ Build mapping between cutout grid cells and population (total, urban, rural). import logging -logger = logging.getLogger(__name__) - - import atlite import geopandas as gpd import numpy as np import pandas as pd import xarray as xr +logger = logging.getLogger(__name__) + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake diff --git a/scripts/cluster_gas_network.py b/scripts/cluster_gas_network.py index e7554dff..b8da5012 100755 --- a/scripts/cluster_gas_network.py +++ b/scripts/cluster_gas_network.py @@ -8,14 +8,14 @@ Cluster gas transmission network to clustered model regions. import logging -logger = logging.getLogger(__name__) - import geopandas as gpd import pandas as pd from packaging.version import Version, parse from pypsa.geo import haversine_pts from shapely import wkt +logger = logging.getLogger(__name__) + def concat_gdf(gdf_list, crs="EPSG:4326"): """ diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 7223f4d5..7f08b678 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -8,9 +8,6 @@ capacity factors, curtailment, energy balances, prices and other metrics. """ import logging - -logger = logging.getLogger(__name__) - import sys import numpy as np @@ -19,7 +16,7 @@ import pypsa from prepare_sector_network import prepare_costs idx = pd.IndexSlice - +logger = logging.getLogger(__name__) opt_name = {"Store": "e", "Line": "s", "Transformer": "s"} diff --git a/scripts/plot_network.py b/scripts/plot_network.py index b34ba432..d8c17587 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -13,8 +13,6 @@ nodes. import logging -logger = logging.getLogger(__name__) - import cartopy.crs as ccrs import geopandas as gpd import matplotlib.pyplot as plt @@ -24,6 +22,7 @@ from make_summary import assign_carriers from plot_summary import preferred_order, rename_techs from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches +logger = logging.getLogger(__name__) plt.style.use(["ggplot"]) diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index d29207af..7e2c955d 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -8,12 +8,11 @@ Creates plots from summary CSV files. import logging -logger = logging.getLogger(__name__) - import matplotlib.gridspec as gridspec import matplotlib.pyplot as plt import pandas as pd +logger = logging.getLogger(__name__) plt.style.use("ggplot") from prepare_sector_network import co2_emissions_year diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 3be2bdac..21291d7e 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -11,6 +11,7 @@ import logging import os import re from itertools import product +from types import SimpleNamespace import networkx as nx import numpy as np @@ -22,18 +23,13 @@ from add_electricity import calculate_annuity, sanitize_carriers from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement from networkx.algorithms.connectivity.edge_augmentation import k_edge_augmentation +from packaging.version import Version, parse from pypsa.geo import haversine_pts from pypsa.io import import_components_from_dataframe from scipy.stats import beta -logger = logging.getLogger(__name__) - -from types import SimpleNamespace - spatial = SimpleNamespace() - -from packaging.version import Version, parse - +logger = logging.getLogger(__name__) pd_version = parse(pd.__version__) agg_group_kwargs = dict(numeric_only=False) if pd_version >= Version("1.3") else {} diff --git a/scripts/retrieve_sector_databundle.py b/scripts/retrieve_sector_databundle.py index cb6cc969..5baf2c56 100644 --- a/scripts/retrieve_sector_databundle.py +++ b/scripts/retrieve_sector_databundle.py @@ -7,14 +7,13 @@ Retrieve and extract data bundle for sector-coupled studies. """ import logging - -logger = logging.getLogger(__name__) - import tarfile from pathlib import Path from _helpers import configure_logging, progress_retrieve, validate_checksum +logger = logging.getLogger(__name__) + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake diff --git a/scripts/solve_network.py b/scripts/solve_network.py index c6c1b10c..4a1e27f9 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -39,10 +39,10 @@ import xarray as xr from _benchmark import memory_logger from _helpers import configure_logging, get_opt, update_config_with_sector_opts from pypsa.descriptors import get_activity_mask +from pypsa.descriptors import get_switchable_as_dense as get_as_dense logger = logging.getLogger(__name__) pypsa.pf.logger.setLevel(logging.WARNING) -from pypsa.descriptors import get_switchable_as_dense as get_as_dense def add_land_use_constraint(n, planning_horizons, config): From 025688bf70b50c182cd17fa358cc39c07604cdee Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 19 Jan 2024 12:16:07 +0100 Subject: [PATCH 153/591] refactor and fix remaining linting problems --- scripts/_helpers.py | 24 +++++++++++++++---- scripts/add_electricity.py | 10 ++++---- scripts/build_biomass_transport_costs.py | 5 ++++ scripts/build_clustered_population_layouts.py | 2 +- scripts/build_gas_input_locations.py | 15 +++++++----- scripts/build_heat_demand.py | 2 +- scripts/build_industrial_distribution_key.py | 4 ++-- scripts/build_line_rating.py | 2 +- scripts/build_population_layouts.py | 2 +- scripts/build_retro_cost.py | 12 +++++----- scripts/build_temperature_profiles.py | 2 +- scripts/cluster_network.py | 5 +--- scripts/make_summary.py | 4 ---- scripts/plot_network.py | 3 +-- scripts/plot_summary.py | 3 +-- scripts/prepare_network.py | 2 +- scripts/prepare_perfect_foresight.py | 4 ++-- scripts/prepare_sector_network.py | 6 ++--- scripts/retrieve_monthly_fuel_prices.py | 5 ++-- scripts/solve_network.py | 4 ++-- 20 files changed, 64 insertions(+), 52 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 67b20877..d84f025b 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -360,8 +360,24 @@ def generate_periodic_profiles(dt_index, nodes, weekly_profile, localize=None): return week_df -def parse(l): - return yaml.safe_load(l[0]) if len(l) == 1 else {l.pop(0): parse(l)} +def parse(infix): + """ + Recursively parse a list into a dictionary or a YAML object. + + Parameters + ---------- + list_to_parse : list + The list to parse. + + Returns + ------- + dict or YAML object + The parsed list. + """ + if len(infix) == 1: + return yaml.safe_load(infix[0]) + else: + return {infix[0]: parse(infix[1:])} def update_config_with_sector_opts(config, sector_opts): @@ -369,8 +385,8 @@ def update_config_with_sector_opts(config, sector_opts): for o in sector_opts.split("-"): if o.startswith("CF+"): - l = o.split("+")[1:] - update_config(config, parse(l)) + infix = o.split("+")[1:] + update_config(config, parse(infix)) def get_checksum_from_zenodo(file_url): diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index e626f456..c9e5abca 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -294,10 +294,10 @@ def attach_load(n, regions, load, nuts3_shapes, ua_md_gdp, countries, scaling=1. nuts3 = gpd.read_file(nuts3_shapes).set_index("index") def upsample(cntry, group): - l = opsd_load[cntry] + load = opsd_load[cntry] if len(group) == 1: - return pd.DataFrame({group.index[0]: l}) + return pd.DataFrame({group.index[0]: load}) nuts3_cntry = nuts3.loc[nuts3.country == cntry] transfer = shapes_to_shapes(group, nuts3_cntry.geometry).T.tocsr() gdp_n = pd.Series( @@ -314,8 +314,8 @@ def attach_load(n, regions, load, nuts3_shapes, ua_md_gdp, countries, scaling=1. # overwrite factor because nuts3 provides no data for UA+MD factors = normed(ua_md_gdp.loc[group.index, "GDP_PPP"].squeeze()) return pd.DataFrame( - factors.values * l.values[:, np.newaxis], - index=l.index, + factors.values * load.values[:, np.newaxis], + index=load.index, columns=factors.index, ) @@ -622,7 +622,7 @@ def attach_hydro(n, costs, ppl, profile_hydro, hydro_capacities, carriers, **par hydro.max_hours > 0, hydro.country.map(max_hours_country) ).fillna(6) - if flatten_dispatch := params.get("flatten_dispatch", False): + if params.get("flatten_dispatch", False): buffer = params.get("flatten_dispatch_buffer", 0.2) average_capacity_factor = inflow_t[hydro.index].mean() / hydro["p_nom"] p_max_pu = (average_capacity_factor + buffer).clip(upper=1) diff --git a/scripts/build_biomass_transport_costs.py b/scripts/build_biomass_transport_costs.py index 9271b600..05b64519 100644 --- a/scripts/build_biomass_transport_costs.py +++ b/scripts/build_biomass_transport_costs.py @@ -80,4 +80,9 @@ def build_biomass_transport_costs(): if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake("build_biomass_transport_costs") + build_biomass_transport_costs() diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index 2f237656..f1d386bd 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -28,7 +28,7 @@ if __name__ == "__main__": gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0) ) - I = cutout.indicatormatrix(clustered_regions) + I = cutout.indicatormatrix(clustered_regions) # noqa: E741 pop = {} for item in ["total", "urban", "rural"]: diff --git a/scripts/build_gas_input_locations.py b/scripts/build_gas_input_locations.py index 0c9e4c4b..d8727063 100644 --- a/scripts/build_gas_input_locations.py +++ b/scripts/build_gas_input_locations.py @@ -27,8 +27,11 @@ def build_gem_lng_data(fn): df = pd.read_excel(fn[0], sheet_name="LNG terminals - data") df = df.set_index("ComboID") - remove_country = ["Cyprus", "Turkey"] - remove_terminal = ["Puerto de la Luz LNG Terminal", "Gran Canaria LNG Terminal"] + remove_country = ["Cyprus", "Turkey"] # noqa: F841 + remove_terminal = [ + "Puerto de la Luz LNG Terminal", + "Gran Canaria LNG Terminal", + ] # noqa: F841 df = df.query( "Status != 'Cancelled' \ @@ -45,8 +48,8 @@ def build_gem_prod_data(fn): df = pd.read_excel(fn[0], sheet_name="Gas extraction - main") df = df.set_index("GEM Unit ID") - remove_country = ["Cyprus", "Türkiye"] - remove_fuel_type = ["oil"] + remove_country = ["Cyprus", "Türkiye"] # noqa: F841 + remove_fuel_type = ["oil"] # noqa: F841 df = df.query( "Status != 'shut in' \ @@ -96,8 +99,8 @@ def build_gas_input_locations(gem_fn, entry_fn, sto_fn, countries): ] sto = read_scigrid_gas(sto_fn) - remove_country = ["RU", "UA", "TR", "BY"] - sto = sto.query("country_code != @remove_country") + remove_country = ["RU", "UA", "TR", "BY"] # noqa: F841 + sto = sto.query("country_code not in @remove_country") # production sites inside the model scope prod = build_gem_prod_data(gem_fn) diff --git a/scripts/build_heat_demand.py b/scripts/build_heat_demand.py index 77768404..b983f125 100644 --- a/scripts/build_heat_demand.py +++ b/scripts/build_heat_demand.py @@ -34,7 +34,7 @@ if __name__ == "__main__": gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0) ) - I = cutout.indicatormatrix(clustered_regions) + I = cutout.indicatormatrix(clustered_regions) # noqa: E741 pop_layout = xr.open_dataarray(snakemake.input.pop_layout) diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index 08de3bae..fe7cf0c1 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -30,7 +30,7 @@ def locate_missing_industrial_sites(df): try: from geopy.extra.rate_limiter import RateLimiter from geopy.geocoders import Nominatim - except: + except ImportError: raise ModuleNotFoundError( "Optional dependency 'geopy' not found." "Install via 'conda install -c conda-forge geopy'" @@ -99,7 +99,7 @@ def prepare_hotmaps_database(regions): # get all duplicated entries duplicated_i = gdf.index[gdf.index.duplicated()] # convert from raw data country name to iso-2-code - code = cc.convert(gdf.loc[duplicated_i, "Country"], to="iso2") + code = cc.convert(gdf.loc[duplicated_i, "Country"], to="iso2") # noqa: F841 # screen out malformed country allocation gdf_filtered = gdf.loc[duplicated_i].query("country == @code") # concat not duplicated and filtered gdf diff --git a/scripts/build_line_rating.py b/scripts/build_line_rating.py index 4d45b910..5b4cd6b3 100755 --- a/scripts/build_line_rating.py +++ b/scripts/build_line_rating.py @@ -98,7 +98,7 @@ def calculate_line_rating(n, cutout): ------- xarray DataArray object with maximal power. """ - relevant_lines = n.lines[(n.lines["underground"] == False)] + relevant_lines = n.lines[~n.lines["underground"]] buses = relevant_lines[["bus0", "bus1"]].values x = n.buses.x y = n.buses.y diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index 3e2b77d4..e215e6c0 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -33,7 +33,7 @@ if __name__ == "__main__": nuts3 = gpd.read_file(snakemake.input.nuts3_shapes).set_index("index") # Indicator matrix NUTS3 -> grid cells - I = atlite.cutout.compute_indicatormatrix(nuts3.geometry, grid_cells) + I = atlite.cutout.compute_indicatormatrix(nuts3.geometry, grid_cells) # noqa: E741 # Indicator matrix grid_cells -> NUTS3; inprinciple Iinv*I is identity # but imprecisions mean not perfect diff --git a/scripts/build_retro_cost.py b/scripts/build_retro_cost.py index d2aae140..67440263 100755 --- a/scripts/build_retro_cost.py +++ b/scripts/build_retro_cost.py @@ -554,7 +554,7 @@ def prepare_temperature_data(): # windows --------------------------------------------------------------- -def window_limit(l, window_assumptions): +def window_limit(l, window_assumptions): # noqa: E741 """ Define limit u value from which on window is retrofitted. """ @@ -567,7 +567,7 @@ def window_limit(l, window_assumptions): return m * l + a -def u_retro_window(l, window_assumptions): +def u_retro_window(l, window_assumptions): # noqa: E741 """ Define retrofitting value depending on renovation strength. """ @@ -580,7 +580,7 @@ def u_retro_window(l, window_assumptions): return max(m * l + a, 0.8) -def window_cost(u, cost_retro, window_assumptions): +def window_cost(u, cost_retro, window_assumptions): # noqa: E741 """ Get costs for new windows depending on u value. """ @@ -600,7 +600,7 @@ def window_cost(u, cost_retro, window_assumptions): return window_cost -def calculate_costs(u_values, l, cost_retro, window_assumptions): +def calculate_costs(u_values, l, cost_retro, window_assumptions): # noqa: E741 """ Returns costs for a given retrofitting strength weighted by the average surface/volume ratio of the component for each building type. @@ -626,7 +626,7 @@ def calculate_costs(u_values, l, cost_retro, window_assumptions): ) -def calculate_new_u(u_values, l, l_weight, window_assumptions, k=0.035): +def calculate_new_u(u_values, l, l_weight, window_assumptions, k=0.035): # noqa: E741 """ Calculate U-values after building retrofitting, depending on the old U-values (u_values). This is for simple insulation measuers, adding an @@ -746,7 +746,7 @@ def calculate_heat_losses(u_values, data_tabula, l_strength, temperature_factor) """ # (1) by transmission # calculate new U values of building elements due to additional insulation - for l in l_strength: + for l in l_strength: # noqa: E741 u_values[f"new_U_{l}"] = calculate_new_u( u_values, l, l_weight, window_assumptions ) diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index a13ec3c2..02fa4a71 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -34,7 +34,7 @@ if __name__ == "__main__": gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0) ) - I = cutout.indicatormatrix(clustered_regions) + I = cutout.indicatormatrix(clustered_regions) # noqa: E741 pop_layout = xr.open_dataarray(snakemake.input.pop_layout) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 28f08396..01af29aa 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -133,6 +133,7 @@ import pyomo.environ as po import pypsa import seaborn as sns from _helpers import configure_logging, update_p_nom_max +from add_electricity import load_costs from pypsa.clustering.spatial import ( busmap_by_greedy_modularity, busmap_by_hac, @@ -141,11 +142,7 @@ from pypsa.clustering.spatial import ( ) warnings.filterwarnings(action="ignore", category=UserWarning) - -from add_electricity import load_costs - idx = pd.IndexSlice - logger = logging.getLogger(__name__) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 7f08b678..0fab5367 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -506,10 +506,6 @@ def calculate_weighted_prices(n, label, weighted_prices): if carrier in ["H2", "gas"]: load = pd.DataFrame(index=n.snapshots, columns=buses, data=0.0) - elif carrier[:5] == "space": - load = heat_demand_df[buses.str[:2]].rename( - columns=lambda i: str(i) + suffix - ) else: load = n.loads_t.p_set[buses] diff --git a/scripts/plot_network.py b/scripts/plot_network.py index d8c17587..6a3783e7 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -895,8 +895,7 @@ def plot_series(network, carrier="AC", name="test"): fig.tight_layout() fig.savefig( - "{}/{RDIR}maps/series-{}-{}-{}-{}-{}.pdf".format( - "results", + "results/{}maps/series-{}-{}-{}-{}.pdf".format( snakemake.params.RDIR, snakemake.wildcards["ll"], carrier, diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index 7e2c955d..b2ec0892 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -11,12 +11,11 @@ import logging import matplotlib.gridspec as gridspec import matplotlib.pyplot as plt import pandas as pd +from prepare_sector_network import co2_emissions_year logger = logging.getLogger(__name__) plt.style.use("ggplot") -from prepare_sector_network import co2_emissions_year - # consolidate and rename def rename_techs(label): diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 75e5daba..5652dc6e 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -194,7 +194,7 @@ def apply_time_segmentation(n, segments, solver_name="cbc"): logger.info(f"Aggregating time series to {segments} segments.") try: import tsam.timeseriesaggregation as tsam - except: + except ImportError: raise ModuleNotFoundError( "Optional dependency 'tsam' not found." "Install via 'pip install tsam'" ) diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index 00f23fab..1c3a0ebe 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -305,7 +305,7 @@ def set_carbon_constraints(n, opts): m = re.match(r"^\d+p\d$", o, re.IGNORECASE) if m is not None: budget = snakemake.config["co2_budget"][m.group(0)] * 1e9 - if budget != None: + if budget is not None: logger.info(f"add carbon budget of {budget}") n.add( "GlobalConstraint", @@ -428,7 +428,7 @@ def apply_time_segmentation_perfect( """ try: import tsam.timeseriesaggregation as tsam - except: + except ImportError: raise ModuleNotFoundError( "Optional dependency 'tsam' not found." "Install via 'pip install tsam'" ) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 21291d7e..4d36e7d4 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -183,8 +183,6 @@ def define_spatial(nodes, options): return spatial -from types import SimpleNamespace - spatial = SimpleNamespace() @@ -1472,7 +1470,6 @@ def add_land_transport(n, costs): # TODO options? logger.info("Add land transport") - nhours = n.snapshot_weightings.generators.sum() transport = pd.read_csv( snakemake.input.transport_demand, index_col=0, parse_dates=True @@ -3120,6 +3117,7 @@ def add_waste_heat(n): # TODO options? logger.info("Add possibility to use industrial waste heat in district heating") + cf_industry = snakemake.params.industry # AC buses with district heating urban_central = n.buses.index[n.buses.carrier == "urban central heat"] @@ -3480,7 +3478,7 @@ def apply_time_segmentation( """ try: import tsam.timeseriesaggregation as tsam - except: + except ImportError: raise ModuleNotFoundError( "Optional dependency 'tsam' not found." "Install via 'pip install tsam'" ) diff --git a/scripts/retrieve_monthly_fuel_prices.py b/scripts/retrieve_monthly_fuel_prices.py index 11e351ce..e64066cb 100644 --- a/scripts/retrieve_monthly_fuel_prices.py +++ b/scripts/retrieve_monthly_fuel_prices.py @@ -7,13 +7,12 @@ Retrieve monthly fuel prices from Destatis. """ import logging - -logger = logging.getLogger(__name__) - from pathlib import Path from _helpers import configure_logging, progress_retrieve +logger = logging.getLogger(__name__) + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 4a1e27f9..1c37bfd2 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -572,7 +572,7 @@ def add_SAFE_constraints(n, config): peakdemand = n.loads_t.p_set.sum(axis=1).max() margin = 1.0 + config["electricity"]["SAFE_reservemargin"] reserve_margin = peakdemand * margin - conventional_carriers = config["electricity"]["conventional_carriers"] + conventional_carriers = config["electricity"]["conventional_carriers"] # noqa: F841 ext_gens_i = n.generators.query( "carrier in @conventional_carriers & p_nom_extendable" ).index @@ -694,7 +694,7 @@ def add_lossy_bidirectional_link_constraints(n): return n.links["reversed"] = n.links.reversed.fillna(0).astype(bool) - carriers = n.links.loc[n.links.reversed, "carrier"].unique() + carriers = n.links.loc[n.links.reversed, "carrier"].unique() # noqa: F841 forward_i = n.links.query( "carrier in @carriers and ~reversed and p_nom_extendable" From 1ffb28b3fc4661c60d5a0a314cd8a94fb7a4268e Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 19 Jan 2024 12:23:29 +0100 Subject: [PATCH 154/591] helpers: parse: fix docstring and take original implementation --- scripts/_helpers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index d84f025b..3173671d 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -362,7 +362,8 @@ def generate_periodic_profiles(dt_index, nodes, weekly_profile, localize=None): def parse(infix): """ - Recursively parse a list into a dictionary or a YAML object. + Recursively parse a chained wildcard expression into a dictionary or a YAML + object. Parameters ---------- @@ -377,7 +378,7 @@ def parse(infix): if len(infix) == 1: return yaml.safe_load(infix[0]) else: - return {infix[0]: parse(infix[1:])} + return {infix.pop(0): parse(infix)} def update_config_with_sector_opts(config, sector_opts): From d0cb57e9ab743d7099ccfbea2266788a9b02cb97 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 19 Jan 2024 12:37:07 +0100 Subject: [PATCH 155/591] make_summary_perfect: reinsert calclulate_<> functions --- scripts/build_gas_input_locations.py | 4 ++-- scripts/make_summary_perfect.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/build_gas_input_locations.py b/scripts/build_gas_input_locations.py index d8727063..081f74b9 100644 --- a/scripts/build_gas_input_locations.py +++ b/scripts/build_gas_input_locations.py @@ -28,10 +28,10 @@ def build_gem_lng_data(fn): df = df.set_index("ComboID") remove_country = ["Cyprus", "Turkey"] # noqa: F841 - remove_terminal = [ + remove_terminal = [ # noqa: F841 "Puerto de la Luz LNG Terminal", "Gran Canaria LNG Terminal", - ] # noqa: F841 + ] df = df.query( "Status != 'Cancelled' \ diff --git a/scripts/make_summary_perfect.py b/scripts/make_summary_perfect.py index 93411a4c..555e5da5 100644 --- a/scripts/make_summary_perfect.py +++ b/scripts/make_summary_perfect.py @@ -12,6 +12,9 @@ other metrics. import numpy as np import pandas as pd import pypsa +from make_summary import calculate_cfs # noqa: F401 +from make_summary import calculate_nodal_cfs # noqa: F401 +from make_summary import calculate_nodal_costs # noqa: F401 from make_summary import assign_carriers, assign_locations from prepare_sector_network import prepare_costs from pypsa.descriptors import get_active_assets From 9b3e68a6a8c297f40accef7bfa9e2deb6d217dcd Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 19 Jan 2024 16:58:05 +0100 Subject: [PATCH 156/591] correctly retrieve solver threads and add back memory logfile --- rules/solve_overnight.smk | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index a3fed042..ae3a34d4 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -22,11 +22,13 @@ rule solve_sector_network: shadow: "shallow" log: - solver=LOGS - + "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: config["solving"]["solver"].get("threads", 4) + solver=RESULTS + + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_solver.log", + memory=RESULTS + + "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) resources: mem_mb=config["solving"]["mem"], walltime=config["solving"].get("walltime", "12:00:00"), From 01c1b9161b85e068900a7f1d2711696d8957d729 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 19 Jan 2024 16:59:39 +0100 Subject: [PATCH 157/591] COPT solver provide sensible default settings --- config/config.default.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/config.default.yaml b/config/config.default.yaml index 661f855e..d071f73f 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -755,6 +755,10 @@ solving: solutiontype: 2 # non basic solution, ie no crossover barrier.convergetol: 1.e-5 feasopt.tolerance: 1.e-6 + copt-default: + Threads: 8 + LpMethod: 2 + Crossover: 0 cbc-default: {} # Used in CI glpk-default: {} # Used in CI From 58b012e03dbc7da4701f77f390827fa10b13c680 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 16:00:19 +0000 Subject: [PATCH 158/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/solve_overnight.smk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index ae3a34d4..39778162 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -28,7 +28,9 @@ 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: config["solving"]["solver_options"][config["solving"]["solver"]["options"]].get( + "threads", 4 +) resources: mem_mb=config["solving"]["mem"], walltime=config["solving"].get("walltime", "12:00:00"), From 77f49d44042921feb17173652e6e47de0f138941 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 19 Jan 2024 19:00:33 +0100 Subject: [PATCH 159/591] update technology-data to 0.6.2 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 d071f73f..6349f43e 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -625,7 +625,7 @@ industry: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#costs costs: year: 2030 - version: v0.6.0 + version: v0.6.2 rooftop_share: 0.14 # based on the potentials, assuming (0.1 kW/m2 and 10 m2/person) social_discountrate: 0.02 fill_values: From fbff32dcfcba57fab3cfaea1e10ae76f1cad75f1 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Fri, 12 Jan 2024 16:42:12 +0100 Subject: [PATCH 160/591] build_pop_weighted_energy: don't reduce district heat share Previously the DH share was being multiplied by the population weighting, reducing the DH share with multiple nodes. --- scripts/build_population_weighted_energy_totals.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 879e3b9b..20467f72 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -26,4 +26,9 @@ if __name__ == "__main__": nodal_energy_totals.index = pop_layout.index nodal_energy_totals = nodal_energy_totals.multiply(pop_layout.fraction, axis=0) + # district heating share should not be divided by population fraction + dh_share = energy_totals["district heat share"].loc[pop_layout.ct].fillna(0.0) + dh_share.index = pop_layout.index + nodal_energy_totals["district heat share"] = dh_share + nodal_energy_totals.to_csv(snakemake.output[0]) From 6c20ce83d7f0fd509013cc8d060a4bb91fd2c879 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Mon, 15 Jan 2024 16:47:19 +0100 Subject: [PATCH 161/591] move building of daily heat profile to its own script Previously this was handled inside prepare_sector_network.py. --- rules/build_sector.smk | 36 +++++++--- ...t_demand.py => build_daily_heat_demand.py} | 0 scripts/build_hourly_heat_demand.py | 69 +++++++++++++++++++ scripts/prepare_sector_network.py | 29 ++------ 4 files changed, 102 insertions(+), 32 deletions(-) rename scripts/{build_heat_demand.py => build_daily_heat_demand.py} (100%) create mode 100644 scripts/build_hourly_heat_demand.py diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 4744aa25..efaff2a3 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -123,7 +123,7 @@ rule cluster_gas_network: "../scripts/cluster_gas_network.py" -rule build_heat_demands: +rule build_daily_heat_demand: params: snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, input: @@ -131,18 +131,39 @@ rule build_heat_demands: regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", output: - heat_demand=RESOURCES + "heat_demand_{scope}_elec_s{simpl}_{clusters}.nc", + heat_demand=RESOURCES + "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc", resources: mem_mb=20000, threads: 8 log: - LOGS + "build_heat_demands_{scope}_{simpl}_{clusters}.loc", + LOGS + "build_daily_heat_demand_{scope}_{simpl}_{clusters}.loc", benchmark: - BENCHMARKS + "build_heat_demands/{scope}_s{simpl}_{clusters}" + BENCHMARKS + "build_daily_heat_demand/{scope}_s{simpl}_{clusters}" conda: "../envs/environment.yaml" script: - "../scripts/build_heat_demand.py" + "../scripts/build_daily_heat_demand.py" + + +rule build_hourly_heat_demand: + params: + snapshots=config["snapshots"], + input: + heat_profile="data/heat_load_profile_BDEW.csv", + heat_demand=RESOURCES + "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc", + output: + heat_demand=RESOURCES + "hourly_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc", + resources: + mem_mb=2000, + threads: 8 + log: + LOGS + "build_hourly_heat_demand_{scope}_{simpl}_{clusters}.loc", + benchmark: + BENCHMARKS + "build_hourly_heat_demand/{scope}_s{simpl}_{clusters}" + conda: + "../envs/environment.yaml" + script: + "../scripts/build_hourly_heat_demand.py" rule build_temperature_profiles: @@ -727,7 +748,6 @@ rule prepare_sector_network: if config["foresight"] == "overnight" else RESOURCES + "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv", - heat_profile="data/heat_load_profile_BDEW.csv", costs="data/costs_{}.csv".format(config["costs"]["year"]) if config["foresight"] == "overnight" else "data/costs_{planning_horizons}.csv", @@ -740,9 +760,7 @@ rule prepare_sector_network: simplified_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}.csv", industrial_demand=RESOURCES + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv", - heat_demand_urban=RESOURCES + "heat_demand_urban_elec_s{simpl}_{clusters}.nc", - heat_demand_rural=RESOURCES + "heat_demand_rural_elec_s{simpl}_{clusters}.nc", - heat_demand_total=RESOURCES + "heat_demand_total_elec_s{simpl}_{clusters}.nc", + hourly_heat_demand_total=RESOURCES + "hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc", temp_soil_total=RESOURCES + "temp_soil_total_elec_s{simpl}_{clusters}.nc", temp_soil_rural=RESOURCES + "temp_soil_rural_elec_s{simpl}_{clusters}.nc", temp_soil_urban=RESOURCES + "temp_soil_urban_elec_s{simpl}_{clusters}.nc", diff --git a/scripts/build_heat_demand.py b/scripts/build_daily_heat_demand.py similarity index 100% rename from scripts/build_heat_demand.py rename to scripts/build_daily_heat_demand.py diff --git a/scripts/build_hourly_heat_demand.py b/scripts/build_hourly_heat_demand.py new file mode 100644 index 00000000..94ad7266 --- /dev/null +++ b/scripts/build_hourly_heat_demand.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Build hourly heat demand time series from daily ones. +""" + +import pandas as pd +import xarray as xr +from _helpers import generate_periodic_profiles, update_config_with_sector_opts +from itertools import product + + + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake( + "build_heat_demands", + simpl="", + clusters=48, + ) + + snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) + + daily_space_heat_demand = ( + xr.open_dataarray(snakemake.input.heat_demand) + .to_pandas() + .reindex(index=snapshots, method="ffill") + ) + + intraday_profiles = pd.read_csv(snakemake.input.heat_profile, index_col=0) + + sectors = ["residential", "services"] + uses = ["water", "space"] + + heat_demand = {} + for sector, use in product(sectors, uses): + weekday = list(intraday_profiles[f"{sector} {use} weekday"]) + weekend = list(intraday_profiles[f"{sector} {use} weekend"]) + weekly_profile = weekday * 5 + weekend * 2 + intraday_year_profile = generate_periodic_profiles( + daily_space_heat_demand.index.tz_localize("UTC"), + nodes=daily_space_heat_demand.columns, + weekly_profile=weekly_profile, + ) + + if use == "space": + heat_demand[f"{sector} {use}"] = daily_space_heat_demand * intraday_year_profile + else: + heat_demand[f"{sector} {use}"] = intraday_year_profile + + heat_demand = pd.concat(heat_demand, + axis=1, + names = ["sector use", "node"]) + + heat_demand.index.name="snapshots" + + print(heat_demand) + + print(heat_demand.stack()) + + ds = heat_demand.stack().to_xarray()#xr.Dataset.from_dataframe(heat_demand) + + print(ds) + + ds.to_netcdf(snakemake.output.heat_demand) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 4d36e7d4..1f404c4e 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -18,7 +18,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import generate_periodic_profiles, update_config_with_sector_opts +from _helpers import update_config_with_sector_opts from add_electricity import calculate_annuity, sanitize_carriers from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement @@ -1639,14 +1639,8 @@ def add_land_transport(n, costs): def build_heat_demand(n): - # copy forward the daily average heat demand into each hour, so it can be multiplied by the intraday profile - daily_space_heat_demand = ( - xr.open_dataarray(snakemake.input.heat_demand_total) - .to_pandas() - .reindex(index=n.snapshots, method="ffill") - ) - intraday_profiles = pd.read_csv(snakemake.input.heat_profile, index_col=0) + heat_demand_shape = xr.open_dataset(snakemake.input.hourly_heat_demand_total).to_dataframe().unstack(level=1) sectors = ["residential", "services"] uses = ["water", "space"] @@ -1654,25 +1648,14 @@ def build_heat_demand(n): heat_demand = {} electric_heat_supply = {} for sector, use in product(sectors, uses): - weekday = list(intraday_profiles[f"{sector} {use} weekday"]) - weekend = list(intraday_profiles[f"{sector} {use} weekend"]) - weekly_profile = weekday * 5 + weekend * 2 - intraday_year_profile = generate_periodic_profiles( - daily_space_heat_demand.index.tz_localize("UTC"), - nodes=daily_space_heat_demand.columns, - weekly_profile=weekly_profile, - ) - if use == "space": - heat_demand_shape = daily_space_heat_demand * intraday_year_profile - else: - heat_demand_shape = intraday_year_profile + name = f"{sector} {use}" - heat_demand[f"{sector} {use}"] = ( - heat_demand_shape / heat_demand_shape.sum() + heat_demand[name] = ( + heat_demand_shape[name] / heat_demand_shape[name].sum() ).multiply(pop_weighted_energy_totals[f"total {sector} {use}"]) * 1e6 electric_heat_supply[f"{sector} {use}"] = ( - heat_demand_shape / heat_demand_shape.sum() + heat_demand_shape[name] / heat_demand_shape[name].sum() ).multiply(pop_weighted_energy_totals[f"electricity {sector} {use}"]) * 1e6 heat_demand = pd.concat(heat_demand, axis=1) From bd8a5ecf2bd5124a1062e0fb8666cdcaa18df19d Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Mon, 15 Jan 2024 17:51:08 +0100 Subject: [PATCH 162/591] build_energy_totals: output district heat share to separate file --- rules/build_sector.smk | 1 + scripts/build_energy_totals.py | 31 +++++++++++++++++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index efaff2a3..bfe168e1 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -256,6 +256,7 @@ rule build_energy_totals: energy_name=RESOURCES + "energy_totals.csv", co2_name=RESOURCES + "co2_totals.csv", transport_name=RESOURCES + "transport_data.csv", + district_heat_share=RESOURCES + "district_heat_share.csv", threads: 16 resources: mem_mb=10000, diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 39b2a1be..53aab980 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -391,13 +391,6 @@ def build_idees(countries, year): # convert TWh/100km to kWh/km totals.loc["passenger car efficiency"] *= 10 - # district heating share - district_heat = totals.loc[ - ["derived heat residential", "derived heat services"] - ].sum() - total_heat = totals.loc[["thermal uses residential", "thermal uses services"]].sum() - totals.loc["district heat share"] = district_heat.div(total_heat) - return totals.T @@ -572,16 +565,31 @@ def build_energy_totals(countries, eurostat, swiss, idees): ratio = df.at["BA", "total residential"] / df.at["RS", "total residential"] df.loc["BA", missing] = ratio * df.loc["RS", missing] + return df + + +def build_district_heat_share(idees): + + # district heating share + district_heat = idees[ + ["derived heat residential", "derived heat services"] + ].sum(axis=1) + total_heat = idees[["thermal uses residential", "thermal uses services"]].sum(axis=1) + + district_heat_share = district_heat/total_heat + # Missing district heating share dh_share = pd.read_csv( snakemake.input.district_heat_share, index_col=0, usecols=[0, 1] ) # make conservative assumption and take minimum from both data sets - df["district heat share"] = pd.concat( - [df["district heat share"], dh_share.reindex(index=df.index) / 100], axis=1 + district_heat_share = pd.concat( + [district_heat_share, dh_share.reindex(index=district_heat_share.index) / 100], axis=1 ).min(axis=1) - return df + district_heat_share.name = "district heat share" + + return district_heat_share def build_eea_co2(input_co2, year=1990, emissions_scope="CO2"): @@ -750,6 +758,9 @@ if __name__ == "__main__": energy = build_energy_totals(countries, eurostat, swiss, idees) energy.to_csv(snakemake.output.energy_name) + district_heat_share = build_district_heat_share(idees) + district_heat_share.to_csv(snakemake.output.district_heat_share) + base_year_emissions = params["base_emissions_year"] emissions_scope = snakemake.params.energy["emissions"] eea_co2 = build_eea_co2(snakemake.input.co2, base_year_emissions, emissions_scope) From 1a477d6b325dd8d78b561295509cf9608bd2b056 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Mon, 15 Jan 2024 18:55:09 +0100 Subject: [PATCH 163/591] move calculation of district heating share to its own script Now the script build_district_heat_share.py does what the old function create_nodes_for_heating() in prepare_sector_networks.py did. There is no need to build nodes lists for each heating sector, since all nodes have district heating now. --- rules/build_sector.smk | 22 +++ scripts/build_district_heat_share.py | 77 +++++++++ scripts/build_energy_totals.py | 6 +- ...build_population_weighted_energy_totals.py | 5 - scripts/prepare_sector_network.py | 161 +++++++----------- 5 files changed, 164 insertions(+), 107 deletions(-) create mode 100644 scripts/build_district_heat_share.py diff --git a/rules/build_sector.smk b/rules/build_sector.smk index bfe168e1..14156268 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -710,6 +710,27 @@ rule build_transport_demand: "../scripts/build_transport_demand.py" + + +rule build_district_heat_share: + params: + sector=config["sector"], + input: + district_heat_share=RESOURCES + "district_heat_share.csv", + clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", + output: + district_heat_share=RESOURCES + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + threads: 1 + resources: + mem_mb=1000, + log: + LOGS + "build_district_heat_share_s{simpl}_{clusters}_{planning_horizons}.log", + conda: + "../envs/environment.yaml" + script: + "../scripts/build_district_heat_share.py" + + rule prepare_sector_network: params: co2_budget=config["co2_budget"], @@ -762,6 +783,7 @@ rule prepare_sector_network: industrial_demand=RESOURCES + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv", hourly_heat_demand_total=RESOURCES + "hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc", + district_heat_share=RESOURCES + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", temp_soil_total=RESOURCES + "temp_soil_total_elec_s{simpl}_{clusters}.nc", temp_soil_rural=RESOURCES + "temp_soil_rural_elec_s{simpl}_{clusters}.nc", temp_soil_urban=RESOURCES + "temp_soil_urban_elec_s{simpl}_{clusters}.nc", diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py new file mode 100644 index 00000000..d521214d --- /dev/null +++ b/scripts/build_district_heat_share.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Build district heat shares at each node, depending on investment year. +""" + +import pandas as pd + +from prepare_sector_network import get + +import logging + + +logger = logging.getLogger(__name__) + + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake( + "build_heat_demands", + simpl="", + clusters=48, + ) + + investment_year = int(snakemake.wildcards.planning_horizons[-4:]) + + pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, + index_col=0) + + district_heat_share = pd.read_csv(snakemake.input.district_heat_share, + index_col=0).squeeze() + + # make ct-based share nodal + district_heat_share = district_heat_share.loc[pop_layout.ct] + district_heat_share.index = pop_layout.index + + # total urban population per country + ct_urban = pop_layout.urban.groupby(pop_layout.ct).sum() + + # distribution of urban population within a country + pop_layout["urban_ct_fraction"] = pop_layout.urban / pop_layout.ct.map(ct_urban.get) + + # fraction of node that is urban + urban_fraction = pop_layout.urban / pop_layout[["rural", "urban"]].sum(axis=1) + + # maximum potential of urban demand covered by district heating + central_fraction = snakemake.config["sector"]["district_heating"]["potential"] + + # district heating share at each node + dist_fraction_node = ( + district_heat_share * pop_layout["urban_ct_fraction"] / pop_layout["fraction"] + ) + + # if district heating share larger than urban fraction -> set urban + # fraction to district heating share + urban_fraction = pd.concat([urban_fraction, dist_fraction_node], axis=1).max(axis=1) + + # difference of max potential and today's share of district heating + diff = (urban_fraction * central_fraction) - dist_fraction_node + progress = get(snakemake.config["sector"]["district_heating"]["progress"], investment_year) + dist_fraction_node += diff * progress + logger.info( + f"Increase district heating share by a progress factor of {progress:.2%} " + f"resulting in new average share of {dist_fraction_node.mean():.2%}" + ) + + df = pd.DataFrame(dtype=float) + + df["original district heat share"] = district_heat_share + df["district fraction of node"] = dist_fraction_node + df["urban fraction"] = urban_fraction + + df.to_csv(snakemake.output.district_heat_share) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 53aab980..306caf4d 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -568,7 +568,7 @@ def build_energy_totals(countries, eurostat, swiss, idees): return df -def build_district_heat_share(idees): +def build_district_heat_share(countries, idees): # district heating share district_heat = idees[ @@ -578,6 +578,8 @@ def build_district_heat_share(idees): district_heat_share = district_heat/total_heat + district_heat_share = district_heat_share.reindex(countries) + # Missing district heating share dh_share = pd.read_csv( snakemake.input.district_heat_share, index_col=0, usecols=[0, 1] @@ -758,7 +760,7 @@ if __name__ == "__main__": energy = build_energy_totals(countries, eurostat, swiss, idees) energy.to_csv(snakemake.output.energy_name) - district_heat_share = build_district_heat_share(idees) + district_heat_share = build_district_heat_share(countries, idees) district_heat_share.to_csv(snakemake.output.district_heat_share) base_year_emissions = params["base_emissions_year"] diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 20467f72..879e3b9b 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -26,9 +26,4 @@ if __name__ == "__main__": nodal_energy_totals.index = pop_layout.index nodal_energy_totals = nodal_energy_totals.multiply(pop_layout.fraction, axis=0) - # district heating share should not be divided by population fraction - dh_share = energy_totals["district heat share"].loc[pop_layout.ct].fillna(0.0) - dh_share.index = pop_layout.index - nodal_energy_totals["district heat share"] = dh_share - nodal_energy_totals.to_csv(snakemake.output[0]) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 1f404c4e..8d56ae6b 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1678,7 +1678,10 @@ def add_heat(n, costs): heat_demand = build_heat_demand(n) - nodes, dist_fraction, urban_fraction = create_nodes_for_heat_sector() + district_heat_info = pd.read_csv(snakemake.input.district_heat_share, + index_col=0) + dist_fraction = district_heat_info["district fraction of node"] + urban_fraction = district_heat_info["urban fraction"] # NB: must add costs of central heating afterwards (EUR 400 / kWpeak, 50a, 1% FOM from Fraunhofer ISE) @@ -1715,6 +1718,8 @@ def add_heat(n, costs): # 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2 solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3 + nodes = pop_layout.index + for name in heat_systems: name_type = "central" if name == "urban central" else "decentral" @@ -1722,8 +1727,8 @@ def add_heat(n, costs): n.madd( "Bus", - nodes[name] + f" {name} heat", - location=nodes[name], + nodes + f" {name} heat", + location=nodes, carrier=name + " heat", unit="MWh_th", ) @@ -1731,9 +1736,9 @@ def add_heat(n, costs): if name == "urban central" and options.get("central_heat_vent"): n.madd( "Generator", - nodes[name] + f" {name} heat vent", - bus=nodes[name] + f" {name} heat", - location=nodes[name], + nodes + f" {name} heat vent", + bus=nodes + f" {name} heat", + location=nodes, carrier=name + " heat vent", p_nom_extendable=True, p_max_pu=0, @@ -1746,11 +1751,11 @@ def add_heat(n, costs): for sector in sectors: # heat demand weighting if "rural" in name: - factor = 1 - urban_fraction[nodes[name]] + factor = 1 - urban_fraction[nodes] elif "urban central" in name: - factor = dist_fraction[nodes[name]] + factor = dist_fraction[nodes] elif "urban decentral" in name: - factor = urban_fraction[nodes[name]] - dist_fraction[nodes[name]] + factor = urban_fraction[nodes] - dist_fraction[nodes] else: raise NotImplementedError( f" {name} not in " f"heat systems: {heat_systems}" @@ -1761,7 +1766,7 @@ def add_heat(n, costs): heat_demand[[sector + " water", sector + " space"]] .T.groupby(level=1) .sum() - .T[nodes[name]] + .T[nodes] .multiply(factor) ) @@ -1769,7 +1774,7 @@ def add_heat(n, costs): heat_load = ( heat_demand.T.groupby(level=1) .sum() - .T[nodes[name]] + .T[nodes] .multiply( factor * (1 + options["district_heating"]["district_heating_loss"]) ) @@ -1777,9 +1782,9 @@ def add_heat(n, costs): n.madd( "Load", - nodes[name], + nodes, suffix=f" {name} heat", - bus=nodes[name] + f" {name} heat", + bus=nodes + f" {name} heat", carrier=name + " heat", p_set=heat_load, ) @@ -1790,17 +1795,17 @@ def add_heat(n, costs): costs_name = f"{name_type} {heat_pump_type}-sourced heat pump" efficiency = ( - cop[heat_pump_type][nodes[name]] + cop[heat_pump_type][nodes] if options["time_dep_hp_cop"] else costs.at[costs_name, "efficiency"] ) n.madd( "Link", - nodes[name], + nodes, suffix=f" {name} {heat_pump_type} heat pump", - bus0=nodes[name], - bus1=nodes[name] + f" {name} heat", + bus0=nodes, + bus1=nodes + f" {name} heat", carrier=f"{name} {heat_pump_type} heat pump", efficiency=efficiency, capital_cost=costs.at[costs_name, "efficiency"] @@ -1814,17 +1819,17 @@ def add_heat(n, costs): n.madd( "Bus", - nodes[name] + f" {name} water tanks", - location=nodes[name], + nodes + f" {name} water tanks", + location=nodes, carrier=name + " water tanks", unit="MWh_th", ) n.madd( "Link", - nodes[name] + f" {name} water tanks charger", - bus0=nodes[name] + f" {name} heat", - bus1=nodes[name] + f" {name} water tanks", + nodes + f" {name} water tanks charger", + bus0=nodes + f" {name} heat", + bus1=nodes + f" {name} water tanks", efficiency=costs.at["water tank charger", "efficiency"], carrier=name + " water tanks charger", p_nom_extendable=True, @@ -1832,9 +1837,9 @@ def add_heat(n, costs): n.madd( "Link", - nodes[name] + f" {name} water tanks discharger", - bus0=nodes[name] + f" {name} water tanks", - bus1=nodes[name] + f" {name} heat", + nodes + f" {name} water tanks discharger", + bus0=nodes + f" {name} water tanks", + bus1=nodes + f" {name} heat", carrier=name + " water tanks discharger", efficiency=costs.at["water tank discharger", "efficiency"], p_nom_extendable=True, @@ -1853,8 +1858,8 @@ def add_heat(n, costs): n.madd( "Store", - nodes[name] + f" {name} water tanks", - bus=nodes[name] + f" {name} water tanks", + nodes + f" {name} water tanks", + bus=nodes + f" {name} water tanks", e_cyclic=True, e_nom_extendable=True, carrier=name + " water tanks", @@ -1868,9 +1873,9 @@ def add_heat(n, costs): n.madd( "Link", - nodes[name] + f" {name} resistive heater", - bus0=nodes[name], - bus1=nodes[name] + f" {name} heat", + nodes + f" {name} resistive heater", + bus0=nodes, + bus1=nodes + f" {name} heat", carrier=name + " resistive heater", efficiency=costs.at[key, "efficiency"], capital_cost=costs.at[key, "efficiency"] * costs.at[key, "fixed"], @@ -1883,10 +1888,10 @@ def add_heat(n, costs): n.madd( "Link", - nodes[name] + f" {name} gas boiler", + nodes + f" {name} gas boiler", p_nom_extendable=True, - bus0=spatial.gas.df.loc[nodes[name], "nodes"].values, - bus1=nodes[name] + f" {name} heat", + bus0=spatial.gas.df.loc[nodes, "nodes"].values, + bus1=nodes + f" {name} heat", bus2="co2 atmosphere", carrier=name + " gas boiler", efficiency=costs.at[key, "efficiency"], @@ -1900,13 +1905,13 @@ def add_heat(n, costs): n.madd( "Generator", - nodes[name], + nodes, suffix=f" {name} solar thermal collector", - bus=nodes[name] + f" {name} heat", + bus=nodes + f" {name} heat", carrier=name + " solar thermal", p_nom_extendable=True, capital_cost=costs.at[name_type + " solar thermal", "fixed"], - p_max_pu=solar_thermal[nodes[name]], + p_max_pu=solar_thermal[nodes], lifetime=costs.at[name_type + " solar thermal", "lifetime"], ) @@ -1914,10 +1919,10 @@ def add_heat(n, costs): # add gas CHP; biomass CHP is added in biomass section n.madd( "Link", - nodes[name] + " urban central gas CHP", - bus0=spatial.gas.df.loc[nodes[name], "nodes"].values, - bus1=nodes[name], - bus2=nodes[name] + " urban central heat", + nodes + " urban central gas CHP", + bus0=spatial.gas.df.loc[nodes, "nodes"].values, + bus1=nodes, + bus2=nodes + " urban central heat", bus3="co2 atmosphere", carrier="urban central gas CHP", p_nom_extendable=True, @@ -1933,12 +1938,12 @@ def add_heat(n, costs): n.madd( "Link", - nodes[name] + " urban central gas CHP CC", - bus0=spatial.gas.df.loc[nodes[name], "nodes"].values, - bus1=nodes[name], - bus2=nodes[name] + " urban central heat", + nodes + " urban central gas CHP CC", + bus0=spatial.gas.df.loc[nodes, "nodes"].values, + bus1=nodes, + bus2=nodes + " urban central heat", bus3="co2 atmosphere", - bus4=spatial.co2.df.loc[nodes[name], "nodes"].values, + bus4=spatial.co2.df.loc[nodes, "nodes"].values, carrier="urban central gas CHP CC", p_nom_extendable=True, capital_cost=costs.at["central gas CHP", "fixed"] @@ -1970,11 +1975,11 @@ def add_heat(n, costs): if options["chp"] and options["micro_chp"] and name != "urban central": n.madd( "Link", - nodes[name] + f" {name} micro gas CHP", + nodes + f" {name} micro gas CHP", p_nom_extendable=True, - bus0=spatial.gas.df.loc[nodes[name], "nodes"].values, - bus1=nodes[name], - bus2=nodes[name] + f" {name} heat", + bus0=spatial.gas.df.loc[nodes, "nodes"].values, + bus1=nodes, + bus2=nodes + f" {name} heat", bus3="co2 atmosphere", carrier=name + " micro gas CHP", efficiency=costs.at["micro CHP", "efficiency"], @@ -2105,50 +2110,6 @@ def add_heat(n, costs): ) -def create_nodes_for_heat_sector(): - # TODO pop_layout - - # rural are areas with low heating density and individual heating - # urban are areas with high heating density - # urban can be split into district heating (central) and individual heating (decentral) - - ct_urban = pop_layout.urban.groupby(pop_layout.ct).sum() - # distribution of urban population within a country - pop_layout["urban_ct_fraction"] = pop_layout.urban / pop_layout.ct.map(ct_urban.get) - - sectors = ["residential", "services"] - - nodes = {} - urban_fraction = pop_layout.urban / pop_layout[["rural", "urban"]].sum(axis=1) - - for sector in sectors: - nodes[sector + " rural"] = pop_layout.index - nodes[sector + " urban decentral"] = pop_layout.index - - district_heat_share = pop_weighted_energy_totals["district heat share"] - - # maximum potential of urban demand covered by district heating - central_fraction = options["district_heating"]["potential"] - # district heating share at each node - dist_fraction_node = ( - district_heat_share * pop_layout["urban_ct_fraction"] / pop_layout["fraction"] - ) - nodes["urban central"] = dist_fraction_node.index - # if district heating share larger than urban fraction -> set urban - # fraction to district heating share - urban_fraction = pd.concat([urban_fraction, dist_fraction_node], axis=1).max(axis=1) - # difference of max potential and today's share of district heating - diff = (urban_fraction * central_fraction) - dist_fraction_node - progress = get(options["district_heating"]["progress"], investment_year) - dist_fraction_node += diff * progress - logger.info( - f"Increase district heating share by a progress factor of {progress:.2%} " - f"resulting in new average share of {dist_fraction_node.mean():.2%}" - ) - - return nodes, dist_fraction_node, urban_fraction - - def add_biomass(n, costs): logger.info("Add biomass") @@ -2366,7 +2327,7 @@ def add_biomass(n, costs): if options["biomass_boiler"]: # TODO: Add surcharge for pellets - nodes_heat = create_nodes_for_heat_sector()[0] + nodes = pop_layout.index for name in [ "residential rural", "services rural", @@ -2375,10 +2336,10 @@ def add_biomass(n, costs): ]: n.madd( "Link", - nodes_heat[name] + f" {name} biomass boiler", + nodes + f" {name} biomass boiler", p_nom_extendable=True, - bus0=spatial.biomass.df.loc[nodes_heat[name], "nodes"].values, - bus1=nodes_heat[name] + f" {name} heat", + bus0=spatial.biomass.df.loc[nodes, "nodes"].values, + bus1=nodes + f" {name} heat", carrier=name + " biomass boiler", efficiency=costs.at["biomass boiler", "efficiency"], capital_cost=costs.at["biomass boiler", "efficiency"] @@ -2821,7 +2782,7 @@ def add_industry(n, costs): ) if options["oil_boilers"]: - nodes_heat = create_nodes_for_heat_sector()[0] + nodes = pop_layout.index for name in [ "residential rural", @@ -2831,10 +2792,10 @@ def add_industry(n, costs): ]: n.madd( "Link", - nodes_heat[name] + f" {name} oil boiler", + nodes + f" {name} oil boiler", p_nom_extendable=True, bus0=spatial.oil.nodes, - bus1=nodes_heat[name] + f" {name} heat", + bus1=nodes + f" {name} heat", bus2="co2 atmosphere", carrier=f"{name} oil boiler", efficiency=costs.at["decentral oil boiler", "efficiency"], From 9897cd6f0535fdbef82b66816c844a9f0ebf10b5 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Fri, 19 Jan 2024 16:24:39 +0100 Subject: [PATCH 164/591] only add district heating (DH) for nodes with non-zero DH share --- scripts/prepare_sector_network.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 8d56ae6b..0bf9848b 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1718,11 +1718,15 @@ def add_heat(n, costs): # 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2 solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3 - nodes = pop_layout.index for name in heat_systems: name_type = "central" if name == "urban central" else "decentral" + if name == "urban central": + nodes = dist_fraction.index[dist_fraction > 0] + else: + nodes = pop_layout.index + n.add("Carrier", name + " heat") n.madd( From d98ad95332a8f9c81c06d5a42c426fd0b4be921a Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Fri, 19 Jan 2024 18:42:49 +0100 Subject: [PATCH 165/591] move building of distribution of existing heating to own script This makes the distribution of existing heating to urban/rural, residential/services and spatially more transparent. --- rules/solve_myopic.smk | 37 ++++- scripts/add_existing_baseyear.py | 136 ++++-------------- .../build_existing_heating_distribution.py | 108 ++++++++++++++ 3 files changed, 172 insertions(+), 109 deletions(-) create mode 100644 scripts/build_existing_heating_distribution.py diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 7ca8857d..20043286 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -1,8 +1,40 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-4 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT +rule build_existing_heating_distribution: + params: + baseyear=config["scenario"]["planning_horizons"][0], + sector=config["sector"], + existing_capacities=config["existing_capacities"], + input: + existing_heating="data/existing_infrastructure/existing_heating_raw.csv", + clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", + clustered_pop_energy_layout=RESOURCES + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv", + district_heat_share=RESOURCES + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + output: + existing_heating_distribution=RESOURCES + + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + wildcard_constraints: + planning_horizons=config["scenario"]["planning_horizons"][0], #only applies to baseyear + threads: 1 + resources: + mem_mb=2000, + log: + LOGS + + "build_existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.log", + benchmark: + ( + BENCHMARKS + + "build_existing_heating_distribution/elec_s{simpl}_{clusters}_{planning_horizons}" + ) + conda: + "../envs/environment.yaml" + script: + "../scripts/build_existing_heating_distribution.py" + + rule add_existing_baseyear: params: baseyear=config["scenario"]["planning_horizons"][0], @@ -19,7 +51,8 @@ rule add_existing_baseyear: costs="data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), cop_soil_total=RESOURCES + "cop_soil_total_elec_s{simpl}_{clusters}.nc", cop_air_total=RESOURCES + "cop_air_total_elec_s{simpl}_{clusters}.nc", - existing_heating="data/existing_infrastructure/existing_heating_raw.csv", + existing_heating_distribution=RESOURCES + + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv", existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", existing_offwind="data/existing_infrastructure/offwind_capacity_IRENA.csv", diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index c8486758..01d54cc2 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -409,97 +409,20 @@ def add_heating_capacities_installed_before_baseyear( # file: "WP2_DataAnnex_1_BuildingTechs_ForPublication_201603.xls" -> "existing_heating_raw.csv". # TODO start from original file - # retrieve existing heating capacities - techs = [ - "gas boiler", - "oil boiler", - "resistive heater", - "air heat pump", - "ground heat pump", - ] - df = pd.read_csv(snakemake.input.existing_heating, index_col=0, header=0) + existing_heating = pd.read_csv(snakemake.input.existing_heating_distribution, + header=[0,1], + index_col=0) - # data for Albania, Montenegro and Macedonia not included in database - df.loc["Albania"] = np.nan - df.loc["Montenegro"] = np.nan - df.loc["Macedonia"] = np.nan - df.fillna(0.0, inplace=True) + techs = existing_heating.columns.get_level_values(1).unique() - # convert GW to MW - df *= 1e3 + for name in existing_heating.columns.get_level_values(0).unique(): - df.index = cc.convert(df.index, to="iso2") - - # coal and oil boilers are assimilated to oil boilers - df["oil boiler"] = df["oil boiler"] + df["coal boiler"] - df.drop(["coal boiler"], axis=1, inplace=True) - - # distribute technologies to nodes by population - pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) - - nodal_df = df.loc[pop_layout.ct] - nodal_df.index = pop_layout.index - nodal_df = nodal_df.multiply(pop_layout.fraction, axis=0) - - # split existing capacities between residential and services - # proportional to energy demand - p_set_sum = n.loads_t.p_set.sum() - ratio_residential = pd.Series( - [ - ( - p_set_sum[f"{node} residential rural heat"] - / ( - p_set_sum[f"{node} residential rural heat"] - + p_set_sum[f"{node} services rural heat"] - ) - ) - # if rural heating demand for one of the nodes doesn't exist, - # then columns were dropped before and heating demand share should be 0.0 - if all( - f"{node} {service} rural heat" in p_set_sum.index - for service in ["residential", "services"] - ) - else 0.0 - for node in nodal_df.index - ], - index=nodal_df.index, - ) - - for tech in techs: - nodal_df["residential " + tech] = nodal_df[tech] * ratio_residential - nodal_df["services " + tech] = nodal_df[tech] * (1 - ratio_residential) - - names = [ - "residential rural", - "services rural", - "residential urban decentral", - "services urban decentral", - "urban central", - ] - - nodes = {} - p_nom = {} - for name in names: name_type = "central" if name == "urban central" else "decentral" - nodes[name] = pd.Index( - [ - n.buses.at[index, "location"] - for index in n.buses.index[ - n.buses.index.str.contains(name) - & n.buses.index.str.contains("heat") - ] - ] - ) - heat_pump_type = "air" if "urban" in name else "ground" - heat_type = "residential" if "residential" in name else "services" - if name == "urban central": - p_nom[name] = nodal_df["air heat pump"][nodes[name]] - else: - p_nom[name] = nodal_df[f"{heat_type} {heat_pump_type} heat pump"][ - nodes[name] - ] + nodes = pd.Index(n.buses.location[n.buses.index.str.contains(f"{name} heat")]) + + heat_pump_type = "air" if "urban" in name else "ground" # Add heat pumps costs_name = f"decentral {heat_pump_type}-sourced heat pump" @@ -507,7 +430,7 @@ def add_heating_capacities_installed_before_baseyear( cop = {"air": ashp_cop, "ground": gshp_cop} if time_dep_hp_cop: - efficiency = cop[heat_pump_type][nodes[name]] + efficiency = cop[heat_pump_type][nodes] else: efficiency = costs.at[costs_name, "efficiency"] @@ -520,27 +443,26 @@ def add_heating_capacities_installed_before_baseyear( n.madd( "Link", - nodes[name], + nodes, suffix=f" {name} {heat_pump_type} heat pump-{grouping_year}", - bus0=nodes[name], - bus1=nodes[name] + " " + name + " heat", + bus0=nodes, + bus1=nodes + " " + 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=p_nom[name] * ratio / costs.at[costs_name, "efficiency"], + p_nom=existing_heating[(name, f"{heat_pump_type} heat pump")][nodes] * ratio / costs.at[costs_name, "efficiency"], build_year=int(grouping_year), lifetime=costs.at[costs_name, "lifetime"], ) # add resistive heater, gas boilers and oil boilers - # (50% capacities to rural buses, 50% to urban buses) n.madd( "Link", - nodes[name], + nodes, suffix=f" {name} resistive heater-{grouping_year}", - bus0=nodes[name], - bus1=nodes[name] + " " + name + " heat", + bus0=nodes, + bus1=nodes + " " + name + " heat", carrier=name + " resistive heater", efficiency=costs.at[f"{name_type} resistive heater", "efficiency"], capital_cost=( @@ -548,21 +470,20 @@ def add_heating_capacities_installed_before_baseyear( * costs.at[f"{name_type} resistive heater", "fixed"] ), p_nom=( - 0.5 - * nodal_df[f"{heat_type} resistive heater"][nodes[name]] + existing_heating[(name, "resistive heater")][nodes] * ratio / costs.at[f"{name_type} resistive heater", "efficiency"] ), build_year=int(grouping_year), - lifetime=costs.at[costs_name, "lifetime"], + lifetime=costs.at[f"{name_type} resistive heater", "lifetime"], ) n.madd( "Link", - nodes[name], + nodes, suffix=f" {name} gas boiler-{grouping_year}", bus0=spatial.gas.nodes, - bus1=nodes[name] + " " + name + " heat", + bus1=nodes + " " + name + " heat", bus2="co2 atmosphere", carrier=name + " gas boiler", efficiency=costs.at[f"{name_type} gas boiler", "efficiency"], @@ -572,8 +493,7 @@ def add_heating_capacities_installed_before_baseyear( * costs.at[f"{name_type} gas boiler", "fixed"] ), p_nom=( - 0.5 - * nodal_df[f"{heat_type} gas boiler"][nodes[name]] + existing_heating[(name, "gas boiler")][nodes] * ratio / costs.at[f"{name_type} gas boiler", "efficiency"] ), @@ -583,20 +503,20 @@ def add_heating_capacities_installed_before_baseyear( n.madd( "Link", - nodes[name], + nodes, suffix=f" {name} oil boiler-{grouping_year}", bus0=spatial.oil.nodes, - bus1=nodes[name] + " " + name + " heat", + bus1=nodes + " " + name + " heat", bus2="co2 atmosphere", carrier=name + " oil boiler", efficiency=costs.at["decentral oil boiler", "efficiency"], efficiency2=costs.at["oil", "CO2 intensity"], capital_cost=costs.at["decentral oil boiler", "efficiency"] * costs.at["decentral oil boiler", "fixed"], - p_nom=0.5 - * nodal_df[f"{heat_type} oil boiler"][nodes[name]] - * ratio - / costs.at["decentral oil boiler", "efficiency"], + p_nom= ( + existing_heating[(name, "oil boiler")][nodes] + * ratio + / costs.at["decentral oil boiler", "efficiency"]), build_year=int(grouping_year), lifetime=costs.at[f"{name_type} gas boiler", "lifetime"], ) @@ -624,6 +544,8 @@ def add_heating_capacities_installed_before_baseyear( # drop assets which are at the end of their lifetime links_i = n.links[(n.links.build_year + n.links.lifetime <= baseyear)].index + logger.info("Removing following links because at end of their lifetime:") + logger.info(links_i) n.mremove("Link", links_i) diff --git a/scripts/build_existing_heating_distribution.py b/scripts/build_existing_heating_distribution.py new file mode 100644 index 00000000..fe282d39 --- /dev/null +++ b/scripts/build_existing_heating_distribution.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Builds table of existing heat generation capacities for initial planning +horizon. +""" +import pandas as pd +import sys +from pypsa.descriptors import Dict +import numpy as np +import country_converter as coco + +cc = coco.CountryConverter() + + +def build_existing_heating(): + # retrieve existing heating capacities + techs = [ + "gas boiler", + "oil boiler", + "resistive heater", + "air heat pump", + "ground heat pump", + ] + + existing_heating = pd.read_csv(snakemake.input.existing_heating, + index_col=0, + header=0) + + # data for Albania, Montenegro and Macedonia not included in database existing_heating.loc["Albania"] = np.nan + existing_heating.loc["Montenegro"] = np.nan + existing_heating.loc["Macedonia"] = np.nan + + existing_heating.fillna(0.0, inplace=True) + + # convert GW to MW + existing_heating *= 1e3 + + existing_heating.index = cc.convert(existing_heating.index, to="iso2") + + # coal and oil boilers are assimilated to oil boilers + existing_heating["oil boiler"] = existing_heating["oil boiler"] + existing_heating["coal boiler"] + existing_heating.drop(["coal boiler"], axis=1, inplace=True) + + # distribute technologies to nodes by population + pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, + index_col=0) + + nodal_heating = existing_heating.loc[pop_layout.ct] + nodal_heating.index = pop_layout.index + nodal_heating = nodal_heating.multiply(pop_layout.fraction, axis=0) + + district_heat_info = pd.read_csv(snakemake.input.district_heat_share, + index_col=0) + dist_fraction = district_heat_info["district fraction of node"] + urban_fraction = district_heat_info["urban fraction"] + + energy_layout = pd.read_csv(snakemake.input.clustered_pop_energy_layout, + index_col=0) + + uses = ["space", "water"] + sectors = ["residential", "services"] + + nodal_sectoral_totals = pd.DataFrame(dtype=float) + + for sector in sectors: + nodal_sectoral_totals[sector] = energy_layout[[f"total {sector} {use}" for use in uses]].sum(axis=1) + + nodal_sectoral_fraction = nodal_sectoral_totals.div(nodal_sectoral_totals.sum(axis=1), + axis=0) + + + nodal_heat_name_fraction = pd.DataFrame(dtype=float) + + nodal_heat_name_fraction["urban central"] = dist_fraction + + for sector in sectors: + + nodal_heat_name_fraction[f"{sector} rural"] = nodal_sectoral_fraction[sector]*(1 - urban_fraction) + nodal_heat_name_fraction[f"{sector} urban decentral"] = nodal_sectoral_fraction[sector]*(urban_fraction - dist_fraction) + + + nodal_heat_name_tech = pd.concat({name : nodal_heating .multiply(nodal_heat_name_fraction[name], + axis=0) for name in nodal_heat_name_fraction.columns}, + axis=1, + names=["heat name","technology"]) + + + #move all ground HPs to rural, all air to urban + + for sector in sectors: + nodal_heat_name_tech[(f"{sector} rural","ground heat pump")] += (nodal_heat_name_tech[("urban central","ground heat pump")]*nodal_sectoral_fraction[sector] + + nodal_heat_name_tech[(f"{sector} urban decentral","ground heat pump")]) + nodal_heat_name_tech[(f"{sector} urban decentral","ground heat pump")] = 0. + + nodal_heat_name_tech[(f"{sector} urban decentral","air heat pump")] += nodal_heat_name_tech[(f"{sector} rural","air heat pump")] + nodal_heat_name_tech[(f"{sector} rural","air heat pump")] = 0. + + nodal_heat_name_tech[("urban central","ground heat pump")] = 0. + + nodal_heat_name_tech.to_csv(snakemake.output.existing_heating_distribution) + + +if __name__ == "__main__": + + build_existing_heating() From 2183e742b2b44a7caca47a525537f8e827e501e5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 09:18:26 +0100 Subject: [PATCH 166/591] add release notes, minor code improvements --- doc/release_notes.rst | 18 +++++++++++++++ doc/sector.rst | 20 ++++++++++++++-- rules/solve_overnight.smk | 7 +++--- scripts/add_existing_baseyear.py | 8 +++---- scripts/build_daily_heat_demand.py | 3 ++- scripts/build_district_heat_share.py | 15 ++++++------ scripts/build_energy_totals.py | 4 ++-- .../build_existing_heating_distribution.py | 23 ++++++++++--------- scripts/build_hourly_heat_demand.py | 18 +++++---------- scripts/prepare_sector_network.py | 2 +- 10 files changed, 75 insertions(+), 43 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index dc1a9dd1..56fee0d8 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -28,6 +28,24 @@ Upcoming Release * Cluster residential and services heat buses by default. Can be disabled with ``cluster_heat_buses: false``. +* Bugfix: Do not reduce district heat share when building population-weighted + energy statistics. Previously the district heating share was being multiplied + by the population weighting, reducing the DH share with multiple nodes. + +* Move building of daily heat profile to its own rule + :mod:`build_hourly_heat_demand` from :mod:`prepare_sector_network`. + +* In :mod:`build_energy_totals`, district heating shares are now reported in a + separate file. + +* Move calculation of district heating share to its own rule + :mod:`build_district_heat_share`. + +* Move building of distribution of existing heating to own rule + :mod:`build_existing_heating_distribution`. This makes the distribution of + existing heating to urban/rural, residential/services and spatially more + transparent. + PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/doc/sector.rst b/doc/sector.rst index 303e7ed2..411bfd57 100644 --- a/doc/sector.rst +++ b/doc/sector.rst @@ -20,6 +20,12 @@ Rule ``add_existing_baseyear`` .. automodule:: add_existing_baseyear +Rule ``build_existing_heating_distribution`` +============================================================================== + +.. automodule:: build_existing_heating_distribution + + Rule ``build_ammonia_production`` ============================================================================== @@ -60,10 +66,20 @@ Rule ``build_gas_network`` .. automodule:: build_gas_network -Rule ``build_heat_demand`` +Rule ``build_daily_heat_demand`` ============================================================================== -.. automodule:: build_heat_demand +.. automodule:: build_daily_heat_demand + +Rule ``build_hourly_heat_demand`` +============================================================================== + +.. automodule:: build_hourly_heat_demand + +Rule ``build_district_heat_share`` +============================================================================== + +.. automodule:: build_district_heat_share Rule ``build_industrial_distribution_key`` ============================================================================== diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index 39778162..47c86410 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -28,9 +28,10 @@ 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: + config["solving"]["solver_options"][ + config["solving"]["solver"]["options"] + ].get("threads", 4) resources: mem_mb=config["solving"]["mem"], walltime=config["solving"].get("walltime", "12:00:00"), diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 01d54cc2..d61ece85 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -451,7 +451,7 @@ def add_heating_capacities_installed_before_baseyear( efficiency=efficiency, capital_cost=costs.at[costs_name, "efficiency"] * costs.at[costs_name, "fixed"], - p_nom=existing_heating[(name, f"{heat_pump_type} heat pump")][nodes] * ratio / costs.at[costs_name, "efficiency"], + p_nom=existing_heating.loc[nodes, (name, f"{heat_pump_type} heat pump")] * ratio / costs.at[costs_name, "efficiency"], build_year=int(grouping_year), lifetime=costs.at[costs_name, "lifetime"], ) @@ -470,7 +470,7 @@ def add_heating_capacities_installed_before_baseyear( * costs.at[f"{name_type} resistive heater", "fixed"] ), p_nom=( - existing_heating[(name, "resistive heater")][nodes] + existing_heating.loc[nodes, (name, "resistive heater")] * ratio / costs.at[f"{name_type} resistive heater", "efficiency"] ), @@ -493,7 +493,7 @@ def add_heating_capacities_installed_before_baseyear( * costs.at[f"{name_type} gas boiler", "fixed"] ), p_nom=( - existing_heating[(name, "gas boiler")][nodes] + existing_heating.loc[nodes, (name, "gas boiler")] * ratio / costs.at[f"{name_type} gas boiler", "efficiency"] ), @@ -514,7 +514,7 @@ def add_heating_capacities_installed_before_baseyear( capital_cost=costs.at["decentral oil boiler", "efficiency"] * costs.at["decentral oil boiler", "fixed"], p_nom= ( - existing_heating[(name, "oil boiler")][nodes] + existing_heating.loc[nodes, (name, "oil boiler")] * ratio / costs.at["decentral oil boiler", "efficiency"]), build_year=int(grouping_year), diff --git a/scripts/build_daily_heat_demand.py b/scripts/build_daily_heat_demand.py index b983f125..e334b1b3 100644 --- a/scripts/build_daily_heat_demand.py +++ b/scripts/build_daily_heat_demand.py @@ -18,7 +18,8 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "build_heat_demands", + "build_daily_heat_demands", + scope="total", simpl="", clusters=48, ) diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index d521214d..996ed861 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ @@ -21,9 +21,10 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "build_heat_demands", + "build_district_heat_share", simpl="", clusters=48, + planning_horizons="2050", ) investment_year = int(snakemake.wildcards.planning_horizons[-4:]) @@ -68,10 +69,10 @@ if __name__ == "__main__": f"resulting in new average share of {dist_fraction_node.mean():.2%}" ) - df = pd.DataFrame(dtype=float) - - df["original district heat share"] = district_heat_share - df["district fraction of node"] = dist_fraction_node - df["urban fraction"] = urban_fraction + df = pd.DataFrame({ + "original district heat share": district_heat_share, + "district fraction of node": dist_fraction_node, + "urban fraction": urban_fraction + }, dtype=float) df.to_csv(snakemake.output.district_heat_share) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 306caf4d..08d5bef5 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -583,10 +583,10 @@ def build_district_heat_share(countries, idees): # Missing district heating share dh_share = pd.read_csv( snakemake.input.district_heat_share, index_col=0, usecols=[0, 1] - ) + ).div(100).squeeze() # make conservative assumption and take minimum from both data sets district_heat_share = pd.concat( - [district_heat_share, dh_share.reindex(index=district_heat_share.index) / 100], axis=1 + [district_heat_share, dh_share.reindex_like(district_heat_share)], axis=1 ).min(axis=1) district_heat_share.name = "district heat share" diff --git a/scripts/build_existing_heating_distribution.py b/scripts/build_existing_heating_distribution.py index fe282d39..443c5baa 100644 --- a/scripts/build_existing_heating_distribution.py +++ b/scripts/build_existing_heating_distribution.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ @@ -7,8 +7,6 @@ Builds table of existing heat generation capacities for initial planning horizon. """ import pandas as pd -import sys -from pypsa.descriptors import Dict import numpy as np import country_converter as coco @@ -17,19 +15,13 @@ cc = coco.CountryConverter() def build_existing_heating(): # retrieve existing heating capacities - techs = [ - "gas boiler", - "oil boiler", - "resistive heater", - "air heat pump", - "ground heat pump", - ] existing_heating = pd.read_csv(snakemake.input.existing_heating, index_col=0, header=0) - # data for Albania, Montenegro and Macedonia not included in database existing_heating.loc["Albania"] = np.nan + # data for Albania, Montenegro and Macedonia not included in database + existing_heating.loc["Albania"] = np.nan existing_heating.loc["Montenegro"] = np.nan existing_heating.loc["Macedonia"] = np.nan @@ -104,5 +96,14 @@ def build_existing_heating(): if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake( + "build_existing_heating_distribution", + simpl="", + clusters=48, + planning_horizons=2050, + ) build_existing_heating() diff --git a/scripts/build_hourly_heat_demand.py b/scripts/build_hourly_heat_demand.py index 94ad7266..2d1dee54 100644 --- a/scripts/build_hourly_heat_demand.py +++ b/scripts/build_hourly_heat_demand.py @@ -6,19 +6,19 @@ Build hourly heat demand time series from daily ones. """ -import pandas as pd -import xarray as xr -from _helpers import generate_periodic_profiles, update_config_with_sector_opts from itertools import product - +import pandas as pd +import xarray as xr +from _helpers import generate_periodic_profiles if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake snakemake = mock_snakemake( - "build_heat_demands", + "build_hourly_heat_demands", + scope="total", simpl="", clusters=48, ) @@ -58,12 +58,6 @@ if __name__ == "__main__": heat_demand.index.name="snapshots" - print(heat_demand) - - print(heat_demand.stack()) - - ds = heat_demand.stack().to_xarray()#xr.Dataset.from_dataframe(heat_demand) - - print(ds) + ds = heat_demand.stack().to_xarray() ds.to_netcdf(snakemake.output.heat_demand) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 0bf9848b..241f3c30 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1654,7 +1654,7 @@ def build_heat_demand(n): heat_demand[name] = ( heat_demand_shape[name] / heat_demand_shape[name].sum() ).multiply(pop_weighted_energy_totals[f"total {sector} {use}"]) * 1e6 - electric_heat_supply[f"{sector} {use}"] = ( + electric_heat_supply[name] = ( heat_demand_shape[name] / heat_demand_shape[name].sum() ).multiply(pop_weighted_energy_totals[f"electricity {sector} {use}"]) * 1e6 From d3cf329456056d02fcfcbabe175e6ff9a8e2bb0c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 09:28:51 +0100 Subject: [PATCH 167/591] correctly read number of solver threads in rule definition --- doc/release_notes.rst | 2 ++ rules/common.smk | 7 +++++++ rules/solve_electricity.smk | 2 +- rules/solve_myopic.smk | 2 +- rules/solve_overnight.smk | 5 +---- rules/solve_perfect.smk | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 56fee0d8..1a0013d5 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -46,6 +46,8 @@ Upcoming Release existing heating to urban/rural, residential/services and spatially more transparent. +* 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 20043286..8c46ed59 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -137,7 +137,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 47c86410..aa08b8c3 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -28,10 +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 9865a970893d9e515786f33c629b14f71645bf1e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 09:29:32 +0100 Subject: [PATCH 168/591] apply automated formatting --- rules/build_sector.smk | 11 +-- rules/solve_myopic.smk | 6 +- scripts/add_existing_baseyear.py | 17 ++-- scripts/build_district_heat_share.py | 31 ++++---- scripts/build_energy_totals.py | 21 ++--- .../build_existing_heating_distribution.py | 77 +++++++++++-------- scripts/build_hourly_heat_demand.py | 12 +-- scripts/prepare_sector_network.py | 12 +-- 8 files changed, 105 insertions(+), 82 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 14156268..a24f9f7d 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -710,8 +710,6 @@ rule build_transport_demand: "../scripts/build_transport_demand.py" - - rule build_district_heat_share: params: sector=config["sector"], @@ -719,7 +717,8 @@ rule build_district_heat_share: district_heat_share=RESOURCES + "district_heat_share.csv", clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", output: - district_heat_share=RESOURCES + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + district_heat_share=RESOURCES + + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", threads: 1 resources: mem_mb=1000, @@ -782,8 +781,10 @@ rule prepare_sector_network: simplified_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}.csv", industrial_demand=RESOURCES + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv", - hourly_heat_demand_total=RESOURCES + "hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc", - district_heat_share=RESOURCES + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + hourly_heat_demand_total=RESOURCES + + "hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc", + district_heat_share=RESOURCES + + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", temp_soil_total=RESOURCES + "temp_soil_total_elec_s{simpl}_{clusters}.nc", temp_soil_rural=RESOURCES + "temp_soil_rural_elec_s{simpl}_{clusters}.nc", temp_soil_urban=RESOURCES + "temp_soil_urban_elec_s{simpl}_{clusters}.nc", diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 8c46ed59..75334073 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -11,8 +11,10 @@ rule build_existing_heating_distribution: input: existing_heating="data/existing_infrastructure/existing_heating_raw.csv", clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", - clustered_pop_energy_layout=RESOURCES + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv", - district_heat_share=RESOURCES + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + clustered_pop_energy_layout=RESOURCES + + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv", + district_heat_share=RESOURCES + + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", output: existing_heating_distribution=RESOURCES + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv", diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index d61ece85..c67d5f8b 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -409,15 +409,13 @@ def add_heating_capacities_installed_before_baseyear( # file: "WP2_DataAnnex_1_BuildingTechs_ForPublication_201603.xls" -> "existing_heating_raw.csv". # TODO start from original file - existing_heating = pd.read_csv(snakemake.input.existing_heating_distribution, - header=[0,1], - index_col=0) - + existing_heating = pd.read_csv( + snakemake.input.existing_heating_distribution, header=[0, 1], index_col=0 + ) techs = existing_heating.columns.get_level_values(1).unique() for name in existing_heating.columns.get_level_values(0).unique(): - name_type = "central" if name == "urban central" else "decentral" nodes = pd.Index(n.buses.location[n.buses.index.str.contains(f"{name} heat")]) @@ -451,7 +449,9 @@ def add_heating_capacities_installed_before_baseyear( efficiency=efficiency, capital_cost=costs.at[costs_name, "efficiency"] * costs.at[costs_name, "fixed"], - p_nom=existing_heating.loc[nodes, (name, f"{heat_pump_type} heat pump")] * ratio / costs.at[costs_name, "efficiency"], + p_nom=existing_heating.loc[nodes, (name, f"{heat_pump_type} heat pump")] + * ratio + / costs.at[costs_name, "efficiency"], build_year=int(grouping_year), lifetime=costs.at[costs_name, "lifetime"], ) @@ -513,10 +513,11 @@ def add_heating_capacities_installed_before_baseyear( efficiency2=costs.at["oil", "CO2 intensity"], capital_cost=costs.at["decentral oil boiler", "efficiency"] * costs.at["decentral oil boiler", "fixed"], - p_nom= ( + p_nom=( existing_heating.loc[nodes, (name, "oil boiler")] * ratio - / costs.at["decentral oil boiler", "efficiency"]), + / costs.at["decentral oil boiler", "efficiency"] + ), build_year=int(grouping_year), lifetime=costs.at[f"{name_type} gas boiler", "lifetime"], ) diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index 996ed861..3353437a 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -6,12 +6,10 @@ Build district heat shares at each node, depending on investment year. """ -import pandas as pd - -from prepare_sector_network import get - import logging +import pandas as pd +from prepare_sector_network import get logger = logging.getLogger(__name__) @@ -29,11 +27,11 @@ if __name__ == "__main__": investment_year = int(snakemake.wildcards.planning_horizons[-4:]) - pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, - index_col=0) + pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) - district_heat_share = pd.read_csv(snakemake.input.district_heat_share, - index_col=0).squeeze() + district_heat_share = pd.read_csv( + snakemake.input.district_heat_share, index_col=0 + ).squeeze() # make ct-based share nodal district_heat_share = district_heat_share.loc[pop_layout.ct] @@ -62,17 +60,22 @@ if __name__ == "__main__": # difference of max potential and today's share of district heating diff = (urban_fraction * central_fraction) - dist_fraction_node - progress = get(snakemake.config["sector"]["district_heating"]["progress"], investment_year) + progress = get( + snakemake.config["sector"]["district_heating"]["progress"], investment_year + ) dist_fraction_node += diff * progress logger.info( f"Increase district heating share by a progress factor of {progress:.2%} " f"resulting in new average share of {dist_fraction_node.mean():.2%}" ) - df = pd.DataFrame({ - "original district heat share": district_heat_share, - "district fraction of node": dist_fraction_node, - "urban fraction": urban_fraction - }, dtype=float) + df = pd.DataFrame( + { + "original district heat share": district_heat_share, + "district fraction of node": dist_fraction_node, + "urban fraction": urban_fraction, + }, + dtype=float, + ) df.to_csv(snakemake.output.district_heat_share) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 08d5bef5..c67bb49d 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -569,21 +569,24 @@ def build_energy_totals(countries, eurostat, swiss, idees): def build_district_heat_share(countries, idees): - # district heating share - district_heat = idees[ - ["derived heat residential", "derived heat services"] - ].sum(axis=1) - total_heat = idees[["thermal uses residential", "thermal uses services"]].sum(axis=1) + district_heat = idees[["derived heat residential", "derived heat services"]].sum( + axis=1 + ) + total_heat = idees[["thermal uses residential", "thermal uses services"]].sum( + axis=1 + ) - district_heat_share = district_heat/total_heat + district_heat_share = district_heat / total_heat district_heat_share = district_heat_share.reindex(countries) # Missing district heating share - dh_share = pd.read_csv( - snakemake.input.district_heat_share, index_col=0, usecols=[0, 1] - ).div(100).squeeze() + dh_share = ( + pd.read_csv(snakemake.input.district_heat_share, index_col=0, usecols=[0, 1]) + .div(100) + .squeeze() + ) # make conservative assumption and take minimum from both data sets district_heat_share = pd.concat( [district_heat_share, dh_share.reindex_like(district_heat_share)], axis=1 diff --git a/scripts/build_existing_heating_distribution.py b/scripts/build_existing_heating_distribution.py index 443c5baa..67993c29 100644 --- a/scripts/build_existing_heating_distribution.py +++ b/scripts/build_existing_heating_distribution.py @@ -6,9 +6,9 @@ Builds table of existing heat generation capacities for initial planning horizon. """ -import pandas as pd -import numpy as np import country_converter as coco +import numpy as np +import pandas as pd cc = coco.CountryConverter() @@ -16,9 +16,9 @@ cc = coco.CountryConverter() def build_existing_heating(): # retrieve existing heating capacities - existing_heating = pd.read_csv(snakemake.input.existing_heating, - index_col=0, - header=0) + existing_heating = pd.read_csv( + snakemake.input.existing_heating, index_col=0, header=0 + ) # data for Albania, Montenegro and Macedonia not included in database existing_heating.loc["Albania"] = np.nan @@ -33,24 +33,25 @@ def build_existing_heating(): existing_heating.index = cc.convert(existing_heating.index, to="iso2") # coal and oil boilers are assimilated to oil boilers - existing_heating["oil boiler"] = existing_heating["oil boiler"] + existing_heating["coal boiler"] + existing_heating["oil boiler"] = ( + existing_heating["oil boiler"] + existing_heating["coal boiler"] + ) existing_heating.drop(["coal boiler"], axis=1, inplace=True) # distribute technologies to nodes by population - pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, - index_col=0) + pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) nodal_heating = existing_heating.loc[pop_layout.ct] nodal_heating.index = pop_layout.index nodal_heating = nodal_heating.multiply(pop_layout.fraction, axis=0) - district_heat_info = pd.read_csv(snakemake.input.district_heat_share, - index_col=0) + district_heat_info = pd.read_csv(snakemake.input.district_heat_share, index_col=0) dist_fraction = district_heat_info["district fraction of node"] urban_fraction = district_heat_info["urban fraction"] - energy_layout = pd.read_csv(snakemake.input.clustered_pop_energy_layout, - index_col=0) + energy_layout = pd.read_csv( + snakemake.input.clustered_pop_energy_layout, index_col=0 + ) uses = ["space", "water"] sectors = ["residential", "services"] @@ -58,39 +59,51 @@ def build_existing_heating(): nodal_sectoral_totals = pd.DataFrame(dtype=float) for sector in sectors: - nodal_sectoral_totals[sector] = energy_layout[[f"total {sector} {use}" for use in uses]].sum(axis=1) - - nodal_sectoral_fraction = nodal_sectoral_totals.div(nodal_sectoral_totals.sum(axis=1), - axis=0) + nodal_sectoral_totals[sector] = energy_layout[ + [f"total {sector} {use}" for use in uses] + ].sum(axis=1) + nodal_sectoral_fraction = nodal_sectoral_totals.div( + nodal_sectoral_totals.sum(axis=1), axis=0 + ) nodal_heat_name_fraction = pd.DataFrame(dtype=float) nodal_heat_name_fraction["urban central"] = dist_fraction for sector in sectors: + nodal_heat_name_fraction[f"{sector} rural"] = nodal_sectoral_fraction[ + sector + ] * (1 - urban_fraction) + nodal_heat_name_fraction[f"{sector} urban decentral"] = nodal_sectoral_fraction[ + sector + ] * (urban_fraction - dist_fraction) - nodal_heat_name_fraction[f"{sector} rural"] = nodal_sectoral_fraction[sector]*(1 - urban_fraction) - nodal_heat_name_fraction[f"{sector} urban decentral"] = nodal_sectoral_fraction[sector]*(urban_fraction - dist_fraction) + nodal_heat_name_tech = pd.concat( + { + name: nodal_heating.multiply(nodal_heat_name_fraction[name], axis=0) + for name in nodal_heat_name_fraction.columns + }, + axis=1, + names=["heat name", "technology"], + ) - - nodal_heat_name_tech = pd.concat({name : nodal_heating .multiply(nodal_heat_name_fraction[name], - axis=0) for name in nodal_heat_name_fraction.columns}, - axis=1, - names=["heat name","technology"]) - - - #move all ground HPs to rural, all air to urban + # move all ground HPs to rural, all air to urban for sector in sectors: - nodal_heat_name_tech[(f"{sector} rural","ground heat pump")] += (nodal_heat_name_tech[("urban central","ground heat pump")]*nodal_sectoral_fraction[sector] - + nodal_heat_name_tech[(f"{sector} urban decentral","ground heat pump")]) - nodal_heat_name_tech[(f"{sector} urban decentral","ground heat pump")] = 0. + nodal_heat_name_tech[(f"{sector} rural", "ground heat pump")] += ( + nodal_heat_name_tech[("urban central", "ground heat pump")] + * nodal_sectoral_fraction[sector] + + nodal_heat_name_tech[(f"{sector} urban decentral", "ground heat pump")] + ) + nodal_heat_name_tech[(f"{sector} urban decentral", "ground heat pump")] = 0.0 - nodal_heat_name_tech[(f"{sector} urban decentral","air heat pump")] += nodal_heat_name_tech[(f"{sector} rural","air heat pump")] - nodal_heat_name_tech[(f"{sector} rural","air heat pump")] = 0. + nodal_heat_name_tech[ + (f"{sector} urban decentral", "air heat pump") + ] += nodal_heat_name_tech[(f"{sector} rural", "air heat pump")] + nodal_heat_name_tech[(f"{sector} rural", "air heat pump")] = 0.0 - nodal_heat_name_tech[("urban central","ground heat pump")] = 0. + nodal_heat_name_tech[("urban central", "ground heat pump")] = 0.0 nodal_heat_name_tech.to_csv(snakemake.output.existing_heating_distribution) diff --git a/scripts/build_hourly_heat_demand.py b/scripts/build_hourly_heat_demand.py index 2d1dee54..c972da89 100644 --- a/scripts/build_hourly_heat_demand.py +++ b/scripts/build_hourly_heat_demand.py @@ -48,16 +48,16 @@ if __name__ == "__main__": ) if use == "space": - heat_demand[f"{sector} {use}"] = daily_space_heat_demand * intraday_year_profile + heat_demand[f"{sector} {use}"] = ( + daily_space_heat_demand * intraday_year_profile + ) else: heat_demand[f"{sector} {use}"] = intraday_year_profile - heat_demand = pd.concat(heat_demand, - axis=1, - names = ["sector use", "node"]) + heat_demand = pd.concat(heat_demand, axis=1, names=["sector use", "node"]) - heat_demand.index.name="snapshots" + heat_demand.index.name = "snapshots" - ds = heat_demand.stack().to_xarray() + ds = heat_demand.stack().to_xarray() ds.to_netcdf(snakemake.output.heat_demand) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 241f3c30..ba92e137 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1639,8 +1639,11 @@ def add_land_transport(n, costs): def build_heat_demand(n): - - heat_demand_shape = xr.open_dataset(snakemake.input.hourly_heat_demand_total).to_dataframe().unstack(level=1) + heat_demand_shape = ( + xr.open_dataset(snakemake.input.hourly_heat_demand_total) + .to_dataframe() + .unstack(level=1) + ) sectors = ["residential", "services"] uses = ["water", "space"] @@ -1648,7 +1651,6 @@ def build_heat_demand(n): heat_demand = {} electric_heat_supply = {} for sector, use in product(sectors, uses): - name = f"{sector} {use}" heat_demand[name] = ( @@ -1678,8 +1680,7 @@ def add_heat(n, costs): heat_demand = build_heat_demand(n) - district_heat_info = pd.read_csv(snakemake.input.district_heat_share, - index_col=0) + district_heat_info = pd.read_csv(snakemake.input.district_heat_share, index_col=0) dist_fraction = district_heat_info["district fraction of node"] urban_fraction = district_heat_info["urban fraction"] @@ -1718,7 +1719,6 @@ def add_heat(n, costs): # 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2 solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3 - for name in heat_systems: name_type = "central" if name == "urban central" else "decentral" From 31c7c10fc5e86702d47f9e2da7eb7dfd230e8b54 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 09:30:53 +0100 Subject: [PATCH 169/591] git-blame-ignore-revs: add automated formatting commit --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 0b78b5b6..53f63e71 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -6,3 +6,4 @@ 5d1ef8a64055a039aa4a0834d2d26fe7752fe9a0 92080b1cd2ca5f123158571481722767b99c2b27 13769f90af4500948b0376d57df4cceaa13e78b5 +9865a970893d9e515786f33c629b14f71645bf1e \ No newline at end of file From 757fbcc464c4c04b94d2a29cd325963f0a35aa8a 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 08:31:57 +0000 Subject: [PATCH 170/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .git-blame-ignore-revs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 53f63e71..3f1edbd8 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -6,4 +6,4 @@ 5d1ef8a64055a039aa4a0834d2d26fe7752fe9a0 92080b1cd2ca5f123158571481722767b99c2b27 13769f90af4500948b0376d57df4cceaa13e78b5 -9865a970893d9e515786f33c629b14f71645bf1e \ No newline at end of file +9865a970893d9e515786f33c629b14f71645bf1e From fd57311094f9ef86400e94121cb33e87b6abacbf Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 10:10:40 +0100 Subject: [PATCH 171/591] build_district_heat_share: make safe for single-country runs --- scripts/build_district_heat_share.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index 3353437a..6e934a2b 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -31,7 +31,7 @@ if __name__ == "__main__": district_heat_share = pd.read_csv( snakemake.input.district_heat_share, index_col=0 - ).squeeze() + )["district heat share"] # make ct-based share nodal district_heat_share = district_heat_share.loc[pop_layout.ct] From 025f48c0c2ba402f61f9cf2d0cf8c4656beae1ac 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 09:11:06 +0000 Subject: [PATCH 172/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/build_district_heat_share.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index 6e934a2b..86c42631 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -29,9 +29,9 @@ if __name__ == "__main__": pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) - district_heat_share = pd.read_csv( - snakemake.input.district_heat_share, index_col=0 - )["district heat share"] + district_heat_share = pd.read_csv(snakemake.input.district_heat_share, index_col=0)[ + "district heat share" + ] # make ct-based share nodal district_heat_share = district_heat_share.loc[pop_layout.ct] From a2315c289e8b264655eb4fab8afaf112d84d681b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 14:31:10 +0100 Subject: [PATCH 173/591] 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 174/591] 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 6c593a551b6f090b1066285061ec41f48c325d1c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 22 Jan 2024 18:07:33 +0100 Subject: [PATCH 175/591] build_hourly_heat_demand: only pass subset of snapshot config --- rules/build_sector.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index a24f9f7d..0586ec01 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -147,7 +147,7 @@ rule build_daily_heat_demand: rule build_hourly_heat_demand: params: - snapshots=config["snapshots"], + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, input: heat_profile="data/heat_load_profile_BDEW.csv", heat_demand=RESOURCES + "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc", 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 176/591] [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 177/591] 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 178/591] [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 179/591] 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 180/591] 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 181/591] 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 182/591] [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 183/591] 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 184/591] 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 185/591] 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 186/591] [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 187/591] 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 188/591] 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 189/591] 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 190/591] 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 191/591] 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 192/591] 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 193/591] 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." From 20f39971f77db4ec3b79a7dea7c419be14321446 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Wed, 24 Jan 2024 13:38:39 +0100 Subject: [PATCH 194/591] solve_network: make sure infeasibilities are printed properly Without this formatting, there is an error adding a string to a list. --- scripts/solve_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 9fc41555..23e9b0f8 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -926,7 +926,7 @@ def solve_network(n, config, solving, opts="", **kwargs): ) if "infeasible" in condition: labels = n.model.compute_infeasibilities() - logger.info("Labels:\n" + labels) + logger.info(f"Labels:\n{labels}") n.model.print_infeasibilities() raise RuntimeError("Solving status 'infeasible'") From 999ff852888f4c1fcab28796332cefc7d16f6272 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 25 Jan 2024 17:19:55 +0100 Subject: [PATCH 195/591] fix snakemake.inputs for add_existing_baseyear with perfect foresight --- rules/solve_perfect.smk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index ad310f9f..76051976 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -17,6 +17,8 @@ rule add_existing_baseyear: costs="data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), cop_soil_total=RESOURCES + "cop_soil_total_elec_s{simpl}_{clusters}.nc", cop_air_total=RESOURCES + "cop_air_total_elec_s{simpl}_{clusters}.nc", + existing_heating_distribution=RESOURCES + + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv", existing_heating="data/existing_infrastructure/existing_heating_raw.csv", existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", From bb202ad2c44558b01bf8d7cdaccaea97bf80cca2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 27 Aug 2023 17:05:54 +0200 Subject: [PATCH 196/591] plot_network: remove function plot_map_without() --- rules/postprocess.smk | 2 -- scripts/plot_network.py | 74 ----------------------------------------- 2 files changed, 76 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 9f4ac78e..5bbffeb8 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -20,8 +20,6 @@ if config["foresight"] != "perfect": output: map=RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", - today=RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}-today.pdf", threads: 2 resources: mem_mb=10000, diff --git a/scripts/plot_network.py b/scripts/plot_network.py index 13736d01..d951d2e7 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -671,79 +671,6 @@ def plot_ch4_map(network): ) -def plot_map_without(network): - n = network.copy() - assign_location(n) - - # 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": proj}) - - # PDF has minimum width, so set these to zero - line_lower_threshold = 200.0 - line_upper_threshold = 1e4 - linewidth_factor = 3e3 - ac_color = "rosybrown" - dc_color = "darkseagreen" - - # hack because impossible to drop buses... - if "EU gas" in n.buses.index: - eu_location = snakemake.params.plotting.get( - "eu_node_location", dict(x=-5.5, y=46) - ) - n.buses.loc["EU gas", "x"] = eu_location["x"] - n.buses.loc["EU gas", "y"] = eu_location["y"] - - to_drop = n.links.index[(n.links.carrier != "DC") & (n.links.carrier != "B2B")] - n.links.drop(to_drop, inplace=True) - - if snakemake.wildcards["ll"] == "v1.0": - line_widths = n.lines.s_nom - link_widths = n.links.p_nom - else: - line_widths = n.lines.s_nom_min - link_widths = n.links.p_nom_min - - line_widths = line_widths.clip(line_lower_threshold, line_upper_threshold) - link_widths = link_widths.clip(line_lower_threshold, line_upper_threshold) - - line_widths = line_widths.replace(line_lower_threshold, 0) - link_widths = link_widths.replace(line_lower_threshold, 0) - - n.plot( - bus_colors="k", - line_colors=ac_color, - link_colors=dc_color, - line_widths=line_widths / linewidth_factor, - link_widths=link_widths / linewidth_factor, - ax=ax, - **map_opts, - ) - - handles = [] - labels = [] - - for s in (10, 5): - handles.append( - plt.Line2D([0], [0], color=ac_color, linewidth=s * 1e3 / linewidth_factor) - ) - labels.append(f"{s} GW") - l1_1 = ax.legend( - handles, - labels, - loc="upper left", - bbox_to_anchor=(0.05, 1.01), - frameon=False, - labelspacing=0.8, - handletextpad=1.5, - title="Today's transmission", - ) - ax.add_artist(l1_1) - - fig.savefig(snakemake.output.today, transparent=True, bbox_inches="tight") - - def plot_series(network, carrier="AC", name="test"): n = network.copy() assign_location(n) @@ -1101,7 +1028,6 @@ if __name__ == "__main__": plot_h2_map(n, regions) plot_ch4_map(n) - plot_map_without(n) # plot_series(n, carrier="AC", name=suffix) # plot_series(n, carrier="heat", name=suffix) From 46a2f55c1bbebe9a491bea76f9805e363cdd6b5c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 27 Aug 2023 17:10:41 +0200 Subject: [PATCH 197/591] plot_network: remove function plot_series() This function is superseded by plot_balance_timeseries rule. --- scripts/plot_network.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/plot_network.py b/scripts/plot_network.py index d951d2e7..dde7d61b 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -671,6 +671,7 @@ def plot_ch4_map(network): ) +<<<<<<< HEAD def plot_series(network, carrier="AC", name="test"): n = network.copy() assign_location(n) @@ -984,6 +985,8 @@ def plot_map_perfect( ) +======= +>>>>>>> ead390b4 (plot_network: remove function plot_series()) if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -1028,6 +1031,3 @@ if __name__ == "__main__": plot_h2_map(n, regions) plot_ch4_map(n) - - # plot_series(n, carrier="AC", name=suffix) - # plot_series(n, carrier="heat", name=suffix) From ce4d18c8616917165d3716e9543b42667d82c44c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 25 Jan 2024 17:32:17 +0100 Subject: [PATCH 198/591] remove plot_series() leftovers --- scripts/plot_network.py | 164 ---------------------------------------- 1 file changed, 164 deletions(-) diff --git a/scripts/plot_network.py b/scripts/plot_network.py index dde7d61b..b06e5ce2 100644 --- a/scripts/plot_network.py +++ b/scripts/plot_network.py @@ -671,168 +671,6 @@ def plot_ch4_map(network): ) -<<<<<<< HEAD -def plot_series(network, carrier="AC", name="test"): - n = network.copy() - assign_location(n) - assign_carriers(n) - - buses = n.buses.index[n.buses.carrier.str.contains(carrier)] - - supply = pd.DataFrame(index=n.snapshots) - for c in n.iterate_components(n.branch_components): - n_port = 4 if c.name == "Link" else 2 - for i in range(n_port): - supply = pd.concat( - ( - supply, - ( - -1 - * c.pnl[f"p{str(i)}"] - .loc[:, c.df.index[c.df[f"bus{str(i)}"].isin(buses)]] - .groupby(c.df.carrier, axis=1) - .sum() - ), - ), - axis=1, - ) - - for c in n.iterate_components(n.one_port_components): - comps = c.df.index[c.df.bus.isin(buses)] - supply = pd.concat( - ( - supply, - ((c.pnl["p"].loc[:, comps]).multiply(c.df.loc[comps, "sign"])) - .groupby(c.df.carrier, axis=1) - .sum(), - ), - axis=1, - ) - - supply = supply.groupby(rename_techs_tyndp, axis=1).sum() - - both = supply.columns[(supply < 0.0).any() & (supply > 0.0).any()] - - positive_supply = supply[both] - negative_supply = supply[both] - - positive_supply[positive_supply < 0.0] = 0.0 - negative_supply[negative_supply > 0.0] = 0.0 - - supply[both] = positive_supply - - suffix = " charging" - - negative_supply.columns = negative_supply.columns + suffix - - supply = pd.concat((supply, negative_supply), axis=1) - - # 14-21.2 for flaute - # 19-26.1 for flaute - - start = "2013-02-19" - stop = "2013-02-26" - - threshold = 10e3 - - to_drop = supply.columns[(abs(supply) < threshold).all()] - - if len(to_drop) != 0: - logger.info(f"Dropping {to_drop.tolist()} from supply") - supply.drop(columns=to_drop, inplace=True) - - supply.index.name = None - - supply = supply / 1e3 - - supply.rename( - columns={"electricity": "electric demand", "heat": "heat demand"}, inplace=True - ) - supply.columns = supply.columns.str.replace("residential ", "") - supply.columns = supply.columns.str.replace("services ", "") - supply.columns = supply.columns.str.replace("urban decentral ", "decentral ") - - preferred_order = pd.Index( - [ - "electric demand", - "transmission lines", - "hydroelectricity", - "hydro reservoir", - "run of river", - "pumped hydro storage", - "CHP", - "onshore wind", - "offshore wind", - "solar PV", - "solar thermal", - "building retrofitting", - "ground heat pump", - "air heat pump", - "resistive heater", - "OCGT", - "gas boiler", - "gas", - "natural gas", - "methanation", - "hydrogen storage", - "battery storage", - "hot water storage", - ] - ) - - new_columns = preferred_order.intersection(supply.columns).append( - supply.columns.difference(preferred_order) - ) - - supply = supply.groupby(supply.columns, axis=1).sum() - fig, ax = plt.subplots() - fig.set_size_inches((8, 5)) - - ( - supply.loc[start:stop, new_columns].plot( - ax=ax, - kind="area", - stacked=True, - linewidth=0.0, - color=[ - snakemake.params.plotting["tech_colors"][i.replace(suffix, "")] - for i in new_columns - ], - ) - ) - - handles, labels = ax.get_legend_handles_labels() - - handles.reverse() - labels.reverse() - - new_handles = [] - new_labels = [] - - for i, item in enumerate(labels): - if "charging" not in item: - new_handles.append(handles[i]) - new_labels.append(labels[i]) - - ax.legend(new_handles, new_labels, ncol=3, loc="upper left", frameon=False) - ax.set_xlim([start, stop]) - ax.set_ylim([-1300, 1900]) - ax.grid(True) - ax.set_ylabel("Power [GW]") - fig.tight_layout() - - fig.savefig( - "results/{}maps/series-{}-{}-{}-{}.pdf".format( - snakemake.params.RDIR, - snakemake.wildcards["ll"], - carrier, - start, - stop, - ), - transparent=True, - ) - - def plot_map_perfect( network, components=["Link", "Store", "StorageUnit", "Generator"], @@ -985,8 +823,6 @@ def plot_map_perfect( ) -======= ->>>>>>> ead390b4 (plot_network: remove function plot_series()) if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake From ffd4e1f1af716dbd790e26da014366758b6188e5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 25 Jan 2024 20:34:59 +0100 Subject: [PATCH 199/591] plot_network: split into separate scripts for power, hydrogen, gas --- doc/plotting.rst | 21 +- doc/release_notes.rst | 6 + rules/collect.smk | 10 - rules/postprocess.smk | 87 ++- scripts/plot_gas_network.py | 251 ++++++++ scripts/plot_hydrogen_network.py | 267 ++++++++ scripts/plot_network.py | 869 -------------------------- scripts/plot_power_network.py | 271 ++++++++ scripts/plot_power_network_perfect.py | 199 ++++++ 9 files changed, 1086 insertions(+), 895 deletions(-) create mode 100644 scripts/plot_gas_network.py create mode 100644 scripts/plot_hydrogen_network.py delete mode 100644 scripts/plot_network.py create mode 100644 scripts/plot_power_network.py create mode 100644 scripts/plot_power_network_perfect.py diff --git a/doc/plotting.rst b/doc/plotting.rst index 895eab3b..02748cf2 100644 --- a/doc/plotting.rst +++ b/doc/plotting.rst @@ -22,7 +22,22 @@ Rule ``plot_summary`` .. _map_plot: -Rule ``plot_network`` -======================== +Rule ``plot_power_network`` +=========================== -.. automodule:: plot_network +.. automodule:: plot_power_network + +Rule ``plot_power_network_perfect`` +=================================== + +.. automodule:: plot_power_network_perfect + +Rule ``plot_hydrogen_network`` +============================== + +.. automodule:: plot_hydrogen_network + +Rule ``plot_gas_network`` +========================= + +.. automodule:: plot_gas_network diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 93d1a268..5bcaf0d2 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -37,6 +37,12 @@ Upcoming Release * Add the option to customise map projection in plotting config. +* The rule ``plot_network`` has been split into separate rules for plotting + electricity, hydrogen and gas networks. + +* Added new collection rule ``plot_all`` which should be used instead of + ``plot_summary``. This allows running the rule :mod:`make_summary` and + :mod:`plot_summary` even if the network plotting rules fail. PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/rules/collect.smk b/rules/collect.smk index c9bb10ea..1d977da1 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -11,7 +11,6 @@ localrules: prepare_sector_networks, solve_elec_networks, solve_sector_networks, - plot_networks, rule cluster_networks: @@ -69,15 +68,6 @@ rule solve_sector_networks_perfect: ), -rule plot_networks: - input: - expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", - **config["scenario"] - ), - - rule validate_elec_networks: input: expand( diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 5bbffeb8..6db3079a 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT @@ -9,9 +9,8 @@ localrules: if config["foresight"] != "perfect": - rule plot_network: + rule plot_power_network: params: - foresight=config["foresight"], plotting=config["plotting"], input: network=RESULTS @@ -26,19 +25,66 @@ if config["foresight"] != "perfect": benchmark: ( BENCHMARKS - + "plot_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" script: - "../scripts/plot_network.py" + "../scripts/plot_power_network.py" + + + rule plot_hydrogen_network: + params: + plotting=config["plotting"], + input: + network=RESULTS + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + regions=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + output: + map=RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", + threads: 2 + resources: + mem_mb=10000, + benchmark: + ( + BENCHMARKS + + "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) + conda: + "../envs/environment.yaml" + script: + "../scripts/plot_hydrogen_network.py" + + + rule plot_gas_network: + params: + plotting=config["plotting"], + input: + network=RESULTS + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + regions=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + output: + map=RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", + threads: 2 + resources: + mem_mb=10000, + benchmark: + ( + BENCHMARKS + + "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) + conda: + "../envs/environment.yaml" + script: + "../scripts/plot_gas_network.py" if config["foresight"] == "perfect": - rule plot_network: + rule plot_power_network_perfect: params: - foresight=config["foresight"], plotting=config["plotting"], input: network=RESULTS @@ -60,7 +106,7 @@ if config["foresight"] == "perfect": conda: "../envs/environment.yaml" script: - "../scripts/plot_network.py" + "../scripts/plot_power_network_perfect.py" rule copy_config: @@ -95,11 +141,6 @@ rule make_summary: costs="data/costs_{}.csv".format(config["costs"]["year"]) if config["foresight"] == "overnight" else "data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), - plots=expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", - **config["scenario"] - ), output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", nodal_capacities=RESULTS + "csvs/nodal_capacities.csv", @@ -161,6 +202,26 @@ rule plot_summary: "../scripts/plot_summary.py" +rule plot_all: + input: + RESULTS + "graphs/costs.pdf", + expand( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", + **config["scenario"] + ), + expand( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", + **config["scenario"] + ), + expand( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", + **config["scenario"] + ), + + STATISTICS_BARPLOTS = [ "capacity_factor", "installed_capacity", diff --git a/scripts/plot_gas_network.py b/scripts/plot_gas_network.py new file mode 100644 index 00000000..a72c5c56 --- /dev/null +++ b/scripts/plot_gas_network.py @@ -0,0 +1,251 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Creates map of optimised gas network, storage and selected other infrastructure. +""" + +import logging + +import geopandas as gpd +import matplotlib.pyplot as plt +import pandas as pd +import pypsa +from _helpers import configure_logging +from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches +from plot_power_network import assign_location, load_projection + +logger = logging.getLogger(__name__) + + +def plot_ch4_map(n): + # if "gas pipeline" not in n.links.carrier.unique(): + # return + + assign_location(n) + + bus_size_factor = 8e7 + linewidth_factor = 1e4 + # MW below which not drawn + line_lower_threshold = 1e3 + + # Drop non-electric buses so they don't clutter the plot + n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True) + + fossil_gas_i = n.generators[n.generators.carrier == "gas"].index + fossil_gas = ( + n.generators_t.p.loc[:, fossil_gas_i] + .mul(n.snapshot_weightings.generators, axis=0) + .sum() + .groupby(n.generators.loc[fossil_gas_i, "bus"]) + .sum() + / bus_size_factor + ) + fossil_gas.rename(index=lambda x: x.replace(" gas", ""), inplace=True) + fossil_gas = fossil_gas.reindex(n.buses.index).fillna(0) + # make a fake MultiIndex so that area is correct for legend + fossil_gas.index = pd.MultiIndex.from_product([fossil_gas.index, ["fossil gas"]]) + + methanation_i = n.links.query("carrier == 'Sabatier'").index + methanation = ( + abs( + n.links_t.p1.loc[:, methanation_i].mul( + n.snapshot_weightings.generators, axis=0 + ) + ) + .sum() + .groupby(n.links.loc[methanation_i, "bus1"]) + .sum() + / bus_size_factor + ) + methanation = ( + methanation.groupby(methanation.index) + .sum() + .rename(index=lambda x: x.replace(" gas", "")) + ) + # make a fake MultiIndex so that area is correct for legend + methanation.index = pd.MultiIndex.from_product([methanation.index, ["methanation"]]) + + biogas_i = n.stores[n.stores.carrier == "biogas"].index + biogas = ( + n.stores_t.p.loc[:, biogas_i] + .mul(n.snapshot_weightings.generators, axis=0) + .sum() + .groupby(n.stores.loc[biogas_i, "bus"]) + .sum() + / bus_size_factor + ) + biogas = ( + biogas.groupby(biogas.index) + .sum() + .rename(index=lambda x: x.replace(" biogas", "")) + ) + # make a fake MultiIndex so that area is correct for legend + biogas.index = pd.MultiIndex.from_product([biogas.index, ["biogas"]]) + + bus_sizes = pd.concat([fossil_gas, methanation, biogas]) + bus_sizes.sort_index(inplace=True) + + to_remove = n.links.index[~n.links.carrier.str.contains("gas pipeline")] + n.links.drop(to_remove, inplace=True) + + link_widths_rem = n.links.p_nom_opt / linewidth_factor + link_widths_rem[n.links.p_nom_opt < line_lower_threshold] = 0.0 + + link_widths_orig = n.links.p_nom / linewidth_factor + link_widths_orig[n.links.p_nom < line_lower_threshold] = 0.0 + + max_usage = n.links_t.p0.abs().max(axis=0) + link_widths_used = max_usage / linewidth_factor + link_widths_used[max_usage < line_lower_threshold] = 0.0 + + tech_colors = snakemake.params.plotting["tech_colors"] + + pipe_colors = { + "gas pipeline": "#f08080", + "gas pipeline new": "#c46868", + "gas pipeline (in 2020)": "lightgrey", + "gas pipeline (available)": "#e8d1d1", + } + + link_color_used = n.links.carrier.map(pipe_colors) + + n.links.bus0 = n.links.bus0.str.replace(" gas", "") + n.links.bus1 = n.links.bus1.str.replace(" gas", "") + + bus_colors = { + "fossil gas": tech_colors["fossil gas"], + "methanation": tech_colors["methanation"], + "biogas": "seagreen", + } + + fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": proj}) + + n.plot( + bus_sizes=bus_sizes, + bus_colors=bus_colors, + link_colors=pipe_colors["gas pipeline (in 2020)"], + link_widths=link_widths_orig, + branch_components=["Link"], + ax=ax, + **map_opts, + ) + + n.plot( + ax=ax, + bus_sizes=0.0, + link_colors=pipe_colors["gas pipeline (available)"], + link_widths=link_widths_rem, + branch_components=["Link"], + color_geomap=False, + boundaries=map_opts["boundaries"], + ) + + n.plot( + ax=ax, + bus_sizes=0.0, + link_colors=link_color_used, + link_widths=link_widths_used, + branch_components=["Link"], + color_geomap=False, + boundaries=map_opts["boundaries"], + ) + + sizes = [100, 10] + labels = [f"{s} TWh" for s in sizes] + sizes = [s / bus_size_factor * 1e6 for s in sizes] + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0, 1.03), + labelspacing=0.8, + frameon=False, + handletextpad=1, + title="gas sources", + ) + + add_legend_circles( + ax, + sizes, + labels, + srid=n.srid, + patch_kw=dict(facecolor="lightgrey"), + legend_kw=legend_kw, + ) + + sizes = [50, 10] + labels = [f"{s} GW" for s in sizes] + scale = 1e3 / linewidth_factor + sizes = [s * scale for s in sizes] + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0.25, 1.03), + frameon=False, + labelspacing=0.8, + handletextpad=1, + title="gas pipeline", + ) + + add_legend_lines( + ax, + sizes, + labels, + patch_kw=dict(color="lightgrey"), + legend_kw=legend_kw, + ) + + colors = list(pipe_colors.values()) + list(bus_colors.values()) + labels = list(pipe_colors.keys()) + list(bus_colors.keys()) + + # legend on the side + # legend_kw = dict( + # bbox_to_anchor=(1.47, 1.04), + # frameon=False, + # ) + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0, 1.24), + ncol=2, + frameon=False, + ) + + add_legend_patches( + ax, + colors, + labels, + legend_kw=legend_kw, + ) + + fig.savefig(snakemake.output.map, bbox_inches="tight") + + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake( + "plot_gas_network", + simpl="", + opts="", + clusters="37", + ll="v1.0", + sector_opts="4380H-T-H-B-I-A-dist1", + ) + + configure_logging(snakemake) + + n = pypsa.Network(snakemake.input.network) + + regions = gpd.read_file(snakemake.input.regions).set_index("name") + + map_opts = snakemake.params.plotting["map"] + + if map_opts["boundaries"] is None: + map_opts["boundaries"] = regions.total_bounds[[0, 2, 1, 3]] + [-1, 1, -1, 1] + + proj = load_projection(snakemake.params.plotting) + + plot_ch4_map(n) diff --git a/scripts/plot_hydrogen_network.py b/scripts/plot_hydrogen_network.py new file mode 100644 index 00000000..13728553 --- /dev/null +++ b/scripts/plot_hydrogen_network.py @@ -0,0 +1,267 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Creates map of optimised hydrogen network, storage and selected other infrastructure. +""" + +import logging + +import geopandas as gpd +import matplotlib.pyplot as plt +import pandas as pd +import pypsa +from _helpers import configure_logging +from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches + +from plot_power_network import assign_location, load_projection + +logger = logging.getLogger(__name__) + + +def group_pipes(df, drop_direction=False): + """ + Group pipes which connect same buses and return overall capacity. + """ + if drop_direction: + positive_order = df.bus0 < df.bus1 + df_p = df[positive_order] + swap_buses = {"bus0": "bus1", "bus1": "bus0"} + df_n = df[~positive_order].rename(columns=swap_buses) + df = pd.concat([df_p, df_n]) + + # there are pipes for each investment period rename to AC buses name for plotting + df.index = df.apply( + lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}", + axis=1, + ) + return df.groupby(level=0).agg({"p_nom_opt": sum, "bus0": "first", "bus1": "first"}) + + +def plot_h2_map(n, regions): + # if "H2 pipeline" not in n.links.carrier.unique(): + # return + + assign_location(n) + + h2_storage = n.stores.query("carrier == 'H2'") + regions["H2"] = ( + h2_storage.rename(index=h2_storage.bus.map(n.buses.location)) + .e_nom_opt.groupby(level=0) + .sum() + .div(1e6) + ) # TWh + regions["H2"] = regions["H2"].where(regions["H2"] > 0.1) + + bus_size_factor = 1e5 + linewidth_factor = 7e3 + # MW below which not drawn + line_lower_threshold = 750 + + # Drop non-electric buses so they don't clutter the plot + n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True) + + carriers = ["H2 Electrolysis", "H2 Fuel Cell"] + + elec = n.links[n.links.carrier.isin(carriers)].index + + bus_sizes = ( + n.links.loc[elec, "p_nom_opt"].groupby([n.links["bus0"], n.links.carrier]).sum() + / bus_size_factor + ) + + # make a fake MultiIndex so that area is correct for legend + bus_sizes.rename(index=lambda x: x.replace(" H2", ""), level=0, inplace=True) + # drop all links which are not H2 pipelines + n.links.drop( + n.links.index[~n.links.carrier.str.contains("H2 pipeline")], inplace=True + ) + + h2_new = n.links[n.links.carrier == "H2 pipeline"] + h2_retro = n.links[n.links.carrier == "H2 pipeline retrofitted"] + + if snakemake.params.foresight == "myopic": + # sum capacitiy for pipelines from different investment periods + h2_new = group_pipes(h2_new) + + if not h2_retro.empty: + h2_retro = ( + group_pipes(h2_retro, drop_direction=True) + .reindex(h2_new.index) + .fillna(0) + ) + + if not h2_retro.empty: + positive_order = h2_retro.bus0 < h2_retro.bus1 + h2_retro_p = h2_retro[positive_order] + swap_buses = {"bus0": "bus1", "bus1": "bus0"} + h2_retro_n = h2_retro[~positive_order].rename(columns=swap_buses) + h2_retro = pd.concat([h2_retro_p, h2_retro_n]) + + h2_retro["index_orig"] = h2_retro.index + h2_retro.index = h2_retro.apply( + lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}", + axis=1, + ) + + retro_w_new_i = h2_retro.index.intersection(h2_new.index) + h2_retro_w_new = h2_retro.loc[retro_w_new_i] + + retro_wo_new_i = h2_retro.index.difference(h2_new.index) + h2_retro_wo_new = h2_retro.loc[retro_wo_new_i] + h2_retro_wo_new.index = h2_retro_wo_new.index_orig + + to_concat = [h2_new, h2_retro_w_new, h2_retro_wo_new] + h2_total = pd.concat(to_concat).p_nom_opt.groupby(level=0).sum() + + else: + h2_total = h2_new.p_nom_opt + + link_widths_total = h2_total / linewidth_factor + + n.links.rename(index=lambda x: x.split("-2")[0], inplace=True) + n.links = n.links.groupby(level=0).first() + link_widths_total = link_widths_total.reindex(n.links.index).fillna(0.0) + link_widths_total[n.links.p_nom_opt < line_lower_threshold] = 0.0 + + retro = n.links.p_nom_opt.where( + n.links.carrier == "H2 pipeline retrofitted", other=0.0 + ) + link_widths_retro = retro / linewidth_factor + link_widths_retro[n.links.p_nom_opt < line_lower_threshold] = 0.0 + + n.links.bus0 = n.links.bus0.str.replace(" H2", "") + n.links.bus1 = n.links.bus1.str.replace(" H2", "") + + regions = regions.to_crs(proj.proj4_init) + + fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": proj}) + + color_h2_pipe = "#b3f3f4" + color_retrofit = "#499a9c" + + bus_colors = {"H2 Electrolysis": "#ff29d9", "H2 Fuel Cell": "#805394"} + + n.plot( + geomap=True, + bus_sizes=bus_sizes, + bus_colors=bus_colors, + link_colors=color_h2_pipe, + link_widths=link_widths_total, + branch_components=["Link"], + ax=ax, + **map_opts, + ) + + n.plot( + geomap=True, + bus_sizes=0, + link_colors=color_retrofit, + link_widths=link_widths_retro, + branch_components=["Link"], + ax=ax, + **map_opts, + ) + + regions.plot( + ax=ax, + column="H2", + cmap="Blues", + linewidths=0, + legend=True, + vmax=6, + vmin=0, + legend_kwds={ + "label": "Hydrogen Storage [TWh]", + "shrink": 0.7, + "extend": "max", + }, + ) + + sizes = [50, 10] + labels = [f"{s} GW" for s in sizes] + sizes = [s / bus_size_factor * 1e3 for s in sizes] + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0, 1), + labelspacing=0.8, + handletextpad=0, + frameon=False, + ) + + add_legend_circles( + ax, + sizes, + labels, + srid=n.srid, + patch_kw=dict(facecolor="lightgrey"), + legend_kw=legend_kw, + ) + + sizes = [30, 10] + labels = [f"{s} GW" for s in sizes] + scale = 1e3 / linewidth_factor + sizes = [s * scale for s in sizes] + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0.23, 1), + frameon=False, + labelspacing=0.8, + handletextpad=1, + ) + + add_legend_lines( + ax, + sizes, + labels, + patch_kw=dict(color="lightgrey"), + legend_kw=legend_kw, + ) + + colors = [bus_colors[c] for c in carriers] + [color_h2_pipe, color_retrofit] + labels = carriers + ["H2 pipeline (total)", "H2 pipeline (repurposed)"] + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0, 1.13), + ncol=2, + frameon=False, + ) + + add_legend_patches(ax, colors, labels, legend_kw=legend_kw) + + ax.set_facecolor("white") + + fig.savefig(snakemake.output.map, bbox_inches="tight") + + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake( + "plot_hydrogen_network", + simpl="", + opts="", + clusters="37", + ll="v1.0", + sector_opts="4380H-T-H-B-I-A-dist1", + ) + + configure_logging(snakemake) + + n = pypsa.Network(snakemake.input.network) + + regions = gpd.read_file(snakemake.input.regions).set_index("name") + + map_opts = snakemake.params.plotting["map"] + + if map_opts["boundaries"] is None: + map_opts["boundaries"] = regions.total_bounds[[0, 2, 1, 3]] + [-1, 1, -1, 1] + + proj = load_projection(snakemake.params.plotting) + + plot_h2_map(n, regions) diff --git a/scripts/plot_network.py b/scripts/plot_network.py deleted file mode 100644 index b06e5ce2..00000000 --- a/scripts/plot_network.py +++ /dev/null @@ -1,869 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT -""" -Creates plots for optimised network topologies, including electricity, gas and -hydrogen networks, and regional generation, storage and conversion capacities -built. - -This rule plots a map of the network with technology capacities at the -nodes. -""" - -import logging - -import cartopy.crs as ccrs -import geopandas as gpd -import matplotlib.pyplot as plt -import pandas as pd -import pypsa -from make_summary import assign_carriers -from plot_summary import preferred_order, rename_techs -from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches - -logger = logging.getLogger(__name__) -plt.style.use(["ggplot"]) - - -def rename_techs_tyndp(tech): - tech = rename_techs(tech) - if "heat pump" in tech or "resistive heater" in tech: - return "power-to-heat" - elif tech in ["H2 Electrolysis", "methanation", "H2 liquefaction"]: - return "power-to-gas" - elif tech == "H2": - return "H2 storage" - elif tech in ["NH3", "Haber-Bosch", "ammonia cracker", "ammonia store"]: - return "ammonia" - elif tech in ["OCGT", "CHP", "gas boiler", "H2 Fuel Cell"]: - return "gas-to-power/heat" - # elif "solar" in tech: - # return "solar" - elif tech in ["Fischer-Tropsch", "methanolisation"]: - return "power-to-liquid" - elif "offshore wind" in tech: - return "offshore wind" - elif "CC" in tech or "sequestration" in tech: - return "CCS" - else: - return tech - - -def assign_location(n): - for c in n.iterate_components(n.one_port_components | n.branch_components): - ifind = pd.Series(c.df.index.str.find(" ", start=4), c.df.index) - for i in ifind.value_counts().index: - # these have already been assigned defaults - if i == -1: - continue - names = ifind.index[ifind == i] - c.df.loc[names, "location"] = names.str[:i] - - -def plot_map( - network, - components=["links", "stores", "storage_units", "generators"], - bus_size_factor=1.7e10, - transmission=False, - with_legend=True, -): - tech_colors = snakemake.params.plotting["tech_colors"] - - n = network.copy() - assign_location(n) - # Drop non-electric buses so they don't clutter the plot - n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True) - - costs = pd.DataFrame(index=n.buses.index) - - for comp in components: - df_c = getattr(n, comp) - - if df_c.empty: - continue - - df_c["nice_group"] = df_c.carrier.map(rename_techs_tyndp) - - attr = "e_nom_opt" if comp == "stores" else "p_nom_opt" - - costs_c = ( - (df_c.capital_cost * df_c[attr]) - .groupby([df_c.location, df_c.nice_group]) - .sum() - .unstack() - .fillna(0.0) - ) - costs = pd.concat([costs, costs_c], axis=1) - - logger.debug(f"{comp}, {costs}") - - costs = costs.groupby(costs.columns, axis=1).sum() - - costs.drop(list(costs.columns[(costs == 0.0).all()]), axis=1, inplace=True) - - new_columns = preferred_order.intersection(costs.columns).append( - costs.columns.difference(preferred_order) - ) - costs = costs[new_columns] - - for item in new_columns: - if item not in tech_colors: - logger.warning(f"{item} not in config/plotting/tech_colors") - - costs = costs.stack() # .sort_index() - - # hack because impossible to drop buses... - eu_location = snakemake.params.plotting.get("eu_node_location", dict(x=-5.5, y=46)) - n.buses.loc["EU gas", "x"] = eu_location["x"] - n.buses.loc["EU gas", "y"] = eu_location["y"] - - n.links.drop( - n.links.index[(n.links.carrier != "DC") & (n.links.carrier != "B2B")], - inplace=True, - ) - - # drop non-bus - to_drop = costs.index.levels[0].symmetric_difference(n.buses.index) - if len(to_drop) != 0: - logger.info(f"Dropping non-buses {to_drop.tolist()}") - costs.drop(to_drop, level=0, inplace=True, axis=0, errors="ignore") - - # make sure they are removed from index - costs.index = pd.MultiIndex.from_tuples(costs.index.values) - - threshold = 100e6 # 100 mEUR/a - carriers = costs.groupby(level=1).sum() - carriers = carriers.where(carriers > threshold).dropna() - carriers = list(carriers.index) - - # PDF has minimum width, so set these to zero - line_lower_threshold = 500.0 - line_upper_threshold = 1e4 - linewidth_factor = 4e3 - ac_color = "rosybrown" - dc_color = "darkseagreen" - - title = "added grid" - - if snakemake.wildcards["ll"] == "v1.0": - # should be zero - line_widths = n.lines.s_nom_opt - n.lines.s_nom - link_widths = n.links.p_nom_opt - n.links.p_nom - if transmission: - line_widths = n.lines.s_nom_opt - link_widths = n.links.p_nom_opt - linewidth_factor = 2e3 - line_lower_threshold = 0.0 - title = "current grid" - else: - line_widths = n.lines.s_nom_opt - n.lines.s_nom_min - link_widths = n.links.p_nom_opt - n.links.p_nom_min - if transmission: - line_widths = n.lines.s_nom_opt - link_widths = n.links.p_nom_opt - title = "total grid" - - line_widths = line_widths.clip(line_lower_threshold, line_upper_threshold) - link_widths = link_widths.clip(line_lower_threshold, line_upper_threshold) - - 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": proj}) - fig.set_size_inches(7, 6) - - n.plot( - bus_sizes=costs / bus_size_factor, - bus_colors=tech_colors, - line_colors=ac_color, - link_colors=dc_color, - line_widths=line_widths / linewidth_factor, - link_widths=link_widths / linewidth_factor, - ax=ax, - **map_opts, - ) - - sizes = [20, 10, 5] - labels = [f"{s} bEUR/a" for s in sizes] - sizes = [s / bus_size_factor * 1e9 for s in sizes] - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0.01, 1.06), - labelspacing=0.8, - frameon=False, - handletextpad=0, - title="system cost", - ) - - add_legend_circles( - ax, - sizes, - labels, - srid=n.srid, - patch_kw=dict(facecolor="lightgrey"), - legend_kw=legend_kw, - ) - - sizes = [10, 5] - labels = [f"{s} GW" for s in sizes] - scale = 1e3 / linewidth_factor - sizes = [s * scale for s in sizes] - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0.27, 1.06), - frameon=False, - labelspacing=0.8, - handletextpad=1, - title=title, - ) - - add_legend_lines( - ax, sizes, labels, patch_kw=dict(color="lightgrey"), legend_kw=legend_kw - ) - - legend_kw = dict( - bbox_to_anchor=(1.52, 1.04), - frameon=False, - ) - - if with_legend: - colors = [tech_colors[c] for c in carriers] + [ac_color, dc_color] - labels = carriers + ["HVAC line", "HVDC link"] - - add_legend_patches( - ax, - colors, - labels, - legend_kw=legend_kw, - ) - - fig.savefig(snakemake.output.map, transparent=True, bbox_inches="tight") - - -def group_pipes(df, drop_direction=False): - """ - Group pipes which connect same buses and return overall capacity. - """ - if drop_direction: - positive_order = df.bus0 < df.bus1 - df_p = df[positive_order] - swap_buses = {"bus0": "bus1", "bus1": "bus0"} - df_n = df[~positive_order].rename(columns=swap_buses) - df = pd.concat([df_p, df_n]) - - # there are pipes for each investment period rename to AC buses name for plotting - df.index = df.apply( - lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}", - axis=1, - ) - return df.groupby(level=0).agg({"p_nom_opt": sum, "bus0": "first", "bus1": "first"}) - - -def plot_h2_map(network, regions): - n = network.copy() - if "H2 pipeline" not in n.links.carrier.unique(): - return - - assign_location(n) - - h2_storage = n.stores.query("carrier == 'H2'") - regions["H2"] = ( - h2_storage.rename(index=h2_storage.bus.map(n.buses.location)) - .e_nom_opt.groupby(level=0) - .sum() - .div(1e6) - ) # TWh - regions["H2"] = regions["H2"].where(regions["H2"] > 0.1) - - bus_size_factor = 1e5 - linewidth_factor = 7e3 - # MW below which not drawn - line_lower_threshold = 750 - - # Drop non-electric buses so they don't clutter the plot - n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True) - - carriers = ["H2 Electrolysis", "H2 Fuel Cell"] - - elec = n.links[n.links.carrier.isin(carriers)].index - - bus_sizes = ( - n.links.loc[elec, "p_nom_opt"].groupby([n.links["bus0"], n.links.carrier]).sum() - / bus_size_factor - ) - - # make a fake MultiIndex so that area is correct for legend - bus_sizes.rename(index=lambda x: x.replace(" H2", ""), level=0, inplace=True) - # drop all links which are not H2 pipelines - n.links.drop( - n.links.index[~n.links.carrier.str.contains("H2 pipeline")], inplace=True - ) - - h2_new = n.links[n.links.carrier == "H2 pipeline"] - h2_retro = n.links[n.links.carrier == "H2 pipeline retrofitted"] - - if snakemake.params.foresight == "myopic": - # sum capacitiy for pipelines from different investment periods - h2_new = group_pipes(h2_new) - - if not h2_retro.empty: - h2_retro = ( - group_pipes(h2_retro, drop_direction=True) - .reindex(h2_new.index) - .fillna(0) - ) - - if not h2_retro.empty: - positive_order = h2_retro.bus0 < h2_retro.bus1 - h2_retro_p = h2_retro[positive_order] - swap_buses = {"bus0": "bus1", "bus1": "bus0"} - h2_retro_n = h2_retro[~positive_order].rename(columns=swap_buses) - h2_retro = pd.concat([h2_retro_p, h2_retro_n]) - - h2_retro["index_orig"] = h2_retro.index - h2_retro.index = h2_retro.apply( - lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}", - axis=1, - ) - - retro_w_new_i = h2_retro.index.intersection(h2_new.index) - h2_retro_w_new = h2_retro.loc[retro_w_new_i] - - retro_wo_new_i = h2_retro.index.difference(h2_new.index) - h2_retro_wo_new = h2_retro.loc[retro_wo_new_i] - h2_retro_wo_new.index = h2_retro_wo_new.index_orig - - to_concat = [h2_new, h2_retro_w_new, h2_retro_wo_new] - h2_total = pd.concat(to_concat).p_nom_opt.groupby(level=0).sum() - - else: - h2_total = h2_new.p_nom_opt - - link_widths_total = h2_total / linewidth_factor - - n.links.rename(index=lambda x: x.split("-2")[0], inplace=True) - n.links = n.links.groupby(level=0).first() - link_widths_total = link_widths_total.reindex(n.links.index).fillna(0.0) - link_widths_total[n.links.p_nom_opt < line_lower_threshold] = 0.0 - - retro = n.links.p_nom_opt.where( - n.links.carrier == "H2 pipeline retrofitted", other=0.0 - ) - link_widths_retro = retro / linewidth_factor - link_widths_retro[n.links.p_nom_opt < line_lower_threshold] = 0.0 - - n.links.bus0 = n.links.bus0.str.replace(" H2", "") - n.links.bus1 = n.links.bus1.str.replace(" H2", "") - - regions = regions.to_crs(proj.proj4_init) - - fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": proj}) - - color_h2_pipe = "#b3f3f4" - color_retrofit = "#499a9c" - - bus_colors = {"H2 Electrolysis": "#ff29d9", "H2 Fuel Cell": "#805394"} - - n.plot( - geomap=True, - bus_sizes=bus_sizes, - bus_colors=bus_colors, - link_colors=color_h2_pipe, - link_widths=link_widths_total, - branch_components=["Link"], - ax=ax, - **map_opts, - ) - - n.plot( - geomap=True, - bus_sizes=0, - link_colors=color_retrofit, - link_widths=link_widths_retro, - branch_components=["Link"], - ax=ax, - **map_opts, - ) - - regions.plot( - ax=ax, - column="H2", - cmap="Blues", - linewidths=0, - legend=True, - vmax=6, - vmin=0, - legend_kwds={ - "label": "Hydrogen Storage [TWh]", - "shrink": 0.7, - "extend": "max", - }, - ) - - sizes = [50, 10] - labels = [f"{s} GW" for s in sizes] - sizes = [s / bus_size_factor * 1e3 for s in sizes] - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0, 1), - labelspacing=0.8, - handletextpad=0, - frameon=False, - ) - - add_legend_circles( - ax, - sizes, - labels, - srid=n.srid, - patch_kw=dict(facecolor="lightgrey"), - legend_kw=legend_kw, - ) - - sizes = [30, 10] - labels = [f"{s} GW" for s in sizes] - scale = 1e3 / linewidth_factor - sizes = [s * scale for s in sizes] - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0.23, 1), - frameon=False, - labelspacing=0.8, - handletextpad=1, - ) - - add_legend_lines( - ax, - sizes, - labels, - patch_kw=dict(color="lightgrey"), - legend_kw=legend_kw, - ) - - colors = [bus_colors[c] for c in carriers] + [color_h2_pipe, color_retrofit] - labels = carriers + ["H2 pipeline (total)", "H2 pipeline (repurposed)"] - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0, 1.13), - ncol=2, - frameon=False, - ) - - add_legend_patches(ax, colors, labels, legend_kw=legend_kw) - - ax.set_facecolor("white") - - fig.savefig( - snakemake.output.map.replace("-costs-all", "-h2_network"), bbox_inches="tight" - ) - - -def plot_ch4_map(network): - n = network.copy() - - if "gas pipeline" not in n.links.carrier.unique(): - return - - assign_location(n) - - bus_size_factor = 8e7 - linewidth_factor = 1e4 - # MW below which not drawn - line_lower_threshold = 1e3 - - # Drop non-electric buses so they don't clutter the plot - n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True) - - fossil_gas_i = n.generators[n.generators.carrier == "gas"].index - fossil_gas = ( - n.generators_t.p.loc[:, fossil_gas_i] - .mul(n.snapshot_weightings.generators, axis=0) - .sum() - .groupby(n.generators.loc[fossil_gas_i, "bus"]) - .sum() - / bus_size_factor - ) - fossil_gas.rename(index=lambda x: x.replace(" gas", ""), inplace=True) - fossil_gas = fossil_gas.reindex(n.buses.index).fillna(0) - # make a fake MultiIndex so that area is correct for legend - fossil_gas.index = pd.MultiIndex.from_product([fossil_gas.index, ["fossil gas"]]) - - methanation_i = n.links.query("carrier == 'Sabatier'").index - methanation = ( - abs( - n.links_t.p1.loc[:, methanation_i].mul( - n.snapshot_weightings.generators, axis=0 - ) - ) - .sum() - .groupby(n.links.loc[methanation_i, "bus1"]) - .sum() - / bus_size_factor - ) - methanation = ( - methanation.groupby(methanation.index) - .sum() - .rename(index=lambda x: x.replace(" gas", "")) - ) - # make a fake MultiIndex so that area is correct for legend - methanation.index = pd.MultiIndex.from_product([methanation.index, ["methanation"]]) - - biogas_i = n.stores[n.stores.carrier == "biogas"].index - biogas = ( - n.stores_t.p.loc[:, biogas_i] - .mul(n.snapshot_weightings.generators, axis=0) - .sum() - .groupby(n.stores.loc[biogas_i, "bus"]) - .sum() - / bus_size_factor - ) - biogas = ( - biogas.groupby(biogas.index) - .sum() - .rename(index=lambda x: x.replace(" biogas", "")) - ) - # make a fake MultiIndex so that area is correct for legend - biogas.index = pd.MultiIndex.from_product([biogas.index, ["biogas"]]) - - bus_sizes = pd.concat([fossil_gas, methanation, biogas]) - bus_sizes.sort_index(inplace=True) - - to_remove = n.links.index[~n.links.carrier.str.contains("gas pipeline")] - n.links.drop(to_remove, inplace=True) - - link_widths_rem = n.links.p_nom_opt / linewidth_factor - link_widths_rem[n.links.p_nom_opt < line_lower_threshold] = 0.0 - - link_widths_orig = n.links.p_nom / linewidth_factor - link_widths_orig[n.links.p_nom < line_lower_threshold] = 0.0 - - max_usage = n.links_t.p0.abs().max(axis=0) - link_widths_used = max_usage / linewidth_factor - link_widths_used[max_usage < line_lower_threshold] = 0.0 - - tech_colors = snakemake.params.plotting["tech_colors"] - - pipe_colors = { - "gas pipeline": "#f08080", - "gas pipeline new": "#c46868", - "gas pipeline (in 2020)": "lightgrey", - "gas pipeline (available)": "#e8d1d1", - } - - link_color_used = n.links.carrier.map(pipe_colors) - - n.links.bus0 = n.links.bus0.str.replace(" gas", "") - n.links.bus1 = n.links.bus1.str.replace(" gas", "") - - bus_colors = { - "fossil gas": tech_colors["fossil gas"], - "methanation": tech_colors["methanation"], - "biogas": "seagreen", - } - - fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": proj}) - - n.plot( - bus_sizes=bus_sizes, - bus_colors=bus_colors, - link_colors=pipe_colors["gas pipeline (in 2020)"], - link_widths=link_widths_orig, - branch_components=["Link"], - ax=ax, - **map_opts, - ) - - n.plot( - ax=ax, - bus_sizes=0.0, - link_colors=pipe_colors["gas pipeline (available)"], - link_widths=link_widths_rem, - branch_components=["Link"], - color_geomap=False, - boundaries=map_opts["boundaries"], - ) - - n.plot( - ax=ax, - bus_sizes=0.0, - link_colors=link_color_used, - link_widths=link_widths_used, - branch_components=["Link"], - color_geomap=False, - boundaries=map_opts["boundaries"], - ) - - sizes = [100, 10] - labels = [f"{s} TWh" for s in sizes] - sizes = [s / bus_size_factor * 1e6 for s in sizes] - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0, 1.03), - labelspacing=0.8, - frameon=False, - handletextpad=1, - title="gas sources", - ) - - add_legend_circles( - ax, - sizes, - labels, - srid=n.srid, - patch_kw=dict(facecolor="lightgrey"), - legend_kw=legend_kw, - ) - - sizes = [50, 10] - labels = [f"{s} GW" for s in sizes] - scale = 1e3 / linewidth_factor - sizes = [s * scale for s in sizes] - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0.25, 1.03), - frameon=False, - labelspacing=0.8, - handletextpad=1, - title="gas pipeline", - ) - - add_legend_lines( - ax, - sizes, - labels, - patch_kw=dict(color="lightgrey"), - legend_kw=legend_kw, - ) - - colors = list(pipe_colors.values()) + list(bus_colors.values()) - labels = list(pipe_colors.keys()) + list(bus_colors.keys()) - - # legend on the side - # legend_kw = dict( - # bbox_to_anchor=(1.47, 1.04), - # frameon=False, - # ) - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0, 1.24), - ncol=2, - frameon=False, - ) - - add_legend_patches( - ax, - colors, - labels, - legend_kw=legend_kw, - ) - - fig.savefig( - snakemake.output.map.replace("-costs-all", "-ch4_network"), bbox_inches="tight" - ) - - -def plot_map_perfect( - network, - components=["Link", "Store", "StorageUnit", "Generator"], - bus_size_factor=1.7e10, -): - n = network.copy() - assign_location(n) - # Drop non-electric buses so they don't clutter the plot - n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True) - # investment periods - investments = n.snapshots.levels[0] - - costs = {} - for comp in components: - df_c = n.df(comp) - if df_c.empty: - continue - df_c["nice_group"] = df_c.carrier.map(rename_techs_tyndp) - - attr = "e_nom_opt" if comp == "Store" else "p_nom_opt" - - active = pd.concat( - [n.get_active_assets(comp, inv_p).rename(inv_p) for inv_p in investments], - axis=1, - ).astype(int) - capital_cost = n.df(comp)[attr] * n.df(comp).capital_cost - capital_cost_t = ( - (active.mul(capital_cost, axis=0)) - .groupby([n.df(comp).location, n.df(comp).nice_group]) - .sum() - ) - - capital_cost_t.drop("load", level=1, inplace=True, errors="ignore") - - costs[comp] = capital_cost_t - - costs = pd.concat(costs).groupby(level=[1, 2]).sum() - costs.drop(costs[costs.sum(axis=1) == 0].index, inplace=True) - - new_columns = preferred_order.intersection(costs.index.levels[1]).append( - costs.index.levels[1].difference(preferred_order) - ) - costs = costs.reindex(new_columns, level=1) - - for item in new_columns: - if item not in snakemake.config["plotting"]["tech_colors"]: - print( - "Warning!", - item, - "not in config/plotting/tech_colors, assign random color", - ) - snakemake.config["plotting"]["tech_colors"] = "pink" - - n.links.drop( - n.links.index[(n.links.carrier != "DC") & (n.links.carrier != "B2B")], - inplace=True, - ) - - # drop non-bus - to_drop = costs.index.levels[0].symmetric_difference(n.buses.index) - if len(to_drop) != 0: - print("dropping non-buses", to_drop) - costs.drop(to_drop, level=0, inplace=True, axis=0, errors="ignore") - - # make sure they are removed from index - costs.index = pd.MultiIndex.from_tuples(costs.index.values) - - # PDF has minimum width, so set these to zero - line_lower_threshold = 500.0 - line_upper_threshold = 1e4 - linewidth_factor = 2e3 - ac_color = "gray" - dc_color = "m" - - line_widths = n.lines.s_nom_opt - link_widths = n.links.p_nom_opt - linewidth_factor = 2e3 - line_lower_threshold = 0.0 - title = "Today's transmission" - - line_widths[line_widths < line_lower_threshold] = 0.0 - link_widths[link_widths < line_lower_threshold] = 0.0 - - line_widths[line_widths > line_upper_threshold] = line_upper_threshold - link_widths[link_widths > line_upper_threshold] = line_upper_threshold - - for year in costs.columns: - fig, ax = plt.subplots(subplot_kw={"projection": proj}) - fig.set_size_inches(7, 6) - fig.suptitle(year) - - n.plot( - bus_sizes=costs[year] / bus_size_factor, - bus_colors=snakemake.config["plotting"]["tech_colors"], - line_colors=ac_color, - link_colors=dc_color, - line_widths=line_widths / linewidth_factor, - link_widths=link_widths / linewidth_factor, - ax=ax, - **map_opts, - ) - - sizes = [20, 10, 5] - labels = [f"{s} bEUR/a" for s in sizes] - sizes = [s / bus_size_factor * 1e9 for s in sizes] - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0.01, 1.06), - labelspacing=0.8, - frameon=False, - handletextpad=0, - title="system cost", - ) - - add_legend_circles( - ax, - sizes, - labels, - srid=n.srid, - patch_kw=dict(facecolor="lightgrey"), - legend_kw=legend_kw, - ) - - sizes = [10, 5] - labels = [f"{s} GW" for s in sizes] - scale = 1e3 / linewidth_factor - sizes = [s * scale for s in sizes] - - legend_kw = dict( - loc="upper left", - bbox_to_anchor=(0.27, 1.06), - frameon=False, - labelspacing=0.8, - handletextpad=1, - title=title, - ) - - add_legend_lines( - ax, sizes, labels, patch_kw=dict(color="lightgrey"), legend_kw=legend_kw - ) - - legend_kw = dict( - bbox_to_anchor=(1.52, 1.04), - frameon=False, - ) - - fig.savefig( - snakemake.output[f"map_{year}"], transparent=True, bbox_inches="tight" - ) - - -if __name__ == "__main__": - if "snakemake" not in globals(): - from _helpers import mock_snakemake - - snakemake = mock_snakemake( - "plot_network", - simpl="", - opts="", - clusters="37", - ll="v1.0", - sector_opts="4380H-T-H-B-I-A-dist1", - ) - - logging.basicConfig(level=snakemake.config["logging"]["level"]) - - n = pypsa.Network(snakemake.input.network) - - regions = gpd.read_file(snakemake.input.regions).set_index("name") - - map_opts = snakemake.params.plotting["map"] - - if map_opts["boundaries"] is None: - map_opts["boundaries"] = regions.total_bounds[[0, 2, 1, 3]] + [-1, 1, -1, 1] - - 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( - n, - components=["Link", "Store", "StorageUnit", "Generator"], - bus_size_factor=2e10, - ) - else: - plot_map( - n, - components=["generators", "links", "stores", "storage_units"], - bus_size_factor=2e10, - transmission=False, - ) - - plot_h2_map(n, regions) - plot_ch4_map(n) diff --git a/scripts/plot_power_network.py b/scripts/plot_power_network.py new file mode 100644 index 00000000..48aa01e3 --- /dev/null +++ b/scripts/plot_power_network.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Creates plots for optimised power network topologies and regional generation, +storage and conversion capacities built. +""" + +import logging + +import cartopy.crs as ccrs +import geopandas as gpd +import matplotlib.pyplot as plt +import pandas as pd +import pypsa +from plot_summary import preferred_order, rename_techs +from _helpers import configure_logging +from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches + +logger = logging.getLogger(__name__) + +def rename_techs_tyndp(tech): + tech = rename_techs(tech) + if "heat pump" in tech or "resistive heater" in tech: + return "power-to-heat" + elif tech in ["H2 Electrolysis", "methanation", "H2 liquefaction"]: + return "power-to-gas" + elif tech == "H2": + return "H2 storage" + elif tech in ["NH3", "Haber-Bosch", "ammonia cracker", "ammonia store"]: + return "ammonia" + elif tech in ["OCGT", "CHP", "gas boiler", "H2 Fuel Cell"]: + return "gas-to-power/heat" + # elif "solar" in tech: + # return "solar" + elif tech in ["Fischer-Tropsch", "methanolisation"]: + return "power-to-liquid" + elif "offshore wind" in tech: + return "offshore wind" + elif "CC" in tech or "sequestration" in tech: + return "CCS" + else: + return tech + + +def assign_location(n): + for c in n.iterate_components(n.one_port_components | n.branch_components): + ifind = pd.Series(c.df.index.str.find(" ", start=4), c.df.index) + for i in ifind.value_counts().index: + # these have already been assigned defaults + if i == -1: + continue + names = ifind.index[ifind == i] + c.df.loc[names, "location"] = names.str[:i] + + +def load_projection(plotting_params): + proj_kwargs = plotting_params.get("projection", dict(name="EqualEarth")) + proj_func = getattr(ccrs, proj_kwargs.pop("name")) + return proj_func(**proj_kwargs) + + +def plot_map( + n, + components=["links", "stores", "storage_units", "generators"], + bus_size_factor=2e10, + transmission=False, + with_legend=True, +): + tech_colors = snakemake.params.plotting["tech_colors"] + + assign_location(n) + # Drop non-electric buses so they don't clutter the plot + n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True) + + costs = pd.DataFrame(index=n.buses.index) + + for comp in components: + df_c = getattr(n, comp) + + if df_c.empty: + continue + + df_c["nice_group"] = df_c.carrier.map(rename_techs_tyndp) + + attr = "e_nom_opt" if comp == "stores" else "p_nom_opt" + + costs_c = ( + (df_c.capital_cost * df_c[attr]) + .groupby([df_c.location, df_c.nice_group]) + .sum() + .unstack() + .fillna(0.0) + ) + costs = pd.concat([costs, costs_c], axis=1) + + logger.debug(f"{comp}, {costs}") + + costs = costs.groupby(costs.columns, axis=1).sum() + + costs.drop(list(costs.columns[(costs == 0.0).all()]), axis=1, inplace=True) + + new_columns = preferred_order.intersection(costs.columns).append( + costs.columns.difference(preferred_order) + ) + costs = costs[new_columns] + + for item in new_columns: + if item not in tech_colors: + logger.warning(f"{item} not in config/plotting/tech_colors") + + costs = costs.stack() # .sort_index() + + # hack because impossible to drop buses... + eu_location = snakemake.params.plotting.get("eu_node_location", dict(x=-5.5, y=46)) + n.buses.loc["EU gas", "x"] = eu_location["x"] + n.buses.loc["EU gas", "y"] = eu_location["y"] + + n.links.drop( + n.links.index[(n.links.carrier != "DC") & (n.links.carrier != "B2B")], + inplace=True, + ) + + # drop non-bus + to_drop = costs.index.levels[0].symmetric_difference(n.buses.index) + if len(to_drop) != 0: + logger.info(f"Dropping non-buses {to_drop.tolist()}") + costs.drop(to_drop, level=0, inplace=True, axis=0, errors="ignore") + + # make sure they are removed from index + costs.index = pd.MultiIndex.from_tuples(costs.index.values) + + threshold = 100e6 # 100 mEUR/a + carriers = costs.groupby(level=1).sum() + carriers = carriers.where(carriers > threshold).dropna() + carriers = list(carriers.index) + + # PDF has minimum width, so set these to zero + line_lower_threshold = 500.0 + line_upper_threshold = 1e4 + linewidth_factor = 4e3 + ac_color = "rosybrown" + dc_color = "darkseagreen" + + title = "added grid" + + if snakemake.wildcards["ll"] == "v1.0": + # should be zero + line_widths = n.lines.s_nom_opt - n.lines.s_nom + link_widths = n.links.p_nom_opt - n.links.p_nom + if transmission: + line_widths = n.lines.s_nom_opt + link_widths = n.links.p_nom_opt + linewidth_factor = 2e3 + line_lower_threshold = 0.0 + title = "current grid" + else: + line_widths = n.lines.s_nom_opt - n.lines.s_nom_min + link_widths = n.links.p_nom_opt - n.links.p_nom_min + if transmission: + line_widths = n.lines.s_nom_opt + link_widths = n.links.p_nom_opt + title = "total grid" + + line_widths = line_widths.clip(line_lower_threshold, line_upper_threshold) + link_widths = link_widths.clip(line_lower_threshold, line_upper_threshold) + + 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": proj}) + fig.set_size_inches(7, 6) + + n.plot( + bus_sizes=costs / bus_size_factor, + bus_colors=tech_colors, + line_colors=ac_color, + link_colors=dc_color, + line_widths=line_widths / linewidth_factor, + link_widths=link_widths / linewidth_factor, + ax=ax, + **map_opts, + ) + + sizes = [20, 10, 5] + labels = [f"{s} bEUR/a" for s in sizes] + sizes = [s / bus_size_factor * 1e9 for s in sizes] + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0.01, 1.06), + labelspacing=0.8, + frameon=False, + handletextpad=0, + title="system cost", + ) + + add_legend_circles( + ax, + sizes, + labels, + srid=n.srid, + patch_kw=dict(facecolor="lightgrey"), + legend_kw=legend_kw, + ) + + sizes = [10, 5] + labels = [f"{s} GW" for s in sizes] + scale = 1e3 / linewidth_factor + sizes = [s * scale for s in sizes] + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0.27, 1.06), + frameon=False, + labelspacing=0.8, + handletextpad=1, + title=title, + ) + + add_legend_lines( + ax, sizes, labels, patch_kw=dict(color="lightgrey"), legend_kw=legend_kw + ) + + legend_kw = dict( + bbox_to_anchor=(1.52, 1.04), + frameon=False, + ) + + if with_legend: + colors = [tech_colors[c] for c in carriers] + [ac_color, dc_color] + labels = carriers + ["HVAC line", "HVDC link"] + + add_legend_patches( + ax, + colors, + labels, + legend_kw=legend_kw, + ) + + fig.savefig(snakemake.output.map, bbox_inches="tight") + + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake( + "plot_power_network", + simpl="", + opts="", + clusters="37", + ll="v1.0", + sector_opts="4380H-T-H-B-I-A-dist1", + ) + + configure_logging(snakemake) + + n = pypsa.Network(snakemake.input.network) + + regions = gpd.read_file(snakemake.input.regions).set_index("name") + + map_opts = snakemake.params.plotting["map"] + + if map_opts["boundaries"] is None: + map_opts["boundaries"] = regions.total_bounds[[0, 2, 1, 3]] + [-1, 1, -1, 1] + + proj = load_projection(snakemake.params.plotting) + + plot_map(n) diff --git a/scripts/plot_power_network_perfect.py b/scripts/plot_power_network_perfect.py new file mode 100644 index 00000000..ce8afef0 --- /dev/null +++ b/scripts/plot_power_network_perfect.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Creates plots for optimised power network topologies and regional generation, +storage and conversion capacities built for the perfect foresight scenario. +""" + +import logging + +import geopandas as gpd +import matplotlib.pyplot as plt +import pandas as pd +import pypsa +from _helpers import configure_logging +from pypsa.plot import add_legend_circles, add_legend_lines +from plot_power_network import assign_location, rename_techs_tyndp, load_projection +from plot_summary import preferred_order + +logger = logging.getLogger(__name__) + + +def plot_map_perfect( + n, + components=["Link", "Store", "StorageUnit", "Generator"], + bus_size_factor=2e10, +): + assign_location(n) + # Drop non-electric buses so they don't clutter the plot + n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True) + # investment periods + investments = n.snapshots.levels[0] + + costs = {} + for comp in components: + df_c = n.df(comp) + if df_c.empty: + continue + df_c["nice_group"] = df_c.carrier.map(rename_techs_tyndp) + + attr = "e_nom_opt" if comp == "Store" else "p_nom_opt" + + active = pd.concat( + [n.get_active_assets(comp, inv_p).rename(inv_p) for inv_p in investments], + axis=1, + ).astype(int) + capital_cost = n.df(comp)[attr] * n.df(comp).capital_cost + capital_cost_t = ( + (active.mul(capital_cost, axis=0)) + .groupby([n.df(comp).location, n.df(comp).nice_group]) + .sum() + ) + + capital_cost_t.drop("load", level=1, inplace=True, errors="ignore") + + costs[comp] = capital_cost_t + + costs = pd.concat(costs).groupby(level=[1, 2]).sum() + costs.drop(costs[costs.sum(axis=1) == 0].index, inplace=True) + + new_columns = preferred_order.intersection(costs.index.levels[1]).append( + costs.index.levels[1].difference(preferred_order) + ) + costs = costs.reindex(new_columns, level=1) + + for item in new_columns: + if item not in snakemake.config["plotting"]["tech_colors"]: + print( + "Warning!", + item, + "not in config/plotting/tech_colors, assign random color", + ) + snakemake.config["plotting"]["tech_colors"] = "pink" + + n.links.drop( + n.links.index[(n.links.carrier != "DC") & (n.links.carrier != "B2B")], + inplace=True, + ) + + # drop non-bus + to_drop = costs.index.levels[0].symmetric_difference(n.buses.index) + if len(to_drop) != 0: + print("dropping non-buses", to_drop) + costs.drop(to_drop, level=0, inplace=True, axis=0, errors="ignore") + + # make sure they are removed from index + costs.index = pd.MultiIndex.from_tuples(costs.index.values) + + # PDF has minimum width, so set these to zero + line_lower_threshold = 500.0 + line_upper_threshold = 1e4 + linewidth_factor = 2e3 + ac_color = "gray" + dc_color = "m" + + line_widths = n.lines.s_nom_opt + link_widths = n.links.p_nom_opt + linewidth_factor = 2e3 + line_lower_threshold = 0.0 + title = "Today's transmission" + + line_widths[line_widths < line_lower_threshold] = 0.0 + link_widths[link_widths < line_lower_threshold] = 0.0 + + line_widths[line_widths > line_upper_threshold] = line_upper_threshold + link_widths[link_widths > line_upper_threshold] = line_upper_threshold + + for year in costs.columns: + fig, ax = plt.subplots(subplot_kw={"projection": proj}) + fig.set_size_inches(7, 6) + fig.suptitle(year) + + n.plot( + bus_sizes=costs[year] / bus_size_factor, + bus_colors=snakemake.config["plotting"]["tech_colors"], + line_colors=ac_color, + link_colors=dc_color, + line_widths=line_widths / linewidth_factor, + link_widths=link_widths / linewidth_factor, + ax=ax, + **map_opts, + ) + + sizes = [20, 10, 5] + labels = [f"{s} bEUR/a" for s in sizes] + sizes = [s / bus_size_factor * 1e9 for s in sizes] + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0.01, 1.06), + labelspacing=0.8, + frameon=False, + handletextpad=0, + title="system cost", + ) + + add_legend_circles( + ax, + sizes, + labels, + srid=n.srid, + patch_kw=dict(facecolor="lightgrey"), + legend_kw=legend_kw, + ) + + sizes = [10, 5] + labels = [f"{s} GW" for s in sizes] + scale = 1e3 / linewidth_factor + sizes = [s * scale for s in sizes] + + legend_kw = dict( + loc="upper left", + bbox_to_anchor=(0.27, 1.06), + frameon=False, + labelspacing=0.8, + handletextpad=1, + title=title, + ) + + add_legend_lines( + ax, sizes, labels, patch_kw=dict(color="lightgrey"), legend_kw=legend_kw + ) + + legend_kw = dict( + bbox_to_anchor=(1.52, 1.04), + frameon=False, + ) + + fig.savefig(snakemake.output[f"map_{year}"], bbox_inches="tight") + + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake( + "plot_power_network_perfect", + simpl="", + opts="", + clusters="37", + ll="v1.0", + sector_opts="4380H-T-H-B-I-A-dist1", + ) + + configure_logging(snakemake) + + n = pypsa.Network(snakemake.input.network) + + regions = gpd.read_file(snakemake.input.regions).set_index("name") + + map_opts = snakemake.params.plotting["map"] + + if map_opts["boundaries"] is None: + map_opts["boundaries"] = regions.total_bounds[[0, 2, 1, 3]] + [-1, 1, -1, 1] + + proj = load_projection(snakemake.params.plotting) + + plot_map_perfect(n) From 3f112f0e957d804e3a556a37b02ab4250c31e114 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 25 Jan 2024 20:37:33 +0100 Subject: [PATCH 200/591] incorporate network plots in rule --- Snakefile | 15 +++++++++++++++ doc/release_notes.rst | 3 --- rules/postprocess.smk | 20 -------------------- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/Snakefile b/Snakefile index 14c9e821..76ea7b80 100644 --- a/Snakefile +++ b/Snakefile @@ -75,6 +75,21 @@ if config["foresight"] == "perfect": rule all: input: RESULTS + "graphs/costs.pdf", + expand( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", + **config["scenario"] + ), + expand( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", + **config["scenario"] + ), + expand( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", + **config["scenario"] + ), default_target: True diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 5bcaf0d2..7ffbe63c 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -40,9 +40,6 @@ Upcoming Release * The rule ``plot_network`` has been split into separate rules for plotting electricity, hydrogen and gas networks. -* Added new collection rule ``plot_all`` which should be used instead of - ``plot_summary``. This allows running the rule :mod:`make_summary` and - :mod:`plot_summary` even if the network plotting rules fail. PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 6db3079a..22cefcbd 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -202,26 +202,6 @@ rule plot_summary: "../scripts/plot_summary.py" -rule plot_all: - input: - RESULTS + "graphs/costs.pdf", - expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", - **config["scenario"] - ), - expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", - **config["scenario"] - ), - expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", - **config["scenario"] - ), - - STATISTICS_BARPLOTS = [ "capacity_factor", "installed_capacity", From 30ccde5b908aa680ea858fcdb08b09b593e901cf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 19:39:07 +0000 Subject: [PATCH 201/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/postprocess.smk | 2 -- scripts/plot_gas_network.py | 5 +++-- scripts/plot_hydrogen_network.py | 6 +++--- scripts/plot_power_network.py | 3 ++- scripts/plot_power_network_perfect.py | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 22cefcbd..f7c50733 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -32,7 +32,6 @@ if config["foresight"] != "perfect": script: "../scripts/plot_power_network.py" - rule plot_hydrogen_network: params: plotting=config["plotting"], @@ -56,7 +55,6 @@ if config["foresight"] != "perfect": script: "../scripts/plot_hydrogen_network.py" - rule plot_gas_network: params: plotting=config["plotting"], diff --git a/scripts/plot_gas_network.py b/scripts/plot_gas_network.py index a72c5c56..cd515e96 100644 --- a/scripts/plot_gas_network.py +++ b/scripts/plot_gas_network.py @@ -3,7 +3,8 @@ # # SPDX-License-Identifier: MIT """ -Creates map of optimised gas network, storage and selected other infrastructure. +Creates map of optimised gas network, storage and selected other +infrastructure. """ import logging @@ -13,8 +14,8 @@ import matplotlib.pyplot as plt import pandas as pd import pypsa from _helpers import configure_logging -from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches from plot_power_network import assign_location, load_projection +from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches logger = logging.getLogger(__name__) diff --git a/scripts/plot_hydrogen_network.py b/scripts/plot_hydrogen_network.py index 13728553..a1183311 100644 --- a/scripts/plot_hydrogen_network.py +++ b/scripts/plot_hydrogen_network.py @@ -3,7 +3,8 @@ # # SPDX-License-Identifier: MIT """ -Creates map of optimised hydrogen network, storage and selected other infrastructure. +Creates map of optimised hydrogen network, storage and selected other +infrastructure. """ import logging @@ -13,9 +14,8 @@ import matplotlib.pyplot as plt import pandas as pd import pypsa from _helpers import configure_logging -from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches - from plot_power_network import assign_location, load_projection +from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches logger = logging.getLogger(__name__) diff --git a/scripts/plot_power_network.py b/scripts/plot_power_network.py index 48aa01e3..271e638d 100644 --- a/scripts/plot_power_network.py +++ b/scripts/plot_power_network.py @@ -14,12 +14,13 @@ import geopandas as gpd import matplotlib.pyplot as plt import pandas as pd import pypsa -from plot_summary import preferred_order, rename_techs from _helpers import configure_logging +from plot_summary import preferred_order, rename_techs from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches logger = logging.getLogger(__name__) + def rename_techs_tyndp(tech): tech = rename_techs(tech) if "heat pump" in tech or "resistive heater" in tech: diff --git a/scripts/plot_power_network_perfect.py b/scripts/plot_power_network_perfect.py index ce8afef0..ff576d33 100644 --- a/scripts/plot_power_network_perfect.py +++ b/scripts/plot_power_network_perfect.py @@ -14,9 +14,9 @@ import matplotlib.pyplot as plt import pandas as pd import pypsa from _helpers import configure_logging -from pypsa.plot import add_legend_circles, add_legend_lines -from plot_power_network import assign_location, rename_techs_tyndp, load_projection +from plot_power_network import assign_location, load_projection, rename_techs_tyndp from plot_summary import preferred_order +from pypsa.plot import add_legend_circles, add_legend_lines logger = logging.getLogger(__name__) From a2cd042472ac6e4148afeb651337e812eb6b2092 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 14 Aug 2023 18:25:58 +0200 Subject: [PATCH 202/591] plot clustered network topology before optimisation --- Snakefile | 1 + rules/postprocess.smk | 20 +++++++ scripts/plot_power_network_clustered.py | 79 +++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 scripts/plot_power_network_clustered.py diff --git a/Snakefile b/Snakefile index 76ea7b80..23835a7e 100644 --- a/Snakefile +++ b/Snakefile @@ -75,6 +75,7 @@ if config["foresight"] == "perfect": rule all: input: RESULTS + "graphs/costs.pdf", + expand(RESULTS + "maps/power-network-{clusters}.pdf", **config["scenario"]), expand( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", diff --git a/rules/postprocess.smk b/rules/postprocess.smk index f7c50733..d275279e 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -9,6 +9,26 @@ localrules: if config["foresight"] != "perfect": + rule plot_power_network_clustered: + params: + plotting=config["plotting"], + input: + network=RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", + regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + rc="matplotlibrc", + output: + map=RESULTS + "maps/power-network-{clusters}.pdf", + threads: 1 + resources: + mem_mb=4000, + benchmark: + BENCHMARKS + "plot_power_network_clustered/elec_s{simpl}_{clusters}" + conda: + "../envs/environment.yaml" + script: + "../scripts/plot_power_network_clustered.py" + + rule plot_power_network: params: plotting=config["plotting"], diff --git a/scripts/plot_power_network_clustered.py b/scripts/plot_power_network_clustered.py new file mode 100644 index 00000000..e1140fd6 --- /dev/null +++ b/scripts/plot_power_network_clustered.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2023-2024 PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Plot clustered electricity transmission network. +""" + +import pypsa +import geopandas as gpd +import matplotlib.pyplot as plt +import cartopy.crs as ccrs +from matplotlib.lines import Line2D +from pypsa.plot import add_legend_lines + +from plot_power_network import load_projection + + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake( + "plot_power_network_clustered", + clusters=128, + configfiles=["../../config/config.test.yaml"] + ) + + plt.style.use(snakemake.input.rc) + + lw_factor = 2e3 + + n = pypsa.Network(snakemake.input.network) + + regions = gpd.read_file(snakemake.input.regions_onshore).set_index('name') + + proj = load_projection(snakemake.params.plotting) + + fig, ax = plt.subplots(figsize=(8,8), subplot_kw={"projection": proj}) + regions.to_crs(proj.proj4_init).plot( + ax=ax, + facecolor='none', + edgecolor='lightgray', + linewidth=0.75 + ) + n.plot( + ax=ax, + margin=0.06, + line_widths=n.lines.s_nom / lw_factor, + link_colors=n.links.p_nom.apply( + lambda x: "darkseagreen" if x > 0 else "skyblue" + ), + link_widths=2., + ) + + sizes = [10, 20] + labels = [f"HVAC ({s} GW)" for s in sizes] + scale = 1e3 / lw_factor + sizes = [s * scale for s in sizes] + + legend_kw = dict( + loc=[0.25, 0.9], + frameon=False, + labelspacing=0.5, + handletextpad=1, + fontsize=13, + ) + + add_legend_lines( + ax, sizes, labels, patch_kw=dict(color="rosybrown"), legend_kw=legend_kw + ) + + handles = [ + Line2D([0], [0], color="darkseagreen", lw=2), + Line2D([0], [0], color="skyblue", lw=2), + ] + plt.legend(handles, ["HVDC existing", "HVDC planned"], frameon=False, loc=[0., 0.9], fontsize=13) + + plt.savefig(snakemake.output.map, bbox_inches='tight') From 5fcfafe971cdb0b7ccbd31fa4a613d989f499b0d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 19:50:03 +0000 Subject: [PATCH 203/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/postprocess.smk | 4 ++-- scripts/plot_power_network_clustered.py | 31 +++++++++++++------------ 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index d275279e..d1c65ced 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -14,7 +14,8 @@ if config["foresight"] != "perfect": plotting=config["plotting"], input: network=RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", - regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + regions_onshore=RESOURCES + + "regions_onshore_elec_s{simpl}_{clusters}.geojson", rc="matplotlibrc", output: map=RESULTS + "maps/power-network-{clusters}.pdf", @@ -28,7 +29,6 @@ if config["foresight"] != "perfect": script: "../scripts/plot_power_network_clustered.py" - rule plot_power_network: params: plotting=config["plotting"], diff --git a/scripts/plot_power_network_clustered.py b/scripts/plot_power_network_clustered.py index e1140fd6..318afbb9 100644 --- a/scripts/plot_power_network_clustered.py +++ b/scripts/plot_power_network_clustered.py @@ -6,15 +6,13 @@ Plot clustered electricity transmission network. """ -import pypsa +import cartopy.crs as ccrs import geopandas as gpd import matplotlib.pyplot as plt -import cartopy.crs as ccrs +import pypsa from matplotlib.lines import Line2D -from pypsa.plot import add_legend_lines - from plot_power_network import load_projection - +from pypsa.plot import add_legend_lines if __name__ == "__main__": if "snakemake" not in globals(): @@ -23,7 +21,7 @@ if __name__ == "__main__": snakemake = mock_snakemake( "plot_power_network_clustered", clusters=128, - configfiles=["../../config/config.test.yaml"] + configfiles=["../../config/config.test.yaml"], ) plt.style.use(snakemake.input.rc) @@ -32,16 +30,13 @@ if __name__ == "__main__": n = pypsa.Network(snakemake.input.network) - regions = gpd.read_file(snakemake.input.regions_onshore).set_index('name') + regions = gpd.read_file(snakemake.input.regions_onshore).set_index("name") proj = load_projection(snakemake.params.plotting) - fig, ax = plt.subplots(figsize=(8,8), subplot_kw={"projection": proj}) + fig, ax = plt.subplots(figsize=(8, 8), subplot_kw={"projection": proj}) regions.to_crs(proj.proj4_init).plot( - ax=ax, - facecolor='none', - edgecolor='lightgray', - linewidth=0.75 + ax=ax, facecolor="none", edgecolor="lightgray", linewidth=0.75 ) n.plot( ax=ax, @@ -50,7 +45,7 @@ if __name__ == "__main__": link_colors=n.links.p_nom.apply( lambda x: "darkseagreen" if x > 0 else "skyblue" ), - link_widths=2., + link_widths=2.0, ) sizes = [10, 20] @@ -74,6 +69,12 @@ if __name__ == "__main__": Line2D([0], [0], color="darkseagreen", lw=2), Line2D([0], [0], color="skyblue", lw=2), ] - plt.legend(handles, ["HVDC existing", "HVDC planned"], frameon=False, loc=[0., 0.9], fontsize=13) + plt.legend( + handles, + ["HVDC existing", "HVDC planned"], + frameon=False, + loc=[0.0, 0.9], + fontsize=13, + ) - plt.savefig(snakemake.output.map, bbox_inches='tight') + plt.savefig(snakemake.output.map, bbox_inches="tight") From 7becfdea9c044c98224cccf1e6b09a092db4a774 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 25 Jan 2024 20:51:51 +0100 Subject: [PATCH 204/591] resolve merge conflict --- Snakefile | 2 +- rules/postprocess.smk | 3 +-- scripts/plot_power_network_clustered.py | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Snakefile b/Snakefile index 23835a7e..8a256acc 100644 --- a/Snakefile +++ b/Snakefile @@ -75,7 +75,7 @@ if config["foresight"] == "perfect": rule all: input: RESULTS + "graphs/costs.pdf", - expand(RESULTS + "maps/power-network-{clusters}.pdf", **config["scenario"]), + expand(RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", **config["scenario"]), expand( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", diff --git a/rules/postprocess.smk b/rules/postprocess.smk index d1c65ced..1ca6eb4d 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -16,9 +16,8 @@ if config["foresight"] != "perfect": network=RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", - rc="matplotlibrc", output: - map=RESULTS + "maps/power-network-{clusters}.pdf", + map=RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", threads: 1 resources: mem_mb=4000, diff --git a/scripts/plot_power_network_clustered.py b/scripts/plot_power_network_clustered.py index 318afbb9..8217ac2e 100644 --- a/scripts/plot_power_network_clustered.py +++ b/scripts/plot_power_network_clustered.py @@ -24,8 +24,6 @@ if __name__ == "__main__": configfiles=["../../config/config.test.yaml"], ) - plt.style.use(snakemake.input.rc) - lw_factor = 2e3 n = pypsa.Network(snakemake.input.network) From a56bd830f8b5808189020414efcae11a7bfc184a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 19:53:23 +0000 Subject: [PATCH 205/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- Snakefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index 8a256acc..2021b49f 100644 --- a/Snakefile +++ b/Snakefile @@ -75,7 +75,10 @@ if config["foresight"] == "perfect": rule all: input: RESULTS + "graphs/costs.pdf", - expand(RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", **config["scenario"]), + expand( + RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", + **config["scenario"] + ), expand( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", From 707adcec69d13e6c1e628fb80ebb7cf64c5aff82 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 26 Jan 2024 09:15:04 +0100 Subject: [PATCH 206/591] all: make H2 and CH4 maps dependent on network config --- Snakefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Snakefile b/Snakefile index 2021b49f..211e7540 100644 --- a/Snakefile +++ b/Snakefile @@ -86,12 +86,16 @@ rule all: ), expand( RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf" + if config["sector"]["H2_network"] + else [], **config["scenario"] ), expand( RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf" + if config["sector"]["gas_network"] + else [], **config["scenario"] ), default_target: True From ae825d82dcebae7ab67f591329fe8e6140a96d72 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 26 Jan 2024 12:10:39 +0100 Subject: [PATCH 207/591] prepare_sector_network: reorder buses for dac components --- doc/release_notes.rst | 2 ++ scripts/add_electricity.py | 2 +- scripts/prepare_sector_network.py | 22 +++++++++++----------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 93d1a268..94d5c55f 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -37,6 +37,8 @@ Upcoming Release * Add the option to customise map projection in plotting config. +* The order of buses (bus0, bus1, ...) for DAC components has changed to meet the convention of the other components. Therefore, `bus0` refers to the electricity bus (input), `bus1` to the heat bus (input), 'bus2' to the CO2 atmosphere bus (input), and `bus3` to the CO2 storage bus (output). + PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index c9e5abca..8a1086bd 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -288,7 +288,7 @@ def attach_load(n, regions, load, nuts3_shapes, ua_md_gdp, countries, scaling=1. ua_md_gdp = pd.read_csv(ua_md_gdp, dtype={"name": "str"}).set_index("name") - logger.info(f"Load data scaled with scalling factor {scaling}.") + logger.info(f"Load data scaled by factor {scaling}.") opsd_load *= scaling nuts3 = gpd.read_file(nuts3_shapes).set_index("index") diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index d24feb79..3ea8c8dd 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -710,27 +710,27 @@ def add_dac(n, costs): heat_buses = n.buses.index[n.buses.carrier.isin(heat_carriers)] locations = n.buses.location[heat_buses] - efficiency2 = -( + electricity_input = ( costs.at["direct air capture", "electricity-input"] + costs.at["direct air capture", "compression-electricity-input"] - ) - efficiency3 = -( + ) # MWh_el / tCO2 + heat_input = ( costs.at["direct air capture", "heat-input"] - costs.at["direct air capture", "compression-heat-output"] - ) + ) # MWh_th / tCO2 n.madd( "Link", heat_buses.str.replace(" heat", " DAC"), - bus0="co2 atmosphere", - bus1=spatial.co2.df.loc[locations, "nodes"].values, - bus2=locations.values, - bus3=heat_buses, + bus0=locations.values, + bus1=heat_buses, + bus2="co2 atmosphere", + bus3=spatial.co2.df.loc[locations, "nodes"].values, carrier="DAC", capital_cost=costs.at["direct air capture", "fixed"], - efficiency=1.0, - efficiency2=efficiency2, - efficiency3=efficiency3, + efficiency=-heat_input / electricity_input, + efficiency2=-electricity_input, + efficiency3=electricity_input, p_nom_extendable=True, lifetime=costs.at["direct air capture", "lifetime"], ) From b73c614f5bc122cb78cfa6e594817edfe6538b41 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 26 Jan 2024 16:39:03 +0100 Subject: [PATCH 208/591] plot_gas_network: save max usage calculation --- scripts/plot_gas_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/plot_gas_network.py b/scripts/plot_gas_network.py index cd515e96..e2953604 100644 --- a/scripts/plot_gas_network.py +++ b/scripts/plot_gas_network.py @@ -97,7 +97,7 @@ def plot_ch4_map(n): link_widths_orig = n.links.p_nom / linewidth_factor link_widths_orig[n.links.p_nom < line_lower_threshold] = 0.0 - max_usage = n.links_t.p0.abs().max(axis=0) + max_usage = n.links_t.p0[n.links.index].abs().max(axis=0) link_widths_used = max_usage / linewidth_factor link_widths_used[max_usage < line_lower_threshold] = 0.0 From f84e73006fa478e9a3b176081615eb34ad1ae216 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 26 Jan 2024 17:05:38 +0100 Subject: [PATCH 209/591] postprocess: keep network plotting triggers in make_summary --- Snakefile | 23 ----------------------- rules/postprocess.smk | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Snakefile b/Snakefile index 211e7540..14c9e821 100644 --- a/Snakefile +++ b/Snakefile @@ -75,29 +75,6 @@ if config["foresight"] == "perfect": rule all: input: RESULTS + "graphs/costs.pdf", - expand( - RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", - **config["scenario"] - ), - expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", - **config["scenario"] - ), - expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf" - if config["sector"]["H2_network"] - else [], - **config["scenario"] - ), - expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf" - if config["sector"]["gas_network"] - else [], - **config["scenario"] - ), default_target: True diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 1ca6eb4d..d01f90db 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -158,6 +158,29 @@ rule make_summary: costs="data/costs_{}.csv".format(config["costs"]["year"]) if config["foresight"] == "overnight" else "data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), + expand( + RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", + **config["scenario"] + ), + costs_plot=expand( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", + **config["scenario"] + ), + h2_plot=expand( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf" + if config["sector"]["H2_network"] + else [], + **config["scenario"] + ), + ch4_plot=expand( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf" + if config["sector"]["gas_network"] + else [], + **config["scenario"] + ), output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", nodal_capacities=RESULTS + "csvs/nodal_capacities.csv", From d6288d3d4dfed4bb2ce58fa4053eabf0123e3404 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 16:06:20 +0000 Subject: [PATCH 210/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/postprocess.smk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index d01f90db..88b56e2f 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -150,6 +150,10 @@ rule make_summary: scenario=config["scenario"], RDIR=RDIR, input: + expand( + RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", + **config["scenario"] + ), networks=expand( RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -158,10 +162,6 @@ rule make_summary: costs="data/costs_{}.csv".format(config["costs"]["year"]) if config["foresight"] == "overnight" else "data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), - expand( - RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", - **config["scenario"] - ), costs_plot=expand( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", From 8cb7396c112de5e80e04a1ba115ea5a733a4d7da Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 26 Jan 2024 17:07:19 +0100 Subject: [PATCH 211/591] make_summary: name all inputs --- rules/postprocess.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index d01f90db..50fe634c 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -158,7 +158,7 @@ rule make_summary: costs="data/costs_{}.csv".format(config["costs"]["year"]) if config["foresight"] == "overnight" else "data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), - expand( + ac_plot=expand( RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", **config["scenario"] ), From 08a4d196af265ba1e4fc5729b33f654cdd8ffc7b Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 26 Jan 2024 23:16:33 +0100 Subject: [PATCH 212/591] ci: add workflow with inhouse package at current master --- .github/workflows/ci-sync.yaml | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 .github/workflows/ci-sync.yaml diff --git a/.github/workflows/ci-sync.yaml b/.github/workflows/ci-sync.yaml new file mode 100644 index 00000000..e5b4006c --- /dev/null +++ b/.github/workflows/ci-sync.yaml @@ -0,0 +1,97 @@ +# SPDX-FileCopyrightText: : 2021-2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: CC0-1.0 + +name: CI - Synced Inhouse Packages + +# Caching method based on and described by: +# epassaro (2021): https://dev.to/epassaro/caching-anaconda-environments-in-github-actions-5hde +# and code in GitHub repo: https://github.com/epassaro/cache-conda-envs + +on: + push: + branches: + - master + pull_request: + branches: + - master + schedule: + - cron: "0 5 * * TUE" + +env: + DATA_CACHE_NUMBER: 2 + +jobs: + build: + + strategy: + fail-fast: false + max-parallel: 1 + + runs-on: ubuntu-latest + + defaults: + run: + shell: bash -l {0} + + steps: + - uses: actions/checkout@v3 + + - name: Setup secrets + run: | + echo -ne "url: ${CDSAPI_URL}\nkey: ${CDSAPI_TOKEN}\n" > ~/.cdsapirc + + - name: Add solver to environment + run: | + echo -e "- glpk\n- ipopt<3.13.3" >> envs/environment.yaml + if: ${{ matrix.os }} == 'windows-latest' + + - name: Add solver to environment + run: | + echo -e "- glpk\n- ipopt" >> envs/environment.yaml + if: ${{ matrix.os }} != 'windows-latest' + + - name: Setup micromamba + uses: mamba-org/setup-micromamba@v1 + with: + micromamba-version: latest + environment-file: envs/environment.yaml + log-level: debug + init-shell: bash + cache-environment: true + cache-downloads: true + + # install inhouse packages from master branch with pip + - name: Install inhouse packages + run: | + pip install git+https://github.com/PyPSA/atlite.git@master git+https://github.com/PyPSA/powerplantmatching.git@master git+https://github.com/PyPSA/linopy.git@master + + + - name: Set cache dates + run: | + echo "WEEK=$(date +'%Y%U')" >> $GITHUB_ENV + + - name: Cache data and cutouts folders + uses: actions/cache@v3 + with: + path: | + data + cutouts + key: data-cutouts-${{ env.WEEK }}-${{ env.DATA_CACHE_NUMBER }} + + - name: Test snakemake workflow + run: | + snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime + snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime + snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime + snakemake -call all --configfile config/test/config.perfect.yaml --rerun-triggers=mtime + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: resources-results + path: | + resources + results + if-no-files-found: warn + retention-days: 1 From ae1b83121d0dfc4afcd0206f1ae1b0a2cf5808be Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 26 Jan 2024 23:20:03 +0100 Subject: [PATCH 213/591] prepare_sector: fix dac co2 input/output efficiencies --- scripts/prepare_sector_network.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 3ea8c8dd..52b805d4 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -729,8 +729,8 @@ def add_dac(n, costs): carrier="DAC", capital_cost=costs.at["direct air capture", "fixed"], efficiency=-heat_input / electricity_input, - efficiency2=-electricity_input, - efficiency3=electricity_input, + efficiency2=-1 / electricity_input, + efficiency3=1 / electricity_input, p_nom_extendable=True, lifetime=costs.at["direct air capture", "lifetime"], ) From 7b0356803f07267be1d4bee8b2a1c1e5f16f052b Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 29 Jan 2024 09:01:08 +0100 Subject: [PATCH 214/591] prepare_sector: adjust DAC costs --- 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 3fa46605..9fba84ea 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -727,7 +727,7 @@ def add_dac(n, costs): bus2="co2 atmosphere", bus3=spatial.co2.df.loc[locations, "nodes"].values, carrier="DAC", - capital_cost=costs.at["direct air capture", "fixed"], + capital_cost=costs.at["direct air capture", "fixed"] / electricity_input, efficiency=-heat_input / electricity_input, efficiency2=-1 / electricity_input, efficiency3=1 / electricity_input, From 81e7c4eb67a8385eee5f5701c2ee134b67fd585a Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 29 Jan 2024 12:08:56 +0100 Subject: [PATCH 215/591] remove pyomo dependency in cluster network, use scip as OS solver --- envs/environment.yaml | 3 +-- scripts/cluster_network.py | 41 ++++++++++++++------------------------ 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/envs/environment.yaml b/envs/environment.yaml index 6ff4b7f1..895b271a 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -36,7 +36,7 @@ dependencies: - networkx - scipy - shapely>=2.0 -- pyomo +- scipopt - matplotlib - proj - fiona @@ -47,7 +47,6 @@ dependencies: - tabula-py - pyxlsb - graphviz -- ipopt # Keep in conda environment when calling ipython - ipython diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 01af29aa..a18121e8 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -126,10 +126,10 @@ import warnings from functools import reduce import geopandas as gpd +import linopy import matplotlib.pyplot as plt import numpy as np import pandas as pd -import pyomo.environ as po import pypsa import seaborn as sns from _helpers import configure_logging, update_p_nom_max @@ -214,7 +214,7 @@ def get_feature_for_hac(n, buses_i=None, feature=None): return feature_data -def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="cbc"): +def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="scip"): """ Determine the number of clusters per country. """ @@ -254,31 +254,20 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="cbc"): L.sum(), 1.0, rtol=1e-3 ), f"Country weights L must sum up to 1.0 when distributing clusters. Is {L.sum()}." - m = po.ConcreteModel() - - def n_bounds(model, *n_id): - return (1, N[n_id]) - - m.n = po.Var(list(L.index), bounds=n_bounds, domain=po.Integers) - m.tot = po.Constraint(expr=(po.summation(m.n) == n_clusters)) - m.objective = po.Objective( - expr=sum((m.n[i] - L.loc[i] * n_clusters) ** 2 for i in L.index), - sense=po.minimize, + m = linopy.Model() + clusters = m.add_variables( + lower=1, upper=N, coords=[L.index], name="n", integer=True ) - - opt = po.SolverFactory(solver_name) - if solver_name == "appsi_highs" or not opt.has_capability("quadratic_objective"): - logger.warning( - f"The configured solver `{solver_name}` does not support quadratic objectives. Falling back to `ipopt`." - ) - opt = po.SolverFactory("ipopt") - - results = opt.solve(m) - assert ( - results["Solver"][0]["Status"] == "ok" - ), f"Solver returned non-optimally: {results}" - - return pd.Series(m.n.get_values(), index=L.index).round().astype(int) + m.add_constraints(clusters.sum() == n_clusters, name="tot") + m.objective = ( + clusters * clusters - 2 * clusters * L * n_clusters + ) # + (L * n_clusters) ** 2 (constant) + if solver_name == "gurobi": + logging.getLogger("gurobipy").propagate = False + else: + solver_name = "scip" + m.solve(solver_name=solver_name) + return m.solution["n"].to_series().astype(int) def busmap_for_n_clusters( From ca1628a585dcfe1749c464cdbc5e1f5af7a0405a Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 29 Jan 2024 12:22:42 +0100 Subject: [PATCH 216/591] cluster_network: tidy up --- scripts/cluster_network.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index a18121e8..b63e7f89 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -122,6 +122,7 @@ Exemplary unsolved network clustered to 37 nodes: """ import logging +import os import warnings from functools import reduce @@ -259,12 +260,14 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="scip"): lower=1, upper=N, coords=[L.index], name="n", integer=True ) m.add_constraints(clusters.sum() == n_clusters, name="tot") - m.objective = ( - clusters * clusters - 2 * clusters * L * n_clusters - ) # + (L * n_clusters) ** 2 (constant) + # leave out constant in objective L * n_clusters ** 2 + m.objective = (clusters * clusters - 2 * clusters * L * n_clusters).sum() if solver_name == "gurobi": logging.getLogger("gurobipy").propagate = False - else: + elif solver_name != "scip": + logger.info( + f"The configured solver `{solver_name}` does not support quadratic objectives. Falling back to `scip`." + ) solver_name = "scip" m.solve(solver_name=solver_name) return m.solution["n"].to_series().astype(int) @@ -374,7 +377,7 @@ def clustering_for_n_clusters( aggregate_carriers=None, line_length_factor=1.25, aggregation_strategies=dict(), - solver_name="cbc", + solver_name="scip", algorithm="hac", feature=None, extended_link_costs=0, @@ -451,7 +454,6 @@ if __name__ == "__main__": params = snakemake.params solver_name = snakemake.config["solving"]["solver"]["name"] - solver_name = "appsi_highs" if solver_name == "highs" else solver_name n = pypsa.Network(snakemake.input.network) From 3ceffabc944f8f3d881fc749ab05671e92f19019 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 18:30:17 +0000 Subject: [PATCH 217/591] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 23.12.1 → 24.1.1](https://github.com/psf/black-pre-commit-mirror/compare/23.12.1...24.1.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 a38e6800..d90f5cb9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,7 +51,7 @@ repos: # Formatting with "black" coding style - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.12.1 + rev: 24.1.1 hooks: # Format Python files - id: black From d2f2d4ab0b6a77446573b6c85ad1927861804d69 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 18:31:03 +0000 Subject: [PATCH 218/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/build_retro_cost.py | 49 ++++++++++++++++++------------- scripts/plot_summary.py | 12 ++++---- scripts/prepare_sector_network.py | 21 ++++++------- scripts/simplify_network.py | 6 ++-- scripts/solve_network.py | 8 +++-- 5 files changed, 55 insertions(+), 41 deletions(-) diff --git a/scripts/build_retro_cost.py b/scripts/build_retro_cost.py index 67440263..bd285e18 100755 --- a/scripts/build_retro_cost.py +++ b/scripts/build_retro_cost.py @@ -607,21 +607,28 @@ def calculate_costs(u_values, l, cost_retro, window_assumptions): # noqa: E741 """ return u_values.apply( lambda x: ( - cost_retro.loc[x.name[3], "cost_var"] - * 100 - * float(l) - * l_weight.loc[x.name[3]].iloc[0] - + cost_retro.loc[x.name[3], "cost_fix"] - ) - * x.A_element - / x.A_C_Ref - if x.name[3] != "Window" - else ( - (window_cost(x[f"new_U_{l}"], cost_retro, window_assumptions) * x.A_element) + ( + cost_retro.loc[x.name[3], "cost_var"] + * 100 + * float(l) + * l_weight.loc[x.name[3]].iloc[0] + + cost_retro.loc[x.name[3], "cost_fix"] + ) + * x.A_element / x.A_C_Ref - ) - if x.value > window_limit(float(l), window_assumptions) - else 0, + if x.name[3] != "Window" + else ( + ( + ( + window_cost(x[f"new_U_{l}"], cost_retro, window_assumptions) + * x.A_element + ) + / x.A_C_Ref + ) + if x.value > window_limit(float(l), window_assumptions) + else 0 + ) + ), axis=1, ) @@ -648,12 +655,14 @@ def calculate_new_u(u_values, l, l_weight, window_assumptions, k=0.035): # noqa k: thermal conductivity """ return u_values.apply( - lambda x: k / ((k / x.value) + (float(l) * l_weight.loc[x.name[3]])) - if x.name[3] != "Window" - else ( - min(x.value, u_retro_window(float(l), window_assumptions)) - if x.value > window_limit(float(l), window_assumptions) - else x.value + lambda x: ( + k / ((k / x.value) + (float(l) * l_weight.loc[x.name[3]])) + if x.name[3] != "Window" + else ( + min(x.value, u_retro_window(float(l), window_assumptions)) + if x.value > window_limit(float(l), window_assumptions) + else x.value + ) ), axis=1, ) diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index 92bf726c..cfb32441 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -281,12 +281,14 @@ 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", "4"]) + ( + i[:-1] + if ( + (i not in ["co2", "NH3", "H2"]) + and (i[-1:] in ["0", "1", "2", "3", "4"]) + ) + else i ) - else i for i in df.index ] diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 22fb1bcc..42def055 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -458,9 +458,9 @@ def update_wind_solar_costs(n, costs): ) ) - n.generators.loc[ - n.generators.carrier == tech, "capital_cost" - ] = capital_cost.rename(index=lambda node: node + " " + tech) + n.generators.loc[n.generators.carrier == tech, "capital_cost"] = ( + capital_cost.rename(index=lambda node: node + " " + tech) + ) def add_carrier_buses(n, carrier, nodes=None): @@ -2932,9 +2932,11 @@ def add_industry(n, costs): nodes, suffix=" low-temperature heat for industry", bus=[ - node + " urban central heat" - if node + " urban central heat" in n.buses.index - else node + " services urban decentral heat" + ( + node + " urban central heat" + if node + " urban central heat" in n.buses.index + else node + " services urban decentral heat" + ) for node in nodes ], carrier="low-temperature heat for industry", @@ -3529,10 +3531,9 @@ def lossy_bidirectional_links(n, carrier, efficiencies={}): ) n.links.loc[carrier_i, "p_min_pu"] = 0 - n.links.loc[ - carrier_i, "efficiency" - ] = efficiency_static * efficiency_per_1000km ** ( - n.links.loc[carrier_i, "length"] / 1e3 + n.links.loc[carrier_i, "efficiency"] = ( + efficiency_static + * efficiency_per_1000km ** (n.links.loc[carrier_i, "length"] / 1e3) ) rev_links = ( n.links.loc[carrier_i].copy().rename({"bus0": "bus1", "bus1": "bus0"}, axis=1) diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index f8629ea7..31bc8f4e 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -468,9 +468,9 @@ def aggregate_to_substations(n, aggregation_strategies=dict(), buses_i=None): dijkstra(adj, directed=False, indices=bus_indexer), buses_i, n.buses.index ) - dist[ - buses_i - ] = np.inf # bus in buses_i should not be assigned to different bus in buses_i + dist[buses_i] = ( + np.inf + ) # bus in buses_i should not be assigned to different bus in buses_i for c in n.buses.country.unique(): incountry_b = n.buses.country == c diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 23e9b0f8..a1d790a7 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -703,9 +703,11 @@ def add_lossy_bidirectional_link_constraints(n): def get_backward_i(forward_i): return pd.Index( [ - re.sub(r"-(\d{4})$", r"-reversed-\1", s) - if re.search(r"-\d{4}$", s) - else s + "-reversed" + ( + re.sub(r"-(\d{4})$", r"-reversed-\1", s) + if re.search(r"-\d{4}$", s) + else s + "-reversed" + ) for s in forward_i ] ) From 56b22a3b4ea3e95e521bf4234b21899a963eefb5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 30 Jan 2024 10:29:08 +0100 Subject: [PATCH 219/591] env: correct pyscipopt dependency cluster_network: address deprecation warning --- envs/environment.yaml | 2 +- scripts/cluster_network.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/envs/environment.yaml b/envs/environment.yaml index 895b271a..d92eb696 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -36,7 +36,7 @@ dependencies: - networkx - scipy - shapely>=2.0 -- scipopt +- pyscipopt - matplotlib - proj - fiona diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index b63e7f89..2c69b9af 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -364,7 +364,7 @@ def busmap_for_n_clusters( return ( n.buses.groupby(["country", "sub_network"], group_keys=False) - .apply(busmap_for_country) + .apply(busmap_for_country, include_groups=False) .squeeze() .rename("busmap") ) From 662252d20fa4ad488c95847c8ea1136ed6d0b629 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 30 Jan 2024 11:06:05 +0100 Subject: [PATCH 220/591] update release notes --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 86763287..c20f1ebe 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -60,6 +60,8 @@ Upcoming Release * The rule ``plot_network`` has been split into separate rules for plotting electricity, hydrogen and gas networks. +* To determine the optimal topology to meet the number of clusters, the workflow used pyomo in combination with ``ipopt`` or ``gurobi``. This dependency has been replaced by using ``linopy`` in combination with ``scipopt`` or ``gurobi``. The environment file has been updated accordingly. + PyPSA-Eur 0.9.0 (5th January 2024) ================================== From 9c558a3e460355d212d8d4e28f7e4f0dd87441ae Mon Sep 17 00:00:00 2001 From: Fabian Hofmann Date: Tue, 30 Jan 2024 17:37:44 +0100 Subject: [PATCH 221/591] Update scripts/cluster_network.py Co-authored-by: Fabian Neumann --- scripts/cluster_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 2c69b9af..39b6ad96 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -260,7 +260,7 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="scip"): lower=1, upper=N, coords=[L.index], name="n", integer=True ) m.add_constraints(clusters.sum() == n_clusters, name="tot") - # leave out constant in objective L * n_clusters ** 2 + # leave out constant in objective (L * n_clusters) ** 2 m.objective = (clusters * clusters - 2 * clusters * L * n_clusters).sum() if solver_name == "gurobi": logging.getLogger("gurobipy").propagate = False From b7750d21eaa58fd1f03af8b51ce39dd745290f71 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Jan 2024 09:44:13 +0100 Subject: [PATCH 222/591] CI: use scip and highs as solvers for clustering and solving, instead of ipopt and glpk --- .github/workflows/ci.yaml | 10 ---------- config/test/config.electricity.yaml | 4 ++-- config/test/config.myopic.yaml | 4 ++-- config/test/config.overnight.yaml | 4 ++-- config/test/config.perfect.yaml | 4 ++-- doc/release_notes.rst | 5 +++++ envs/environment.yaml | 1 + 7 files changed, 14 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c0fb745d..cf52172f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -46,16 +46,6 @@ jobs: run: | echo -ne "url: ${CDSAPI_URL}\nkey: ${CDSAPI_TOKEN}\n" > ~/.cdsapirc - - name: Add solver to environment - run: | - echo -e "- glpk\n- ipopt<3.13.3" >> envs/environment.yaml - if: ${{ matrix.os }} == 'windows-latest' - - - name: Add solver to environment - run: | - echo -e "- glpk\n- ipopt" >> envs/environment.yaml - if: ${{ matrix.os }} != 'windows-latest' - - name: Setup micromamba uses: mamba-org/setup-micromamba@v1 with: diff --git a/config/test/config.electricity.yaml b/config/test/config.electricity.yaml index b750bf62..ef9bfdc0 100644 --- a/config/test/config.electricity.yaml +++ b/config/test/config.electricity.yaml @@ -69,8 +69,8 @@ lines: solving: solver: - name: glpk - options: "glpk-default" + name: highs + options: "highs-default" plotting: diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index 2dab7b04..1da51b36 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -73,8 +73,8 @@ industry: solving: solver: - name: glpk - options: glpk-default + name: highs + options: highs-default mem: 4000 plotting: diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index 6d1900cf..dffdab5a 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -65,8 +65,8 @@ sector: solving: solver: - name: glpk - options: glpk-default + name: highs + options: highs-default mem: 4000 plotting: diff --git a/config/test/config.perfect.yaml b/config/test/config.perfect.yaml index f20a2c9f..8a5a9cce 100644 --- a/config/test/config.perfect.yaml +++ b/config/test/config.perfect.yaml @@ -75,8 +75,8 @@ industry: solving: solver: - name: glpk - options: glpk-default + name: highs + options: highs-default mem: 4000 plotting: diff --git a/doc/release_notes.rst b/doc/release_notes.rst index c20f1ebe..55e0ad97 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -62,6 +62,11 @@ Upcoming Release * To determine the optimal topology to meet the number of clusters, the workflow used pyomo in combination with ``ipopt`` or ``gurobi``. This dependency has been replaced by using ``linopy`` in combination with ``scipopt`` or ``gurobi``. The environment file has been updated accordingly. +* The ``highs`` solver was added to the default environment file. + +* The default solver for testing the workflow in the CI has been changed from ``glpk`` to ``highs``. + + PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/envs/environment.yaml b/envs/environment.yaml index d92eb696..235d7729 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -59,3 +59,4 @@ dependencies: - pip: - tsam>=2.3.1 + - highspy From 718dbbb1c50ba25fb004925e993e517c2e8dc10e Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Jan 2024 09:54:58 +0100 Subject: [PATCH 223/591] CI: integrate inhouse tests into main CI yaml --- .github/workflows/ci-sync.yaml | 97 ---------------------------------- .github/workflows/ci.yaml | 14 ++++- 2 files changed, 13 insertions(+), 98 deletions(-) delete mode 100644 .github/workflows/ci-sync.yaml diff --git a/.github/workflows/ci-sync.yaml b/.github/workflows/ci-sync.yaml deleted file mode 100644 index e5b4006c..00000000 --- a/.github/workflows/ci-sync.yaml +++ /dev/null @@ -1,97 +0,0 @@ -# SPDX-FileCopyrightText: : 2021-2023 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: CC0-1.0 - -name: CI - Synced Inhouse Packages - -# Caching method based on and described by: -# epassaro (2021): https://dev.to/epassaro/caching-anaconda-environments-in-github-actions-5hde -# and code in GitHub repo: https://github.com/epassaro/cache-conda-envs - -on: - push: - branches: - - master - pull_request: - branches: - - master - schedule: - - cron: "0 5 * * TUE" - -env: - DATA_CACHE_NUMBER: 2 - -jobs: - build: - - strategy: - fail-fast: false - max-parallel: 1 - - runs-on: ubuntu-latest - - defaults: - run: - shell: bash -l {0} - - steps: - - uses: actions/checkout@v3 - - - name: Setup secrets - run: | - echo -ne "url: ${CDSAPI_URL}\nkey: ${CDSAPI_TOKEN}\n" > ~/.cdsapirc - - - name: Add solver to environment - run: | - echo -e "- glpk\n- ipopt<3.13.3" >> envs/environment.yaml - if: ${{ matrix.os }} == 'windows-latest' - - - name: Add solver to environment - run: | - echo -e "- glpk\n- ipopt" >> envs/environment.yaml - if: ${{ matrix.os }} != 'windows-latest' - - - name: Setup micromamba - uses: mamba-org/setup-micromamba@v1 - with: - micromamba-version: latest - environment-file: envs/environment.yaml - log-level: debug - init-shell: bash - cache-environment: true - cache-downloads: true - - # install inhouse packages from master branch with pip - - name: Install inhouse packages - run: | - pip install git+https://github.com/PyPSA/atlite.git@master git+https://github.com/PyPSA/powerplantmatching.git@master git+https://github.com/PyPSA/linopy.git@master - - - - name: Set cache dates - run: | - echo "WEEK=$(date +'%Y%U')" >> $GITHUB_ENV - - - name: Cache data and cutouts folders - uses: actions/cache@v3 - with: - path: | - data - cutouts - key: data-cutouts-${{ env.WEEK }}-${{ env.DATA_CACHE_NUMBER }} - - - name: Test snakemake workflow - run: | - snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime - snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime - snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime - snakemake -call all --configfile config/test/config.perfect.yaml --rerun-triggers=mtime - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: resources-results - path: | - resources - results - if-no-files-found: warn - retention-days: 1 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c0fb745d..172d07ac 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -32,7 +32,14 @@ jobs: - ubuntu-latest - macos-latest - windows-latest - + inhouse: + - stable + - master + exclude: + - os: macos-latest + inhouse: master + - os: windows-latest + inhouse: master runs-on: ${{ matrix.os }} defaults: @@ -66,6 +73,11 @@ jobs: cache-environment: true cache-downloads: true + - name: Install inhouse packages + run: | + pip install git+https://github.com/PyPSA/atlite.git@master git+https://github.com/PyPSA/powerplantmatching.git@master git+https://github.com/PyPSA/linopy.git@master + if: ${{ matrix.inhouse }} == 'master' + - name: Set cache dates run: | echo "WEEK=$(date +'%Y%U')" >> $GITHUB_ENV From c4a634659dc008f9e10095e8787e11064a42ae33 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Jan 2024 09:59:31 +0100 Subject: [PATCH 224/591] CI: correct if statement --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 172d07ac..637a0304 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -76,7 +76,7 @@ jobs: - name: Install inhouse packages run: | pip install git+https://github.com/PyPSA/atlite.git@master git+https://github.com/PyPSA/powerplantmatching.git@master git+https://github.com/PyPSA/linopy.git@master - if: ${{ matrix.inhouse }} == 'master' + if: ${{ matrix.inhouse }} == 'master' - name: Set cache dates run: | From df2296ce3effcb953411892ec6abfc70ea2410e1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Jan 2024 12:23:35 +0100 Subject: [PATCH 225/591] ci: only upload artefacts for ubuntu and stable --- .github/workflows/ci.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 637a0304..bba03cd7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -98,7 +98,7 @@ jobs: snakemake -call all --configfile config/test/config.perfect.yaml --rerun-triggers=mtime - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4.3.0 with: name: resources-results path: | @@ -106,3 +106,4 @@ jobs: results if-no-files-found: warn retention-days: 1 + if: matrix.os == 'ubuntu' && matrix.inhouse == 'stable' From bd55e368f7510aacfc234def4af4b525c4b740ab Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Jan 2024 13:04:10 +0100 Subject: [PATCH 226/591] test: revert setting highs as default solver, as not available for macos --- config/test/config.electricity.yaml | 4 ++-- config/test/config.myopic.yaml | 4 ++-- config/test/config.overnight.yaml | 4 ++-- config/test/config.perfect.yaml | 4 ++-- doc/release_notes.rst | 2 -- envs/environment.yaml | 1 + 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/config/test/config.electricity.yaml b/config/test/config.electricity.yaml index ef9bfdc0..b750bf62 100644 --- a/config/test/config.electricity.yaml +++ b/config/test/config.electricity.yaml @@ -69,8 +69,8 @@ lines: solving: solver: - name: highs - options: "highs-default" + name: glpk + options: "glpk-default" plotting: diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index 1da51b36..2dab7b04 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -73,8 +73,8 @@ industry: solving: solver: - name: highs - options: highs-default + name: glpk + options: glpk-default mem: 4000 plotting: diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index dffdab5a..6d1900cf 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -65,8 +65,8 @@ sector: solving: solver: - name: highs - options: highs-default + name: glpk + options: glpk-default mem: 4000 plotting: diff --git a/config/test/config.perfect.yaml b/config/test/config.perfect.yaml index 8a5a9cce..f20a2c9f 100644 --- a/config/test/config.perfect.yaml +++ b/config/test/config.perfect.yaml @@ -75,8 +75,8 @@ industry: solving: solver: - name: highs - options: highs-default + name: glpk + options: glpk-default mem: 4000 plotting: diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 55e0ad97..6fa88738 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -64,8 +64,6 @@ Upcoming Release * The ``highs`` solver was added to the default environment file. -* The default solver for testing the workflow in the CI has been changed from ``glpk`` to ``highs``. - PyPSA-Eur 0.9.0 (5th January 2024) diff --git a/envs/environment.yaml b/envs/environment.yaml index 235d7729..26e18f0d 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -35,6 +35,7 @@ dependencies: - netcdf4 - networkx - scipy +- glpk - shapely>=2.0 - pyscipopt - matplotlib From d32789bd02bc29fafd2f0a411a06ff723b10d182 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Jan 2024 16:53:14 +0100 Subject: [PATCH 227/591] snakefile: allow to share resources in directory ci: use test.sh script which can be executed locally --- .github/workflows/ci.yaml | 6 +----- Snakefile | 7 ++++++- config/test/config.electricity.yaml | 4 ++-- config/test/config.myopic.yaml | 4 ++-- config/test/config.overnight.yaml | 4 ++-- config/test/config.perfect.yaml | 2 +- test.sh | 8 ++++++++ 7 files changed, 22 insertions(+), 13 deletions(-) create mode 100755 test.sh diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4fa9f280..1af8e733 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -81,11 +81,7 @@ jobs: key: data-cutouts-${{ env.WEEK }}-${{ env.DATA_CACHE_NUMBER }} - name: Test snakemake workflow - run: | - snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime - snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime - snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime - snakemake -call all --configfile config/test/config.perfect.yaml --rerun-triggers=mtime + run: ./test.sh - name: Upload artifacts uses: actions/upload-artifact@v4.3.0 diff --git a/Snakefile b/Snakefile index 14c9e821..8391156c 100644 --- a/Snakefile +++ b/Snakefile @@ -31,7 +31,12 @@ CDIR = RDIR if not run.get("shared_cutouts") else "" LOGS = "logs/" + RDIR BENCHMARKS = "benchmarks/" + RDIR -RESOURCES = "resources/" + RDIR if not run.get("shared_resources") else "resources/" +if not (shared_resources := run.get("shared_resources")): + RESOURCES = "resources/" + RDIR +elif isinstance(shared_resources, str): + RESOURCES = "resources/" + shared_resources + "/" +else: + RESOURCES = "resources/" RESULTS = "results/" + RDIR diff --git a/config/test/config.electricity.yaml b/config/test/config.electricity.yaml index b750bf62..22c8e8d3 100644 --- a/config/test/config.electricity.yaml +++ b/config/test/config.electricity.yaml @@ -8,14 +8,14 @@ tutorial: true run: name: "test-elec" # use this to keep track of runs with different settings disable_progressbar: true - shared_resources: true + shared_resources: "test" shared_cutouts: true scenario: clusters: - 5 opts: - - Co2L-24H + - Co2L-24h countries: ['BE'] diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index 2dab7b04..2e7b3e6e 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -7,7 +7,7 @@ tutorial: true run: name: "test-sector-myopic" disable_progressbar: true - shared_resources: true + shared_resources: "test" shared_cutouts: true foresight: myopic @@ -18,7 +18,7 @@ scenario: clusters: - 5 sector_opts: - - 24H-T-H-B-I-A-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 6d1900cf..8b98fea9 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -7,7 +7,7 @@ tutorial: true run: name: "test-sector-overnight" disable_progressbar: true - shared_resources: true + shared_resources: "test" shared_cutouts: true @@ -17,7 +17,7 @@ scenario: clusters: - 5 sector_opts: - - CO2L0-24H-T-H-B-I-A-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 f20a2c9f..6eb9113e 100644 --- a/config/test/config.perfect.yaml +++ b/config/test/config.perfect.yaml @@ -7,7 +7,7 @@ tutorial: true run: name: "test-sector-perfect" disable_progressbar: true - shared_resources: true + shared_resources: "test" shared_cutouts: true foresight: perfect diff --git a/test.sh b/test.sh new file mode 100755 index 00000000..a40276b8 --- /dev/null +++ b/test.sh @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: : 2021-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: CC0-1.0 + +snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime && \ +snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime && \ +snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime && \ +snakemake -call all --configfile config/test/config.perfect.yaml --rerun-triggers=mtime From 0f80e2d089088e0c65f635516cac160954ee27e2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Jan 2024 17:07:01 +0100 Subject: [PATCH 228/591] plot: fix params and groupby deprecation warning --- rules/postprocess.smk | 3 +++ scripts/plot_power_network.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 59f9ead7..c1dd24c0 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -31,6 +31,7 @@ if config["foresight"] != "perfect": rule plot_power_network: params: plotting=config["plotting"], + foresight=config["foresight"], input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -54,6 +55,7 @@ if config["foresight"] != "perfect": rule plot_hydrogen_network: params: plotting=config["plotting"], + foresight=config["foresight"], input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -77,6 +79,7 @@ if config["foresight"] != "perfect": rule plot_gas_network: params: plotting=config["plotting"], + foresight=config["foresight"], input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", diff --git a/scripts/plot_power_network.py b/scripts/plot_power_network.py index 271e638d..0e13e497 100644 --- a/scripts/plot_power_network.py +++ b/scripts/plot_power_network.py @@ -98,7 +98,7 @@ def plot_map( logger.debug(f"{comp}, {costs}") - costs = costs.groupby(costs.columns, axis=1).sum() + costs = costs.T.groupby(costs.columns).sum().T costs.drop(list(costs.columns[(costs == 0.0).all()]), axis=1, inplace=True) From 46d8ce8f1f8293c127602e9c1a87eb58fcccf1ec Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Jan 2024 17:10:08 +0100 Subject: [PATCH 229/591] address deprecation warnings --- scripts/add_electricity.py | 12 +++++++----- scripts/add_existing_baseyear.py | 2 +- scripts/base_network.py | 8 +++++--- scripts/build_biomass_potentials.py | 6 +++--- scripts/build_gas_network.py | 20 ++++++++------------ scripts/build_line_rating.py | 2 +- scripts/build_population_layouts.py | 3 ++- scripts/build_retro_cost.py | 8 ++++---- scripts/cluster_network.py | 4 +++- scripts/prepare_network.py | 4 ++-- scripts/solve_network.py | 8 ++++---- 11 files changed, 40 insertions(+), 37 deletions(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index c9e5abca..a57edd11 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -327,7 +327,9 @@ def attach_load(n, regions, load, nuts3_shapes, ua_md_gdp, countries, scaling=1. axis=1, ) - n.madd("Load", substation_lv_i, bus=substation_lv_i, p_set=load) + n.madd( + "Load", substation_lv_i, bus=substation_lv_i, p_set=load + ) # carrier="electricity" def update_transmission_costs(n, costs, length_factor=1.0): @@ -504,8 +506,8 @@ def attach_conventional_generators( snakemake.input[f"conventional_{carrier}_{attr}"], index_col=0 ).iloc[:, 0] bus_values = n.buses.country.map(values) - n.generators[attr].update( - n.generators.loc[idx].bus.map(bus_values).dropna() + n.generators.update( + {attr: n.generators.loc[idx].bus.map(bus_values).dropna()} ) else: # Single value affecting all generators of technology k indiscriminantely of country @@ -749,8 +751,8 @@ def attach_OPSD_renewables(n: pypsa.Network, tech_map: Dict[str, List[str]]) -> caps = caps.groupby(["bus"]).Capacity.sum() caps = caps / gens_per_bus.reindex(caps.index, fill_value=1) - n.generators.p_nom.update(gens.bus.map(caps).dropna()) - n.generators.p_nom_min.update(gens.bus.map(caps).dropna()) + n.generators.update({"p_nom": gens.bus.map(caps).dropna()}) + n.generators.update({"p_nom_min": gens.bus.map(caps).dropna()}) def estimate_renewable_capacities( diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 46d4bc31..0235a4d7 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -48,7 +48,7 @@ def add_build_year_to_new_assets(n, baseyear): "series" ) & n.component_attrs[c.name].status.str.contains("Input") for attr in n.component_attrs[c.name].index[selection]: - c.pnl[attr].rename(columns=rename, inplace=True) + c.pnl[attr] = c.pnl[attr].rename(columns=rename) def add_existing_renewables(df_agg): diff --git a/scripts/base_network.py b/scripts/base_network.py index 2fa31f98..1de3ef96 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -138,7 +138,9 @@ def _load_buses_from_eg(eg_buses, europe_shape, config_elec): ) buses["carrier"] = buses.pop("dc").map({True: "DC", False: "AC"}) - buses["under_construction"] = buses["under_construction"].fillna(False).astype(bool) + buses["under_construction"] = buses.under_construction.where( + lambda s: s.notnull(), False + ).astype(bool) # remove all buses outside of all countries including exclusive economic zones (offshore) europe_shape = gpd.read_file(europe_shape).loc[0, "geometry"] @@ -525,9 +527,9 @@ def _set_countries_and_substations(n, config, country_shapes, offshore_shapes): gb = buses.loc[substation_b].groupby( ["x", "y"], as_index=False, group_keys=False, sort=False ) - bus_map_low = gb.apply(prefer_voltage, "min") + bus_map_low = gb.apply(prefer_voltage, "min", include_groups=False) lv_b = (bus_map_low == bus_map_low.index).reindex(buses.index, fill_value=False) - bus_map_high = gb.apply(prefer_voltage, "max") + bus_map_high = gb.apply(prefer_voltage, "max", include_groups=False) hv_b = (bus_map_high == bus_map_high.index).reindex(buses.index, fill_value=False) onshore_b = pd.Series(False, buses.index) diff --git a/scripts/build_biomass_potentials.py b/scripts/build_biomass_potentials.py index b6cbbfbf..6b5cb147 100644 --- a/scripts/build_biomass_potentials.py +++ b/scripts/build_biomass_potentials.py @@ -132,14 +132,14 @@ def disaggregate_nuts0(bio): pop = build_nuts_population_data() # get population in nuts2 - pop_nuts2 = pop.loc[pop.index.str.len() == 4] + pop_nuts2 = pop.loc[pop.index.str.len() == 4].copy() by_country = pop_nuts2.total.groupby(pop_nuts2.ct).sum() - pop_nuts2.loc[:, "fraction"] = pop_nuts2.total / pop_nuts2.ct.map(by_country) + pop_nuts2["fraction"] = pop_nuts2.total / pop_nuts2.ct.map(by_country) # distribute nuts0 data to nuts2 by population bio_nodal = bio.loc[pop_nuts2.ct] bio_nodal.index = pop_nuts2.index - bio_nodal = bio_nodal.mul(pop_nuts2.fraction, axis=0) + bio_nodal = bio_nodal.mul(pop_nuts2.fraction, axis=0).astype(float) # update inplace bio.update(bio_nodal) diff --git a/scripts/build_gas_network.py b/scripts/build_gas_network.py index 8df7744d..13cd75ba 100644 --- a/scripts/build_gas_network.py +++ b/scripts/build_gas_network.py @@ -114,12 +114,10 @@ def prepare_dataset( df["p_nom_diameter"] = df.diameter_mm.apply(diameter_to_capacity) ratio = df.p_nom / df.p_nom_diameter not_nordstream = df.max_pressure_bar < 220 - df.p_nom.update( - df.p_nom_diameter.where( - (df.p_nom <= 500) - | ((ratio > correction_threshold_p_nom) & not_nordstream) - | ((ratio < 1 / correction_threshold_p_nom) & not_nordstream) - ) + df["p_nom"] = df.p_nom_diameter.where( + (df.p_nom <= 500) + | ((ratio > correction_threshold_p_nom) & not_nordstream) + | ((ratio < 1 / correction_threshold_p_nom) & not_nordstream) ) # lines which have way too discrepant line lengths @@ -130,12 +128,10 @@ def prepare_dataset( axis=1, ) ratio = df.eval("length / length_haversine") - df["length"].update( - df.length_haversine.where( - (df["length"] < 20) - | (ratio > correction_threshold_length) - | (ratio < 1 / correction_threshold_length) - ) + df["length"] = df.length_haversine.where( + (df["length"] < 20) + | (ratio > correction_threshold_length) + | (ratio < 1 / correction_threshold_length) ) return df diff --git a/scripts/build_line_rating.py b/scripts/build_line_rating.py index 5b4cd6b3..522f08cf 100755 --- a/scripts/build_line_rating.py +++ b/scripts/build_line_rating.py @@ -98,7 +98,7 @@ def calculate_line_rating(n, cutout): ------- xarray DataArray object with maximal power. """ - relevant_lines = n.lines[~n.lines["underground"]] + relevant_lines = n.lines[~n.lines["underground"]].copy() buses = relevant_lines[["bus0", "bus1"]].values x = n.buses.x y = n.buses.y diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index e215e6c0..cb63c27e 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -83,7 +83,8 @@ if __name__ == "__main__": # correct for imprecision of Iinv*I pop_ct = nuts3.loc[nuts3.country == ct, "pop"].sum() - pop_cells_ct *= pop_ct / pop_cells_ct.sum() + if pop_cells_ct.sum() != 0: + pop_cells_ct *= pop_ct / pop_cells_ct.sum() # The first low density grid cells to reach rural fraction are rural asc_density_i = density_cells_ct.sort_values().index diff --git a/scripts/build_retro_cost.py b/scripts/build_retro_cost.py index bd285e18..60d74afa 100755 --- a/scripts/build_retro_cost.py +++ b/scripts/build_retro_cost.py @@ -297,8 +297,8 @@ def prepare_building_stock_data(): errors="ignore", ) - u_values.subsector.replace(rename_sectors, inplace=True) - u_values.btype.replace(rename_sectors, inplace=True) + u_values["subsector"] = u_values.subsector.replace(rename_sectors) + u_values["btype"] = u_values.btype.replace(rename_sectors) # for missing weighting of surfaces of building types assume MFH u_values["assumed_subsector"] = u_values.subsector @@ -306,8 +306,8 @@ def prepare_building_stock_data(): ~u_values.subsector.isin(rename_sectors.values()), "assumed_subsector" ] = "MFH" - u_values.country_code.replace({"UK": "GB"}, inplace=True) - u_values.bage.replace({"Berfore 1945": "Before 1945"}, inplace=True) + u_values["country_code"] = u_values.country_code.replace({"UK": "GB"}) + u_values["bage"] = u_values.bage.replace({"Berfore 1945": "Before 1945"}) u_values = u_values[~u_values.bage.isna()] u_values.set_index(["country_code", "subsector", "bage", "type"], inplace=True) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 39b6ad96..34a138cd 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -488,7 +488,9 @@ if __name__ == "__main__": gens.efficiency, bins=[0, low, high, 1], labels=labels ).astype(str) carriers += [f"{c} {label} efficiency" for label in labels] - n.generators.carrier.update(gens.carrier + " " + suffix + " efficiency") + n.generators.update( + {"carrier": gens.carrier + " " + suffix + " efficiency"} + ) aggregate_carriers = carriers if n_clusters == len(n.buses): diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 5652dc6e..e358c05e 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -269,8 +269,8 @@ def set_line_nom_max( hvdc = n.links.index[n.links.carrier == "DC"] n.links.loc[hvdc, "p_nom_max"] = n.links.loc[hvdc, "p_nom"] + p_nom_max_ext - n.lines.s_nom_max.clip(upper=s_nom_max_set, inplace=True) - n.links.p_nom_max.clip(upper=p_nom_max_set, inplace=True) + n.lines["s_nom_max"] = n.lines.s_nom_max.clip(upper=s_nom_max_set) + n.links["p_nom_max"] = n.links.p_nom_max.clip(upper=p_nom_max_set) if __name__ == "__main__": diff --git a/scripts/solve_network.py b/scripts/solve_network.py index a1d790a7..551222c0 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -418,7 +418,7 @@ def add_CCL_constraints(n, config): Example ------- scenario: - opts: [Co2L-CCL-24H] + opts: [Co2L-CCL-24h] electricity: agg_p_nom_limits: data/agg_p_nom_minmax.csv """ @@ -463,7 +463,7 @@ def add_EQ_constraints(n, o, scaling=1e-1): Example ------- scenario: - opts: [Co2L-EQ0.7-24H] + opts: [Co2L-EQ0.7-24h] Require each country or node to on average produce a minimal share of its total electricity consumption itself. Example: EQ0.7c demands each country @@ -527,7 +527,7 @@ def add_BAU_constraints(n, config): Example ------- scenario: - opts: [Co2L-BAU-24H] + opts: [Co2L-BAU-24h] electricity: BAU_mincapacities: solar: 0 @@ -564,7 +564,7 @@ def add_SAFE_constraints(n, config): config.yaml requires to specify opts: scenario: - opts: [Co2L-SAFE-24H] + opts: [Co2L-SAFE-24h] electricity: SAFE_reservemargin: 0.1 Which sets a reserve margin of 10% above the peak demand. From c60e1c5b73ac23dc7d53ad88be3e30cab3924e1b Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Jan 2024 17:12:36 +0100 Subject: [PATCH 230/591] update release notes --- doc/release_notes.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 6fa88738..44ccdff5 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -64,6 +64,9 @@ Upcoming Release * The ``highs`` solver was added to the default environment file. +* It is now possible to determine the directory for shared resources by setting `shared_resources` to a string. + +* A ``test.sh`` script was added to the repository to run the tests locally. PyPSA-Eur 0.9.0 (5th January 2024) From 550e6f07940399b3c4ee6ee3cf0c274981d4aecf Mon Sep 17 00:00:00 2001 From: JulianGeis Date: Thu, 1 Feb 2024 14:23:04 +0100 Subject: [PATCH 231/591] deleted code to include kernnetz as it is no longer needed --- scripts/prepare_sector_network.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 42def055..03cba48b 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1319,22 +1319,6 @@ def add_storage_and_grids(n, costs): n, "H2 pipeline ", carriers=["DC", "gas pipeline"] ) - h2_pipes["p_nom"] = 0.0 - - if snakemake.input.get("custom_h2_pipelines"): - fn = snakemake.input.custom_h2_pipelines - custom_pipes = pd.read_csv(fn, index_col=0) - - h2_pipes = pd.concat([h2_pipes, custom_pipes]) - - # drop duplicates according to buses (order can be different) and keep pipe with highest p_nom - h2_pipes["buses_sorted"] = h2_pipes[["bus0", "bus1"]].apply(sorted, axis=1) - h2_pipes = ( - h2_pipes.sort_values("p_nom") - .drop_duplicates(subset=["buses_sorted"], keep="last") - .drop(columns="buses_sorted") - ) - # TODO Add efficiency losses n.madd( "Link", @@ -1343,7 +1327,6 @@ def add_storage_and_grids(n, costs): bus1=h2_pipes.bus1.values + " H2", p_min_pu=-1, p_nom_extendable=True, - p_nom_min=h2_pipes.p_nom.values, length=h2_pipes.length.values, capital_cost=costs.at["H2 (g) pipeline", "fixed"] * h2_pipes.length.values, carrier="H2 pipeline", From 4c0491341cd1242e0295e1e3ac47e403c934719b Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 31 Jan 2024 12:45:45 +0000 Subject: [PATCH 232/591] Move `build_existing_heating_distribution` rule --- rules/build_sector.smk | 34 ++++++++++++++++++++++++++++++++++ rules/solve_myopic.smk | 34 ---------------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 0586ec01..a8f419c3 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -730,6 +730,40 @@ rule build_district_heat_share: "../scripts/build_district_heat_share.py" +rule build_existing_heating_distribution: + params: + baseyear=config["scenario"]["planning_horizons"][0], + sector=config["sector"], + existing_capacities=config["existing_capacities"], + input: + existing_heating="data/existing_infrastructure/existing_heating_raw.csv", + clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", + clustered_pop_energy_layout=RESOURCES + + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv", + district_heat_share=RESOURCES + + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + output: + existing_heating_distribution=RESOURCES + + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + wildcard_constraints: + planning_horizons=config["scenario"]["planning_horizons"][0], #only applies to baseyear + threads: 1 + resources: + mem_mb=2000, + log: + LOGS + + "build_existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.log", + benchmark: + ( + BENCHMARKS + + "build_existing_heating_distribution/elec_s{simpl}_{clusters}_{planning_horizons}" + ) + conda: + "../envs/environment.yaml" + script: + "../scripts/build_existing_heating_distribution.py" + + rule prepare_sector_network: params: co2_budget=config["co2_budget"], diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 75334073..94e75a5d 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -3,40 +3,6 @@ # SPDX-License-Identifier: MIT -rule build_existing_heating_distribution: - params: - baseyear=config["scenario"]["planning_horizons"][0], - sector=config["sector"], - existing_capacities=config["existing_capacities"], - input: - existing_heating="data/existing_infrastructure/existing_heating_raw.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", - clustered_pop_energy_layout=RESOURCES - + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv", - district_heat_share=RESOURCES - + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", - output: - existing_heating_distribution=RESOURCES - + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv", - wildcard_constraints: - planning_horizons=config["scenario"]["planning_horizons"][0], #only applies to baseyear - threads: 1 - resources: - mem_mb=2000, - log: - LOGS - + "build_existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.log", - benchmark: - ( - BENCHMARKS - + "build_existing_heating_distribution/elec_s{simpl}_{clusters}_{planning_horizons}" - ) - conda: - "../envs/environment.yaml" - script: - "../scripts/build_existing_heating_distribution.py" - - rule add_existing_baseyear: params: baseyear=config["scenario"]["planning_horizons"][0], From 25a24f555225de2cef68dfb832e945fea06ca198 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 1 Feb 2024 14:18:27 +0000 Subject: [PATCH 233/591] Remove unnecessary `add_brownfield` rule from perfect foresight --- rules/solve_perfect.smk | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 76051976..9e164a16 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -45,38 +45,6 @@ rule add_existing_baseyear: "../scripts/add_existing_baseyear.py" -rule add_brownfield: - params: - H2_retrofit=config["sector"]["H2_retrofit"], - H2_retrofit_capacity_per_CH4=config["sector"]["H2_retrofit_capacity_per_CH4"], - threshold_capacity=config["existing_capacities"]["threshold_capacity"], - input: - network=RESULTS - + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - network_p=solved_previous_horizon, #solved network at previous time step - costs="data/costs_{planning_horizons}.csv", - cop_soil_total=RESOURCES + "cop_soil_total_elec_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec_s{simpl}_{clusters}.nc", - output: - RESULTS - + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - threads: 4 - resources: - mem_mb=10000, - log: - LOGS - + "add_brownfield_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", - benchmark: - ( - BENCHMARKS - + "add_brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) - conda: - "../envs/environment.yaml" - script: - "../scripts/add_brownfield.py" - - rule prepare_perfect_foresight: input: **{ @@ -192,6 +160,3 @@ rule make_summary_perfect: "../envs/environment.yaml" script: "../scripts/make_summary_perfect.py" - - -ruleorder: add_existing_baseyear > add_brownfield From de384c7cf620c769df2ae91a588ac4e78ea77c3f Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 1 Feb 2024 14:46:13 +0000 Subject: [PATCH 234/591] Correctly carry over time-varying data between investment periods Previously, time-varying data in each "next" investment period was set to the default values, implying capacity factors of 1 for renewable generators for example. --- scripts/prepare_perfect_foresight.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index f5ae3919..8fd6bc1f 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -199,8 +199,13 @@ def concat_networks(years): pnl[k].loc[pnl_year.index, pnl_year.columns] = pnl_year else: - # this is to avoid adding multiple times assets with - # infinite lifetime as ror + # For components that aren't new, we just extend + # time-varying data from the previous investment + # period. + if i > 0: + pnl[k].loc[(year,)] = pnl[k].loc[(years[i - 1],)].values + + # Now, add time-varying data for new components. cols = pnl_year.columns.difference(pnl[k].columns) pnl[k] = pd.concat([pnl[k], pnl_year[cols]], axis=1) From b67e800da9c442079d20eb08cbf6eb242b9fa476 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 1 Feb 2024 14:52:16 +0000 Subject: [PATCH 235/591] Simplify concat of static components in `prepare_perfect_forsight` --- scripts/prepare_perfect_foresight.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index 8fd6bc1f..278472f6 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -162,15 +162,17 @@ def concat_networks(years): add_build_year_to_new_assets(network, year) # static ---------------------------------- - # (1) add buses and carriers - for component in network.iterate_components(["Bus", "Carrier"]): - df_year = component.df - # get missing assets - missing = get_missing(df_year, n, component.list_name) - import_components_from_dataframe(n, missing, component.name) - # (2) add generators, links, stores and loads for component in network.iterate_components( - ["Generator", "Link", "Store", "Load", "Line", "StorageUnit"] + [ + "Bus", + "Carrier", + "Generator", + "Link", + "Store", + "Load", + "Line", + "StorageUnit", + ] ): df_year = component.df.copy() missing = get_missing(df_year, n, component.list_name) From 7f77c3690abd8f9f7c6d1251c5b5be5c540d2982 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 2 Feb 2024 08:54:44 +0100 Subject: [PATCH 236/591] Add release note --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 6fa88738..1ffeb310 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -64,6 +64,8 @@ Upcoming Release * The ``highs`` solver was added to the default environment file. +* Various minor bugfixes to the perfect foresight workflow, though perfect foresight must still be considered experimental. + PyPSA-Eur 0.9.0 (5th January 2024) From cc77456195b5264db4b8a823499b83d180b4a88e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 2 Feb 2024 10:11:59 +0100 Subject: [PATCH 237/591] env: add pre-commit --- envs/environment.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/envs/environment.yaml b/envs/environment.yaml index 26e18f0d..88e394fa 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -48,6 +48,7 @@ dependencies: - tabula-py - pyxlsb - graphviz +- pre-commit # Keep in conda environment when calling ipython - ipython From 6d40ff1340898bc2b5b61c5630cebe9ae72f9b0a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 2 Feb 2024 11:52:01 +0100 Subject: [PATCH 238/591] config: add sensible defaults for HVC recycling and reuse --- config/config.default.yaml | 31 ++++++++++++++++++++++++++++--- doc/release_notes.rst | 6 ++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 51080862..5afc6f8e 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -606,9 +606,34 @@ industry: 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 primary/recycling based on values used in Neumann et al https://doi.org/10.1016/j.joule.2023.06.016, linearly interpolated between 2020 and 2050 + #2020 recycling rates based on Agora https://static.agora-energiewende.de/fileadmin/Projekte/2021/2021_02_EU_CEAP/A-EW_254_Mobilising-circular-economy_study_WEB.pdf + #fractions refer to the total primary HVC production in 2020 + #assumes 6.7 Mtplastics produced from recycling in 2020 + HVC_primary_fraction: + 2020: 1.0 + 2025: 0.9 + 2030: 0.8 + 2035: 0.7 + 2040: 0.6 + 2045: 0.5 + 2050: 0.4 + HVC_mechanical_recycling_fraction: + 2020: 0.12 + 2025: 0.15 + 2030: 0.18 + 2035: 0.21 + 2040: 0.24 + 2045: 0.27 + 2050: 0.30 + HVC_chemical_recycling_fraction: + 2020: 0.0 + 2025: 0.0 + 2030: 0.04 + 2035: 0.08 + 2040: 0.12 + 2045: 0.16 + 2050: 0.20 HVC_production_today: 52. MWh_elec_per_tHVC_mechanical_recycling: 0.547 MWh_elec_per_tHVC_chemical_recycling: 6.9 diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 6fa88738..a3331748 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -64,6 +64,12 @@ Upcoming Release * The ``highs`` solver was added to the default environment file. +* Default settings for recycling rates and primary product shares of high-value + chemicals have been set in accordance with the values used in `Neumann et al. + (2023) `_ linearly interpolated + between 2020 and 2050. The recycling rates are based on data from `Agora + Energiewende (2021) + `_. PyPSA-Eur 0.9.0 (5th January 2024) From 0006f6e5a90b548d80cc448711edab145470917e Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 2 Feb 2024 12:19:08 +0000 Subject: [PATCH 239/591] Fix gas input for existing heat gas boilers --- scripts/add_existing_baseyear.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 46d4bc31..ca11a747 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -482,7 +482,7 @@ def add_heating_capacities_installed_before_baseyear( "Link", nodes, suffix=f" {name} gas boiler-{grouping_year}", - bus0=spatial.gas.nodes, + bus0="EU gas" if "EU gas" in spatial.gas.nodes else nodes + " gas", bus1=nodes + " " + name + " heat", bus2="co2 atmosphere", carrier=name + " gas boiler", From 344989d76b4f81bea5e3c1555021a767d3b3bd9b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 5 Feb 2024 08:21:26 +0100 Subject: [PATCH 240/591] Apply suggestions from code review --- rules/postprocess.smk | 3 --- 1 file changed, 3 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index c1dd24c0..59f9ead7 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -31,7 +31,6 @@ if config["foresight"] != "perfect": rule plot_power_network: params: plotting=config["plotting"], - foresight=config["foresight"], input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -55,7 +54,6 @@ if config["foresight"] != "perfect": rule plot_hydrogen_network: params: plotting=config["plotting"], - foresight=config["foresight"], input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -79,7 +77,6 @@ if config["foresight"] != "perfect": rule plot_gas_network: params: plotting=config["plotting"], - foresight=config["foresight"], input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", From e76749ab31e543733a671c37968c548f3386037a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 5 Feb 2024 08:37:19 +0100 Subject: [PATCH 241/591] plot_hydrogen_network: add foresight params back in --- rules/postprocess.smk | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 59f9ead7..3045d0da 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -54,6 +54,7 @@ if config["foresight"] != "perfect": rule plot_hydrogen_network: params: plotting=config["plotting"], + foresight=config["foresight"], input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", From a834ff222acac9175b66285077b35baf7ceeb037 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 5 Feb 2024 12:10:35 +0100 Subject: [PATCH 242/591] streamline code for year-dependent technologies (turbines/panels) --- config/config.default.yaml | 17 ++---- doc/configtables/offwind-ac.csv | 2 +- doc/configtables/offwind-dc.csv | 2 +- doc/configtables/onwind.csv | 2 +- doc/configtables/solar.csv | 2 +- doc/release_notes.rst | 6 ++ rules/build_electricity.smk | 1 - rules/solve_myopic.smk | 3 + scripts/add_brownfield.py | 73 ++++++++-------------- scripts/add_electricity.py | 4 ++ scripts/build_renewable_profiles.py | 95 ++++++++++++----------------- scripts/prepare_sector_network.py | 5 ++ 12 files changed, 90 insertions(+), 122 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index bdbc046e..bc420b36 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -164,14 +164,11 @@ atlite: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#renewable renewable: - year: 2020 onwind: cutout: europe-2013-era5 resource: method: wind - turbine: - 2020: Vestas_V112_3MW - 2030: NREL_ReferenceTurbine_2020ATB_5.5MW + turbine: Vestas_V112_3MW add_cutout_windspeed: true capacity_per_sqkm: 3 # correction_factor: 0.93 @@ -190,9 +187,7 @@ renewable: cutout: europe-2013-era5 resource: method: wind - turbine: - 2020: NREL_ReferenceTurbine_5MW_offshore.yaml - 2030: NREL_ReferenceTurbine_2020ATB_15MW_offshore + turbine: NREL_ReferenceTurbine_5MW_offshore add_cutout_windspeed: true capacity_per_sqkm: 2 correction_factor: 0.8855 @@ -208,10 +203,7 @@ renewable: cutout: europe-2013-era5 resource: method: wind - turbine: - 2020: Vestas_V164_7MW_offshore - 2025: NREL_ReferenceTurbine_2020ATB_15MW_offshore - 2030: NREL_ReferenceTurbine_2020ATB_18MW_offshore + turbine: Vestas_V164_7MW_offshore add_cutout_windspeed: true capacity_per_sqkm: 2 correction_factor: 0.8855 @@ -227,8 +219,7 @@ renewable: cutout: europe-2013-sarah resource: method: pv - panel: - 2020: CSi + panel: CSi orientation: slope: 35. azimuth: 180. diff --git a/doc/configtables/offwind-ac.csv b/doc/configtables/offwind-ac.csv index 9dc0614c..b2533f04 100644 --- a/doc/configtables/offwind-ac.csv +++ b/doc/configtables/offwind-ac.csv @@ -2,7 +2,7 @@ cutout,--,"Should be a folder listed in the configuration ``atlite: cutouts:`` (e.g. 'europe-2013-era5') or reference an existing folder in the directory ``cutouts``. Source module must be ERA5.","Specifies the directory where the relevant weather data ist stored." resource,,, -- method,--,"Must be 'wind'","A superordinate technology type." --- turbine,--,"One of turbine types included in `atlite `_","Specifies the turbine type and its characteristic power curve." +-- turbine,--,"One of turbine types included in `atlite `_. Can be a string or a dictionary with years as keys which denote the year another turbine model becomes available.","Specifies the turbine type and its characteristic power curve." capacity_per_sqkm,:math:`MW/km^2`,float,"Allowable density of wind turbine placement." correction_factor,--,float,"Correction factor for capacity factor time series." excluder_resolution,m,float,"Resolution on which to perform geographical elibility analysis." diff --git a/doc/configtables/offwind-dc.csv b/doc/configtables/offwind-dc.csv index c947f358..7c537543 100644 --- a/doc/configtables/offwind-dc.csv +++ b/doc/configtables/offwind-dc.csv @@ -2,7 +2,7 @@ cutout,--,"Should be a folder listed in the configuration ``atlite: cutouts:`` (e.g. 'europe-2013-era5') or reference an existing folder in the directory ``cutouts``. Source module must be ERA5.","Specifies the directory where the relevant weather data ist stored." resource,,, -- method,--,"Must be 'wind'","A superordinate technology type." --- turbine,--,"One of turbine types included in `atlite `__","Specifies the turbine type and its characteristic power curve." +-- turbine,--,"One of turbine types included in `atlite `_. Can be a string or a dictionary with years as keys which denote the year another turbine model becomes available.","Specifies the turbine type and its characteristic power curve." capacity_per_sqkm,:math:`MW/km^2`,float,"Allowable density of wind turbine placement." correction_factor,--,float,"Correction factor for capacity factor time series." excluder_resolution,m,float,"Resolution on which to perform geographical elibility analysis." diff --git a/doc/configtables/onwind.csv b/doc/configtables/onwind.csv index f6b36e5d..3b09214b 100644 --- a/doc/configtables/onwind.csv +++ b/doc/configtables/onwind.csv @@ -2,7 +2,7 @@ cutout,--,"Should be a folder listed in the configuration ``atlite: cutouts:`` (e.g. 'europe-2013-era5') or reference an existing folder in the directory ``cutouts``. Source module must be ERA5.","Specifies the directory where the relevant weather data ist stored." resource,,, -- method,--,"Must be 'wind'","A superordinate technology type." --- turbine,--,"One of turbine types included in `atlite `__","Specifies the turbine type and its characteristic power curve." +-- turbine,--,"One of turbine types included in `atlite `_. Can be a string or a dictionary with years as keys which denote the year another turbine model becomes available.","Specifies the turbine type and its characteristic power curve." capacity_per_sqkm,:math:`MW/km^2`,float,"Allowable density of wind turbine placement." corine,,, -- grid_codes,--,"Any subset of the `CORINE Land Cover code list `_","Specifies areas according to CORINE Land Cover codes which are generally eligible for wind turbine placement." diff --git a/doc/configtables/solar.csv b/doc/configtables/solar.csv index 8328d342..18587694 100644 --- a/doc/configtables/solar.csv +++ b/doc/configtables/solar.csv @@ -2,7 +2,7 @@ cutout,--,"Should be a folder listed in the configuration ``atlite: cutouts:`` (e.g. 'europe-2013-era5') or reference an existing folder in the directory ``cutouts``. Source module can be ERA5 or SARAH-2.","Specifies the directory where the relevant weather data ist stored that is specified at ``atlite/cutouts`` configuration. Both ``sarah`` and ``era5`` work." resource,,, -- method,--,"Must be 'pv'","A superordinate technology type." --- panel,--,"One of {'Csi', 'CdTe', 'KANENA'} as defined in `atlite `__","Specifies the solar panel technology and its characteristic attributes." +-- panel,--,"One of {'Csi', 'CdTe', 'KANENA'} as defined in `atlite `_ . Can be a string or a dictionary with years as keys which denote the year another turbine model becomes available.","Specifies the solar panel technology and its characteristic attributes." -- orientation,,, -- -- slope,°,"Realistically any angle in [0., 90.]","Specifies the tilt angle (or slope) of the solar panel. A slope of zero corresponds to the face of the panel aiming directly overhead. A positive tilt angle steers the panel towards the equator." -- -- azimuth,°,"Any angle in [0., 360.]","Specifies the `azimuth `_ orientation of the solar panel. South corresponds to 180.°." diff --git a/doc/release_notes.rst b/doc/release_notes.rst index a3331748..6bf78fcd 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -71,6 +71,12 @@ Upcoming Release Energiewende (2021) `_. +* Added option to specify turbine and solar panel models for specific years as a + dictionary (e.g. ``renewable: onwind: resource: turbine:``). The years will be + interpreted as years from when the the corresponding turbine model substitutes + the previous model for new installations. This will only have an effect on + workflows with foresight "myopic" and still needs to be added foresight option + "perfect". PyPSA-Eur 0.9.0 (5th January 2024) ================================== diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 5846dd9d..6b092638 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -261,7 +261,6 @@ rule build_renewable_profiles: params: snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, renewable=config["renewable"], - foresight=config["foresight"], input: **opt, base_network=RESOURCES + "networks/base.nc", diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index a5f2b12b..49df9d1e 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -85,10 +85,13 @@ rule add_brownfield: H2_retrofit=config["sector"]["H2_retrofit"], H2_retrofit_capacity_per_CH4=config["sector"]["H2_retrofit_capacity_per_CH4"], threshold_capacity=config["existing_capacities"]["threshold_capacity"], + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, + carriers=config["electricity"]["renewable_carriers"], input: **{ f"profile_{tech}": RESOURCES + f"profile_{tech}.nc" for tech in config["electricity"]["renewable_carriers"] + if tech != "hydro" }, simplify_busmap=RESOURCES + "busmap_elec_s{simpl}.csv", cluster_busmap=RESOURCES + "busmap_elec_s{simpl}_{clusters}.csv", diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 912b01ae..3b77c437 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -145,78 +145,53 @@ def disable_grid_expansion_if_LV_limit_hit(n): n.global_constraints.drop("lv_limit", inplace=True) -def adjust_renewable_profiles(n, input_profiles, config, year): +def adjust_renewable_profiles(n, input_profiles, params, year): """ - Adjusts renewable profiles according to the renewable technology specified. - - If the planning horizon is not available, the closest year is used - instead. + Adjusts renewable profiles according to the renewable technology specified, + using the latest year below or equal to the selected year. """ + # spatial clustering cluster_busmap = pd.read_csv(snakemake.input.cluster_busmap, index_col=0).squeeze() simplify_busmap = pd.read_csv( snakemake.input.simplify_busmap, index_col=0 ).squeeze() clustermaps = simplify_busmap.map(cluster_busmap) clustermaps.index = clustermaps.index.astype(str) - dr = pd.date_range(**config["snapshots"], freq="H") + + # temporal clustering + dr = pd.date_range(**params["snapshots"], freq="h") snapshotmaps = ( pd.Series(dr, index=dr).where(lambda x: x.isin(n.snapshots), pd.NA).ffill() ) - for carrier in config["electricity"]["renewable_carriers"]: - if carrier == "hydro": - continue - - clustermaps.index = clustermaps.index.astype(str) - dr = pd.date_range(**config["snapshots"], freq="H") - snapshotmaps = ( - pd.Series(dr, index=dr).where(lambda x: x.isin(n.snapshots), pd.NA).ffill() - ) - for carrier in config["electricity"]["renewable_carriers"]: + for carrier in params["carriers"]: if carrier == "hydro": continue with xr.open_dataset(getattr(input_profiles, "profile_" + carrier)) as ds: if ds.indexes["bus"].empty or "year" not in ds.indexes: continue - if year in ds.indexes["year"]: - p_max_pu = ( - ds["year_profiles"] - .sel(year=year) - .transpose("time", "bus") - .to_pandas() - ) - else: - available_previous_years = [ - available_year - for available_year in ds.indexes["year"] - if available_year < year - ] - available_following_years = [ - available_year - for available_year in ds.indexes["year"] - if available_year > year - ] - if available_previous_years: - closest_year = max(available_previous_years) - if available_following_years: - closest_year = min(available_following_years) - logging.warning( - f"Planning horizon {year} not in {carrier} profiles. Using closest year {closest_year} instead." - ) - p_max_pu = ( - ds["year_profiles"] - .sel(year=closest_year) - .transpose("time", "bus") - .to_pandas() - ) + + closest_year = max( + (y for y in ds.year.values if y <= year), default=min(ds.year.values) + ) + + p_max_pu = ( + ds["profile"] + .sel(year=closest_year) + .transpose("time", "bus") + .to_pandas() + ) + # spatial clustering - weight = ds["weight"].to_pandas() + weight = ds["weight"].sel(year=closest_year).to_pandas() weight = weight.groupby(clustermaps).transform(normed_or_uniform) p_max_pu = (p_max_pu * weight).T.groupby(clustermaps).sum().T p_max_pu.columns = p_max_pu.columns + f" {carrier}" + # temporal_clustering p_max_pu = p_max_pu.groupby(snapshotmaps).mean() + # replace renewable time series n.generators_t.p_max_pu.loc[:, p_max_pu.columns] = p_max_pu @@ -245,7 +220,7 @@ if __name__ == "__main__": n = pypsa.Network(snakemake.input.network) - adjust_renewable_profiles(n, snakemake.input, snakemake.config, year) + adjust_renewable_profiles(n, snakemake.input, snakemake.params, year) add_build_year_to_new_assets(n, year) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index c9e5abca..431f1cfa 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -374,6 +374,10 @@ def attach_wind_and_solar( if ds.indexes["bus"].empty: continue + # if-statement for compatibility with old profiles + if "year" in ds.indexes: + ds = ds.sel(year=ds.year.min(), drop=True) + supcar = car.split("-", 2)[0] if supcar == "offwind": underwater_fraction = ds["underwater_fraction"].to_pandas() diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 66c888e6..99b177a8 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -200,24 +200,20 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_renewable_profiles", technology="onwind") + snakemake = mock_snakemake("build_renewable_profiles", technology="offwind-dc") configure_logging(snakemake) nprocesses = int(snakemake.threads) noprogress = snakemake.config["run"].get("disable_progressbar", True) noprogress = noprogress or not snakemake.config["atlite"]["show_progress"] - year = snakemake.params.renewable["year"] - foresight = snakemake.params.foresight params = snakemake.params.renewable[snakemake.wildcards.technology] resource = params["resource"] # pv panel params / wind turbine params - year_dependent_techs = { - k: resource.get(k) - for k in ["panel", "turbine"] - if isinstance(resource.get(k), dict) - } - for key, techs in year_dependent_techs.items(): - resource[key] = resource[key][year] + tech = next(t for t in ["panel", "turbine"] if t in resource) + models = resource[tech] + if not isinstance(models, dict): + models = {0: models} + resource[tech] = models[next(iter(models))] correction_factor = params.get("correction_factor", 1.0) capacity_per_sqkm = params["capacity_per_sqkm"] @@ -334,45 +330,40 @@ if __name__ == "__main__": duration = time.time() - start logger.info(f"Completed average capacity factor calculation ({duration:2.2f}s)") - logger.info("Calculate weighted capacity factor time series...") - start = time.time() + profiles = [] + capacities = [] + for year, model in models.items(): - profile, capacities = func( - matrix=availability.stack(spatial=["y", "x"]), - layout=layout, - index=buses, - per_unit=True, - return_capacity=True, - **resource, - ) + logger.info( + f"Calculate weighted capacity factor time series for model {model}..." + ) + start = time.time() - if year_dependent_techs and foresight != "overnight": - for key, techs in year_dependent_techs.items(): - year_profiles = list() - tech_profiles = dict() - tech_profiles[resource[key]] = profile - for year, tech in techs.items(): - resource[key] = tech - if tech not in tech_profiles: - tech_profiles[tech] = func( - matrix=availability.stack(spatial=["y", "x"]), - layout=layout, - index=buses, - per_unit=True, - return_capacity=False, - **resource, - ) - year_profile = tech_profiles[tech] - year_profile = year_profile.expand_dims({"year": [year]}).rename( - "year_profiles" - ) - year_profiles.append(year_profile) - year_profiles = xr.merge(year_profiles) + resource[tech] = model - duration = time.time() - start - logger.info( - f"Completed weighted capacity factor time series calculation ({duration:2.2f}s)" - ) + profile, capacity = func( + matrix=availability.stack(spatial=["y", "x"]), + layout=layout, + index=buses, + per_unit=True, + return_capacity=True, + **resource, + ) + + dim = {"year": [year]} + profile = profile.expand_dims(dim) + capacity = capacity.expand_dims(dim) + + profiles.append(profile.rename("profile")) + capacities.append(capacity.rename("weight")) + + duration = time.time() - start + logger.info( + f"Completed weighted capacity factor time series calculation for model {model} ({duration:2.2f}s)" + ) + + profiles = xr.merge(profiles) + capacities = xr.merge(capacities) logger.info("Calculating maximal capacity per bus") p_nom_max = capacity_per_sqkm * availability @ area @@ -399,17 +390,14 @@ if __name__ == "__main__": ds = xr.merge( [ - (correction_factor * profile).rename("profile"), - capacities.rename("weight"), + correction_factor * profiles, + capacities, p_nom_max.rename("p_nom_max"), potential.rename("potential"), average_distance.rename("average_distance"), ] ) - if year_dependent_techs: - ds = xr.merge([ds, year_profiles * correction_factor]) - if snakemake.wildcards.technology.startswith("offwind"): logger.info("Calculate underwater fraction of connections.") offshore_shape = gpd.read_file(snakemake.input["offshore_shapes"]).unary_union @@ -425,7 +413,7 @@ if __name__ == "__main__": # select only buses with some capacity and minimal capacity factor ds = ds.sel( bus=( - (ds["profile"].mean("time") > params.get("min_p_max_pu", 0.0)) + (ds["profile"].mean("time").max("year") > params.get("min_p_max_pu", 0.0)) & (ds["p_nom_max"] > params.get("min_p_nom_max", 0.0)) ) ) @@ -433,9 +421,6 @@ if __name__ == "__main__": if "clip_p_max_pu" in params: min_p_max_pu = params["clip_p_max_pu"] ds["profile"] = ds["profile"].where(ds["profile"] >= min_p_max_pu, 0) - ds["year_profiles"] = ds["year_profiles"].where( - ds["year_profiles"] >= min_p_max_pu, 0 - ) ds.to_netcdf(snakemake.output.profile) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 03cba48b..59184b79 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -421,6 +421,11 @@ def update_wind_solar_costs(n, costs): tech = "offwind-" + connection profile = snakemake.input["profile_offwind_" + connection] with xr.open_dataset(profile) as ds: + + # if-statement for compatibility with old profiles + if "year" in ds.indexes: + ds = ds.sel(year=ds.year.min(), drop=True) + underwater_fraction = ds["underwater_fraction"].to_pandas() connection_cost = ( snakemake.params.length_factor From 76872fa0f1547bc0b7de9592ce5c77060959c687 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 5 Feb 2024 16:16:34 +0100 Subject: [PATCH 243/591] add sanitize_locations function and apply it address some deprecation warnings --- config/test/config.perfect.yaml | 2 +- scripts/add_electricity.py | 9 +++++++++ scripts/add_extra_components.py | 8 ++++---- scripts/make_summary.py | 12 +++++++++--- scripts/make_summary_perfect.py | 24 ++++++++++++++++-------- scripts/plot_hydrogen_network.py | 4 +++- scripts/prepare_perfect_foresight.py | 2 +- scripts/prepare_sector_network.py | 16 ++++++++++++++-- 8 files changed, 57 insertions(+), 20 deletions(-) diff --git a/config/test/config.perfect.yaml b/config/test/config.perfect.yaml index 6eb9113e..2e716066 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-dist1 + - 8760h-T-H-B-I-A-dist1 planning_horizons: - 2030 - 2040 diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 6c63abda..d67e2fa2 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -178,6 +178,15 @@ def sanitize_carriers(n, config): n.carriers["color"] = n.carriers.color.where(n.carriers.color != "", colors) +def sanitize_locations(n): + n.buses["x"] = n.buses.x.where(n.buses.x != 0, n.buses.location.map(n.buses.x)) + n.buses["y"] = n.buses.y.where(n.buses.y != 0, n.buses.location.map(n.buses.y)) + n.buses["country"] = n.buses.country.where( + n.buses.country.ne("") & n.buses.country.notnull(), + n.buses.location.map(n.buses.country), + ) + + def add_co2_emissions(n, costs, carriers): """ Add CO2 emissions to the network's carriers attribute. diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index e00e1e5f..731e36be 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -56,7 +56,7 @@ import numpy as np import pandas as pd import pypsa from _helpers import configure_logging -from add_electricity import load_costs, sanitize_carriers +from add_electricity import load_costs, sanitize_carriers, sanitize_locations idx = pd.IndexSlice @@ -100,10 +100,9 @@ def attach_stores(n, costs, extendable_carriers): n.madd("Carrier", carriers) buses_i = n.buses.index - bus_sub_dict = {k: n.buses[k].values for k in ["x", "y", "country"]} if "H2" in carriers: - h2_buses_i = n.madd("Bus", buses_i + " H2", carrier="H2", **bus_sub_dict) + h2_buses_i = n.madd("Bus", buses_i + " H2", carrier="H2", location=buses_i) n.madd( "Store", @@ -143,7 +142,7 @@ def attach_stores(n, costs, extendable_carriers): if "battery" in carriers: b_buses_i = n.madd( - "Bus", buses_i + " battery", carrier="battery", **bus_sub_dict + "Bus", buses_i + " battery", carrier="battery", location=buses_i ) n.madd( @@ -246,6 +245,7 @@ if __name__ == "__main__": attach_hydrogen_pipelines(n, costs, extendable_carriers) sanitize_carriers(n, snakemake.config) + sanitize_locations(n) n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) n.export_to_netcdf(snakemake.output[0]) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 0fab5367..76d8099c 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -507,7 +507,7 @@ def calculate_weighted_prices(n, label, weighted_prices): if carrier in ["H2", "gas"]: load = pd.DataFrame(index=n.snapshots, columns=buses, data=0.0) else: - load = n.loads_t.p_set[buses] + load = n.loads_t.p_set[buses.intersection(n.loads.index)] for tech in value: names = n.links.index[n.links.index.to_series().str[-len(tech) :] == tech] @@ -560,7 +560,10 @@ def calculate_market_values(n, label, market_values): ) revenue = dispatch * n.buses_t.marginal_price[buses] - market_values.at[tech, label] = revenue.sum().sum() / dispatch.sum().sum() + if total_dispatch := dispatch.sum().sum(): + market_values.at[tech, label] = revenue.sum().sum() / total_dispatch + else: + market_values.at[tech, label] = np.nan ## Now do market value of links ## @@ -583,7 +586,10 @@ def calculate_market_values(n, label, market_values): revenue = dispatch * n.buses_t.marginal_price[buses] - market_values.at[tech, label] = revenue.sum().sum() / dispatch.sum().sum() + if total_dispatch := dispatch.sum().sum(): + market_values.at[tech, label] = revenue.sum().sum() / total_dispatch + else: + market_values.at[tech, label] = np.nan return market_values diff --git a/scripts/make_summary_perfect.py b/scripts/make_summary_perfect.py index 555e5da5..d401b28e 100644 --- a/scripts/make_summary_perfect.py +++ b/scripts/make_summary_perfect.py @@ -265,7 +265,7 @@ def calculate_energy(n, label, energy): totals[no_bus] = float( n.component_attrs[c.name].loc["p" + port, "default"] ) - c_energies -= totals.groupby(c.df.carrier, axis=1).sum() + c_energies -= totals.T.groupby(c.df.carrier).sum().T c_energies = pd.concat([c_energies.T], keys=[c.list_name]) @@ -376,9 +376,8 @@ def calculate_supply_energy(n, label, supply_energy): .groupby(level=0) .sum() .multiply(c.df.loc[items, "sign"]) - .groupby(c.df.loc[items, "carrier"], axis=1) + .T.groupby(c.df.loc[items, "carrier"]) .sum() - .T ) s = pd.concat([s], keys=[c.list_name]) s = pd.concat([s], keys=[i]) @@ -525,9 +524,12 @@ def calculate_weighted_prices(n, label, weighted_prices): # stores[stores > 0.] = 0. # load += -stores - weighted_prices.loc[carrier, label] = ( - load * n.buses_t.marginal_price[buses] - ).sum().sum() / load.sum().sum() + if total_load := load.sum().sum(): + weighted_prices.loc[carrier, label] = ( + load * n.buses_t.marginal_price[buses] + ).sum().sum() / total_load + else: + weighted_prices.loc[carrier, label] = np.nan if carrier[:5] == "space": print(load * n.buses_t.marginal_price[buses]) @@ -562,7 +564,10 @@ def calculate_market_values(n, label, market_values): revenue = dispatch * n.buses_t.marginal_price[buses] - market_values.at[tech, label] = revenue.sum().sum() / dispatch.sum().sum() + if total_dispatch := dispatch.sum().sum(): + market_values.at[tech, label] = revenue.sum().sum() / total_dispatch + else: + market_values.at[tech, label] = np.nan ## Now do market value of links ## @@ -585,7 +590,10 @@ def calculate_market_values(n, label, market_values): revenue = dispatch * n.buses_t.marginal_price[buses] - market_values.at[tech, label] = revenue.sum().sum() / dispatch.sum().sum() + if total_dispatch := dispatch.sum().sum(): + market_values.at[tech, label] = revenue.sum().sum() / total_dispatch + else: + market_values.at[tech, label] = np.nan return market_values diff --git a/scripts/plot_hydrogen_network.py b/scripts/plot_hydrogen_network.py index a1183311..95741170 100644 --- a/scripts/plot_hydrogen_network.py +++ b/scripts/plot_hydrogen_network.py @@ -36,7 +36,9 @@ def group_pipes(df, drop_direction=False): lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}", axis=1, ) - return df.groupby(level=0).agg({"p_nom_opt": sum, "bus0": "first", "bus1": "first"}) + return df.groupby(level=0).agg( + {"p_nom_opt": "sum", "bus0": "first", "bus1": "first"} + ) def plot_h2_map(n, regions): diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index 278472f6..3d72cd8c 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -221,7 +221,7 @@ def concat_networks(years): # set investment periods n.investment_periods = n.snapshots.levels[0] # weighting of the investment period -> assuming last period same weighting as the period before - time_w = n.investment_periods.to_series().diff().shift(-1).fillna(method="ffill") + time_w = n.investment_periods.to_series().diff().shift(-1).ffill() n.investment_period_weightings["years"] = time_w # set objective weightings objective_w = get_investment_weighting( diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index f7e91605..5abd2ce6 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -19,7 +19,7 @@ import pandas as pd import pypsa import xarray as xr from _helpers import update_config_with_sector_opts -from add_electricity import calculate_annuity, sanitize_carriers +from add_electricity import calculate_annuity, sanitize_carriers, sanitize_locations from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement from networkx.algorithms.connectivity.edge_augmentation import k_edge_augmentation @@ -546,6 +546,14 @@ def patch_electricity_network(n): n.loads_t.p_set.rename(lambda x: x.strip(), axis=1, inplace=True) +def add_eu_bus(n, x=-5.5, y=46): + """ + Add EU bus to the network. + """ + n.add("Bus", "EU", location="EU", x=x, y=y, carrier="none") + n.add("Carrier", "none") + + def add_co2_tracking(n, costs, options): # minus sign because opposite to how fossil fuels used: # CH4 burning puts CH4 down, atmosphere up @@ -1005,6 +1013,7 @@ def insert_electricity_distribution_grid(n, costs): "Store", nodes + " home battery", bus=nodes + " home battery", + location=nodes, e_cyclic=True, e_nom_extendable=True, carrier="home battery", @@ -3527,8 +3536,8 @@ def lossy_bidirectional_links(n, carrier, efficiencies={}): rev_links["reversed"] = True rev_links.index = rev_links.index.map(lambda x: x + "-reversed") + n.links["reversed"] = False n.links = pd.concat([n.links, rev_links], sort=False) - n.links["reversed"] = n.links["reversed"].fillna(False) n.links["length_original"] = n.links["length_original"].fillna(n.links.length) # do compression losses after concatenation to take electricity consumption at bus0 in either direction @@ -3594,6 +3603,8 @@ if __name__ == "__main__": for carrier in conventional: add_carrier_buses(n, carrier) + add_eu_bus(n) + add_co2_tracking(n, costs, options) add_generation(n, costs) @@ -3733,5 +3744,6 @@ if __name__ == "__main__": n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) sanitize_carriers(n, snakemake.config) + sanitize_locations(n) n.export_to_netcdf(snakemake.output[0]) From 32451f6ca8e45ca6f3c292f29c324104499e9276 Mon Sep 17 00:00:00 2001 From: Fabian Hofmann Date: Mon, 5 Feb 2024 19:13:42 +0100 Subject: [PATCH 244/591] Update scripts/prepare_sector_network.py Co-authored-by: Fabian Neumann --- 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 5abd2ce6..8eb38d69 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3536,8 +3536,8 @@ def lossy_bidirectional_links(n, carrier, efficiencies={}): rev_links["reversed"] = True rev_links.index = rev_links.index.map(lambda x: x + "-reversed") - n.links["reversed"] = False n.links = pd.concat([n.links, rev_links], sort=False) + n.links["reversed"] = n.links["reversed"].fillna(False) n.links["length_original"] = n.links["length_original"].fillna(n.links.length) # do compression losses after concatenation to take electricity consumption at bus0 in either direction From 2a01ed3d48f75b03e0ed0193304fa810e81b84a7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 5 Feb 2024 19:15:55 +0100 Subject: [PATCH 245/591] prepare_sector: add description of eu bus --- scripts/prepare_sector_network.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 8eb38d69..4948d451 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -549,6 +549,9 @@ def patch_electricity_network(n): def add_eu_bus(n, x=-5.5, y=46): """ Add EU bus to the network. + + This cosmetic bus serves as a reference point for the location of + the EU buses in the plots and summaries. """ n.add("Bus", "EU", location="EU", x=x, y=y, carrier="none") n.add("Carrier", "none") From 0553108e3d2e722d13e91cac65b7f823b81dc1cd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:23:30 +0000 Subject: [PATCH 246/591] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/snakemake/snakefmt: v0.9.0 → v0.10.0](https://github.com/snakemake/snakefmt/compare/v0.9.0...v0.10.0) --- .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 d90f5cb9..5c41e781 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -74,7 +74,7 @@ repos: # Format Snakemake rule / workflow files - repo: https://github.com/snakemake/snakefmt - rev: v0.9.0 + rev: v0.10.0 hooks: - id: snakefmt From 39890630efc3bc1b2356ef274faf9fbebf92ce82 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:23:48 +0000 Subject: [PATCH 247/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 16 +++++++----- rules/build_sector.smk | 49 +++++++++++++++++++++---------------- rules/collect.smk | 14 +++++------ rules/postprocess.smk | 40 +++++++++++++++++------------- rules/retrieve.smk | 8 +++--- 5 files changed, 73 insertions(+), 54 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 6b092638..89f4f736 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -401,18 +401,22 @@ rule add_electricity: if str(fn).startswith("data/") }, base_network=RESOURCES + "networks/base.nc", - line_rating=RESOURCES + "networks/line_rating.nc" - if config["lines"]["dynamic_line_rating"]["activate"] - else RESOURCES + "networks/base.nc", + line_rating=( + RESOURCES + "networks/line_rating.nc" + if config["lines"]["dynamic_line_rating"]["activate"] + else RESOURCES + "networks/base.nc" + ), tech_costs=COSTS, regions=RESOURCES + "regions_onshore.geojson", powerplants=RESOURCES + "powerplants.csv", hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), geth_hydro_capacities="data/geth2015_hydro_capacities.csv", unit_commitment="data/unit_commitment.csv", - fuel_price=RESOURCES + "monthly_fuel_price.csv" - if config["conventional"]["dynamic_fuel_price"] - else [], + fuel_price=( + RESOURCES + "monthly_fuel_price.csv" + if config["conventional"]["dynamic_fuel_price"] + else [] + ), load=RESOURCES + "load.csv", nuts3_shapes=RESOURCES + "nuts3_shapes.geojson", ua_md_gdp="data/GDP_PPP_30arcsec_v3_mapped_default.csv", diff --git a/rules/build_sector.smk b/rules/build_sector.smk index a8f419c3..c25c8673 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -797,15 +797,19 @@ rule prepare_sector_network: dsm_profile=RESOURCES + "dsm_profile_s{simpl}_{clusters}.csv", co2_totals_name=RESOURCES + "co2_totals.csv", co2="data/bundle-sector/eea/UNFCCC_v23.csv", - biomass_potentials=RESOURCES - + "biomass_potentials_s{simpl}_{clusters}_" - + "{}.csv".format(config["biomass"]["year"]) - if config["foresight"] == "overnight" - else RESOURCES - + "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv", - costs="data/costs_{}.csv".format(config["costs"]["year"]) - if config["foresight"] == "overnight" - else "data/costs_{planning_horizons}.csv", + biomass_potentials=( + RESOURCES + + "biomass_potentials_s{simpl}_{clusters}_" + + "{}.csv".format(config["biomass"]["year"]) + if config["foresight"] == "overnight" + else RESOURCES + + "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv" + ), + costs=( + "data/costs_{}.csv".format(config["costs"]["year"]) + if config["foresight"] == "overnight" + else "data/costs_{planning_horizons}.csv" + ), profile_offwind_ac=RESOURCES + "profile_offwind-ac.nc", profile_offwind_dc=RESOURCES + "profile_offwind-dc.nc", h2_cavern=RESOURCES + "salt_cavern_potentials_s{simpl}_{clusters}.csv", @@ -831,18 +835,21 @@ rule prepare_sector_network: cop_air_total=RESOURCES + "cop_air_total_elec_s{simpl}_{clusters}.nc", cop_air_rural=RESOURCES + "cop_air_rural_elec_s{simpl}_{clusters}.nc", cop_air_urban=RESOURCES + "cop_air_urban_elec_s{simpl}_{clusters}.nc", - solar_thermal_total=RESOURCES - + "solar_thermal_total_elec_s{simpl}_{clusters}.nc" - if config["sector"]["solar_thermal"] - else [], - solar_thermal_urban=RESOURCES - + "solar_thermal_urban_elec_s{simpl}_{clusters}.nc" - if config["sector"]["solar_thermal"] - else [], - solar_thermal_rural=RESOURCES - + "solar_thermal_rural_elec_s{simpl}_{clusters}.nc" - if config["sector"]["solar_thermal"] - else [], + solar_thermal_total=( + RESOURCES + "solar_thermal_total_elec_s{simpl}_{clusters}.nc" + if config["sector"]["solar_thermal"] + else [] + ), + solar_thermal_urban=( + RESOURCES + "solar_thermal_urban_elec_s{simpl}_{clusters}.nc" + if config["sector"]["solar_thermal"] + else [] + ), + solar_thermal_rural=( + RESOURCES + "solar_thermal_rural_elec_s{simpl}_{clusters}.nc" + if config["sector"]["solar_thermal"] + else [] + ), output: RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", diff --git a/rules/collect.smk b/rules/collect.smk index 1d977da1..dc0a94cc 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -29,7 +29,7 @@ rule prepare_elec_networks: input: expand( RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - **config["scenario"] + **config["scenario"], ), @@ -38,7 +38,7 @@ rule prepare_sector_networks: expand( RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - **config["scenario"] + **config["scenario"], ), @@ -46,7 +46,7 @@ rule solve_elec_networks: input: expand( RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", - **config["scenario"] + **config["scenario"], ), @@ -55,7 +55,7 @@ rule solve_sector_networks: expand( RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - **config["scenario"] + **config["scenario"], ), @@ -64,7 +64,7 @@ rule solve_sector_networks_perfect: expand( RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", - **config["scenario"] + **config["scenario"], ), @@ -73,11 +73,11 @@ rule validate_elec_networks: expand( RESULTS + "figures/.statistics_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", - **config["scenario"] + **config["scenario"], ), expand( RESULTS + "figures/.validation_{kind}_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", **config["scenario"], - kind=["production", "prices", "cross_border"] + kind=["production", "prices", "cross_border"], ), diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 3045d0da..2e90d233 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -153,38 +153,44 @@ rule make_summary: input: expand( RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", - **config["scenario"] + **config["scenario"], ), networks=expand( RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - **config["scenario"] + **config["scenario"], + ), + costs=( + "data/costs_{}.csv".format(config["costs"]["year"]) + if config["foresight"] == "overnight" + else "data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]) ), - costs="data/costs_{}.csv".format(config["costs"]["year"]) - if config["foresight"] == "overnight" - else "data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), ac_plot=expand( RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", - **config["scenario"] + **config["scenario"], ), costs_plot=expand( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", - **config["scenario"] + **config["scenario"], ), h2_plot=expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf" - if config["sector"]["H2_network"] - else [], - **config["scenario"] + ( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf" + if config["sector"]["H2_network"] + else [] + ), + **config["scenario"], ), ch4_plot=expand( - RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf" - if config["sector"]["gas_network"] - else [], - **config["scenario"] + ( + RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf" + if config["sector"]["gas_network"] + else [] + ), + **config["scenario"], ), output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 05bbefd8..2980583f 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -191,9 +191,11 @@ 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" - if config["snapshots"]["end"] < "2019" - else "2020-10-06" + version=( + "2019-06-05" + if config["snapshots"]["end"] < "2019" + else "2020-10-06" + ) ), keep_local=True, static=True, From 7fbb6051340eaf038133a7058f3ea7c43d1daf69 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 2 Feb 2024 10:41:05 +0000 Subject: [PATCH 248/591] Address FutureWarnings in `make_summary_perfect` related to groupby --- scripts/make_summary_perfect.py | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/scripts/make_summary_perfect.py b/scripts/make_summary_perfect.py index d401b28e..d68ac628 100644 --- a/scripts/make_summary_perfect.py +++ b/scripts/make_summary_perfect.py @@ -246,8 +246,9 @@ def calculate_energy(n, label, energy): .groupby(level=0) .sum() .multiply(c.df.sign) - .groupby(c.df.carrier, axis=1) + .T.groupby(c.df.carrier) .sum() + .T ) else: c_energies = pd.DataFrame( @@ -394,16 +395,9 @@ def calculate_supply_energy(n, label, supply_energy): if len(items) == 0: continue - s = ( - (-1) - * c.pnl["p" + end] - .reindex(items, axis=1) - .multiply(n.snapshot_weightings.objective, axis=0) - .groupby(level=0) - .sum() - .groupby(c.df.loc[items, "carrier"], axis=1) - .sum() - ).T + s = (-1) * c.pnl["p" + end].reindex(items, axis=1).multiply( + n.snapshot_weightings.objective, axis=0 + ).groupby(level=0).sum().T.groupby(c.df.loc[items, "carrier"]).sum() s.index = s.index + end s = pd.concat([s], keys=[c.list_name]) s = pd.concat([s], keys=[i]) @@ -514,9 +508,7 @@ def calculate_weighted_prices(n, label, weighted_prices): if names.empty: continue - load += ( - n.links_t.p0[names].groupby(n.links.loc[names, "bus0"], axis=1).sum() - ) + load += n.links_t.p0[names].T.groupby(n.links.loc[names, "bus0"]).sum() # Add H2 Store when charging # if carrier == "H2": @@ -557,9 +549,9 @@ def calculate_market_values(n, label, market_values): dispatch = ( n.generators_t.p[gens] - .groupby(n.generators.loc[gens, "bus"], axis=1) + .T.groupby(n.generators.loc[gens, "bus"]) .sum() - .reindex(columns=buses, fill_value=0.0) + .T.reindex(columns=buses, fill_value=0.0) ) revenue = dispatch * n.buses_t.marginal_price[buses] @@ -583,9 +575,9 @@ def calculate_market_values(n, label, market_values): dispatch = ( n.links_t["p" + i][links] - .groupby(n.links.loc[links, "bus" + i], axis=1) + .T.groupby(n.links.loc[links, "bus" + i]) .sum() - .reindex(columns=buses, fill_value=0.0) + .T.reindex(columns=buses, fill_value=0.0) ) revenue = dispatch * n.buses_t.marginal_price[buses] @@ -652,7 +644,7 @@ def calculate_co2_emissions(n, label, df): emitted = n.generators_t.p[gens.index].mul(em_pu) emitted_grouped = ( - emitted.groupby(level=0).sum().groupby(n.generators.carrier, axis=1).sum().T + emitted.groupby(level=0).sum().T.groupby(n.generators.carrier).sum().T ) df = df.reindex(emitted_grouped.index.union(df.index)) From 73b80ebab38cf275d3410fb5918e37061df452e4 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 6 Feb 2024 09:39:11 +0000 Subject: [PATCH 249/591] Address pandas deprecation warnings in `prepare_perfect_foresight` --- scripts/prepare_perfect_foresight.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index 3d72cd8c..467682a9 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -56,7 +56,9 @@ def get_investment_weighting(time_weighting, r=0.01): end = time_weighting.cumsum() start = time_weighting.cumsum().shift().fillna(0) return pd.concat([start, end], axis=1).apply( - lambda x: sum(get_social_discount(t, r) for t in range(int(x[0]), int(x[1]))), + lambda x: sum( + get_social_discount(t, r) for t in range(int(x.iloc[0]), int(x.iloc[1])) + ), axis=1, ) @@ -188,7 +190,7 @@ def concat_networks(years): pnl = getattr(n, component.list_name + "_t") for k in iterkeys(component.pnl): pnl_year = component.pnl[k].copy().reindex(snapshots, level=1) - if pnl_year.empty and ~(component.name == "Load" and k == "p_set"): + if pnl_year.empty and (not (component.name == "Load" and k == "p_set")): continue if component.name == "Load": static_load = network.loads.loc[network.loads.p_set != 0] @@ -398,7 +400,7 @@ def add_H2_boilers(n): c = "Link" logger.info("Add H2 boilers.") # existing gas boilers - mask = n.links.carrier.str.contains("gas boiler") & ~n.links.p_nom_extendable + mask = n.links.carrier.str.contains("gas boiler") & (not n.links.p_nom_extendable) gas_i = n.links[mask].index df = n.links.loc[gas_i] # adjust bus 0 From 1f482f3c9259fcfab94280a85bf38fcea9609562 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 6 Feb 2024 11:45:20 +0100 Subject: [PATCH 250/591] Revert mistaken deprecation "fix" --- scripts/prepare_perfect_foresight.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index 467682a9..cf013577 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -400,7 +400,7 @@ def add_H2_boilers(n): c = "Link" logger.info("Add H2 boilers.") # existing gas boilers - mask = n.links.carrier.str.contains("gas boiler") & (not n.links.p_nom_extendable) + mask = n.links.carrier.str.contains("gas boiler") & ~n.links.p_nom_extendable gas_i = n.links[mask].index df = n.links.loc[gas_i] # adjust bus 0 From 3e6394b23c3e5361eb8e97bf5ce4e8d62727a666 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 6 Feb 2024 13:55:27 +0100 Subject: [PATCH 251/591] revert to previous offshore wind turbine models --- config/config.default.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index bc420b36..5afc6f8e 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -187,7 +187,7 @@ renewable: cutout: europe-2013-era5 resource: method: wind - turbine: NREL_ReferenceTurbine_5MW_offshore + turbine: NREL_ReferenceTurbine_2020ATB_5.5MW add_cutout_windspeed: true capacity_per_sqkm: 2 correction_factor: 0.8855 @@ -203,7 +203,7 @@ renewable: cutout: europe-2013-era5 resource: method: wind - turbine: Vestas_V164_7MW_offshore + turbine: NREL_ReferenceTurbine_2020ATB_5.5MW add_cutout_windspeed: true capacity_per_sqkm: 2 correction_factor: 0.8855 From ba409c2f1e1943c57ddc3b63460cd21ba2cd308c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 6 Feb 2024 13:55:51 +0100 Subject: [PATCH 252/591] backwards compatibility with old profile_{tech}.nc files --- scripts/build_renewable_profiles.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 99b177a8..a24045a8 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -411,9 +411,13 @@ if __name__ == "__main__": ds["underwater_fraction"] = xr.DataArray(underwater_fraction, [buses]) # select only buses with some capacity and minimal capacity factor + mean_profile = ds["profile"].mean("time") + if "year" in ds.indexes: + mean_profile.max("year") + ds = ds.sel( bus=( - (ds["profile"].mean("time").max("year") > params.get("min_p_max_pu", 0.0)) + (mean_profile > params.get("min_p_max_pu", 0.0)) & (ds["p_nom_max"] > params.get("min_p_nom_max", 0.0)) ) ) From c8e18298803fa9c2dd838008902fa6f41b5857d0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 6 Feb 2024 18:38:53 +0100 Subject: [PATCH 253/591] fix to backwards compatibility with old profile_{tech}.nc files --- scripts/build_renewable_profiles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index a24045a8..a075450d 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -413,7 +413,7 @@ if __name__ == "__main__": # select only buses with some capacity and minimal capacity factor mean_profile = ds["profile"].mean("time") if "year" in ds.indexes: - mean_profile.max("year") + mean_profile = mean_profile.max("year") ds = ds.sel( bus=( From 823765b353991918cbd7e0bd6432b210b1e146f2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 7 Feb 2024 09:52:30 +0100 Subject: [PATCH 254/591] update technology-data to 0.7.0 by default --- config/config.default.yaml | 2 +- doc/release_notes.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 5afc6f8e..b13bed4e 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -650,7 +650,7 @@ industry: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#costs costs: year: 2030 - version: v0.6.2 + version: v0.7.0 rooftop_share: 0.14 # based on the potentials, assuming (0.1 kW/m2 and 10 m2/person) social_discountrate: 0.02 fill_values: diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 976d727e..bf9860c6 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,8 @@ Release Notes Upcoming Release ================ +* Upgrade techno-economic assumptions to ``technology-data`` v0.7.0. + * Bugfix: Correct technology keys for the electricity production plotting to work out the box. * New configuration option ``everywhere_powerplants`` to build conventional powerplants everywhere, irrespective of existing powerplants locations, in the network (https://github.com/PyPSA/pypsa-eur/pull/850). From c3d3b5f415342d526a3283f9bf422604c9f89b0b Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 7 Feb 2024 10:55:44 +0100 Subject: [PATCH 255/591] Fixes to `calculated_weighted_prices` --- scripts/make_summary_perfect.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/make_summary_perfect.py b/scripts/make_summary_perfect.py index d68ac628..064db454 100644 --- a/scripts/make_summary_perfect.py +++ b/scripts/make_summary_perfect.py @@ -492,7 +492,7 @@ def calculate_weighted_prices(n, label, weighted_prices): else: suffix = " " + carrier - buses = n.buses.index[n.buses.index.str[2:] == suffix] + buses = n.buses.index[n.buses.index.str[5:] == suffix] if buses.empty: continue @@ -503,12 +503,14 @@ def calculate_weighted_prices(n, label, weighted_prices): else n.loads_t.p_set.reindex(buses, axis=1) ) for tech in value: - names = n.links.index[n.links.index.to_series().str[-len(tech) :] == tech] + names = n.links.index[ + n.links.index.to_series().str[-len(tech) - 5 : -5] == tech + ] if names.empty: continue - load += n.links_t.p0[names].T.groupby(n.links.loc[names, "bus0"]).sum() + load += n.links_t.p0[names].T.groupby(n.links.loc[names, "bus0"]).sum().T # Add H2 Store when charging # if carrier == "H2": @@ -644,7 +646,7 @@ def calculate_co2_emissions(n, label, df): emitted = n.generators_t.p[gens.index].mul(em_pu) emitted_grouped = ( - emitted.groupby(level=0).sum().T.groupby(n.generators.carrier).sum().T + emitted.groupby(level=0).sum().T.groupby(n.generators.carrier).sum() ) df = df.reindex(emitted_grouped.index.union(df.index)) From bf073000108e37e9b948185dcb84321c4fe1bcaf Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 7 Feb 2024 11:03:48 +0100 Subject: [PATCH 256/591] add_electricity: Remove long-deprecated function attach_extendable_generators --- doc/release_notes.rst | 2 ++ scripts/add_electricity.py | 71 -------------------------------------- 2 files changed, 2 insertions(+), 71 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index bf9860c6..685f8502 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,8 @@ Release Notes Upcoming Release ================ +* Remove long-deprecated function ``attach_extendable_generators`` in :mod:`add_electricity`. + * Upgrade techno-economic assumptions to ``technology-data`` v0.7.0. * Bugfix: Correct technology keys for the electricity production plotting to work out the box. diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 9fd7e4a5..ab97dcd0 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -662,77 +662,6 @@ def attach_hydro(n, costs, ppl, profile_hydro, hydro_capacities, carriers, **par ) -def attach_extendable_generators(n, costs, ppl, carriers): - logger.warning( - "The function `attach_extendable_generators` is deprecated in v0.5.0." - ) - add_missing_carriers(n, carriers) - add_co2_emissions(n, costs, carriers) - - for tech in carriers: - if tech.startswith("OCGT"): - ocgt = ( - ppl.query("carrier in ['OCGT', 'CCGT']") - .groupby("bus", as_index=False) - .first() - ) - n.madd( - "Generator", - ocgt.index, - suffix=" OCGT", - bus=ocgt["bus"], - carrier=tech, - p_nom_extendable=True, - p_nom=0.0, - capital_cost=costs.at["OCGT", "capital_cost"], - marginal_cost=costs.at["OCGT", "marginal_cost"], - efficiency=costs.at["OCGT", "efficiency"], - ) - - elif tech.startswith("CCGT"): - ccgt = ( - ppl.query("carrier in ['OCGT', 'CCGT']") - .groupby("bus", as_index=False) - .first() - ) - n.madd( - "Generator", - ccgt.index, - suffix=" CCGT", - bus=ccgt["bus"], - carrier=tech, - p_nom_extendable=True, - p_nom=0.0, - capital_cost=costs.at["CCGT", "capital_cost"], - marginal_cost=costs.at["CCGT", "marginal_cost"], - efficiency=costs.at["CCGT", "efficiency"], - ) - - elif tech.startswith("nuclear"): - nuclear = ( - ppl.query("carrier == 'nuclear'").groupby("bus", as_index=False).first() - ) - n.madd( - "Generator", - nuclear.index, - suffix=" nuclear", - bus=nuclear["bus"], - carrier=tech, - p_nom_extendable=True, - p_nom=0.0, - capital_cost=costs.at["nuclear", "capital_cost"], - marginal_cost=costs.at["nuclear", "marginal_cost"], - efficiency=costs.at["nuclear", "efficiency"], - ) - - else: - raise NotImplementedError( - "Adding extendable generators for carrier " - "'{tech}' is not implemented, yet. " - "Only OCGT, CCGT and nuclear are allowed at the moment." - ) - - def attach_OPSD_renewables(n: pypsa.Network, tech_map: Dict[str, List[str]]) -> None: """ Attach renewable capacities from the OPSD dataset to the network. From 5902be199f1f1f9e43f437eb32d9ef47a33918bc Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 7 Feb 2024 11:20:05 +0100 Subject: [PATCH 257/591] powerplants_filter: phase-out status 2023 (incl. nuclear in DE) --- config/config.default.yaml | 2 +- doc/release_notes.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index b13bed4e..93b0568e 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -114,7 +114,7 @@ electricity: Store: [battery, H2] Link: [] # H2 pipeline - powerplants_filter: (DateOut >= 2022 or DateOut != DateOut) + powerplants_filter: (DateOut >= 2023 or DateOut != DateOut) and not (Country == 'Germany' and Fueltype == 'Nuclear') custom_powerplants: false everywhere_powerplants: [nuclear, oil, OCGT, CCGT, coal, lignite, geothermal, biomass] diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 685f8502..b1511dd7 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -12,6 +12,8 @@ Upcoming Release * Remove long-deprecated function ``attach_extendable_generators`` in :mod:`add_electricity`. +* The filtering of power plants in the ``config.default.yaml`` has been updated regarding phased-out power plants in 2023. + * Upgrade techno-economic assumptions to ``technology-data`` v0.7.0. * Bugfix: Correct technology keys for the electricity production plotting to work out the box. From f38681f13462187dc83eb78c093bd0ccfa5899fb Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Mon, 29 Jan 2024 10:02:05 +0100 Subject: [PATCH 258/591] correctly source the existing heating technologies for buildings The source URL has changed. It represents the year 2012 and is only for buildings, not district heating. So the capacities for urban central are now set to zero from this source. --- doc/configtables/licenses-sector.csv | 2 +- scripts/add_existing_baseyear.py | 12 +++------ .../build_existing_heating_distribution.py | 27 +++++++++++-------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/doc/configtables/licenses-sector.csv b/doc/configtables/licenses-sector.csv index a297b2f6..7f20b5a6 100644 --- a/doc/configtables/licenses-sector.csv +++ b/doc/configtables/licenses-sector.csv @@ -10,7 +10,7 @@ BASt emobility statistics,emobility/,unknown,http://www.bast.de/DE/Verkehrstechn BDEW heating profile,heat_load_profile_BDEW.csv,unknown,https://github.com/oemof/demandlib heating profiles for Aarhus,heat_load_profile_DK_AdamJensen.csv,unknown,Adam Jensen MA thesis at Aarhus University co2 budgets,co2_budget.csv,CC BY 4.0,https://arxiv.org/abs/2004.11009 -existing heating potentials,existing_infrastructure/existing_heating_raw.csv,unknown,https://ec.europa.eu/energy/studies/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment_en?redir=1 +existing heating potentials,existing_infrastructure/existing_heating_raw.csv,unknown,https://energy.ec.europa.eu/publications/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment-fossilrenewables-1_en IRENA existing VRE capacities,existing_infrastructure/{solar|onwind|offwind}_capcity_IRENA.csv,unknown,https://www.irena.org/Statistics/Download-Data USGS ammonia production,myb1-2017-nitro.xls,unknown,https://www.usgs.gov/centers/nmic/nitrogen-statistics-and-information hydrogen salt cavern potentials,h2_salt_caverns_GWh_per_sqkm.geojson,CC BY 4.0,https://doi.org/10.1016/j.ijhydene.2019.12.161 https://doi.org/10.20944/preprints201910.0187.v1 diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 4f476b4d..3934079e 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -402,16 +402,10 @@ def add_heating_capacities_installed_before_baseyear( """ logger.debug(f"Adding heating capacities installed before {baseyear}") - # Add existing heating capacities, data comes from the study - # "Mapping and analyses of the current and future (2020 - 2030) - # heating/cooling fuel deployment (fossil/renewables) " - # https://ec.europa.eu/energy/studies/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment_en?redir=1 - # file: "WP2_DataAnnex_1_BuildingTechs_ForPublication_201603.xls" -> "existing_heating_raw.csv". - # TODO start from original file + existing_heating = pd.read_csv(snakemake.input.existing_heating_distribution, + header=[0,1], + index_col=0) - existing_heating = pd.read_csv( - snakemake.input.existing_heating_distribution, header=[0, 1], index_col=0 - ) techs = existing_heating.columns.get_level_values(1).unique() diff --git a/scripts/build_existing_heating_distribution.py b/scripts/build_existing_heating_distribution.py index 67993c29..12bfd4da 100644 --- a/scripts/build_existing_heating_distribution.py +++ b/scripts/build_existing_heating_distribution.py @@ -16,9 +16,17 @@ cc = coco.CountryConverter() def build_existing_heating(): # retrieve existing heating capacities - existing_heating = pd.read_csv( - snakemake.input.existing_heating, index_col=0, header=0 - ) + # Add existing heating capacities, data comes from the study + # "Mapping and analyses of the current and future (2020 - 2030) + # heating/cooling fuel deployment (fossil/renewables) " + # https://energy.ec.europa.eu/publications/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment-fossilrenewables-1_en + # file: "WP2_DataAnnex_1_BuildingTechs_ForPublication_201603.xls" -> "existing_heating_raw.csv". + # data is for buildings only (i.e. NOT district heating) and represents the year 2012 + # TODO start from original file + + existing_heating = pd.read_csv(snakemake.input.existing_heating, + index_col=0, + header=0) # data for Albania, Montenegro and Macedonia not included in database existing_heating.loc["Albania"] = np.nan @@ -67,17 +75,14 @@ def build_existing_heating(): nodal_sectoral_totals.sum(axis=1), axis=0 ) - nodal_heat_name_fraction = pd.DataFrame(dtype=float) + nodal_heat_name_fraction = pd.DataFrame(index=district_heat_info.index, + dtype=float) - nodal_heat_name_fraction["urban central"] = dist_fraction + nodal_heat_name_fraction["urban central"] = 0. for sector in sectors: - nodal_heat_name_fraction[f"{sector} rural"] = nodal_sectoral_fraction[ - sector - ] * (1 - urban_fraction) - nodal_heat_name_fraction[f"{sector} urban decentral"] = nodal_sectoral_fraction[ - sector - ] * (urban_fraction - dist_fraction) + nodal_heat_name_fraction[f"{sector} rural"] = nodal_sectoral_fraction[sector]*(1 - urban_fraction) + nodal_heat_name_fraction[f"{sector} urban decentral"] = nodal_sectoral_fraction[sector]*urban_fraction nodal_heat_name_tech = pd.concat( { From d7f3f16a9bf5a8228b7d28157f292260c3aaff40 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 7 Feb 2024 17:15:08 +0100 Subject: [PATCH 259/591] autoformat --- scripts/add_existing_baseyear.py | 7 +++---- .../build_existing_heating_distribution.py | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 3934079e..e8683e16 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -402,10 +402,9 @@ def add_heating_capacities_installed_before_baseyear( """ logger.debug(f"Adding heating capacities installed before {baseyear}") - existing_heating = pd.read_csv(snakemake.input.existing_heating_distribution, - header=[0,1], - index_col=0) - + existing_heating = pd.read_csv( + snakemake.input.existing_heating_distribution, header=[0, 1], index_col=0 + ) techs = existing_heating.columns.get_level_values(1).unique() diff --git a/scripts/build_existing_heating_distribution.py b/scripts/build_existing_heating_distribution.py index 12bfd4da..78518597 100644 --- a/scripts/build_existing_heating_distribution.py +++ b/scripts/build_existing_heating_distribution.py @@ -24,9 +24,9 @@ def build_existing_heating(): # data is for buildings only (i.e. NOT district heating) and represents the year 2012 # TODO start from original file - existing_heating = pd.read_csv(snakemake.input.existing_heating, - index_col=0, - header=0) + existing_heating = pd.read_csv( + snakemake.input.existing_heating, index_col=0, header=0 + ) # data for Albania, Montenegro and Macedonia not included in database existing_heating.loc["Albania"] = np.nan @@ -75,14 +75,17 @@ def build_existing_heating(): nodal_sectoral_totals.sum(axis=1), axis=0 ) - nodal_heat_name_fraction = pd.DataFrame(index=district_heat_info.index, - dtype=float) + nodal_heat_name_fraction = pd.DataFrame(index=district_heat_info.index, dtype=float) - nodal_heat_name_fraction["urban central"] = 0. + nodal_heat_name_fraction["urban central"] = 0.0 for sector in sectors: - nodal_heat_name_fraction[f"{sector} rural"] = nodal_sectoral_fraction[sector]*(1 - urban_fraction) - nodal_heat_name_fraction[f"{sector} urban decentral"] = nodal_sectoral_fraction[sector]*urban_fraction + nodal_heat_name_fraction[f"{sector} rural"] = nodal_sectoral_fraction[ + sector + ] * (1 - urban_fraction) + nodal_heat_name_fraction[f"{sector} urban decentral"] = ( + nodal_sectoral_fraction[sector] * urban_fraction + ) nodal_heat_name_tech = pd.concat( { From 6d94439bbb9b650dc6d3c8d1da3064ee5affd813 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Mon, 29 Jan 2024 11:25:09 +0100 Subject: [PATCH 260/591] for existing heating use new default_heating_lifetime This is because old costs default (25) is longer than all heating technologies (20). Script was distributing across 25 years, then throwing out boilers older than 20 years, an inconsistent behaviour. Now existing boilers are smoothly distributed across 20 years. --- config/config.default.yaml | 1 + scripts/add_existing_baseyear.py | 10 ++-------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 93b0568e..633bed70 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -357,6 +357,7 @@ 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 + default_heating_lifetime: 20 conventional_carriers: - lignite - coal diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index e8683e16..13527fad 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -429,7 +429,7 @@ def add_heating_capacities_installed_before_baseyear( if int(grouping_year) + default_lifetime <= int(baseyear): continue - # installation is assumed to be linear for the past 25 years (default lifetime) + # installation is assumed to be linear for the past default_lifetime years ratio = (int(grouping_year) - int(grouping_years[i - 1])) / default_lifetime n.madd( @@ -536,12 +536,6 @@ def add_heating_capacities_installed_before_baseyear( ], ) - # drop assets which are at the end of their lifetime - links_i = n.links[(n.links.build_year + n.links.lifetime <= baseyear)].index - logger.info("Removing following links because at end of their lifetime:") - logger.info(links_i) - n.mremove("Link", links_i) - if __name__ == "__main__": if "snakemake" not in globals(): @@ -598,7 +592,7 @@ if __name__ == "__main__": .to_pandas() .reindex(index=n.snapshots) ) - default_lifetime = snakemake.params.costs["fill_values"]["lifetime"] + default_lifetime = snakemake.params.existing_capacities["default_heating_lifetime"] add_heating_capacities_installed_before_baseyear( n, baseyear, From 92d00a0c83d6ec912d7c34eeffea8da67bee18ea Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Mon, 29 Jan 2024 12:22:54 +0100 Subject: [PATCH 261/591] add new default to overdimension heating in individual buildings This allows them to cover heat demand peaks e.g. 10% higher than those in the data. The disadvantage of manipulating the costs is that the capacity is then not quite right. This way at least the costs are right. Doing it properly would require introducing artificial peaks, but this creates new problems (e.g. what is going on with wind/solar/other demand). --- config/config.default.yaml | 1 + scripts/add_existing_baseyear.py | 4 +++- scripts/prepare_sector_network.py | 22 ++++++++++++++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 633bed70..b24f2ceb 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -483,6 +483,7 @@ sector: resistive_heaters: true oil_boilers: false biomass_boiler: true + overdimension_individual_heating: 1.1 #to cover demand peaks bigger than data chp: true micro_chp: false solar_thermal: true diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 13527fad..c0d37a5b 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -592,7 +592,9 @@ if __name__ == "__main__": .to_pandas() .reindex(index=n.snapshots) ) - default_lifetime = snakemake.params.existing_capacities["default_heating_lifetime"] + default_lifetime = snakemake.params.existing_capacities[ + "default_heating_lifetime" + ] add_heating_capacities_installed_before_baseyear( n, baseyear, diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 394a67f8..eb24d9cf 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1680,6 +1680,8 @@ def add_heat(n, costs): heat_demand = build_heat_demand(n) + overdim_factor = options["overdimension_individual_heating"] + district_heat_info = pd.read_csv(snakemake.input.district_heat_share, index_col=0) dist_fraction = district_heat_info["district fraction of node"] urban_fraction = district_heat_info["urban fraction"] @@ -1814,7 +1816,8 @@ def add_heat(n, costs): carrier=f"{name} {heat_pump_type} heat pump", efficiency=efficiency, capital_cost=costs.at[costs_name, "efficiency"] - * costs.at[costs_name, "fixed"], + * costs.at[costs_name, "fixed"] + * overdim_factor, p_nom_extendable=True, lifetime=costs.at[costs_name, "lifetime"], ) @@ -1883,7 +1886,9 @@ def add_heat(n, costs): bus1=nodes + f" {name} heat", carrier=name + " resistive heater", efficiency=costs.at[key, "efficiency"], - capital_cost=costs.at[key, "efficiency"] * costs.at[key, "fixed"], + capital_cost=costs.at[key, "efficiency"] + * costs.at[key, "fixed"] + * overdim_factor, p_nom_extendable=True, lifetime=costs.at[key, "lifetime"], ) @@ -1901,7 +1906,9 @@ def add_heat(n, costs): carrier=name + " gas boiler", efficiency=costs.at[key, "efficiency"], efficiency2=costs.at["gas", "CO2 intensity"], - capital_cost=costs.at[key, "efficiency"] * costs.at[key, "fixed"], + capital_cost=costs.at[key, "efficiency"] + * costs.at[key, "fixed"] + * overdim_factor, lifetime=costs.at[key, "lifetime"], ) @@ -1915,7 +1922,8 @@ def add_heat(n, costs): bus=nodes + f" {name} heat", carrier=name + " solar thermal", p_nom_extendable=True, - capital_cost=costs.at[name_type + " solar thermal", "fixed"], + capital_cost=costs.at[name_type + " solar thermal", "fixed"] + * overdim_factor, p_max_pu=solar_thermal[nodes], lifetime=costs.at[name_type + " solar thermal", "lifetime"], ) @@ -2348,7 +2356,8 @@ def add_biomass(n, costs): carrier=name + " biomass boiler", efficiency=costs.at["biomass boiler", "efficiency"], capital_cost=costs.at["biomass boiler", "efficiency"] - * costs.at["biomass boiler", "fixed"], + * costs.at["biomass boiler", "fixed"] + * options["overdimension_individual_heating"], marginal_cost=costs.at["biomass boiler", "pelletizing cost"], lifetime=costs.at["biomass boiler", "lifetime"], ) @@ -2806,7 +2815,8 @@ def add_industry(n, costs): efficiency=costs.at["decentral oil boiler", "efficiency"], efficiency2=costs.at["oil", "CO2 intensity"], capital_cost=costs.at["decentral oil boiler", "efficiency"] - * costs.at["decentral oil boiler", "fixed"], + * costs.at["decentral oil boiler", "fixed"] + * options["overdimension_individual_heating"], lifetime=costs.at["decentral oil boiler", "lifetime"], ) From 7ad5dcc3eea0bed4bcc66acae6f8a6c3bb5ed5bd Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 7 Feb 2024 17:25:09 +0100 Subject: [PATCH 262/591] add release notes and documentation --- doc/configtables/existing_capacities.csv | 1 + doc/configtables/sector.csv | 1 + doc/release_notes.rst | 13 +++++++++++++ 3 files changed, 15 insertions(+) diff --git a/doc/configtables/existing_capacities.csv b/doc/configtables/existing_capacities.csv index 87519193..eacae35b 100644 --- a/doc/configtables/existing_capacities.csv +++ b/doc/configtables/existing_capacities.csv @@ -3,4 +3,5 @@ grouping_years_power ,--,A list of years,Intervals to group existing capacities grouping_years_heat ,--,A list of years below 2020,Intervals to group existing capacities for heat threshold_capacity ,MW,float,Capacities generators and links of below threshold are removed during add_existing_capacities +default_heating_lifetime ,years,int,Default lifetime for heating technologies conventional_carriers ,--,"Any subset of {uranium, coal, lignite, oil} ",List of conventional power plants to include in the sectoral network diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv index 338cf34e..d8cc3288 100644 --- a/doc/configtables/sector.csv +++ b/doc/configtables/sector.csv @@ -66,6 +66,7 @@ boilers,--,"{true, false}",Add option for transforming gas into heat using gas b resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers) oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers +overdimension_individual_heating,--,"float",Add option for overdimensioning individual heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1. chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas. solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b1511dd7..fea45d74 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,19 @@ Release Notes Upcoming Release ================ +* Add new default to overdimension heating in individual buildings. This allows + them to cover heat demand peaks e.g. 10% higher than those in the data. The + disadvantage of manipulating the costs is that the capacity is then not quite + right. This way at least the costs are right. + +* Add option to specify to set a default heating lifetime for existing heating + (``existing_capacities: default_heating_lifetime:``). + +* Correctly source the existing heating technologies for buildings since the + source URL has changed. It represents the year 2012 and is only for + buildings, not district heating. So the capacities for urban central are now + set to zero from this source. + * Remove long-deprecated function ``attach_extendable_generators`` in :mod:`add_electricity`. * The filtering of power plants in the ``config.default.yaml`` has been updated regarding phased-out power plants in 2023. From 3e411fe79d9a8d707053ae9b37fd6c17cd81ee0d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:27:18 +0000 Subject: [PATCH 263/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/release_notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index fea45d74..ee7bd64b 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -16,7 +16,7 @@ Upcoming Release right. This way at least the costs are right. * Add option to specify to set a default heating lifetime for existing heating - (``existing_capacities: default_heating_lifetime:``). + (``existing_capacities: default_heating_lifetime:``). * Correctly source the existing heating technologies for buildings since the source URL has changed. It represents the year 2012 and is only for From b9c71c3c151662d51334c5ec66fd6136b733cfad Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 7 Feb 2024 17:53:10 +0100 Subject: [PATCH 264/591] add logs to plot_*_network rules --- rules/postprocess.smk | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 2e90d233..18d65c16 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -41,6 +41,11 @@ if config["foresight"] != "perfect": threads: 2 resources: mem_mb=10000, + log: + ( + LOGS + + "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ) benchmark: ( BENCHMARKS @@ -65,6 +70,11 @@ if config["foresight"] != "perfect": threads: 2 resources: mem_mb=10000, + log: + ( + LOGS + + "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ) benchmark: ( BENCHMARKS @@ -88,6 +98,11 @@ if config["foresight"] != "perfect": threads: 2 resources: mem_mb=10000, + log: + ( + LOGS + + "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ) benchmark: ( BENCHMARKS From e0dafc50b34ee4e62a624fd3b3c09ddc8c65a9b5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 9 Feb 2024 10:15:11 +0100 Subject: [PATCH 265/591] add missing heat pump colors --- config/config.default.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/config.default.yaml b/config/config.default.yaml index b24f2ceb..1033d49d 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -1001,9 +1001,11 @@ plotting: air heat pump: '#36eb41' residential urban decentral air heat pump: '#48f74f' services urban decentral air heat pump: '#5af95d' + services rural air heat pump: '#5af95d' urban central air heat pump: '#6cfb6b' ground heat pump: '#2fb537' residential rural ground heat pump: '#48f74f' + residential rural air heat pump: '#48f74f' services rural ground heat pump: '#5af95d' Ambient: '#98eb9d' CHP: '#8a5751' From 3691f9f4c16fd2149fdc255e8e3669ce7117077c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 9 Feb 2024 13:59:15 +0100 Subject: [PATCH 266/591] update version compatibility handling --- rules/postprocess.smk | 6 +++--- scripts/_helpers.py | 8 +++----- scripts/base_network.py | 8 ++++++-- scripts/build_industrial_distribution_key.py | 8 +------- scripts/cluster_gas_network.py | 10 +++------- scripts/cluster_network.py | 7 ++++++- scripts/prepare_sector_network.py | 18 +++--------------- 7 files changed, 25 insertions(+), 40 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 18d65c16..98b90fd1 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -45,7 +45,7 @@ if config["foresight"] != "perfect": ( LOGS + "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ) + ), benchmark: ( BENCHMARKS @@ -74,7 +74,7 @@ if config["foresight"] != "perfect": ( LOGS + "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ) + ), benchmark: ( BENCHMARKS @@ -102,7 +102,7 @@ if config["foresight"] != "perfect": ( LOGS + "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ) + ), benchmark: ( BENCHMARKS diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 3173671d..3de23c9f 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -264,7 +264,6 @@ def mock_snakemake( import os import snakemake as sm - from packaging.version import Version, parse from pypsa.descriptors import Dict from snakemake.script import Snakemake @@ -290,13 +289,12 @@ def mock_snakemake( if os.path.exists(p): snakefile = p break - kwargs = ( - dict(rerun_triggers=[]) if parse(sm.__version__) > Version("7.7.0") else {} - ) if isinstance(configfiles, str): configfiles = [configfiles] - workflow = sm.Workflow(snakefile, overwrite_configfiles=configfiles, **kwargs) + workflow = sm.Workflow( + snakefile, overwrite_configfiles=configfiles, rerun_triggers=[] + ) workflow.include(snakefile) if configfiles: diff --git a/scripts/base_network.py b/scripts/base_network.py index 1de3ef96..2bfee9d7 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -78,10 +78,13 @@ import shapely.prepared import shapely.wkt import yaml from _helpers import configure_logging +from packaging.version import Version, parse from scipy import spatial from scipy.sparse import csgraph from shapely.geometry import LineString, Point +PD_GE_2_2 = parse(pd.__version__) >= Version("2.2") + logger = logging.getLogger(__name__) @@ -524,12 +527,13 @@ def _set_countries_and_substations(n, config, country_shapes, offshore_shapes): ) return pd.Series(key, index) + compat_kws = dict(include_groups=False) if PD_GE_2_2 else {} gb = buses.loc[substation_b].groupby( ["x", "y"], as_index=False, group_keys=False, sort=False ) - bus_map_low = gb.apply(prefer_voltage, "min", include_groups=False) + bus_map_low = gb.apply(prefer_voltage, "min", **compat_kws) lv_b = (bus_map_low == bus_map_low.index).reindex(buses.index, fill_value=False) - bus_map_high = gb.apply(prefer_voltage, "max", include_groups=False) + bus_map_high = gb.apply(prefer_voltage, "max", **compat_kws) hv_b = (bus_map_high == bus_map_high.index).reindex(buses.index, fill_value=False) onshore_b = pd.Series(False, buses.index) diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index fe7cf0c1..9b234e29 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -13,7 +13,6 @@ from itertools import product import country_converter as coco import geopandas as gpd import pandas as pd -from packaging.version import Version, parse logger = logging.getLogger(__name__) cc = coco.CountryConverter() @@ -84,12 +83,7 @@ def prepare_hotmaps_database(regions): gdf = gpd.GeoDataFrame(df, geometry="coordinates", crs="EPSG:4326") - kws = ( - dict(op="within") - if parse(gpd.__version__) < Version("0.10") - else dict(predicate="within") - ) - gdf = gpd.sjoin(gdf, regions, how="inner", **kws) + gdf = gpd.sjoin(gdf, regions, how="inner", predicate="within") gdf.rename(columns={"index_right": "bus"}, inplace=True) gdf["country"] = gdf.bus.str[:2] diff --git a/scripts/cluster_gas_network.py b/scripts/cluster_gas_network.py index bc4a6e14..e709d772 100755 --- a/scripts/cluster_gas_network.py +++ b/scripts/cluster_gas_network.py @@ -10,7 +10,6 @@ import logging import geopandas as gpd import pandas as pd -from packaging.version import Version, parse from pypsa.geo import haversine_pts from shapely import wkt @@ -41,12 +40,9 @@ def build_clustered_gas_network(df, bus_regions, length_factor=1.25): for i in [0, 1]: gdf = gpd.GeoDataFrame(geometry=df[f"point{i}"], crs="EPSG:4326") - kws = ( - dict(op="within") - if parse(gpd.__version__) < Version("0.10") - else dict(predicate="within") - ) - bus_mapping = gpd.sjoin(gdf, bus_regions, how="left", **kws).index_right + bus_mapping = gpd.sjoin( + gdf, bus_regions, how="left", predicate="within" + ).index_right bus_mapping = bus_mapping.groupby(bus_mapping.index).first() df[f"bus{i}"] = bus_mapping diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 34a138cd..fe74ac38 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -135,6 +135,7 @@ import pypsa import seaborn as sns from _helpers import configure_logging, update_p_nom_max from add_electricity import load_costs +from packaging.version import Version, parse from pypsa.clustering.spatial import ( busmap_by_greedy_modularity, busmap_by_hac, @@ -142,6 +143,8 @@ from pypsa.clustering.spatial import ( get_clustering_from_busmap, ) +PD_GE_2_2 = parse(pd.__version__) >= Version("2.2") + warnings.filterwarnings(action="ignore", category=UserWarning) idx = pd.IndexSlice logger = logging.getLogger(__name__) @@ -362,9 +365,11 @@ def busmap_for_n_clusters( f"`algorithm` must be one of 'kmeans' or 'hac'. Is {algorithm}." ) + compat_kws = dict(include_groups=False) if PD_GE_2_2 else {} + return ( n.buses.groupby(["country", "sub_network"], group_keys=False) - .apply(busmap_for_country, include_groups=False) + .apply(busmap_for_country, **compat_kws) .squeeze() .rename("busmap") ) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index eb24d9cf..be8aea53 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -23,15 +23,12 @@ from add_electricity import calculate_annuity, sanitize_carriers, sanitize_locat from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement from networkx.algorithms.connectivity.edge_augmentation import k_edge_augmentation -from packaging.version import Version, parse from pypsa.geo import haversine_pts from pypsa.io import import_components_from_dataframe from scipy.stats import beta spatial = SimpleNamespace() logger = logging.getLogger(__name__) -pd_version = parse(pd.__version__) -agg_group_kwargs = dict(numeric_only=False) if pd_version >= Version("1.3") else {} def define_spatial(nodes, options): @@ -1853,16 +1850,7 @@ def add_heat(n, costs): p_nom_extendable=True, ) - if isinstance(options["tes_tau"], dict): - tes_time_constant_days = options["tes_tau"][name_type] - else: - logger.warning( - "Deprecated: a future version will require you to specify 'tes_tau' ", - "for 'decentral' and 'central' separately.", - ) - tes_time_constant_days = ( - options["tes_tau"] if name_type == "decentral" else 180.0 - ) + tes_time_constant_days = options["tes_tau"][name_type] n.madd( "Store", @@ -3404,7 +3392,7 @@ def cluster_heat_buses(n): # cluster heat nodes # static dataframe agg = define_clustering(df.columns, aggregate_dict) - df = df.groupby(level=0).agg(agg, **agg_group_kwargs) + df = df.groupby(level=0).agg(agg, numeric_only=False) # time-varying data pnl = c.pnl agg = define_clustering(pd.Index(pnl.keys()), aggregate_dict) @@ -3413,7 +3401,7 @@ def cluster_heat_buses(n): def renamer(s): return s.replace("residential ", "").replace("services ", "") - pnl[k] = pnl[k].T.groupby(renamer).agg(agg[k], **agg_group_kwargs).T + pnl[k] = pnl[k].T.groupby(renamer).agg(agg[k], numeric_only=False).T # remove unclustered assets of service/residential to_drop = c.df.index.difference(df.index) From 4b6199de42d8547c35b4b35dec482ab23ffb55b3 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 9 Feb 2024 15:43:27 +0100 Subject: [PATCH 267/591] create a bus for every unique coordinate, not only substations (closes #699) --- rules/postprocess.smk | 6 +++--- scripts/base_network.py | 1 + scripts/build_bus_regions.py | 8 +++++++- scripts/simplify_network.py | 1 + 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 18d65c16..98b90fd1 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -45,7 +45,7 @@ if config["foresight"] != "perfect": ( LOGS + "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ) + ), benchmark: ( BENCHMARKS @@ -74,7 +74,7 @@ if config["foresight"] != "perfect": ( LOGS + "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ) + ), benchmark: ( BENCHMARKS @@ -102,7 +102,7 @@ if config["foresight"] != "perfect": ( LOGS + "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ) + ), benchmark: ( BENCHMARKS diff --git a/scripts/base_network.py b/scripts/base_network.py index 1de3ef96..684ca613 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -555,6 +555,7 @@ def _set_countries_and_substations(n, config, country_shapes, offshore_shapes): for b, df in product(("bus0", "bus1"), (n.lines, n.links)): has_connections_b |= ~df.groupby(b).under_construction.min() + buses["onshore_bus"] = onshore_b buses["substation_lv"] = ( lv_b & onshore_b & (~buses["under_construction"]) & has_connections_b ) diff --git a/scripts/build_bus_regions.py b/scripts/build_bus_regions.py index a6500bb0..f9bf287e 100644 --- a/scripts/build_bus_regions.py +++ b/scripts/build_bus_regions.py @@ -135,7 +135,13 @@ if __name__ == "__main__": c_b = n.buses.country == country onshore_shape = country_shapes[country] - onshore_locs = n.buses.loc[c_b & n.buses.substation_lv, ["x", "y"]] + onshore_locs = ( + n.buses.loc[c_b & n.buses.onshore_bus] + .sort_values( + by="substation_lv", ascending=False + ) # preference for substations + .drop_duplicates(subset=["x", "y"], keep="first")[["x", "y"]] + ) onshore_regions.append( gpd.GeoDataFrame( { diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 31bc8f4e..cc4ff4f6 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -611,6 +611,7 @@ if __name__ == "__main__": "symbol", "tags", "under_construction", + "onshore_bus", "substation_lv", "substation_off", "geometry", From 201d0ddcfe00796d92ca33fcea6728cbeeb3a409 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 9 Feb 2024 15:48:54 +0100 Subject: [PATCH 268/591] build_shapes: handle europe_shape multipolygon with shapely>=2 (closes #852) --- scripts/build_shapes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_shapes.py b/scripts/build_shapes.py index 35bae147..c5faf597 100644 --- a/scripts/build_shapes.py +++ b/scripts/build_shapes.py @@ -158,7 +158,7 @@ def country_cover(country_shapes, eez_shapes=None): shapes = pd.concat([shapes, eez_shapes]) europe_shape = shapes.unary_union if isinstance(europe_shape, MultiPolygon): - europe_shape = max(europe_shape, key=attrgetter("area")) + europe_shape = max(europe_shape.geoms, key=attrgetter("area")) return Polygon(shell=europe_shape.exterior) From e838b63ded1eb2084964639c132b24c91f1bc123 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 10 Feb 2024 16:22:36 +0000 Subject: [PATCH 269/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 27 ++++++++++------- rules/build_sector.smk | 42 ++++++++++++++++++--------- rules/collect.smk | 18 ++++++------ rules/postprocess.smk | 10 +++---- rules/solve_myopic.smk | 6 ++-- scripts/cluster_network.py | 2 +- scripts/prepare_sector_network.py | 2 +- scripts/retrieve_sector_databundle.py | 2 +- scripts/solve_network.py | 2 +- 9 files changed, 67 insertions(+), 44 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index fd925d1f..4c6650bc 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -20,7 +20,7 @@ if config["enable"].get("prepare_links_p_nom", False): rule build_electricity_demand: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider countries=config_provider("countries"), load=config_provider("load"), input: @@ -62,7 +62,7 @@ rule build_powerplants: rule base_network: params: countries=config_provider("countries"), - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider lines=config_provider("lines"), links=config_provider("links"), transformers=config_provider("transformers"), @@ -145,7 +145,7 @@ if config["enable"].get("build_cutout", False): rule build_cutout: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider cutouts=config_provider("atlite", "cutouts"), input: regions_onshore=resources("regions_onshore.geojson"), @@ -259,7 +259,7 @@ else: rule build_renewable_profiles: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider renewable=config_provider("renewable"), input: **opt, @@ -401,18 +401,22 @@ rule add_electricity: if str(fn).startswith("data/") }, base_network=resources("networks/base.nc"), - line_rating=resources("networks/line_rating.nc") - if config["lines"]["dynamic_line_rating"]["activate"] - else resources("networks/base.nc"), + line_rating=( + resources("networks/line_rating.nc") + if config["lines"]["dynamic_line_rating"]["activate"] + else resources("networks/base.nc") + ), tech_costs=COSTS, regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), geth_hydro_capacities="data/geth2015_hydro_capacities.csv", unit_commitment="data/unit_commitment.csv", - fuel_price=resources("monthly_fuel_price.csv") - if config["conventional"]["dynamic_fuel_price"] - else [], + fuel_price=( + resources("monthly_fuel_price.csv") + if config["conventional"]["dynamic_fuel_price"] + else [] + ), load=resources("load.csv"), nuts3_shapes=resources("nuts3_shapes.geojson"), ua_md_gdp="data/GDP_PPP_30arcsec_v3_mapped_default.csv", @@ -540,7 +544,8 @@ rule prepare_network: snapshots={ "resolution": config["snapshots"].get("resolution", False), "segmentation": config["snapshots"].get("segmentation", False), - }, # TODO: use config provider + }, + # TODO: use config provider links=config_provider("links"), lines=config_provider("lines"), co2base=config_provider("electricity", "co2base"), diff --git a/rules/build_sector.smk b/rules/build_sector.smk index f0081d32..aea16519 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -94,7 +94,9 @@ rule build_gas_input_locations: regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), output: gas_input_nodes=resources("gas_input_locations_s{simpl}_{clusters}.geojson"), - gas_input_nodes_simplified=resources("gas_input_locations_s{simpl}_{clusters}_simplified.csv"), + gas_input_nodes_simplified=resources( + "gas_input_locations_s{simpl}_{clusters}_simplified.csv" + ), resources: mem_mb=2000, log: @@ -124,7 +126,7 @@ rule cluster_gas_network: rule build_daily_heat_demand: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), @@ -167,7 +169,7 @@ rule build_hourly_heat_demand: rule build_temperature_profiles: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), @@ -219,7 +221,7 @@ rule build_cop_profiles: rule build_solar_thermal_profiles: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO use config_provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO use config_provider solar_thermal=config_provider("solar_thermal"), input: pop_layout=resources("pop_layout_{scope}.nc"), @@ -287,7 +289,9 @@ rule build_biomass_potentials: biomass_potentials_all=resources( "biomass_potentials_all_s{simpl}_{clusters}_{planning_horizons}.csv" ), - biomass_potentials=resources("biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv"), + biomass_potentials=resources( + "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv" + ), threads: 1 resources: mem_mb=1000, @@ -707,7 +711,7 @@ rule build_shipping_demand: rule build_transport_demand: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider sector=config_provider("sector"), input: clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), @@ -814,7 +818,9 @@ rule prepare_sector_network: network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), energy_totals_name=resources("energy_totals.csv"), eurostat=input_eurostat, - pop_weighted_energy_totals=resources("pop_weighted_energy_totals_s{simpl}_{clusters}.csv"), + pop_weighted_energy_totals=resources( + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" + ), shipping_demand=resources("shipping_demand_s{simpl}_{clusters}.csv"), transport_demand=resources("transport_demand_s{simpl}_{clusters}.csv"), transport_data=resources("transport_data_s{simpl}_{clusters}.csv"), @@ -823,10 +829,14 @@ rule prepare_sector_network: co2_totals_name=resources("co2_totals.csv"), co2="data/bundle-sector/eea/UNFCCC_v23.csv", biomass_potentials=( - resources("biomass_potentials_s{simpl}_{clusters}_" - + "{}.csv".format(config["biomass"]["year"])) + resources( + "biomass_potentials_s{simpl}_{clusters}_" + + "{}.csv".format(config["biomass"]["year"]) + ) if config["foresight"] == "overnight" - else resources("biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv") + else resources( + "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv" + ) ), costs=( "data/costs_{}.csv".format(config["costs"]["year"]) @@ -840,9 +850,15 @@ rule prepare_sector_network: busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), simplified_pop_layout=resources("pop_layout_elec_s{simpl}.csv"), - industrial_demand=resources("industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), - hourly_heat_demand_total=resources("hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc"), - district_heat_share=resources("district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), + industrial_demand=resources( + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), + hourly_heat_demand_total=resources( + "hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc" + ), + district_heat_share=resources( + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"), temp_soil_rural=resources("temp_soil_rural_elec_s{simpl}_{clusters}.nc"), temp_soil_urban=resources("temp_soil_urban_elec_s{simpl}_{clusters}.nc"), diff --git a/rules/collect.smk b/rules/collect.smk index 0fb19165..8a451d7a 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -24,7 +24,7 @@ rule cluster_networks: expand( resources("networks/elec_s{simpl}_{clusters}.nc"), **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), @@ -33,7 +33,7 @@ rule extra_components_networks: expand( resources("networks/elec_s{simpl}_{clusters}_ec.nc"), **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), @@ -42,7 +42,7 @@ rule prepare_elec_networks: expand( resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), @@ -52,7 +52,7 @@ rule prepare_sector_networks: RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), @@ -61,7 +61,7 @@ rule solve_elec_networks: expand( RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), @@ -71,7 +71,7 @@ rule solve_sector_networks: RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), @@ -81,7 +81,7 @@ rule solve_sector_networks_perfect: RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), @@ -91,12 +91,12 @@ rule validate_elec_networks: RESULTS + "figures/.statistics_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), expand( RESULTS + "figures/.validation_{kind}_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", **config["scenario"], run=config["run"]["name"], - kind=["production", "prices", "cross_border"] + kind=["production", "prices", "cross_border"], ), diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 19dc34be..7e269688 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -162,7 +162,7 @@ rule make_summary: params: foresight=config_provider("foresight"), costs=config_provider("costs"), - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider scenario=config_provider("scenario"), RDIR=RDIR, input: @@ -174,7 +174,7 @@ rule make_summary: RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), costs=( "data/costs_{}.csv".format(config["costs"]["year"]) @@ -189,7 +189,7 @@ rule make_summary: RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), h2_plot=expand( ( @@ -199,7 +199,7 @@ rule make_summary: else [] ), **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), ch4_plot=expand( ( @@ -209,7 +209,7 @@ rule make_summary: else [] ), **config["scenario"], - run=config["run"]["name"] + run=config["run"]["name"], ), output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index fac58456..7035f1c1 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -21,7 +21,9 @@ rule add_existing_baseyear: ), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), - existing_heating_distribution=resources("existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), + existing_heating_distribution=resources( + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", existing_offwind="data/existing_infrastructure/offwind_capacity_IRENA.csv", @@ -54,7 +56,7 @@ rule add_brownfield: "sector", "H2_retrofit_capacity_per_CH4" ), threshold_capacity=config_provider("existing_capacities", " threshold_capacity"), - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider carriers=config_provider("electricity", "renewable_carriers"), input: **{ diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 44b83e99..bd00a258 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -133,7 +133,7 @@ import numpy as np import pandas as pd import pypsa import seaborn as sns -from _helpers import configure_logging, update_p_nom_max, set_scenario_config +from _helpers import configure_logging, set_scenario_config, update_p_nom_max from add_electricity import load_costs from packaging.version import Version, parse from pypsa.clustering.spatial import ( diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 06aea9ec..b1161c19 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -18,7 +18,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import update_config_with_sector_opts, set_scenario_config +from _helpers import set_scenario_config, update_config_with_sector_opts from add_electricity import calculate_annuity, sanitize_carriers, sanitize_locations from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement diff --git a/scripts/retrieve_sector_databundle.py b/scripts/retrieve_sector_databundle.py index defc806c..f95986b4 100644 --- a/scripts/retrieve_sector_databundle.py +++ b/scripts/retrieve_sector_databundle.py @@ -13,8 +13,8 @@ from pathlib import Path from _helpers import ( configure_logging, progress_retrieve, - validate_checksum, set_scenario_config, + validate_checksum, ) logger = logging.getLogger(__name__) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 5ca0ec82..b828bbd2 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -40,8 +40,8 @@ from _benchmark import memory_logger from _helpers import ( configure_logging, get_opt, - update_config_with_sector_opts, set_scenario_config, + update_config_with_sector_opts, ) from pypsa.descriptors import get_activity_mask from pypsa.descriptors import get_switchable_as_dense as get_as_dense From a9dad3f34ece29af49481738b1d0b6ddd43d67d1 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 10 Feb 2024 18:09:23 +0100 Subject: [PATCH 270/591] add new resources(), logs(), benchmarks(), config_providers() --- Snakefile | 2 +- rules/build_electricity.smk | 63 +++++++++++++------------- rules/build_sector.smk | 90 ++++++++++++++++--------------------- rules/collect.smk | 6 --- rules/common.smk | 10 ++--- rules/postprocess.smk | 68 ++++++++++------------------ rules/retrieve.smk | 4 +- rules/solve_electricity.smk | 18 +++----- rules/solve_myopic.smk | 37 +++++---------- rules/solve_overnight.smk | 5 +-- rules/solve_perfect.smk | 84 +++++++++++++++------------------- rules/validate.smk | 14 +++--- 12 files changed, 163 insertions(+), 238 deletions(-) diff --git a/Snakefile b/Snakefile index e0949ed9..7df61162 100644 --- a/Snakefile +++ b/Snakefile @@ -91,7 +91,7 @@ if config["foresight"] == "perfect": rule all: input: - RESULTS + "graphs/costs.pdf", + expand(RESULTS + "graphs/costs.pdf", run=config["run"]["name"]), default_target: True diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 4c6650bc..951d3331 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -20,7 +20,7 @@ if config["enable"].get("prepare_links_p_nom", False): rule build_electricity_demand: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, countries=config_provider("countries"), load=config_provider("load"), input: @@ -62,7 +62,7 @@ rule build_powerplants: rule base_network: params: countries=config_provider("countries"), - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, lines=config_provider("lines"), links=config_provider("links"), transformers=config_provider("transformers"), @@ -145,7 +145,7 @@ if config["enable"].get("build_cutout", False): rule build_cutout: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, cutouts=config_provider("atlite", "cutouts"), input: regions_onshore=resources("regions_onshore.geojson"), @@ -170,7 +170,7 @@ if config["enable"].get("build_natura_raster", False): rule build_natura_raster: input: natura=ancient("data/bundle/natura/Natura2000_end2015.shp"), - cutouts=expand("cutouts/" + CDIR + "{cutouts}.nc", **config["atlite"]), + cutouts=expand("cutouts/" + CDIR + "{cutouts}.nc", **config_provider("atlite")), output: resources("natura.tiff"), resources: @@ -189,8 +189,8 @@ rule build_ship_raster: cutouts=expand( "cutouts/" + CDIR + "{cutout}.nc", cutout=[ - config["renewable"][k]["cutout"] - for k in config["electricity"]["renewable_carriers"] + config_provider("renewable", k, "cutout") + for k in config_provider("electricity", "renewable_carriers") ], ), output: @@ -214,30 +214,30 @@ rule determine_availability_matrix_MD_UA: wdpa_marine="data/WDPA_WDOECM_marine.gpkg", gebco=lambda w: ( "data/bundle/GEBCO_2014_2D.nc" - if "max_depth" in config["renewable"][w.technology].keys() + if config_provider("renewable", w.technology)(w).get("max_depth") else [] ), ship_density=lambda w: ( - RESOURCES + "shipdensity_raster.tif" - if "ship_threshold" in config["renewable"][w.technology].keys() + resources("shipdensity_raster.tif") + if "ship_threshold" in config_provider("renewable", w.technology)(w).keys() else [] ), - country_shapes=RESOURCES + "country_shapes.geojson", - offshore_shapes=RESOURCES + "offshore_shapes.geojson", + country_shapes=resources("country_shapes.geojson"), + offshore_shapes=resources("offshore_shapes.geojson"), regions=lambda w: ( - RESOURCES + "regions_onshore.geojson" + resources("regions_onshore.geojson") if w.technology in ("onwind", "solar") - else RESOURCES + "regions_offshore.geojson" + else resources("regions_offshore.geojson") ), cutout=lambda w: "cutouts/" + CDIR - + config["renewable"][w.technology]["cutout"] + + config_provider("renewable", w.technology, "cutout")(w) + ".nc", output: - availability_matrix=RESOURCES + "availability_matrix_MD-UA_{technology}.nc", - availability_map=RESOURCES + "availability_matrix_MD-UA_{technology}.png", + availability_matrix=resources("availability_matrix_MD-UA_{technology}.nc"), + availability_map=resources("availability_matrix_MD-UA_{technology}.png"), log: - LOGS + "determine_availability_matrix_MD_UA_{technology}.log", + logs("determine_availability_matrix_MD_UA_{technology}.log"), threads: ATLITE_NPROCESSES resources: mem_mb=ATLITE_NPROCESSES * 5000, @@ -250,8 +250,7 @@ rule determine_availability_matrix_MD_UA: # Optional input when having Ukraine (UA) or Moldova (MD) in the countries list if {"UA", "MD"}.intersection(set(config["countries"])): opt = { - "availability_matrix_MD_UA": RESOURCES - + "availability_matrix_MD-UA_{technology}.nc" + "availability_matrix_MD_UA": resources("availability_matrix_MD-UA_{technology}.nc") } else: opt = {} @@ -259,7 +258,7 @@ else: rule build_renewable_profiles: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, renewable=config_provider("renewable"), input: **opt, @@ -272,7 +271,7 @@ rule build_renewable_profiles: ), luisa=lambda w: ( "data/LUISA_basemap_020321_50m.tif" - if config["renewable"][w.technology].get("luisa") + if config_provider("renewable", w.technology, "luisa")(w) else [] ), gebco=ancient( @@ -340,7 +339,7 @@ rule build_hydro_profile: input: country_shapes=resources("country_shapes.geojson"), eia_hydro_generation="data/eia_hydro_annual_generation.csv", - cutout=f"cutouts/" + CDIR + config["renewable"]["hydro"]["cutout"] + ".nc", + cutout=f"cutouts/" + CDIR + config_provider("renewable", "hydro", "cutout") + ".nc", output: resources("profile_hydro.nc"), log: @@ -357,12 +356,12 @@ if config["lines"]["dynamic_line_rating"]["activate"]: rule build_line_rating: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, input: base_network=resources("networks/base.nc"), cutout="cutouts/" + CDIR - + config["lines"]["dynamic_line_rating"]["cutout"] + + config_provider("lines", "dynamic_line_rating", "cutout") + ".nc", output: output=resources("networks/line_rating.nc"), @@ -391,19 +390,19 @@ rule add_electricity: input: **{ f"profile_{tech}": resources(f"profile_{tech}.nc") - for tech in config["electricity"]["renewable_carriers"] + for tech in config_provider("electricity", "renewable_carriers") }, **{ f"conventional_{carrier}_{attr}": fn for carrier, d in config.get("conventional", {None: {}}).items() - if carrier in config["electricity"]["conventional_carriers"] + if carrier in config_provider("electricity", "conventional_carriers") for attr, fn in d.items() if str(fn).startswith("data/") }, base_network=resources("networks/base.nc"), line_rating=( resources("networks/line_rating.nc") - if config["lines"]["dynamic_line_rating"]["activate"] + if config_provider("lines", "dynamic_line_rating", "activate") else resources("networks/base.nc") ), tech_costs=COSTS, @@ -414,7 +413,7 @@ rule add_electricity: unit_commitment="data/unit_commitment.csv", fuel_price=( resources("monthly_fuel_price.csv") - if config["conventional"]["dynamic_fuel_price"] + if config_provider("conventional", "dynamic_fuel_price") else [] ), load=resources("load.csv"), @@ -493,7 +492,7 @@ rule cluster_network: busmap=ancient(resources("busmap_elec_s{simpl}.csv")), custom_busmap=( "data/custom_busmap_elec_s{simpl}_{clusters}.csv" - if config["enable"].get("custom_busmap", False) + if config_provider("enable", "custom_busmap", default=False) else [] ), tech_costs=COSTS, @@ -542,10 +541,10 @@ rule add_extra_components: rule prepare_network: params: snapshots={ - "resolution": config["snapshots"].get("resolution", False), - "segmentation": config["snapshots"].get("segmentation", False), + "resolution": config_provider("snapshots", "resolution", default=False), + "segmentation": config_provider("snapshots", "segmentation", default=False), }, - # TODO: use config provider + links=config_provider("links"), lines=config_provider("lines"), co2base=config_provider("electricity", "co2base"), diff --git a/rules/build_sector.smk b/rules/build_sector.smk index aea16519..a26efaf4 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -7,7 +7,7 @@ rule build_population_layouts: input: nuts3_shapes=resources("nuts3_shapes.geojson"), urban_percent="data/urban_percent.csv", - cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", + cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", output: pop_layout_total=resources("pop_layout_total.nc"), pop_layout_urban=resources("pop_layout_urban.nc"), @@ -31,7 +31,7 @@ rule build_clustered_population_layouts: pop_layout_urban=resources("pop_layout_urban.nc"), pop_layout_rural=resources("pop_layout_rural.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", + cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", output: clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), log: @@ -52,7 +52,7 @@ rule build_simplified_population_layouts: pop_layout_urban=resources("pop_layout_urban.nc"), pop_layout_rural=resources("pop_layout_rural.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), - cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", + cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", output: clustered_pop_layout=resources("pop_layout_elec_s{simpl}.csv"), resources: @@ -126,11 +126,11 @@ rule cluster_gas_network: rule build_daily_heat_demand: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", + cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", output: heat_demand=resources("daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), resources: @@ -148,19 +148,19 @@ rule build_daily_heat_demand: rule build_hourly_heat_demand: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, input: heat_profile="data/heat_load_profile_BDEW.csv", - heat_demand=RESOURCES + "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc", + heat_demand=resources("daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), output: - heat_demand=RESOURCES + "hourly_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc", + heat_demand=resources("hourly_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=2000, threads: 8 log: - LOGS + "build_hourly_heat_demand_{scope}_{simpl}_{clusters}.loc", + logs("build_hourly_heat_demand_{scope}_{simpl}_{clusters}.loc"), benchmark: - BENCHMARKS + "build_hourly_heat_demand/{scope}_s{simpl}_{clusters}" + benchmarks("build_hourly_heat_demand/{scope}_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -169,11 +169,11 @@ rule build_hourly_heat_demand: rule build_temperature_profiles: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", + cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", output: temp_soil=resources("temp_soil_{scope}_elec_s{simpl}_{clusters}.nc"), temp_air=resources("temp_air_{scope}_elec_s{simpl}_{clusters}.nc"), @@ -221,12 +221,12 @@ rule build_cop_profiles: rule build_solar_thermal_profiles: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO use config_provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, # TODO use config_provider solar_thermal=config_provider("solar_thermal"), input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", + cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", output: solar_thermal=resources("solar_thermal_{scope}_elec_s{simpl}_{clusters}.nc"), resources: @@ -711,7 +711,7 @@ rule build_shipping_demand: rule build_transport_demand: params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, sector=config_provider("sector"), input: clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), @@ -740,18 +740,17 @@ rule build_transport_demand: rule build_district_heat_share: params: - sector=config["sector"], + sector=config_provider("sector"), input: - district_heat_share=RESOURCES + "district_heat_share.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", + district_heat_share=resources("district_heat_share.csv"), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), output: - district_heat_share=RESOURCES - + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + district_heat_share=resources("district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), threads: 1 resources: mem_mb=1000, log: - LOGS + "build_district_heat_share_s{simpl}_{clusters}_{planning_horizons}.log", + logs("build_district_heat_share_s{simpl}_{clusters}_{planning_horizons}.log"), conda: "../envs/environment.yaml" script: @@ -760,32 +759,25 @@ rule build_district_heat_share: rule build_existing_heating_distribution: params: - baseyear=config["scenario"]["planning_horizons"][0], - sector=config["sector"], - existing_capacities=config["existing_capacities"], + baseyear=config_provider("scenario", "planning_horizons", 0), + sector=config_provider("sector"), + existing_capacities=config_provider("existing_capacities"), input: existing_heating="data/existing_infrastructure/existing_heating_raw.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", - clustered_pop_energy_layout=RESOURCES - + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv", - district_heat_share=RESOURCES - + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), + clustered_pop_energy_layout=resources("pop_weighted_energy_totals_s{simpl}_{clusters}.csv"), + district_heat_share=resources("district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), output: - existing_heating_distribution=RESOURCES - + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + existing_heating_distribution=resources("existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), wildcard_constraints: - planning_horizons=config["scenario"]["planning_horizons"][0], #only applies to baseyear + planning_horizons=config_provider("scenario", "planning_horizons", 0), #only applies to baseyear threads: 1 resources: mem_mb=2000, log: - LOGS - + "build_existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.log", + logs("build_existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.log"), benchmark: - ( - BENCHMARKS - + "build_existing_heating_distribution/elec_s{simpl}_{clusters}_{planning_horizons}" - ) + benchmarks("build_existing_heating_distribution/elec_s{simpl}_{clusters}_{planning_horizons}") conda: "../envs/environment.yaml" script: @@ -831,16 +823,16 @@ rule prepare_sector_network: biomass_potentials=( resources( "biomass_potentials_s{simpl}_{clusters}_" - + "{}.csv".format(config["biomass"]["year"]) + + "{}.csv".format(config_provider("biomass", "year")) ) - if config["foresight"] == "overnight" + if config_provider("foresight") == "overnight" else resources( "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv" ) ), costs=( - "data/costs_{}.csv".format(config["costs"]["year"]) - if config["foresight"] == "overnight" + "data/costs_{}.csv".format(config_provider("costs", "year")) + if config_provider("foresight") == "overnight" else "data/costs_{planning_horizons}.csv" ), profile_offwind_ac=resources("profile_offwind-ac.nc"), @@ -873,17 +865,17 @@ rule prepare_sector_network: cop_air_urban=resources("cop_air_urban_elec_s{simpl}_{clusters}.nc"), solar_thermal_total=( resources("solar_thermal_total_elec_s{simpl}_{clusters}.nc") - if config["sector"]["solar_thermal"] + if config_provider("sector", "solar_thermal") else [] ), solar_thermal_urban=( resources("solar_thermal_urban_elec_s{simpl}_{clusters}.nc") - if config["sector"]["solar_thermal"] + if config_provider("sector", "solar_thermal") else [] ), solar_thermal_rural=( resources("solar_thermal_rural_elec_s{simpl}_{clusters}.nc") - if config["sector"]["solar_thermal"] + if config_provider("sector", "solar_thermal") else [] ), output: @@ -893,13 +885,9 @@ rule prepare_sector_network: resources: mem_mb=2000, log: - LOGS - + "prepare_sector_network_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + logs("prepare_sector_network_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), benchmark: - ( - BENCHMARKS - + "prepare_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) + benchmarks("prepare_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") conda: "../envs/environment.yaml" script: diff --git a/rules/collect.smk b/rules/collect.smk index 8a451d7a..9be12f25 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -13,12 +13,6 @@ localrules: solve_sector_networks, -rule all: - input: - expand(RESULTS + "graphs/costs.pdf", run=config["run"]["name"]), - default_target: True - - rule cluster_networks: input: expand( diff --git a/rules/common.smk b/rules/common.smk index b6c0f734..af991be7 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -78,8 +78,8 @@ def config_provider(*keys, default=None): def solver_threads(w): - solver_options = config["solving"]["solver_options"] - option_set = config["solving"]["solver"]["options"] + solver_options = config_provider("solving", "solver_options") + option_set = config_provider("solving", "solver", "options") threads = solver_options[option_set].get("threads", 4) return threads @@ -105,7 +105,7 @@ def memory(w): def input_custom_extra_functionality(w): - path = config["solving"]["options"].get("custom_extra_functionality", False) + path = config_provider("solving", "options", "custom_extra_functionality", default=False) if path: return os.path.join(os.path.dirname(workflow.snakefile), path) return [] @@ -129,12 +129,12 @@ def has_internet_access(url="www.zenodo.org") -> bool: def input_eurostat(w): # 2016 includes BA, 2017 does not - report_year = config["energy"]["eurostat_report_year"] + report_year = config_provider("energy", "eurostat_report_year") return f"data/bundle-sector/eurostat-energy_balances-june_{report_year}_edition" def solved_previous_horizon(wildcards): - planning_horizons = config["scenario"]["planning_horizons"] + planning_horizons = config_provider("scenario", "planning_horizons") i = planning_horizons.index(int(wildcards.planning_horizons)) planning_horizon_p = str(planning_horizons[i - 1]) return ( diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 7e269688..98399cde 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -13,16 +13,15 @@ if config_provider("foresight") != "perfect": params: plotting=config_provider("plotting"), input: - network=RESOURCES + "networks/elec_s{simpl}_{clusters}.nc", - regions_onshore=RESOURCES - + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + network=resources("networks/elec_s{simpl}_{clusters}.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: map=RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", threads: 1 resources: mem_mb=4000, benchmark: - BENCHMARKS + "plot_power_network_clustered/elec_s{simpl}_{clusters}" + benchmarks("plot_power_network_clustered/elec_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -34,7 +33,7 @@ if config_provider("foresight") != "perfect": input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: map=RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", @@ -42,15 +41,9 @@ if config_provider("foresight") != "perfect": resources: mem_mb=10000, log: - ( - LOGS - + "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ), + logs("plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log") benchmark: - ( - BENCHMARKS - + "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) + benchmarks("plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") conda: "../envs/environment.yaml" script: @@ -63,7 +56,7 @@ if config_provider("foresight") != "perfect": input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: map=RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", @@ -71,15 +64,9 @@ if config_provider("foresight") != "perfect": resources: mem_mb=10000, log: - ( - LOGS - + "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ), + logs("plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), benchmark: - ( - BENCHMARKS - + "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) + benchmarks("plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") conda: "../envs/environment.yaml" script: @@ -91,7 +78,7 @@ if config_provider("foresight") != "perfect": input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: map=RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", @@ -99,15 +86,9 @@ if config_provider("foresight") != "perfect": resources: mem_mb=10000, log: - ( - LOGS - + "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ), + logs("plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), benchmark: - ( - BENCHMARKS - + "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) + benchmarks("plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") conda: "../envs/environment.yaml" script: @@ -122,7 +103,7 @@ if config_provider("foresight") == "perfect": input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", - regions=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson", + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: **{ f"map_{year}": RESULTS @@ -134,8 +115,7 @@ if config_provider("foresight") == "perfect": resources: mem_mb=10000, benchmark: - BENCHMARKS - +"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years_benchmark" + benchmarks("postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years_benchmark") conda: "../envs/environment.yaml" script: @@ -151,7 +131,7 @@ rule copy_config: resources: mem_mb=1000, benchmark: - BENCHMARKS + "copy_config" + benchmarks("copy_config") conda: "../envs/environment.yaml" script: @@ -162,7 +142,7 @@ rule make_summary: params: foresight=config_provider("foresight"), costs=config_provider("costs"), - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, scenario=config_provider("scenario"), RDIR=RDIR, input: @@ -177,9 +157,9 @@ rule make_summary: run=config["run"]["name"], ), costs=( - "data/costs_{}.csv".format(config["costs"]["year"]) + "data/costs_{}.csv".format(config_provider("costs", "year")) if config_provider("foresight") == "overnight" - else "data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]) + else "data/costs_{}.csv".format(config_provider("scenario", "planning_horizons", 0)) ), ac_plot=expand( RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", @@ -195,7 +175,7 @@ rule make_summary: ( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf" - if config["sector"]["H2_network"] + if config_provider("sector", "H2_network") else [] ), **config["scenario"], @@ -205,7 +185,7 @@ rule make_summary: ( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf" - if config["sector"]["gas_network"] + if config_provider("sector", "gas_network") else [] ), **config["scenario"], @@ -231,9 +211,9 @@ rule make_summary: resources: mem_mb=10000, log: - LOGS + "make_summary.log", + logs("make_summary.log"), benchmark: - BENCHMARKS + "make_summary" + benchmarks("make_summary") conda: "../envs/environment.yaml" script: @@ -263,9 +243,9 @@ rule plot_summary: resources: mem_mb=10000, log: - LOGS + "plot_summary.log", + logs("plot_summary.log"), benchmark: - BENCHMARKS + "plot_summary" + benchmarks("plot_summary") conda: "../envs/environment.yaml" script: diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 46741830..a0647e57 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -50,7 +50,7 @@ if config["enable"].get("retrieve_irena"): onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", solar="data/existing_infrastructure/solar_capacity_IRENA.csv", log: - LOGS + "retrieve_irena.log", + logs("retrieve_irena.log"), resources: mem_mb=1000, retries: 2 @@ -86,7 +86,7 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_cost_data", T input: HTTP.remote( "raw.githubusercontent.com/PyPSA/technology-data/{}/outputs/".format( - config["costs"]["version"] + config_provider("costs", "version") ) + "costs_{year}.csv", keep_local=True, diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index fc8e8cea..4ff94bf2 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -19,12 +19,11 @@ rule solve_network: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", log: solver=normpath( - LOGS + "solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log" + logs("solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log") ), - python=LOGS - + "solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", + python=logs("solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log"), benchmark: - BENCHMARKS + "solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" + benchmarks("solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}") threads: solver_threads resources: mem_mb=memory, @@ -46,16 +45,11 @@ rule solve_operations_network: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc", log: solver=normpath( - LOGS - + "solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log" + logs("solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log") ), - python=LOGS - + "solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log", + python=logs("solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log"), benchmark: - ( - BENCHMARKS - + "solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" - ) + benchmarks("solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}") threads: 4 resources: mem_mb=(lambda w: 10000 + 372 * int(w.clusters)), diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 7035f1c1..260837b7 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -36,13 +36,9 @@ rule add_existing_baseyear: resources: mem_mb=2000, log: - LOGS - + "add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + logs("add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), benchmark: - ( - BENCHMARKS - + "add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) + benchmarks("add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") conda: "../envs/environment.yaml" script: @@ -56,16 +52,16 @@ rule add_brownfield: "sector", "H2_retrofit_capacity_per_CH4" ), threshold_capacity=config_provider("existing_capacities", " threshold_capacity"), - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, # TODO: use config_provider + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, carriers=config_provider("electricity", "renewable_carriers"), input: **{ - f"profile_{tech}": RESOURCES + f"profile_{tech}.nc" - for tech in config["electricity"]["renewable_carriers"] + f"profile_{tech}": resources(f"profile_{tech}.nc") + for tech in config_provider("electricity", "renewable_carriers") if tech != "hydro" }, - simplify_busmap=RESOURCES + "busmap_elec_s{simpl}.csv", - cluster_busmap=RESOURCES + "busmap_elec_s{simpl}_{clusters}.csv", + simplify_busmap=resources("busmap_elec_s{simpl}.csv"), + cluster_busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", network_p=solved_previous_horizon, #solved network at previous time step @@ -79,13 +75,9 @@ rule add_brownfield: resources: mem_mb=10000, log: - LOGS - + "add_brownfield_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + logs("add_brownfield_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), benchmark: - ( - BENCHMARKS - + "add_brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) + benchmarks("add_brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") conda: "../envs/environment.yaml" script: @@ -115,19 +107,14 @@ rule solve_sector_network_myopic: shadow: "shallow" log: - solver=LOGS - + "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", + solver=logs("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: solver_threads resources: mem_mb=config_provider("solving", "mem"), walltime=config_provider("solving", "walltime", default="12:00:00"), benchmark: - ( - BENCHMARKS - + "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) + benchmarks("solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") conda: "../envs/environment.yaml" script: diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index 76621012..7811efe3 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -33,10 +33,7 @@ rule solve_sector_network: mem_mb=config_provider("solving", "mem"), walltime=config_provider("solving", "walltime", default="12:00:00"), benchmark: - ( - BENCHMARKS - + "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) + benchmarks("solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") conda: "../envs/environment.yaml" script: diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 9e164a16..85f87d9b 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -3,22 +3,21 @@ # SPDX-License-Identifier: MIT rule add_existing_baseyear: params: - baseyear=config["scenario"]["planning_horizons"][0], - sector=config["sector"], - existing_capacities=config["existing_capacities"], - costs=config["costs"], + baseyear=config_provider("scenario", "planning_horizons", 0), + sector=config_provider("sector"), + existing_capacities=config_provider("existing_capacities"), + costs=config_provider("costs"), input: network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - powerplants=RESOURCES + "powerplants.csv", - busmap_s=RESOURCES + "busmap_elec_s{simpl}.csv", - busmap=RESOURCES + "busmap_elec_s{simpl}_{clusters}.csv", - clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv", - costs="data/costs_{}.csv".format(config["scenario"]["planning_horizons"][0]), - cop_soil_total=RESOURCES + "cop_soil_total_elec_s{simpl}_{clusters}.nc", - cop_air_total=RESOURCES + "cop_air_total_elec_s{simpl}_{clusters}.nc", - existing_heating_distribution=RESOURCES - + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv", + powerplants=resources("powerplants.csv"), + busmap_s=resources("busmap_elec_s{simpl}.csv"), + busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), + costs="data/costs_{}.csv".format(config_provider("scenario", "planning_horizons", 0)), + cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), + cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), + existing_heating_distribution=resources("existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), existing_heating="data/existing_infrastructure/existing_heating_raw.csv", existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", @@ -27,18 +26,14 @@ rule add_existing_baseyear: RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", wildcard_constraints: - planning_horizons=config["scenario"]["planning_horizons"][0], #only applies to baseyear + planning_horizons=config_provider("scenario", "planning_horizons", 0), #only applies to baseyear threads: 1 resources: mem_mb=2000, log: - LOGS - + "add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + logs("add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), benchmark: - ( - BENCHMARKS - + "add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" - ) + benchmarks("add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") conda: "../envs/environment.yaml" script: @@ -51,13 +46,13 @@ rule prepare_perfect_foresight: f"network_{year}": RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_" + f"{year}.nc" - for year in config["scenario"]["planning_horizons"][1:] + for year in config_provider("scenario", "planning_horizons")[1:] }, brownfield_network=lambda w: ( RESULTS + "prenetworks-brownfield/" + "elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_" - + "{}.nc".format(str(config["scenario"]["planning_horizons"][0])) + + "{}.nc".format(str(config_provider("scenario", "planning_horizons", 0))) ), output: RESULTS @@ -66,13 +61,9 @@ rule prepare_perfect_foresight: resources: mem_mb=10000, log: - LOGS - + "prepare_perfect_foresight{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}.log", + logs("prepare_perfect_foresight{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}.log"), benchmark: - ( - BENCHMARKS - + "prepare_perfect_foresight{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}" - ) + benchmarks("prepare_perfect_foresight{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}") conda: "../envs/environment.yaml" script: @@ -81,13 +72,11 @@ rule prepare_perfect_foresight: rule solve_sector_network_perfect: params: - solving=config["solving"], - foresight=config["foresight"], - sector=config["sector"], - planning_horizons=config["scenario"]["planning_horizons"], - co2_sequestration_potential=config["sector"].get( - "co2_sequestration_potential", 200 - ), + solving=config_provider("solving"), + foresight=config_provider("foresight"), + sector=config_provider("sector"), + planning_horizons=config_provider("scenario", "planning_horizons"), + co2_sequestration_potential=config_provider("sector", "co2_sequestration_potential", 200), custom_extra_functionality=input_custom_extra_functionality, input: network=RESULTS @@ -99,7 +88,7 @@ rule solve_sector_network_perfect: + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", threads: solver_threads resources: - mem_mb=config["solving"]["mem"], + mem_mb=config_provider("solving", "mem"), shadow: "shallow" log: @@ -110,10 +99,7 @@ rule solve_sector_network_perfect: memory=RESULTS + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years_memory.log", benchmark: - ( - BENCHMARKS - + "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years}" - ) + benchmarks("solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years}") conda: "../envs/environment.yaml" script: @@ -124,13 +110,13 @@ rule make_summary_perfect: input: **{ f"networks_{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}": RESULTS - + f"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc" - for simpl in config["scenario"]["simpl"] - for clusters in config["scenario"]["clusters"] - for opts in config["scenario"]["opts"] - for sector_opts in config["scenario"]["sector_opts"] - for ll in config["scenario"]["ll"] - }, + + f"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc" + for simpl in config_provider("scenario", "simpl") + for clusters in config_provider("scenario", "clusters") + for opts in config_provider("scenario", "opts") + for sector_opts in config_provider("scenario", "sector_opts") + for ll in config_provider("scenario", "ll") + }, costs="data/costs_2020.csv", output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", @@ -153,9 +139,9 @@ rule make_summary_perfect: resources: mem_mb=10000, log: - LOGS + "make_summary_perfect.log", + logs("make_summary_perfect.log"), benchmark: - (BENCHMARKS + "make_summary_perfect") + benchmarks("make_summary_perfect") conda: "../envs/environment.yaml" script: diff --git a/rules/validate.smk b/rules/validate.smk index fefb6ba6..f8ebea5d 100644 --- a/rules/validate.smk +++ b/rules/validate.smk @@ -17,8 +17,8 @@ rule build_electricity_production: The data is used for validation of the optimization results. """ params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, - countries=config["countries"], + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + countries=config_provider("countries"), output: resources("historical_electricity_production.csv"), log: @@ -35,8 +35,8 @@ rule build_cross_border_flows: The data is used for validation of the optimization results. """ params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, - countries=config["countries"], + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + countries=config_provider("countries"), input: network=resources("networks/base.nc"), output: @@ -55,8 +55,8 @@ rule build_electricity_prices: The data is used for validation of the optimization results. """ params: - snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]}, - countries=config["countries"], + snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + countries=config_provider("countries"), output: resources("historical_electricity_prices.csv"), log: @@ -85,7 +85,7 @@ rule plot_validation_electricity_production: rule plot_validation_cross_border_flows: params: - countries=config["countries"], + countries=config_provider("countries"), input: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", cross_border_flows=resources("historical_cross_border_flows.csv"), From 4ff06046fc72b316a7fbc01ad8295d2546db322f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 10 Feb 2024 17:09:46 +0000 Subject: [PATCH 271/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 40 +++++++++++++++++++++------- rules/build_sector.smk | 52 +++++++++++++++++++++++++++---------- rules/common.smk | 4 ++- rules/postprocess.smk | 40 +++++++++++++++++++++------- rules/solve_electricity.smk | 8 ++++-- rules/solve_myopic.smk | 32 +++++++++++++++++------ rules/solve_overnight.smk | 4 ++- rules/solve_perfect.smk | 46 +++++++++++++++++++++----------- rules/validate.smk | 12 ++++++--- 9 files changed, 175 insertions(+), 63 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 951d3331..bdae24d1 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -20,7 +20,9 @@ if config["enable"].get("prepare_links_p_nom", False): rule build_electricity_demand: params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, countries=config_provider("countries"), load=config_provider("load"), input: @@ -62,7 +64,9 @@ rule build_powerplants: rule base_network: params: countries=config_provider("countries"), - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, lines=config_provider("lines"), links=config_provider("links"), transformers=config_provider("transformers"), @@ -145,7 +149,10 @@ if config["enable"].get("build_cutout", False): rule build_cutout: params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) + for k in ["start", "end", "inclusive"] + }, cutouts=config_provider("atlite", "cutouts"), input: regions_onshore=resources("regions_onshore.geojson"), @@ -170,7 +177,9 @@ if config["enable"].get("build_natura_raster", False): rule build_natura_raster: input: natura=ancient("data/bundle/natura/Natura2000_end2015.shp"), - cutouts=expand("cutouts/" + CDIR + "{cutouts}.nc", **config_provider("atlite")), + cutouts=expand( + "cutouts/" + CDIR + "{cutouts}.nc", **config_provider("atlite") + ), output: resources("natura.tiff"), resources: @@ -250,7 +259,9 @@ rule determine_availability_matrix_MD_UA: # Optional input when having Ukraine (UA) or Moldova (MD) in the countries list if {"UA", "MD"}.intersection(set(config["countries"])): opt = { - "availability_matrix_MD_UA": resources("availability_matrix_MD-UA_{technology}.nc") + "availability_matrix_MD_UA": resources( + "availability_matrix_MD-UA_{technology}.nc" + ) } else: opt = {} @@ -258,7 +269,9 @@ else: rule build_renewable_profiles: params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, renewable=config_provider("renewable"), input: **opt, @@ -339,7 +352,10 @@ rule build_hydro_profile: input: country_shapes=resources("country_shapes.geojson"), eia_hydro_generation="data/eia_hydro_annual_generation.csv", - cutout=f"cutouts/" + CDIR + config_provider("renewable", "hydro", "cutout") + ".nc", + cutout=f"cutouts/" + + CDIR + + config_provider("renewable", "hydro", "cutout") + + ".nc", output: resources("profile_hydro.nc"), log: @@ -356,7 +372,10 @@ if config["lines"]["dynamic_line_rating"]["activate"]: rule build_line_rating: params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) + for k in ["start", "end", "inclusive"] + }, input: base_network=resources("networks/base.nc"), cutout="cutouts/" @@ -542,9 +561,10 @@ rule prepare_network: params: snapshots={ "resolution": config_provider("snapshots", "resolution", default=False), - "segmentation": config_provider("snapshots", "segmentation", default=False), + "segmentation": config_provider( + "snapshots", "segmentation", default=False + ), }, - links=config_provider("links"), lines=config_provider("lines"), co2base=config_provider("electricity", "co2base"), diff --git a/rules/build_sector.smk b/rules/build_sector.smk index a26efaf4..268113f9 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -126,7 +126,9 @@ rule cluster_gas_network: rule build_daily_heat_demand: params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), @@ -148,7 +150,9 @@ rule build_daily_heat_demand: rule build_hourly_heat_demand: params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, input: heat_profile="data/heat_load_profile_BDEW.csv", heat_demand=resources("daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), @@ -169,7 +173,9 @@ rule build_hourly_heat_demand: rule build_temperature_profiles: params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), @@ -221,7 +227,9 @@ rule build_cop_profiles: rule build_solar_thermal_profiles: params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, # TODO use config_provider + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, # TODO use config_provider solar_thermal=config_provider("solar_thermal"), input: pop_layout=resources("pop_layout_{scope}.nc"), @@ -711,7 +719,9 @@ rule build_shipping_demand: rule build_transport_demand: params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, sector=config_provider("sector"), input: clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), @@ -745,7 +755,9 @@ rule build_district_heat_share: district_heat_share=resources("district_heat_share.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), output: - district_heat_share=resources("district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), + district_heat_share=resources( + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), threads: 1 resources: mem_mb=1000, @@ -765,19 +777,29 @@ rule build_existing_heating_distribution: input: existing_heating="data/existing_infrastructure/existing_heating_raw.csv", clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - clustered_pop_energy_layout=resources("pop_weighted_energy_totals_s{simpl}_{clusters}.csv"), - district_heat_share=resources("district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), + clustered_pop_energy_layout=resources( + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" + ), + district_heat_share=resources( + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), output: - existing_heating_distribution=resources("existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), + existing_heating_distribution=resources( + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), wildcard_constraints: planning_horizons=config_provider("scenario", "planning_horizons", 0), #only applies to baseyear threads: 1 resources: mem_mb=2000, log: - logs("build_existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.log"), + logs( + "build_existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.log" + ), benchmark: - benchmarks("build_existing_heating_distribution/elec_s{simpl}_{clusters}_{planning_horizons}") + benchmarks( + "build_existing_heating_distribution/elec_s{simpl}_{clusters}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: @@ -885,9 +907,13 @@ rule prepare_sector_network: resources: mem_mb=2000, log: - logs("prepare_sector_network_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), + logs( + "prepare_sector_network_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ), benchmark: - benchmarks("prepare_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") + benchmarks( + "prepare_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: diff --git a/rules/common.smk b/rules/common.smk index af991be7..bf5e0894 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -105,7 +105,9 @@ def memory(w): def input_custom_extra_functionality(w): - path = config_provider("solving", "options", "custom_extra_functionality", default=False) + path = config_provider( + "solving", "options", "custom_extra_functionality", default=False + ) if path: return os.path.join(os.path.dirname(workflow.snakefile), path) return [] diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 98399cde..cf0ef6cd 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -14,7 +14,9 @@ if config_provider("foresight") != "perfect": plotting=config_provider("plotting"), input: network=resources("networks/elec_s{simpl}_{clusters}.nc"), - regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec_s{simpl}_{clusters}.geojson" + ), output: map=RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", threads: 1 @@ -41,9 +43,13 @@ if config_provider("foresight") != "perfect": resources: mem_mb=10000, log: - logs("plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log") + logs( + "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ), benchmark: - benchmarks("plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") + benchmarks( + "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: @@ -64,9 +70,13 @@ if config_provider("foresight") != "perfect": resources: mem_mb=10000, log: - logs("plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), + logs( + "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ), benchmark: - benchmarks("plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") + benchmarks( + "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: @@ -86,9 +96,13 @@ if config_provider("foresight") != "perfect": resources: mem_mb=10000, log: - logs("plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), + logs( + "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ), benchmark: - benchmarks("plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") + benchmarks( + "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: @@ -115,7 +129,9 @@ if config_provider("foresight") == "perfect": resources: mem_mb=10000, benchmark: - benchmarks("postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years_benchmark") + benchmarks( + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years_benchmark" + ) conda: "../envs/environment.yaml" script: @@ -142,7 +158,9 @@ rule make_summary: params: foresight=config_provider("foresight"), costs=config_provider("costs"), - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, scenario=config_provider("scenario"), RDIR=RDIR, input: @@ -159,7 +177,9 @@ rule make_summary: costs=( "data/costs_{}.csv".format(config_provider("costs", "year")) if config_provider("foresight") == "overnight" - else "data/costs_{}.csv".format(config_provider("scenario", "planning_horizons", 0)) + else "data/costs_{}.csv".format( + config_provider("scenario", "planning_horizons", 0) + ) ), ac_plot=expand( RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index 4ff94bf2..d3aa8d4c 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -45,9 +45,13 @@ rule solve_operations_network: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc", log: solver=normpath( - logs("solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log") + logs( + "solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log" + ) + ), + python=logs( + "solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log" ), - python=logs("solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log"), benchmark: benchmarks("solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}") threads: 4 diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 260837b7..a6313cac 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -36,9 +36,13 @@ rule add_existing_baseyear: resources: mem_mb=2000, log: - logs("add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), + logs( + "add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ), benchmark: - benchmarks("add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") + benchmarks( + "add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: @@ -52,7 +56,9 @@ rule add_brownfield: "sector", "H2_retrofit_capacity_per_CH4" ), threshold_capacity=config_provider("existing_capacities", " threshold_capacity"), - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, carriers=config_provider("electricity", "renewable_carriers"), input: **{ @@ -75,9 +81,13 @@ rule add_brownfield: resources: mem_mb=10000, log: - logs("add_brownfield_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), + logs( + "add_brownfield_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ), benchmark: - benchmarks("add_brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") + benchmarks( + "add_brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: @@ -107,14 +117,20 @@ rule solve_sector_network_myopic: shadow: "shallow" log: - solver=logs("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"), + solver=logs( + "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: solver_threads resources: mem_mb=config_provider("solving", "mem"), walltime=config_provider("solving", "walltime", default="12:00:00"), benchmark: - benchmarks("solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") + benchmarks( + "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index 7811efe3..64ad007c 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -33,7 +33,9 @@ rule solve_sector_network: mem_mb=config_provider("solving", "mem"), walltime=config_provider("solving", "walltime", default="12:00:00"), benchmark: - benchmarks("solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") + benchmarks( + "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 85f87d9b..ee16a201 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -14,10 +14,14 @@ rule add_existing_baseyear: busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - costs="data/costs_{}.csv".format(config_provider("scenario", "planning_horizons", 0)), + costs="data/costs_{}.csv".format( + config_provider("scenario", "planning_horizons", 0) + ), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), - existing_heating_distribution=resources("existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv"), + existing_heating_distribution=resources( + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" + ), existing_heating="data/existing_infrastructure/existing_heating_raw.csv", existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", @@ -31,9 +35,13 @@ rule add_existing_baseyear: resources: mem_mb=2000, log: - logs("add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log"), + logs( + "add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" + ), benchmark: - benchmarks("add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}") + benchmarks( + "add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: @@ -61,9 +69,13 @@ rule prepare_perfect_foresight: resources: mem_mb=10000, log: - logs("prepare_perfect_foresight{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}.log"), + logs( + "prepare_perfect_foresight{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}.log" + ), benchmark: - benchmarks("prepare_perfect_foresight{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}") + benchmarks( + "prepare_perfect_foresight{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}" + ) conda: "../envs/environment.yaml" script: @@ -76,7 +88,9 @@ rule solve_sector_network_perfect: foresight=config_provider("foresight"), sector=config_provider("sector"), planning_horizons=config_provider("scenario", "planning_horizons"), - co2_sequestration_potential=config_provider("sector", "co2_sequestration_potential", 200), + co2_sequestration_potential=config_provider( + "sector", "co2_sequestration_potential", 200 + ), custom_extra_functionality=input_custom_extra_functionality, input: network=RESULTS @@ -99,7 +113,9 @@ rule solve_sector_network_perfect: memory=RESULTS + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years_memory.log", benchmark: - benchmarks("solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years}") + benchmarks( + "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years}" + ) conda: "../envs/environment.yaml" script: @@ -110,13 +126,13 @@ rule make_summary_perfect: input: **{ f"networks_{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}": RESULTS - + f"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc" - for simpl in config_provider("scenario", "simpl") - for clusters in config_provider("scenario", "clusters") - for opts in config_provider("scenario", "opts") - for sector_opts in config_provider("scenario", "sector_opts") - for ll in config_provider("scenario", "ll") - }, + + f"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc" + for simpl in config_provider("scenario", "simpl") + for clusters in config_provider("scenario", "clusters") + for opts in config_provider("scenario", "opts") + for sector_opts in config_provider("scenario", "sector_opts") + for ll in config_provider("scenario", "ll") + }, costs="data/costs_2020.csv", output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", diff --git a/rules/validate.smk b/rules/validate.smk index f8ebea5d..3c42c5f0 100644 --- a/rules/validate.smk +++ b/rules/validate.smk @@ -17,7 +17,9 @@ rule build_electricity_production: The data is used for validation of the optimization results. """ params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, countries=config_provider("countries"), output: resources("historical_electricity_production.csv"), @@ -35,7 +37,9 @@ rule build_cross_border_flows: The data is used for validation of the optimization results. """ params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, countries=config_provider("countries"), input: network=resources("networks/base.nc"), @@ -55,7 +59,9 @@ rule build_electricity_prices: The data is used for validation of the optimization results. """ params: - snapshots={k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"]}, + snapshots={ + k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + }, countries=config_provider("countries"), output: resources("historical_electricity_prices.csv"), From 8781e690661b064432689511f215eaa48affa7bf Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Fri, 9 Feb 2024 18:36:16 +0100 Subject: [PATCH 272/591] bugfix: coal emissions for industry weren't tracked Also allow industrial coal demand to be regional (so we can include them in regional CO2 constraints). --- config/config.default.yaml | 1 + scripts/prepare_sector_network.py | 39 +++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 1033d49d..44b54148 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -501,6 +501,7 @@ sector: SMR_cc: true regional_methanol_demand: false regional_oil_demand: false + regional_coal_demand: false regional_co2_sequestration_potential: enable: false attribute: 'conservative estimate Mt' diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index be8aea53..18d1feb0 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -172,6 +172,13 @@ def define_spatial(nodes, options): spatial.coal.nodes = ["EU coal"] spatial.coal.locations = ["EU"] + if options["regional_coal_demand"]: + spatial.coal.demand_locations = nodes + spatial.coal.industry = nodes + " coal for industry" + else: + spatial.coal.demand_locations = ["EU"] + spatial.coal.industry = ["EU coal for industry"] + # lignite spatial.lignite = SimpleNamespace() spatial.lignite.nodes = ["EU lignite"] @@ -3048,19 +3055,41 @@ def add_industry(n, costs): mwh_coal_per_mwh_coke = 1.366 # from eurostat energy balance p_set = ( - industrial_demand["coal"].sum() - + mwh_coal_per_mwh_coke * industrial_demand["coke"].sum() + industrial_demand["coal"] + + mwh_coal_per_mwh_coke * industrial_demand["coke"] ) / nhours + if not options["regional_coal_demand"]: + p_set = p_set.sum() + + n.madd( + "Bus", + spatial.coal.industry, + location=spatial.coal.demand_locations, + carrier="coal for industry", + unit="MWh_LHV", + ) + n.madd( "Load", - spatial.coal.nodes, - suffix=" for industry", - bus=spatial.coal.nodes, + spatial.coal.industry, + bus=spatial.coal.industry, carrier="coal for industry", p_set=p_set, ) + n.madd( + "Link", + spatial.coal.industry, + bus0=spatial.coal.nodes, + bus1=spatial.coal.industry, + bus2="co2 atmosphere", + carrier="coal for industry", + p_nom_extendable=True, + efficiency2=costs.at["coal", "CO2 intensity"], + ) + + def add_waste_heat(n): # TODO options? From 17105b81256a5364739a4a2f4c3e865a3ba3fc95 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 10 Feb 2024 18:17:57 +0000 Subject: [PATCH 273/591] [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 18d1feb0..5d5e271b 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3090,7 +3090,6 @@ def add_industry(n, costs): ) - def add_waste_heat(n): # TODO options? From 5c7bbcd94de57792d02af7c38cc4aa216ed2624a Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 16 Aug 2023 11:41:48 +0200 Subject: [PATCH 274/591] retrieve electricity demand: use script in order to concat time-series --- rules/retrieve.smk | 16 ++--------- scripts/retrieve_electricity_demand.py | 37 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 scripts/retrieve_electricity_demand.py diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 2980583f..716b81c0 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -188,18 +188,6 @@ if config["enable"]["retrieve"]: if config["enable"]["retrieve"]: rule retrieve_electricity_demand: - input: - HTTP.remote( - "data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv".format( - version=( - "2019-06-05" - if config["snapshots"]["end"] < "2019" - else "2020-10-06" - ) - ), - keep_local=True, - static=True, - ), output: RESOURCES + "load_raw.csv", log: @@ -207,8 +195,8 @@ if config["enable"]["retrieve"]: resources: mem_mb=5000, retries: 2 - run: - move(input[0], output[0]) + script: + "../scripts/retrieve_electricity_demand.py" if config["enable"]["retrieve"]: diff --git a/scripts/retrieve_electricity_demand.py b/scripts/retrieve_electricity_demand.py new file mode 100644 index 00000000..58615755 --- /dev/null +++ b/scripts/retrieve_electricity_demand.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Retrieve monthly fuel prices from Destatis. +""" + +import logging + +import pandas as pd + +logger = logging.getLogger(__name__) + +from pathlib import Path + +from _helpers import configure_logging, set_scenario_config + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake("retrieve_eletricity_demand") + rootpath = ".." + else: + rootpath = "." + configure_logging(snakemake) + set_scenario_config(snakemake) + + versions = ["2019-06-05", "2020-10-06"] + url = "https://data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv" + + df1, df2 = [ + pd.read_csv(url.format(version=version), index_col=0) for version in versions + ] + res = pd.concat([df1, df2[df2.index > df1.index[-1]]], join="inner") + res.to_csv(snakemake.output[0]) From 2bd80210584921bffa9822fff215f02f2f4840e7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 16 Aug 2023 11:47:27 +0200 Subject: [PATCH 275/591] retrieve electricity demand: make online version snakemake params --- rules/retrieve.smk | 2 ++ scripts/retrieve_electricity_demand.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 716b81c0..0fea03ac 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -188,6 +188,8 @@ if config["enable"]["retrieve"]: if config["enable"]["retrieve"]: rule retrieve_electricity_demand: + params: + versions=["2019-06-05", "2020-10-06"], output: RESOURCES + "load_raw.csv", log: diff --git a/scripts/retrieve_electricity_demand.py b/scripts/retrieve_electricity_demand.py index 58615755..58511857 100644 --- a/scripts/retrieve_electricity_demand.py +++ b/scripts/retrieve_electricity_demand.py @@ -27,11 +27,11 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - versions = ["2019-06-05", "2020-10-06"] url = "https://data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv" df1, df2 = [ - pd.read_csv(url.format(version=version), index_col=0) for version in versions + pd.read_csv(url.format(version=version), index_col=0) + for version in snakemake.params.versions ] res = pd.concat([df1, df2[df2.index > df1.index[-1]]], join="inner") res.to_csv(snakemake.output[0]) From 94f72d7276b2f53f5042117ccdfc5179689d9280 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 17 Aug 2023 10:17:12 +0200 Subject: [PATCH 276/591] electricity demand: remove powerstastics flag, merge sources in retrieve_electricity_demand --- doc/configtables/load.csv | 1 - doc/retrieve.rst | 2 +- rules/build_electricity.smk | 2 +- rules/retrieve.smk | 2 +- scripts/build_electricity_demand.py | 172 ++++++++++--------------- scripts/retrieve_electricity_demand.py | 16 ++- 6 files changed, 85 insertions(+), 110 deletions(-) diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index 6e98f881..ac666947 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -1,5 +1,4 @@ ,Unit,Values,Description -power_statistics,bool,"{true, false}",Whether to load the electricity consumption data of the ENTSOE power statistics (only for files from 2019 and before) or from the ENTSOE transparency data (only has load data from 2015 onwards). interpolate_limit,hours,integer,"Maximum gap size (consecutive nans) which interpolated linearly." time_shift_for_large_gaps,string,string,"Periods which are used for copying time-slices in order to fill large gaps of nans. Have to be valid ``pandas`` period strings." manual_adjustments,bool,"{true, false}","Whether to adjust the load data manually according to the function in :func:`manual_adjustment`." diff --git a/doc/retrieve.rst b/doc/retrieve.rst index 06a07441..e4800fd2 100644 --- a/doc/retrieve.rst +++ b/doc/retrieve.rst @@ -91,7 +91,7 @@ None. **Outputs** -- ``resources/load_raw.csv`` +- ``resources/electricity_demand.csv`` Rule ``retrieve_cost_data`` diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 89f4f736..ba11f060 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -24,7 +24,7 @@ rule build_electricity_demand: countries=config["countries"], load=config["load"], input: - ancient(RESOURCES + "load_raw.csv"), + ancient(RESOURCES + "electricity_demand.csv"), output: RESOURCES + "load.csv", log: diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 0fea03ac..0821a6b7 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -191,7 +191,7 @@ if config["enable"]["retrieve"]: params: versions=["2019-06-05", "2020-10-06"], output: - RESOURCES + "load_raw.csv", + RESOURCES + "electricity_demand.csv", log: LOGS + "retrieve_electricity_demand.log", resources: diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index a08055ba..2810edfa 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -31,7 +31,7 @@ Relevant Settings Inputs ------ -- ``resources/load_raw.csv``: +- ``resources/electricity_demand.csv``: Outputs ------- @@ -49,7 +49,7 @@ from pandas import Timedelta as Delta logger = logging.getLogger(__name__) -def load_timeseries(fn, years, countries, powerstatistics=True): +def load_timeseries(fn, years, countries): """ Read load data from OPSD time-series package version 2020-10-06. @@ -62,10 +62,6 @@ def load_timeseries(fn, years, countries, powerstatistics=True): File name or url location (file format .csv) countries : listlike Countries for which to read load data. - powerstatistics: bool - Whether the electricity consumption data of the ENTSOE power - statistics (if true) or of the ENTSOE transparency map (if false) - should be parsed. Returns ------- @@ -74,17 +70,9 @@ def load_timeseries(fn, years, countries, powerstatistics=True): """ logger.info(f"Retrieving load data from '{fn}'.") - pattern = "power_statistics" if powerstatistics else "transparency" - pattern = f"_load_actual_entsoe_{pattern}" - - def rename(s): - return s[: -len(pattern)] - return ( pd.read_csv(fn, index_col=0, parse_dates=[0], date_format="%Y-%m-%dT%H:%M:%SZ") .tz_localize(None) - .filter(like=pattern) - .rename(columns=rename) .dropna(how="all", axis=0) .rename(columns={"GB_UKM": "GB"}) .filter(items=countries) @@ -149,17 +137,18 @@ def copy_timeslice(load, cntry, start, stop, delta, fn_load=None): ].values elif fn_load is not None: duration = pd.date_range(freq="h", start=start - delta, end=stop - delta) - load_raw = load_timeseries(fn_load, duration, [cntry], powerstatistics) + load_raw = load_timeseries(fn_load, duration, [cntry]) load.loc[start:stop, cntry] = load_raw.loc[ start - delta : stop - delta, cntry ].values -def manual_adjustment(load, fn_load, powerstatistics, countries): +def manual_adjustment(load, fn_load): """ Adjust gaps manual for load data from OPSD time-series package. - 1. For the ENTSOE power statistics load data (if powerstatistics is True) + 1. For years later than 2015 for which the load data is mainly taken from the + ENTSOE power statistics Kosovo (KV) and Albania (AL) do not exist in the data set. Kosovo gets the same load curve as Serbia and Albania the same as Macdedonia, both scaled @@ -167,7 +156,8 @@ def manual_adjustment(load, fn_load, powerstatistics, countries): IEA Data browser [0] for the year 2013. - 2. For the ENTSOE transparency load data (if powerstatistics is False) + 2. For years earlier than 2015 for which the load data is mainly taken from the + ENTSOE transparency platforms Albania (AL) and Macedonia (MK) do not exist in the data set. Both get the same load curve as Montenegro, scaled by the corresponding ratio of total energy @@ -183,9 +173,6 @@ def manual_adjustment(load, fn_load, powerstatistics, countries): ---------- load : pd.DataFrame Load time-series with UTC timestamps x ISO-2 countries - powerstatistics: bool - Whether argument load comprises the electricity consumption data of - the ENTSOE power statistics or of the ENTSOE transparency map load_fn: str File name or url location (file format .csv) @@ -195,88 +182,66 @@ def manual_adjustment(load, fn_load, powerstatistics, countries): Manual adjusted and interpolated load time-series with UTC timestamps x ISO-2 countries """ - if powerstatistics: - if "MK" in load.columns: - if "AL" not in load.columns or load.AL.isnull().values.all(): - load["AL"] = load["MK"] * (4.1 / 7.4) - if "RS" in load.columns: - if "KV" not in load.columns or load.KV.isnull().values.all(): - load["KV"] = load["RS"] * (4.8 / 27.0) + if "MK" in load: + if "AL" not in load or load.AL.isnull().values.all(): + load["AL"] = load["MK"] * (4.1 / 7.4) + if "RS" in load: + if "KV" not in load or load.KV.isnull().values.all(): + load["KV"] = load["RS"] * (4.8 / 27.0) + if "ME" in load: + if "AL" not in load and "AL" in countries: + load["AL"] = load.ME * (5.7 / 2.9) + if "MK" not in load and "MK" in countries: + load["MK"] = load.ME * (6.7 / 2.9) + if "BA" not in load and "BA" in countries: + load["BA"] = load.HR * (11.0 / 16.2) - copy_timeslice( - load, "GR", "2015-08-11 21:00", "2015-08-15 20:00", Delta(weeks=1) - ) - copy_timeslice( - load, "AT", "2018-12-31 22:00", "2019-01-01 22:00", Delta(days=2) - ) - copy_timeslice( - load, "CH", "2010-01-19 07:00", "2010-01-19 22:00", Delta(days=1) - ) - copy_timeslice( - load, "CH", "2010-03-28 00:00", "2010-03-28 21:00", Delta(days=1) - ) - # is a WE, so take WE before - copy_timeslice( - load, "CH", "2010-10-08 13:00", "2010-10-10 21:00", Delta(weeks=1) - ) - copy_timeslice( - load, "CH", "2010-11-04 04:00", "2010-11-04 22:00", Delta(days=1) - ) - copy_timeslice( - load, "NO", "2010-12-09 11:00", "2010-12-09 18:00", Delta(days=1) - ) - # whole january missing - copy_timeslice( - load, - "GB", - "2010-01-01 00:00", - "2010-01-31 23:00", - Delta(days=-365), - fn_load, - ) - # 1.1. at midnight gets special treatment - copy_timeslice( - load, - "IE", - "2016-01-01 00:00", - "2016-01-01 01:00", - Delta(days=-366), - fn_load, - ) - copy_timeslice( - load, - "PT", - "2016-01-01 00:00", - "2016-01-01 01:00", - Delta(days=-366), - fn_load, - ) - copy_timeslice( - load, - "GB", - "2016-01-01 00:00", - "2016-01-01 01:00", - Delta(days=-366), - fn_load, - ) + copy_timeslice(load, "GR", "2015-08-11 21:00", "2015-08-15 20:00", Delta(weeks=1)) + copy_timeslice(load, "AT", "2018-12-31 22:00", "2019-01-01 22:00", Delta(days=2)) + copy_timeslice(load, "CH", "2010-01-19 07:00", "2010-01-19 22:00", Delta(days=1)) + copy_timeslice(load, "CH", "2010-03-28 00:00", "2010-03-28 21:00", Delta(days=1)) + # is a WE, so take WE before + copy_timeslice(load, "CH", "2010-10-08 13:00", "2010-10-10 21:00", Delta(weeks=1)) + copy_timeslice(load, "CH", "2010-11-04 04:00", "2010-11-04 22:00", Delta(days=1)) + copy_timeslice(load, "NO", "2010-12-09 11:00", "2010-12-09 18:00", Delta(days=1)) + # whole january missing + copy_timeslice( + load, + "GB", + "2010-01-01 00:00", + "2010-01-31 23:00", + Delta(days=-365), + fn_load, + ) + # 1.1. at midnight gets special treatment + copy_timeslice( + load, + "IE", + "2016-01-01 00:00", + "2016-01-01 01:00", + Delta(days=-366), + fn_load, + ) + copy_timeslice( + load, + "PT", + "2016-01-01 00:00", + "2016-01-01 01:00", + Delta(days=-366), + fn_load, + ) + copy_timeslice( + load, + "GB", + "2016-01-01 00:00", + "2016-01-01 01:00", + Delta(days=-366), + fn_load, + ) - else: - if "ME" in load: - if "AL" not in load and "AL" in countries: - load["AL"] = load.ME * (5.7 / 2.9) - if "MK" not in load and "MK" in countries: - load["MK"] = load.ME * (6.7 / 2.9) - if "BA" not in load and "BA" in countries: - load["BA"] = load.HR * (11.0 / 16.2) - copy_timeslice( - load, "BG", "2018-10-27 21:00", "2018-10-28 22:00", Delta(weeks=1) - ) - copy_timeslice( - load, "LU", "2019-01-02 11:00", "2019-01-05 05:00", Delta(weeks=-1) - ) - copy_timeslice( - load, "LU", "2019-02-05 20:00", "2019-02-06 19:00", Delta(weeks=-1) - ) + copy_timeslice(load, "BG", "2018-10-27 21:00", "2018-10-28 22:00", Delta(weeks=1)) + copy_timeslice(load, "LU", "2019-01-02 11:00", "2019-01-05 05:00", Delta(weeks=-1)) + copy_timeslice(load, "LU", "2019-02-05 20:00", "2019-02-06 19:00", Delta(weeks=-1)) if "UA" in countries: copy_timeslice( @@ -297,14 +262,13 @@ if __name__ == "__main__": configure_logging(snakemake) - powerstatistics = snakemake.params.load["power_statistics"] interpolate_limit = snakemake.params.load["interpolate_limit"] countries = snakemake.params.countries snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) years = slice(snapshots[0], snapshots[-1]) time_shift = snakemake.params.load["time_shift_for_large_gaps"] - load = load_timeseries(snakemake.input[0], years, countries, powerstatistics) + load = load_timeseries(snakemake.input[0], years, countries) if "UA" in countries: # attach load of UA (best data only for entsoe transparency) @@ -321,7 +285,7 @@ if __name__ == "__main__": load["MD"] = 6.2e6 * (load_ua / load_ua.sum()) if snakemake.params.load["manual_adjustments"]: - load = manual_adjustment(load, snakemake.input[0], powerstatistics, countries) + load = manual_adjustment(load, snakemake.input[0]) if load.empty: logger.warning("Build electricity demand time series is empty.") diff --git a/scripts/retrieve_electricity_demand.py b/scripts/retrieve_electricity_demand.py index 58511857..01dc4aa8 100644 --- a/scripts/retrieve_electricity_demand.py +++ b/scripts/retrieve_electricity_demand.py @@ -20,7 +20,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("retrieve_eletricity_demand") + snakemake = mock_snakemake("retrieve_electricity_demand") rootpath = ".." else: rootpath = "." @@ -33,5 +33,17 @@ if __name__ == "__main__": pd.read_csv(url.format(version=version), index_col=0) for version in snakemake.params.versions ] - res = pd.concat([df1, df2[df2.index > df1.index[-1]]], join="inner") + combined = pd.concat([df1, df2[df2.index > df1.index[-1]]]) + + pattern = "_load_actual_entsoe_transparency" + transparency = combined.filter(like=pattern).rename( + columns=lambda x: x.replace(pattern, "") + ) + pattern = "_load_actual_entsoe_power_statistics" + powerstatistics = combined.filter(like=pattern).rename( + columns=lambda x: x.replace(pattern, "") + ) + + res = transparency.fillna(powerstatistics) + res.to_csv(snakemake.output[0]) From 49171901d787ff63ac4d3964e0b139579846b801 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 10:12:03 +0100 Subject: [PATCH 277/591] selective cherry-pick from 91eff472a7748dc617d19cd9ad788bf81144c356 --- scripts/build_electricity_demand.py | 32 ++++++++++++++++------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 2810edfa..d708cf6f 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -68,8 +68,6 @@ def load_timeseries(fn, years, countries): load : pd.DataFrame Load time-series with UTC timestamps x ISO-2 countries """ - logger.info(f"Retrieving load data from '{fn}'.") - return ( pd.read_csv(fn, index_col=0, parse_dates=[0], date_format="%Y-%m-%dT%H:%M:%SZ") .tz_localize(None) @@ -182,20 +180,26 @@ def manual_adjustment(load, fn_load): Manual adjusted and interpolated load time-series with UTC timestamps x ISO-2 countries """ - if "MK" in load: - if "AL" not in load or load.AL.isnull().values.all(): - load["AL"] = load["MK"] * (4.1 / 7.4) - if "RS" in load: - if "KV" not in load or load.KV.isnull().values.all(): - load["KV"] = load["RS"] * (4.8 / 27.0) - if "ME" in load: - if "AL" not in load and "AL" in countries: + + if "AL" not in load and "AL" in countries: + if "ME" in load: load["AL"] = load.ME * (5.7 / 2.9) - if "MK" not in load and "MK" in countries: - load["MK"] = load.ME * (6.7 / 2.9) - if "BA" not in load and "BA" in countries: + elif "MK" in load: + load["AL"] = load["MK"] * (4.1 / 7.4) + + if "MK" in countries: + if "MK" not in load or load.MK.isnull().sum() > len(load) / 2: + if "ME" in load: + load["MK"] = load.ME * (6.7 / 2.9) + + if "BA" not in load and "BA" in countries: + if "ME" in load: load["BA"] = load.HR * (11.0 / 16.2) + if "KV" not in load or load.KV.isnull().values.all(): + if "RS" in load: + load["KV"] = load["RS"] * (4.8 / 27.0) + copy_timeslice(load, "GR", "2015-08-11 21:00", "2015-08-15 20:00", Delta(weeks=1)) copy_timeslice(load, "AT", "2018-12-31 22:00", "2019-01-01 22:00", Delta(days=2)) copy_timeslice(load, "CH", "2010-01-19 07:00", "2010-01-19 22:00", Delta(days=1)) @@ -258,7 +262,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_electricity_demand") + snakemake = mock_snakemake("build_electricity_demand", run="network2019") configure_logging(snakemake) From 09ada56bf1266a0a6b81e713e2c58d49ef779c57 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 10:49:45 +0100 Subject: [PATCH 278/591] finishing touches and release notes --- doc/release_notes.rst | 3 +++ rules/build_electricity.smk | 6 +++--- rules/retrieve.smk | 2 +- scripts/add_electricity.py | 2 +- scripts/build_electricity_demand.py | 26 +++++++++++--------------- scripts/retrieve_electricity_demand.py | 9 +++------ 6 files changed, 22 insertions(+), 26 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index ee7bd64b..fce4ae1b 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,9 @@ Release Notes Upcoming Release ================ +* Merged two OPSD time series data versions into such that the option ``load: + power_statistics:`` becomes superfluous and was hence removed. + * Add new default to overdimension heating in individual buildings. This allows them to cover heat demand peaks e.g. 10% higher than those in the data. The disadvantage of manipulating the costs is that the capacity is then not quite diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index ba11f060..f05e18c0 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -24,9 +24,9 @@ rule build_electricity_demand: countries=config["countries"], load=config["load"], input: - ancient(RESOURCES + "electricity_demand.csv"), + ancient("data/electricity_demand_raw.csv"), output: - RESOURCES + "load.csv", + RESOURCES + "electricity_demand.csv", log: LOGS + "build_electricity_demand.log", resources: @@ -417,7 +417,7 @@ rule add_electricity: if config["conventional"]["dynamic_fuel_price"] else [] ), - load=RESOURCES + "load.csv", + load=RESOURCES + "electricity_demand.csv", nuts3_shapes=RESOURCES + "nuts3_shapes.geojson", ua_md_gdp="data/GDP_PPP_30arcsec_v3_mapped_default.csv", output: diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 0821a6b7..acb8a1c1 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -191,7 +191,7 @@ if config["enable"]["retrieve"]: params: versions=["2019-06-05", "2020-10-06"], output: - RESOURCES + "electricity_demand.csv", + "data/electricity_demand_raw.csv", log: LOGS + "retrieve_electricity_demand.log", resources: diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index ab97dcd0..614e3330 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -52,7 +52,7 @@ Inputs :scale: 34 % - ``data/geth2015_hydro_capacities.csv``: alternative to capacities above; not currently used! -- ``resources/load.csv`` Hourly per-country load profiles. +- ``resources/electricity_demand.csv`` Hourly per-country electricity demand profiles. - ``resources/regions_onshore.geojson``: confer :ref:`busregions` - ``resources/nuts3_shapes.geojson``: confer :ref:`shapes` - ``resources/powerplants.csv``: confer :ref:`powerplants` diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index d708cf6f..5d013065 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -1,15 +1,13 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020 @JanFrederickUnnewehr, The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020 @JanFrederickUnnewehr, 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ -This rule downloads the load data from `Open Power System Data Time series. - +This rule downloads the load data from `Open Power System Data Time series `_. For all countries in -the network, the per country load timeseries with suffix -``_load_actual_entsoe_transparency`` are extracted from the dataset. After -filling small gaps linearly and large gaps by copying time-slice of a given -period, the load data is exported to a ``.csv`` file. +the network, the per country load timeseries are extracted from the dataset. +After filling small gaps linearly and large gaps by copying time-slice of a +given period, the load data is exported to a ``.csv`` file. Relevant Settings ----------------- @@ -19,9 +17,7 @@ Relevant Settings snapshots: load: - interpolate_limit: - time_shift_for_large_gaps: - manual_adjustments: + interpolate_limit: time_shift_for_large_gaps: manual_adjustments: .. seealso:: @@ -31,12 +27,12 @@ Relevant Settings Inputs ------ -- ``resources/electricity_demand.csv``: +- ``data/electricity_demand_raw.csv``: Outputs ------- -- ``resources/load.csv``: +- ``resources/electricity_demand.csv``: """ import logging @@ -141,7 +137,7 @@ def copy_timeslice(load, cntry, start, stop, delta, fn_load=None): ].values -def manual_adjustment(load, fn_load): +def manual_adjustment(load, fn_load, countries): """ Adjust gaps manual for load data from OPSD time-series package. @@ -262,7 +258,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_electricity_demand", run="network2019") + snakemake = mock_snakemake("build_electricity_demand") configure_logging(snakemake) @@ -289,7 +285,7 @@ if __name__ == "__main__": load["MD"] = 6.2e6 * (load_ua / load_ua.sum()) if snakemake.params.load["manual_adjustments"]: - load = manual_adjustment(load, snakemake.input[0]) + load = manual_adjustment(load, snakemake.input[0], countries) if load.empty: logger.warning("Build electricity demand time series is empty.") diff --git a/scripts/retrieve_electricity_demand.py b/scripts/retrieve_electricity_demand.py index 01dc4aa8..a8a44b68 100644 --- a/scripts/retrieve_electricity_demand.py +++ b/scripts/retrieve_electricity_demand.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ -Retrieve monthly fuel prices from Destatis. +Retrieve electricity prices from OPSD. """ import logging @@ -12,9 +12,7 @@ import pandas as pd logger = logging.getLogger(__name__) -from pathlib import Path - -from _helpers import configure_logging, set_scenario_config +from _helpers import configure_logging if __name__ == "__main__": if "snakemake" not in globals(): @@ -25,7 +23,6 @@ if __name__ == "__main__": else: rootpath = "." configure_logging(snakemake) - set_scenario_config(snakemake) url = "https://data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv" From 1a883debb5170e754f83ace5c5cf598453041019 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:00:02 +0000 Subject: [PATCH 279/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_sector.smk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 268113f9..d7fbe638 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -229,7 +229,8 @@ rule build_solar_thermal_profiles: params: snapshots={ k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] - }, # TODO use config_provider + }, + # TODO use config_provider solar_thermal=config_provider("solar_thermal"), input: pop_layout=resources("pop_layout_{scope}.nc"), From bb7b65eebd9c1dce423b1ff3127ae9d7ce9d1264 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 11:52:07 +0100 Subject: [PATCH 280/591] move create_scenarios.py to config directory --- .gitignore | 1 + {scripts => config}/create_scenarios.py | 0 doc/configtables/run.csv | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) rename {scripts => config}/create_scenarios.py (100%) diff --git a/.gitignore b/.gitignore index 467ecd95..f5f88861 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ doc/_build /scripts/old /scripts/create_scenarios.py +/config/create_scenarios.py config.yaml config/scenarios.yaml diff --git a/scripts/create_scenarios.py b/config/create_scenarios.py similarity index 100% rename from scripts/create_scenarios.py rename to config/create_scenarios.py diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index 925c2dea..75f29928 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -2,7 +2,7 @@ name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenario: enable`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenario: file``." scenarios,,, -- enable,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``file``." --- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``create_scenarios.py`` script in ``scripts``." +-- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``config/create_scenarios.py`` script in ``scripts``." disable_progrssbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." shared_resources,bool/str/list,,"Switch to select whether resources should be shared across runs. If a string or list is passed, it is assumed to be wildcard(s) which indicates up to which set of wildcards the resource folder should be shared. If set to 'base', only resources before creating the elec.nc file are shared." shared_cutouts,bool,"{true, false}","Switch to select whether cutouts should be shared across runs." From 40b27b4107713e00029ca2c7c88c86eed1ad94e5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 11:53:20 +0100 Subject: [PATCH 281/591] use set_scenario_config everywhere --- scripts/add_brownfield.py | 5 +++-- scripts/add_existing_baseyear.py | 5 +++-- scripts/build_ammonia_production.py | 4 ++++ scripts/build_biomass_potentials.py | 5 +++++ scripts/build_clustered_population_layouts.py | 4 ++++ scripts/build_cop_profiles.py | 4 ++++ scripts/build_daily_heat_demand.py | 2 ++ scripts/build_district_heat_share.py | 3 +++ scripts/build_energy_totals.py | 5 +++-- scripts/build_existing_heating_distribution.py | 2 ++ scripts/build_gas_input_locations.py | 4 +++- scripts/build_gas_network.py | 4 +++- scripts/build_hourly_heat_demand.py | 3 ++- scripts/build_industrial_distribution_key.py | 6 ++++-- .../build_industrial_energy_demand_per_country_today.py | 2 ++ scripts/build_industrial_energy_demand_per_node.py | 3 +++ scripts/build_industrial_energy_demand_per_node_today.py | 3 +++ scripts/build_industrial_production_per_country.py | 6 +++--- .../build_industrial_production_per_country_tomorrow.py | 3 +++ scripts/build_industrial_production_per_node.py | 2 ++ scripts/build_industry_sector_ratios.py | 3 ++- scripts/build_population_layouts.py | 5 ++++- scripts/build_population_weighted_energy_totals.py | 3 +++ scripts/build_retro_cost.py | 2 ++ scripts/build_salt_cavern_potentials.py | 3 +++ scripts/build_sequestration_potentials.py | 4 ++++ scripts/build_shipping_demand.py | 2 ++ scripts/build_solar_thermal_profiles.py | 3 +++ scripts/build_temperature_profiles.py | 2 ++ scripts/build_transport_demand.py | 3 ++- scripts/cluster_gas_network.py | 5 +++-- scripts/determine_availability_matrix_MD_UA.py | 3 ++- scripts/make_summary.py | 4 +++- scripts/make_summary_perfect.py | 2 ++ scripts/plot_gas_network.py | 3 ++- scripts/plot_hydrogen_network.py | 3 ++- scripts/plot_power_network.py | 3 ++- scripts/plot_power_network_clustered.py | 3 ++- scripts/plot_power_network_perfect.py | 3 ++- scripts/plot_summary.py | 4 +++- scripts/prepare_perfect_foresight.py | 4 +++- scripts/prepare_sector_network.py | 4 ++-- scripts/retrieve_databundle.py | 7 +++---- scripts/retrieve_electricity_demand.py | 3 ++- scripts/retrieve_gas_infrastructure_data.py | 4 +++- scripts/retrieve_irena.py | 3 ++- scripts/solve_network.py | 1 + 47 files changed, 127 insertions(+), 37 deletions(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 3b77c437..b0727b17 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -12,7 +12,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import update_config_with_sector_opts +from _helpers import update_config_with_sector_opts, configure_logging, set_scenario_config from add_existing_baseyear import add_build_year_to_new_assets from pypsa.clustering.spatial import normed_or_uniform @@ -210,7 +210,8 @@ if __name__ == "__main__": planning_horizons=2030, ) - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index c0d37a5b..25e35edd 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -15,7 +15,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import update_config_with_sector_opts +from _helpers import update_config_with_sector_opts, set_scenario_config, configure_logging from add_electricity import sanitize_carriers from prepare_sector_network import cluster_heat_buses, define_spatial, prepare_costs @@ -552,7 +552,8 @@ if __name__ == "__main__": planning_horizons=2020, ) - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) diff --git a/scripts/build_ammonia_production.py b/scripts/build_ammonia_production.py index 1bcdf9ae..47907cc9 100644 --- a/scripts/build_ammonia_production.py +++ b/scripts/build_ammonia_production.py @@ -9,6 +9,8 @@ Build historical annual ammonia production per country in ktonNH3/a. import country_converter as coco import pandas as pd +from _helpers import set_scenario_config + cc = coco.CountryConverter() @@ -18,6 +20,8 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_ammonia_production") + set_scenario_config(snakemake) + ammonia = pd.read_excel( snakemake.input.usgs, sheet_name="T12", diff --git a/scripts/build_biomass_potentials.py b/scripts/build_biomass_potentials.py index 6b5cb147..2fe6922c 100644 --- a/scripts/build_biomass_potentials.py +++ b/scripts/build_biomass_potentials.py @@ -16,6 +16,8 @@ import pandas as pd logger = logging.getLogger(__name__) AVAILABLE_BIOMASS_YEARS = [2010, 2020, 2030, 2040, 2050] +from _helpers import configure_logging, set_scenario_config + def build_nuts_population_data(year=2013): pop = pd.read_csv( @@ -220,6 +222,9 @@ if __name__ == "__main__": clusters="5", planning_horizons=2050, ) + + configure_logging(snakemake) + set_scenario_config(snakemake) overnight = snakemake.config["foresight"] == "overnight" params = snakemake.params.biomass diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index f1d386bd..4217baff 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -12,6 +12,8 @@ import geopandas as gpd import pandas as pd import xarray as xr +from _helpers import set_scenario_config + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -22,6 +24,8 @@ if __name__ == "__main__": clusters=48, ) + set_scenario_config(snakemake) + cutout = atlite.Cutout(snakemake.input.cutout) clustered_regions = ( diff --git a/scripts/build_cop_profiles.py b/scripts/build_cop_profiles.py index 4b1d952e..ee68dd0a 100644 --- a/scripts/build_cop_profiles.py +++ b/scripts/build_cop_profiles.py @@ -15,6 +15,8 @@ https://doi.org/10.1039/C2EE22653G. import xarray as xr +from _helpers import set_scenario_config + def coefficient_of_performance(delta_T, source="air"): if source == "air": @@ -35,6 +37,8 @@ if __name__ == "__main__": clusters=48, ) + set_scenario_config(snakemake) + for area in ["total", "urban", "rural"]: for source in ["air", "soil"]: source_T = xr.open_dataarray(snakemake.input[f"temp_{source}_{area}"]) diff --git a/scripts/build_daily_heat_demand.py b/scripts/build_daily_heat_demand.py index e334b1b3..03ba8c2e 100644 --- a/scripts/build_daily_heat_demand.py +++ b/scripts/build_daily_heat_demand.py @@ -12,6 +12,7 @@ import numpy as np import pandas as pd import xarray as xr from dask.distributed import Client, LocalCluster +from _helpers import set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): @@ -23,6 +24,7 @@ if __name__ == "__main__": simpl="", clusters=48, ) + set_scenario_config(snakemake) nprocesses = int(snakemake.threads) cluster = LocalCluster(n_workers=nprocesses, threads_per_worker=1) diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index 86c42631..121e4663 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -10,6 +10,7 @@ import logging import pandas as pd from prepare_sector_network import get +from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) @@ -24,6 +25,8 @@ if __name__ == "__main__": clusters=48, planning_horizons="2050", ) + configure_logging(snakemake) + set_scenario_config(snakemake) investment_year = int(snakemake.wildcards.planning_horizons[-4:]) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index c67bb49d..f22ddc25 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -14,7 +14,7 @@ import country_converter as coco import geopandas as gpd import numpy as np import pandas as pd -from _helpers import mute_print +from _helpers import mute_print, configure_logging, set_scenario_config from tqdm import tqdm cc = coco.CountryConverter() @@ -743,7 +743,8 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_energy_totals") - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) params = snakemake.params.energy diff --git a/scripts/build_existing_heating_distribution.py b/scripts/build_existing_heating_distribution.py index 78518597..eb2361c2 100644 --- a/scripts/build_existing_heating_distribution.py +++ b/scripts/build_existing_heating_distribution.py @@ -9,6 +9,7 @@ horizon. import country_converter as coco import numpy as np import pandas as pd +from _helpers import set_scenario_config cc = coco.CountryConverter() @@ -126,5 +127,6 @@ if __name__ == "__main__": clusters=48, planning_horizons=2050, ) + set_scenario_config(snakemake) build_existing_heating() diff --git a/scripts/build_gas_input_locations.py b/scripts/build_gas_input_locations.py index 081f74b9..5aba46e5 100644 --- a/scripts/build_gas_input_locations.py +++ b/scripts/build_gas_input_locations.py @@ -12,6 +12,7 @@ import logging import geopandas as gpd import pandas as pd from cluster_gas_network import load_bus_regions +from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) @@ -134,7 +135,8 @@ if __name__ == "__main__": clusters="128", ) - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) regions = load_bus_regions( snakemake.input.regions_onshore, snakemake.input.regions_offshore diff --git a/scripts/build_gas_network.py b/scripts/build_gas_network.py index 13cd75ba..0febd43d 100644 --- a/scripts/build_gas_network.py +++ b/scripts/build_gas_network.py @@ -13,6 +13,7 @@ import geopandas as gpd import pandas as pd from pypsa.geo import haversine_pts from shapely.geometry import Point +from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) @@ -143,7 +144,8 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_gas_network") - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) gas_network = load_dataset(snakemake.input.gas_network) diff --git a/scripts/build_hourly_heat_demand.py b/scripts/build_hourly_heat_demand.py index c972da89..a3110e1f 100644 --- a/scripts/build_hourly_heat_demand.py +++ b/scripts/build_hourly_heat_demand.py @@ -10,7 +10,7 @@ from itertools import product import pandas as pd import xarray as xr -from _helpers import generate_periodic_profiles +from _helpers import generate_periodic_profiles, set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): @@ -22,6 +22,7 @@ if __name__ == "__main__": simpl="", clusters=48, ) + set_scenario_config(snakemake) snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index 9b234e29..29b7538e 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -14,6 +14,8 @@ import country_converter as coco import geopandas as gpd import pandas as pd +from _helpers import configure_logging, set_scenario_config + logger = logging.getLogger(__name__) cc = coco.CountryConverter() @@ -148,8 +150,8 @@ if __name__ == "__main__": simpl="", clusters=128, ) - - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) countries = snakemake.params.countries diff --git a/scripts/build_industrial_energy_demand_per_country_today.py b/scripts/build_industrial_energy_demand_per_country_today.py index d1c672f1..99342b9e 100644 --- a/scripts/build_industrial_energy_demand_per_country_today.py +++ b/scripts/build_industrial_energy_demand_per_country_today.py @@ -12,6 +12,7 @@ from functools import partial import country_converter as coco import pandas as pd from tqdm import tqdm +from _helpers import set_scenario_config cc = coco.CountryConverter() @@ -175,6 +176,7 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake("build_industrial_energy_demand_per_country_today") + set_scenario_config(snakemake) params = snakemake.params.industry year = params.get("reference_year", 2015) diff --git a/scripts/build_industrial_energy_demand_per_node.py b/scripts/build_industrial_energy_demand_per_node.py index 55c10c5d..fcc0abd9 100644 --- a/scripts/build_industrial_energy_demand_per_node.py +++ b/scripts/build_industrial_energy_demand_per_node.py @@ -8,6 +8,8 @@ Build industrial energy demand per model region. import pandas as pd +from _helpers import set_scenario_config + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -18,6 +20,7 @@ if __name__ == "__main__": clusters=48, planning_horizons=2030, ) + set_scenario_config(snakemake) # import EU ratios df as csv fn = snakemake.input.industry_sector_ratios diff --git a/scripts/build_industrial_energy_demand_per_node_today.py b/scripts/build_industrial_energy_demand_per_node_today.py index d845e704..1b7aba83 100644 --- a/scripts/build_industrial_energy_demand_per_node_today.py +++ b/scripts/build_industrial_energy_demand_per_node_today.py @@ -11,6 +11,8 @@ from itertools import product import numpy as np import pandas as pd +from _helpers import set_scenario_config + # map JRC/our sectors to hotmaps sector, where mapping exist sector_mapping = { "Electric arc": "Iron and steel", @@ -75,5 +77,6 @@ if __name__ == "__main__": simpl="", clusters=48, ) + set_scenario_config(snakemake) build_nodal_industrial_energy_demand() diff --git a/scripts/build_industrial_production_per_country.py b/scripts/build_industrial_production_per_country.py index 0aea4f15..d9ec9afd 100644 --- a/scripts/build_industrial_production_per_country.py +++ b/scripts/build_industrial_production_per_country.py @@ -13,7 +13,7 @@ from functools import partial import country_converter as coco import numpy as np import pandas as pd -from _helpers import mute_print +from _helpers import mute_print, set_scenario_config, configure_logging from tqdm import tqdm logger = logging.getLogger(__name__) @@ -274,8 +274,8 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake("build_industrial_production_per_country") - - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) countries = snakemake.params.countries diff --git a/scripts/build_industrial_production_per_country_tomorrow.py b/scripts/build_industrial_production_per_country_tomorrow.py index ffed5195..835a2687 100644 --- a/scripts/build_industrial_production_per_country_tomorrow.py +++ b/scripts/build_industrial_production_per_country_tomorrow.py @@ -9,11 +9,14 @@ Build future industrial production per country. import pandas as pd from prepare_sector_network import get +from _helpers import set_scenario_config + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake snakemake = mock_snakemake("build_industrial_production_per_country_tomorrow") + set_scenario_config(snakemake) params = snakemake.params.industry diff --git a/scripts/build_industrial_production_per_node.py b/scripts/build_industrial_production_per_node.py index 7b69948a..c84590b7 100644 --- a/scripts/build_industrial_production_per_node.py +++ b/scripts/build_industrial_production_per_node.py @@ -7,6 +7,7 @@ Build industrial production per model region. """ from itertools import product +from _helpers import set_scenario_config import pandas as pd @@ -72,5 +73,6 @@ if __name__ == "__main__": simpl="", clusters=48, ) + set_scenario_config(snakemake) build_nodal_industrial_production() diff --git a/scripts/build_industry_sector_ratios.py b/scripts/build_industry_sector_ratios.py index 45705002..6014feee 100644 --- a/scripts/build_industry_sector_ratios.py +++ b/scripts/build_industry_sector_ratios.py @@ -7,7 +7,7 @@ Build specific energy consumption by carrier and industries. """ import pandas as pd -from _helpers import mute_print +from _helpers import mute_print, set_scenario_config # GWh/ktoe OR MWh/toe toe_to_MWh = 11.630 @@ -1464,6 +1464,7 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake("build_industry_sector_ratios") + set_scenario_config(snakemake) # TODO make params option year = 2015 diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index cb63c27e..db548140 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -14,6 +14,8 @@ import numpy as np import pandas as pd import xarray as xr +from _helpers import configure_logging, set_scenario_config + logger = logging.getLogger(__name__) if __name__ == "__main__": @@ -22,7 +24,8 @@ if __name__ == "__main__": snakemake = mock_snakemake("build_population_layouts") - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) cutout = atlite.Cutout(snakemake.input.cutout) diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 879e3b9b..6ed32086 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -8,6 +8,8 @@ Distribute country-level energy demands by population. import pandas as pd +from _helpers import set_scenario_config + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -17,6 +19,7 @@ if __name__ == "__main__": simpl="", clusters=48, ) + set_scenario_config(snakemake) pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) diff --git a/scripts/build_retro_cost.py b/scripts/build_retro_cost.py index 60d74afa..b6153a2d 100755 --- a/scripts/build_retro_cost.py +++ b/scripts/build_retro_cost.py @@ -68,6 +68,7 @@ The script has the following structure: """ import pandas as pd import xarray as xr +from _helpers import set_scenario_config # (i) --- FIXED PARAMETER / STANDARD VALUES ----------------------------------- @@ -1053,6 +1054,7 @@ if __name__ == "__main__": ll="v1.0", sector_opts="Co2L0-168H-T-H-B-I-solar3-dist1", ) + set_scenario_config(snakemake) # ******** config ********************************************************* diff --git a/scripts/build_salt_cavern_potentials.py b/scripts/build_salt_cavern_potentials.py index ed039772..08071b22 100644 --- a/scripts/build_salt_cavern_potentials.py +++ b/scripts/build_salt_cavern_potentials.py @@ -24,6 +24,7 @@ onshore (>50km from sea), offshore (Figure 7). import geopandas as gpd import pandas as pd +from _helpers import set_scenario_config def concat_gdf(gdf_list, crs="EPSG:4326"): @@ -77,6 +78,8 @@ if __name__ == "__main__": "build_salt_cavern_potentials", simpl="", clusters="37" ) + set_scenario_config(snakemake) + fn_onshore = snakemake.input.regions_onshore fn_offshore = snakemake.input.regions_offshore diff --git a/scripts/build_sequestration_potentials.py b/scripts/build_sequestration_potentials.py index f6ad3526..9e7678bb 100644 --- a/scripts/build_sequestration_potentials.py +++ b/scripts/build_sequestration_potentials.py @@ -11,6 +11,8 @@ database_en>`_. import geopandas as gpd import pandas as pd +from _helpers import set_scenario_config + def area(gdf): """ @@ -39,6 +41,8 @@ if __name__ == "__main__": "build_sequestration_potentials", simpl="", clusters="181" ) + set_scenario_config(snakemake) + cf = snakemake.params.sequestration_potential gdf = gpd.read_file(snakemake.input.sequestration_potential[0]) diff --git a/scripts/build_shipping_demand.py b/scripts/build_shipping_demand.py index 8000c66c..0690e33d 100644 --- a/scripts/build_shipping_demand.py +++ b/scripts/build_shipping_demand.py @@ -11,6 +11,7 @@ import json import geopandas as gpd import pandas as pd +from _helpers import set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): @@ -21,6 +22,7 @@ if __name__ == "__main__": simpl="", clusters=48, ) + set_scenario_config(snakemake) scope = gpd.read_file(snakemake.input.scope).geometry[0] regions = gpd.read_file(snakemake.input.regions).set_index("name") diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index ee6ed881..12826420 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -13,6 +13,8 @@ import pandas as pd import xarray as xr from dask.distributed import Client, LocalCluster +from _helpers import set_scenario_config + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -22,6 +24,7 @@ if __name__ == "__main__": simpl="", clusters=48, ) + set_scenario_config(snakemake) nprocesses = int(snakemake.threads) cluster = LocalCluster(n_workers=nprocesses, threads_per_worker=1) diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index 02fa4a71..878ebc03 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -12,6 +12,7 @@ import numpy as np import pandas as pd import xarray as xr from dask.distributed import Client, LocalCluster +from _helpers import set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): @@ -22,6 +23,7 @@ if __name__ == "__main__": simpl="", clusters=48, ) + set_scenario_config(snakemake) nprocesses = int(snakemake.threads) cluster = LocalCluster(n_workers=nprocesses, threads_per_worker=1) diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index 33c8faae..671357dd 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -13,7 +13,7 @@ import logging import numpy as np import pandas as pd import xarray as xr -from _helpers import configure_logging, generate_periodic_profiles +from _helpers import configure_logging, generate_periodic_profiles, set_scenario_config logger = logging.getLogger(__name__) @@ -171,6 +171,7 @@ if __name__ == "__main__": clusters=48, ) configure_logging(snakemake) + set_scenario_config(snakemake) pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) diff --git a/scripts/cluster_gas_network.py b/scripts/cluster_gas_network.py index e709d772..567f4458 100755 --- a/scripts/cluster_gas_network.py +++ b/scripts/cluster_gas_network.py @@ -12,6 +12,7 @@ import geopandas as gpd import pandas as pd from pypsa.geo import haversine_pts from shapely import wkt +from _helpers import set_scenario_config, configure_logging logger = logging.getLogger(__name__) @@ -105,8 +106,8 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake("cluster_gas_network", simpl="", clusters="37") - - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) fn = snakemake.input.cleaned_gas_network df = pd.read_csv(fn, index_col=0) diff --git a/scripts/determine_availability_matrix_MD_UA.py b/scripts/determine_availability_matrix_MD_UA.py index efe9a712..84076383 100644 --- a/scripts/determine_availability_matrix_MD_UA.py +++ b/scripts/determine_availability_matrix_MD_UA.py @@ -15,7 +15,7 @@ import fiona import geopandas as gpd import matplotlib.pyplot as plt import numpy as np -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from atlite.gis import shape_availability from rasterio.plot import show @@ -38,6 +38,7 @@ if __name__ == "__main__": "determine_availability_matrix_MD_UA", technology="solar" ) configure_logging(snakemake) + set_scenario_config(snakemake) nprocesses = None # snakemake.config["atlite"].get("nprocesses") noprogress = not snakemake.config["atlite"].get("show_progress", True) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 76d8099c..82ce2328 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -14,6 +14,7 @@ import numpy as np import pandas as pd import pypsa from prepare_sector_network import prepare_costs +from _helpers import set_scenario_config, configure_logging idx = pd.IndexSlice logger = logging.getLogger(__name__) @@ -673,7 +674,8 @@ if __name__ == "__main__": snakemake = mock_snakemake("make_summary") - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) networks_dict = { (cluster, ll, opt + sector_opt, planning_horizon): "results/" diff --git a/scripts/make_summary_perfect.py b/scripts/make_summary_perfect.py index 064db454..7c2e8d30 100644 --- a/scripts/make_summary_perfect.py +++ b/scripts/make_summary_perfect.py @@ -19,6 +19,7 @@ from make_summary import assign_carriers, assign_locations from prepare_sector_network import prepare_costs from pypsa.descriptors import get_active_assets from six import iteritems +from _helpers import set_scenario_config idx = pd.IndexSlice @@ -722,6 +723,7 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake("make_summary_perfect") + set_scenario_config(snakemake) run = snakemake.config["run"]["name"] if run != "": diff --git a/scripts/plot_gas_network.py b/scripts/plot_gas_network.py index e2953604..26186d51 100644 --- a/scripts/plot_gas_network.py +++ b/scripts/plot_gas_network.py @@ -13,7 +13,7 @@ import geopandas as gpd import matplotlib.pyplot as plt import pandas as pd import pypsa -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from plot_power_network import assign_location, load_projection from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches @@ -237,6 +237,7 @@ if __name__ == "__main__": ) configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.network) diff --git a/scripts/plot_hydrogen_network.py b/scripts/plot_hydrogen_network.py index 95741170..4cb58557 100644 --- a/scripts/plot_hydrogen_network.py +++ b/scripts/plot_hydrogen_network.py @@ -13,7 +13,7 @@ import geopandas as gpd import matplotlib.pyplot as plt import pandas as pd import pypsa -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from plot_power_network import assign_location, load_projection from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches @@ -254,6 +254,7 @@ if __name__ == "__main__": ) configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.network) diff --git a/scripts/plot_power_network.py b/scripts/plot_power_network.py index 0e13e497..6db53bcc 100644 --- a/scripts/plot_power_network.py +++ b/scripts/plot_power_network.py @@ -14,7 +14,7 @@ import geopandas as gpd import matplotlib.pyplot as plt import pandas as pd import pypsa -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from plot_summary import preferred_order, rename_techs from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches @@ -257,6 +257,7 @@ if __name__ == "__main__": ) configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.network) diff --git a/scripts/plot_power_network_clustered.py b/scripts/plot_power_network_clustered.py index 8217ac2e..43746039 100644 --- a/scripts/plot_power_network_clustered.py +++ b/scripts/plot_power_network_clustered.py @@ -6,13 +6,13 @@ Plot clustered electricity transmission network. """ -import cartopy.crs as ccrs import geopandas as gpd import matplotlib.pyplot as plt import pypsa from matplotlib.lines import Line2D from plot_power_network import load_projection from pypsa.plot import add_legend_lines +from _helpers import set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): @@ -23,6 +23,7 @@ if __name__ == "__main__": clusters=128, configfiles=["../../config/config.test.yaml"], ) + set_scenario_config(snakemake) lw_factor = 2e3 diff --git a/scripts/plot_power_network_perfect.py b/scripts/plot_power_network_perfect.py index ff576d33..f7506a00 100644 --- a/scripts/plot_power_network_perfect.py +++ b/scripts/plot_power_network_perfect.py @@ -13,7 +13,7 @@ import geopandas as gpd import matplotlib.pyplot as plt import pandas as pd import pypsa -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config from plot_power_network import assign_location, load_projection, rename_techs_tyndp from plot_summary import preferred_order from pypsa.plot import add_legend_circles, add_legend_lines @@ -184,6 +184,7 @@ if __name__ == "__main__": ) configure_logging(snakemake) + set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.network) diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index cfb32441..da077348 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -12,6 +12,7 @@ import matplotlib.gridspec as gridspec import matplotlib.pyplot as plt import pandas as pd from prepare_sector_network import co2_emissions_year +from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) plt.style.use("ggplot") @@ -572,7 +573,8 @@ if __name__ == "__main__": snakemake = mock_snakemake("plot_summary") - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) + set_scenario_config(snakemake) n_header = 4 diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index cf013577..de9932fd 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -12,7 +12,7 @@ import re import numpy as np import pandas as pd import pypsa -from _helpers import update_config_with_sector_opts +from _helpers import update_config_with_sector_opts, set_scenario_config, configure_logging from add_existing_baseyear import add_build_year_to_new_assets from pypsa.descriptors import expand_series from pypsa.io import import_components_from_dataframe @@ -514,6 +514,8 @@ if __name__ == "__main__": ll="v1.5", sector_opts="1p7-4380H-T-H-B-I-A-dist1", ) + configure_logging(snakemake) + set_scenario_config(snakemake) update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) # parameters ----------------------------------------------------------- diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index b1161c19..bf9ed58f 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -18,7 +18,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import set_scenario_config, update_config_with_sector_opts +from _helpers import configure_logging, set_scenario_config, update_config_with_sector_opts from add_electricity import calculate_annuity, sanitize_carriers, sanitize_locations from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement @@ -3572,7 +3572,7 @@ if __name__ == "__main__": planning_horizons="2030", ) - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) set_scenario_config(snakemake) update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) diff --git a/scripts/retrieve_databundle.py b/scripts/retrieve_databundle.py index 25894063..b6a4d378 100644 --- a/scripts/retrieve_databundle.py +++ b/scripts/retrieve_databundle.py @@ -36,7 +36,7 @@ import logging import tarfile from pathlib import Path -from _helpers import configure_logging, progress_retrieve, validate_checksum +from _helpers import configure_logging, progress_retrieve, validate_checksum, set_scenario_config logger = logging.getLogger(__name__) @@ -49,9 +49,8 @@ if __name__ == "__main__": rootpath = ".." else: rootpath = "." - configure_logging( - snakemake - ) # TODO Make logging compatible with progressbar (see PR #102) + configure_logging(snakemake) + set_scenario_config(snakemake) if snakemake.config["tutorial"]: url = "https://zenodo.org/record/3517921/files/pypsa-eur-tutorial-data-bundle.tar.xz" diff --git a/scripts/retrieve_electricity_demand.py b/scripts/retrieve_electricity_demand.py index a8a44b68..94077fdf 100644 --- a/scripts/retrieve_electricity_demand.py +++ b/scripts/retrieve_electricity_demand.py @@ -12,7 +12,7 @@ import pandas as pd logger = logging.getLogger(__name__) -from _helpers import configure_logging +from _helpers import configure_logging, set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): @@ -23,6 +23,7 @@ if __name__ == "__main__": else: rootpath = "." configure_logging(snakemake) + set_scenario_config(snakemake) url = "https://data.open-power-system-data.org/time_series/{version}/time_series_60min_singleindex.csv" diff --git a/scripts/retrieve_gas_infrastructure_data.py b/scripts/retrieve_gas_infrastructure_data.py index d984b9fe..7cc1c270 100644 --- a/scripts/retrieve_gas_infrastructure_data.py +++ b/scripts/retrieve_gas_infrastructure_data.py @@ -11,7 +11,7 @@ import logging import zipfile from pathlib import Path -from _helpers import progress_retrieve, validate_checksum +from _helpers import progress_retrieve, validate_checksum, set_scenario_config, configure_logging logger = logging.getLogger(__name__) @@ -24,6 +24,8 @@ if __name__ == "__main__": rootpath = ".." else: rootpath = "." + configure_logging(snakemake) + set_scenario_config(snakemake) url = "https://zenodo.org/record/4767098/files/IGGIELGN.zip" diff --git a/scripts/retrieve_irena.py b/scripts/retrieve_irena.py index 7b123475..dbd11129 100644 --- a/scripts/retrieve_irena.py +++ b/scripts/retrieve_irena.py @@ -26,7 +26,7 @@ This rule downloads the existing capacities from `IRENASTAT Date: Mon, 12 Feb 2024 11:53:37 +0100 Subject: [PATCH 282/591] do not use config_provider outside rule definitions --- rules/postprocess.smk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index cf0ef6cd..38e5f7d9 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -7,7 +7,7 @@ localrules: copy_config, -if config_provider("foresight") != "perfect": +if config["foresight"] != "perfect": rule plot_power_network_clustered: params: @@ -109,7 +109,7 @@ if config_provider("foresight") != "perfect": "../scripts/plot_gas_network.py" -if config_provider("foresight") == "perfect": +if config["foresight"] == "perfect": rule plot_power_network_perfect: params: From e0b6ebd174a9f5f55bb462c8650e0754a1121a9d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:54:13 +0000 Subject: [PATCH 283/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/add_brownfield.py | 6 +++++- scripts/add_existing_baseyear.py | 6 +++++- scripts/build_ammonia_production.py | 1 - scripts/build_biomass_potentials.py | 2 +- scripts/build_clustered_population_layouts.py | 1 - scripts/build_cop_profiles.py | 1 - scripts/build_daily_heat_demand.py | 2 +- scripts/build_district_heat_share.py | 2 +- scripts/build_energy_totals.py | 2 +- scripts/build_gas_input_locations.py | 2 +- scripts/build_gas_network.py | 2 +- scripts/build_industrial_distribution_key.py | 1 - .../build_industrial_energy_demand_per_country_today.py | 2 +- scripts/build_industrial_energy_demand_per_node.py | 1 - scripts/build_industrial_energy_demand_per_node_today.py | 1 - scripts/build_industrial_production_per_country.py | 2 +- .../build_industrial_production_per_country_tomorrow.py | 3 +-- scripts/build_industrial_production_per_node.py | 2 +- scripts/build_population_layouts.py | 1 - scripts/build_population_weighted_energy_totals.py | 1 - scripts/build_sequestration_potentials.py | 1 - scripts/build_solar_thermal_profiles.py | 3 +-- scripts/build_temperature_profiles.py | 2 +- scripts/cluster_gas_network.py | 2 +- scripts/make_summary.py | 2 +- scripts/make_summary_perfect.py | 2 +- scripts/plot_power_network_clustered.py | 2 +- scripts/plot_summary.py | 2 +- scripts/prepare_perfect_foresight.py | 6 +++++- scripts/prepare_sector_network.py | 6 +++++- scripts/retrieve_databundle.py | 7 ++++++- scripts/retrieve_gas_infrastructure_data.py | 7 ++++++- 32 files changed, 49 insertions(+), 34 deletions(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index b0727b17..d45742dd 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -12,7 +12,11 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import update_config_with_sector_opts, configure_logging, set_scenario_config +from _helpers import ( + configure_logging, + set_scenario_config, + update_config_with_sector_opts, +) from add_existing_baseyear import add_build_year_to_new_assets from pypsa.clustering.spatial import normed_or_uniform diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 25e35edd..780460a2 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -15,7 +15,11 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import update_config_with_sector_opts, set_scenario_config, configure_logging +from _helpers import ( + configure_logging, + set_scenario_config, + update_config_with_sector_opts, +) from add_electricity import sanitize_carriers from prepare_sector_network import cluster_heat_buses, define_spatial, prepare_costs diff --git a/scripts/build_ammonia_production.py b/scripts/build_ammonia_production.py index 47907cc9..a9cd907a 100644 --- a/scripts/build_ammonia_production.py +++ b/scripts/build_ammonia_production.py @@ -8,7 +8,6 @@ Build historical annual ammonia production per country in ktonNH3/a. import country_converter as coco import pandas as pd - from _helpers import set_scenario_config cc = coco.CountryConverter() diff --git a/scripts/build_biomass_potentials.py b/scripts/build_biomass_potentials.py index 2fe6922c..6291b03e 100644 --- a/scripts/build_biomass_potentials.py +++ b/scripts/build_biomass_potentials.py @@ -222,7 +222,7 @@ if __name__ == "__main__": clusters="5", planning_horizons=2050, ) - + configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index 4217baff..c923abf9 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -11,7 +11,6 @@ import atlite import geopandas as gpd import pandas as pd import xarray as xr - from _helpers import set_scenario_config if __name__ == "__main__": diff --git a/scripts/build_cop_profiles.py b/scripts/build_cop_profiles.py index ee68dd0a..54eac3a3 100644 --- a/scripts/build_cop_profiles.py +++ b/scripts/build_cop_profiles.py @@ -14,7 +14,6 @@ https://doi.org/10.1039/C2EE22653G. """ import xarray as xr - from _helpers import set_scenario_config diff --git a/scripts/build_daily_heat_demand.py b/scripts/build_daily_heat_demand.py index 03ba8c2e..4f1a3303 100644 --- a/scripts/build_daily_heat_demand.py +++ b/scripts/build_daily_heat_demand.py @@ -11,8 +11,8 @@ import geopandas as gpd import numpy as np import pandas as pd import xarray as xr -from dask.distributed import Client, LocalCluster from _helpers import set_scenario_config +from dask.distributed import Client, LocalCluster if __name__ == "__main__": if "snakemake" not in globals(): diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index 121e4663..46ada2f6 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -9,8 +9,8 @@ Build district heat shares at each node, depending on investment year. import logging import pandas as pd -from prepare_sector_network import get from _helpers import configure_logging, set_scenario_config +from prepare_sector_network import get logger = logging.getLogger(__name__) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index f22ddc25..2b4ebd19 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -14,7 +14,7 @@ import country_converter as coco import geopandas as gpd import numpy as np import pandas as pd -from _helpers import mute_print, configure_logging, set_scenario_config +from _helpers import configure_logging, mute_print, set_scenario_config from tqdm import tqdm cc = coco.CountryConverter() diff --git a/scripts/build_gas_input_locations.py b/scripts/build_gas_input_locations.py index 5aba46e5..b0aadce8 100644 --- a/scripts/build_gas_input_locations.py +++ b/scripts/build_gas_input_locations.py @@ -11,8 +11,8 @@ import logging import geopandas as gpd import pandas as pd -from cluster_gas_network import load_bus_regions from _helpers import configure_logging, set_scenario_config +from cluster_gas_network import load_bus_regions logger = logging.getLogger(__name__) diff --git a/scripts/build_gas_network.py b/scripts/build_gas_network.py index 0febd43d..52235cd1 100644 --- a/scripts/build_gas_network.py +++ b/scripts/build_gas_network.py @@ -11,9 +11,9 @@ import logging import geopandas as gpd import pandas as pd +from _helpers import configure_logging, set_scenario_config from pypsa.geo import haversine_pts from shapely.geometry import Point -from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index 29b7538e..90687b33 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -13,7 +13,6 @@ from itertools import product import country_converter as coco import geopandas as gpd import pandas as pd - from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) diff --git a/scripts/build_industrial_energy_demand_per_country_today.py b/scripts/build_industrial_energy_demand_per_country_today.py index 99342b9e..1ccae6c2 100644 --- a/scripts/build_industrial_energy_demand_per_country_today.py +++ b/scripts/build_industrial_energy_demand_per_country_today.py @@ -11,8 +11,8 @@ from functools import partial import country_converter as coco import pandas as pd -from tqdm import tqdm from _helpers import set_scenario_config +from tqdm import tqdm cc = coco.CountryConverter() diff --git a/scripts/build_industrial_energy_demand_per_node.py b/scripts/build_industrial_energy_demand_per_node.py index fcc0abd9..42df4250 100644 --- a/scripts/build_industrial_energy_demand_per_node.py +++ b/scripts/build_industrial_energy_demand_per_node.py @@ -7,7 +7,6 @@ Build industrial energy demand per model region. """ import pandas as pd - from _helpers import set_scenario_config if __name__ == "__main__": diff --git a/scripts/build_industrial_energy_demand_per_node_today.py b/scripts/build_industrial_energy_demand_per_node_today.py index 1b7aba83..ce8d971f 100644 --- a/scripts/build_industrial_energy_demand_per_node_today.py +++ b/scripts/build_industrial_energy_demand_per_node_today.py @@ -10,7 +10,6 @@ from itertools import product import numpy as np import pandas as pd - from _helpers import set_scenario_config # map JRC/our sectors to hotmaps sector, where mapping exist diff --git a/scripts/build_industrial_production_per_country.py b/scripts/build_industrial_production_per_country.py index d9ec9afd..44cb0752 100644 --- a/scripts/build_industrial_production_per_country.py +++ b/scripts/build_industrial_production_per_country.py @@ -13,7 +13,7 @@ from functools import partial import country_converter as coco import numpy as np import pandas as pd -from _helpers import mute_print, set_scenario_config, configure_logging +from _helpers import configure_logging, mute_print, set_scenario_config from tqdm import tqdm logger = logging.getLogger(__name__) diff --git a/scripts/build_industrial_production_per_country_tomorrow.py b/scripts/build_industrial_production_per_country_tomorrow.py index 835a2687..67557b17 100644 --- a/scripts/build_industrial_production_per_country_tomorrow.py +++ b/scripts/build_industrial_production_per_country_tomorrow.py @@ -7,9 +7,8 @@ Build future industrial production per country. """ import pandas as pd -from prepare_sector_network import get - from _helpers import set_scenario_config +from prepare_sector_network import get if __name__ == "__main__": if "snakemake" not in globals(): diff --git a/scripts/build_industrial_production_per_node.py b/scripts/build_industrial_production_per_node.py index c84590b7..7e074967 100644 --- a/scripts/build_industrial_production_per_node.py +++ b/scripts/build_industrial_production_per_node.py @@ -7,9 +7,9 @@ Build industrial production per model region. """ from itertools import product -from _helpers import set_scenario_config import pandas as pd +from _helpers import set_scenario_config # map JRC/our sectors to hotmaps sector, where mapping exist sector_mapping = { diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index db548140..bab2e9a4 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -13,7 +13,6 @@ import geopandas as gpd import numpy as np import pandas as pd import xarray as xr - from _helpers import configure_logging, set_scenario_config logger = logging.getLogger(__name__) diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 6ed32086..60d66e56 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -7,7 +7,6 @@ Distribute country-level energy demands by population. """ import pandas as pd - from _helpers import set_scenario_config if __name__ == "__main__": diff --git a/scripts/build_sequestration_potentials.py b/scripts/build_sequestration_potentials.py index 9e7678bb..ac1f22e2 100644 --- a/scripts/build_sequestration_potentials.py +++ b/scripts/build_sequestration_potentials.py @@ -10,7 +10,6 @@ database_en>`_. import geopandas as gpd import pandas as pd - from _helpers import set_scenario_config diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index 12826420..eb4c6f8f 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -11,9 +11,8 @@ import geopandas as gpd import numpy as np import pandas as pd import xarray as xr -from dask.distributed import Client, LocalCluster - from _helpers import set_scenario_config +from dask.distributed import Client, LocalCluster if __name__ == "__main__": if "snakemake" not in globals(): diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index 878ebc03..eb005d3d 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -11,8 +11,8 @@ import geopandas as gpd import numpy as np import pandas as pd import xarray as xr -from dask.distributed import Client, LocalCluster from _helpers import set_scenario_config +from dask.distributed import Client, LocalCluster if __name__ == "__main__": if "snakemake" not in globals(): diff --git a/scripts/cluster_gas_network.py b/scripts/cluster_gas_network.py index 567f4458..1292cdc3 100755 --- a/scripts/cluster_gas_network.py +++ b/scripts/cluster_gas_network.py @@ -10,9 +10,9 @@ import logging import geopandas as gpd import pandas as pd +from _helpers import configure_logging, set_scenario_config from pypsa.geo import haversine_pts from shapely import wkt -from _helpers import set_scenario_config, configure_logging logger = logging.getLogger(__name__) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 82ce2328..2dac717a 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -13,8 +13,8 @@ import sys import numpy as np import pandas as pd import pypsa +from _helpers import configure_logging, set_scenario_config from prepare_sector_network import prepare_costs -from _helpers import set_scenario_config, configure_logging idx = pd.IndexSlice logger = logging.getLogger(__name__) diff --git a/scripts/make_summary_perfect.py b/scripts/make_summary_perfect.py index 7c2e8d30..4a0b1556 100644 --- a/scripts/make_summary_perfect.py +++ b/scripts/make_summary_perfect.py @@ -12,6 +12,7 @@ other metrics. import numpy as np import pandas as pd import pypsa +from _helpers import set_scenario_config from make_summary import calculate_cfs # noqa: F401 from make_summary import calculate_nodal_cfs # noqa: F401 from make_summary import calculate_nodal_costs # noqa: F401 @@ -19,7 +20,6 @@ from make_summary import assign_carriers, assign_locations from prepare_sector_network import prepare_costs from pypsa.descriptors import get_active_assets from six import iteritems -from _helpers import set_scenario_config idx = pd.IndexSlice diff --git a/scripts/plot_power_network_clustered.py b/scripts/plot_power_network_clustered.py index 43746039..0c3dc635 100644 --- a/scripts/plot_power_network_clustered.py +++ b/scripts/plot_power_network_clustered.py @@ -9,10 +9,10 @@ Plot clustered electricity transmission network. import geopandas as gpd import matplotlib.pyplot as plt import pypsa +from _helpers import set_scenario_config from matplotlib.lines import Line2D from plot_power_network import load_projection from pypsa.plot import add_legend_lines -from _helpers import set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index da077348..addb87ef 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -11,8 +11,8 @@ import logging import matplotlib.gridspec as gridspec import matplotlib.pyplot as plt import pandas as pd -from prepare_sector_network import co2_emissions_year from _helpers import configure_logging, set_scenario_config +from prepare_sector_network import co2_emissions_year logger = logging.getLogger(__name__) plt.style.use("ggplot") diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index de9932fd..97e5eeeb 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -12,7 +12,11 @@ import re import numpy as np import pandas as pd import pypsa -from _helpers import update_config_with_sector_opts, set_scenario_config, configure_logging +from _helpers import ( + configure_logging, + set_scenario_config, + update_config_with_sector_opts, +) from add_existing_baseyear import add_build_year_to_new_assets from pypsa.descriptors import expand_series from pypsa.io import import_components_from_dataframe diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index bf9ed58f..90df5c93 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -18,7 +18,11 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import configure_logging, set_scenario_config, update_config_with_sector_opts +from _helpers import ( + configure_logging, + set_scenario_config, + update_config_with_sector_opts, +) from add_electricity import calculate_annuity, sanitize_carriers, sanitize_locations from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement diff --git a/scripts/retrieve_databundle.py b/scripts/retrieve_databundle.py index b6a4d378..1d217a43 100644 --- a/scripts/retrieve_databundle.py +++ b/scripts/retrieve_databundle.py @@ -36,7 +36,12 @@ import logging import tarfile from pathlib import Path -from _helpers import configure_logging, progress_retrieve, validate_checksum, set_scenario_config +from _helpers import ( + configure_logging, + progress_retrieve, + set_scenario_config, + validate_checksum, +) logger = logging.getLogger(__name__) diff --git a/scripts/retrieve_gas_infrastructure_data.py b/scripts/retrieve_gas_infrastructure_data.py index 7cc1c270..64bd6dc2 100644 --- a/scripts/retrieve_gas_infrastructure_data.py +++ b/scripts/retrieve_gas_infrastructure_data.py @@ -11,7 +11,12 @@ import logging import zipfile from pathlib import Path -from _helpers import progress_retrieve, validate_checksum, set_scenario_config, configure_logging +from _helpers import ( + configure_logging, + progress_retrieve, + set_scenario_config, + validate_checksum, +) logger = logging.getLogger(__name__) From fe143ff8fef243d0fb78e420ee7a8274aac02b39 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 12:10:05 +0100 Subject: [PATCH 284/591] use default config as base configuration --- Snakefile | 11 +++-------- config/config.yaml | 7 +++++++ doc/configuration.rst | 2 +- doc/installation.rst | 13 ++++--------- doc/introduction.rst | 2 +- doc/release_notes.rst | 5 +++++ 6 files changed, 21 insertions(+), 19 deletions(-) create mode 100644 config/config.yaml diff --git a/Snakefile b/Snakefile index 8391156c..ba60cbc9 100644 --- a/Snakefile +++ b/Snakefile @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: MIT -from os.path import normpath, exists -from shutil import copyfile, move, rmtree +from os.path import normpath +from shutil import move, rmtree from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider @@ -13,12 +13,7 @@ from snakemake.utils import min_version min_version("7.7") -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.default.yaml" configfile: "config/config.yaml" diff --git a/config/config.yaml b/config/config.yaml new file mode 100644 index 00000000..6fa1862c --- /dev/null +++ b/config/config.yaml @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: : 2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: CC0-1.0 +# add your own configuration overrides here, for instance + +# enable: +# retrieve: false \ No newline at end of file diff --git a/doc/configuration.rst b/doc/configuration.rst index 92ed269b..f65aa4c2 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -9,7 +9,7 @@ Configuration ########################################## -PyPSA-Eur has several configuration options which are documented in this section and are collected in a ``config/config.yaml`` file located in the root directory. Users should copy the provided default configuration (``config/config.default.yaml``) and amend their own modifications and assumptions in the user-specific configuration file (``config/config.yaml``); confer installation instructions at :ref:`defaultconfig`. +PyPSA-Eur has several configuration options which are documented in this section and are collected in a ``config/config.yaml`` file. This file defines deviations from the default configuration (``config/config.default.yaml``); confer installation instructions at :ref:`defaultconfig`. .. _toplevel_cf: diff --git a/doc/installation.rst b/doc/installation.rst index 01fdafeb..d2fdfb4e 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -118,11 +118,10 @@ Nevertheless, you can still use open-source solvers for smaller problems. Handling Configuration Files ============================ -PyPSA-Eur has several configuration options that must be specified in a -``config/config.yaml`` file located in the root directory. An example configuration -``config/config.default.yaml`` is maintained in the repository, which will be used to -automatically create your customisable ``config/config.yaml`` on first use. More -details on the configuration options are in :ref:`config`. +PyPSA-Eur has several configuration options that users can specify in a +``config/config.yaml`` file. The default configuration +``config/config.default.yaml`` is maintained in the repository. More details on +the configuration options are in :ref:`config`. You can also use ``snakemake`` to specify another file, e.g. ``config/config.mymodifications.yaml``, to update the settings of the ``config/config.yaml``. @@ -131,7 +130,3 @@ You can also use ``snakemake`` to specify another file, e.g. .../pypsa-eur % snakemake -call --configfile config/config.mymodifications.yaml -.. warning:: - Users are advised to regularly check their own ``config/config.yaml`` against changes - in the ``config/config.default.yaml`` when pulling a new version from the remote - repository. diff --git a/doc/introduction.rst b/doc/introduction.rst index 413db9d1..0047f0a7 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -74,7 +74,7 @@ what data to retrieve and what files to produce. Details are explained in :ref:`wildcards` and :ref:`scenario`. The model also has several further configuration options collected in the -``config/config.yaml`` file located in the root directory, which that are not part of +``config/config.default.yaml`` file located in the root directory, which that are not part of the scenarios. Options are explained in :ref:`config`. Folder Structure diff --git a/doc/release_notes.rst b/doc/release_notes.rst index fce4ae1b..cab8229a 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,11 @@ Release Notes Upcoming Release ================ +* The default configuration ``config/config.default.yaml`` is now automatically + used as a base configuration file and no longer copied to + ``config/config.yaml`` on first use. The file ``config/config.yaml`` should be + used to define deviations from the default configuration. + * Merged two OPSD time series data versions into such that the option ``load: power_statistics:`` becomes superfluous and was hence removed. From abe06a68fbc28c3d71c459eb66ed7daf5b8d42b0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:11:02 +0000 Subject: [PATCH 285/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- Snakefile | 1 + config/config.yaml | 2 +- doc/installation.rst | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Snakefile b/Snakefile index ba60cbc9..ee24841a 100644 --- a/Snakefile +++ b/Snakefile @@ -13,6 +13,7 @@ from snakemake.utils import min_version min_version("7.7") + configfile: "config/config.default.yaml" configfile: "config/config.yaml" diff --git a/config/config.yaml b/config/config.yaml index 6fa1862c..6b8bdd77 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -4,4 +4,4 @@ # add your own configuration overrides here, for instance # enable: -# retrieve: false \ No newline at end of file +# retrieve: false diff --git a/doc/installation.rst b/doc/installation.rst index d2fdfb4e..4289b098 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -129,4 +129,3 @@ You can also use ``snakemake`` to specify another file, e.g. .. code:: bash .../pypsa-eur % snakemake -call --configfile config/config.mymodifications.yaml - From 5840a9aa11378a028504e09edd91322c53b0b2cb Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 12:17:13 +0100 Subject: [PATCH 286/591] remove inefficient _helper.py file search --- rules/common.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/common.smk b/rules/common.smk index 5aa7ae53..4c6cc7c2 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -4,7 +4,7 @@ import os, sys, glob -helper_source_path = [match for match in glob.glob("**/_helpers.py", recursive=True)] +helper_source_path = workflow.source_path("scripts/_helpers.py") for path in helper_source_path: path = os.path.dirname(os.path.abspath(path)) From 1e5163b66bc5cd3d67f3b7b84b7997ebf2d3a5be Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 13:45:42 +0100 Subject: [PATCH 287/591] alternative approach --- rules/common.smk | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/rules/common.smk b/rules/common.smk index 4c6cc7c2..50132f4b 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -4,11 +4,8 @@ import os, sys, glob -helper_source_path = workflow.source_path("scripts/_helpers.py") - -for path in helper_source_path: - path = os.path.dirname(os.path.abspath(path)) - sys.path.insert(0, os.path.abspath(path)) +for path in ["../scripts", "./scripts"]: + sys.path.insert(0, os.path.abspath(path) from _helpers import validate_checksum From fa931cc2b102ebd8a7241e0e0aba8bd8281e1eb5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 13:54:28 +0100 Subject: [PATCH 288/591] alternative approach 2 --- rules/common.smk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/common.smk b/rules/common.smk index 50132f4b..598d3b98 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -4,8 +4,8 @@ import os, sys, glob -for path in ["../scripts", "./scripts"]: - sys.path.insert(0, os.path.abspath(path) +path = workflow.source_path("../scripts/_helpers.py") +sys.path.insert(0, os.path.dirname(path)) from _helpers import validate_checksum From 69e20e344864245039bb392089b9f2645799ba2a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 13:55:32 +0100 Subject: [PATCH 289/591] need at least one entry for config/config.yaml to read as yaml --- config/config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/config.yaml b/config/config.yaml index 6fa1862c..620a695c 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -3,5 +3,6 @@ # SPDX-License-Identifier: CC0-1.0 # add your own configuration overrides here, for instance +version: 0.9.0 # enable: # retrieve: false \ No newline at end of file From f024412301beed2f6a36c9df74b52aaeb13969f5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 16:49:15 +0100 Subject: [PATCH 290/591] simplify test cases --- config/scenarios.yaml | 38 +++++++------------ config/test/config.scenarios.electricity.yaml | 34 +---------------- config/test/scenarios.electricity.yaml | 3 -- 3 files changed, 16 insertions(+), 59 deletions(-) diff --git a/config/scenarios.yaml b/config/scenarios.yaml index c493311f..0eba9d75 100644 --- a/config/scenarios.yaml +++ b/config/scenarios.yaml @@ -11,28 +11,18 @@ # electricity: # renewable_carriers: [wind, solar] # override the list of renewable carriers +normal: + electricity: + renewable_carriers: + - solar + - onwind + - offwind-ac + - offwind-dc + - hydro -network2013: - snapshots: - start: "2013-01-01" - end: "2014-01-01" - inclusive: 'left' - - -network2019: - snapshots: - start: "2019-01-01" - end: "2020-01-01" - inclusive: 'left' - - renewable: - onwind: - cutout: europe-2019-era5 - offwind-ac: - cutout: europe-2019-era5 - offwind-dc: - cutout: europe-2019-era5 - solar: - cutout: europe-2019-era5 - hydro: - cutout: europe-2019-era5 +no-offwind: + electricity: + renewable_carriers: + - solar + - onwind + - hydro diff --git a/config/test/config.scenarios.electricity.yaml b/config/test/config.scenarios.electricity.yaml index 185dcda4..dde138ed 100644 --- a/config/test/config.scenarios.electricity.yaml +++ b/config/test/config.scenarios.electricity.yaml @@ -28,16 +28,10 @@ snapshots: end: "2013-03-08" electricity: - co2limit: 100.e+6 - extendable_carriers: Generator: [OCGT] - StorageUnit: [battery] - Store: [H2] - Link: [H2 pipeline] - - renewable_carriers: [solar, onwind, offwind-ac, offwind-dc] - + StorageUnit: [battery, H2] + Store: [] atlite: default_cutout: be-03-2013-era5 @@ -60,31 +54,7 @@ renewable: solar: cutout: be-03-2013-era5 - -clustering: - exclude_carriers: ["OCGT", "offwind-ac", "coal"] - -lines: - dynamic_line_rating: - activate: true - cutout: be-03-2013-era5 - max_line_rating: 1.3 - - solving: solver: name: glpk options: "glpk-default" - - -plotting: - map: - boundaries: - eu_node_location: - x: -5.5 - y: 46. - costs_max: 1000 - costs_threshold: 0.0000001 - energy_max: - energy_min: - energy_threshold: 0.000001 diff --git a/config/test/scenarios.electricity.yaml b/config/test/scenarios.electricity.yaml index e9893479..962cc91e 100644 --- a/config/test/scenarios.electricity.yaml +++ b/config/test/scenarios.electricity.yaml @@ -6,9 +6,6 @@ test-elec-no-offshore-wind: electricity: renewable_carriers: [solar, onwind] - test-elec-no-onshore-wind: electricity: - extendable_carriers: - Generator: [OCGT] renewable_carriers: [solar, offwind-ac, offwind-dc] From c83db4e84e17a94755ab3fa914553047c1e97365 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 16:54:33 +0100 Subject: [PATCH 291/591] add retrieve_cost_data.py script to handle config_provider and move to resources since dependent on config setting --- Snakefile | 2 +- doc/configtables/sector-opts.csv | 2 +- doc/costs.rst | 4 +-- rules/build_sector.smk | 8 +++--- rules/postprocess.smk | 8 +++--- rules/retrieve.smk | 16 ++++-------- rules/solve_myopic.smk | 6 ++--- rules/solve_perfect.smk | 12 +++------ scripts/retrieve_cost_data.py | 42 ++++++++++++++++++++++++++++++++ 9 files changed, 65 insertions(+), 35 deletions(-) create mode 100644 scripts/retrieve_cost_data.py diff --git a/Snakefile b/Snakefile index 7df61162..4acba0c8 100644 --- a/Snakefile +++ b/Snakefile @@ -22,7 +22,7 @@ if not exists(conf_file) and exists(conf_default_file): configfile: "config/config.yaml" -COSTS = f"data/costs_{config['costs']['year']}.csv" +COSTS = f"resources/costs_{config['costs']['year']}.csv" ATLITE_NPROCESSES = config["atlite"].get("nprocesses", 4) run = config["run"] diff --git a/doc/configtables/sector-opts.csv b/doc/configtables/sector-opts.csv index ea39c3b0..fc9e8c10 100644 --- a/doc/configtables/sector-opts.csv +++ b/doc/configtables/sector-opts.csv @@ -7,5 +7,5 @@ Trigger, Description, Definition, Status ``B``,Add biomass,,In active use ``I``,Add industry sector,,In active use ``A``,Add agriculture sector,,In active use -``dist``+``n``,Add distribution grid with investment costs of ``n`` times costs in ``data/costs_{cost_year}.csv``,,In active use +``dist``+``n``,Add distribution grid with investment costs of ``n`` times costs in ``resources/costs_{cost_year}.csv``,,In active use ``seq``+``n``,Sets the CO2 sequestration potential to ``n`` Mt CO2 per year,,In active use diff --git a/doc/costs.rst b/doc/costs.rst index 5ddbb360..9a06fd16 100644 --- a/doc/costs.rst +++ b/doc/costs.rst @@ -9,7 +9,7 @@ Techno-Economic Assumptions The database of cost assumptions is retrieved from the repository `PyPSA/technology-data `_ and then -saved to a file ``data/costs_{year}.csv``. The ``config/config.yaml`` provides options +saved to a file ``resources/costs_{year}.csv``. The ``config/config.yaml`` provides options to choose a reference year and use a specific version of the repository. .. literalinclude:: ../config/config.default.yaml @@ -50,7 +50,7 @@ Modifying Assumptions Some cost assumptions (e.g. marginal cost and capital cost) can be directly set in the ``config/config.yaml`` (cf. Section :ref:`costs_cf` in :ref:`config`). To change cost assumptions in more detail, make a copy of -``data/costs_{year}.csv`` and reference the new cost file in the ``Snakefile``: +``resources/costs_{year}.csv`` and reference the new cost file in the ``Snakefile``: .. literalinclude:: ../Snakefile :start-at: COSTS diff --git a/rules/build_sector.smk b/rules/build_sector.smk index d7fbe638..62b69337 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -853,10 +853,10 @@ rule prepare_sector_network: "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv" ) ), - costs=( - "data/costs_{}.csv".format(config_provider("costs", "year")) - if config_provider("foresight") == "overnight" - else "data/costs_{planning_horizons}.csv" + costs=lambda w: ( + "resources/costs_{}.csv".format(config_provider("costs", "year")) + if config_provider("foresight")(w) == "overnight" + else "resources/costs_{planning_horizons}.csv" ), profile_offwind_ac=resources("profile_offwind-ac.nc"), profile_offwind_dc=resources("profile_offwind-dc.nc"), diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 38e5f7d9..542c8d29 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -174,10 +174,10 @@ rule make_summary: **config["scenario"], run=config["run"]["name"], ), - costs=( - "data/costs_{}.csv".format(config_provider("costs", "year")) - if config_provider("foresight") == "overnight" - else "data/costs_{}.csv".format( + costs=lambda w: ( + "resources/costs_{}.csv".format(config_provider("costs", "year")) + if config_provider("foresight")(w) == "overnight" + else "resources/costs_{}.csv".format( config_provider("scenario", "planning_horizons", 0) ) ), diff --git a/rules/retrieve.smk b/rules/retrieve.smk index c9fd91aa..1b2513fb 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -83,23 +83,17 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_cutout", True if config["enable"]["retrieve"] and config["enable"].get("retrieve_cost_data", True): rule retrieve_cost_data: - input: - HTTP.remote( - "raw.githubusercontent.com/PyPSA/technology-data/{}/outputs/".format( - config_provider("costs", "version") - ) - + "costs_{year}.csv", - keep_local=True, - ), + params: + version=lambda w: config_provider("costs", "version")(w), output: - "data/costs_{year}.csv", + resources("costs_{year}.csv"), log: "logs/retrieve_cost_data_{year}.log", resources: mem_mb=1000, retries: 2 - run: - move(input[0], output[0]) + script: + "../scripts/retrieve_cost_data.py" if config["enable"]["retrieve"] and config["enable"].get( diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index a6313cac..bea6b6cc 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -16,7 +16,7 @@ rule add_existing_baseyear: busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - costs=lambda w: "data/costs_{}.csv".format( + costs=lambda w: "resources/costs_{}.csv".format( config_provider("scenario", "planning_horizons", 0)(w) ), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), @@ -71,7 +71,7 @@ rule add_brownfield: network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", network_p=solved_previous_horizon, #solved network at previous time step - costs="data/costs_{planning_horizons}.csv", + costs="resources/costs_{planning_horizons}.csv", cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), output: @@ -109,7 +109,7 @@ rule solve_sector_network_myopic: input: network=RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - costs="data/costs_{planning_horizons}.csv", + costs="resources/costs_{planning_horizons}.csv", config=RESULTS + "config.yaml", output: RESULTS diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index ee16a201..d1a5f745 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -14,7 +14,7 @@ rule add_existing_baseyear: busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - costs="data/costs_{}.csv".format( + costs="resources/costs_{}.csv".format( config_provider("scenario", "planning_horizons", 0) ), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), @@ -95,7 +95,7 @@ rule solve_sector_network_perfect: input: network=RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", - costs="data/costs_2030.csv", + costs="resources/costs_2030.csv", config=RESULTS + "config.yaml", output: RESULTS @@ -127,13 +127,7 @@ rule make_summary_perfect: **{ f"networks_{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}": RESULTS + f"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc" - for simpl in config_provider("scenario", "simpl") - for clusters in config_provider("scenario", "clusters") - for opts in config_provider("scenario", "opts") - for sector_opts in config_provider("scenario", "sector_opts") - for ll in config_provider("scenario", "ll") - }, - costs="data/costs_2020.csv", + costs="resources/costs_2020.csv", output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", nodal_capacities=RESULTS + "csvs/nodal_capacities.csv", diff --git a/scripts/retrieve_cost_data.py b/scripts/retrieve_cost_data.py new file mode 100644 index 00000000..ceae8bf9 --- /dev/null +++ b/scripts/retrieve_cost_data.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Retrieve cost data from ``technology-data``. +""" + +import logging +from pathlib import Path + +from _helpers import configure_logging, progress_retrieve, set_scenario_config + +logger = logging.getLogger(__name__) + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake("retrieve_cost_data", year=2030) + rootpath = ".." + else: + rootpath = "." + configure_logging(snakemake) + set_scenario_config(snakemake) + + version = snakemake.params.version + baseurl = f"https://raw.githubusercontent.com/PyPSA/technology-data/{version}/outputs/" + filepath = Path(snakemake.output[0]) + url = baseurl + filepath.name + + print(url) + + to_fn = Path(rootpath) / filepath + + print(to_fn) + + logger.info(f"Downloading technology data from '{url}'.") + disable_progress = snakemake.config["run"].get("disable_progressbar", False) + progress_retrieve(url, to_fn, disable=disable_progress) + + logger.info(f"Technology data available at at {to_fn}") From c3feb0e283d19c7d7c963ed7cb479bb064fe7db5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 12 Feb 2024 16:56:00 +0100 Subject: [PATCH 292/591] handle complicated config-dependent inputs using unpack() with input functions --- Snakefile | 2 + doc/configtables/run.csv | 2 +- rules/build_electricity.smk | 71 +++++---- rules/build_sector.smk | 277 +++++++++++++++++++----------------- rules/common.smk | 8 +- rules/postprocess.smk | 20 +-- rules/solve_myopic.smk | 19 ++- rules/solve_perfect.smk | 31 ++-- rules/validate.smk | 15 +- 9 files changed, 247 insertions(+), 198 deletions(-) diff --git a/Snakefile b/Snakefile index 4acba0c8..826521c1 100644 --- a/Snakefile +++ b/Snakefile @@ -8,6 +8,8 @@ from pathlib import Path import yaml from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider from snakemake.utils import min_version + +# TODO: check if this works with mock_snakemake from scripts._helpers import path_provider min_version("7.7") diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index 75f29928..e2a81e0b 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -2,7 +2,7 @@ name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenario: enable`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenario: file``." scenarios,,, -- enable,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``file``." --- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``config/create_scenarios.py`` script in ``scripts``." +-- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run: scenarios`` has to be set to ``true`` and ``run: name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combination of settings, alter and use the ``config/create_scenarios.py`` script in the ``config`` directory." disable_progrssbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." shared_resources,bool/str/list,,"Switch to select whether resources should be shared across runs. If a string or list is passed, it is assumed to be wildcard(s) which indicates up to which set of wildcards the resource folder should be shared. If set to 'base', only resources before creating the elec.nc file are shared." shared_cutouts,bool,"{true, false}","Switch to select whether cutouts should be shared across runs." diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 4c83e0b0..8876c68e 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -20,8 +20,9 @@ if config["enable"].get("prepare_links_p_nom", False): rule build_electricity_demand: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, countries=config_provider("countries"), load=config_provider("load"), @@ -64,8 +65,9 @@ rule build_powerplants: rule base_network: params: countries=config_provider("countries"), - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, lines=config_provider("lines"), links=config_provider("links"), @@ -177,8 +179,8 @@ if config["enable"].get("build_natura_raster", False): rule build_natura_raster: input: natura=ancient("data/bundle/natura/Natura2000_end2015.shp"), - cutouts=expand( - "cutouts/" + CDIR + "{cutouts}.nc", **config_provider("atlite") + cutouts=lambda w: expand( + "cutouts/" + CDIR + "{cutouts}.nc", **config_provider("atlite")(w) ), output: resources("natura.tiff"), @@ -195,11 +197,11 @@ if config["enable"].get("build_natura_raster", False): rule build_ship_raster: input: ship_density="data/shipdensity_global.zip", - cutouts=expand( + cutouts=lambda w: expand( "cutouts/" + CDIR + "{cutout}.nc", cutout=[ - config_provider("renewable", k, "cutout") - for k in config_provider("electricity", "renewable_carriers") + config_provider("renewable", k, "cutout")(w) + for k in config_provider("electricity", "renewable_carriers")(w) ], ), output: @@ -269,8 +271,9 @@ else: rule build_renewable_profiles: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, renewable=config_provider("renewable"), input: @@ -352,9 +355,9 @@ rule build_hydro_profile: input: country_shapes=resources("country_shapes.geojson"), eia_hydro_generation="data/eia_hydro_annual_generation.csv", - cutout=f"cutouts/" + cutout=lambda w: f"cutouts/" + CDIR - + config_provider("renewable", "hydro", "cutout") + + config_provider("renewable", "hydro", "cutout")(w) + ".nc", output: resources("profile_hydro.nc"), @@ -397,6 +400,23 @@ if config["lines"]["dynamic_line_rating"]["activate"]: "../scripts/build_line_rating.py" +def input_profile_tech(w): + return { + f"profile_{tech}": resources(f"profile_{tech}.nc") + for tech in config_provider("electricity", "renewable_carriers")(w) + } + + +def input_conventional(w): + return { + f"conventional_{carrier}_{attr}": fn + for carrier, d in config_provider("conventional", default={None: {}})(w).items() + if carrier in config_provider("electricity", "conventional_carriers")(w) + for attr, fn in d.items() + if str(fn).startswith("data/") + } + + rule add_electricity: params: length_factor=config_provider("lines", "length_factor"), @@ -407,21 +427,12 @@ rule add_electricity: conventional=config_provider("conventional"), costs=config_provider("costs"), input: - **{ - f"profile_{tech}": resources(f"profile_{tech}.nc") - for tech in config_provider("electricity", "renewable_carriers") - }, - **{ - f"conventional_{carrier}_{attr}": fn - for carrier, d in config.get("conventional", {None: {}}).items() - if carrier in config_provider("electricity", "conventional_carriers") - for attr, fn in d.items() - if str(fn).startswith("data/") - }, + unpack(input_profile_tech), + unpack(input_conventional), base_network=resources("networks/base.nc"), - line_rating=( + line_rating=lambda w: ( resources("networks/line_rating.nc") - if config_provider("lines", "dynamic_line_rating", "activate") + if config_provider("lines", "dynamic_line_rating", "activate")(w) else resources("networks/base.nc") ), tech_costs=COSTS, @@ -430,9 +441,9 @@ rule add_electricity: hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), geth_hydro_capacities="data/geth2015_hydro_capacities.csv", unit_commitment="data/unit_commitment.csv", - fuel_price=( + fuel_price=lambda w: ( resources("monthly_fuel_price.csv") - if config_provider("conventional", "dynamic_fuel_price") + if config_provider("conventional", "dynamic_fuel_price")(w) else [] ), load=resources("electricity_demand.csv"), @@ -509,9 +520,9 @@ rule cluster_network: regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), regions_offshore=resources("regions_offshore_elec_s{simpl}.geojson"), busmap=ancient(resources("busmap_elec_s{simpl}.csv")), - custom_busmap=( + custom_busmap=lambda w: ( "data/custom_busmap_elec_s{simpl}_{clusters}.csv" - if config_provider("enable", "custom_busmap", default=False) + if config_provider("enable", "custom_busmap", default=False)(w) else [] ), tech_costs=COSTS, diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 62b69337..cfd7191e 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -7,7 +7,10 @@ rule build_population_layouts: input: nuts3_shapes=resources("nuts3_shapes.geojson"), urban_percent="data/urban_percent.csv", - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: pop_layout_total=resources("pop_layout_total.nc"), pop_layout_urban=resources("pop_layout_urban.nc"), @@ -31,7 +34,10 @@ rule build_clustered_population_layouts: pop_layout_urban=resources("pop_layout_urban.nc"), pop_layout_rural=resources("pop_layout_rural.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), log: @@ -52,7 +58,10 @@ rule build_simplified_population_layouts: pop_layout_urban=resources("pop_layout_urban.nc"), pop_layout_rural=resources("pop_layout_rural.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: clustered_pop_layout=resources("pop_layout_elec_s{simpl}.csv"), resources: @@ -126,13 +135,17 @@ rule cluster_gas_network: rule build_daily_heat_demand: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: heat_demand=resources("daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), resources: @@ -150,8 +163,9 @@ rule build_daily_heat_demand: rule build_hourly_heat_demand: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, input: heat_profile="data/heat_load_profile_BDEW.csv", @@ -173,13 +187,17 @@ rule build_hourly_heat_demand: rule build_temperature_profiles: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: temp_soil=resources("temp_soil_{scope}_elec_s{simpl}_{clusters}.nc"), temp_air=resources("temp_air_{scope}_elec_s{simpl}_{clusters}.nc"), @@ -227,15 +245,18 @@ rule build_cop_profiles: rule build_solar_thermal_profiles: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, - # TODO use config_provider solar_thermal=config_provider("solar_thermal"), input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: solar_thermal=resources("solar_thermal_{scope}_elec_s{simpl}_{clusters}.nc"), resources: @@ -314,76 +335,54 @@ rule build_biomass_potentials: "../scripts/build_biomass_potentials.py" -if config["sector"]["biomass_transport"] or config["sector"]["biomass_spatial"]: - - rule build_biomass_transport_costs: - input: - transport_cost_data=HTTP.remote( - "publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", - keep_local=True, - ), - output: - biomass_transport_costs=resources("biomass_transport_costs.csv"), - threads: 1 - resources: - mem_mb=1000, - log: - logs("build_biomass_transport_costs.log"), - benchmark: - benchmarks("build_biomass_transport_costs") - conda: - "../envs/environment.yaml" - script: - "../scripts/build_biomass_transport_costs.py" - - build_biomass_transport_costs_output = rules.build_biomass_transport_costs.output +rule build_biomass_transport_costs: + input: + transport_cost_data=HTTP.remote( + "publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", + keep_local=True, + ), + output: + biomass_transport_costs=resources("biomass_transport_costs.csv"), + threads: 1 + resources: + mem_mb=1000, + log: + logs("build_biomass_transport_costs.log"), + benchmark: + benchmarks("build_biomass_transport_costs") + conda: + "../envs/environment.yaml" + script: + "../scripts/build_biomass_transport_costs.py" -if not (config["sector"]["biomass_transport"] or config["sector"]["biomass_spatial"]): - # this is effecively an `else` statement which is however not liked by snakefmt - build_biomass_transport_costs_output = {} - - -if config["sector"]["regional_co2_sequestration_potential"]["enable"]: - - rule build_sequestration_potentials: - params: - sequestration_potential=config_provider( - "sector", "regional_co2_sequestration_potential" - ), - input: - sequestration_potential=HTTP.remote( - "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", - keep_local=True, - ), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}_{clusters}.geojson" - ), - output: - sequestration_potential=resources( - "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv" - ), - threads: 1 - resources: - mem_mb=4000, - log: - logs("build_sequestration_potentials_s{simpl}_{clusters}.log"), - benchmark: - benchmarks("build_sequestration_potentials_s{simpl}_{clusters}") - conda: - "../envs/environment.yaml" - script: - "../scripts/build_sequestration_potentials.py" - - build_sequestration_potentials_output = rules.build_sequestration_potentials.output - - -if not config["sector"]["regional_co2_sequestration_potential"]["enable"]: - # this is effecively an `else` statement which is however not liked by snakefmt - build_sequestration_potentials_output = {} +rule build_sequestration_potentials: + params: + sequestration_potential=config_provider( + "sector", "regional_co2_sequestration_potential" + ), + input: + sequestration_potential=HTTP.remote( + "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", + keep_local=True, + ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), + output: + sequestration_potential=resources( + "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv" + ), + threads: 1 + resources: + mem_mb=4000, + log: + logs("build_sequestration_potentials_s{simpl}_{clusters}.log"), + benchmark: + benchmarks("build_sequestration_potentials_s{simpl}_{clusters}") + conda: + "../envs/environment.yaml" + script: + "../scripts/build_sequestration_potentials.py" rule build_salt_cavern_potentials: @@ -643,43 +642,34 @@ rule build_industrial_energy_demand_per_node_today: "../scripts/build_industrial_energy_demand_per_node_today.py" -if config["sector"]["retrofitting"]["retro_endogen"]: - - rule build_retro_cost: - params: - retrofitting=config_provider("sector", "retrofitting"), - countries=config_provider("countries"), - input: - building_stock="data/retro/data_building_stock.csv", - data_tabula="data/bundle-sector/retro/tabula-calculator-calcsetbuilding.csv", - air_temperature=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), - u_values_PL="data/retro/u_values_poland.csv", - tax_w="data/retro/electricity_taxes_eu.csv", - construction_index="data/retro/comparative_level_investment.csv", - floor_area_missing="data/retro/floor_area_missing.csv", - clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - cost_germany="data/retro/retro_cost_germany.csv", - window_assumptions="data/retro/window_assumptions.csv", - output: - retro_cost=resources("retro_cost_elec_s{simpl}_{clusters}.csv"), - floor_area=resources("floor_area_elec_s{simpl}_{clusters}.csv"), - resources: - mem_mb=1000, - log: - logs("build_retro_cost_s{simpl}_{clusters}.log"), - benchmark: - benchmarks("build_retro_cost/s{simpl}_{clusters}") - conda: - "../envs/environment.yaml" - script: - "../scripts/build_retro_cost.py" - - build_retro_cost_output = rules.build_retro_cost.output - - -if not config["sector"]["retrofitting"]["retro_endogen"]: - # this is effecively an `else` statement which is however not liked by snakefmt - build_retro_cost_output = {} +rule build_retro_cost: + params: + retrofitting=config_provider("sector", "retrofitting"), + countries=config_provider("countries"), + input: + building_stock="data/retro/data_building_stock.csv", + data_tabula="data/bundle-sector/retro/tabula-calculator-calcsetbuilding.csv", + air_temperature=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), + u_values_PL="data/retro/u_values_poland.csv", + tax_w="data/retro/electricity_taxes_eu.csv", + construction_index="data/retro/comparative_level_investment.csv", + floor_area_missing="data/retro/floor_area_missing.csv", + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), + cost_germany="data/retro/retro_cost_germany.csv", + window_assumptions="data/retro/window_assumptions.csv", + output: + retro_cost=resources("retro_cost_elec_s{simpl}_{clusters}.csv"), + floor_area=resources("floor_area_elec_s{simpl}_{clusters}.csv"), + resources: + mem_mb=1000, + log: + logs("build_retro_cost_s{simpl}_{clusters}.log"), + benchmark: + benchmarks("build_retro_cost/s{simpl}_{clusters}") + conda: + "../envs/environment.yaml" + script: + "../scripts/build_retro_cost.py" rule build_population_weighted_energy_totals: @@ -720,8 +710,9 @@ rule build_shipping_demand: rule build_transport_demand: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, sector=config_provider("sector"), input: @@ -825,11 +816,31 @@ rule prepare_sector_network: eurostat_report_year=config_provider("energy", "eurostat_report_year"), RDIR=RDIR, input: - **build_retro_cost_output, - **build_biomass_transport_costs_output, **rules.cluster_gas_network.output, **rules.build_gas_input_locations.output, - **build_sequestration_potentials_output, + retro_cost=lambda w: ( + resources("retro_cost_elec_s{simpl}_{clusters}.csv") + if config_provider("sector", "retrofitting", "retro_endogen")(w) + else [] + ), + floor_area=lambda w: ( + resources("floor_area_elec_s{simpl}_{clusters}.csv") + if config_provider("sector", "retrofitting", "retro_endogen")(w) + else [] + ), + biomass_transport_costs=lambda w: ( + resources("biomass_transport_costs.csv") + if config_provider("sector", "biomass_transport")(w) + or config_provider("sector", "biomass_spatial")(w) + else [] + ), + sequestration_potential=lambda w: ( + resources("co2_sequestration_potential_elec_s{simpl}_{clusters}.csv") + if config_provider( + "sector", "regional_co2_sequestration_potential", "enable" + )(w) + else [] + ), network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), energy_totals_name=resources("energy_totals.csv"), eurostat=input_eurostat, @@ -843,12 +854,12 @@ rule prepare_sector_network: dsm_profile=resources("dsm_profile_s{simpl}_{clusters}.csv"), co2_totals_name=resources("co2_totals.csv"), co2="data/bundle-sector/eea/UNFCCC_v23.csv", - biomass_potentials=( + biomass_potentials=lambda w: ( resources( "biomass_potentials_s{simpl}_{clusters}_" + "{}.csv".format(config_provider("biomass", "year")) ) - if config_provider("foresight") == "overnight" + if config_provider("foresight")(w) == "overnight" else resources( "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv" ) @@ -886,19 +897,19 @@ rule prepare_sector_network: cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), cop_air_rural=resources("cop_air_rural_elec_s{simpl}_{clusters}.nc"), cop_air_urban=resources("cop_air_urban_elec_s{simpl}_{clusters}.nc"), - solar_thermal_total=( + solar_thermal_total=lambda w: ( resources("solar_thermal_total_elec_s{simpl}_{clusters}.nc") - if config_provider("sector", "solar_thermal") + if config_provider("sector", "solar_thermal")(w) else [] ), - solar_thermal_urban=( + solar_thermal_urban=lambda w: ( resources("solar_thermal_urban_elec_s{simpl}_{clusters}.nc") - if config_provider("sector", "solar_thermal") + if config_provider("sector", "solar_thermal")(w) else [] ), - solar_thermal_rural=( + solar_thermal_rural=lambda w: ( resources("solar_thermal_rural_elec_s{simpl}_{clusters}.nc") - if config_provider("sector", "solar_thermal") + if config_provider("sector", "solar_thermal")(w) else [] ), output: diff --git a/rules/common.smk b/rules/common.smk index bf5e0894..c352a3a9 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -78,8 +78,8 @@ def config_provider(*keys, default=None): def solver_threads(w): - solver_options = config_provider("solving", "solver_options") - option_set = config_provider("solving", "solver", "options") + solver_options = config_provider("solving", "solver_options")(w) + option_set = config_provider("solving", "solver", "options")(w) threads = solver_options[option_set].get("threads", 4) return threads @@ -107,7 +107,7 @@ def memory(w): def input_custom_extra_functionality(w): path = config_provider( "solving", "options", "custom_extra_functionality", default=False - ) + )(w) if path: return os.path.join(os.path.dirname(workflow.snakefile), path) return [] @@ -131,7 +131,7 @@ def has_internet_access(url="www.zenodo.org") -> bool: def input_eurostat(w): # 2016 includes BA, 2017 does not - report_year = config_provider("energy", "eurostat_report_year") + report_year = config_provider("energy", "eurostat_report_year")(w) return f"data/bundle-sector/eurostat-energy_balances-june_{report_year}_edition" diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 542c8d29..79634bf6 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -111,6 +111,14 @@ if config["foresight"] != "perfect": if config["foresight"] == "perfect": + def output_map_year(w): + return { + f"map_{year}": RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_" + + f"{year}.pdf" + for year in config_provider("scenario", "planning_horizons")(w) + } + rule plot_power_network_perfect: params: plotting=config_provider("plotting"), @@ -119,12 +127,7 @@ if config["foresight"] == "perfect": + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: - **{ - f"map_{year}": RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_" - + f"{year}.pdf" - for year in config_provider("scenario", "planning_horizons") - }, + unpack(output_map_year), threads: 2 resources: mem_mb=10000, @@ -158,8 +161,9 @@ rule make_summary: params: foresight=config_provider("foresight"), costs=config_provider("costs"), - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, scenario=config_provider("scenario"), RDIR=RDIR, diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index bea6b6cc..a52f17c0 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -49,6 +49,14 @@ rule add_existing_baseyear: "../scripts/add_existing_baseyear.py" +def input_profile_tech_brownfield(w): + return { + f"profile_{tech}": resources(f"profile_{tech}.nc") + for tech in config_provider("electricity", "renewable_carriers")(w) + if tech != "hydro" + } + + rule add_brownfield: params: H2_retrofit=config_provider("sector", "H2_retrofit"), @@ -56,16 +64,13 @@ rule add_brownfield: "sector", "H2_retrofit_capacity_per_CH4" ), threshold_capacity=config_provider("existing_capacities", " threshold_capacity"), - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, carriers=config_provider("electricity", "renewable_carriers"), input: - **{ - f"profile_{tech}": resources(f"profile_{tech}.nc") - for tech in config_provider("electricity", "renewable_carriers") - if tech != "hydro" - }, + unpack(input_profile_tech_brownfield), simplify_busmap=resources("busmap_elec_s{simpl}.csv"), cluster_busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), network=RESULTS diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index d1a5f745..0d94ad9c 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -48,14 +48,17 @@ rule add_existing_baseyear: "../scripts/add_existing_baseyear.py" +def input_network_year(w): + return { + f"network_{year}": RESULTS + + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{year}.nc" + for year in config_provider("scenario", "planning_horizons")(w)[1:] + } + + rule prepare_perfect_foresight: input: - **{ - f"network_{year}": RESULTS - + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_" - + f"{year}.nc" - for year in config_provider("scenario", "planning_horizons")[1:] - }, + unpack(input_network_year), brownfield_network=lambda w: ( RESULTS + "prenetworks-brownfield/" @@ -122,11 +125,21 @@ rule solve_sector_network_perfect: "../scripts/solve_network.py" +def input_networks_make_summary_perfect(w): + return { + f"networks_{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}": RESULTS + + f"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc" + for simpl in config_provider("scenario", "simpl")(w) + for clusters in config_provider("scenario", "clusters")(w) + for opts in config_provider("scenario", "opts")(w) + for sector_opts in config_provider("scenario", "sector_opts")(w) + for ll in config_provider("scenario", "ll")(w) + } + + rule make_summary_perfect: input: - **{ - f"networks_{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}": RESULTS - + f"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc" + unpack(input_networks_make_summary_perfect), costs="resources/costs_2020.csv", output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", diff --git a/rules/validate.smk b/rules/validate.smk index 3c42c5f0..66949335 100644 --- a/rules/validate.smk +++ b/rules/validate.smk @@ -17,8 +17,9 @@ rule build_electricity_production: The data is used for validation of the optimization results. """ params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, countries=config_provider("countries"), output: @@ -37,8 +38,9 @@ rule build_cross_border_flows: The data is used for validation of the optimization results. """ params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, countries=config_provider("countries"), input: @@ -59,8 +61,9 @@ rule build_electricity_prices: The data is used for validation of the optimization results. """ params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, countries=config_provider("countries"), output: From 78b184ad0f457b4ba3ef9dd44306802e9c22f670 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 15:57:45 +0000 Subject: [PATCH 293/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/retrieve_cost_data.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/retrieve_cost_data.py b/scripts/retrieve_cost_data.py index ceae8bf9..eb1ef041 100644 --- a/scripts/retrieve_cost_data.py +++ b/scripts/retrieve_cost_data.py @@ -25,7 +25,9 @@ if __name__ == "__main__": set_scenario_config(snakemake) version = snakemake.params.version - baseurl = f"https://raw.githubusercontent.com/PyPSA/technology-data/{version}/outputs/" + baseurl = ( + f"https://raw.githubusercontent.com/PyPSA/technology-data/{version}/outputs/" + ) filepath = Path(snakemake.output[0]) url = baseurl + filepath.name From 9c592d9f73630d350447ba45c9c408f06456c7f8 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 14 Feb 2024 10:49:40 +0100 Subject: [PATCH 294/591] add config/config.yaml to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c9d2e171..6454616c 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ gurobi.log doc/_build config.yaml +config/config.yaml dconf /data/links_p_nom.csv From ecedea02d630d49ff14ad54c97c11b919211ea77 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Mon, 12 Feb 2024 18:17:53 +0100 Subject: [PATCH 295/591] bugfix: include all countries in ammonia production resource This is so that the full EU28 ammonia demand can be correctly subtracted in the build_industry_sector_ratios.py script. No other downstream scripts are affected by this change. --- scripts/build_ammonia_production.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/build_ammonia_production.py b/scripts/build_ammonia_production.py index 1bcdf9ae..bfcfaf02 100644 --- a/scripts/build_ammonia_production.py +++ b/scripts/build_ammonia_production.py @@ -8,6 +8,7 @@ Build historical annual ammonia production per country in ktonNH3/a. import country_converter as coco import pandas as pd +import numpy as np cc = coco.CountryConverter() @@ -30,8 +31,12 @@ if __name__ == "__main__": ammonia.index = cc.convert(ammonia.index, to="iso2") years = [str(i) for i in range(2013, 2018)] - countries = ammonia.index.intersection(snakemake.params.countries) - ammonia = ammonia.loc[countries, years].astype(float) + + ammonia = ammonia[years] + ammonia.replace("--", + np.nan, + inplace=True) + ammonia = ammonia.astype(float) # convert from ktonN to ktonNH3 ammonia *= 17 / 14 From c54626cc1a847ffded57e50cba2330f1f994a4ec Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Mon, 12 Feb 2024 18:19:25 +0100 Subject: [PATCH 296/591] bugfix: correct units of subtracted chlorine and methanol in build_industry_sector_ratios.py. In the config the units are Mt/a, they are multiplied by MWh/t, but what is desired is GWh/a. --- scripts/build_industry_sector_ratios.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/build_industry_sector_ratios.py b/scripts/build_industry_sector_ratios.py index 45705002..805cf3e7 100644 --- a/scripts/build_industry_sector_ratios.py +++ b/scripts/build_industry_sector_ratios.py @@ -408,15 +408,15 @@ def chemicals_industry(): df.loc["methane", sector] -= ammonia_total * params["MWh_CH4_per_tNH3_SMR"] df.loc["elec", sector] -= ammonia_total * params["MWh_elec_per_tNH3_SMR"] - # subtract chlorine demand + # subtract chlorine demand (in MtCl/a) chlorine_total = params["chlorine_production_today"] - df.loc["hydrogen", sector] -= chlorine_total * params["MWh_H2_per_tCl"] - df.loc["elec", sector] -= chlorine_total * params["MWh_elec_per_tCl"] + df.loc["hydrogen", sector] -= chlorine_total * params["MWh_H2_per_tCl"] * 1e3 + df.loc["elec", sector] -= chlorine_total * params["MWh_elec_per_tCl"] * 1e3 - # subtract methanol demand + # subtract methanol demand (in MtMeOH/a) methanol_total = params["methanol_production_today"] - df.loc["methane", sector] -= methanol_total * params["MWh_CH4_per_tMeOH"] - df.loc["elec", sector] -= methanol_total * params["MWh_elec_per_tMeOH"] + df.loc["methane", sector] -= methanol_total * params["MWh_CH4_per_tMeOH"] * 1e3 + df.loc["elec", sector] -= methanol_total * params["MWh_elec_per_tMeOH"] * 1e3 # MWh/t material df.loc[sources, sector] = df.loc[sources, sector] / s_out From cbf7ed0d38d059c60b8e220040be5be2e7ffa9ce Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Wed, 14 Feb 2024 10:09:13 +0100 Subject: [PATCH 297/591] for today's industry energy demand, separate MeOH, Cl and HVC I.e. split basic chemicals (without ammonia) into MeOH, Cl and HVC. This now agrees with scheme for industrial sectors tomorrow. --- config/config.default.yaml | 1 + ...ustrial_energy_demand_per_country_today.py | 50 +++++++++---------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 1033d49d..40dfb330 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -636,6 +636,7 @@ industry: 2040: 0.12 2045: 0.16 2050: 0.20 + basic_chemicals_without_NH3_energy_demand_today: 1138. #TWh/a HVC_production_today: 52. MWh_elec_per_tHVC_mechanical_recycling: 0.547 MWh_elec_per_tHVC_chemical_recycling: 6.9 diff --git a/scripts/build_industrial_energy_demand_per_country_today.py b/scripts/build_industrial_energy_demand_per_country_today.py index d1c672f1..696921de 100644 --- a/scripts/build_industrial_energy_demand_per_country_today.py +++ b/scripts/build_industrial_energy_demand_per_country_today.py @@ -73,7 +73,7 @@ def industrial_energy_demand_per_country(country, year, jrc_dir): def get_subsector_data(sheet): df = df_dict[sheet][year].groupby(fuels).sum() - df["ammonia"] = 0.0 + df["hydrogen"] = 0.0 df["other"] = df["all"] - df.loc[df.index != "all"].sum() @@ -94,36 +94,41 @@ def industrial_energy_demand_per_country(country, year, jrc_dir): return df -def add_ammonia_energy_demand(demand): +def separate_basic_chemicals(demand): # MtNH3/a fn = snakemake.input.ammonia_production ammonia = pd.read_csv(fn, index_col=0)[str(year)] / 1e3 - def get_ammonia_by_fuel(x): - fuels = { - "gas": params["MWh_CH4_per_tNH3_SMR"], - "electricity": params["MWh_elec_per_tNH3_SMR"], - } - - return pd.Series({k: x * v for k, v in fuels.items()}) - - ammonia_by_fuel = ammonia.apply(get_ammonia_by_fuel).T - ammonia_by_fuel = ammonia_by_fuel.unstack().reindex( - index=demand.index, fill_value=0.0 - ) - - ammonia = pd.DataFrame({"ammonia": ammonia * params["MWh_NH3_per_tNH3"]}).T + ammonia = pd.DataFrame({"gas": ammonia * params["MWh_CH4_per_tNH3_SMR"], + "electricity" : ammonia * params["MWh_elec_per_tNH3_SMR"]}).T demand["Ammonia"] = ammonia.unstack().reindex(index=demand.index, fill_value=0.0) demand["Basic chemicals (without ammonia)"] = ( - demand["Basic chemicals"] - ammonia_by_fuel + demand["Basic chemicals"] - demand["Ammonia"] ) - demand["Basic chemicals (without ammonia)"].clip(lower=0, inplace=True) - demand.drop(columns="Basic chemicals", inplace=True) + distribution = demand["Basic chemicals (without ammonia)"].groupby(level=0).sum()/params["basic_chemicals_without_NH3_energy_demand_today"] + + chlorine = pd.DataFrame({"hydrogen": distribution * params["chlorine_production_today"] * params["MWh_H2_per_tCl"], + "electricity" : distribution * params["chlorine_production_today"] * params["MWh_elec_per_tCl"]}).T + + methanol = pd.DataFrame({"gas": distribution * params["methanol_production_today"] * params["MWh_CH4_per_tMeOH"], + "electricity" : distribution * params["methanol_production_today"] * params["MWh_elec_per_tMeOH"]}).T + + demand["Chlorine"] = chlorine.unstack().reindex(index=demand.index, fill_value=0.0) + demand["Methanol"] = methanol.unstack().reindex(index=demand.index, fill_value=0.0) + + demand["HVC"] = ( + demand["Basic chemicals (without ammonia)"] -demand["Methanol"] - demand["Chlorine"] + ) + + demand.drop(columns="Basic chemicals (without ammonia)", inplace=True) + + demand["HVC"].clip(lower=0, inplace=True) + return demand @@ -135,11 +140,6 @@ def add_non_eu28_industrial_energy_demand(countries, demand): fn = snakemake.input.industrial_production_per_country production = pd.read_csv(fn, index_col=0) / 1e3 - # recombine HVC, Chlorine and Methanol to Basic chemicals (without ammonia) - chemicals = ["HVC", "Chlorine", "Methanol"] - production["Basic chemicals (without ammonia)"] = production[chemicals].sum(axis=1) - production.drop(columns=chemicals, inplace=True) - eu28_production = production.loc[countries.intersection(eu28)].sum() eu28_energy = demand.groupby(level=1).sum() eu28_averages = eu28_energy / eu28_production @@ -182,7 +182,7 @@ if __name__ == "__main__": demand = industrial_energy_demand(countries.intersection(eu28), year) - demand = add_ammonia_energy_demand(demand) + demand = separate_basic_chemicals(demand) demand = add_non_eu28_industrial_energy_demand(countries, demand) From cc57952402a80a785d16c4c1887d16d7c5aaed2b Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Wed, 14 Feb 2024 10:33:50 +0100 Subject: [PATCH 298/591] industrial prod: use EU28 total for denominator for distribution key This makes sure the distribution key is correct when only subsets of countries are used. This is then consistent with the HVC, MeOH and Cl totals being EU28 totals. Without this change, industry production is overestimated when using subsets of countries. Or the user has to adjust the totals for industrial production themselves. --- config/config.default.yaml | 1 + scripts/build_industrial_production_per_country.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 40dfb330..4245d926 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -637,6 +637,7 @@ industry: 2045: 0.16 2050: 0.20 basic_chemicals_without_NH3_energy_demand_today: 1138. #TWh/a + basic_chemicals_without_NH3_production_today: 69. #Mt/a HVC_production_today: 52. MWh_elec_per_tHVC_mechanical_recycling: 0.547 MWh_elec_per_tHVC_chemical_recycling: 6.9 diff --git a/scripts/build_industrial_production_per_country.py b/scripts/build_industrial_production_per_country.py index 0aea4f15..afbe4de7 100644 --- a/scripts/build_industrial_production_per_country.py +++ b/scripts/build_industrial_production_per_country.py @@ -261,7 +261,7 @@ def separate_basic_chemicals(demand, year): demand["Basic chemicals"].clip(lower=0.0, inplace=True) # assume HVC, methanol, chlorine production proportional to non-ammonia basic chemicals - distribution_key = demand["Basic chemicals"] / demand["Basic chemicals"].sum() + distribution_key = demand["Basic chemicals"] / params["basic_chemicals_without_NH3_production_today"] / 1e3 demand["HVC"] = params["HVC_production_today"] * 1e3 * distribution_key demand["Chlorine"] = params["chlorine_production_today"] * 1e3 * distribution_key demand["Methanol"] = params["methanol_production_today"] * 1e3 * distribution_key From 7f3ad792a9a7e36f09ce85c819834d29b247b558 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Wed, 14 Feb 2024 12:24:58 +0100 Subject: [PATCH 299/591] use production to determine today's energy demand for basic chemicals This uniformises how demand for basic chemicals is calculated. We also avoid unnecessary use of ammonia production separately. --- config/config.default.yaml | 3 +- rules/build_sector.smk | 1 - ...ustrial_energy_demand_per_country_today.py | 45 +++++++------------ 3 files changed, 17 insertions(+), 32 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 4245d926..79ca890d 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -636,8 +636,7 @@ industry: 2040: 0.12 2045: 0.16 2050: 0.20 - basic_chemicals_without_NH3_energy_demand_today: 1138. #TWh/a - basic_chemicals_without_NH3_production_today: 69. #Mt/a + basic_chemicals_without_NH3_production_today: 69. #Mt/a, = 86 Mtethylene-equiv - 17 MtNH3 HVC_production_today: 52. MWh_elec_per_tHVC_mechanical_recycling: 0.547 MWh_elec_per_tHVC_chemical_recycling: 6.9 diff --git a/rules/build_sector.smk b/rules/build_sector.smk index c25c8673..f50432d6 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -566,7 +566,6 @@ rule build_industrial_energy_demand_per_country_today: industry=config["industry"], input: jrc="data/bundle-sector/jrc-idees-2015", - ammonia_production=RESOURCES + "ammonia_production.csv", industrial_production_per_country=RESOURCES + "industrial_production_per_country.csv", output: diff --git a/scripts/build_industrial_energy_demand_per_country_today.py b/scripts/build_industrial_energy_demand_per_country_today.py index 696921de..65569b55 100644 --- a/scripts/build_industrial_energy_demand_per_country_today.py +++ b/scripts/build_industrial_energy_demand_per_country_today.py @@ -94,51 +94,34 @@ def industrial_energy_demand_per_country(country, year, jrc_dir): return df -def separate_basic_chemicals(demand): - # MtNH3/a - fn = snakemake.input.ammonia_production - ammonia = pd.read_csv(fn, index_col=0)[str(year)] / 1e3 +def separate_basic_chemicals(demand, production): - ammonia = pd.DataFrame({"gas": ammonia * params["MWh_CH4_per_tNH3_SMR"], - "electricity" : ammonia * params["MWh_elec_per_tNH3_SMR"]}).T + ammonia = pd.DataFrame({"hydrogen": production["Ammonia"] * params["MWh_H2_per_tNH3_electrolysis"], + "electricity" : production["Ammonia"] * params["MWh_elec_per_tNH3_electrolysis"]}).T + chlorine = pd.DataFrame({"hydrogen": production["Chlorine"] * params["MWh_H2_per_tCl"], + "electricity" : production["Chlorine"] * params["MWh_elec_per_tCl"]}).T + methanol = pd.DataFrame({"gas": production["Methanol"] * params["MWh_CH4_per_tMeOH"], + "electricity" : production["Methanol"] * params["MWh_elec_per_tMeOH"]}).T demand["Ammonia"] = ammonia.unstack().reindex(index=demand.index, fill_value=0.0) - - demand["Basic chemicals (without ammonia)"] = ( - demand["Basic chemicals"] - demand["Ammonia"] - ) - - demand.drop(columns="Basic chemicals", inplace=True) - - distribution = demand["Basic chemicals (without ammonia)"].groupby(level=0).sum()/params["basic_chemicals_without_NH3_energy_demand_today"] - - chlorine = pd.DataFrame({"hydrogen": distribution * params["chlorine_production_today"] * params["MWh_H2_per_tCl"], - "electricity" : distribution * params["chlorine_production_today"] * params["MWh_elec_per_tCl"]}).T - - methanol = pd.DataFrame({"gas": distribution * params["methanol_production_today"] * params["MWh_CH4_per_tMeOH"], - "electricity" : distribution * params["methanol_production_today"] * params["MWh_elec_per_tMeOH"]}).T - demand["Chlorine"] = chlorine.unstack().reindex(index=demand.index, fill_value=0.0) demand["Methanol"] = methanol.unstack().reindex(index=demand.index, fill_value=0.0) demand["HVC"] = ( - demand["Basic chemicals (without ammonia)"] -demand["Methanol"] - demand["Chlorine"] + demand["Basic chemicals"] - demand["Ammonia"] - demand["Methanol"] - demand["Chlorine"] ) - demand.drop(columns="Basic chemicals (without ammonia)", inplace=True) + demand.drop(columns="Basic chemicals", inplace=True) demand["HVC"].clip(lower=0, inplace=True) return demand -def add_non_eu28_industrial_energy_demand(countries, demand): +def add_non_eu28_industrial_energy_demand(countries, demand, production): non_eu28 = countries.difference(eu28) if non_eu28.empty: return demand - # output in MtMaterial/a - fn = snakemake.input.industrial_production_per_country - production = pd.read_csv(fn, index_col=0) / 1e3 eu28_production = production.loc[countries.intersection(eu28)].sum() eu28_energy = demand.groupby(level=1).sum() @@ -182,9 +165,13 @@ if __name__ == "__main__": demand = industrial_energy_demand(countries.intersection(eu28), year) - demand = separate_basic_chemicals(demand) + # output in MtMaterial/a + production = pd.read_csv(snakemake.input.industrial_production_per_country, + index_col=0) / 1e3 - demand = add_non_eu28_industrial_energy_demand(countries, demand) + demand = separate_basic_chemicals(demand, production) + + demand = add_non_eu28_industrial_energy_demand(countries, demand, production) # for format compatibility demand = demand.stack(dropna=False).unstack(level=[0, 2]) From e14bae345b5009cf65c49d573517176bda7d69f4 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Wed, 14 Feb 2024 18:15:18 +0100 Subject: [PATCH 300/591] new script to interpolate industry sector ratios today to tomorrow For each country we gradually switch industry processes from today's specific energy carrier usage per ton material output to the best-in-class energy consumption of tomorrow in the industry_sector_ratios.csv. This is done on a per-country basis. The ratio of today to tomorrow's energy consumption is set with the config["industry"]["sector_ratios_fraction_future"] parameter. --- config/config.default.yaml | 8 ++ rules/build_sector.smk | 26 ++++++- ...build_industrial_energy_demand_per_node.py | 21 +++-- ...ild_industry_sector_ratios_intermediate.py | 77 +++++++++++++++++++ 4 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 scripts/build_industry_sector_ratios_intermediate.py diff --git a/config/config.default.yaml b/config/config.default.yaml index 79ca890d..0f28ee93 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -636,6 +636,14 @@ industry: 2040: 0.12 2045: 0.16 2050: 0.20 + sector_ratios_fraction_future: + 2020: 0.0 + 2025: 0.1 + 2030: 0.3 + 2035: 0.5 + 2040: 0.7 + 2045: 0.9 + 2050: 1.0 basic_chemicals_without_NH3_production_today: 69. #Mt/a, = 86 Mtethylene-equiv - 17 MtNH3 HVC_production_today: 52. MWh_elec_per_tHVC_mechanical_recycling: 0.547 diff --git a/rules/build_sector.smk b/rules/build_sector.smk index f50432d6..bec9aa7a 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -433,6 +433,30 @@ rule build_industry_sector_ratios: "../scripts/build_industry_sector_ratios.py" +rule build_industry_sector_ratios_intermediate: + params: + industry=config["industry"], + input: + industry_sector_ratios=RESOURCES + "industry_sector_ratios.csv", + industrial_energy_demand_per_country_today=RESOURCES + + "industrial_energy_demand_per_country_today.csv", + industrial_production_per_country=RESOURCES + + "industrial_production_per_country.csv", + output: + industry_sector_ratios=RESOURCES + "industry_sector_ratios_{planning_horizons}.csv", + threads: 1 + resources: + mem_mb=1000, + log: + LOGS + "build_industry_sector_ratios_{planning_horizons}.log", + benchmark: + BENCHMARKS + "build_industry_sector_ratios_{planning_horizons}" + conda: + "../envs/environment.yaml" + script: + "../scripts/build_industry_sector_ratios_intermediate.py" + + rule build_industrial_production_per_country: params: industry=config["industry"], @@ -535,7 +559,7 @@ rule build_industrial_production_per_node: rule build_industrial_energy_demand_per_node: input: - industry_sector_ratios=RESOURCES + "industry_sector_ratios.csv", + industry_sector_ratios=RESOURCES + "industry_sector_ratios_{planning_horizons}.csv", industrial_production_per_node=RESOURCES + "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv", industrial_energy_demand_per_node_today=RESOURCES diff --git a/scripts/build_industrial_energy_demand_per_node.py b/scripts/build_industrial_energy_demand_per_node.py index 55c10c5d..84f8679a 100644 --- a/scripts/build_industrial_energy_demand_per_node.py +++ b/scripts/build_industrial_energy_demand_per_node.py @@ -19,23 +19,28 @@ if __name__ == "__main__": planning_horizons=2030, ) - # import EU ratios df as csv + # import ratios fn = snakemake.input.industry_sector_ratios - industry_sector_ratios = pd.read_csv(fn, index_col=0) + sector_ratios = pd.read_csv(fn, + header=[0,1], + index_col=0) - # material demand per node and industry (kton/a) + # material demand per node and industry (Mton/a) fn = snakemake.input.industrial_production_per_node - nodal_production = pd.read_csv(fn, index_col=0) + nodal_production = pd.read_csv(fn, index_col=0) / 1e3 # energy demand today to get current electricity fn = snakemake.input.industrial_energy_demand_per_node_today nodal_today = pd.read_csv(fn, index_col=0) - # final energy consumption per node and industry (TWh/a) - nodal_df = nodal_production.dot(industry_sector_ratios.T) + nodal_sector_ratios = pd.concat({node: sector_ratios[node[:2]] for node in nodal_production.index}, + axis=1) - # convert GWh to TWh and ktCO2 to MtCO2 - nodal_df *= 0.001 + nodal_production_stacked = nodal_production.stack() + nodal_production_stacked.index.names = [None,None] + + # final energy consumption per node and industry (TWh/a) + nodal_df = (nodal_sector_ratios.multiply(nodal_production_stacked)).T.groupby(level=0).sum() rename_sectors = { "elec": "electricity", diff --git a/scripts/build_industry_sector_ratios_intermediate.py b/scripts/build_industry_sector_ratios_intermediate.py new file mode 100644 index 00000000..86f88218 --- /dev/null +++ b/scripts/build_industry_sector_ratios_intermediate.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Build specific energy consumption by carrier and industries and by country, +that interpolates between the current average energy consumption (from 2015-2020) +and the ideal future best-in-class consumption. +""" + +import pandas as pd + +from prepare_sector_network import get + +def build_industry_sector_ratios_intermediate(): + + # in TWh/a + demand = pd.read_csv(snakemake.input.industrial_energy_demand_per_country_today, + header=[0,1], + index_col=0) + + # in Mt/a + production = pd.read_csv(snakemake.input.industrial_production_per_country, + index_col=0) / 1e3 + production = production.unstack().swaplevel() + + # in MWh/t + future_sector_ratios = pd.read_csv(snakemake.input.industry_sector_ratios, + index_col=0) + + production.index.names = [None,None] + + today_sector_ratios = demand.div(production, axis=1) + + today_sector_ratios.drop(columns=today_sector_ratios.columns[today_sector_ratios.isna().all()], + inplace=True) + + rename = pd.Series(today_sector_ratios.index, + today_sector_ratios.index) + rename["waste"] = "biomass" + rename["electricity"] = "elec" + rename["solid"] = "coke" + rename["gas"] = "methane" + rename["other"] = "biomass" + rename["liquid"] = "naphtha" + + today_sector_ratios.rename(rename, + inplace=True) + + + fraction_future = get(params["sector_ratios_fraction_future"], year) + + intermediate_sector_ratios = {} + + for ct in today_sector_ratios.columns.unique(level=0): + + intermediate_sector_ratio = future_sector_ratios.copy() + + intermediate_sector_ratio.loc[today_sector_ratios[ct].index,today_sector_ratios[ct].columns] = (fraction_future*intermediate_sector_ratio.loc[today_sector_ratios[ct].index,today_sector_ratios[ct].columns] + + (1 - fraction_future)*today_sector_ratios[ct]) + intermediate_sector_ratios[ct] = intermediate_sector_ratio + + intermediate_sector_ratios = pd.concat(intermediate_sector_ratios, axis=1) + + intermediate_sector_ratios.to_csv(snakemake.output.industry_sector_ratios) + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake("build_industry_sector_ratios_intermediate") + + year = int(snakemake.wildcards.planning_horizons[-4:]) + + params = snakemake.params.industry + + build_industry_sector_ratios_intermediate() From b45df1724bda1611c5792f0775b6496e36d88638 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 14 Feb 2024 17:31:48 +0000 Subject: [PATCH 301/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_sector.smk | 6 ++- ...ustrial_energy_demand_per_country_today.py | 36 +++++++++---- ...build_industrial_energy_demand_per_node.py | 17 +++--- ...build_industrial_production_per_country.py | 6 ++- ...ild_industry_sector_ratios_intermediate.py | 52 ++++++++++++------- 5 files changed, 78 insertions(+), 39 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index bec9aa7a..0c53fdd1 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -443,7 +443,8 @@ rule build_industry_sector_ratios_intermediate: industrial_production_per_country=RESOURCES + "industrial_production_per_country.csv", output: - industry_sector_ratios=RESOURCES + "industry_sector_ratios_{planning_horizons}.csv", + industry_sector_ratios=RESOURCES + + "industry_sector_ratios_{planning_horizons}.csv", threads: 1 resources: mem_mb=1000, @@ -559,7 +560,8 @@ rule build_industrial_production_per_node: rule build_industrial_energy_demand_per_node: input: - industry_sector_ratios=RESOURCES + "industry_sector_ratios_{planning_horizons}.csv", + industry_sector_ratios=RESOURCES + + "industry_sector_ratios_{planning_horizons}.csv", industrial_production_per_node=RESOURCES + "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv", industrial_energy_demand_per_node_today=RESOURCES diff --git a/scripts/build_industrial_energy_demand_per_country_today.py b/scripts/build_industrial_energy_demand_per_country_today.py index 65569b55..9105a790 100644 --- a/scripts/build_industrial_energy_demand_per_country_today.py +++ b/scripts/build_industrial_energy_demand_per_country_today.py @@ -96,19 +96,35 @@ def industrial_energy_demand_per_country(country, year, jrc_dir): def separate_basic_chemicals(demand, production): - ammonia = pd.DataFrame({"hydrogen": production["Ammonia"] * params["MWh_H2_per_tNH3_electrolysis"], - "electricity" : production["Ammonia"] * params["MWh_elec_per_tNH3_electrolysis"]}).T - chlorine = pd.DataFrame({"hydrogen": production["Chlorine"] * params["MWh_H2_per_tCl"], - "electricity" : production["Chlorine"] * params["MWh_elec_per_tCl"]}).T - methanol = pd.DataFrame({"gas": production["Methanol"] * params["MWh_CH4_per_tMeOH"], - "electricity" : production["Methanol"] * params["MWh_elec_per_tMeOH"]}).T + ammonia = pd.DataFrame( + { + "hydrogen": production["Ammonia"] * params["MWh_H2_per_tNH3_electrolysis"], + "electricity": production["Ammonia"] + * params["MWh_elec_per_tNH3_electrolysis"], + } + ).T + chlorine = pd.DataFrame( + { + "hydrogen": production["Chlorine"] * params["MWh_H2_per_tCl"], + "electricity": production["Chlorine"] * params["MWh_elec_per_tCl"], + } + ).T + methanol = pd.DataFrame( + { + "gas": production["Methanol"] * params["MWh_CH4_per_tMeOH"], + "electricity": production["Methanol"] * params["MWh_elec_per_tMeOH"], + } + ).T demand["Ammonia"] = ammonia.unstack().reindex(index=demand.index, fill_value=0.0) demand["Chlorine"] = chlorine.unstack().reindex(index=demand.index, fill_value=0.0) demand["Methanol"] = methanol.unstack().reindex(index=demand.index, fill_value=0.0) demand["HVC"] = ( - demand["Basic chemicals"] - demand["Ammonia"] - demand["Methanol"] - demand["Chlorine"] + demand["Basic chemicals"] + - demand["Ammonia"] + - demand["Methanol"] + - demand["Chlorine"] ) demand.drop(columns="Basic chemicals", inplace=True) @@ -166,8 +182,10 @@ if __name__ == "__main__": demand = industrial_energy_demand(countries.intersection(eu28), year) # output in MtMaterial/a - production = pd.read_csv(snakemake.input.industrial_production_per_country, - index_col=0) / 1e3 + production = ( + pd.read_csv(snakemake.input.industrial_production_per_country, index_col=0) + / 1e3 + ) demand = separate_basic_chemicals(demand, production) diff --git a/scripts/build_industrial_energy_demand_per_node.py b/scripts/build_industrial_energy_demand_per_node.py index 84f8679a..ec571c71 100644 --- a/scripts/build_industrial_energy_demand_per_node.py +++ b/scripts/build_industrial_energy_demand_per_node.py @@ -21,9 +21,7 @@ if __name__ == "__main__": # import ratios fn = snakemake.input.industry_sector_ratios - sector_ratios = pd.read_csv(fn, - header=[0,1], - index_col=0) + sector_ratios = pd.read_csv(fn, header=[0, 1], index_col=0) # material demand per node and industry (Mton/a) fn = snakemake.input.industrial_production_per_node @@ -33,14 +31,19 @@ if __name__ == "__main__": fn = snakemake.input.industrial_energy_demand_per_node_today nodal_today = pd.read_csv(fn, index_col=0) - nodal_sector_ratios = pd.concat({node: sector_ratios[node[:2]] for node in nodal_production.index}, - axis=1) + nodal_sector_ratios = pd.concat( + {node: sector_ratios[node[:2]] for node in nodal_production.index}, axis=1 + ) nodal_production_stacked = nodal_production.stack() - nodal_production_stacked.index.names = [None,None] + nodal_production_stacked.index.names = [None, None] # final energy consumption per node and industry (TWh/a) - nodal_df = (nodal_sector_ratios.multiply(nodal_production_stacked)).T.groupby(level=0).sum() + nodal_df = ( + (nodal_sector_ratios.multiply(nodal_production_stacked)) + .T.groupby(level=0) + .sum() + ) rename_sectors = { "elec": "electricity", diff --git a/scripts/build_industrial_production_per_country.py b/scripts/build_industrial_production_per_country.py index afbe4de7..afab1403 100644 --- a/scripts/build_industrial_production_per_country.py +++ b/scripts/build_industrial_production_per_country.py @@ -261,7 +261,11 @@ def separate_basic_chemicals(demand, year): demand["Basic chemicals"].clip(lower=0.0, inplace=True) # assume HVC, methanol, chlorine production proportional to non-ammonia basic chemicals - distribution_key = demand["Basic chemicals"] / params["basic_chemicals_without_NH3_production_today"] / 1e3 + distribution_key = ( + demand["Basic chemicals"] + / params["basic_chemicals_without_NH3_production_today"] + / 1e3 + ) demand["HVC"] = params["HVC_production_today"] * 1e3 * distribution_key demand["Chlorine"] = params["chlorine_production_today"] * 1e3 * distribution_key demand["Methanol"] = params["methanol_production_today"] * 1e3 * distribution_key diff --git a/scripts/build_industry_sector_ratios_intermediate.py b/scripts/build_industry_sector_ratios_intermediate.py index 86f88218..0cbdfa06 100644 --- a/scripts/build_industry_sector_ratios_intermediate.py +++ b/scripts/build_industry_sector_ratios_intermediate.py @@ -4,39 +4,45 @@ # SPDX-License-Identifier: MIT """ Build specific energy consumption by carrier and industries and by country, -that interpolates between the current average energy consumption (from 2015-2020) -and the ideal future best-in-class consumption. +that interpolates between the current average energy consumption (from +2015-2020) and the ideal future best-in-class consumption. """ import pandas as pd - from prepare_sector_network import get + def build_industry_sector_ratios_intermediate(): # in TWh/a - demand = pd.read_csv(snakemake.input.industrial_energy_demand_per_country_today, - header=[0,1], - index_col=0) + demand = pd.read_csv( + snakemake.input.industrial_energy_demand_per_country_today, + header=[0, 1], + index_col=0, + ) # in Mt/a - production = pd.read_csv(snakemake.input.industrial_production_per_country, - index_col=0) / 1e3 + production = ( + pd.read_csv(snakemake.input.industrial_production_per_country, index_col=0) + / 1e3 + ) production = production.unstack().swaplevel() # in MWh/t - future_sector_ratios = pd.read_csv(snakemake.input.industry_sector_ratios, - index_col=0) + future_sector_ratios = pd.read_csv( + snakemake.input.industry_sector_ratios, index_col=0 + ) - production.index.names = [None,None] + production.index.names = [None, None] today_sector_ratios = demand.div(production, axis=1) - today_sector_ratios.drop(columns=today_sector_ratios.columns[today_sector_ratios.isna().all()], - inplace=True) + today_sector_ratios.drop( + columns=today_sector_ratios.columns[today_sector_ratios.isna().all()], + inplace=True, + ) - rename = pd.Series(today_sector_ratios.index, - today_sector_ratios.index) + rename = pd.Series(today_sector_ratios.index, today_sector_ratios.index) rename["waste"] = "biomass" rename["electricity"] = "elec" rename["solid"] = "coke" @@ -44,9 +50,7 @@ def build_industry_sector_ratios_intermediate(): rename["other"] = "biomass" rename["liquid"] = "naphtha" - today_sector_ratios.rename(rename, - inplace=True) - + today_sector_ratios.rename(rename, inplace=True) fraction_future = get(params["sector_ratios_fraction_future"], year) @@ -56,14 +60,22 @@ def build_industry_sector_ratios_intermediate(): intermediate_sector_ratio = future_sector_ratios.copy() - intermediate_sector_ratio.loc[today_sector_ratios[ct].index,today_sector_ratios[ct].columns] = (fraction_future*intermediate_sector_ratio.loc[today_sector_ratios[ct].index,today_sector_ratios[ct].columns] - + (1 - fraction_future)*today_sector_ratios[ct]) + intermediate_sector_ratio.loc[ + today_sector_ratios[ct].index, today_sector_ratios[ct].columns + ] = ( + fraction_future + * intermediate_sector_ratio.loc[ + today_sector_ratios[ct].index, today_sector_ratios[ct].columns + ] + + (1 - fraction_future) * today_sector_ratios[ct] + ) intermediate_sector_ratios[ct] = intermediate_sector_ratio intermediate_sector_ratios = pd.concat(intermediate_sector_ratios, axis=1) intermediate_sector_ratios.to_csv(snakemake.output.industry_sector_ratios) + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake From 4fa504b0dbd60aa0b410d2bffba4c68e525159ff Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 14 Feb 2024 17:32:20 +0000 Subject: [PATCH 302/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/build_ammonia_production.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/build_ammonia_production.py b/scripts/build_ammonia_production.py index bfcfaf02..77b33075 100644 --- a/scripts/build_ammonia_production.py +++ b/scripts/build_ammonia_production.py @@ -7,8 +7,8 @@ Build historical annual ammonia production per country in ktonNH3/a. """ import country_converter as coco -import pandas as pd import numpy as np +import pandas as pd cc = coco.CountryConverter() @@ -33,9 +33,7 @@ if __name__ == "__main__": years = [str(i) for i in range(2013, 2018)] ammonia = ammonia[years] - ammonia.replace("--", - np.nan, - inplace=True) + ammonia.replace("--", np.nan, inplace=True) ammonia = ammonia.astype(float) # convert from ktonN to ktonNH3 From 87ab0a55759507aa5eb4115a9b7fb98634fd40ea Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Thu, 15 Feb 2024 14:58:53 +0100 Subject: [PATCH 303/591] update h2 pipe losses --- config/config.default.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 1033d49d..cfda5224 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -538,8 +538,8 @@ sector: efficiency_static: 0.98 efficiency_per_1000km: 0.977 H2 pipeline: - efficiency_per_1000km: 1 # 0.979 - compression_per_1000km: 0.019 + efficiency_per_1000km: 0.996 + compression_per_1000km: 0.018 gas pipeline: efficiency_per_1000km: 1 #0.977 compression_per_1000km: 0.01 From 8464415b356171c633e53fb0268660f9b9ee994d Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Thu, 15 Feb 2024 15:14:32 +0100 Subject: [PATCH 304/591] update for 70 bars instead of 140 --- config/config.default.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index cfda5224..97b0edb3 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -538,8 +538,8 @@ sector: efficiency_static: 0.98 efficiency_per_1000km: 0.977 H2 pipeline: - efficiency_per_1000km: 0.996 - compression_per_1000km: 0.018 + efficiency_per_1000km: 0.9905 + compression_per_1000km: 0.008 gas pipeline: efficiency_per_1000km: 1 #0.977 compression_per_1000km: 0.01 From 16955d24abec236e757c5f19cf0af003939defbb Mon Sep 17 00:00:00 2001 From: martacki Date: Thu, 15 Feb 2024 16:27:44 +0100 Subject: [PATCH 305/591] data: upload swiss energy totals data for all years --- data/switzerland-new_format-all_years.csv | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 data/switzerland-new_format-all_years.csv diff --git a/data/switzerland-new_format-all_years.csv b/data/switzerland-new_format-all_years.csv new file mode 100644 index 00000000..93123009 --- /dev/null +++ b/data/switzerland-new_format-all_years.csv @@ -0,0 +1,25 @@ +country,item,2010,2011,2012,2013,2014,2015 +CH,total residential,268.2,223.4,243.4,261.3,214.2,229.1 +CH,total residential space,192.2,149.0,168.1,185.5,139.7,154.4 +CH,total residential water,32.2,31.6,31.9,32.2,31.7,31.9 +CH,total residential cooking,9.3,9.3,9.3,9.4,9.5,9.6 +CH,electricity residential,67.9,63.7,65.7,67.6,63.0,64.4 +CH,electricity residential space,15.9,12.8,14.3,15.8,12.3,13.5 +CH,electricity residential water,8.8,8.5,8.5,8.6,8.5,8.6 +CH,electricity residential cooking,4.9,4.9,4.9,4.9,5.0,5.0 +CH,total services,145.9,127.4,136.7,144.0,124.5,132.5 +CH,total services space,80.0,62.2,70.8,77.4,58.3,64.3 +CH,total services water,10.1,10.0,10.1,10.1,10.0,10.0 +CH,total services cooking,2.5,2.4,2.3,2.3,2.4,2.3 +CH,electricity services,60.5,59.2,60.3,61.4,60.3,62.6 +CH,electricity services space,4.0,3.2,3.8,4.2,3.3,3.6 +CH,electricity services water,0.7,0.7,0.7,0.7,0.7,0.7 +CH,electricity services cooking,2.5,2.4,2.3,2.3,2.4,2.3 +CH,total rail,11.5,11.1,11.2,11.4,11.1,11.4 +CH,total road,199.4,200.4,200.4,201.2,202.0,203.1 +CH,electricity road,0.,0.,0.,0.,0.,0. +CH,electricity rail,11.5,11.1,11.2,11.4,11.1,11.4 +CH,total domestic aviation,3.3,3.2,3.4,3.4,3.5,3.5 +CH,total international aviation,58.0,62.0,63.5,64.2,64.5,66.8 +CH,total domestic navigation,1.6,1.6,1.6,1.6,1.6,1.6 +CH,total international navigation,0.,0.,0.,0.,0.,0. From a22b19dcc49639ce927d72ac1bb640c29059fcdf Mon Sep 17 00:00:00 2001 From: martacki Date: Thu, 15 Feb 2024 16:28:24 +0100 Subject: [PATCH 306/591] use new swiss data for building energy totals --- rules/build_sector.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index c25c8673..d99c39ae 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -248,7 +248,7 @@ rule build_energy_totals: input: nuts3_shapes=RESOURCES + "nuts3_shapes.geojson", co2="data/bundle-sector/eea/UNFCCC_v23.csv", - swiss="data/bundle-sector/switzerland-sfoe/switzerland-new_format.csv", + swiss="data/switzerland-new_format-all_years.csv", idees="data/bundle-sector/jrc-idees-2015", district_heat_share="data/district_heat_share.csv", eurostat=input_eurostat, From 6196fd689283e25c0be0660bfc313a2fb4f07430 Mon Sep 17 00:00:00 2001 From: martacki Date: Thu, 15 Feb 2024 16:29:29 +0100 Subject: [PATCH 307/591] change default energy totals year to 2013 to comply with default weather year --- config/config.default.yaml | 2 +- doc/release_notes.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 1033d49d..ba99e3ba 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -314,7 +314,7 @@ pypsa_eur: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#energy energy: - energy_totals_year: 2011 + energy_totals_year: 2013 base_emissions_year: 1990 eurostat_report_year: 2016 emissions: CO2 diff --git a/doc/release_notes.rst b/doc/release_notes.rst index cab8229a..fde06f97 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -113,6 +113,8 @@ Upcoming Release workflows with foresight "myopic" and still needs to be added foresight option "perfect". +* Swiched the energy totals year from 2011 to 2013 to comply with the assumed default weather year. + PyPSA-Eur 0.9.0 (5th January 2024) ================================== From ccbf835976e2cf776f421a5f868158dbe9d42848 Mon Sep 17 00:00:00 2001 From: martacki Date: Fri, 16 Feb 2024 09:49:00 +0100 Subject: [PATCH 308/591] fix typo to make pre-commit.ci happy --- doc/release_notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index fde06f97..e017b07d 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -113,7 +113,7 @@ Upcoming Release workflows with foresight "myopic" and still needs to be added foresight option "perfect". -* Swiched the energy totals year from 2011 to 2013 to comply with the assumed default weather year. +* Switched the energy totals year from 2011 to 2013 to comply with the assumed default weather year. PyPSA-Eur 0.9.0 (5th January 2024) From 16e42c8fe61fdb9441773dcaf35e82765a106d31 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 11:17:00 +0100 Subject: [PATCH 309/591] further progress and bugfixes --- .gitignore | 2 +- Snakefile | 20 +++++++++----------- config/config.default.yaml | 2 +- rules/build_electricity.smk | 34 +++++++++++++++++----------------- rules/build_sector.smk | 6 +++--- rules/postprocess.smk | 25 ++++++++----------------- rules/retrieve.smk | 6 +++++- rules/solve_electricity.smk | 1 - rules/solve_myopic.smk | 8 ++++---- rules/solve_perfect.smk | 8 ++++---- scripts/_helpers.py | 11 ++++++----- 11 files changed, 58 insertions(+), 65 deletions(-) diff --git a/.gitignore b/.gitignore index f5f88861..5dafb3ce 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,7 @@ doc/_build /scripts/create_scenarios.py /config/create_scenarios.py -config.yaml +config/config.yaml config/scenarios.yaml diff --git a/Snakefile b/Snakefile index 2b4fd64e..2c342efc 100644 --- a/Snakefile +++ b/Snakefile @@ -20,9 +20,6 @@ configfile: "config/config.default.yaml" configfile: "config/config.yaml" -COSTS = f"resources/costs_{config['costs']['year']}.csv" -ATLITE_NPROCESSES = config["atlite"].get("nprocesses", 4) - run = config["run"] scenarios = run.get("scenarios", {}) if run["name"]: @@ -39,16 +36,17 @@ benchmarks = path_provider("benchmarks/", RDIR, run["shared_resources"]) resources = path_provider("resources/", RDIR, run["shared_resources"]) CDIR = "" if run["shared_cutouts"] else RDIR -LOGS = "logs/" + RDIR -BENCHMARKS = "benchmarks/" + RDIR -if not (shared_resources := run.get("shared_resources")): - RESOURCES = "resources/" + RDIR -elif isinstance(shared_resources, str): - RESOURCES = "resources/" + shared_resources + "/" -else: - RESOURCES = "resources/" RESULTS = "results/" + RDIR +# TODO: this needs to be aligned with new scenario management +# if not (shared_resources := run.get("shared_resources")): +# RESOURCES = "resources/" + RDIR +# elif isinstance(shared_resources, str): +# RESOURCES = "resources/" + shared_resources + "/" +# else: +# RESOURCES = "resources/" + + localrules: purge, diff --git a/config/config.default.yaml b/config/config.default.yaml index ccd3baf8..9e169a5d 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -25,7 +25,7 @@ run: enable: false file: config/scenarios.yaml disable_progressbar: false - shared_resources: false + shared_resources: false # TODO: splitting resources by wildcard does not work well, neither does true, only base works well shared_cutouts: true # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#foresight diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 8876c68e..e18ae5dc 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -162,12 +162,12 @@ if config["enable"].get("build_cutout", False): output: protected("cutouts/" + CDIR + "{cutout}.nc"), log: - "logs/" + CDIR + "build_cutout/{cutout}.log", + logs(CDIR + "build_cutout/{cutout}.log"), benchmark: "benchmarks/" + CDIR + "build_cutout_{cutout}" - threads: ATLITE_NPROCESSES + threads: config["atlite"].get("nprocesses", 4) resources: - mem_mb=ATLITE_NPROCESSES * 1000, + mem_mb=config["atlite"].get("nprocesses", 4) * 1000, conda: "../envs/environment.yaml" script: @@ -249,9 +249,9 @@ rule determine_availability_matrix_MD_UA: availability_map=resources("availability_matrix_MD-UA_{technology}.png"), log: logs("determine_availability_matrix_MD_UA_{technology}.log"), - threads: ATLITE_NPROCESSES + threads: config["atlite"].get("nprocesses", 4) resources: - mem_mb=ATLITE_NPROCESSES * 5000, + mem_mb=config["atlite"].get("nprocesses", 4) * 5000, conda: "../envs/environment.yaml" script: @@ -319,9 +319,9 @@ rule build_renewable_profiles: logs("build_renewable_profile_{technology}.log"), benchmark: benchmarks("build_renewable_profiles_{technology}") - threads: ATLITE_NPROCESSES + threads: config["atlite"].get("nprocesses", 4) resources: - mem_mb=ATLITE_NPROCESSES * 5000, + mem_mb=config["atlite"].get("nprocesses", 4) * 5000, wildcard_constraints: technology="(?!hydro).*", # Any technology other than hydro conda: @@ -391,9 +391,9 @@ if config["lines"]["dynamic_line_rating"]["activate"]: logs("build_line_rating.log"), benchmark: benchmarks("build_line_rating") - threads: ATLITE_NPROCESSES + threads: config["atlite"].get("nprocesses", 4) resources: - mem_mb=ATLITE_NPROCESSES * 1000, + mem_mb=config["atlite"].get("nprocesses", 4) * 1000, conda: "../envs/environment.yaml" script: @@ -435,7 +435,7 @@ rule add_electricity: if config_provider("lines", "dynamic_line_rating", "activate")(w) else resources("networks/base.nc") ), - tech_costs=COSTS, + tech_costs=resources(f"costs_{config['costs']['year']}.csv"), regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), @@ -478,7 +478,7 @@ rule simplify_network: costs=config_provider("costs"), input: network=resources("networks/elec.nc"), - tech_costs=COSTS, + tech_costs=resources(f"costs_{config['costs']['year']}.csv"), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), output: @@ -525,7 +525,7 @@ rule cluster_network: if config_provider("enable", "custom_busmap", default=False)(w) else [] ), - tech_costs=COSTS, + tech_costs=resources(f"costs_{config['costs']['year']}.csv"), output: network=resources("networks/elec_s{simpl}_{clusters}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), @@ -552,7 +552,7 @@ rule add_extra_components: costs=config_provider("costs"), input: network=resources("networks/elec_s{simpl}_{clusters}.nc"), - tech_costs=COSTS, + tech_costs=resources(f"costs_{config['costs']['year']}.csv"), output: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), log: @@ -570,11 +570,11 @@ rule add_extra_components: rule prepare_network: params: - snapshots={ - "resolution": config_provider("snapshots", "resolution", default=False), + snapshots=lambda w: { + "resolution": config_provider("snapshots", "resolution", default=False)(w), "segmentation": config_provider( "snapshots", "segmentation", default=False - ), + )(w), }, links=config_provider("links"), lines=config_provider("lines"), @@ -588,7 +588,7 @@ rule prepare_network: autarky=config_provider("electricity", "autarky", default={}), input: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), - tech_costs=COSTS, + tech_costs=resources(f"costs_{config['costs']['year']}.csv"), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), diff --git a/rules/build_sector.smk b/rules/build_sector.smk index cfd7191e..ba56564e 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -857,7 +857,7 @@ rule prepare_sector_network: biomass_potentials=lambda w: ( resources( "biomass_potentials_s{simpl}_{clusters}_" - + "{}.csv".format(config_provider("biomass", "year")) + + "{}.csv".format(config_provider("biomass", "year")(w)) ) if config_provider("foresight")(w) == "overnight" else resources( @@ -865,9 +865,9 @@ rule prepare_sector_network: ) ), costs=lambda w: ( - "resources/costs_{}.csv".format(config_provider("costs", "year")) + resources("costs_{}.csv".format(config_provider("costs", "year")(w))) if config_provider("foresight")(w) == "overnight" - else "resources/costs_{planning_horizons}.csv" + else resources("costs_{planning_horizons}.csv") ), profile_offwind_ac=resources("profile_offwind-ac.nc"), profile_offwind_dc=resources("profile_offwind-dc.nc"), diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 79634bf6..6302bb46 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -18,7 +18,7 @@ if config["foresight"] != "perfect": "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), output: - map=RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", + map=resources("maps/power-network-s{simpl}-{clusters}.pdf"), threads: 1 resources: mem_mb=4000, @@ -149,8 +149,6 @@ rule copy_config: threads: 1 resources: mem_mb=1000, - benchmark: - benchmarks("copy_config") conda: "../envs/environment.yaml" script: @@ -168,10 +166,6 @@ rule make_summary: scenario=config_provider("scenario"), RDIR=RDIR, input: - expand( - RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", - **config["scenario"], - ), networks=expand( RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -179,15 +173,16 @@ rule make_summary: run=config["run"]["name"], ), costs=lambda w: ( - "resources/costs_{}.csv".format(config_provider("costs", "year")) + resources("costs_{}.csv".format(config_provider("costs", "year")(w))) if config_provider("foresight")(w) == "overnight" - else "resources/costs_{}.csv".format( + else resources("costs_{}.csv".format( config_provider("scenario", "planning_horizons", 0) - ) + )) ), ac_plot=expand( - RESULTS + "maps/power-network-s{simpl}-{clusters}.pdf", + resources("maps/power-network-s{simpl}-{clusters}.pdf"), **config["scenario"], + run=config["run"]["name"], ), costs_plot=expand( RESULTS @@ -235,9 +230,7 @@ rule make_summary: resources: mem_mb=10000, log: - logs("make_summary.log"), - benchmark: - benchmarks("make_summary") + RESULTS + "logs/make_summary.log", conda: "../envs/environment.yaml" script: @@ -267,9 +260,7 @@ rule plot_summary: resources: mem_mb=10000, log: - logs("plot_summary.log"), - benchmark: - benchmarks("plot_summary") + RESULTS + "logs/plot_summary.log", conda: "../envs/environment.yaml" script: diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 1b2513fb..9e9ff1f0 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -88,10 +88,12 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_cost_data", T output: resources("costs_{year}.csv"), log: - "logs/retrieve_cost_data_{year}.log", + logs("retrieve_cost_data_{year}.log"), resources: mem_mb=1000, retries: 2 + conda: + "../envs/retrieve.yaml" script: "../scripts/retrieve_cost_data.py" @@ -191,6 +193,8 @@ if config["enable"]["retrieve"]: resources: mem_mb=5000, retries: 2 + conda: + "../envs/retrieve.yaml" script: "../scripts/retrieve_electricity_demand.py" diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index d3aa8d4c..b6a7902e 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -2,7 +2,6 @@ # # SPDX-License-Identifier: MIT - rule solve_network: params: solving=config_provider("solving"), diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index a52f17c0..8caf5201 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -16,9 +16,9 @@ rule add_existing_baseyear: busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - costs=lambda w: "resources/costs_{}.csv".format( + costs=lambda w: resources("costs_{}.csv".format( config_provider("scenario", "planning_horizons", 0)(w) - ), + )), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), existing_heating_distribution=resources( @@ -76,7 +76,7 @@ rule add_brownfield: network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", network_p=solved_previous_horizon, #solved network at previous time step - costs="resources/costs_{planning_horizons}.csv", + costs=resources("costs_{planning_horizons}.csv"), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), output: @@ -114,7 +114,7 @@ rule solve_sector_network_myopic: input: network=RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - costs="resources/costs_{planning_horizons}.csv", + costs=resources("costs_{planning_horizons}.csv"), config=RESULTS + "config.yaml", output: RESULTS diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 0d94ad9c..af5e884c 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -14,9 +14,9 @@ rule add_existing_baseyear: busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - costs="resources/costs_{}.csv".format( + costs=resources("costs_{}.csv".format( config_provider("scenario", "planning_horizons", 0) - ), + )), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), existing_heating_distribution=resources( @@ -98,7 +98,7 @@ rule solve_sector_network_perfect: input: network=RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", - costs="resources/costs_2030.csv", + costs=resources("costs_2030.csv"), config=RESULTS + "config.yaml", output: RESULTS @@ -140,7 +140,7 @@ def input_networks_make_summary_perfect(w): rule make_summary_perfect: input: unpack(input_networks_make_summary_perfect), - costs="resources/costs_2020.csv", + costs=resources("costs_2020.csv"), output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", nodal_capacities=RESULTS + "csvs/nodal_capacities.csv", diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 1aa90168..c33d39f6 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -52,15 +52,16 @@ def get_run_path(fn, dir, rdir, shared_resources): Notes ----- - Special case for "base" allows no wildcards other than - "technology" and excludes filenames starting with "networks/elec" or + Special case for "base" allows no wildcards other than "technology", "year" + and "scope" and excludes filenames starting with "networks/elec" or "add_electricity". """ pattern = r"\{([^{}]+)\}" - existing_wildcards = list(re.findall(pattern, fn)) + existing_wildcards = set(re.findall(pattern, fn)) if shared_resources == "base": # special case for shared "base" resources - no_relevant_wildcards = not len(set(existing_wildcards) - {"technology"}) + irrelevant_wildcards = {"technology", "year", "scope"} + no_relevant_wildcards = not len(existing_wildcards - irrelevant_wildcards) no_elec_rule = not fn.startswith("networks/elec") and not fn.startswith( "add_electricity" ) @@ -68,7 +69,7 @@ def get_run_path(fn, dir, rdir, shared_resources): elif isinstance(shared_resources, (str, list)): if isinstance(shared_resources, str): shared_resources = [shared_resources] - is_shared = set(existing_wildcards).issubset(shared_resources) + is_shared = (existing_wildcards).issubset(shared_resources) else: is_shared = shared_resources From c22e47cd58e46b98fb591e5d951652518257e61a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 12:07:37 +0100 Subject: [PATCH 310/591] add release note --- doc/release_notes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index cab8229a..08ec9dd5 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,11 @@ Release Notes Upcoming Release ================ +* Regions are assigned to all buses with unique coordinates in the network with + a preference given to substations. Previously, only substations had assigned + regions, but this could lead to issues when a high spatial resolution was + applied. + * The default configuration ``config/config.default.yaml`` is now automatically used as a base configuration file and no longer copied to ``config/config.yaml`` on first use. The file ``config/config.yaml`` should be From 67484f9cf0428bf8d8c8e463730db9c0001e064d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 12:13:35 +0100 Subject: [PATCH 311/591] remove numpy import, add release ntoe --- doc/release_notes.rst | 4 ++++ rules/build_sector.smk | 2 -- scripts/build_ammonia_production.py | 4 +--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index cab8229a..fc58c899 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,10 @@ Release Notes Upcoming Release ================ +* Include all countries in ammonia production resource. This is so that the full + EU28 ammonia demand can be correctly subtracted in the rule + :mod:`build_industry_sector_ratios`. + * The default configuration ``config/config.default.yaml`` is now automatically used as a base configuration file and no longer copied to ``config/config.yaml`` on first use. The file ``config/config.yaml`` should be diff --git a/rules/build_sector.smk b/rules/build_sector.smk index c25c8673..35a59008 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -392,8 +392,6 @@ rule build_salt_cavern_potentials: rule build_ammonia_production: - params: - countries=config["countries"], input: usgs="data/bundle-sector/myb1-2017-nitro.xls", output: diff --git a/scripts/build_ammonia_production.py b/scripts/build_ammonia_production.py index 77b33075..e2cf6a7b 100644 --- a/scripts/build_ammonia_production.py +++ b/scripts/build_ammonia_production.py @@ -7,7 +7,6 @@ Build historical annual ammonia production per country in ktonNH3/a. """ import country_converter as coco -import numpy as np import pandas as pd cc = coco.CountryConverter() @@ -26,6 +25,7 @@ if __name__ == "__main__": header=0, index_col=0, skipfooter=19, + na_values=["--"], ) ammonia.index = cc.convert(ammonia.index, to="iso2") @@ -33,8 +33,6 @@ if __name__ == "__main__": years = [str(i) for i in range(2013, 2018)] ammonia = ammonia[years] - ammonia.replace("--", np.nan, inplace=True) - ammonia = ammonia.astype(float) # convert from ktonN to ktonNH3 ammonia *= 17 / 14 From 7e66c1428d5a538efd0917ed2ff8002e1e9fcfec Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 12:40:05 +0100 Subject: [PATCH 312/591] add release note --- doc/release_notes.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index cab8229a..ffe1a794 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,9 @@ Release Notes Upcoming Release ================ +* Bugfix: Correct units of subtracted chlorine and methanol demand in + :mod:`build_industry_sector_ratios`. + * The default configuration ``config/config.default.yaml`` is now automatically used as a base configuration file and no longer copied to ``config/config.yaml`` on first use. The file ``config/config.yaml`` should be From 6d80b332e606c7569e180f8519204a3be30724a4 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 12:47:01 +0100 Subject: [PATCH 313/591] add release note --- doc/release_notes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index ee7bd64b..ccb886e6 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,11 @@ Release Notes Upcoming Release ================ +* Bugfix: The industry coal emissions for industry were not properly tracked. + +* Allow industrial coal demand to be regional so its emissions can be included + in regional emission limits. + * Add new default to overdimension heating in individual buildings. This allows them to cover heat demand peaks e.g. 10% higher than those in the data. The disadvantage of manipulating the costs is that the capacity is then not quite From 472a09988101d280b434d5d26947a5408f54cceb Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 13:30:52 +0100 Subject: [PATCH 314/591] add_electricity: set locations and units of electricity buses --- scripts/add_electricity.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 614e3330..9ac3638d 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -903,5 +903,9 @@ if __name__ == "__main__": sanitize_carriers(n, snakemake.config) + # set locations and units of electricity buses + n.buses["location"] = n.buses.index + n.buses["unit"] = "MWh_el" + n.meta = snakemake.config n.export_to_netcdf(snakemake.output[0]) From 9e8ed7394d65fcf24d0f631f22656a2dc544d61e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 13:32:24 +0100 Subject: [PATCH 315/591] Update config/config.default.yaml --- config/config.default.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 97b0edb3..48f2a78d 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -538,8 +538,8 @@ sector: efficiency_static: 0.98 efficiency_per_1000km: 0.977 H2 pipeline: - efficiency_per_1000km: 0.9905 - compression_per_1000km: 0.008 + efficiency_per_1000km: 1 # 0.982 + compression_per_1000km: 0.018 gas pipeline: efficiency_per_1000km: 1 #0.977 compression_per_1000km: 0.01 From 93bb4e5f54c09ae9f3e571e07e83444150c6f59b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 15:14:18 +0100 Subject: [PATCH 316/591] add release note, simplify build_industry_sector_ratios_intermediate script --- doc/configtables/industry.csv | 2 + doc/release_notes.rst | 9 +++ ...ild_industry_sector_ratios_intermediate.py | 60 ++++++++----------- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/doc/configtables/industry.csv b/doc/configtables/industry.csv index fc1b3f0f..d1b560ed 100644 --- a/doc/configtables/industry.csv +++ b/doc/configtables/industry.csv @@ -17,6 +17,8 @@ HVC_primary_fraction,--,float,The fraction of high value chemicals (HVC) produce HVC_mechanical_recycling _fraction,--,float,The fraction of high value chemicals (HVC) produced using mechanical recycling HVC_chemical_recycling _fraction,--,float,The fraction of high value chemicals (HVC) produced using chemical recycling ,,, +sector_ratios_fraction_future,--,Dictionary with planning horizons as keys.,The fraction of total progress in fuel and process switching achieved in the industry sector. +basic_chemicals_without_NH3_production_today,Mt/a,float,"The amount of basic chemicals produced without ammonia (= 86 Mtethylene-equiv - 17 MtNH3)." HVC_production_today,MtHVC/a,float,"The amount of high value chemicals (HVC) produced. This includes ethylene, propylene and BTX. From `DECHEMA (2017) `_, Figure 16, page 107" Mwh_elec_per_tHVC _mechanical_recycling,MWh/tHVC,float,"The energy amount of electricity needed to produce a ton of high value chemical (HVC) using mechanical recycling. From SI of `Meys et al (2020) `_, Table S5, for HDPE, PP, PS, PET. LDPE would be 0.756." Mwh_elec_per_tHVC _chemical_recycling,MWh/tHVC,float,"The energy amount of electricity needed to produce a ton of high value chemical (HVC) using chemical recycling. The default value is based on pyrolysis and electric steam cracking. From `Material Economics (2019) `_, page 125" diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 1a7564d5..b4425308 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,15 @@ Release Notes Upcoming Release ================ +* Improved representation of industry transition pathways. A new script was + added to interpolate industry sector ratios from today's status quo to future + systems (i.e. specific emissions and demands for energy and feedstocks). For + each country we gradually switch industry processes from today's specific + energy carrier usage per ton material output to the best-in-class energy + consumption of tomorrow. This is done on a per-country basis. The ratio of + today to tomorrow's energy consumption is set with the ``industry: + sector_ratios_fraction_future:`` parameter. + * Bugfix: Correct units of subtracted chlorine and methanol demand in :mod:`build_industry_sector_ratios`. diff --git a/scripts/build_industry_sector_ratios_intermediate.py b/scripts/build_industry_sector_ratios_intermediate.py index 0cbdfa06..4b1a2d34 100644 --- a/scripts/build_industry_sector_ratios_intermediate.py +++ b/scripts/build_industry_sector_ratios_intermediate.py @@ -25,62 +25,52 @@ def build_industry_sector_ratios_intermediate(): production = ( pd.read_csv(snakemake.input.industrial_production_per_country, index_col=0) / 1e3 - ) - production = production.unstack().swaplevel() + ).stack() + production.index.names = [None, None] # in MWh/t future_sector_ratios = pd.read_csv( snakemake.input.industry_sector_ratios, index_col=0 ) - production.index.names = [None, None] - today_sector_ratios = demand.div(production, axis=1) - today_sector_ratios.drop( - columns=today_sector_ratios.columns[today_sector_ratios.isna().all()], - inplace=True, - ) + today_sector_ratios.dropna(how="all", axis=1, inplace=True) - rename = pd.Series(today_sector_ratios.index, today_sector_ratios.index) - rename["waste"] = "biomass" - rename["electricity"] = "elec" - rename["solid"] = "coke" - rename["gas"] = "methane" - rename["other"] = "biomass" - rename["liquid"] = "naphtha" - - today_sector_ratios.rename(rename, inplace=True) + rename = { + "waste": "biomass", + "electricity": "elec", + "solid": "coke", + "gas": "methane", + "other": "biomass", + "liquid": "naphtha", + } + today_sector_ratios = today_sector_ratios.rename(rename).groupby(level=0).sum() fraction_future = get(params["sector_ratios_fraction_future"], year) intermediate_sector_ratios = {} - - for ct in today_sector_ratios.columns.unique(level=0): - - intermediate_sector_ratio = future_sector_ratios.copy() - - intermediate_sector_ratio.loc[ - today_sector_ratios[ct].index, today_sector_ratios[ct].columns - ] = ( - fraction_future - * intermediate_sector_ratio.loc[ - today_sector_ratios[ct].index, today_sector_ratios[ct].columns - ] - + (1 - fraction_future) * today_sector_ratios[ct] + for ct, group in today_sector_ratios.T.groupby(level=0): + today_sector_ratios_ct = ( + group.droplevel(0) + .T.reindex_like(future_sector_ratios) + .fillna(future_sector_ratios) + ) + intermediate_sector_ratios[ct] = ( + today_sector_ratios_ct * (1 - fraction_future) + + future_sector_ratios * fraction_future ) - intermediate_sector_ratios[ct] = intermediate_sector_ratio - intermediate_sector_ratios = pd.concat(intermediate_sector_ratios, axis=1) - intermediate_sector_ratios.to_csv(snakemake.output.industry_sector_ratios) - if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_industry_sector_ratios_intermediate") + snakemake = mock_snakemake( + "build_industry_sector_ratios_intermediate", + planning_horizons="2030", + ) year = int(snakemake.wildcards.planning_horizons[-4:]) From 8ae0669b333f0c9387f1a1a8a8bb38f4fa01b82b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 15:31:17 +0100 Subject: [PATCH 317/591] Revert "add_electricity: set locations and units of electricity buses" This reverts commit 472a09988101d280b434d5d26947a5408f54cceb. --- scripts/add_electricity.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 9ac3638d..614e3330 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -903,9 +903,5 @@ if __name__ == "__main__": sanitize_carriers(n, snakemake.config) - # set locations and units of electricity buses - n.buses["location"] = n.buses.index - n.buses["unit"] = "MWh_el" - n.meta = snakemake.config n.export_to_netcdf(snakemake.output[0]) From 27f9fb8cbaf7b377f182fb126246bf8a08772ba6 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 16:18:31 +0100 Subject: [PATCH 318/591] add back in to_csv export (accidentally deleted) --- scripts/build_industry_sector_ratios_intermediate.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/build_industry_sector_ratios_intermediate.py b/scripts/build_industry_sector_ratios_intermediate.py index 4b1a2d34..14e09505 100644 --- a/scripts/build_industry_sector_ratios_intermediate.py +++ b/scripts/build_industry_sector_ratios_intermediate.py @@ -62,6 +62,8 @@ def build_industry_sector_ratios_intermediate(): ) intermediate_sector_ratios = pd.concat(intermediate_sector_ratios, axis=1) + intermediate_sector_ratios.to_csv(snakemake.output.industry_sector_ratios) + if __name__ == "__main__": if "snakemake" not in globals(): From 7f1ff0c3240b545fc5d93eeb8fdef28ef328975a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 16 Feb 2024 16:41:21 +0100 Subject: [PATCH 319/591] Fix plotting of retrofitted hydrogen pipelines with pathway optimisation. --- doc/release_notes.rst | 2 ++ scripts/plot_hydrogen_network.py | 25 ++++++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b4425308..7feb4d72 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -19,6 +19,8 @@ Upcoming Release today to tomorrow's energy consumption is set with the ``industry: sector_ratios_fraction_future:`` parameter. +* Fix plotting of retrofitted hydrogen pipelines with pathway optimisation. + * Bugfix: Correct units of subtracted chlorine and methanol demand in :mod:`build_industry_sector_ratios`. diff --git a/scripts/plot_hydrogen_network.py b/scripts/plot_hydrogen_network.py index 95741170..c6b90ceb 100644 --- a/scripts/plot_hydrogen_network.py +++ b/scripts/plot_hydrogen_network.py @@ -24,6 +24,7 @@ def group_pipes(df, drop_direction=False): """ Group pipes which connect same buses and return overall capacity. """ + df = df.copy() if drop_direction: positive_order = df.bus0 < df.bus1 df_p = df[positive_order] @@ -32,12 +33,13 @@ def group_pipes(df, drop_direction=False): df = pd.concat([df_p, df_n]) # there are pipes for each investment period rename to AC buses name for plotting + df["index_orig"] = df.index df.index = df.apply( lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}", axis=1, ) return df.groupby(level=0).agg( - {"p_nom_opt": "sum", "bus0": "first", "bus1": "first"} + {"p_nom_opt": "sum", "bus0": "first", "bus1": "first", "index_orig": "first"} ) @@ -95,17 +97,18 @@ def plot_h2_map(n, regions): ) if not h2_retro.empty: - positive_order = h2_retro.bus0 < h2_retro.bus1 - h2_retro_p = h2_retro[positive_order] - swap_buses = {"bus0": "bus1", "bus1": "bus0"} - h2_retro_n = h2_retro[~positive_order].rename(columns=swap_buses) - h2_retro = pd.concat([h2_retro_p, h2_retro_n]) + if snakemake.params.foresight != "myopic": + positive_order = h2_retro.bus0 < h2_retro.bus1 + h2_retro_p = h2_retro[positive_order] + swap_buses = {"bus0": "bus1", "bus1": "bus0"} + h2_retro_n = h2_retro[~positive_order].rename(columns=swap_buses) + h2_retro = pd.concat([h2_retro_p, h2_retro_n]) - h2_retro["index_orig"] = h2_retro.index - h2_retro.index = h2_retro.apply( - lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}", - axis=1, - ) + h2_retro["index_orig"] = h2_retro.index + h2_retro.index = h2_retro.apply( + lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}", + axis=1, + ) retro_w_new_i = h2_retro.index.intersection(h2_new.index) h2_retro_w_new = h2_retro.loc[retro_w_new_i] From dd2416a59e16560fbecd6eed383aa60a1c730632 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 11:57:16 +0100 Subject: [PATCH 320/591] handle all {opts} and {sector_opts} wildcard values in config --- config/config.default.yaml | 17 ++- doc/configtables/adjustments.csv | 8 + doc/configtables/clustering.csv | 3 + doc/configtables/sector.csv | 6 + doc/configtables/snapshots.csv | 2 - doc/configuration.rst | 15 ++ rules/build_electricity.smk | 16 +- rules/build_sector.smk | 13 +- rules/postprocess.smk | 5 +- rules/solve_myopic.smk | 2 +- rules/solve_perfect.smk | 2 + rules/validate.smk | 6 +- scripts/_helpers.py | 181 +++++++++++++++++++++- scripts/add_brownfield.py | 4 +- scripts/add_existing_baseyear.py | 7 +- scripts/plot_summary.py | 9 +- scripts/prepare_network.py | 109 +++++--------- scripts/prepare_perfect_foresight.py | 48 ++---- scripts/prepare_sector_network.py | 218 ++++++++------------------- scripts/solve_network.py | 49 ++---- scripts/solve_operations_network.py | 10 +- 21 files changed, 385 insertions(+), 345 deletions(-) create mode 100644 doc/configtables/adjustments.csv diff --git a/config/config.default.yaml b/config/config.default.yaml index 91f38b91..1b207f1e 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -59,9 +59,6 @@ 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: @@ -366,6 +363,11 @@ existing_capacities: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#sector sector: + transport: true + heating: true + biomass: true + industry: true + agriculture: true district_heating: potential: 0.6 progress: @@ -531,6 +533,7 @@ sector: use_methanation_waste_heat: true use_fuel_cell_waste_heat: true use_electrolysis_waste_heat: true + electricity_transmission_grid: true electricity_distribution_grid: true electricity_distribution_grid_cost_factor: 1.0 electricity_grid_connection: true @@ -712,6 +715,14 @@ clustering: committable: any ramp_limit_up: max ramp_limit_down: max + temporal: + resolution_elec: false + resolution_sector: false + +# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#adjustments +adjustments: + electricity: false + sector: false # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#solving solving: diff --git a/doc/configtables/adjustments.csv b/doc/configtables/adjustments.csv new file mode 100644 index 00000000..52617352 --- /dev/null +++ b/doc/configtables/adjustments.csv @@ -0,0 +1,8 @@ +,Unit,Values,Description +adjustments,,, +-- electricity,bool or dict,,"Parameter adjustments for capital cost, marginal cost, and maximum capacities of carriers. Applied in :mod:`prepare_network.`" +-- -- {attr},,,"Attribute can be ``e_nom_opt``, ``p_nom_opt``, ``marginal_cost`` or ``capital_cost``" +-- -- -- {carrier},float,per-unit,"Any carrier of the network to which parameter adjustment factor should be applied." +-- sector,bool or dict,,"Parameter adjustments for capital cost, marginal cost, and maximum capacities of carriers. Applied in :mod:`prepare_sector_network.`" +-- -- {attr},,,"Attribute can be ``e_nom_opt``, ``p_nom_opt``, ``marginal_cost`` or ``capital_cost``" +-- -- -- {carrier},float,per-unit,"Any carrier of the network to which parameter adjustment factor should be applied." diff --git a/doc/configtables/clustering.csv b/doc/configtables/clustering.csv index e831ca84..65411738 100644 --- a/doc/configtables/clustering.csv +++ b/doc/configtables/clustering.csv @@ -17,3 +17,6 @@ aggregation_strategies,,, -- -- {key},str,"{key} can be any of the component of the generator (str). It’s value can be any that can be converted to pandas.Series using getattr(). For example one of {min, max, sum}.","Aggregates the component according to the given strategy. For example, if sum, then all values within each cluster are summed to represent the new generator." -- buses,,, -- -- {key},str,"{key} can be any of the component of the bus (str). It’s value can be any that can be converted to pandas.Series using getattr(). For example one of {min, max, sum}.","Aggregates the component according to the given strategy. For example, if sum, then all values within each cluster are summed to represent the new bus." +temporal,,,Options for temporal resolution +-- resolution_elec,--,"{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." +-- resolution_sector,--,"{false,``nH``; i.e. ``2H``-``6H``}","Resample the time-resolution by averaging over every ``n`` snapshots in :mod:`prepare_sector_network`." diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv index d8cc3288..1f8bb030 100644 --- a/doc/configtables/sector.csv +++ b/doc/configtables/sector.csv @@ -1,4 +1,9 @@ ,Unit,Values,Description +transport,--,"{true, false}",Flag to include transport sector. +heating,--,"{true, false}",Flag to include heating sector. +biomass,--,"{true, false}",Flag to include biomass sector. +industry,--,"{true, false}",Flag to include industry sector. +agriculture,--,"{true, false}",Flag to include agriculture sector. district_heating,--,,`prepare_sector_network.py `_ -- potential,--,float,maximum fraction of urban demand which can be supplied by district heating -- progress,--,Dictionary with planning horizons as keys., Increase of today's district heating demand to potential maximum district heating share. Progress = 0 means today's district heating share. Progress = 1 means maximum fraction of urban demand is supplied by district heating @@ -109,6 +114,7 @@ min_part_load _methanolisation,per unit of p_nom ,float,The minimum unit dispatc use_fischer_tropsch _waste_heat,--,"{true, false}",Add option for using waste heat of Fischer Tropsch in district heating networks use_fuel_cell_waste_heat,--,"{true, false}",Add option for using waste heat of fuel cells in district heating networks use_electrolysis_waste _heat,--,"{true, false}",Add option for using waste heat of electrolysis in district heating networks +electricity_transmission _grid,--,"{true, false}",Switch for enabling/disabling the electricity transmission grid. electricity_distribution _grid,--,"{true, false}",Add a simplified representation of the exchange capacity between transmission and distribution grid level through a link. electricity_distribution _grid_cost_factor,,,Multiplies the investment cost of the electricity distribution grid ,,, diff --git a/doc/configtables/snapshots.csv b/doc/configtables/snapshots.csv index 0226a9aa..4be0439b 100644 --- a/doc/configtables/snapshots.csv +++ b/doc/configtables/snapshots.csv @@ -2,5 +2,3 @@ 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 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." diff --git a/doc/configuration.rst b/doc/configuration.rst index f65aa4c2..e8b0426a 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -561,6 +561,21 @@ The list of available biomass is given by the category in `ENSPRESO_BIOMASS 0: - return True, float(m[0]) + return True, float(m[0].replace("p", ".").replace("m", "-")) else: return True, None return False, None @@ -379,13 +380,177 @@ def parse(infix): return {infix.pop(0): parse(infix)} -def update_config_with_sector_opts(config, sector_opts): - from snakemake.utils import update_config +def update_config_from_wildcards(config, w): + """ + Parses configuration settings from wildcards and updates the config. - for o in sector_opts.split("-"): - if o.startswith("CF+"): - infix = o.split("+")[1:] - update_config(config, parse(infix)) + - TODO: Should be run inside config_provider function. + """ + + if w.get("opts"): + opts = w.opts.split("-") + + if nhours := get_opt(opts, r"^\d+(h|seg)$"): + config["clustering"]["temporal"]["resolution_elec"] = nhours + + co2l_enable, co2l_value = find_opt(opts, "Co2L") + if co2l_enable: + config["electricity"]["co2limit_enable"] = True + if co2l_value is not None: + config["electricity"]["co2limit"] = ( + co2l_value * config["electricity"]["co2base"] + ) + + gasl_enable, gasl_value = find_opt(opts, "CH4L") + if gasl_enable: + config["electricity"]["gaslimit_enable"] = True + if gasl_value is not None: + config["electricity"]["gaslimit"] = gasl_value * 1e6 + + if "Ept" in opts: + config["costs"]["emission_prices"]["co2_monthly_prices"] = True + + ep_enable, ep_value = find_opt(opts, "Ep") + if ep_enable: + config["costs"]["emission_prices"]["enable"] = True + if ep_value is not None: + config["costs"]["emission_prices"]["co2"] = ep_value + + if "ATK" in opts: + config["autarky"]["enable"] = True + if "ATKc" in opts: + config["autarky"]["by_country"] = True + + attr_lookup = { + "p": "p_nom_max", + "e": "e_nom_max", + "c": "capital_cost", + "m": "marginal_cost", + } + for o in opts: + flags = ["+e", "+p", "+m", "+c"] + if all(flag not in o for flag in flags): + continue + carrier, attr_factor = o.split("+") + attr = attr_lookup[attr_factor[0]] + factor = float(attr_factor[1:]) + if not isinstance(config["adjustments"]["electricity"], dict): + config["adjustments"]["electricity"] = dict() + update_config( + config["adjustments"]["electricity"], {attr: {carrier: factor}} + ) + + if w.get("sector_opts"): + opts = w.sector_opts.split("-") + + if "T" in opts: + config["sector"]["transport"] = True + + if "H" in opts: + config["sector"]["heating"] = True + + if "B" in opts: + config["sector"]["biomass"] = True + + if "I" in opts: + config["sector"]["industry"] = True + + if "A" in opts: + config["sector"]["agriculture"] = True + + if "CCL" in opts: + config["solving"]["constraints"]["CCL"] = True + + eq_value = get_opt(opts, r"^EQ+\d*\.?\d+(c|)") + for o in opts: + if eq_value is not None: + config["solving"]["constraints"]["EQ"] = eq_value + elif "EQ" in o: + config["solving"]["constraints"]["EQ"] = True + break + + if "BAU" in opts: + config["solving"]["constraints"]["BAU"] = True + + if "SAFE" in opts: + config["solving"]["constraints"]["SAFE"] = True + + if nhours := get_opt(opts, r"^\d+(h|sn|seg)$"): + config["clustering"]["temporal"]["resolution_sector"] = nhours + + if "decentral" in opts: + config["sector"]["electricity_transmission_grid"] = False + + if "noH2network" in opts: + config["sector"]["H2_network"] = False + + if "nowasteheat" in opts: + config["sector"]["use_fischer_tropsch_waste_heat"] = False + config["sector"]["use_methanolisation_waste_heat"] = False + config["sector"]["use_haber_bosch_waste_heat"] = False + config["sector"]["use_methanation_waste_heat"] = False + config["sector"]["use_fuel_cell_waste_heat"] = False + config["sector"]["use_electrolysis_waste_heat"] = False + + if "nodistrict" in opts: + config["sector"]["district_heating"]["progress"] = 0.0 + + dg_enable, dg_factor = find_opt(opts, "dist") + if dg_enable: + config["sector"]["electricity_distribution_grid"] = True + if dg_factor is not None: + config["sector"][ + "electricity_distribution_grid_cost_factor" + ] = dg_factor + + if "biomasstransport" in opts: + config["sector"]["biomass_transport"] = True + + _, maxext = find_opt(opts, "linemaxext") + if maxext is not None: + config["lines"]["max_extension"] = maxext * 1e3 + config["links"]["max_extension"] = maxext * 1e3 + + _, co2l_value = find_opt(opts, "Co2L") + if co2l_value is not None: + config["co2_budget"] = float(co2l_value) + + if co2_distribution := get_opt(opts, r"^(cb)\d+(\.\d+)?(ex|be)$"): + config["co2_budget"] = co2_distribution + + if co2_budget := get_opt(opts, r"^(cb)\d+(\.\d+)?$"): + config["co2_budget"] = float(co2_budget[2:]) + + attr_lookup = { + "p": "p_nom_max", + "e": "e_nom_max", + "c": "capital_cost", + "m": "marginal_cost", + } + for o in opts: + flags = ["+e", "+p", "+m", "+c"] + if all(flag not in o for flag in flags): + continue + carrier, attr_factor = o.split("+") + attr = attr_lookup[attr_factor[0]] + factor = float(attr_factor[1:]) + if not isinstance(config["adjustments"]["sector"], dict): + config["adjustments"]["sector"] = dict() + update_config(config["adjustments"]["sector"], {attr: {carrier: factor}}) + + _, sdr_value = find_opt(opts, "sdr") + if sdr_value is not None: + config["costs"]["social_discountrate"] = sdr_value / 100 + + _, seq_limit = find_opt(opts, "seq") + if seq_limit is not None: + config["sector"]["co2_sequestration_potential"] = seq_limit + + # any config option can be represented in wildcard + for o in opts: + if o.startswith("CF+"): + infix = o.split("+")[1:] + update_config(config, parse(infix)) def get_checksum_from_zenodo(file_url): diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 3b77c437..329bde4c 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -12,7 +12,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import update_config_with_sector_opts +from _helpers import update_config_from_wildcards from add_existing_baseyear import add_build_year_to_new_assets from pypsa.clustering.spatial import normed_or_uniform @@ -212,7 +212,7 @@ if __name__ == "__main__": logging.basicConfig(level=snakemake.config["logging"]["level"]) - update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) + update_config_from_wildcards(snakemake.config, snakemake.wildcards) logger.info(f"Preparing brownfield from the file {snakemake.input.network_p}") diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index c0d37a5b..02711f59 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -15,7 +15,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import update_config_with_sector_opts +from _helpers import update_config_from_wildcards from add_electricity import sanitize_carriers from prepare_sector_network import cluster_heat_buses, define_spatial, prepare_costs @@ -554,10 +554,9 @@ if __name__ == "__main__": logging.basicConfig(level=snakemake.config["logging"]["level"]) - update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) + update_config_from_wildcards(snakemake.config, snakemake.wildcards) options = snakemake.params.sector - opts = snakemake.wildcards.sector_opts.split("-") baseyear = snakemake.params.baseyear @@ -580,7 +579,7 @@ if __name__ == "__main__": n, grouping_years_power, costs, baseyear ) - if "H" in opts: + if options["heating"]: time_dep_hp_cop = options["time_dep_hp_cop"] ashp_cop = ( xr.open_dataarray(snakemake.input.cop_air_total) diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index cfb32441..05ffa2d4 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -582,7 +582,8 @@ if __name__ == "__main__": plot_balances() - for sector_opts in snakemake.params.sector_opts: - opts = sector_opts.split("-") - if any("cb" in o for o in opts) or snakemake.config["foresight"] == "perfect": - plot_carbon_budget_distribution(snakemake.input.eurostat) + if ( + snakemake.params["co2_budget"].startswith("cb") + or snakemake.params["foresight"] == "perfect" + ): + plot_carbon_budget_distribution(snakemake.input.eurostat) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index e358c05e..a9216d51 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -62,7 +62,7 @@ import logging import numpy as np import pandas as pd import pypsa -from _helpers import configure_logging, find_opt, get_opt +from _helpers import configure_logging, update_config_from_wildcards from add_electricity import load_costs, update_transmission_costs from pypsa.descriptors import expand_series @@ -71,6 +71,28 @@ idx = pd.IndexSlice logger = logging.getLogger(__name__) +def maybe_adjust_costs_and_potentials(n, adjustments): + if not adjustments: + return + + for attr, carrier_factor in adjustments.items(): + for carrier, factor in carrier_factor.items(): + # beware if factor is 0 and p_nom_max is np.inf, 0*np.inf is nan + if carrier == "AC": # lines do not have carrier + n.lines[attr] *= factor + continue + comps = { + "p_nom_max": {"Generator", "Link", "StorageUnit"}, + "e_nom_max": {"Store"}, + "capital_cost": {"Generator", "Link", "StorageUnit", "Store"}, + "marginal_cost": {"Generator", "Link", "StorageUnit", "Store"}, + } + for c in n.iterate_components(comps[attr]): + sel = c.df.index[c.df.carrier == carrier] + c.df.loc[sel, attr] *= factor + logger.info(f"changing {attr} for {carrier} by factor {factor}") + + def add_co2limit(n, co2limit, Nyears=1.0): n.add( "GlobalConstraint", @@ -278,11 +300,10 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "prepare_network", simpl="", clusters="37", ll="v1.0", opts="Ept" + "prepare_network", simpl="", clusters="37", ll="v1.0", opts="Co2L-4H" ) configure_logging(snakemake) - - opts = snakemake.wildcards.opts.split("-") + update_config_from_wildcards(snakemake.config, snakemake.wildcards) n = pypsa.Network(snakemake.input[0]) Nyears = n.snapshot_weightings.objective.sum() / 8760.0 @@ -296,81 +317,32 @@ if __name__ == "__main__": set_line_s_max_pu(n, snakemake.params.lines["s_max_pu"]) # temporal averaging - nhours_config = snakemake.params.snapshots.get("resolution", False) - nhours_wildcard = get_opt(opts, r"^\d+h$") - nhours = nhours_wildcard or nhours_config - if nhours: + if nhours := snakemake.params.time_resolution: n = average_every_nhours(n, nhours) # segments with package tsam - time_seg_config = snakemake.params.snapshots.get("segmentation", False) - time_seg_wildcard = get_opt(opts, r"^\d+seg$") - time_seg = time_seg_wildcard or time_seg_config - if time_seg: + if time_seg := snakemake.params.time_resolution: solver_name = snakemake.config["solving"]["solver"]["name"] n = apply_time_segmentation(n, time_seg.replace("seg", ""), solver_name) - Co2L_config = snakemake.params.co2limit_enable - Co2L_wildcard, co2limit_wildcard = find_opt(opts, "Co2L") - if Co2L_wildcard or Co2L_config: - if co2limit_wildcard is not None: - co2limit = co2limit_wildcard * snakemake.params.co2base - add_co2limit(n, co2limit, Nyears) - logger.info("Setting CO2 limit according to wildcard value.") - else: - add_co2limit(n, snakemake.params.co2limit, Nyears) - logger.info("Setting CO2 limit according to config value.") + if snakemake.params.co2limit_enable: + add_co2limit(n, snakemake.params.co2limit, Nyears) - CH4L_config = snakemake.params.gaslimit_enable - CH4L_wildcard, gaslimit_wildcard = find_opt(opts, "CH4L") - if CH4L_wildcard or CH4L_config: - if gaslimit_wildcard is not None: - gaslimit = gaslimit_wildcard * 1e6 - add_gaslimit(n, gaslimit, Nyears) - logger.info("Setting gas usage limit according to wildcard value.") - else: - add_gaslimit(n, snakemake.params.gaslimit, Nyears) - logger.info("Setting gas usage limit according to config value.") + if snakemake.params.gaslimit_enable: + add_gaslimit(n, snakemake.params.gaslimit, Nyears) - for o in opts: - if "+" not in o: - continue - oo = o.split("+") - suptechs = map(lambda c: c.split("-", 2)[0], n.carriers.index) - if oo[0].startswith(tuple(suptechs)): - carrier = oo[0] - # handles only p_nom_max as stores and lines have no potentials - attr_lookup = {"p": "p_nom_max", "c": "capital_cost", "m": "marginal_cost"} - attr = attr_lookup[oo[1][0]] - factor = float(oo[1][1:]) - if carrier == "AC": # lines do not have carrier - n.lines[attr] *= factor - else: - comps = {"Generator", "Link", "StorageUnit", "Store"} - for c in n.iterate_components(comps): - sel = c.df.carrier.str.contains(carrier) - c.df.loc[sel, attr] *= factor + maybe_adjust_costs_and_potentials(n, snakemake.params["adjustments"]) emission_prices = snakemake.params.costs["emission_prices"] - Ept_config = emission_prices.get("co2_monthly_prices", False) - Ept_wildcard = "Ept" in opts - Ep_config = emission_prices.get("enable", False) - Ep_wildcard, co2_wildcard = find_opt(opts, "Ep") - - if Ept_wildcard or Ept_config: + if emission_prices["co2_monthly_prices"]: logger.info( "Setting time dependent emission prices according spot market price" ) add_dynamic_emission_prices(n) - elif Ep_wildcard or Ep_config: - if co2_wildcard is not None: - logger.info("Setting CO2 prices according to wildcard value.") - add_emission_prices(n, dict(co2=co2_wildcard)) - else: - logger.info("Setting CO2 prices according to config value.") - add_emission_prices( - n, dict(co2=snakemake.params.costs["emission_prices"]["co2"]) - ) + elif emission_prices["enable"]: + add_emission_prices( + n, dict(co2=snakemake.params.costs["emission_prices"]["co2"]) + ) ll_type, factor = snakemake.wildcards.ll[0], snakemake.wildcards.ll[1:] set_transmission_limit(n, ll_type, factor, costs, Nyears) @@ -383,11 +355,8 @@ if __name__ == "__main__": p_nom_max_ext=snakemake.params.links.get("max_extension", np.inf), ) - autarky_config = snakemake.params.autarky - if "ATK" in opts or autarky_config.get("enable", False): - only_crossborder = False - if "ATKc" in opts or autarky_config.get("by_country", False): - only_crossborder = True + if snakemake.params.autarky["enable"]: + only_crossborder = snakemake.params.autarky["by_country"] enforce_autarky(n, only_crossborder=only_crossborder) n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index cf013577..54b2ecc0 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -12,7 +12,7 @@ import re import numpy as np import pandas as pd import pypsa -from _helpers import update_config_with_sector_opts +from _helpers import update_config_from_wildcards from add_existing_baseyear import add_build_year_to_new_assets from pypsa.descriptors import expand_series from pypsa.io import import_components_from_dataframe @@ -304,17 +304,14 @@ def set_all_phase_outs(n): n.mremove("Link", remove_i) -def set_carbon_constraints(n, opts): +def set_carbon_constraints(n): """ Add global constraints for carbon emissions. """ - budget = None - for o in opts: - # other budgets - m = re.match(r"^\d+p\d$", o, re.IGNORECASE) - if m is not None: - budget = snakemake.config["co2_budget"][m.group(0)] * 1e9 - if budget is not None: + budget = snakemake.config["co2_budget"] + if budget and isinstance(budget, float): + budget *= 1e9 # convert to t CO2 + logger.info(f"add carbon budget of {budget}") n.add( "GlobalConstraint", @@ -341,7 +338,7 @@ def set_carbon_constraints(n, opts): ) # set minimum CO2 emission constraint to avoid too fast reduction - if "co2min" in opts: + if "co2min" in snakemake.wildcards.sector_opts.split("-"): emissions_1990 = 4.53693 emissions_2019 = 3.344096 target_2030 = 0.45 * emissions_1990 @@ -487,21 +484,6 @@ def apply_time_segmentation_perfect( return n -def set_temporal_aggregation_SEG(n, opts, solver_name): - """ - Aggregate network temporally with tsam. - """ - for o in opts: - # segments with package tsam - m = re.match(r"^(\d+)seg$", o, re.IGNORECASE) - if m is not None: - segments = int(m[1]) - logger.info(f"Use temporal segmentation with {segments} segments") - n = apply_time_segmentation_perfect(n, segments, solver_name=solver_name) - break - return n - - if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -515,14 +497,10 @@ if __name__ == "__main__": sector_opts="1p7-4380H-T-H-B-I-A-dist1", ) - update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) + update_config_from_wildcards(snakemake.config, snakemake.wildcards) # parameters ----------------------------------------------------------- years = snakemake.config["scenario"]["planning_horizons"] - opts = snakemake.wildcards.sector_opts.split("-") - social_discountrate = snakemake.config["costs"]["social_discountrate"] - for o in opts: - if "sdr" in o: - social_discountrate = float(o.replace("sdr", "")) / 100 + social_discountrate = snakemake.params.costs["social_discountrate"] logger.info( f"Concat networks of investment period {years} with social discount rate of {social_discountrate * 100}%" @@ -532,9 +510,10 @@ if __name__ == "__main__": n = concat_networks(years) # temporal aggregate - opts = snakemake.wildcards.sector_opts.split("-") solver_name = snakemake.config["solving"]["solver"]["name"] - n = set_temporal_aggregation_SEG(n, opts, solver_name) + segments = snakemake.params["clustering"]["temporal"]["resolution_sector"] + if isinstance(segments, (int, float)): + n = apply_time_segmentation_perfect(n, segments, solver_name=solver_name) # adjust global constraints lv limit if the same for all years n = adjust_lvlimit(n) @@ -550,8 +529,7 @@ if __name__ == "__main__": add_H2_boilers(n) # set carbon constraints - opts = snakemake.wildcards.sector_opts.split("-") - n = set_carbon_constraints(n, opts) + n = set_carbon_constraints(n) # export network n.export_to_netcdf(snakemake.output[0]) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 5d5e271b..d9cce254 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -9,7 +9,6 @@ technologies for the buildings, transport and industry sectors. import logging import os -import re from itertools import product from types import SimpleNamespace @@ -18,11 +17,12 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import update_config_with_sector_opts +from _helpers import configure_logging, update_config_from_wildcards from add_electricity import calculate_annuity, sanitize_carriers, sanitize_locations from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement from networkx.algorithms.connectivity.edge_augmentation import k_edge_augmentation +from prepare_network import maybe_adjust_costs_and_potentials from pypsa.geo import haversine_pts from pypsa.io import import_components_from_dataframe from scipy.stats import beta @@ -190,13 +190,13 @@ def define_spatial(nodes, options): spatial = SimpleNamespace() -def emission_sectors_from_opts(opts): +def determine_emission_sectors(options): sectors = ["electricity"] - if "T" in opts: + if options["transport"]: sectors += ["rail non-elec", "road non-elec"] - if "H" in opts: + if options["heating"]: sectors += ["residential non-elec", "services non-elec"] - if "I" in opts: + if options["industry"]: sectors += [ "industrial non-elec", "industrial processes", @@ -205,7 +205,7 @@ def emission_sectors_from_opts(opts): "domestic navigation", "international navigation", ] - if "A" in opts: + if options["agriculture"]: sectors += ["agriculture"] return sectors @@ -219,7 +219,7 @@ def get(item, investment_year=None): def co2_emissions_year( - countries, input_eurostat, opts, emissions_scope, report_year, input_co2, year + countries, input_eurostat, options, emissions_scope, report_year, input_co2, year ): """ Calculate CO2 emissions in one specific year (e.g. 1990 or 2018). @@ -237,7 +237,7 @@ def co2_emissions_year( co2_totals = build_co2_totals(countries, eea_co2, eurostat_co2) - sectors = emission_sectors_from_opts(opts) + sectors = determine_emission_sectors(options) co2_emissions = co2_totals.loc[countries, sectors].sum().sum() @@ -248,11 +248,12 @@ def co2_emissions_year( # TODO: move to own rule with sector-opts wildcard? -def build_carbon_budget(o, input_eurostat, fn, emissions_scope, report_year): +def build_carbon_budget( + o, input_eurostat, fn, emissions_scope, report_year, input_co2, options +): """ Distribute carbon budget following beta or exponential transition path. """ - # opts? if "be" in o: # beta decay @@ -268,7 +269,7 @@ def build_carbon_budget(o, input_eurostat, fn, emissions_scope, report_year): e_1990 = co2_emissions_year( countries, input_eurostat, - opts, + options, emissions_scope, report_year, input_co2, @@ -279,7 +280,7 @@ def build_carbon_budget(o, input_eurostat, fn, emissions_scope, report_year): e_0 = co2_emissions_year( countries, input_eurostat, - opts, + options, emissions_scope, report_year, input_co2, @@ -756,12 +757,12 @@ def add_dac(n, costs): ) -def add_co2limit(n, nyears=1.0, limit=0.0): +def add_co2limit(n, options, nyears=1.0, limit=0.0): logger.info(f"Adding CO2 budget limit as per unit of 1990 levels of {limit}") countries = snakemake.params.countries - sectors = emission_sectors_from_opts(opts) + sectors = determine_emission_sectors(options) # convert Mt to tCO2 co2_totals = 1e6 * pd.read_csv(snakemake.input.co2_totals_name, index_col=0) @@ -2000,13 +2001,6 @@ def add_heat(n, costs): if options["retrofitting"]["retro_endogen"]: logger.info("Add retrofitting endogenously") - # resample heat demand temporal 'heat_demand_r' depending on in config - # specified temporal resolution, to not overestimate retrofitting - hours = list(filter(re.compile(r"^\d+h$", re.IGNORECASE).search, opts)) - if len(hours) == 0: - hours = [n.snapshots[1] - n.snapshots[0]] - heat_demand_r = heat_demand.resample(hours[0]).mean() - # retrofitting data 'retro_data' with 'costs' [EUR/m^2] and heat # demand 'dE' [per unit of original heat demand] for each country and # different retrofitting strengths [additional insulation thickness in m] @@ -2024,12 +2018,12 @@ def add_heat(n, costs): # share of space heat demand 'w_space' of total heat demand w_space = {} for sector in sectors: - w_space[sector] = heat_demand_r[sector + " space"] / ( - heat_demand_r[sector + " space"] + heat_demand_r[sector + " water"] + w_space[sector] = heat_demand[sector + " space"] / ( + heat_demand[sector + " space"] + heat_demand[sector + " water"] ) w_space["tot"] = ( - heat_demand_r["services space"] + heat_demand_r["residential space"] - ) / heat_demand_r.T.groupby(level=[1]).sum().T + heat_demand["services space"] + heat_demand["residential space"] + ) / heat_demand.T.groupby(level=[1]).sum().T for name in n.loads[ n.loads.carrier.isin([x + " heat" for x in heat_systems]) @@ -2059,7 +2053,7 @@ def add_heat(n, costs): pop_layout.loc[node].fraction * floor_area.loc[ct, "value"] * 10**6 ).loc[sec] * f # total heat demand at node [MWh] - demand = n.loads_t.p_set[name].resample(hours[0]).mean() + demand = n.loads_t.p_set[name] # space heat demand at node [MWh] space_heat_demand = demand * w_space[sec][node] @@ -3292,52 +3286,6 @@ def remove_h2_network(n): n.stores.drop("EU H2 Store", inplace=True) -def maybe_adjust_costs_and_potentials(n, opts): - for o in opts: - flags = ["+e", "+p", "+m", "+c"] - if all(flag not in o for flag in flags): - continue - oo = o.split("+") - carrier_list = np.hstack( - ( - n.generators.carrier.unique(), - n.links.carrier.unique(), - n.stores.carrier.unique(), - n.storage_units.carrier.unique(), - ) - ) - suptechs = map(lambda c: c.split("-", 2)[0], carrier_list) - if oo[0].startswith(tuple(suptechs)): - carrier = oo[0] - attr_lookup = { - "p": "p_nom_max", - "e": "e_nom_max", - "c": "capital_cost", - "m": "marginal_cost", - } - attr = attr_lookup[oo[1][0]] - factor = float(oo[1][1:]) - # beware if factor is 0 and p_nom_max is np.inf, 0*np.inf is nan - if carrier == "AC": # lines do not have carrier - n.lines[attr] *= factor - else: - if attr == "p_nom_max": - comps = {"Generator", "Link", "StorageUnit"} - elif attr == "e_nom_max": - comps = {"Store"} - else: - comps = {"Generator", "Link", "StorageUnit", "Store"} - for c in n.iterate_components(comps): - if carrier == "solar": - sel = c.df.carrier.str.contains( - carrier - ) & ~c.df.carrier.str.contains("solar rooftop") - else: - sel = c.df.carrier.str.contains(carrier) - c.df.loc[sel, attr] *= factor - logger.info(f"changing {attr} for {carrier} by factor {factor}") - - def limit_individual_line_extension(n, maxext): logger.info(f"Limiting new HVAC and HVDC extensions to {maxext} MW") n.lines["s_nom_max"] = n.lines["s_nom"] + maxext @@ -3507,31 +3455,31 @@ def apply_time_segmentation( return n -def set_temporal_aggregation(n, opts, solver_name): +def set_temporal_aggregation(n, resolution, solver_name): """ Aggregate network temporally. """ - for o in opts: - # temporal averaging - m = re.match(r"^\d+h$", o, re.IGNORECASE) - if m is not None: - n = average_every_nhours(n, m.group(0)) - break - # representative snapshots - m = re.match(r"(^\d+)sn$", o, re.IGNORECASE) - if m is not None: - sn = int(m[1]) - logger.info(f"Use every {sn} snapshot as representative") - n.set_snapshots(n.snapshots[::sn]) - n.snapshot_weightings *= sn - break - # segments with package tsam - m = re.match(r"^(\d+)seg$", o, re.IGNORECASE) - if m is not None: - segments = int(m[1]) - logger.info(f"Use temporal segmentation with {segments} segments") - n = apply_time_segmentation(n, segments, solver_name=solver_name) - break + if not resolution: + return n + + # representative snapshots + if "sn" in resolution.lower(): + sn = int(resolution[:-2]) + logger.info("Use every %s snapshot as representative", sn) + n.set_snapshots(n.snapshots[::sn]) + n.snapshot_weightings *= sn + + # segments with package tsam + elif "seg" in resolution.lower(): + segments = int(resolution[:-3]) + logger.info("Use temporal segmentation with %s segments", segments) + n = apply_time_segmentation(n, segments, solver_name=solver_name) + + # temporal averaging + elif "h" in resolution.lower(): + logger.info("Aggregate to frequency %s", resolution) + n = average_every_nhours(n, resolution) + return n @@ -3600,14 +3548,12 @@ if __name__ == "__main__": planning_horizons="2030", ) - logging.basicConfig(level=snakemake.config["logging"]["level"]) + configure_logging(snakemake) - update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) + update_config_from_wildcards(snakemake.config, snakemake.wildcards) options = snakemake.params.sector - opts = snakemake.wildcards.sector_opts.split("-") - investment_year = int(snakemake.wildcards.planning_horizons[-4:]) n = pypsa.Network(snakemake.input.network) @@ -3645,56 +3591,34 @@ if __name__ == "__main__": add_storage_and_grids(n, costs) - # TODO merge with opts cost adjustment below - for o in opts: - if o[:4] == "dist": - options["electricity_distribution_grid"] = True - options["electricity_distribution_grid_cost_factor"] = float( - o[4:].replace("p", ".").replace("m", "-") - ) - if o == "biomasstransport": - options["biomass_transport"] = True - - if "nodistrict" in opts: - options["district_heating"]["progress"] = 0.0 - - if "nowasteheat" in opts: - logger.info("Disabling waste heat.") - options["use_fischer_tropsch_waste_heat"] = False - options["use_methanolisation_waste_heat"] = False - options["use_haber_bosch_waste_heat"] = False - options["use_methanation_waste_heat"] = False - options["use_fuel_cell_waste_heat"] = False - options["use_electrolysis_waste_heat"] = False - - if "T" in opts: + if options["transport"]: add_land_transport(n, costs) - if "H" in opts: + if options["heating"]: add_heat(n, costs) - if "B" in opts: + if options["biomass"]: add_biomass(n, costs) if options["ammonia"]: add_ammonia(n, costs) - if "I" in opts: + if options["industry"]: add_industry(n, costs) - if "H" in opts: + if options["heating"]: add_waste_heat(n) - if "A" in opts: # requires H and I + if options["agriculture"]: # requires H and I add_agriculture(n, costs) if options["dac"]: add_dac(n, costs) - if "decentral" in opts: + if not options["electricity_transmission_grid"]: decentral(n) - if "noH2network" in opts: + if not options["H2_network"]: remove_h2_network(n) if options["co2network"]: @@ -3704,51 +3628,39 @@ if __name__ == "__main__": add_allam(n, costs) solver_name = snakemake.config["solving"]["solver"]["name"] - n = set_temporal_aggregation(n, opts, solver_name) + resolution = snakemake.params.time_resolution + n = set_temporal_aggregation(n, resolution, solver_name) - limit_type = "config" - limit = get(snakemake.params.co2_budget, investment_year) - for o in opts: - if "cb" not in o: - continue - limit_type = "carbon budget" + co2_budget = snakemake.params.co2_budget + if isinstance(co2_budget, str) and co2_budget.startswith("cb"): fn = "results/" + snakemake.params.RDIR + "/csvs/carbon_budget_distribution.csv" if not os.path.exists(fn): emissions_scope = snakemake.params.emissions_scope report_year = snakemake.params.eurostat_report_year input_co2 = snakemake.input.co2 build_carbon_budget( - o, + co2_budget, snakemake.input.eurostat, fn, emissions_scope, report_year, input_co2, + options, ) co2_cap = pd.read_csv(fn, index_col=0).squeeze() limit = co2_cap.loc[investment_year] - break - for o in opts: - if "Co2L" not in o: - continue - limit_type = "wildcard" - limit = o[o.find("Co2L") + 4 :] - limit = float(limit.replace("p", ".").replace("m", "-")) - break - logger.info(f"Add CO2 limit from {limit_type}") - add_co2limit(n, nyears, limit) + else: + limit = get(co2_budget, investment_year) + add_co2limit(n, options, nyears, limit) - for o in opts: - if not o[:10] == "linemaxext": - continue - maxext = float(o[10:]) * 1e3 + maxext = snakemake.params["lines"]["max_extension"] + if maxext is not None: limit_individual_line_extension(n, maxext) - break if options["electricity_distribution_grid"]: insert_electricity_distribution_grid(n, costs) - maybe_adjust_costs_and_potentials(n, opts) + maybe_adjust_costs_and_potentials(n, snakemake.params["adjustments"]) if options["gas_distribution_grid"]: insert_gas_distribution_costs(n, costs) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 551222c0..278171bc 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -37,7 +37,7 @@ import pandas as pd import pypsa import xarray as xr from _benchmark import memory_logger -from _helpers import configure_logging, get_opt, update_config_with_sector_opts +from _helpers import configure_logging, update_config_from_wildcards from pypsa.descriptors import get_activity_mask from pypsa.descriptors import get_switchable_as_dense as get_as_dense @@ -178,16 +178,10 @@ def _add_land_use_constraint_m(n, planning_horizons, config): n.generators.p_nom_max.clip(lower=0, inplace=True) -def add_co2_sequestration_limit(n, config, limit=200): +def add_co2_sequestration_limit(n, limit=200): """ Add a global constraint on the amount of Mt CO2 that can be sequestered. """ - limit = limit * 1e6 - for o in opts: - if "seq" not in o: - continue - limit = float(o[o.find("seq") + 3 :]) * 1e6 - break if not n.investment_periods.empty: periods = n.investment_periods @@ -200,7 +194,7 @@ def add_co2_sequestration_limit(n, config, limit=200): "GlobalConstraint", names, sense=">=", - constant=-limit, + constant=-limit * 1e6, type="operational_limit", carrier_attribute="co2 sequestered", investment_period=periods, @@ -260,7 +254,7 @@ def add_carbon_budget_constraint(n, snapshots): n.model.add_constraints(lhs <= rhs, name=f"GlobalConstraint-{name}") -def add_max_growth(n, config): +def add_max_growth(n): """ Add maximum growth rates for different carriers. """ @@ -393,11 +387,11 @@ def prepare_network( if foresight == "perfect": n = add_land_use_constraint_perfect(n) if snakemake.params["sector"]["limit_max_growth"]["enable"]: - n = add_max_growth(n, config) + n = add_max_growth(n) if n.stores.carrier.eq("co2 sequestered").any(): limit = co2_sequestration_potential - add_co2_sequestration_limit(n, config, limit=limit) + add_co2_sequestration_limit(n, limit=limit) return n @@ -831,30 +825,20 @@ def extra_functionality(n, snapshots): location to add them. The arguments ``opts`` and ``snakemake.config`` are expected to be attached to the network. """ - opts = n.opts config = n.config constraints = config["solving"].get("constraints", {}) - if ( - "BAU" in opts or constraints.get("BAU", False) - ) and n.generators.p_nom_extendable.any(): + if constraints["BAU"] and n.generators.p_nom_extendable.any(): add_BAU_constraints(n, config) - if ( - "SAFE" in opts or constraints.get("SAFE", False) - ) and n.generators.p_nom_extendable.any(): + if constraints["SAFE"] and n.generators.p_nom_extendable.any(): add_SAFE_constraints(n, config) - if ( - "CCL" in opts or constraints.get("CCL", False) - ) and n.generators.p_nom_extendable.any(): + if constraints["CCL"] and n.generators.p_nom_extendable.any(): add_CCL_constraints(n, config) reserve = config["electricity"].get("operational_reserve", {}) if reserve.get("activate"): add_operational_reserve_margin(n, snapshots, config) - EQ_config = constraints.get("EQ", False) - EQ_wildcard = get_opt(opts, r"^EQ+[0-9]*\.?[0-9]+(c|)") - EQ_o = EQ_wildcard or EQ_config - if EQ_o: + if EQ_o := constraints["EQ"]: add_EQ_constraints(n, EQ_o.replace("EQ", "")) add_battery_constraints(n) @@ -877,7 +861,7 @@ def extra_functionality(n, snapshots): custom_extra_functionality(n, snapshots, snakemake) -def solve_network(n, config, solving, opts="", **kwargs): +def solve_network(n, config, solving, **kwargs): set_of_options = solving["solver"]["options"] cf_solving = solving["options"] @@ -905,7 +889,6 @@ def solve_network(n, config, solving, opts="", **kwargs): # add to network for extra_functionality n.config = config - n.opts = opts if rolling_horizon: kwargs["horizon"] = cf_solving.get("horizon", 365) @@ -950,15 +933,8 @@ if __name__ == "__main__": planning_horizons="2030", ) configure_logging(snakemake) - if "sector_opts" in snakemake.wildcards.keys(): - update_config_with_sector_opts( - snakemake.config, snakemake.wildcards.sector_opts - ) + update_config_from_wildcards(snakemake.config, snakemake.wildcards) - opts = snakemake.wildcards.opts - if "sector_opts" in snakemake.wildcards.keys(): - opts += "-" + snakemake.wildcards.sector_opts - opts = [o for o in opts.split("-") if o != ""] solve_opts = snakemake.params.solving["options"] np.random.seed(solve_opts.get("seed", 123)) @@ -981,7 +957,6 @@ if __name__ == "__main__": n, config=snakemake.config, solving=snakemake.params.solving, - opts=opts, log_fn=snakemake.log.solver, ) diff --git a/scripts/solve_operations_network.py b/scripts/solve_operations_network.py index dca49d02..ec0b3cc1 100644 --- a/scripts/solve_operations_network.py +++ b/scripts/solve_operations_network.py @@ -12,7 +12,7 @@ import logging import numpy as np import pypsa -from _helpers import configure_logging, update_config_with_sector_opts +from _helpers import configure_logging, update_config_from_wildcards from solve_network import prepare_network, solve_network logger = logging.getLogger(__name__) @@ -34,10 +34,8 @@ if __name__ == "__main__": ) configure_logging(snakemake) - update_config_with_sector_opts(snakemake.config, snakemake.wildcards.sector_opts) + update_config_from_wildcards(snakemake.config, snakemake.wildcards) - opts = f"{snakemake.wildcards.opts}-{snakemake.wildcards.sector_opts}".split("-") - opts = [o for o in opts if o != ""] solve_opts = snakemake.params.options np.random.seed(solve_opts.get("seed", 123)) @@ -46,9 +44,7 @@ if __name__ == "__main__": n.optimize.fix_optimal_capacities() n = prepare_network(n, solve_opts, config=snakemake.config) - n = solve_network( - n, config=snakemake.config, opts=opts, log_fn=snakemake.log.solver - ) + n = solve_network(n, config=snakemake.config, log_fn=snakemake.log.solver) n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) n.export_to_netcdf(snakemake.output[0]) From 89d0fa24b69f9e3ab572a65adbc73ca00f894160 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 17:38:46 +0100 Subject: [PATCH 321/591] further adjustments to latest master branch commits --- rules/build_electricity.smk | 75 ++++++++++++++++++------------------- rules/build_sector.smk | 27 +++++++------ rules/postprocess.smk | 8 ++-- rules/solve_electricity.smk | 1 + rules/solve_perfect.smk | 4 +- 5 files changed, 61 insertions(+), 54 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 5cf3c099..8a2148fc 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -250,14 +250,15 @@ rule determine_availability_matrix_MD_UA: # Optional input when having Ukraine (UA) or Moldova (MD) in the countries list -if {"UA", "MD"}.intersection(set(config["countries"])): - opt = { - "availability_matrix_MD_UA": resources( - "availability_matrix_MD-UA_{technology}.nc" - ) - } -else: - opt = {} +def input_ua_md_availability_matrix(w): + countries = set(config_provider("countries")(w)) + if {"UA", "MD"}.intersection(countries): + return { + "availability_matrix_MD_UA": resources( + "availability_matrix_MD-UA_{technology}.nc" + ) + } + return {} rule build_renewable_profiles: @@ -265,7 +266,7 @@ rule build_renewable_profiles: snapshots=config_provider("snapshots"), renewable=config_provider("renewable"), input: - **opt, + unpack(input_ua_md_availability_matrix), base_network=resources("networks/base.nc"), corine=ancient("data/bundle/corine/g250_clc06_V18_5.tif"), natura=lambda w: ( @@ -359,30 +360,28 @@ rule build_hydro_profile: "../scripts/build_hydro_profile.py" -if config["lines"]["dynamic_line_rating"]["activate"]: - - rule build_line_rating: - params: - snapshots=config_provider("snapshots"), - input: - base_network=resources("networks/base.nc"), - cutout="cutouts/" - + CDIR - + config_provider("lines", "dynamic_line_rating", "cutout") - + ".nc", - output: - output=resources("networks/line_rating.nc"), - log: - logs("build_line_rating.log"), - benchmark: - benchmarks("build_line_rating") - threads: config["atlite"].get("nprocesses", 4) - resources: - mem_mb=config["atlite"].get("nprocesses", 4) * 1000, - conda: - "../envs/environment.yaml" - script: - "../scripts/build_line_rating.py" +rule build_line_rating: + params: + snapshots=config_provider("snapshots"), + input: + base_network=resources("networks/base.nc"), + cutout="cutouts/" + + CDIR + + config_provider("lines", "dynamic_line_rating", "cutout") + + ".nc", + output: + output=resources("networks/line_rating.nc"), + log: + logs("build_line_rating.log"), + benchmark: + benchmarks("build_line_rating") + threads: config["atlite"].get("nprocesses", 4) + resources: + mem_mb=config["atlite"].get("nprocesses", 4) * 1000, + conda: + "../envs/environment.yaml" + script: + "../scripts/build_line_rating.py" def input_profile_tech(w): @@ -420,7 +419,7 @@ rule add_electricity: if config_provider("lines", "dynamic_line_rating", "activate")(w) else resources("networks/base.nc") ), - tech_costs=resources(f"costs_{config['costs']['year']}.csv"), + tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), @@ -463,7 +462,7 @@ rule simplify_network: costs=config_provider("costs"), input: network=resources("networks/elec.nc"), - tech_costs=resources(f"costs_{config['costs']['year']}.csv"), + tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), output: @@ -510,7 +509,7 @@ rule cluster_network: if config_provider("enable", "custom_busmap", default=False)(w) else [] ), - tech_costs=resources(f"costs_{config['costs']['year']}.csv"), + tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), output: network=resources("networks/elec_s{simpl}_{clusters}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), @@ -537,7 +536,7 @@ rule add_extra_components: costs=config_provider("costs"), input: network=resources("networks/elec_s{simpl}_{clusters}.nc"), - tech_costs=resources(f"costs_{config['costs']['year']}.csv"), + tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), output: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), log: @@ -569,7 +568,7 @@ rule prepare_network: autarky=config_provider("electricity", "autarky", default={}), input: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), - tech_costs=resources(f"costs_{config['costs']['year']}.csv"), + tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 1bbb626d..0c755834 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -435,23 +435,26 @@ rule build_industry_sector_ratios: rule build_industry_sector_ratios_intermediate: params: - industry=config["industry"], + industry=config_provider("industry"), input: - industry_sector_ratios=RESOURCES + "industry_sector_ratios.csv", - industrial_energy_demand_per_country_today=RESOURCES - + "industrial_energy_demand_per_country_today.csv", - industrial_production_per_country=RESOURCES - + "industrial_production_per_country.csv", + industry_sector_ratios=resources("industry_sector_ratios.csv"), + industrial_energy_demand_per_country_today=resources( + "industrial_energy_demand_per_country_today.csv" + ), + industrial_production_per_country=resources( + "industrial_production_per_country.csv" + ), output: - industry_sector_ratios=RESOURCES - + "industry_sector_ratios_{planning_horizons}.csv", + industry_sector_ratios=resources( + "industry_sector_ratios_{planning_horizons}.csv" + ), threads: 1 resources: mem_mb=1000, log: - LOGS + "build_industry_sector_ratios_{planning_horizons}.log", + logs("build_industry_sector_ratios_{planning_horizons}.log"), benchmark: - BENCHMARKS + "build_industry_sector_ratios_{planning_horizons}" + benchmarks("build_industry_sector_ratios_{planning_horizons}") conda: "../envs/environment.yaml" script: @@ -571,7 +574,9 @@ rule build_industrial_production_per_node: rule build_industrial_energy_demand_per_node: input: - industry_sector_ratios=resources("industry_sector_ratios_{planning_horizons}.csv"), + industry_sector_ratios=resources( + "industry_sector_ratios_{planning_horizons}.csv" + ), industrial_production_per_node=resources( "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), diff --git a/rules/postprocess.smk b/rules/postprocess.smk index e274c502..dfcf9654 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -172,9 +172,11 @@ rule make_summary: costs=lambda w: ( resources("costs_{}.csv".format(config_provider("costs", "year")(w))) if config_provider("foresight")(w) == "overnight" - else resources("costs_{}.csv".format( - config_provider("scenario", "planning_horizons", 0) - )) + else resources( + "costs_{}.csv".format( + config_provider("scenario", "planning_horizons", 0)(w) + ) + ) ), ac_plot=expand( resources("maps/power-network-s{simpl}-{clusters}.pdf"), diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index b6a7902e..d3aa8d4c 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: MIT + rule solve_network: params: solving=config_provider("solving"), diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index f9c5112a..723fd6a7 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -58,14 +58,14 @@ def input_network_year(w): rule prepare_perfect_foresight: params: - costs=config["costs"], + costs=config_provider("costs"), input: unpack(input_network_year), brownfield_network=lambda w: ( RESULTS + "prenetworks-brownfield/" + "elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_" - + "{}.nc".format(str(config_provider("scenario", "planning_horizons", 0))) + + "{}.nc".format(str(config_provider("scenario", "planning_horizons", 0)(w))) ), output: RESULTS From b8d57a6566c410e871fe4ca97096e75dc060fb0e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 17 Feb 2024 16:39:10 +0000 Subject: [PATCH 322/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- Snakefile | 1 - rules/solve_myopic.smk | 8 +++++--- rules/solve_perfect.smk | 10 ++++++---- scripts/prepare_network.py | 6 +++++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Snakefile b/Snakefile index 2c342efc..a59025f9 100644 --- a/Snakefile +++ b/Snakefile @@ -47,7 +47,6 @@ RESULTS = "results/" + RDIR # RESOURCES = "resources/" - localrules: purge, diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 03cbb705..8574bbb8 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -16,9 +16,11 @@ rule add_existing_baseyear: busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - costs=lambda w: resources("costs_{}.csv".format( - config_provider("scenario", "planning_horizons", 0)(w) - )), + costs=lambda w: resources( + "costs_{}.csv".format( + config_provider("scenario", "planning_horizons", 0)(w) + ) + ), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), existing_heating_distribution=resources( diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 723fd6a7..bba71b4d 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -14,9 +14,9 @@ rule add_existing_baseyear: busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - costs=resources("costs_{}.csv".format( - config_provider("scenario", "planning_horizons", 0) - )), + costs=resources( + "costs_{}.csv".format(config_provider("scenario", "planning_horizons", 0)) + ), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), existing_heating_distribution=resources( @@ -65,7 +65,9 @@ rule prepare_perfect_foresight: RESULTS + "prenetworks-brownfield/" + "elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_" - + "{}.nc".format(str(config_provider("scenario", "planning_horizons", 0)(w))) + + "{}.nc".format( + str(config_provider("scenario", "planning_horizons", 0)(w)) + ) ), output: RESULTS diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index e1b42243..6b782d44 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -62,7 +62,11 @@ import logging import numpy as np import pandas as pd import pypsa -from _helpers import configure_logging, update_config_from_wildcards, set_scenario_config +from _helpers import ( + configure_logging, + set_scenario_config, + update_config_from_wildcards, +) from add_electricity import load_costs, update_transmission_costs from pypsa.descriptors import expand_series From 709b831e06862214c1f7709406dbee91e8007310 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 17:51:26 +0100 Subject: [PATCH 323/591] further adjustments where config_provider needs to be called --- Snakefile | 1 - rules/solve_perfect.smk | 2 +- scripts/plot_summary.py | 6 +++--- scripts/prepare_network.py | 6 +++++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Snakefile b/Snakefile index 2c342efc..a59025f9 100644 --- a/Snakefile +++ b/Snakefile @@ -47,7 +47,6 @@ RESULTS = "results/" + RDIR # RESOURCES = "resources/" - localrules: purge, diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 723fd6a7..3bb006c5 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -15,7 +15,7 @@ rule add_existing_baseyear: busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), costs=resources("costs_{}.csv".format( - config_provider("scenario", "planning_horizons", 0) + config_provider("scenario", "planning_horizons", 0)(w) )), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index f0d80176..4119a811 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -584,8 +584,8 @@ if __name__ == "__main__": plot_balances() + co2_budget = snakemake.params["co2_budget"] if ( - snakemake.params["co2_budget"].startswith("cb") - or snakemake.params["foresight"] == "perfect" - ): + isinstance(co2_budget, str) and co2_budget.startswith("cb") + ) or snakemake.params["foresight"] == "perfect": plot_carbon_budget_distribution(snakemake.input.eurostat) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index e1b42243..6b782d44 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -62,7 +62,11 @@ import logging import numpy as np import pandas as pd import pypsa -from _helpers import configure_logging, update_config_from_wildcards, set_scenario_config +from _helpers import ( + configure_logging, + set_scenario_config, + update_config_from_wildcards, +) from add_electricity import load_costs, update_transmission_costs from pypsa.descriptors import expand_series From de244414df2f36298ed5f3b36adab2b967940b1b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 17 Feb 2024 16:56:01 +0000 Subject: [PATCH 324/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/solve_perfect.smk | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index a76dfb39..639bcae8 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -14,9 +14,11 @@ rule add_existing_baseyear: busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - costs=lambda w: resources("costs_{}.csv".format( - config_provider("scenario", "planning_horizons", 0)(w) - )), + costs=lambda w: resources( + "costs_{}.csv".format( + config_provider("scenario", "planning_horizons", 0)(w) + ) + ), cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), existing_heating_distribution=resources( From db7c98395023e67097aecbabae0de3972a5e176b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 18:14:18 +0100 Subject: [PATCH 325/591] mock_snakemake: remove dangeours empty list as default argument --- Snakefile | 9 --------- scripts/_helpers.py | 8 +++++--- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Snakefile b/Snakefile index a59025f9..0bb1b665 100644 --- a/Snakefile +++ b/Snakefile @@ -30,7 +30,6 @@ if run["name"]: else: RDIR = "" -# for possibly shared resources logs = path_provider("logs/", RDIR, run["shared_resources"]) benchmarks = path_provider("benchmarks/", RDIR, run["shared_resources"]) resources = path_provider("resources/", RDIR, run["shared_resources"]) @@ -38,14 +37,6 @@ resources = path_provider("resources/", RDIR, run["shared_resources"]) CDIR = "" if run["shared_cutouts"] else RDIR RESULTS = "results/" + RDIR -# TODO: this needs to be aligned with new scenario management -# if not (shared_resources := run.get("shared_resources")): -# RESOURCES = "resources/" + RDIR -# elif isinstance(shared_resources, str): -# RESOURCES = "resources/" + shared_resources + "/" -# else: -# RESOURCES = "resources/" - localrules: purge, diff --git a/scripts/_helpers.py b/scripts/_helpers.py index f1c659ec..06e68325 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -321,7 +321,7 @@ def progress_retrieve(url, file, disable=False): def mock_snakemake( rulename, root_dir=None, - configfiles=[], + configfiles=None, submodule_dir="workflow/submodules/pypsa-eur", **wildcards, ): @@ -375,7 +375,9 @@ def mock_snakemake( if os.path.exists(p): snakefile = p break - if isinstance(configfiles, str): + if configfiles is None: + configfiles = [] + elif isinstance(configfiles, str): configfiles = [configfiles] workflow = sm.Workflow( @@ -397,7 +399,7 @@ def mock_snakemake( def make_accessable(*ios): for io in ios: - for i in range(len(io)): + for i, _ in enumerate(io): io[i] = os.path.abspath(io[i]) make_accessable(job.input, job.output, job.log) From 84c3852c2ea0a3c55d9df5f652afd8a3a5cb32d7 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 18:15:43 +0100 Subject: [PATCH 326/591] _helpers: remove resource folder separation by wildcard This was not working reliably as the number of input and output wildcards could vary, which the function did not acknowledge --- scripts/_helpers.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 06e68325..98e5aaae 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -39,10 +39,9 @@ def get_run_path(fn, dir, rdir, shared_resources): The base directory. rdir : str Relative directory for non-shared resources. - shared_resources : str, list, or bool + shared_resources : str or bool Specifies which resources should be shared. - - If string or list, assumed to be superset of wildcards for sharing. - - If "base", special handling for shared "base" resources. + - If string is "base", special handling for shared "base" resources (see notes). - If boolean, directly specifies if the resource is shared. Returns @@ -54,24 +53,23 @@ def get_run_path(fn, dir, rdir, shared_resources): ----- Special case for "base" allows no wildcards other than "technology", "year" and "scope" and excludes filenames starting with "networks/elec" or - "add_electricity". + "add_electricity". All other resources are shared. """ - pattern = r"\{([^{}]+)\}" - existing_wildcards = set(re.findall(pattern, fn)) if shared_resources == "base": - # special case for shared "base" resources + pattern = r"\{([^{}]+)\}" + existing_wildcards = set(re.findall(pattern, fn)) irrelevant_wildcards = {"technology", "year", "scope"} - no_relevant_wildcards = not len(existing_wildcards - irrelevant_wildcards) + no_relevant_wildcards = not (existing_wildcards - irrelevant_wildcards) no_elec_rule = not fn.startswith("networks/elec") and not fn.startswith( "add_electricity" ) is_shared = no_relevant_wildcards and no_elec_rule - elif isinstance(shared_resources, (str, list)): - if isinstance(shared_resources, str): - shared_resources = [shared_resources] - is_shared = (existing_wildcards).issubset(shared_resources) - else: + elif isinstance(shared_resources, bool): is_shared = shared_resources + else: + raise ValueError( + "shared_resources must be a boolean or 'base' for special handling." + ) if is_shared: return f"{dir}{fn}" From 95853bb59d492cba345d9faeda902949c4c2a48a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 18:27:59 +0100 Subject: [PATCH 327/591] _helpers: allow specifying dedicated shared_resources folder --- doc/configtables/run.csv | 2 +- scripts/_helpers.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index e2a81e0b..f619d8bf 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -4,5 +4,5 @@ scenarios,,, -- enable,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``file``." -- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run: scenarios`` has to be set to ``true`` and ``run: name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combination of settings, alter and use the ``config/create_scenarios.py`` script in the ``config`` directory." disable_progrssbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." -shared_resources,bool/str/list,,"Switch to select whether resources should be shared across runs. If a string or list is passed, it is assumed to be wildcard(s) which indicates up to which set of wildcards the resource folder should be shared. If set to 'base', only resources before creating the elec.nc file are shared." +shared_resources,bool/str,,"Switch to select whether resources should be shared across runs. If a string is passed, this is used as a subdirectory name for shared resources. If set to 'base', only resources before creating the elec.nc file are shared." shared_cutouts,bool,"{true, false}","Switch to select whether cutouts should be shared across runs." diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 98e5aaae..b2b1b341 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -42,6 +42,7 @@ def get_run_path(fn, dir, rdir, shared_resources): shared_resources : str or bool Specifies which resources should be shared. - If string is "base", special handling for shared "base" resources (see notes). + - If random string other than "base", this folder is used instead of the `rdir` keyword. - If boolean, directly specifies if the resource is shared. Returns @@ -59,11 +60,14 @@ def get_run_path(fn, dir, rdir, shared_resources): pattern = r"\{([^{}]+)\}" existing_wildcards = set(re.findall(pattern, fn)) irrelevant_wildcards = {"technology", "year", "scope"} - no_relevant_wildcards = not (existing_wildcards - irrelevant_wildcards) + no_relevant_wildcards = not existing_wildcards - irrelevant_wildcards no_elec_rule = not fn.startswith("networks/elec") and not fn.startswith( "add_electricity" ) is_shared = no_relevant_wildcards and no_elec_rule + elif isinstance(shared_resources, str): + rdir = shared_resources + "/" + is_shared = True elif isinstance(shared_resources, bool): is_shared = shared_resources else: From e898781fda9fa45970a9c3df301a9cf5a5a4112e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 18:35:26 +0100 Subject: [PATCH 328/591] use wildcard input functions where applicable --- rules/build_electricity.smk | 18 +++++++++--------- rules/retrieve.smk | 2 +- scripts/_helpers.py | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 8a2148fc..f0338492 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -276,7 +276,7 @@ rule build_renewable_profiles: ), luisa=lambda w: ( "data/LUISA_basemap_020321_50m.tif" - if config_provider("renewable", w.technology, "luisa")(w) + if config_provider("renewable", w.technology, "luisa") else [] ), gebco=ancient( @@ -365,9 +365,9 @@ rule build_line_rating: snapshots=config_provider("snapshots"), input: base_network=resources("networks/base.nc"), - cutout="cutouts/" + cutout=lambda w: "cutouts/" + CDIR - + config_provider("lines", "dynamic_line_rating", "cutout") + + config_provider("lines", "dynamic_line_rating", "cutout")(w) + ".nc", output: output=resources("networks/line_rating.nc"), @@ -419,7 +419,7 @@ rule add_electricity: if config_provider("lines", "dynamic_line_rating", "activate")(w) else resources("networks/base.nc") ), - tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), @@ -462,7 +462,7 @@ rule simplify_network: costs=config_provider("costs"), input: network=resources("networks/elec.nc"), - tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), output: @@ -509,7 +509,7 @@ rule cluster_network: if config_provider("enable", "custom_busmap", default=False)(w) else [] ), - tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), output: network=resources("networks/elec_s{simpl}_{clusters}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), @@ -536,7 +536,7 @@ rule add_extra_components: costs=config_provider("costs"), input: network=resources("networks/elec_s{simpl}_{clusters}.nc"), - tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), output: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), log: @@ -564,11 +564,11 @@ rule prepare_network: gaslimit=config_provider("electricity", "gaslimit"), max_hours=config_provider("electricity", "max_hours"), costs=config_provider("costs"), - adjustments=config_provider("adjustments", "electricity", + adjustments=config_provider("adjustments", "electricity"), autarky=config_provider("electricity", "autarky", default={}), input: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), - tech_costs=resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 9e9ff1f0..d6fcbb26 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -84,7 +84,7 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_cost_data", T rule retrieve_cost_data: params: - version=lambda w: config_provider("costs", "version")(w), + version=config_provider("costs", "version"), output: resources("costs_{year}.csv"), log: diff --git a/scripts/_helpers.py b/scripts/_helpers.py index b2b1b341..5fb6a540 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -72,7 +72,7 @@ def get_run_path(fn, dir, rdir, shared_resources): is_shared = shared_resources else: raise ValueError( - "shared_resources must be a boolean or 'base' for special handling." + "shared_resources must be a boolean, str, or 'base' for special handling." ) if is_shared: From cc3d7a4cbb29d6ec1f3f70cfcaabfe8a053fd2ba Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 17 Feb 2024 17:35:52 +0000 Subject: [PATCH 329/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index f0338492..43be60fc 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -419,7 +419,9 @@ rule add_electricity: if config_provider("lines", "dynamic_line_rating", "activate")(w) else resources("networks/base.nc") ), - tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources( + f"costs_{config_provider('costs', 'year')(w)}.csv" + ), regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), @@ -462,7 +464,9 @@ rule simplify_network: costs=config_provider("costs"), input: network=resources("networks/elec.nc"), - tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources( + f"costs_{config_provider('costs', 'year')(w)}.csv" + ), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), output: @@ -509,7 +513,9 @@ rule cluster_network: if config_provider("enable", "custom_busmap", default=False)(w) else [] ), - tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources( + f"costs_{config_provider('costs', 'year')(w)}.csv" + ), output: network=resources("networks/elec_s{simpl}_{clusters}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), @@ -536,7 +542,9 @@ rule add_extra_components: costs=config_provider("costs"), input: network=resources("networks/elec_s{simpl}_{clusters}.nc"), - tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources( + f"costs_{config_provider('costs', 'year')(w)}.csv" + ), output: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), log: @@ -568,7 +576,9 @@ rule prepare_network: autarky=config_provider("electricity", "autarky", default={}), input: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), - tech_costs=lambda w: resources(f"costs_{config_provider('costs', 'year')(w)}.csv"), + tech_costs=lambda w: resources( + f"costs_{config_provider('costs', 'year')(w)}.csv" + ), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), From 16793d1335f92b4b578e0f956aeac54add31c86d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 20:42:37 +0100 Subject: [PATCH 330/591] Snakefile: don't use {run} wildcard if just specifying a run name --- Snakefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index 0bb1b665..fb610c59 100644 --- a/Snakefile +++ b/Snakefile @@ -26,7 +26,9 @@ if run["name"]: if scenarios.get("enable"): fn = Path(scenarios["file"]) scenarios = yaml.safe_load(fn.read_text()) - RDIR = "{run}/" + RDIR = "{run}/" + else: + RDIR = run["name"] + "/" else: RDIR = "" From d335275e0fa32db9bea091a2b4966398dbfbbe50 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 20:43:11 +0100 Subject: [PATCH 331/591] build_electricity: add missing wildcard call --- rules/build_electricity.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 43be60fc..8e62259f 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -276,7 +276,7 @@ rule build_renewable_profiles: ), luisa=lambda w: ( "data/LUISA_basemap_020321_50m.tif" - if config_provider("renewable", w.technology, "luisa") + if config_provider("renewable", w.technology, "luisa")(w) else [] ), gebco=ancient( From 388ea658471c011e685069b1c36139a694b35c07 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 20:44:22 +0100 Subject: [PATCH 332/591] common.smk: use update_config to simplify merge_configs --- rules/common.smk | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/rules/common.smk b/rules/common.smk index 27f82364..a39c2d8d 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -10,7 +10,7 @@ import os, sys, glob path = workflow.source_path("../scripts/_helpers.py") sys.path.insert(0, os.path.dirname(path)) -from _helpers import validate_checksum +from snakemake.utils import update_config def get_config(config, keys, default=None): @@ -29,11 +29,7 @@ def get_config(config, keys, default=None): def merge_configs(base_config, scenario_config): """Merge base config with a specific scenario without modifying the original.""" merged = copy.deepcopy(base_config) - for key, value in scenario_config.items(): - if key in merged and isinstance(merged[key], dict): - merged[key] = merge_configs(merged[key], value) - else: - merged[key] = value + update_config(merged, scenario_config) return merged From 9f643ea429e8158e1220b5464ec8c9915eb42bf8 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 20:45:23 +0100 Subject: [PATCH 333/591] _helpers: add inplace keyword argument to update_config_from_wildcards --- rules/common.smk | 12 ++++++++++-- scripts/_helpers.py | 11 ++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/rules/common.smk b/rules/common.smk index a39c2d8d..ca339cec 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -10,6 +10,7 @@ import os, sys, glob path = workflow.source_path("../scripts/_helpers.py") sys.path.insert(0, os.path.dirname(path)) +from _helpers import validate_checksum, update_config_from_wildcards from snakemake.utils import update_config @@ -41,7 +42,10 @@ def scenario_config(scenario_name): def static_getter(wildcards, keys, default): """Getter function for static config values.""" - return get_config(config, keys, default) + config_with_wildcards = update_config_from_wildcards( + config, wildcards, inplace=False + ) + return get_config(config_with_wildcards, keys, default) def dynamic_getter(wildcards, keys, default): @@ -53,7 +57,11 @@ def dynamic_getter(wildcards, keys, default): raise ValueError( f"Scenario {scenario_name} not found in file {config['run']['scenario']['file']}." ) - return get_config(scenario_config(scenario_name), keys, default) + config_with_scenario = scenario_config(scenario_name) + config_with_wildcards = update_config_from_wildcards( + config_with_scenario, wildcards, inplace=False + ) + return get_config(config_with_wildcards, keys, default) def config_provider(*keys, default=None): diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 5fb6a540..ed60fb5b 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -8,6 +8,7 @@ import hashlib import logging import os import re +import copy import urllib from functools import partial from pathlib import Path @@ -469,13 +470,14 @@ def parse(infix): return {infix.pop(0): parse(infix)} -def update_config_from_wildcards(config, w): +def update_config_from_wildcards(config, w, inplace=True): """ Parses configuration settings from wildcards and updates the config. - - - TODO: Should be run inside config_provider function. """ + if not inplace: + config = copy.deepcopy(config) + if w.get("opts"): opts = w.opts.split("-") @@ -641,6 +643,9 @@ def update_config_from_wildcards(config, w): infix = o.split("+")[1:] update_config(config, parse(infix)) + if not inplace: + return config + def get_checksum_from_zenodo(file_url): parts = file_url.split("/") From 68f2e086c5c0f896de630d0327670d55ab4148e5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 20:48:17 +0100 Subject: [PATCH 334/591] postprocess.smk: add missing wildcard call --- rules/postprocess.smk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index dfcf9654..fe5a8c62 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -189,21 +189,21 @@ rule make_summary: **config["scenario"], run=config["run"]["name"], ), - h2_plot=expand( + h2_plot=lambda w: expand( ( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf" - if config_provider("sector", "H2_network") + if config_provider("sector", "H2_network")(w) else [] ), **config["scenario"], run=config["run"]["name"], ), - ch4_plot=expand( + ch4_plot=lambda w: expand( ( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf" - if config_provider("sector", "gas_network") + if config_provider("sector", "gas_network")(w) else [] ), **config["scenario"], From b543bf37c99bd757319869211cccf22b89b22154 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 20:48:46 +0100 Subject: [PATCH 335/591] retrieve.smk: do not protect gas network data --- rules/retrieve.smk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index d6fcbb26..766e7cf9 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -169,9 +169,7 @@ if config["enable"]["retrieve"]: rule retrieve_gas_infrastructure_data: output: - protected( - expand("data/gas_network/scigrid-gas/data/{files}", files=datafiles) - ), + expand("data/gas_network/scigrid-gas/data/{files}", files=datafiles), log: "logs/retrieve_gas_infrastructure_data.log", retries: 2 From 945180f153055036bcc67f633f39042299c76aa8 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 23:36:46 +0100 Subject: [PATCH 336/591] allow_missing in collection rules, fixes for myopic, wildcard constraints without function --- config/config.default.yaml | 2 +- rules/build_sector.smk | 12 ++++---- rules/common.smk | 7 +++-- rules/postprocess.smk | 45 +++++++++++++--------------- rules/solve_electricity.smk | 23 +++++++------- rules/solve_myopic.smk | 40 +++++++++++++------------ rules/solve_overnight.smk | 5 ++-- rules/solve_perfect.smk | 13 ++++---- scripts/base_network.py | 2 +- scripts/build_electricity_demand.py | 2 +- scripts/prepare_perfect_foresight.py | 2 +- 11 files changed, 79 insertions(+), 74 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 403b7269..1e7c87ce 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -25,7 +25,7 @@ run: enable: false file: config/scenarios.yaml disable_progressbar: false - shared_resources: false # TODO: splitting resources by wildcard does not work well, neither does true, only base works well + shared_resources: false shared_cutouts: true # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#foresight diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 0c755834..9e8bcb90 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -791,8 +791,6 @@ rule build_existing_heating_distribution: existing_heating_distribution=resources( "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), - wildcard_constraints: - planning_horizons=config_provider("scenario", "planning_horizons", 0), #only applies to baseyear threads: 1 resources: mem_mb=2000, @@ -934,12 +932,12 @@ rule prepare_sector_network: resources: mem_mb=2000, log: - logs( - "prepare_sector_network_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ), + RESULTS + + "logs/prepare_sector_network_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: - benchmarks( - "prepare_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ( + RESULTS + + "benchmarks/prepare_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" diff --git a/rules/common.smk b/rules/common.smk index ca339cec..9c41b57b 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -136,10 +136,11 @@ def input_eurostat(w): return f"data/bundle-sector/eurostat-energy_balances-june_{report_year}_edition" -def solved_previous_horizon(wildcards): - planning_horizons = config_provider("scenario", "planning_horizons") - i = planning_horizons.index(int(wildcards.planning_horizons)) +def solved_previous_horizon(w): + planning_horizons = config_provider("scenario", "planning_horizons")(w) + i = planning_horizons.index(int(w.planning_horizons)) planning_horizon_p = str(planning_horizons[i - 1]) + return ( RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_" diff --git a/rules/postprocess.smk b/rules/postprocess.smk index fe5a8c62..dc08699f 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -43,12 +43,12 @@ if config["foresight"] != "perfect": resources: mem_mb=10000, log: - logs( - "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ), + RESULTS + + "logs/plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: - benchmarks( - "plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ( + RESULTS + + "benchmarksplot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -70,12 +70,12 @@ if config["foresight"] != "perfect": resources: mem_mb=10000, log: - logs( - "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ), + RESULTS + + "logs/plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: - benchmarks( - "plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ( + RESULTS + + "benchmarks/plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -96,12 +96,12 @@ if config["foresight"] != "perfect": resources: mem_mb=10000, log: - logs( - "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ), + RESULTS + + "logs/plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: - benchmarks( - "plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ( + RESULTS + + "benchmarks/plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -131,10 +131,6 @@ if config["foresight"] == "perfect": threads: 2 resources: mem_mb=10000, - benchmark: - benchmarks( - "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years_benchmark" - ) conda: "../envs/environment.yaml" script: @@ -167,7 +163,7 @@ rule make_summary: RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", **config["scenario"], - run=config["run"]["name"], + allow_missing=True, ), costs=lambda w: ( resources("costs_{}.csv".format(config_provider("costs", "year")(w))) @@ -181,13 +177,13 @@ rule make_summary: ac_plot=expand( resources("maps/power-network-s{simpl}-{clusters}.pdf"), **config["scenario"], - run=config["run"]["name"], + allow_missing=True, ), costs_plot=expand( RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", **config["scenario"], - run=config["run"]["name"], + allow_missing=True, ), h2_plot=lambda w: expand( ( @@ -197,7 +193,7 @@ rule make_summary: else [] ), **config["scenario"], - run=config["run"]["name"], + allow_missing=True, ), ch4_plot=lambda w: expand( ( @@ -207,7 +203,7 @@ rule make_summary: else [] ), **config["scenario"], - run=config["run"]["name"], + allow_missing=True, ), output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", @@ -245,6 +241,7 @@ rule plot_summary: plotting=config_provider("plotting"), foresight=config_provider("foresight"), co2_budget=config_provider("co2_budget"), + sector=config_provider("sector"), RDIR=RDIR, input: costs=RESULTS + "csvs/costs.csv", diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index d3aa8d4c..6ddbc415 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -19,11 +19,13 @@ rule solve_network: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", log: solver=normpath( - logs("solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log") + RESULTS + + "logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log" ), - python=logs("solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log"), + python=RESULTS + + "logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", benchmark: - benchmarks("solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}") + RESULTS + "benchmarks/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" threads: solver_threads resources: mem_mb=memory, @@ -45,15 +47,16 @@ rule solve_operations_network: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc", log: solver=normpath( - logs( - "solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log" - ) - ), - python=logs( - "solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log" + RESULTS + + "logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log" ), + python=RESULTS + + "logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log", benchmark: - benchmarks("solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}") + ( + RESULTS + + "benchmarks/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" + ) threads: 4 resources: mem_mb=(lambda w: 10000 + 372 * int(w.clusters)), diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 8574bbb8..5eb30233 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -33,17 +33,20 @@ rule add_existing_baseyear: RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", wildcard_constraints: - planning_horizons=config_provider("scenario", "planning_horizons", 0), #only applies to baseyear + # TODO: The first planning_horizon needs to be aligned across scenarios + # snakemake does not support passing functions to wildcard_constraints + # reference: https://github.com/snakemake/snakemake/issues/2703 + planning_horizons=config["scenario"]["planning_horizons"][0], #only applies to baseyear threads: 1 resources: mem_mb=2000, log: - logs( - "add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ), + RESULTS + + "logs/add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: - benchmarks( - "add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ( + RESULTS + + "benchmarks/add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -85,12 +88,12 @@ rule add_brownfield: resources: mem_mb=10000, log: - logs( - "add_brownfield_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" - ), + RESULTS + + "logs/add_brownfield_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: - benchmarks( - "add_brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ( + RESULTS + + "benchmarks/add_brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -121,19 +124,18 @@ rule solve_sector_network_myopic: shadow: "shallow" log: - solver=logs( - "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" - ), + solver=RESULTS + + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_solver.log", + python=RESULTS + + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", threads: solver_threads resources: mem_mb=config_provider("solving", "mem"), walltime=config_provider("solving", "walltime", default="12:00:00"), benchmark: - benchmarks( - "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ( + RESULTS + + "benchmarks/solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index 64ad007c..69e2f364 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -33,8 +33,9 @@ rule solve_sector_network: mem_mb=config_provider("solving", "mem"), walltime=config_provider("solving", "walltime", default="12:00:00"), benchmark: - benchmarks( - "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + ( + RESULTS + + "benchmarks/solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 639bcae8..d3badcb0 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -32,7 +32,7 @@ rule add_existing_baseyear: RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", wildcard_constraints: - planning_horizons=config_provider("scenario", "planning_horizons", 0), #only applies to baseyear + planning_horizons=config["scenario"]["planning_horizons"][0], #only applies to baseyear threads: 1 resources: mem_mb=2000, @@ -53,7 +53,8 @@ rule add_existing_baseyear: def input_network_year(w): return { f"network_{year}": RESULTS - + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{year}.nc" + + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}" + + f"_{year}.nc" for year in config_provider("scenario", "planning_horizons")(w)[1:] } @@ -61,6 +62,7 @@ def input_network_year(w): rule prepare_perfect_foresight: params: costs=config_provider("costs"), + time_resolution=config_provider("clustering", "temporal", "sector"), input: unpack(input_network_year), brownfield_network=lambda w: ( @@ -98,7 +100,7 @@ rule solve_sector_network_perfect: sector=config_provider("sector"), planning_horizons=config_provider("scenario", "planning_horizons"), co2_sequestration_potential=config_provider( - "sector", "co2_sequestration_potential", 200 + "sector", "co2_sequestration_potential", default=200 ), custom_extra_functionality=input_custom_extra_functionality, input: @@ -122,8 +124,9 @@ rule solve_sector_network_perfect: memory=RESULTS + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years_memory.log", benchmark: - benchmarks( - "solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years}" + ( + RESULTS + + "benchmarks/solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years}" ) conda: "../envs/environment.yaml" diff --git a/scripts/base_network.py b/scripts/base_network.py index d83e0588..515ae481 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -767,7 +767,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("base_network", run="network2019") + snakemake = mock_snakemake("base_network") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 4415c835..47befb8a 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -258,7 +258,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_electricity_demand", run="network2019") + snakemake = mock_snakemake("build_electricity_demand") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index 2f2ff608..7f312a8f 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -517,7 +517,7 @@ if __name__ == "__main__": # temporal aggregate solver_name = snakemake.config["solving"]["solver"]["name"] - segments = snakemake.params["clustering"]["temporal"]["resolution_sector"] + segments = snakemake.params.time_resolution if isinstance(segments, (int, float)): n = apply_time_segmentation_perfect(n, segments, solver_name=solver_name) From 770d3526520ec1f3e814d7b694344d9d17888989 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 23:37:31 +0100 Subject: [PATCH 337/591] handle that time_resolution can be float --- scripts/prepare_network.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 6b782d44..72f4963a 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -291,7 +291,7 @@ def set_line_nom_max( n.lines["s_nom_max"] = n.lines["s_nom"] + s_nom_max_ext if np.isfinite(p_nom_max_ext) and p_nom_max_ext > 0: - logger.info(f"Limiting line extensions to {p_nom_max_ext} MW") + logger.info(f"Limiting link extensions to {p_nom_max_ext} MW") hvdc = n.links.index[n.links.carrier == "DC"] n.links.loc[hvdc, "p_nom_max"] = n.links.loc[hvdc, "p_nom"] + p_nom_max_ext @@ -322,13 +322,16 @@ if __name__ == "__main__": set_line_s_max_pu(n, snakemake.params.lines["s_max_pu"]) # temporal averaging - if nhours := snakemake.params.time_resolution: - n = average_every_nhours(n, nhours) + time_resolution = snakemake.params.time_resolution + is_string = isinstance(time_resolution, str) + if is_string and time_resolution.lower().endswith("h"): + n = average_every_nhours(n, time_resolution) # segments with package tsam - if time_seg := snakemake.params.time_resolution: + if is_string and time_resolution.lower().endswith("seg"): solver_name = snakemake.config["solving"]["solver"]["name"] - n = apply_time_segmentation(n, time_seg.replace("seg", ""), solver_name) + segments = int(time_resolution.replace("seg", "")) + n = apply_time_segmentation(n, segments, solver_name) if snakemake.params.co2limit_enable: add_co2limit(n, snakemake.params.co2limit, Nyears) From cf7018c8c44e56d0dfcfb295e5a50d1c5aeaf578 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 23:38:00 +0100 Subject: [PATCH 338/591] plot_summary: remove leftover references to opts wildcard --- scripts/plot_summary.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index 4119a811..82222620 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -428,13 +428,13 @@ def historical_emissions(countries): ) emissions = co2_totals.loc["electricity"] - if "T" in opts: + if options["transport"]: emissions += co2_totals.loc[[i + " non-elec" for i in ["rail", "road"]]].sum() - if "H" in opts: + if options["heating"]: emissions += co2_totals.loc[ [i + " non-elec" for i in ["residential", "services"]] ].sum() - if "I" in opts: + if options["industry"]: emissions += co2_totals.loc[ [ "industrial non-elec", @@ -448,7 +448,7 @@ def historical_emissions(countries): return emissions -def plot_carbon_budget_distribution(input_eurostat): +def plot_carbon_budget_distribution(input_eurostat, options): """ Plot historical carbon emissions in the EU and decarbonization path. """ @@ -470,7 +470,7 @@ def plot_carbon_budget_distribution(input_eurostat): e_1990 = co2_emissions_year( countries, input_eurostat, - opts, + options, emissions_scope, report_year, input_co2, @@ -588,4 +588,5 @@ if __name__ == "__main__": if ( isinstance(co2_budget, str) and co2_budget.startswith("cb") ) or snakemake.params["foresight"] == "perfect": - plot_carbon_budget_distribution(snakemake.input.eurostat) + options = snakemake.params.sector + plot_carbon_budget_distribution(snakemake.input.eurostat, options) From df0eb38a68a0fe1d93eab2d57ac7a8dd19cbf16d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 17 Feb 2024 23:38:59 +0100 Subject: [PATCH 339/591] _helpers: generalise regular expression in find_opt --- scripts/_helpers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index ed60fb5b..d30f205c 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -4,11 +4,11 @@ # SPDX-License-Identifier: MIT import contextlib +import copy import hashlib import logging import os import re -import copy import urllib from functools import partial from pathlib import Path @@ -117,9 +117,9 @@ def find_opt(opts, expr): """ for o in opts: if expr in o: - m = re.findall("^m?\d*(\.|p)?\d+$", o) + m = re.findall(r"m?\d+(?:[\.p]\d+)?", o) if len(m) > 0: - return True, float(m[0].replace("p", ".").replace("m", "-")) + return True, float(m[-1].replace("p", ".").replace("m", "-")) else: return True, None return False, None From d7935e1c065f8a0437190bb691e88a6a0e44272e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Feb 2024 09:45:37 +0100 Subject: [PATCH 340/591] revert part of #925 so that config.default.yaml is still copied and config.yaml remains untracked --- Snakefile | 10 +++++++--- config/config.yaml | 8 -------- 2 files changed, 7 insertions(+), 11 deletions(-) delete mode 100644 config/config.yaml diff --git a/Snakefile b/Snakefile index ee24841a..ca3e4c49 100644 --- a/Snakefile +++ b/Snakefile @@ -1,9 +1,9 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT -from os.path import normpath -from shutil import move, rmtree +from os.path import normpath, exists +from shutil import copyfile, move, rmtree from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider @@ -13,6 +13,10 @@ from snakemake.utils import min_version min_version("7.7") +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.default.yaml" configfile: "config/config.yaml" diff --git a/config/config.yaml b/config/config.yaml deleted file mode 100644 index efe2ccb2..00000000 --- a/config/config.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: : 2024 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: CC0-1.0 -# add your own configuration overrides here, for instance - -version: 0.9.0 -# enable: -# retrieve: false From 3e612950c203f6c2774df7b4c71a185f8541d75d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Feb 2024 09:45:37 +0100 Subject: [PATCH 341/591] revert part of #925 so that config.default.yaml is still copied and config.yaml remains untracked --- Snakefile | 10 +++++++--- config/config.yaml | 8 -------- doc/release_notes.rst | 3 +-- 3 files changed, 8 insertions(+), 13 deletions(-) delete mode 100644 config/config.yaml diff --git a/Snakefile b/Snakefile index ee24841a..ca3e4c49 100644 --- a/Snakefile +++ b/Snakefile @@ -1,9 +1,9 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT -from os.path import normpath -from shutil import move, rmtree +from os.path import normpath, exists +from shutil import copyfile, move, rmtree from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider @@ -13,6 +13,10 @@ from snakemake.utils import min_version min_version("7.7") +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.default.yaml" configfile: "config/config.yaml" diff --git a/config/config.yaml b/config/config.yaml deleted file mode 100644 index efe2ccb2..00000000 --- a/config/config.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: : 2024 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: CC0-1.0 -# add your own configuration overrides here, for instance - -version: 0.9.0 -# enable: -# retrieve: false diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 7feb4d72..68148086 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -34,8 +34,7 @@ Upcoming Release applied. * The default configuration ``config/config.default.yaml`` is now automatically - used as a base configuration file and no longer copied to - ``config/config.yaml`` on first use. The file ``config/config.yaml`` should be + used as a base configuration file. The file ``config/config.yaml`` should be used to define deviations from the default configuration. * Merged two OPSD time series data versions into such that the option ``load: From 20e37c232fc156aa998954a8b76eecfaaec5c338 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Feb 2024 09:55:45 +0100 Subject: [PATCH 342/591] copy a scenarios.yaml from scenarios.template.yaml so it is not git tracked --- Snakefile | 13 +++++++++---- config/{scenarios.yaml => scenarios.template.yaml} | 0 2 files changed, 9 insertions(+), 4 deletions(-) rename config/{scenarios.yaml => scenarios.template.yaml} (100%) diff --git a/Snakefile b/Snakefile index 1c8e1323..4f35dd74 100644 --- a/Snakefile +++ b/Snakefile @@ -16,10 +16,15 @@ from scripts._helpers import path_provider min_version("7.7") HTTP = HTTPRemoteProvider() -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) +default_files = { + "config/config.default.yaml": "config/config.yaml", + "config/scenarios.template.yaml": "config/scenarios.yaml", +} +for template, target in default_files.items(): + target = os.path.join(workflow.current_basedir, target) + template = os.path.join(workflow.current_basedir, template) + if not exists(target) and exists(template): + copyfile(template, target) configfile: "config/config.default.yaml" configfile: "config/config.yaml" diff --git a/config/scenarios.yaml b/config/scenarios.template.yaml similarity index 100% rename from config/scenarios.yaml rename to config/scenarios.template.yaml From 831f0779b3f0f333dc4527d473dc725c3d1c3bed Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 18 Feb 2024 08:57:24 +0000 Subject: [PATCH 343/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- Snakefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Snakefile b/Snakefile index 4f35dd74..2ab6bdc7 100644 --- a/Snakefile +++ b/Snakefile @@ -26,6 +26,7 @@ for template, target in default_files.items(): if not exists(target) and exists(template): copyfile(template, target) + configfile: "config/config.default.yaml" configfile: "config/config.yaml" From 67acbbda8a015d981f09f9a8b7f61b103da028ae Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Feb 2024 10:24:26 +0100 Subject: [PATCH 344/591] run: name: all will collect all keys from scenarios.yaml if run: scenarios: enable: true --- Snakefile | 16 ++++++++-------- doc/configtables/run.csv | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Snakefile b/Snakefile index 4f35dd74..1f02b877 100644 --- a/Snakefile +++ b/Snakefile @@ -10,7 +10,6 @@ import yaml from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider from snakemake.utils import min_version -# TODO: check if this works with mock_snakemake from scripts._helpers import path_provider min_version("7.7") @@ -32,13 +31,14 @@ configfile: "config/config.yaml" run = config["run"] scenarios = run.get("scenarios", {}) -if run["name"]: - if scenarios.get("enable"): - fn = Path(scenarios["file"]) - scenarios = yaml.safe_load(fn.read_text()) - RDIR = "{run}/" - else: - RDIR = run["name"] + "/" +if run["name"] and scenarios.get("enable"): + fn = Path(scenarios["file"]) + scenarios = yaml.safe_load(fn.read_text()) + RDIR = "{run}/" + if run["name"] == "all": + config["run"]["name"] = list(scenarios.keys()) +elif run["name"]: + RDIR = run["name"] + "/" else: RDIR = "" diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index f619d8bf..2835a324 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -1,8 +1,8 @@ ,Unit,Values,Description -name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenario: enable`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenario: file``." +name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenario: enable:`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenario: file:``. If the name is 'all', all defined scenarios will be run." scenarios,,, -- enable,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``file``." -- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run: scenarios`` has to be set to ``true`` and ``run: name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combination of settings, alter and use the ``config/create_scenarios.py`` script in the ``config`` directory." -disable_progrssbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." +disable_progressbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." shared_resources,bool/str,,"Switch to select whether resources should be shared across runs. If a string is passed, this is used as a subdirectory name for shared resources. If set to 'base', only resources before creating the elec.nc file are shared." shared_cutouts,bool,"{true, false}","Switch to select whether cutouts should be shared across runs." From 83f1b5e41d0030083ea5b84d7f305549035cc752 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Feb 2024 10:40:44 +0100 Subject: [PATCH 345/591] Add rule create_scenarios that runs config/create_scenarios.py on request --- Snakefile | 7 +++++++ config/create_scenarios.py | 16 ++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Snakefile b/Snakefile index 1f02b877..344b0934 100644 --- a/Snakefile +++ b/Snakefile @@ -93,6 +93,13 @@ rule all: default_target: True +rule create_scenarios: + output: + config["run"]["scenarios"]["file"], + script: + "config/create_scenarios.py" + + rule purge: run: import builtins diff --git a/config/create_scenarios.py b/config/create_scenarios.py index 40a3c331..4c407058 100644 --- a/config/create_scenarios.py +++ b/config/create_scenarios.py @@ -1,11 +1,15 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT # This script helps to generate a scenarios.yaml file for PyPSA-Eur. # You can modify the template to your needs and define all possible combinations of config values that should be considered. +if "snakemake" in globals(): + filename = snakemake.output[0] +else: + filename = "../config/scenarios.yaml" import itertools @@ -14,23 +18,23 @@ import itertools template = """ scenario{scenario_number}: config_section: - config_value: {config_value} - + config_key: {config_value} config_section2: config_key2: {config_value2} """ # Define all possible combinations of config values. # This must define all config values that are used in the template. -config_values = dict(config_values=["true", "false"], config_values2=[1, 2, 3, 4, 5]) +config_values = dict( + config_value=["true", "false"], + config_value2=[1, 2, 3, 4] +) combinations = [ dict(zip(config_values.keys(), values)) for values in itertools.product(*config_values.values()) ] -# write the scenarios to a file -filename = "../config/scenarios.yaml" with open(filename, "w") as f: for i, config in enumerate(combinations): f.write(template.format(scenario_number=i, **config)) From 1fb90da743e54a096f2c193b615cdbc8f7a059d5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 18 Feb 2024 09:42:20 +0000 Subject: [PATCH 346/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- config/create_scenarios.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/config/create_scenarios.py b/config/create_scenarios.py index 4c407058..cccc29bc 100644 --- a/config/create_scenarios.py +++ b/config/create_scenarios.py @@ -25,10 +25,7 @@ scenario{scenario_number}: # Define all possible combinations of config values. # This must define all config values that are used in the template. -config_values = dict( - config_value=["true", "false"], - config_value2=[1, 2, 3, 4] -) +config_values = dict(config_value=["true", "false"], config_value2=[1, 2, 3, 4]) combinations = [ dict(zip(config_values.keys(), values)) From 8e04b7a1573f305b5065a6a83b605608e9f73f3c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Feb 2024 11:03:37 +0100 Subject: [PATCH 347/591] test.sh: add scenarios dry-run to test cases --- Snakefile | 2 ++ ...config.scenarios.electricity.yaml => config.scenarios.yaml} | 2 +- config/test/{scenarios.electricity.yaml => scenarios.yaml} | 0 test.sh | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) rename config/test/{config.scenarios.electricity.yaml => config.scenarios.yaml} (95%) rename config/test/{scenarios.electricity.yaml => scenarios.yaml} (100%) diff --git a/Snakefile b/Snakefile index 7487b3d5..78a28373 100644 --- a/Snakefile +++ b/Snakefile @@ -97,6 +97,8 @@ rule all: rule create_scenarios: output: config["run"]["scenarios"]["file"], + conda: + "envs/retrieve.yaml" script: "config/create_scenarios.py" diff --git a/config/test/config.scenarios.electricity.yaml b/config/test/config.scenarios.yaml similarity index 95% rename from config/test/config.scenarios.electricity.yaml rename to config/test/config.scenarios.yaml index dde138ed..8ecbb91b 100644 --- a/config/test/config.scenarios.electricity.yaml +++ b/config/test/config.scenarios.yaml @@ -10,7 +10,7 @@ run: - test-elec-no-onshore-wind scenarios: enable: true - file: "config/test/scenarios.electricity.yaml" + file: "config/test/scenarios.yaml" disable_progressbar: true shared_resources: base shared_cutouts: true diff --git a/config/test/scenarios.electricity.yaml b/config/test/scenarios.yaml similarity index 100% rename from config/test/scenarios.electricity.yaml rename to config/test/scenarios.yaml diff --git a/test.sh b/test.sh index a40276b8..c36ce5cd 100755 --- a/test.sh +++ b/test.sh @@ -5,4 +5,5 @@ snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime && \ snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime && \ snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime && \ -snakemake -call all --configfile config/test/config.perfect.yaml --rerun-triggers=mtime +snakemake -call all --configfile config/test/config.perfect.yaml --rerun-triggers=mtime && \ +snakemake -call all --configfile config/test/config.scenarios.yaml --rerun-triggers=mtime -n && \ From 38c90155f1b7b3661335b9c722925e6e2c0d8c3e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Feb 2024 11:48:55 +0100 Subject: [PATCH 348/591] add release notes --- doc/release_notes.rst | 71 +++++++++++++++++++++++++++++++++++++++---- rules/validate.smk | 5 +-- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index c216fd35..0e96f013 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,12 +10,71 @@ Release Notes Upcoming Release ================ -* PyPSA-EUR now supports the simultaneous execution of multiple scenarios. For - this purpose, a scenarios.yaml file has been introduced which contains - customizable scenario names with corresponding configuration overrides. To - enable it, set the ``run: scenarios:`` key to ``True`` and define the scenario - names to run under ``run: name:`` in the configuration file. The latter must - be a subset of toplevel keys in the scenario file. +* Added new scenario management that supports the simultaneous execution of + multiple scenarios with a single ``snakemake`` call. For this purpose, a + ``scenarios.yaml`` file is introduced which contains customizable scenario + names with configuration overrides. To enable it, set the ``run: scenarios: + true`` and define the list of scenario names to run under ``run: name:`` in + the configuration file. The latter must be a subset of toplevel keys in the + scenario file. + + - To get started, a scenarios template file ``config/scenarios.template.yaml`` + is included in the repository, which is copied to ``config/scenarios.yaml`` + on first use. + + - The scenario file can be changed via ``run: scenarios: file:``. + + - If scenario management is activated with ``run: scenarios: enable: true``, a + new wildcard ``{run}`` is introduced. This means that the configuration + settings may depend on the new ``{run}`` wildcard. Therefore, a new + ``config_provider()`` function is used in the ``Snakefile`` and ``.smk`` + files, which takes wildcard values into account. The calls to the ``config`` + object have been reduced in ``.smk`` files since there is no awareness of + wildcard values outside rule definitions. + + - The scenario files can also be programmatically created using the template + script ``config/create_scenarios.py``. This script can be run with + ``snakemake -j1 create_scenarios`` and creates the scenarios file referenced + under ``run: scenarios: file:``. + + - The setting ``run: name: all`` will run all scenarios in + ``config/scenarios.yaml``. Otherwise, it will run those passed as list in + ``run: name:`` as long as ``run: scenarios: enable: true``. + + - The setting ``run: shared_resources:`` indicates via a boolean whether the + resources should be encapsulated by the ``run: name:``. The special setting + ``run: shared_resources: base`` shares resources until ``add_electricity`` + that do not contain wildcards other than ``{"technology", "year", + "scope"}``. + + - Added new configuration options for all ``{opts}`` and ``{sector_opts}`` + wildcard values to create a unique configuration file (``config.yaml``) per + PyPSA network file. This is done with the help of a new function + ``update_config_from_wildcards()`` which parses configuration settings from + wildcards and updates the ``snakemake.config`` object. These updated + configuration settings are used in the scripts rather than directly parsed + values from ``snakemake.wildcards``. + + - The cost data was moved from ``data/costs_{year}.csv`` to + ``resources/costs_{year}.csv`` since it depends on configuration settings. + The ``retrieve_cost_data`` rule was changed to calling a Python script. + + - Moved time clustering settings to ``clustering: temporal:`` from + ``snapshots:`` so that the latter is only used to define the + ``pandas.DatetimeIndex`` which simplifies the scenario management. + + - Collection rules get a new wildcard ``run=config["run"]["name"]`` so they + can collect outputs across different scenarios. + + - **Warning:** One caveat remains for the scenario management with myopic or + perfect foresight pathway optimisation. The first investment period must be + shared across all scenarios. The reason is that the ``wildcard_constraints`` + defined for the rule ``add_existing_baseyear`` do not accept wildcard-aware + input functions (cf. + `https://github.com/snakemake/snakemake/issues/2703`_). + +* The outputs of the rule ``retrieve_gas_infrastructure_data`` no longer + marked as ``protected()`` as the download size is small. * Improved representation of industry transition pathways. A new script was added to interpolate industry sector ratios from today's status quo to future diff --git a/rules/validate.smk b/rules/validate.smk index ec2d87cb..60a6ca50 100644 --- a/rules/validate.smk +++ b/rules/validate.smk @@ -17,10 +17,7 @@ rule build_electricity_production: The data is used for validation of the optimization results. """ params: - snapshots=lambda w: { - k: config_provider("snapshots", k)(w) - for k in ["start", "end", "inclusive"] - }, + snapshots=config_provider("snapshots"), countries=config_provider("countries"), output: resources("historical_electricity_production.csv"), From d6e710e74ae0dde3ff16c158ec5d4b1bfe990854 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sun, 18 Feb 2024 11:51:46 +0100 Subject: [PATCH 349/591] test.sh: patch end-of-file --- test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.sh b/test.sh index c36ce5cd..d6007750 100755 --- a/test.sh +++ b/test.sh @@ -6,4 +6,4 @@ snakemake -call solve_elec_networks --configfile config/test/config.electricity. snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime && \ snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime && \ snakemake -call all --configfile config/test/config.perfect.yaml --rerun-triggers=mtime && \ -snakemake -call all --configfile config/test/config.scenarios.yaml --rerun-triggers=mtime -n && \ +snakemake -call all --configfile config/test/config.scenarios.yaml --rerun-triggers=mtime -n From bbdcf0e055f12074422267f4342c12577cab532a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 19 Feb 2024 16:20:28 +0100 Subject: [PATCH 350/591] bump technology-data version to 0.8.0 --- config/config.default.yaml | 2 +- doc/release_notes.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 91f38b91..b4d96b12 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -662,7 +662,7 @@ industry: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#costs costs: year: 2030 - version: v0.7.0 + version: v0.8.0 rooftop_share: 0.14 # based on the potentials, assuming (0.1 kW/m2 and 10 m2/person) social_discountrate: 0.02 fill_values: diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 68148086..e0e0d22b 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -61,7 +61,7 @@ Upcoming Release * The filtering of power plants in the ``config.default.yaml`` has been updated regarding phased-out power plants in 2023. -* Upgrade techno-economic assumptions to ``technology-data`` v0.7.0. +* Upgrade techno-economic assumptions to ``technology-data`` v0.8.0. * Bugfix: Correct technology keys for the electricity production plotting to work out the box. From 16e2286188d25e40056296fa979c59564ae45887 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 19 Feb 2024 16:21:48 +0100 Subject: [PATCH 351/591] update copyright years to 2024 --- .gitattributes | 2 +- .github/workflows/ci.yaml | 2 +- .gitignore | 2 +- .readthedocs.yml | 2 +- .reuse/dep5 | 16 ++++++++-------- .sync-send | 2 +- LICENSES/MIT.txt | 2 +- README.md | 2 +- config/config.default.yaml | 2 +- config/config.entsoe-all.yaml | 2 +- config/config.perfect.yaml | 2 +- config/config.validation.yaml | 2 +- config/test/config.electricity.yaml | 2 +- config/test/config.myopic.yaml | 2 +- config/test/config.overnight.yaml | 2 +- config/test/config.perfect.yaml | 2 +- doc/Makefile | 2 +- doc/configuration.rst | 2 +- doc/contributing.rst | 2 +- doc/costs.rst | 2 +- doc/foresight.rst | 2 +- doc/index.rst | 2 +- doc/installation.rst | 2 +- doc/introduction.rst | 2 +- doc/licenses.rst | 2 +- doc/limitations.rst | 2 +- doc/make.bat | 2 +- doc/plotting.rst | 2 +- doc/preparation.rst | 2 +- doc/publications.bib | 2 +- doc/publications.rst | 2 +- doc/release_notes.rst | 2 +- doc/requirements.txt | 2 +- doc/retrieve.rst | 2 +- doc/sector.rst | 2 +- doc/simplification.rst | 2 +- doc/solving.rst | 2 +- doc/spatial_resolution.rst | 2 +- doc/supply_demand.rst | 2 +- doc/support.rst | 2 +- doc/tutorial.rst | 2 +- doc/tutorial_sector.rst | 2 +- doc/validation.rst | 2 +- doc/wildcards.rst | 2 +- envs/environment.yaml | 2 +- matplotlibrc | 2 +- rules/build_electricity.smk | 2 +- rules/build_sector.smk | 2 +- rules/collect.smk | 2 +- rules/common.smk | 2 +- rules/retrieve.smk | 2 +- rules/solve_electricity.smk | 2 +- rules/solve_overnight.smk | 2 +- rules/solve_perfect.smk | 2 +- rules/validate.smk | 2 +- scripts/_benchmark.py | 2 +- scripts/_helpers.py | 2 +- scripts/add_brownfield.py | 2 +- scripts/add_electricity.py | 2 +- scripts/add_existing_baseyear.py | 2 +- scripts/add_extra_components.py | 2 +- scripts/base_network.py | 2 +- scripts/build_ammonia_production.py | 2 +- scripts/build_biomass_potentials.py | 2 +- scripts/build_biomass_transport_costs.py | 2 +- scripts/build_bus_regions.py | 2 +- scripts/build_clustered_population_layouts.py | 2 +- scripts/build_cop_profiles.py | 2 +- scripts/build_cross_border_flows.py | 2 +- scripts/build_cutout.py | 2 +- scripts/build_daily_heat_demand.py | 2 +- scripts/build_electricity_prices.py | 2 +- scripts/build_electricity_production.py | 2 +- scripts/build_energy_totals.py | 2 +- scripts/build_gas_input_locations.py | 2 +- scripts/build_gas_network.py | 2 +- scripts/build_hourly_heat_demand.py | 2 +- scripts/build_hydro_profile.py | 2 +- scripts/build_industrial_distribution_key.py | 2 +- ...industrial_energy_demand_per_country_today.py | 2 +- .../build_industrial_energy_demand_per_node.py | 2 +- ...ld_industrial_energy_demand_per_node_today.py | 2 +- .../build_industrial_production_per_country.py | 2 +- ...industrial_production_per_country_tomorrow.py | 2 +- scripts/build_industrial_production_per_node.py | 2 +- scripts/build_industry_sector_ratios.py | 2 +- scripts/build_monthly_prices.py | 2 +- scripts/build_natura_raster.py | 2 +- scripts/build_population_layouts.py | 2 +- .../build_population_weighted_energy_totals.py | 2 +- scripts/build_renewable_profiles.py | 2 +- scripts/build_retro_cost.py | 2 +- scripts/build_salt_cavern_potentials.py | 2 +- scripts/build_sequestration_potentials.py | 2 +- scripts/build_shapes.py | 2 +- scripts/build_shipping_demand.py | 2 +- scripts/build_solar_thermal_profiles.py | 2 +- scripts/build_temperature_profiles.py | 2 +- scripts/build_transport_demand.py | 2 +- scripts/cluster_gas_network.py | 2 +- scripts/cluster_network.py | 2 +- scripts/copy_config.py | 2 +- scripts/determine_availability_matrix_MD_UA.py | 2 +- scripts/make_summary.py | 2 +- scripts/make_summary_perfect.py | 2 +- scripts/plot_statistics.py | 2 +- scripts/plot_summary.py | 2 +- scripts/plot_validation_cross_border_flows.py | 2 +- scripts/plot_validation_electricity_prices.py | 2 +- .../plot_validation_electricity_production.py | 2 +- scripts/prepare_links_p_nom.py | 2 +- scripts/prepare_network.py | 2 +- scripts/prepare_perfect_foresight.py | 2 +- scripts/prepare_sector_network.py | 2 +- scripts/retrieve_databundle.py | 2 +- scripts/retrieve_gas_infrastructure_data.py | 2 +- scripts/retrieve_irena.py | 2 +- scripts/retrieve_monthly_fuel_prices.py | 2 +- scripts/retrieve_sector_databundle.py | 2 +- scripts/simplify_network.py | 2 +- scripts/solve_network.py | 2 +- scripts/solve_operations_network.py | 2 +- 122 files changed, 129 insertions(+), 129 deletions(-) diff --git a/.gitattributes b/.gitattributes index 3f5e771d..b82aaff1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1af8e733..bad6039f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2021-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2021-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/.gitignore b/.gitignore index 6454616c..e9eb7b09 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/.readthedocs.yml b/.readthedocs.yml index 30684052..ca388d80 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/.reuse/dep5 b/.reuse/dep5 index cd8e2660..27edd808 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -4,33 +4,33 @@ Upstream-Contact: Tom Brown Source: https://github.com/pypsa/pypsa-eur Files: doc/img/* -Copyright: 2019-2023 The PyPSA-Eur Authors +Copyright: 2019-2024 The PyPSA-Eur Authors License: CC-BY-4.0 Files: doc/data.csv -Copyright: 2019-2023 The PyPSA-Eur Authors +Copyright: 2019-2024 The PyPSA-Eur Authors License: CC-BY-4.0 Files: doc/configtables/* -Copyright: 2019-2023 The PyPSA-Eur Authors +Copyright: 2019-2024 The PyPSA-Eur Authors License: CC-BY-4.0 Files: data/* -Copyright: 2017-2023 The PyPSA-Eur Authors +Copyright: 2017-2024 The PyPSA-Eur Authors License: CC-BY-4.0 Files: .github/* -Copyright: 2019-2023 The PyPSA-Eur Authors +Copyright: 2019-2024 The PyPSA-Eur Authors License: CC0-1.0 Files: matplotlibrc -Copyright: 2017-2023 The PyPSA-Eur Authors +Copyright: 2017-2024 The PyPSA-Eur Authors License: CC0-1.0 Files: borg-it -Copyright: 2017-2023 The PyPSA-Eur Authors +Copyright: 2017-2024 The PyPSA-Eur Authors License: CC0-1.0 Files: graphics/* -Copyright: 2017-2023 The PyPSA-Eur Authors +Copyright: 2017-2024 The PyPSA-Eur Authors License: CC-BY-4.0 diff --git a/.sync-send b/.sync-send index 72252956..483c7a99 100644 --- a/.sync-send +++ b/.sync-send @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2021-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2021-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt index 87f6d959..baf15333 100644 --- a/LICENSES/MIT.txt +++ b/LICENSES/MIT.txt @@ -1,6 +1,6 @@ MIT License -Copyright 2017-2023 The PyPSA-Eur Authors +Copyright 2017-2024 The PyPSA-Eur Authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/README.md b/README.md index 4a58d75c..b4c03574 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ diff --git a/config/config.default.yaml b/config/config.default.yaml index b4d96b12..6eacdcc9 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/config/config.entsoe-all.yaml b/config/config.entsoe-all.yaml index dd19d2c7..40e3c0a5 100644 --- a/config/config.entsoe-all.yaml +++ b/config/config.entsoe-all.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/config/config.perfect.yaml b/config/config.perfect.yaml index ff531303..7bfdbdd2 100644 --- a/config/config.perfect.yaml +++ b/config/config.perfect.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 run: diff --git a/config/config.validation.yaml b/config/config.validation.yaml index 5bcd5c31..c8fb2fa5 100644 --- a/config/config.validation.yaml +++ b/config/config.validation.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 run: diff --git a/config/test/config.electricity.yaml b/config/test/config.electricity.yaml index 22c8e8d3..57964415 100644 --- a/config/test/config.electricity.yaml +++ b/config/test/config.electricity.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index 2e7b3e6e..5abae36d 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index 8b98fea9..7fb53e42 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/config/test/config.perfect.yaml b/config/test/config.perfect.yaml index 2e716066..5d77c9c5 100644 --- a/config/test/config.perfect.yaml +++ b/config/test/config.perfect.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/doc/Makefile b/doc/Makefile index a2ae2428..9eea4532 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/doc/configuration.rst b/doc/configuration.rst index f65aa4c2..ab01ddd5 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/contributing.rst b/doc/contributing.rst index 30de4f7e..0bf969b6 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/costs.rst b/doc/costs.rst index 5ddbb360..fd2feb17 100644 --- a/doc/costs.rst +++ b/doc/costs.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/foresight.rst b/doc/foresight.rst index f8ea6108..c749c84c 100644 --- a/doc/foresight.rst +++ b/doc/foresight.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2021-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2021-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/index.rst b/doc/index.rst index 7eaffa01..acff820b 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/installation.rst b/doc/installation.rst index 4289b098..4aea5414 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/introduction.rst b/doc/introduction.rst index 0047f0a7..d271391c 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/licenses.rst b/doc/licenses.rst index beb6f5b8..74640ea5 100644 --- a/doc/licenses.rst +++ b/doc/licenses.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2023-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/limitations.rst b/doc/limitations.rst index a67fad0c..2aa8ecfe 100644 --- a/doc/limitations.rst +++ b/doc/limitations.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/make.bat b/doc/make.bat index 3037f934..d64ffdc8 100644 --- a/doc/make.bat +++ b/doc/make.bat @@ -1,4 +1,4 @@ -REM SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors +REM SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors REM SPDX-License-Identifier: MIT @ECHO OFF diff --git a/doc/plotting.rst b/doc/plotting.rst index 02748cf2..a5229d8d 100644 --- a/doc/plotting.rst +++ b/doc/plotting.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/preparation.rst b/doc/preparation.rst index d8f76839..bb55ba6b 100644 --- a/doc/preparation.rst +++ b/doc/preparation.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/publications.bib b/doc/publications.bib index 4be6676a..5e1ee364 100644 --- a/doc/publications.bib +++ b/doc/publications.bib @@ -1,5 +1,5 @@ @Comment{ -SPDX-FileCopyrightText: 2023 The PyPSA-Eur Authors +SPDX-FileCopyrightText: 2023-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC0-1.0 } diff --git a/doc/publications.rst b/doc/publications.rst index c824873e..f6d7986b 100644 --- a/doc/publications.rst +++ b/doc/publications.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2023-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/release_notes.rst b/doc/release_notes.rst index e0e0d22b..45e3de36 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/requirements.txt b/doc/requirements.txt index 3e760c81..a1cd0a5c 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2019-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2019-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 diff --git a/doc/retrieve.rst b/doc/retrieve.rst index e4800fd2..24b51371 100644 --- a/doc/retrieve.rst +++ b/doc/retrieve.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/sector.rst b/doc/sector.rst index 411bfd57..84a5fdc9 100644 --- a/doc/sector.rst +++ b/doc/sector.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2023-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/simplification.rst b/doc/simplification.rst index 21f61de7..2272505d 100644 --- a/doc/simplification.rst +++ b/doc/simplification.rst @@ -1,7 +1,7 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/solving.rst b/doc/solving.rst index 21cc5c25..a8020d29 100644 --- a/doc/solving.rst +++ b/doc/solving.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/spatial_resolution.rst b/doc/spatial_resolution.rst index c6e9c3de..a408f464 100644 --- a/doc/spatial_resolution.rst +++ b/doc/spatial_resolution.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2021-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2021-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/supply_demand.rst b/doc/supply_demand.rst index b043268b..8f6edcad 100644 --- a/doc/supply_demand.rst +++ b/doc/supply_demand.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2021-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2021-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/support.rst b/doc/support.rst index 1d512d59..1a3e6d08 100644 --- a/doc/support.rst +++ b/doc/support.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/tutorial.rst b/doc/tutorial.rst index e58ad123..542263e5 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/tutorial_sector.rst b/doc/tutorial_sector.rst index 53a60353..25690bf7 100644 --- a/doc/tutorial_sector.rst +++ b/doc/tutorial_sector.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2023-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/validation.rst b/doc/validation.rst index 7049e3de..e538717c 100644 --- a/doc/validation.rst +++ b/doc/validation.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/doc/wildcards.rst b/doc/wildcards.rst index 75eec192..f86ff311 100644 --- a/doc/wildcards.rst +++ b/doc/wildcards.rst @@ -1,5 +1,5 @@ .. - SPDX-FileCopyrightText: 2019-2023 The PyPSA-Eur Authors + SPDX-FileCopyrightText: 2019-2024 The PyPSA-Eur Authors SPDX-License-Identifier: CC-BY-4.0 diff --git a/envs/environment.yaml b/envs/environment.yaml index 88e394fa..0e82ddc3 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/matplotlibrc b/matplotlibrc index f00ed5cd..bf667fb1 100644 --- a/matplotlibrc +++ b/matplotlibrc @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: CC0-1.0 font.family: sans-serif diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index f05e18c0..827b4278 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 65000512..acdc3203 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/rules/collect.smk b/rules/collect.smk index dc0a94cc..a857ac64 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/rules/common.smk b/rules/common.smk index 598d3b98..32b94211 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/rules/retrieve.smk b/rules/retrieve.smk index acb8a1c1..9fb38b36 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index ac433cf9..b022cd30 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index aa08b8c3..c4c77992 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 9e164a16..4ce5c081 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT rule add_existing_baseyear: diff --git a/rules/validate.smk b/rules/validate.smk index 0fa1f607..75cb73a9 100644 --- a/rules/validate.smk +++ b/rules/validate.smk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/_benchmark.py b/scripts/_benchmark.py index ced102ba..58fc3d39 100644 --- a/scripts/_benchmark.py +++ b/scripts/_benchmark.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 3de23c9f..b87870a1 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 3b77c437..a82b0c29 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 614e3330..49e69f62 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index c0d37a5b..91b8a822 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index 731e36be..20f66a9f 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/base_network.py b/scripts/base_network.py index 81db4074..8b976875 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/build_ammonia_production.py b/scripts/build_ammonia_production.py index e2cf6a7b..51ad25ec 100644 --- a/scripts/build_ammonia_production.py +++ b/scripts/build_ammonia_production.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_biomass_potentials.py b/scripts/build_biomass_potentials.py index 6b5cb147..cf048685 100644 --- a/scripts/build_biomass_potentials.py +++ b/scripts/build_biomass_potentials.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2021-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2021-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_biomass_transport_costs.py b/scripts/build_biomass_transport_costs.py index 05b64519..9c825c47 100644 --- a/scripts/build_biomass_transport_costs.py +++ b/scripts/build_biomass_transport_costs.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_bus_regions.py b/scripts/build_bus_regions.py index f9bf287e..60bc7ac3 100644 --- a/scripts/build_bus_regions.py +++ b/scripts/build_bus_regions.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index f1d386bd..2697e448 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_cop_profiles.py b/scripts/build_cop_profiles.py index 4b1d952e..4e4f52a9 100644 --- a/scripts/build_cop_profiles.py +++ b/scripts/build_cop_profiles.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_cross_border_flows.py b/scripts/build_cross_border_flows.py index b9fc3fe8..2f3a411f 100644 --- a/scripts/build_cross_border_flows.py +++ b/scripts/build_cross_border_flows.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/build_cutout.py b/scripts/build_cutout.py index 9a7f9e00..60b2c244 100644 --- a/scripts/build_cutout.py +++ b/scripts/build_cutout.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_daily_heat_demand.py b/scripts/build_daily_heat_demand.py index e334b1b3..edbdfebf 100644 --- a/scripts/build_daily_heat_demand.py +++ b/scripts/build_daily_heat_demand.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_electricity_prices.py b/scripts/build_electricity_prices.py index 353ea7e3..4733098e 100644 --- a/scripts/build_electricity_prices.py +++ b/scripts/build_electricity_prices.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/build_electricity_production.py b/scripts/build_electricity_production.py index e89ad78b..741f1c61 100644 --- a/scripts/build_electricity_production.py +++ b/scripts/build_electricity_production.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index c67bb49d..dd27e019 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_gas_input_locations.py b/scripts/build_gas_input_locations.py index 081f74b9..a2fc335c 100644 --- a/scripts/build_gas_input_locations.py +++ b/scripts/build_gas_input_locations.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2021-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2021-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_gas_network.py b/scripts/build_gas_network.py index 13cd75ba..70f1f168 100644 --- a/scripts/build_gas_network.py +++ b/scripts/build_gas_network.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_hourly_heat_demand.py b/scripts/build_hourly_heat_demand.py index c972da89..ead125af 100644 --- a/scripts/build_hourly_heat_demand.py +++ b/scripts/build_hourly_heat_demand.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 65cc22b7..70b6662c 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index 9b234e29..d80dff5a 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_industrial_energy_demand_per_country_today.py b/scripts/build_industrial_energy_demand_per_country_today.py index 9105a790..1c9a8c15 100644 --- a/scripts/build_industrial_energy_demand_per_country_today.py +++ b/scripts/build_industrial_energy_demand_per_country_today.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_industrial_energy_demand_per_node.py b/scripts/build_industrial_energy_demand_per_node.py index ec571c71..8a3b1831 100644 --- a/scripts/build_industrial_energy_demand_per_node.py +++ b/scripts/build_industrial_energy_demand_per_node.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_industrial_energy_demand_per_node_today.py b/scripts/build_industrial_energy_demand_per_node_today.py index d845e704..0bce5c5c 100644 --- a/scripts/build_industrial_energy_demand_per_node_today.py +++ b/scripts/build_industrial_energy_demand_per_node_today.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_industrial_production_per_country.py b/scripts/build_industrial_production_per_country.py index afab1403..70af1d48 100644 --- a/scripts/build_industrial_production_per_country.py +++ b/scripts/build_industrial_production_per_country.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_industrial_production_per_country_tomorrow.py b/scripts/build_industrial_production_per_country_tomorrow.py index ffed5195..a95bca89 100644 --- a/scripts/build_industrial_production_per_country_tomorrow.py +++ b/scripts/build_industrial_production_per_country_tomorrow.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_industrial_production_per_node.py b/scripts/build_industrial_production_per_node.py index 7b69948a..46262180 100644 --- a/scripts/build_industrial_production_per_node.py +++ b/scripts/build_industrial_production_per_node.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_industry_sector_ratios.py b/scripts/build_industry_sector_ratios.py index 805cf3e7..88e5f180 100644 --- a/scripts/build_industry_sector_ratios.py +++ b/scripts/build_industry_sector_ratios.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_monthly_prices.py b/scripts/build_monthly_prices.py index 1c6d461b..f6edaf12 100644 --- a/scripts/build_monthly_prices.py +++ b/scripts/build_monthly_prices.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/build_natura_raster.py b/scripts/build_natura_raster.py index 8fdb4ea3..4f992297 100644 --- a/scripts/build_natura_raster.py +++ b/scripts/build_natura_raster.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index cb63c27e..b455df78 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 879e3b9b..6ac4e946 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index a075450d..c9b0da0c 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_retro_cost.py b/scripts/build_retro_cost.py index 60d74afa..39f6b965 100755 --- a/scripts/build_retro_cost.py +++ b/scripts/build_retro_cost.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_salt_cavern_potentials.py b/scripts/build_salt_cavern_potentials.py index ed039772..64266291 100644 --- a/scripts/build_salt_cavern_potentials.py +++ b/scripts/build_salt_cavern_potentials.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_sequestration_potentials.py b/scripts/build_sequestration_potentials.py index f6ad3526..c7a0089b 100644 --- a/scripts/build_sequestration_potentials.py +++ b/scripts/build_sequestration_potentials.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_shapes.py b/scripts/build_shapes.py index c5faf597..7f5effe1 100644 --- a/scripts/build_shapes.py +++ b/scripts/build_shapes.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_shipping_demand.py b/scripts/build_shipping_demand.py index 8000c66c..b8e5fbb1 100644 --- a/scripts/build_shipping_demand.py +++ b/scripts/build_shipping_demand.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index ee6ed881..331725eb 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index 02fa4a71..0403a7be 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index 33c8faae..74fe2242 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/cluster_gas_network.py b/scripts/cluster_gas_network.py index e709d772..e3b0f7d9 100755 --- a/scripts/cluster_gas_network.py +++ b/scripts/cluster_gas_network.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index fe74ac38..9aea9826 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/copy_config.py b/scripts/copy_config.py index 3dbee6a4..9bba7383 100644 --- a/scripts/copy_config.py +++ b/scripts/copy_config.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/determine_availability_matrix_MD_UA.py b/scripts/determine_availability_matrix_MD_UA.py index efe9a712..72bd0f76 100644 --- a/scripts/determine_availability_matrix_MD_UA.py +++ b/scripts/determine_availability_matrix_MD_UA.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 76d8099c..1f106fe7 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/make_summary_perfect.py b/scripts/make_summary_perfect.py index 064db454..1aec89c4 100644 --- a/scripts/make_summary_perfect.py +++ b/scripts/make_summary_perfect.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/plot_statistics.py b/scripts/plot_statistics.py index b2728931..b6b8620b 100644 --- a/scripts/plot_statistics.py +++ b/scripts/plot_statistics.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index cfb32441..7af0ba79 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/plot_validation_cross_border_flows.py b/scripts/plot_validation_cross_border_flows.py index 65f4f8c7..d062bdf1 100644 --- a/scripts/plot_validation_cross_border_flows.py +++ b/scripts/plot_validation_cross_border_flows.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/plot_validation_electricity_prices.py b/scripts/plot_validation_electricity_prices.py index 38c9fe96..86217096 100644 --- a/scripts/plot_validation_electricity_prices.py +++ b/scripts/plot_validation_electricity_prices.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/plot_validation_electricity_production.py b/scripts/plot_validation_electricity_production.py index e95a8126..8e9ced16 100644 --- a/scripts/plot_validation_electricity_production.py +++ b/scripts/plot_validation_electricity_production.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/prepare_links_p_nom.py b/scripts/prepare_links_p_nom.py index 4b915d22..35f3a2fd 100644 --- a/scripts/prepare_links_p_nom.py +++ b/scripts/prepare_links_p_nom.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index e358c05e..8936afef 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index cf013577..7cc95f33 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 5d5e271b..b1351089 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/retrieve_databundle.py b/scripts/retrieve_databundle.py index 25894063..fcfa8ff4 100644 --- a/scripts/retrieve_databundle.py +++ b/scripts/retrieve_databundle.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright 2019-2022 Fabian Hofmann (TUB, FIAS) -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/retrieve_gas_infrastructure_data.py b/scripts/retrieve_gas_infrastructure_data.py index d984b9fe..be5908a6 100644 --- a/scripts/retrieve_gas_infrastructure_data.py +++ b/scripts/retrieve_gas_infrastructure_data.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2021-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2021-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/retrieve_irena.py b/scripts/retrieve_irena.py index 7b123475..6f42b371 100644 --- a/scripts/retrieve_irena.py +++ b/scripts/retrieve_irena.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright 2023 Thomas Gilon (Climact) -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/retrieve_monthly_fuel_prices.py b/scripts/retrieve_monthly_fuel_prices.py index e64066cb..e3a3eea8 100644 --- a/scripts/retrieve_monthly_fuel_prices.py +++ b/scripts/retrieve_monthly_fuel_prices.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2023-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/retrieve_sector_databundle.py b/scripts/retrieve_sector_databundle.py index 5baf2c56..e20664c7 100644 --- a/scripts/retrieve_sector_databundle.py +++ b/scripts/retrieve_sector_databundle.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2021-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2021-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index cc4ff4f6..47635189 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 551222c0..5d3982a3 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ diff --git a/scripts/solve_operations_network.py b/scripts/solve_operations_network.py index dca49d02..73590d68 100644 --- a/scripts/solve_operations_network.py +++ b/scripts/solve_operations_network.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT """ From 2bb4e81dbdaf41105c2b4431c317e10b6d603543 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 19 Feb 2024 16:58:18 +0100 Subject: [PATCH 352/591] prepare release notes --- doc/release_notes.rst | 259 ++++++++++++++++++++++++++++-------------- 1 file changed, 171 insertions(+), 88 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 45e3de36..6716ebcf 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -7,8 +7,14 @@ Release Notes ########################################## -Upcoming Release -================ +.. Upcoming Release +.. ================ +.. + +PyPSA-Eur 0.10.0 (19th February 2024) +===================================== + +**New Features** * Improved representation of industry transition pathways. A new script was added to interpolate industry sector ratios from today's status quo to future @@ -17,113 +23,80 @@ Upcoming Release energy carrier usage per ton material output to the best-in-class energy consumption of tomorrow. This is done on a per-country basis. The ratio of today to tomorrow's energy consumption is set with the ``industry: - sector_ratios_fraction_future:`` parameter. - -* Fix plotting of retrofitted hydrogen pipelines with pathway optimisation. - -* Bugfix: Correct units of subtracted chlorine and methanol demand in - :mod:`build_industry_sector_ratios`. - -* Include all countries in ammonia production resource. This is so that the full - EU28 ammonia demand can be correctly subtracted in the rule - :mod:`build_industry_sector_ratios`. - -* Regions are assigned to all buses with unique coordinates in the network with - a preference given to substations. Previously, only substations had assigned - regions, but this could lead to issues when a high spatial resolution was - applied. - -* The default configuration ``config/config.default.yaml`` is now automatically - used as a base configuration file. The file ``config/config.yaml`` should be - used to define deviations from the default configuration. - -* Merged two OPSD time series data versions into such that the option ``load: - power_statistics:`` becomes superfluous and was hence removed. -* Bugfix: The industry coal emissions for industry were not properly tracked. - -* Allow industrial coal demand to be regional so its emissions can be included - in regional emission limits. + sector_ratios_fraction_future:`` parameter + (https://github.com/PyPSA/pypsa-eur/pull/929). * Add new default to overdimension heating in individual buildings. This allows them to cover heat demand peaks e.g. 10% higher than those in the data. The disadvantage of manipulating the costs is that the capacity is then not quite - right. This way at least the costs are right. + right. This way at least the costs are right + (https://github.com/PyPSA/pypsa-eur/pull/918). + +* Allow industrial coal demand to be regional so its emissions can be included + in regional emission limits (https://github.com/PyPSA/pypsa-eur/pull/923). * Add option to specify to set a default heating lifetime for existing heating - (``existing_capacities: default_heating_lifetime:``). + (``existing_capacities: default_heating_lifetime:``) + (https://github.com/PyPSA/pypsa-eur/pull/918). -* Correctly source the existing heating technologies for buildings since the - source URL has changed. It represents the year 2012 and is only for - buildings, not district heating. So the capacities for urban central are now - set to zero from this source. +* Added option to specify turbine and solar panel models for specific years as a + dictionary (e.g. ``renewable: onwind: resource: turbine:``). The years will be + interpreted as years from when the the corresponding turbine model substitutes + the previous model for new installations. This will only have an effect on + workflows with foresight ``"myopic"`` and still needs to be added foresight + option ``"perfect"`` (https://github.com/PyPSA/pypsa-eur/pull/912). -* Remove long-deprecated function ``attach_extendable_generators`` in :mod:`add_electricity`. +* New configuration option ``everywhere_powerplants`` to build conventional + powerplants everywhere, irrespective of existing powerplants locations, in the + network (https://github.com/PyPSA/pypsa-eur/pull/850). -* The filtering of power plants in the ``config.default.yaml`` has been updated regarding phased-out power plants in 2023. +* Add the option to customise map projection in plotting config under + ``plotting: projection: name`` (https://github.com/PyPSA/pypsa-eur/pull/898). -* Upgrade techno-economic assumptions to ``technology-data`` v0.8.0. +* Add support for the linopy ``io_api`` option under ``solving: options: + io_api:``. Set to ``"direct"`` to increase model reading and writing + performance for the highs and gurobi solvers on slow file systems + (https://github.com/PyPSA/pypsa-eur/pull/892). -* Bugfix: Correct technology keys for the electricity production plotting to work out the box. +* It is now possible to determine the directory for shared resources by setting + `shared_resources` to a string (https://github.com/PyPSA/pypsa-eur/pull/906). -* New configuration option ``everywhere_powerplants`` to build conventional powerplants everywhere, irrespective of existing powerplants locations, in the network (https://github.com/PyPSA/pypsa-eur/pull/850). + +**Breaking Changes** + +* Remove long-deprecated function ``attach_extendable_generators`` in + :mod:`add_electricity`. * Remove option for wave energy as technology data is not maintained. -* Define global constraint for CO2 emissions on the final state of charge of the - CO2 atmosphere store. This gives a more sparse constraint that should improve - the performance of the solving process. +* The order of buses (bus0, bus1, ...) for DAC components has changed to meet + the convention of the other components. Therefore, `bus0` refers to the + electricity bus (input), `bus1` to the heat bus (input), 'bus2' to the CO2 + atmosphere bus (input), and `bus3` to the CO2 storage bus (output) + (https://github.com/PyPSA/pypsa-eur/pull/901). -* Bugfix: Assure entering of code block which corrects Norwegian heat demand. +**Changes** -* Add warning when BEV availability weekly profile has negative values in `build_transport_demand`. +* Upgrade default techno-economic assumptions to ``technology-data`` v0.8.0. -* Stacktrace of uncaught exceptions should now be correctly included inside log files (via `configure_logging(..)`). - -* Cluster residential and services heat buses by default. Can be disabled with ``cluster_heat_buses: false``. - -* Bugfix: Do not reduce district heat share when building population-weighted - energy statistics. Previously the district heating share was being multiplied - by the population weighting, reducing the DH share with multiple nodes. +* Update hydrogen pipeline losses to latest data from Danish Energy Agency + (https://github.com/PyPSA/pypsa-eur/pull/933). * Move building of daily heat profile to its own rule - :mod:`build_hourly_heat_demand` from :mod:`prepare_sector_network`. + :mod:`build_hourly_heat_demand` from :mod:`prepare_sector_network` + (https://github.com/PyPSA/pypsa-eur/pull/884). * In :mod:`build_energy_totals`, district heating shares are now reported in a - separate file. + separate file (https://github.com/PyPSA/pypsa-eur/pull/884). * Move calculation of district heating share to its own rule - :mod:`build_district_heat_share`. + :mod:`build_district_heat_share` + (https://github.com/PyPSA/pypsa-eur/pull/884). * Move building of distribution of existing heating to own rule :mod:`build_existing_heating_distribution`. This makes the distribution of existing heating to urban/rural, residential/services and spatially more - transparent. - -* Bugfix: Correctly read out number of solver threads from configuration file. - -* Air-sourced heat pumps can now also be built in rural areas. Previously, only - ground-sourced heat pumps were considered for this category. - -* 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 the option to customise map projection in plotting config. - -* The order of buses (bus0, bus1, ...) for DAC components has changed to meet the convention of the other components. Therefore, `bus0` refers to the electricity bus (input), `bus1` to the heat bus (input), 'bus2' to the CO2 atmosphere bus (input), and `bus3` to the CO2 storage bus (output). - -* The rule ``plot_network`` has been split into separate rules for plotting - electricity, hydrogen and gas networks. - -* To determine the optimal topology to meet the number of clusters, the workflow used pyomo in combination with ``ipopt`` or ``gurobi``. This dependency has been replaced by using ``linopy`` in combination with ``scipopt`` or ``gurobi``. The environment file has been updated accordingly. - -* The ``highs`` solver was added to the default environment file. - -* Various minor bugfixes to the perfect foresight workflow, though perfect foresight must still be considered experimental. - -* It is now possible to determine the directory for shared resources by setting `shared_resources` to a string. - -* A ``test.sh`` script was added to the repository to run the tests locally. + transparent (https://github.com/PyPSA/pypsa-eur/pull/884). * Default settings for recycling rates and primary product shares of high-value chemicals have been set in accordance with the values used in `Neumann et al. @@ -132,14 +105,124 @@ Upcoming Release Energiewende (2021) `_. -* Added option to specify turbine and solar panel models for specific years as a - dictionary (e.g. ``renewable: onwind: resource: turbine:``). The years will be - interpreted as years from when the the corresponding turbine model substitutes - the previous model for new installations. This will only have an effect on - workflows with foresight "myopic" and still needs to be added foresight option - "perfect". +* Air-sourced heat pumps can now also be built in rural areas. Previously, only + ground-sourced heat pumps were considered for this category + (https://github.com/PyPSA/pypsa-eur/pull/890). -* Switched the energy totals year from 2011 to 2013 to comply with the assumed default weather year. +* The default configuration ``config/config.default.yaml`` is now automatically + used as a base configuration file. The file ``config/config.yaml`` can now be + used to only define deviations from the default configuration. The + ``config/config.default.yaml`` is still copied into ``config/config.yaml`` on + first usage (https://github.com/PyPSA/pypsa-eur/pull/925). + +* Regions are assigned to all buses with unique coordinates in the network with + a preference given to substations. Previously, only substations had assigned + regions, but this could lead to issues when a high spatial resolution was + applied (https://github.com/PyPSA/pypsa-eur/pull/922). + +* Define global constraint for CO2 emissions on the final state of charge of the + CO2 atmosphere store. This gives a more sparse constraint that should improve + the performance of the solving process + (https://github.com/PyPSA/pypsa-eur/pull/862). + +* Switched the energy totals year from 2011 to 2013 to comply with the assumed + default weather year (https://github.com/PyPSA/pypsa-eur/pull/934). + +* Cluster residential and services heat buses by default. Can be disabled with + ``cluster_heat_buses: false`` (https://github.com/PyPSA/pypsa-eur/pull/877). + +* The rule ``plot_network`` has been split into separate rules for plotting + electricity, hydrogen and gas networks + (https://github.com/PyPSA/pypsa-eur/pull/900). + +* To determine the optimal topology to meet the number of clusters, the workflow + used pyomo in combination with ``ipopt`` or ``gurobi``. This dependency has + been replaced by using ``linopy`` in combination with ``scipopt`` or + ``gurobi``. The environment file has been updated accordingly + (https://github.com/PyPSA/pypsa-eur/pull/903). + +* The ``highs`` solver was added to the default environment file. + +* New default solver settings for COPT solver + (https://github.com/PyPSA/pypsa-eur/pull/882). + +* Data retrieval rules now use their own minimal conda environment. This can + avoid unnecessary reruns of the workflow + (https://github.com/PyPSA/pypsa-eur/pull/888). + +* Merged two OPSD time series data versions into such that the option ``load: + power_statistics:`` becomes superfluous and was hence removed + (https://github.com/PyPSA/pypsa-eur/pull/924). + +* The filtering of power plants in the ``config.default.yaml`` has been updated + regarding phased-out power plants in 2023. + +* Include all countries in ammonia production resource. This is so that the full + EU28 ammonia demand can be correctly subtracted in the rule + :mod:`build_industry_sector_ratios` + (https://github.com/PyPSA/pypsa-eur/pull/931). + +* Correctly source the existing heating technologies for buildings since the + source URL has changed. It represents the year 2012 and is only for buildings, + not district heating (https://github.com/PyPSA/pypsa-eur/pull/918). + +* Add warning when BEV availability weekly profile has negative values in + `build_transport_demand` (https://github.com/PyPSA/pypsa-eur/pull/858). + +* Time series clipping for very small values was added for Links + (https://github.com/PyPSA/pypsa-eur/pull/870). + +* A ``test.sh`` script was added to the repository to run the tests locally. + +* The CI now tests additionally against ``master`` versions of PyPSA, atlite and + powerplantmatching (https://github.com/PyPSA/pypsa-eur/pull/904). + +* A function ``sanitize_locations()`` was added to improve the coverage of the + ``location`` attribute of network components. + +**Bugs and Compatibility** + +* Bugfix: Do not reduce district heat share when building population-weighted + energy statistics. Previously the district heating share was being multiplied + by the population weighting, reducing the DH share with multiple nodes + (https://github.com/PyPSA/pypsa-eur/pull/884). + +* Bugfix: The industry coal emissions for industry were not properly tracked + (https://github.com/PyPSA/pypsa-eur/pull/923). + +* Bugfix: Correct units of subtracted chlorine and methanol demand in + :mod:`build_industry_sector_ratios` + (https://github.com/PyPSA/pypsa-eur/pull/930). + +* Various minor bugfixes to the perfect foresight workflow, though perfect + foresight must still be considered experimental + (https://github.com/PyPSA/pypsa-eur/pull/910). + +* Fix plotting of retrofitted hydrogen pipelines with myopic pathway + optimisation (https://github.com/PyPSA/pypsa-eur/pull/937). + +* Bugfix: Correct technology keys for the electricity production plotting to + work out the box. + +* Bugfix: Assure entering of code block which corrects Norwegian heat demand + (https://github.com/PyPSA/pypsa-eur/pull/870). + +* Stacktrace of uncaught exceptions should now be correctly included inside log + files (via `configure_logging(..)`) + (https://github.com/PyPSA/pypsa-eur/pull/875). + +* Bugfix: Correctly read out number of solver threads from configuration file + (https://github.com/PyPSA/pypsa-eur/pull/889). + +* Made copying default config file compatible with snakemake module + (https://github.com/PyPSA/pypsa-eur/pull/894). + +* Compatibility with ``pandas=2.2`` + (https://github.com/PyPSA/pypsa-eur/pull/861). + +Special thanks for this release to Koen van Greevenbroek (`@koen-vg +`_) for various new features, bugfixes and taking +care of deprecations. PyPSA-Eur 0.9.0 (5th January 2024) From 43159e15e97f963e1555100fc809ed6b57f62987 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 19 Feb 2024 17:15:20 +0100 Subject: [PATCH 353/591] update workflow charts --- CITATION.cff | 2 +- config/config.default.yaml | 2 +- doc/conf.py | 6 +- doc/installation.rst | 28 +- doc/release_notes.rst | 2 + doc/tutorial.rst | 158 +++--- doc/tutorial_sector.rst | 1043 +++++++++++++++++++++++------------- graphics/workflow.png | Bin 651103 -> 680340 bytes 8 files changed, 768 insertions(+), 473 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index f8b28b5f..af26fd53 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -6,7 +6,7 @@ cff-version: 1.1.0 message: "If you use this package, please cite it in the following way." title: "PyPSA-Eur: An open sector-coupled optimisation model of the European energy system" repository: https://github.com/pypsa/pypsa-eur -version: 0.9.0 +version: 0.10.0 license: MIT authors: - family-names: Brown diff --git a/config/config.default.yaml b/config/config.default.yaml index 6eacdcc9..09d2f151 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -3,7 +3,7 @@ # SPDX-License-Identifier: CC0-1.0 # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#top-level-configuration -version: 0.9.0 +version: 0.10.0 tutorial: false logging: diff --git a/doc/conf.py b/doc/conf.py index fe577ac7..afa01d3a 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -72,7 +72,7 @@ master_doc = "index" # General information about the project. project = "PyPSA-Eur" -copyright = "2017-2023 Tom Brown (KIT, TUB, FIAS), Jonas Hoersch (KIT, FIAS), Fabian Hofmann (TUB, FIAS), Fabian Neumann (TUB, KIT), Marta Victoria (Aarhus University), Lisa Zeyen (KIT, TUB)" +copyright = "2017-2024 Tom Brown (KIT, TUB, FIAS), Jonas Hoersch (KIT, FIAS), Fabian Hofmann (TUB, FIAS), Fabian Neumann (TUB, KIT), Marta Victoria (Aarhus University), Lisa Zeyen (KIT, TUB)" author = "Tom Brown (KIT, TUB, FIAS), Jonas Hoersch (KIT, FIAS), Fabian Hofmann (TUB, FIAS), Fabian Neumann (TUB, KIT), Marta Victoria (Aarhus University), Lisa Zeyen (KIT, TUB)" # The version info for the project you're documenting, acts as replacement for @@ -80,9 +80,9 @@ author = "Tom Brown (KIT, TUB, FIAS), Jonas Hoersch (KIT, FIAS), Fabian Hofmann # built documents. # # The short X.Y version. -version = "0.9" +version = "0.10" # The full version, including alpha/beta/rc tags. -release = "0.9.0" +release = "0.10.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/installation.rst b/doc/installation.rst index 4aea5414..b07fd290 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -79,31 +79,9 @@ Nevertheless, you can still use open-source solvers for smaller problems. `Instructions how to install a solver in the documentation of PyPSA `_ .. note:: - The rules :mod:`cluster_network` and :mod:`simplify_network` solve a quadratic optimisation problem for clustering. - The open-source solvers Cbc and GlPK cannot handle this. A fallback to Ipopt is implemented in this case, but requires - it to be installed. For an open-source solver setup install in your ``conda`` environment on OSX/Linux - - .. code:: bash - - mamba activate pypsa-eur - mamba install -c conda-forge ipopt coincbc - - and on Windows - - .. code:: bash - - mamba activate pypsa-eur - mamba install -c conda-forge ipopt glpk - - For HiGHS, run - - .. code:: bash - - mamba activate pypsa-eur - mamba install -c conda-forge ipopt - pip install highspy - - For Gurobi, run + The rules :mod:`cluster_network` and :mod:`simplify_network` solve a mixed-integer quadratic optimisation problem for clustering. + The open-source solvers HiGHS, Cbc and GlPK cannot handle this. A fallback to SCIP is implemented in this case. + For an open-source solver setup install in your ``conda`` environment on OSX/Linux. To install the default solver Gurobi, run .. code:: bash diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 6716ebcf..02c686f6 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -61,6 +61,8 @@ PyPSA-Eur 0.10.0 (19th February 2024) * It is now possible to determine the directory for shared resources by setting `shared_resources` to a string (https://github.com/PyPSA/pypsa-eur/pull/906). +* Improve ``mock_snakemake()`` for usage in Snakemake modules + (https://github.com/PyPSA/pypsa-eur/pull/869). **Breaking Changes** diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 542263e5..4f272292 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -133,82 +133,89 @@ This triggers a workflow of multiple preceding jobs that depend on each rule's i graph[bgcolor=white, margin=0]; node[shape=box, style=rounded, fontname=sans, fontsize=10, penwidth=2]; edge[penwidth=2, color=grey]; - 0[label = "solve_network", color = "0.33 0.6 0.85", style="rounded"]; - 1[label = "prepare_network\nll: copt\nopts: Co2L-24H", color = "0.03 0.6 0.85", style="rounded"]; - 2[label = "add_extra_components", color = "0.45 0.6 0.85", style="rounded"]; - 3[label = "cluster_network\nclusters: 6", color = "0.46 0.6 0.85", style="rounded"]; - 4[label = "simplify_network\nsimpl: ", color = "0.52 0.6 0.85", style="rounded"]; - 5[label = "add_electricity", color = "0.55 0.6 0.85", style="rounded"]; - 6[label = "build_renewable_profiles\ntechnology: solar", color = "0.15 0.6 0.85", style="rounded"]; - 7[label = "base_network", color = "0.37 0.6 0.85", style="rounded,dashed"]; - 8[label = "build_shapes", color = "0.07 0.6 0.85", style="rounded,dashed"]; - 9[label = "retrieve_databundle", color = "0.60 0.6 0.85", style="rounded"]; - 10[label = "retrieve_natura_raster", color = "0.42 0.6 0.85", style="rounded"]; - 11[label = "build_bus_regions", color = "0.09 0.6 0.85", style="rounded,dashed"]; - 12[label = "build_renewable_profiles\ntechnology: onwind", color = "0.15 0.6 0.85", style="rounded"]; - 13[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.15 0.6 0.85", style="rounded"]; - 14[label = "build_ship_raster", color = "0.02 0.6 0.85", style="rounded"]; - 15[label = "retrieve_ship_raster", color = "0.40 0.6 0.85", style="rounded"]; - 16[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.15 0.6 0.85", style="rounded"]; - 17[label = "build_line_rating", color = "0.32 0.6 0.85", style="rounded"]; - 18[label = "retrieve_cost_data\nyear: 2030", color = "0.50 0.6 0.85", style="rounded"]; - 19[label = "build_powerplants", color = "0.64 0.6 0.85", style="rounded,dashed"]; - 20[label = "build_electricity_demand", color = "0.13 0.6 0.85", style="rounded,dashed"]; - 21[label = "retrieve_electricity_demand", color = "0.31 0.6 0.85", style="rounded"]; - 22[label = "copy_config", color = "0.23 0.6 0.85", style="rounded"]; + 0[label = "solve_network", color = "0.39 0.6 0.85", style="rounded"]; + 1[label = "prepare_network\nll: copt\nopts: Co2L-24H", color = "0.29 0.6 0.85", style="rounded"]; + 2[label = "add_extra_components", color = "0.28 0.6 0.85", style="rounded"]; + 3[label = "cluster_network\nclusters: 6", color = "0.19 0.6 0.85", style="rounded"]; + 4[label = "simplify_network\nsimpl: ", color = "0.01 0.6 0.85", style="rounded"]; + 5[label = "add_electricity", color = "0.49 0.6 0.85", style="rounded"]; + 6[label = "build_renewable_profiles\ntechnology: solar", color = "0.21 0.6 0.85", style="rounded"]; + 7[label = "base_network", color = "0.27 0.6 0.85", style="rounded"]; + 8[label = "build_shapes", color = "0.26 0.6 0.85", style="rounded"]; + 9[label = "retrieve_databundle", color = "0.59 0.6 0.85", style="rounded"]; + 10[label = "retrieve_natura_raster", color = "0.47 0.6 0.85", style="rounded"]; + 11[label = "build_bus_regions", color = "0.13 0.6 0.85", style="rounded"]; + 12[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.36 0.6 0.85", style="rounded,dashed"]; + 13[label = "build_renewable_profiles\ntechnology: onwind", color = "0.21 0.6 0.85", style="rounded"]; + 14[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.21 0.6 0.85", style="rounded"]; + 15[label = "build_ship_raster", color = "0.00 0.6 0.85", style="rounded"]; + 16[label = "retrieve_ship_raster", color = "0.51 0.6 0.85", style="rounded,dashed"]; + 17[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.21 0.6 0.85", style="rounded"]; + 18[label = "build_line_rating", color = "0.05 0.6 0.85", style="rounded"]; + 19[label = "retrieve_cost_data\nyear: 2030", color = "0.15 0.6 0.85", style="rounded"]; + 20[label = "build_powerplants", color = "0.54 0.6 0.85", style="rounded"]; + 21[label = "build_electricity_demand", color = "0.52 0.6 0.85", style="rounded"]; + 22[label = "retrieve_electricity_demand", color = "0.22 0.6 0.85", style="rounded"]; + 23[label = "copy_config", color = "0.44 0.6 0.85", style="rounded"]; 1 -> 0 - 22 -> 0 + 23 -> 0 2 -> 1 - 18 -> 1 + 19 -> 1 3 -> 2 - 18 -> 2 + 19 -> 2 4 -> 3 - 18 -> 3 + 19 -> 3 5 -> 4 - 18 -> 4 + 19 -> 4 11 -> 4 6 -> 5 - 12 -> 5 13 -> 5 - 16 -> 5 - 7 -> 5 + 14 -> 5 17 -> 5 + 7 -> 5 18 -> 5 - 11 -> 5 19 -> 5 - 9 -> 5 + 11 -> 5 20 -> 5 + 9 -> 5 + 21 -> 5 8 -> 5 7 -> 6 9 -> 6 10 -> 6 8 -> 6 11 -> 6 + 12 -> 6 8 -> 7 9 -> 8 8 -> 11 7 -> 11 - 7 -> 12 - 9 -> 12 - 10 -> 12 - 8 -> 12 - 11 -> 12 7 -> 13 9 -> 13 10 -> 13 - 14 -> 13 8 -> 13 11 -> 13 + 12 -> 13 + 7 -> 14 + 9 -> 14 + 10 -> 14 15 -> 14 - 7 -> 16 - 9 -> 16 - 10 -> 16 - 14 -> 16 - 8 -> 16 - 11 -> 16 + 8 -> 14 + 11 -> 14 + 12 -> 14 + 16 -> 15 + 12 -> 15 7 -> 17 - 7 -> 19 - 21 -> 20 + 9 -> 17 + 10 -> 17 + 15 -> 17 + 8 -> 17 + 11 -> 17 + 12 -> 17 + 7 -> 18 + 12 -> 18 + 7 -> 20 + 22 -> 21 } | @@ -218,26 +225,29 @@ In the terminal, this will show up as a list of jobs to be run: .. code:: bash Building DAG of jobs... - job count min threads max threads - ------------------------ ------- ------------- ------------- - add_electricity 1 1 1 - add_extra_components 1 1 1 - base_network 1 1 1 - build_bus_regions 1 1 1 - build_hydro_profile 1 1 1 - build_electricity_demand 1 1 1 - build_powerplants 1 1 1 - build_renewable_profiles 4 1 1 - build_shapes 1 1 1 - build_ship_raster 1 1 1 - cluster_network 1 1 1 - prepare_network 1 1 1 - retrieve_cost_data 1 1 1 - retrieve_databundle 1 1 1 - retrieve_natura_raster 1 1 1 - simplify_network 1 1 1 - solve_network 1 1 1 - total 20 1 1 + Job stats: + job count + --------------------------- ------- + add_electricity 1 + add_extra_components 1 + base_network 1 + build_bus_regions 1 + build_electricity_demand 1 + build_line_rating 1 + build_powerplants 1 + build_renewable_profiles 4 + build_shapes 1 + build_ship_raster 1 + cluster_network 1 + copy_config 1 + prepare_network 1 + retrieve_cost_data 1 + retrieve_databundle 1 + retrieve_electricity_demand 1 + retrieve_natura_raster 1 + simplify_network 1 + solve_network 1 + total 22 ``snakemake`` then runs these jobs in the correct order. @@ -246,16 +256,16 @@ A job (here ``simplify_network``) will display its attributes and normally some .. code:: bash - [Mon Jan 1 00:00:00 2023] + [Mon Feb 19 17:06:17 2024] rule simplify_network: - input: networks/elec.nc, resources/costs.csv, resources/regions_onshore.geojson, resources/regions_offshore.geojson - output: networks/elec_s.nc, resources/regions_onshore_elec_s.geojson, resources/regions_offshore_elec_s.geojson, resources/busmap_elec_s.csv, resources/connection_costs_s.csv - log: logs/simplify_network/elec_s.log + input: resources/test/networks/elec.nc, data/costs_2030.csv, resources/test/regions_onshore.geojson, resources/test/regions_offshore.geojson + output: resources/test/networks/elec_s.nc, resources/test/regions_onshore_elec_s.geojson, resources/test/regions_offshore_elec_s.geojson, resources/test/busmap_elec_s.csv, resources/test/connection_costs_s.csv + log: logs/test-elec/simplify_network/elec_s.log jobid: 4 - benchmark: benchmarks/simplify_network/elec_s - reason: Missing output files: resources/busmap_elec_s.csv, resources/regions_onshore_elec_s.geojson, networks/elec_s.nc, resources/regions_offshore_elec_s.geojson; Input files updated by another job: resources/regions_offshore.geojson, resources/regions_onshore.geojson, resources/costs.csv, networks/elec.nc + benchmark: benchmarks/test-elec/simplify_network/elec_s + reason: Missing output files: resources/test/regions_offshore_elec_s.geojson, resources/test/busmap_elec_s.csv, resources/test/regions_onshore_elec_s.geojson, resources/test/networks/elec_s.nc; Input files updated by another job: resources/test/regions_offshore.geojson, resources/test/networks/elec.nc, resources/test/regions_onshore.geojson, data/costs_2030.csv wildcards: simpl= - resources: tmpdir=/tmp, mem_mb=4000, mem_mib=3815 + resources: tmpdir=/tmp, mem_mb=12000, mem_mib=11445 Once the whole worktree is finished, it should state so in the terminal. diff --git a/doc/tutorial_sector.rst b/doc/tutorial_sector.rst index 25690bf7..3598cdfb 100644 --- a/doc/tutorial_sector.rst +++ b/doc/tutorial_sector.rst @@ -61,46 +61,69 @@ To run an overnight / greenfiled scenario with the specifications above, run snakemake -call all --configfile config/test/config.overnight.yaml -which will result in the following *additional* jobs ``snakemake`` wants to run -on top of those already included in the electricity-only tutorial: +which will result in the following jobs ``snakemake`` wants to run, some of +which were already included in the electricity-only tutorial: .. code:: bash - job count min threads max threads - ------------------------------------------------ ------- ------------- ------------- - all 1 1 1 - build_ammonia_production 1 1 1 - build_biomass_potentials 1 1 1 - build_clustered_population_layouts 1 1 1 - build_cop_profiles 1 1 1 - build_gas_input_locations 1 1 1 - build_gas_network 1 1 1 - build_heat_demands 3 1 1 - build_industrial_distribution_key 1 1 1 - build_industrial_energy_demand_per_country_today 1 1 1 - build_industrial_energy_demand_per_node 1 1 1 - build_industrial_energy_demand_per_node_today 1 1 1 - build_industrial_production_per_country 1 1 1 - build_industrial_production_per_country_tomorrow 1 1 1 - build_industrial_production_per_node 1 1 1 - build_industry_sector_ratios 1 1 1 - build_population_weighted_energy_totals 1 1 1 - build_salt_cavern_potentials 1 1 1 - build_shipping_demand 1 1 1 - build_simplified_population_layouts 1 1 1 - build_solar_thermal_profiles 3 1 1 - build_temperature_profiles 3 1 1 - build_transport_demand 1 1 1 - cluster_gas_network 1 1 1 - cluster_network 1 1 1 - copy_config 1 1 1 - make_summary 1 1 1 - plot_network 1 1 1 - plot_summary 1 1 1 - prepare_sector_network 1 1 1 - retrieve_gas_infrastructure_data 1 1 1 - retrieve_sector_databundle 1 1 1 - solve_sector_network 1 1 1 + job count + ------------------------------------------------ ------- + add_electricity 1 + add_extra_components 1 + all 1 + base_network 1 + build_ammonia_production 1 + build_biomass_potentials 1 + build_bus_regions 1 + build_clustered_population_layouts 1 + build_cop_profiles 1 + build_daily_heat_demand 1 + build_district_heat_share 1 + build_electricity_demand 1 + build_energy_totals 1 + build_gas_input_locations 1 + build_gas_network 1 + build_hourly_heat_demand 1 + build_industrial_distribution_key 1 + build_industrial_energy_demand_per_country_today 1 + build_industrial_energy_demand_per_node 1 + build_industrial_energy_demand_per_node_today 1 + build_industrial_production_per_country 1 + build_industrial_production_per_country_tomorrow 1 + build_industrial_production_per_node 1 + build_industry_sector_ratios 1 + build_industry_sector_ratios_intermediate 1 + build_population_layouts 1 + build_population_weighted_energy_totals 1 + build_powerplants 1 + build_renewable_profiles 4 + build_salt_cavern_potentials 1 + build_shapes 1 + build_ship_raster 1 + build_shipping_demand 1 + build_simplified_population_layouts 1 + build_temperature_profiles 3 + build_transport_demand 1 + cluster_gas_network 1 + cluster_network 1 + copy_config 1 + make_summary 1 + plot_gas_network 1 + plot_hydrogen_network 1 + plot_power_network 1 + plot_power_network_clustered 1 + plot_summary 1 + prepare_network 1 + prepare_sector_network 1 + retrieve_cost_data 1 + retrieve_databundle 1 + retrieve_electricity_demand 1 + retrieve_gas_infrastructure_data 1 + retrieve_natura_raster 1 + retrieve_sector_databundle 1 + simplify_network 1 + solve_sector_network 1 + total 60 This covers the retrieval of additional raw data from online resources and preprocessing data about the transport, industry, and heating sectors as well as @@ -119,162 +142,235 @@ successfully. graph[bgcolor=white, margin=0]; node[shape=box, style=rounded, fontname=sans, fontsize=10, penwidth=2]; edge[penwidth=2, color=grey]; - 0[label = "all", color = "0.51 0.6 0.85", style="rounded"]; - 1[label = "plot_summary", color = "0.54 0.6 0.85", style="rounded"]; - 2[label = "make_summary", color = "0.44 0.6 0.85", style="rounded"]; - 3[label = "solve_sector_network", color = "0.46 0.6 0.85", style="rounded"]; - 4[label = "prepare_sector_network", color = "0.09 0.6 0.85", style="rounded"]; - 5[label = "cluster_gas_network", color = "0.38 0.6 0.85", style="rounded"]; - 6[label = "build_gas_network", color = "0.00 0.6 0.85", style="rounded"]; - 7[label = "retrieve_gas_infrastructure_data", color = "0.33 0.6 0.85", style="rounded"]; - 8[label = "cluster_network", color = "0.26 0.6 0.85", style="rounded"]; - 9[label = "simplify_network", color = "0.03 0.6 0.85", style="rounded"]; - 10[label = "add_electricity", color = "0.25 0.6 0.85", style="rounded"]; - 11[label = "build_renewable_profiles", color = "0.07 0.6 0.85", style="rounded"]; - 12[label = "base_network", color = "0.16 0.6 0.85", style="rounded"]; - 13[label = "build_shapes", color = "0.65 0.6 0.85", style="rounded"]; - 14[label = "retrieve_databundle", color = "0.20 0.6 0.85", style="rounded"]; - 15[label = "retrieve_natura_raster", color = "0.10 0.6 0.85", style="rounded"]; - 16[label = "build_bus_regions", color = "0.11 0.6 0.85", style="rounded"]; - 17[label = "build_ship_raster", color = "0.56 0.6 0.85", style="rounded"]; - 18[label = "retrieve_ship_raster", color = "0.15 0.6 0.85", style="rounded"]; - 19[label = "retrieve_cost_data", color = "0.50 0.6 0.85", style="rounded"]; - 20[label = "build_powerplants", color = "0.49 0.6 0.85", style="rounded"]; - 21[label = "build_electricity_demand", color = "0.39 0.6 0.85", style="rounded"]; - 22[label = "retrieve_electricity_demand", color = "0.05 0.6 0.85", style="rounded"]; - 23[label = "build_gas_input_locations", color = "0.45 0.6 0.85", style="rounded"]; - 24[label = "prepare_network", color = "0.31 0.6 0.85", style="rounded"]; - 25[label = "add_extra_components", color = "0.23 0.6 0.85", style="rounded"]; - 26[label = "build_energy_totals", color = "0.19 0.6 0.85", style="rounded"]; - 27[label = "build_population_weighted_energy_totals", color = "0.27 0.6 0.85", style="rounded"]; - 28[label = "build_clustered_population_layouts", color = "0.64 0.6 0.85", style="rounded"]; - 29[label = "build_population_layouts", color = "0.43 0.6 0.85", style="rounded"]; - 30[label = "build_shipping_demand", color = "0.57 0.6 0.85", style="rounded"]; - 31[label = "build_transport_demand", color = "0.53 0.6 0.85", style="rounded"]; - 32[label = "build_temperature_profiles", color = "0.58 0.6 0.85", style="rounded"]; - 33[label = "build_biomass_potentials", color = "0.30 0.6 0.85", style="rounded"]; - 34[label = "build_salt_cavern_potentials", color = "0.47 0.6 0.85", style="rounded"]; - 35[label = "build_simplified_population_layouts", color = "0.32 0.6 0.85", style="rounded"]; - 36[label = "build_industrial_energy_demand_per_node", color = "0.14 0.6 0.85", style="rounded"]; - 37[label = "build_industry_sector_ratios", color = "0.18 0.6 0.85", style="rounded"]; - 38[label = "build_ammonia_production", color = "0.48 0.6 0.85", style="rounded"]; - 39[label = "build_industrial_production_per_node", color = "0.12 0.6 0.85", style="rounded"]; - 40[label = "build_industrial_distribution_key", color = "0.61 0.6 0.85", style="rounded"]; - 41[label = "build_industrial_production_per_country_tomorrow", color = "0.22 0.6 0.85", style="rounded"]; - 42[label = "build_industrial_production_per_country", color = "0.59 0.6 0.85", style="rounded"]; - 43[label = "build_industrial_energy_demand_per_node_today", color = "0.62 0.6 0.85", style="rounded"]; - 44[label = "build_industrial_energy_demand_per_country_today", color = "0.41 0.6 0.85", style="rounded"]; - 45[label = "build_heat_demands", color = "0.08 0.6 0.85", style="rounded"]; - 46[label = "build_cop_profiles", color = "0.52 0.6 0.85", style="rounded"]; - 47[label = "build_solar_thermal_profiles", color = "0.17 0.6 0.85", style="rounded"]; - 48[label = "copy_config", color = "0.40 0.6 0.85", style="rounded"]; - 49[label = "plot_network", color = "0.60 0.6 0.85", style="rounded"]; - 1 -> 0 - 2 -> 1 - 49 -> 2 - 19 -> 2 - 3 -> 2 - 48 -> 3 - 4 -> 3 - 19 -> 3 - 9 -> 4 - 11 -> 4 - 45 -> 4 - 36 -> 4 - 47 -> 4 - 26 -> 4 - 27 -> 4 - 8 -> 4 - 33 -> 4 - 24 -> 4 - 35 -> 4 - 5 -> 4 - 23 -> 4 - 34 -> 4 - 19 -> 4 - 31 -> 4 - 46 -> 4 - 30 -> 4 - 32 -> 4 - 28 -> 4 - 6 -> 5 - 8 -> 5 - 7 -> 6 - 19 -> 8 - 9 -> 8 - 19 -> 9 - 10 -> 9 - 16 -> 9 - 14 -> 10 - 21 -> 10 - 20 -> 10 - 19 -> 10 - 11 -> 10 - 16 -> 10 - 13 -> 10 - 12 -> 10 - 14 -> 11 - 17 -> 11 - 15 -> 11 - 16 -> 11 - 12 -> 11 - 13 -> 11 - 13 -> 12 - 14 -> 13 - 12 -> 16 - 13 -> 16 - 18 -> 17 - 12 -> 20 - 22 -> 21 - 8 -> 23 - 7 -> 23 - 25 -> 24 - 19 -> 24 - 19 -> 25 - 8 -> 25 - 13 -> 26 - 28 -> 27 - 26 -> 27 - 8 -> 28 - 29 -> 28 - 13 -> 29 - 13 -> 30 - 8 -> 30 - 26 -> 30 - 32 -> 31 - 28 -> 31 - 27 -> 31 - 26 -> 31 - 8 -> 32 - 29 -> 32 - 13 -> 33 - 14 -> 33 - 8 -> 33 - 8 -> 34 - 9 -> 35 - 29 -> 35 - 37 -> 36 - 39 -> 36 - 43 -> 36 - 38 -> 37 - 41 -> 39 - 40 -> 39 - 28 -> 40 - 8 -> 40 - 42 -> 41 - 38 -> 42 - 44 -> 43 - 40 -> 43 - 38 -> 44 - 42 -> 44 - 8 -> 45 - 29 -> 45 - 32 -> 46 - 8 -> 47 - 29 -> 47 - 8 -> 49 - 3 -> 49 - } + 0[label = "all", color = "0.55 0.6 0.85", style="rounded"]; + 1[label = "plot_summary", color = "0.31 0.6 0.85", style="rounded"]; + 2[label = "make_summary", color = "0.37 0.6 0.85", style="rounded"]; + 3[label = "plot_power_network_clustered", color = "0.50 0.6 0.85", style="rounded"]; + 4[label = "cluster_network\nclusters: 5", color = "0.62 0.6 0.85", style="rounded"]; + 5[label = "simplify_network\nsimpl: ", color = "0.18 0.6 0.85", style="rounded"]; + 6[label = "add_electricity", color = "0.33 0.6 0.85", style="rounded"]; + 7[label = "build_renewable_profiles\ntechnology: solar", color = "0.20 0.6 0.85", style="rounded"]; + 8[label = "base_network", color = "0.31 0.6 0.85", style="rounded"]; + 9[label = "build_shapes", color = "0.36 0.6 0.85", style="rounded"]; + 10[label = "retrieve_databundle", color = "0.29 0.6 0.85", style="rounded"]; + 11[label = "retrieve_natura_raster", color = "0.01 0.6 0.85", style="rounded"]; + 12[label = "build_bus_regions", color = "0.10 0.6 0.85", style="rounded"]; + 13[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.37 0.6 0.85", style="rounded,dashed"]; + 14[label = "build_renewable_profiles\ntechnology: onwind", color = "0.20 0.6 0.85", style="rounded"]; + 15[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.20 0.6 0.85", style="rounded"]; + 16[label = "build_ship_raster", color = "0.64 0.6 0.85", style="rounded"]; + 17[label = "retrieve_ship_raster", color = "0.64 0.6 0.85", style="rounded,dashed"]; + 18[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.20 0.6 0.85", style="rounded"]; + 19[label = "retrieve_cost_data\nyear: 2030", color = "0.12 0.6 0.85", style="rounded"]; + 20[label = "build_powerplants", color = "0.23 0.6 0.85", style="rounded"]; + 21[label = "build_electricity_demand", color = "0.54 0.6 0.85", style="rounded"]; + 22[label = "retrieve_electricity_demand", color = "0.07 0.6 0.85", style="rounded"]; + 23[label = "solve_sector_network", color = "0.41 0.6 0.85", style="rounded"]; + 24[label = "prepare_sector_network\nsector_opts: CO2L0-24h-T-H-B-I-A-dist1", color = "0.22 0.6 0.85", style="rounded"]; + 25[label = "cluster_gas_network", color = "0.24 0.6 0.85", style="rounded"]; + 26[label = "build_gas_network", color = "0.10 0.6 0.85", style="rounded"]; + 27[label = "retrieve_gas_infrastructure_data", color = "0.17 0.6 0.85", style="rounded"]; + 28[label = "build_gas_input_locations", color = "0.16 0.6 0.85", style="rounded"]; + 29[label = "prepare_network\nll: v1.5\nopts: ", color = "0.49 0.6 0.85", style="rounded"]; + 30[label = "add_extra_components", color = "0.14 0.6 0.85", style="rounded"]; + 31[label = "build_energy_totals", color = "0.39 0.6 0.85", style="rounded"]; + 32[label = "retrieve_sector_databundle", color = "0.58 0.6 0.85", style="rounded"]; + 33[label = "build_population_weighted_energy_totals", color = "0.56 0.6 0.85", style="rounded"]; + 34[label = "build_clustered_population_layouts", color = "0.49 0.6 0.85", style="rounded"]; + 35[label = "build_population_layouts", color = "0.06 0.6 0.85", style="rounded"]; + 36[label = "build_shipping_demand", color = "0.47 0.6 0.85", style="rounded"]; + 37[label = "build_transport_demand", color = "0.45 0.6 0.85", style="rounded"]; + 38[label = "build_temperature_profiles\nscope: total", color = "0.04 0.6 0.85", style="rounded"]; + 39[label = "build_biomass_potentials\nplanning_horizons: 2030", color = "0.11 0.6 0.85", style="rounded"]; + 40[label = "build_salt_cavern_potentials", color = "0.15 0.6 0.85", style="rounded"]; + 41[label = "build_simplified_population_layouts", color = "0.46 0.6 0.85", style="rounded"]; + 42[label = "build_industrial_energy_demand_per_node", color = "0.63 0.6 0.85", style="rounded"]; + 43[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2030", color = "0.07 0.6 0.85", style="rounded"]; + 44[label = "build_industry_sector_ratios", color = "0.59 0.6 0.85", style="rounded"]; + 45[label = "build_ammonia_production", color = "0.04 0.6 0.85", style="rounded"]; + 46[label = "build_industrial_energy_demand_per_country_today", color = "0.44 0.6 0.85", style="rounded"]; + 47[label = "build_industrial_production_per_country", color = "0.34 0.6 0.85", style="rounded"]; + 48[label = "build_industrial_production_per_node", color = "0.26 0.6 0.85", style="rounded"]; + 49[label = "build_industrial_distribution_key", color = "0.13 0.6 0.85", style="rounded"]; + 50[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2030", color = "0.32 0.6 0.85", style="rounded"]; + 51[label = "build_industrial_energy_demand_per_node_today", color = "0.48 0.6 0.85", style="rounded"]; + 52[label = "build_hourly_heat_demand", color = "0.28 0.6 0.85", style="rounded"]; + 53[label = "build_daily_heat_demand\nscope: total", color = "0.28 0.6 0.85", style="rounded"]; + 54[label = "build_district_heat_share\nplanning_horizons: 2030", color = "0.52 0.6 0.85", style="rounded"]; + 55[label = "build_temperature_profiles\nscope: rural", color = "0.04 0.6 0.85", style="rounded"]; + 56[label = "build_temperature_profiles\nscope: urban", color = "0.04 0.6 0.85", style="rounded"]; + 57[label = "build_cop_profiles", color = "0.38 0.6 0.85", style="rounded"]; + 58[label = "copy_config", color = "0.19 0.6 0.85", style="rounded"]; + 59[label = "plot_power_network", color = "0.60 0.6 0.85", style="rounded"]; + 60[label = "plot_hydrogen_network", color = "0.27 0.6 0.85", style="rounded"]; + 61[label = "plot_gas_network", color = "0.08 0.6 0.85", style="rounded"]; + 1 -> 0 + 2 -> 1 + 32 -> 1 + 3 -> 2 + 23 -> 2 + 19 -> 2 + 59 -> 2 + 60 -> 2 + 61 -> 2 + 4 -> 3 + 5 -> 4 + 19 -> 4 + 6 -> 5 + 19 -> 5 + 12 -> 5 + 7 -> 6 + 14 -> 6 + 15 -> 6 + 18 -> 6 + 8 -> 6 + 19 -> 6 + 12 -> 6 + 20 -> 6 + 10 -> 6 + 21 -> 6 + 9 -> 6 + 8 -> 7 + 10 -> 7 + 11 -> 7 + 9 -> 7 + 12 -> 7 + 13 -> 7 + 9 -> 8 + 10 -> 9 + 9 -> 12 + 8 -> 12 + 8 -> 14 + 10 -> 14 + 11 -> 14 + 9 -> 14 + 12 -> 14 + 13 -> 14 + 8 -> 15 + 10 -> 15 + 11 -> 15 + 16 -> 15 + 9 -> 15 + 12 -> 15 + 13 -> 15 + 17 -> 16 + 13 -> 16 + 8 -> 18 + 10 -> 18 + 11 -> 18 + 16 -> 18 + 9 -> 18 + 12 -> 18 + 13 -> 18 + 8 -> 20 + 22 -> 21 + 24 -> 23 + 58 -> 23 + 25 -> 24 + 28 -> 24 + 29 -> 24 + 31 -> 24 + 32 -> 24 + 33 -> 24 + 36 -> 24 + 37 -> 24 + 39 -> 24 + 19 -> 24 + 15 -> 24 + 18 -> 24 + 40 -> 24 + 5 -> 24 + 4 -> 24 + 34 -> 24 + 41 -> 24 + 42 -> 24 + 52 -> 24 + 54 -> 24 + 38 -> 24 + 55 -> 24 + 56 -> 24 + 57 -> 24 + 26 -> 25 + 4 -> 25 + 27 -> 26 + 27 -> 28 + 4 -> 28 + 30 -> 29 + 19 -> 29 + 4 -> 30 + 19 -> 30 + 9 -> 31 + 32 -> 31 + 31 -> 33 + 34 -> 33 + 35 -> 34 + 4 -> 34 + 13 -> 34 + 9 -> 35 + 13 -> 35 + 9 -> 36 + 4 -> 36 + 31 -> 36 + 34 -> 37 + 33 -> 37 + 31 -> 37 + 32 -> 37 + 38 -> 37 + 35 -> 38 + 4 -> 38 + 13 -> 38 + 32 -> 39 + 4 -> 39 + 10 -> 39 + 9 -> 39 + 32 -> 40 + 4 -> 40 + 35 -> 41 + 5 -> 41 + 13 -> 41 + 43 -> 42 + 48 -> 42 + 51 -> 42 + 44 -> 43 + 46 -> 43 + 47 -> 43 + 45 -> 44 + 32 -> 44 + 32 -> 45 + 32 -> 46 + 47 -> 46 + 45 -> 47 + 32 -> 47 + 49 -> 48 + 50 -> 48 + 4 -> 49 + 34 -> 49 + 32 -> 49 + 47 -> 50 + 49 -> 51 + 46 -> 51 + 53 -> 52 + 35 -> 53 + 4 -> 53 + 13 -> 53 + 31 -> 54 + 34 -> 54 + 35 -> 55 + 4 -> 55 + 13 -> 55 + 35 -> 56 + 4 -> 56 + 13 -> 56 + 38 -> 57 + 55 -> 57 + 56 -> 57 + 23 -> 59 + 4 -> 59 + 23 -> 60 + 4 -> 60 + 23 -> 61 + 4 -> 61 + } | @@ -320,23 +416,10 @@ To run a myopic foresight scenario with the specifications above, run snakemake -call all --configfile config/test/config.myopic.yaml -which will result in the following *additional* jobs ``snakemake`` wants to run: - -.. code:: bash - - job count min threads max threads - ------------------------------------------------ ------- ------------- ------------- - all 1 1 1 - add_brownfield 2 1 1 - add_existing_baseyear 1 1 1 - plot_network 3 1 1 - plot_summary 1 1 1 - prepare_sector_network 3 1 1 - solve_sector_network_myopic 3 1 1 - -which translates to the following workflow diagram which nicely outlines -how the sequential pathway optimisation with myopic foresight is -implemented in the workflow: +which will result in additional jobs ``snakemake`` wants to run, which +translates to the following workflow diagram which nicely outlines how the +sequential pathway optimisation with myopic foresight is implemented in the +workflow: .. graphviz:: :class: full-width @@ -346,165 +429,387 @@ implemented in the workflow: graph[bgcolor=white, margin=0]; node[shape=box, style=rounded, fontname=sans, fontsize=10, penwidth=2]; edge[penwidth=2, color=grey]; - 0[label = "all", color = "0.38 0.6 0.85", style="rounded"]; - 1[label = "plot_summary", color = "0.61 0.6 0.85", style="rounded"]; - 2[label = "make_summary", color = "0.51 0.6 0.85", style="rounded"]; - 3[label = "solve_sector_network_myopic", color = "0.32 0.6 0.85", style="rounded"]; - 4[label = "add_existing_baseyear", color = "0.20 0.6 0.85", style="rounded"]; - 5[label = "prepare_sector_network", color = "0.14 0.6 0.85", style="rounded"]; - 6[label = "prepare_network", color = "0.06 0.6 0.85", style="rounded"]; - 7[label = "add_extra_components", color = "0.00 0.6 0.85", style="rounded"]; - 8[label = "cluster_network", color = "0.18 0.6 0.85", style="rounded"]; - 9[label = "simplify_network", color = "0.30 0.6 0.85", style="rounded"]; - 10[label = "add_electricity", color = "0.24 0.6 0.85", style="rounded"]; - 11[label = "build_renewable_profiles", color = "0.40 0.6 0.85", style="rounded"]; - 12[label = "base_network", color = "0.11 0.6 0.85", style="rounded"]; - 13[label = "build_shapes", color = "0.29 0.6 0.85", style="rounded"]; - 14[label = "retrieve_databundle", color = "0.58 0.6 0.85", style="rounded"]; - 15[label = "retrieve_natura_raster", color = "0.39 0.6 0.85", style="rounded"]; - 16[label = "build_bus_regions", color = "0.60 0.6 0.85", style="rounded"]; - 17[label = "build_ship_raster", color = "0.65 0.6 0.85", style="rounded"]; - 18[label = "retrieve_ship_raster", color = "0.09 0.6 0.85", style="rounded"]; - 19[label = "retrieve_cost_data", color = "0.04 0.6 0.85", style="rounded"]; - 20[label = "build_powerplants", color = "0.28 0.6 0.85", style="rounded"]; - 21[label = "build_electricity_demand", color = "0.46 0.6 0.85", style="rounded"]; - 22[label = "retrieve_electricity_demand", color = "0.44 0.6 0.85", style="rounded"]; - 23[label = "build_energy_totals", color = "0.53 0.6 0.85", style="rounded"]; - 24[label = "build_population_weighted_energy_totals", color = "0.03 0.6 0.85", style="rounded"]; - 25[label = "build_clustered_population_layouts", color = "0.34 0.6 0.85", style="rounded"]; - 26[label = "build_population_layouts", color = "0.63 0.6 0.85", style="rounded"]; - 27[label = "build_shipping_demand", color = "0.05 0.6 0.85", style="rounded"]; - 28[label = "build_transport_demand", color = "0.52 0.6 0.85", style="rounded"]; - 29[label = "build_temperature_profiles", color = "0.16 0.6 0.85", style="rounded"]; - 30[label = "build_biomass_potentials", color = "0.47 0.6 0.85", style="rounded"]; - 31[label = "build_salt_cavern_potentials", color = "0.48 0.6 0.85", style="rounded"]; - 32[label = "build_simplified_population_layouts", color = "0.08 0.6 0.85", style="rounded"]; - 33[label = "build_industrial_energy_demand_per_node", color = "0.22 0.6 0.85", style="rounded"]; - 34[label = "build_industry_sector_ratios", color = "0.56 0.6 0.85", style="rounded"]; - 35[label = "build_ammonia_production", color = "0.57 0.6 0.85", style="rounded"]; - 36[label = "build_industrial_production_per_node", color = "0.66 0.6 0.85", style="rounded"]; - 37[label = "build_industrial_distribution_key", color = "0.41 0.6 0.85", style="rounded"]; - 38[label = "build_industrial_production_per_country_tomorrow", color = "0.54 0.6 0.85", style="rounded"]; - 39[label = "build_industrial_production_per_country", color = "0.10 0.6 0.85", style="rounded"]; - 40[label = "build_industrial_energy_demand_per_node_today", color = "0.55 0.6 0.85", style="rounded"]; - 41[label = "build_industrial_energy_demand_per_country_today", color = "0.35 0.6 0.85", style="rounded"]; - 42[label = "build_heat_demands", color = "0.49 0.6 0.85", style="rounded"]; - 43[label = "build_cop_profiles", color = "0.01 0.6 0.85", style="rounded"]; - 44[label = "build_solar_thermal_profiles", color = "0.45 0.6 0.85", style="rounded"]; - 45[label = "copy_config", color = "0.33 0.6 0.85", style="rounded"]; - 46[label = "add_brownfield", color = "0.59 0.6 0.85", style="rounded"]; - 47[label = "plot_network", color = "0.15 0.6 0.85", style="rounded"]; - 1 -> 0 - 2 -> 1 - 3 -> 2 - 19 -> 2 - 47 -> 2 - 46 -> 3 - 19 -> 3 - 4 -> 3 - 45 -> 3 - 43 -> 4 - 19 -> 4 - 20 -> 4 - 9 -> 4 - 5 -> 4 - 25 -> 4 - 8 -> 4 - 28 -> 5 - 23 -> 5 - 11 -> 5 - 33 -> 5 - 24 -> 5 - 43 -> 5 - 19 -> 5 - 27 -> 5 - 6 -> 5 - 31 -> 5 - 32 -> 5 - 44 -> 5 - 9 -> 5 - 30 -> 5 - 25 -> 5 - 29 -> 5 - 42 -> 5 - 8 -> 5 - 7 -> 6 - 19 -> 6 - 19 -> 7 - 8 -> 7 - 9 -> 8 - 19 -> 8 - 10 -> 9 - 19 -> 9 - 16 -> 9 - 11 -> 10 - 19 -> 10 - 14 -> 10 - 20 -> 10 - 12 -> 10 - 21 -> 10 - 16 -> 10 - 13 -> 10 - 15 -> 11 - 14 -> 11 - 13 -> 11 - 12 -> 11 - 16 -> 11 - 17 -> 11 - 13 -> 12 - 14 -> 13 - 13 -> 16 - 12 -> 16 - 18 -> 17 - 12 -> 20 - 22 -> 21 - 13 -> 23 - 25 -> 24 - 23 -> 24 - 8 -> 25 - 26 -> 25 - 13 -> 26 - 13 -> 27 - 23 -> 27 - 8 -> 27 - 24 -> 28 - 25 -> 28 - 29 -> 28 - 23 -> 28 - 8 -> 29 - 26 -> 29 - 13 -> 30 - 14 -> 30 - 8 -> 30 - 8 -> 31 - 9 -> 32 - 26 -> 32 - 34 -> 33 - 36 -> 33 - 40 -> 33 - 35 -> 34 - 37 -> 36 - 38 -> 36 - 25 -> 37 - 8 -> 37 - 39 -> 38 - 35 -> 39 - 41 -> 40 - 37 -> 40 - 39 -> 41 - 35 -> 41 - 8 -> 42 - 26 -> 42 - 29 -> 43 - 8 -> 44 - 26 -> 44 - 3 -> 46 - 19 -> 46 - 5 -> 46 - 43 -> 46 - 3 -> 47 - 8 -> 47 - } + 0[label = "all", color = "0.46 0.6 0.85", style="rounded"]; + 1[label = "plot_summary", color = "0.40 0.6 0.85", style="rounded"]; + 2[label = "make_summary", color = "0.59 0.6 0.85", style="rounded"]; + 3[label = "plot_power_network_clustered", color = "0.17 0.6 0.85", style="rounded"]; + 4[label = "cluster_network\nclusters: 5", color = "0.49 0.6 0.85", style="rounded"]; + 5[label = "simplify_network\nsimpl: ", color = "0.16 0.6 0.85", style="rounded"]; + 6[label = "add_electricity", color = "0.32 0.6 0.85", style="rounded"]; + 7[label = "build_renewable_profiles\ntechnology: solar", color = "0.63 0.6 0.85", style="rounded"]; + 8[label = "base_network", color = "0.12 0.6 0.85", style="rounded"]; + 9[label = "build_shapes", color = "0.23 0.6 0.85", style="rounded"]; + 10[label = "retrieve_databundle", color = "0.61 0.6 0.85", style="rounded"]; + 11[label = "retrieve_natura_raster", color = "0.50 0.6 0.85", style="rounded"]; + 12[label = "build_bus_regions", color = "0.51 0.6 0.85", style="rounded"]; + 13[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.37 0.6 0.85", style="rounded,dashed"]; + 14[label = "build_renewable_profiles\ntechnology: onwind", color = "0.63 0.6 0.85", style="rounded"]; + 15[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.63 0.6 0.85", style="rounded"]; + 16[label = "build_ship_raster", color = "0.24 0.6 0.85", style="rounded"]; + 17[label = "retrieve_ship_raster", color = "0.14 0.6 0.85", style="rounded,dashed"]; + 18[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.63 0.6 0.85", style="rounded"]; + 19[label = "retrieve_cost_data\nyear: 2030", color = "0.04 0.6 0.85", style="rounded"]; + 20[label = "build_powerplants", color = "0.58 0.6 0.85", style="rounded"]; + 21[label = "build_electricity_demand", color = "0.04 0.6 0.85", style="rounded"]; + 22[label = "retrieve_electricity_demand", color = "0.62 0.6 0.85", style="rounded"]; + 23[label = "solve_sector_network_myopic", color = "0.30 0.6 0.85", style="rounded"]; + 24[label = "add_existing_baseyear", color = "0.34 0.6 0.85", style="rounded"]; + 25[label = "prepare_sector_network\nsector_opts: 24h-T-H-B-I-A-dist1", color = "0.42 0.6 0.85", style="rounded"]; + 26[label = "cluster_gas_network", color = "0.39 0.6 0.85", style="rounded"]; + 27[label = "build_gas_network", color = "0.59 0.6 0.85", style="rounded"]; + 28[label = "retrieve_gas_infrastructure_data", color = "0.15 0.6 0.85", style="rounded"]; + 29[label = "build_gas_input_locations", color = "0.07 0.6 0.85", style="rounded"]; + 30[label = "prepare_network\nll: v1.5\nopts: ", color = "0.56 0.6 0.85", style="rounded"]; + 31[label = "add_extra_components", color = "0.11 0.6 0.85", style="rounded"]; + 32[label = "build_energy_totals", color = "0.18 0.6 0.85", style="rounded"]; + 33[label = "retrieve_sector_databundle", color = "0.06 0.6 0.85", style="rounded"]; + 34[label = "build_population_weighted_energy_totals", color = "0.03 0.6 0.85", style="rounded"]; + 35[label = "build_clustered_population_layouts", color = "0.25 0.6 0.85", style="rounded"]; + 36[label = "build_population_layouts", color = "0.57 0.6 0.85", style="rounded"]; + 37[label = "build_shipping_demand", color = "0.45 0.6 0.85", style="rounded"]; + 38[label = "build_transport_demand", color = "0.18 0.6 0.85", style="rounded"]; + 39[label = "build_temperature_profiles\nscope: total", color = "0.54 0.6 0.85", style="rounded"]; + 40[label = "build_biomass_potentials\nplanning_horizons: 2030", color = "0.41 0.6 0.85", style="rounded"]; + 41[label = "build_salt_cavern_potentials", color = "0.02 0.6 0.85", style="rounded"]; + 42[label = "build_simplified_population_layouts", color = "0.15 0.6 0.85", style="rounded"]; + 43[label = "build_industrial_energy_demand_per_node", color = "0.47 0.6 0.85", style="rounded"]; + 44[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2030", color = "0.31 0.6 0.85", style="rounded"]; + 45[label = "build_industry_sector_ratios", color = "0.48 0.6 0.85", style="rounded"]; + 46[label = "build_ammonia_production", color = "0.00 0.6 0.85", style="rounded"]; + 47[label = "build_industrial_energy_demand_per_country_today", color = "0.32 0.6 0.85", style="rounded"]; + 48[label = "build_industrial_production_per_country", color = "0.60 0.6 0.85", style="rounded"]; + 49[label = "build_industrial_production_per_node", color = "0.05 0.6 0.85", style="rounded"]; + 50[label = "build_industrial_distribution_key", color = "0.21 0.6 0.85", style="rounded"]; + 51[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2030", color = "0.33 0.6 0.85", style="rounded"]; + 52[label = "build_industrial_energy_demand_per_node_today", color = "0.62 0.6 0.85", style="rounded"]; + 53[label = "build_hourly_heat_demand", color = "0.28 0.6 0.85", style="rounded"]; + 54[label = "build_daily_heat_demand\nscope: total", color = "0.22 0.6 0.85", style="rounded"]; + 55[label = "build_district_heat_share\nplanning_horizons: 2030", color = "0.21 0.6 0.85", style="rounded"]; + 56[label = "build_temperature_profiles\nscope: rural", color = "0.54 0.6 0.85", style="rounded"]; + 57[label = "build_temperature_profiles\nscope: urban", color = "0.54 0.6 0.85", style="rounded"]; + 58[label = "build_cop_profiles", color = "0.52 0.6 0.85", style="rounded"]; + 59[label = "build_existing_heating_distribution", color = "0.09 0.6 0.85", style="rounded"]; + 60[label = "copy_config", color = "0.42 0.6 0.85", style="rounded"]; + 61[label = "solve_sector_network_myopic", color = "0.30 0.6 0.85", style="rounded"]; + 62[label = "add_brownfield", color = "0.10 0.6 0.85", style="rounded"]; + 63[label = "prepare_sector_network\nsector_opts: 24h-T-H-B-I-A-dist1", color = "0.42 0.6 0.85", style="rounded"]; + 64[label = "build_biomass_potentials\nplanning_horizons: 2040", color = "0.41 0.6 0.85", style="rounded"]; + 65[label = "retrieve_cost_data\nyear: 2040", color = "0.04 0.6 0.85", style="rounded"]; + 66[label = "build_industrial_energy_demand_per_node", color = "0.47 0.6 0.85", style="rounded"]; + 67[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2040", color = "0.31 0.6 0.85", style="rounded"]; + 68[label = "build_industrial_production_per_node", color = "0.05 0.6 0.85", style="rounded"]; + 69[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2040", color = "0.33 0.6 0.85", style="rounded"]; + 70[label = "build_district_heat_share\nplanning_horizons: 2040", color = "0.21 0.6 0.85", style="rounded"]; + 71[label = "solve_sector_network_myopic", color = "0.30 0.6 0.85", style="rounded"]; + 72[label = "add_brownfield", color = "0.10 0.6 0.85", style="rounded"]; + 73[label = "prepare_sector_network\nsector_opts: 24h-T-H-B-I-A-dist1", color = "0.42 0.6 0.85", style="rounded"]; + 74[label = "build_biomass_potentials\nplanning_horizons: 2050", color = "0.41 0.6 0.85", style="rounded"]; + 75[label = "retrieve_cost_data\nyear: 2050", color = "0.04 0.6 0.85", style="rounded"]; + 76[label = "build_industrial_energy_demand_per_node", color = "0.47 0.6 0.85", style="rounded"]; + 77[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2050", color = "0.31 0.6 0.85", style="rounded"]; + 78[label = "build_industrial_production_per_node", color = "0.05 0.6 0.85", style="rounded"]; + 79[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2050", color = "0.33 0.6 0.85", style="rounded"]; + 80[label = "build_district_heat_share\nplanning_horizons: 2050", color = "0.21 0.6 0.85", style="rounded"]; + 81[label = "plot_power_network", color = "0.48 0.6 0.85", style="rounded"]; + 82[label = "plot_power_network", color = "0.48 0.6 0.85", style="rounded"]; + 83[label = "plot_power_network", color = "0.48 0.6 0.85", style="rounded"]; + 84[label = "plot_hydrogen_network", color = "0.37 0.6 0.85", style="rounded"]; + 85[label = "plot_hydrogen_network", color = "0.37 0.6 0.85", style="rounded"]; + 86[label = "plot_hydrogen_network", color = "0.37 0.6 0.85", style="rounded"]; + 1 -> 0 + 2 -> 1 + 33 -> 1 + 3 -> 2 + 23 -> 2 + 61 -> 2 + 71 -> 2 + 19 -> 2 + 81 -> 2 + 82 -> 2 + 83 -> 2 + 84 -> 2 + 85 -> 2 + 86 -> 2 + 4 -> 3 + 5 -> 4 + 19 -> 4 + 6 -> 5 + 19 -> 5 + 12 -> 5 + 7 -> 6 + 14 -> 6 + 15 -> 6 + 18 -> 6 + 8 -> 6 + 19 -> 6 + 12 -> 6 + 20 -> 6 + 10 -> 6 + 21 -> 6 + 9 -> 6 + 8 -> 7 + 10 -> 7 + 11 -> 7 + 9 -> 7 + 12 -> 7 + 13 -> 7 + 9 -> 8 + 10 -> 9 + 9 -> 12 + 8 -> 12 + 8 -> 14 + 10 -> 14 + 11 -> 14 + 9 -> 14 + 12 -> 14 + 13 -> 14 + 8 -> 15 + 10 -> 15 + 11 -> 15 + 16 -> 15 + 9 -> 15 + 12 -> 15 + 13 -> 15 + 17 -> 16 + 13 -> 16 + 8 -> 18 + 10 -> 18 + 11 -> 18 + 16 -> 18 + 9 -> 18 + 12 -> 18 + 13 -> 18 + 8 -> 20 + 22 -> 21 + 24 -> 23 + 19 -> 23 + 60 -> 23 + 25 -> 24 + 20 -> 24 + 5 -> 24 + 4 -> 24 + 35 -> 24 + 19 -> 24 + 58 -> 24 + 59 -> 24 + 26 -> 25 + 29 -> 25 + 30 -> 25 + 32 -> 25 + 33 -> 25 + 34 -> 25 + 37 -> 25 + 38 -> 25 + 40 -> 25 + 19 -> 25 + 15 -> 25 + 18 -> 25 + 41 -> 25 + 5 -> 25 + 4 -> 25 + 35 -> 25 + 42 -> 25 + 43 -> 25 + 53 -> 25 + 55 -> 25 + 39 -> 25 + 56 -> 25 + 57 -> 25 + 58 -> 25 + 27 -> 26 + 4 -> 26 + 28 -> 27 + 28 -> 29 + 4 -> 29 + 31 -> 30 + 19 -> 30 + 4 -> 31 + 19 -> 31 + 9 -> 32 + 33 -> 32 + 32 -> 34 + 35 -> 34 + 36 -> 35 + 4 -> 35 + 13 -> 35 + 9 -> 36 + 13 -> 36 + 9 -> 37 + 4 -> 37 + 32 -> 37 + 35 -> 38 + 34 -> 38 + 32 -> 38 + 33 -> 38 + 39 -> 38 + 36 -> 39 + 4 -> 39 + 13 -> 39 + 33 -> 40 + 4 -> 40 + 10 -> 40 + 9 -> 40 + 33 -> 41 + 4 -> 41 + 36 -> 42 + 5 -> 42 + 13 -> 42 + 44 -> 43 + 49 -> 43 + 52 -> 43 + 45 -> 44 + 47 -> 44 + 48 -> 44 + 46 -> 45 + 33 -> 45 + 33 -> 46 + 33 -> 47 + 48 -> 47 + 46 -> 48 + 33 -> 48 + 50 -> 49 + 51 -> 49 + 4 -> 50 + 35 -> 50 + 33 -> 50 + 48 -> 51 + 50 -> 52 + 47 -> 52 + 54 -> 53 + 36 -> 54 + 4 -> 54 + 13 -> 54 + 32 -> 55 + 35 -> 55 + 36 -> 56 + 4 -> 56 + 13 -> 56 + 36 -> 57 + 4 -> 57 + 13 -> 57 + 39 -> 58 + 56 -> 58 + 57 -> 58 + 35 -> 59 + 34 -> 59 + 55 -> 59 + 62 -> 61 + 65 -> 61 + 60 -> 61 + 7 -> 62 + 14 -> 62 + 15 -> 62 + 18 -> 62 + 5 -> 62 + 4 -> 62 + 63 -> 62 + 23 -> 62 + 65 -> 62 + 58 -> 62 + 26 -> 63 + 29 -> 63 + 30 -> 63 + 32 -> 63 + 33 -> 63 + 34 -> 63 + 37 -> 63 + 38 -> 63 + 64 -> 63 + 65 -> 63 + 15 -> 63 + 18 -> 63 + 41 -> 63 + 5 -> 63 + 4 -> 63 + 35 -> 63 + 42 -> 63 + 66 -> 63 + 53 -> 63 + 70 -> 63 + 39 -> 63 + 56 -> 63 + 57 -> 63 + 58 -> 63 + 33 -> 64 + 4 -> 64 + 10 -> 64 + 9 -> 64 + 67 -> 66 + 68 -> 66 + 52 -> 66 + 45 -> 67 + 47 -> 67 + 48 -> 67 + 50 -> 68 + 69 -> 68 + 48 -> 69 + 32 -> 70 + 35 -> 70 + 72 -> 71 + 75 -> 71 + 60 -> 71 + 7 -> 72 + 14 -> 72 + 15 -> 72 + 18 -> 72 + 5 -> 72 + 4 -> 72 + 73 -> 72 + 61 -> 72 + 75 -> 72 + 58 -> 72 + 26 -> 73 + 29 -> 73 + 30 -> 73 + 32 -> 73 + 33 -> 73 + 34 -> 73 + 37 -> 73 + 38 -> 73 + 74 -> 73 + 75 -> 73 + 15 -> 73 + 18 -> 73 + 41 -> 73 + 5 -> 73 + 4 -> 73 + 35 -> 73 + 42 -> 73 + 76 -> 73 + 53 -> 73 + 80 -> 73 + 39 -> 73 + 56 -> 73 + 57 -> 73 + 58 -> 73 + 33 -> 74 + 4 -> 74 + 10 -> 74 + 9 -> 74 + 77 -> 76 + 78 -> 76 + 52 -> 76 + 45 -> 77 + 47 -> 77 + 48 -> 77 + 50 -> 78 + 79 -> 78 + 48 -> 79 + 32 -> 80 + 35 -> 80 + 23 -> 81 + 4 -> 81 + 61 -> 82 + 4 -> 82 + 71 -> 83 + 4 -> 83 + 23 -> 84 + 4 -> 84 + 61 -> 85 + 4 -> 85 + 71 -> 86 + 4 -> 86 + } | diff --git a/graphics/workflow.png b/graphics/workflow.png index a43f240ddd2433dbe5b735f97a59e63b667c66c7..a7fbc5add57498182dab3094d70fb0edd1b3fb75 100644 GIT binary patch literal 680340 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 z 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
=m&%-X( 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

~eS~@=~cU9TDl;Qm-j}{abrC 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

T*!(Uf9VZ<@xBqKx?v@1v)?oi7u&?c1*k}y4VAs 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%0DQ6MgBl4)-R6pyB63%@DZ>;CY8uuQ;IxAX;r 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

4;?8|R644r_RUGzE8ywfgpNuIuPvbc+N{X#;8 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 literal 651103 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%0A>oPOA;^#&ExE1b4C?#5gurd^EK ztWyqSx&v)INv^5{)ve~9M3t~(7Yf&Oev2I#`;+m>XdnpH#5P?0yWG}rgi@qvNmzHF zZ@B)WM-9wdt;~iyakY-+ofF72>CR}k>rsjM_VsHz6daGT>HlXt&0}9GVApH(9*gwI zcs1``zckwW@m})Fp*x$mp^wzmGxdnFmQS(I16K>kxCI2{%%q){o&wv*geL_G@2EH(@z~d#`?lF&1 zDUI>S|AL-4zz%HZJa`C`HMmg2NzXByjnzoIU}lOi7-*fZVcDDARdI3>5wU0`CUa=# z1x|oA!@v(A3OoFBQ%#yGf>m1+*Us%$J0rl2aFEc#afN{77$SceQzp&Lm607p8y+4W z_M>*B_QynRgv3*z7NR}wG{X_jY~3ycyCtVeH`^|3+wOCt9Q8p*PkDKHYo0w9SWJ|~ zWpcO9?Z~PXbrrB<|MdRx<&LG*VVR&XL(hF^@5%%{r+2OXiI=Ge^86F)+VRNIFts@` zarUIgURUTH#U&&d+&%bc_CxOX6#CFPy}<lafpg8JeuSg`%^a;={E6E&}-?Op3O&cOemIOXam1I!}#b3xDlxTVgi#4 zm#Vd6iibyLBC6}^s!B^qP`=?mgRSMIuDB0z8ob0X4aBIj)b)^Dzc^3d=qwci>k5R`S`r|#vq>n$3{A>wRnDbz$ z(2o60OzSzdnVvJ_>H=zr(lXOt!_jdrQAhP~M5XZb{0*LgN9m1KdjlTJ9OmL0UM&)E z_zJaI_-yg)%uLLBV6Cv0ZtaTFhqg8yQZ$LnhdVZ7tCqm$#C zN^uav>({r%(2G@D-;s`zO_FE{`W}@C^&I1ynUri^qjmLqG`#fA-gdG30tdC<$g*ej z3RS?|2~7y<+7`cB<-}J^%SWqXB4pFndw2AG6%Rf;xndoM`EgmP7EIw16L}XT4OBK&Ln4oXGzu!Jv*b3g5Xi6{s3cFaPG;ycBfEC! z&>;)Wr6J7G64S%*KhM*%*xO}PMt9%4-ekfd=KIYj=rf6K@<{u{{}z2{eSjX1O^S4{ z^J(Pue?QB98aR_Q+U_YyOa%DLtc|Gb$}XRk#Jm*#nA>M4JDuyQwCl)27dO?cYuz{L zwIN|uIDN*VGk1@+p~u`Sr)P6*Z{L63S$OK^eoL23-nvCQkd6AV75|va1Xy}ZM`l1ga2tf88w-pM~_}(IQnPLHo1^96M4gI#A?wt za6Lo$%Aqcb?#TWV-Ss@q)FbZ zo&OAz0=I76ffZ)sh>2`Zz~eSiFp-=9k@z-<5P+4lKHML%g=zu7-cHIj7hM z6l;i(CkE_LuIk74o#JgUV#QV?}!+8{gihj4PAR;GlQkkd`#%F#D zG(lI7ewNOGI$G=F}&mByzy=`04I)e~P&Hml%w`aA9|Tem;qWE*L)3JOz}%`Z1f23H^`Q z=%7N|1qI~)lY!E4UF{bnx|zLIkRpR&8ganbMt5RLioUv-Y1YpFui~`r|Fnbt_46+# z5Vq1}TXp4M=TfLL!xG2v?W5bNA3g}DiX1pX%NNHKr?CGT-R?4)yv7RDcz1!r6#|u1 zt6N#~B*AUVNAciGA)b@nPQ>k0xH?ngLi7%^-$bic-D&_rLmc{1+7~t7!?h0g$&7dJ zwnKb#RP89^C!8o@MUNHcnlMUUMRcLWtp?1ZZiVexmSAIBhjqzr7%h{~Vi2t|QPh&6 z>p+QSwiM$N*dMO1y8$H11q-dU&X5jg1afN4OVolA6Qn#XcSnAIi{ z+RP-g_q0F@z{f(4M3TEUfs?}HdoeGq|4FYEd`6x~m;Q(EdOdUZI*9uxzY>y`jx38z zrUWsEAr_Kc&tpJ_A0({5okg7y7w5wt2}Th@*T$IT+1qO0QUu?1M_4 zR{iiH_7_H?)YA6NlH+A^kdzc;HS{N3=N!-&9Ya&;xlqs(4N?(PH8tJW2_ar}^;DJ2 z`ctWeKaDEz%8ZGQzV^MiaIrsNY?>>|{VrNaLIuRr;jdw67zCS;)%l!~$G4>;f`-pE z_4L$Lj)JC1O7++HyKq;DsZ_uM#)^}aoc$^^HjHYM&!xMh-~UL=T~$0H0%WvBmm%05 z`GMpG6zfeH_ z{Xds5XTsSU0~&Y*90Mwbm;LY+F~fNC=4FS5rYlge9u*T~quT%2D{HDbd(z4Z#<}f z>*w0cw9bX^MeMiUbo}w~lF@clKxZgxZax|qRv@h~GVPMx^zBSi69lhH(LHuhN_(q# zEjQ+3a&;;@rwDRMdg95f0~%wob{}AlR^_(AK9rnqHFhay?)K)2bTK-&sq0&)+h|IT z94tkBWmY+*(NbA0c}mRH%Tx8;*~aFL*;9lFa?=uJ8%b~W7#k*nsU)XJ6D1p-L{TH= zwJr&h_rMmlcULy1s5Ynti~j6|>=yP0(@`5sQ3M{7w!-K?trz+ptDzVBqXMnEKLMTr z5p$Vz>)Aze*;wfbB5+J9=|v90O%+`PkC^=dVEeQNpu`4>S0?Tut!;5}@hxi*%=yr< z+oD%^{r2rvqGgbtxX$#EgrW{6|a60AS38>`-F1jo77BQh%r? zatA02r^U1vHD;-c1Dsd zOzy?d+x&bcY*1L>!|ods=lz~`G|*uogogNUj=%Wivx~uI@blBm$=`_Pv0a?HmTmlLpfRt=T3ae#NxJVJtZTe}D z`xY65^1{_##KE_FH!vLnnON*+DDk6m@7-K*C7xsZVx?&D9bdNF+X*;7T0LPZIBIoE z&+1RnoF5sIdmr`&N=y(&GbkR}`^wqZ(`h-l|KvAc;-+2fC|T1bQ2xasL9d5k4vAO1K~;UbRXgoYl+yr%=>K%bczU#3cx6 zkeK~X3Y5TUdC4+M!7?9NojdOkeLpUg#Ss-Re<}b2KstWCb<~@je*Ua(IM_-^!PVGp zNY7bfp<~RMidFnRRwS8okB4aYa&yjprpGZwMXZL4WeiS#^z^J<*;iVt-t^>k=l!0V zI*R#=_4UaOHsaS5)o;O9x=|za5x6%&72wnY4L`BGR213us>fO@Nw4~(!VWzTHpqYO z!dz1)aEPCN7lyA0V^7>F4kutBqL$aw1a__q~saH-QN&*uAvth7=8rE9oOFBx{gXLfI+Zq#6ekT1R7>A zuvcwts9{_(DNE|Jagkq0z(YqnfN%kH9O!Gt7hTnPLog!*IV=94a_^q;9>cdmI6VB> zfQso;4H_tk+w%U|PwMqsq8B#H={B831>ZL1`GxB3#lyiceffJgi5B+lR)38B^qN*7 zALubI4j2ffU7_^e-Ba@2j$HN>h$?^z{-Q-A7nnmcbfjABQwWo50#qjOSVVOYp{LUW zRnt{ot5skv00}-YNGthi?A}t)eTY1m-F0x!>cr%_08EO1aQ@C3?XY0gO<6fpLol~$ znwn4sKE$)=8#Ua>r==)vHf|luE9~yE725c{B(30gvtD@MuO-Kh{7J1x_YEt}>^706 zn6oDDd#4oL0AHY1IC8;S4k0NW-SZ;u(*cI}&%|ze!u({Z*14D_hMQO%b&|6b&`%O4 zAFvn_sP`z^Vk|CoZrz*l<59y&uKj65-B^XI5*Sme4iM6EFb(jK-2ty;avlRBB-_1=_)mSeazM3XxQW4PZQ-`VU*W5 z(DCTV$fu)-?(*7h+~=+nfC*-nLmv0TUOMJe(id!gkKWX%*=SQ{ZKpVUdP^vDgq+e4n7f zp*4KcO$7i;Q?oC}Yb7TdUbT%Q#6e9#a1z$Jo*d4}&24RYu~nN%wI;NJ59}fqt&X)s zpDuVm@D%fJ2ZNP>NPr=DzE(k~vGad`S^Cp~XM@3e;h)oAT zUkna@D7&X37Yet*9zw!XAT_6OuEajYbaS3knde-RA+dRuLj#+-*XMHx1PHFUL6S4u zr58U^!Gf+I9wHr{ku#7mh&UY4;-<|Vj&!rZHO3s-)AMV&T+6KM>w;9t{q3)HF8Q{+ z5T&ZN_Tku0+*F5y@2DqqHh;Prm$@!^5P2d@kCm(bin|WR$Eg5fbEGa{8Vv~vCJCnT zfC)*1fgYA3;a{7mOY0i{Y0)>oS9b8jTL&M+epLi8Y#O|NCv^0l6>ssmFag44lSJ@U z)AEMA4{^rw@$+x`Os)w-n*FI+}s_hq1rp}>8Eh-O(jk`J398ISbHQ<&{d4 z@b!|Rv_8FGz7fE#fkjR0neOtOte#(cGD0tT<^H%ECtRi6$IT53ey^aKE18ujc^_xG zIxDjwBt8951*5c?^+QS`N$-JV6K5f@NElKc7~OVSG8gkOHC#LYVk`*(K^LQ>`6G7W zP)8eK6TKR-*gj)gNL}sIx)HrV$z6TWV);s(bSihnvYEO0bS(SY-%=Ra&>USs->$`( zhC`&%;N5Gv-wM~NAa0)S56DyEvJmMA6@Q`?6ILEJJrp;&i4`dmfB~hIl?z zGuV+hufyU(k>ZQ5$kU#N0Vs=%r+W>}#pn0Xy0MX9?TbU7!~VpUsafHFgonixnONs+ z?B5@gN!XT>bHmCVs7&q+`TN*6keVSm?nyo`8QfG@fty*kwpq#eR~U&oPrMSo3G;O} zoHrzIK(<(@vb3k+KRU^)prfq~3HC%p$2R-9R5I)eao)Pjy}TBs>1xE$Af zA)J|=9rVr*%^t5RiSCT}7X4fBj!8^P>O=I`>=JcAMJ`nr845UHGp|nCZ$;)0jEi9e zNq0;(P%EhdR}bwQT%@_~OUJiSPVQ;5n18v_?CFZ#AZVsX+S!3myNwypzZ@ zL2an{^^N4K+0cLP{&%^IF$ed@#DGHy7GL6_-HBB^-X{AQMh4ij4auXYtV$grn8F}{ zNpiB}p}jj^$#}8BiuqLPk+Zn2|JVaSgCG^-;;4gQbIeL54hvE|7R*oJdP87=E>r!D zjLWZ8xshE(7-XIhK1SOSM)0(ZE5-zgvqR#!gVQRr%42XddBjvsJ(Th0G z`xv?%;FV|2oZ;}_kC;}JLDz(th6F4xVMC#fFKc^$1A&wo$nu8W>4o%DA?H%GCS6LF z2{uBoc#-&jrc^fmsQB=Yop8FuWvL<(UIEbb>WvDhfT~+sxL9@J=YYVh=Y@e?y|(|BIjPo{L33!&9y&~x5^sake?JKp zQ0I1LjMHK70^~!`@iR8`Uw9Q5ZS=m95}H>wQqX?L1S-kPqMrADy5js+{_He0~RMZzcHtkz-B7a&O-4i{v)BD)ceK_`$INJ zr#NYEu!YRkeDi-1lM>%4wb*;lE==|KXpV8UV@Hmh8aFM9b9@>(1X1@)`Zk&IFW#O{ z#IwK$!Nx+02sSV5e-tM&vp*qn4pkDC!znCekjub93##;dZv4=tzF zsG$wPSqiBG6mRe^#9Psx5eMZBrV0*-0k}4&r)^mzUD5{~Eqp(ZbN%xrsi}?EJ^iMj zprL{E5e7kn=UaEd7&kg0LFs4W&YFSg-VkkrJB=gHx8}kw1&DZTPEOdSYGzEn`P2-N zkuZ4zR?a}^)Qg;AW>e`cc{FfqCa^lh!33Bb&x>1Wvk)0^DxQdF;Q7-qep4hf$#jq9 zSz(%|TOEGWK8Q&+UK^E&d`xf3s$me*mhPaN^rNR&)H$`d*dV_sJ6r3ymETIj zPB87JWEJ1?_{^o5D^?0=E+^{ueS2$~e1DL>wz$1Qr{rF}x-=if*cx@5!L(V}H${=d z#)lMU{7m{kSM^Z%mpMhGyt(-Nl-1q5&D$syyPUPPw1`^k96#E694jQd7BW|9*?&g= zd?-1lproKce#n16P6a>3gQBN$u%iK0AJ^6tLj)8i>WN9N{ZC0G>^l4+z1WoMib1L0 z#+}Y>LQC}!hNu@d$HVLhNz5cW&dODDbFLZIWCgX(8Ik~;A5wZo=al<;Bi?D2w6EFm z=Y1F$qPA@Lo!`>2+;WXmM>9>JCB)(H2iiGmpxwmVvD?#r81m}ZEyH9+Fj8sbD_FGh z1vk*!`&xMFHXvk!H0_^>*$DQeByMlJl?hayN)gE;n$1T#=9&g$zJ{pg=@w*qrK&O9 z2=_pA-d5u7%$CLZ4-)S0!_`#CF;Tl*u=Zg2)s?n}{F0IjS!*q3>vO3ZybG&Ycg3?# z=NCOser3EnMovfh_M48;9;%fPc z;u_6AS1TQhJklgIREc6Xhy32h^yqu4aqu84gP5~#dT{HR9e2IKkaa?KfDL_ITYJ5% z@2G%bF`q|QOUpKNgmEjWlV?uK$dn8)jX4$29t0fN*1YDexA3a#YouXpwrtvGsh?k3 zTLZ)7Kj>eY);6^M);=GT94p(x*%di7>Sp*?z~jv%;hn5z!gJxP^R+_~WDs)fW{tRM zju|M>+;M4whQ)>?PfaWYz}YNwi~Sy{ZO)~ZnfB$clANzZ#`s;^vKvAEOWmx0vTeF5aeY8CMunoPUIt(Mki;CDPkS?Qw} z$Uq+>Yr_XQ2`NW;?drZ?wiq5BQwTBRE9U63Y7yU=KQ{Li#f+Xiog9aGpZ+}a`*00YlGo=MT2_k5#lA)*HdfohJ4i= zH$Xy5p8YUkEOY+wW)f-)02*hUopWfbV@J;&4#vuU8d(Cyfrs`z9pZy_>gA&78$zRw`4n%0ByMS`pWu=Vj8k76pU0DV|{osS6zb2WUpmaTYU|Q6avR| z&)3|eH(M5D`EQa)4CPz_nUuWj>mQf{rg=!Ga;|On-yeCUxut}u9?bWV_S^HBD1$J% zw)wMwE36BDZLYLe9>~v&%fT&gPxT=x*O~F^^?o ztP&D*k^`Tg9x!Eoy~SI)h@6Qt$53LQQ;pv4FBK6NukuFjlBL|2ta{ZgSUzQPRS*1G zeS7s&Qt#_yq6yV{Ms!I$7u{u7YHFf8-&`}3eYnZPTsAD?+x57P5D_(f@bSQfNF1~~ zztCSD!&RphJ}Nx!Aijqpbok(oG2+PhzrQr}DAe!@WKr2a3K|wy$C^f%aV8sMfhIic zU4}xm-=q>TMNr0xIgK%5Yn!B|9`}p!Bet!6EI5iQx;Zkh`DEORxcv)$pJ}VF=jcLO zq;5V!O}f<F3)pH|tKF$tY zYw*^qCD{dYo-Niaq1oetTh}-1Je}Or&K3&OXYk?{JWO^yP@Gc)OwJgy9+KYP*00tB!>pYffcSZpHKP<QIj|bVC>E2 zS3T#urr$BC1*#KS#p2V|?^E}&eIFBwbRd(N8}1g;R6b#K!dgaQWOhjW7!$?TTRmAV zT_(TpX=1cka@dR9oTua~-JX!j_o*9CtfJCcjx5d`k-7{o9Z|hqEX>Ru_4@BMKU(+)?>A z%hO5elai8rK8rWa<)WX^+91alj$y4$9Iqi^CFQkrS>2_9EU>{YTl{7%qR3A54Fd%(MAcuxHF^;= z5JWrbT;b^Yl2dGtlaX?B=2_K6tG#C38J|3>aL-OFP&+fJu(<; zU!6R_Y7BQ${03m*U&oY@?rl9n$(*!_6lT1skkRgo-ky*KypV&Ld8DcGEKAj09d6?f zG#M8GypwK#}USb@7KcDne7)VXvr){B}hfZYHs`Yjs+97%Md= zHIBUDD5x5E8fX8-07;&N`yvTAFC#m9SYFKdF-8hBYhlG~uwE5o3C)O^xvJLGD{9tF z$-(e)CBCWTn&{QL+xPV7uRNel^pO8{@10tQe|9lGII#k6tNgrI2ax5o?u}zbJQ`V)mq zLsO=!&Nd1^{r&u_!YTW7%{M4Xs;5eg=ePOWRYsJYNzh6q7vl5Ukl6VNkNaC zEAT=F-$BY74aMyFp|rj;1a|O`zjy`yKFg{)t#W=`Q%KP=wy{Z%$qz_o2&xiwIKPPi zW{AQ0E-vSrMn+_q11ha7t+W~{P$O%dzRD#_{pOSj+EqJ_Ow`{mGrC6{tQb2#q|C{e z7FYzy*$%0WwKbJgYFJpDt=XR+Y9ex{#KCjNoexwbo18fVVKd!xnN|gFcjV|mf_J~c zbG2wTK+(kbkd7!_i=6x39^IvLe$;T1x;L+#V;qO@hix39BOjM-$Se(s-_m`+E{``g z+!&O)xP*N$LFqgS4Ajy%`^_jXe)(JaExRgFhBB^cug(qKpZv( z=1y4iSKkJrfNgXS$Mr3{XTWTLcooKMHo3sGnJxXNc}ZF~A|)fV{=-e~?To|<0t_C9O5pj6jkn6|zpo<1n$f3*O{8RRdL z_VX4hi1-Me+}Km>U=?%MEv4#vVitp`{!(qWSyn!GjUXLhD#!>&M)6^E4p$+#=;>is zU2xCb8q%ztEi&vOw;xCR6MJ~~YWkAc{{8Jw0exmTj^<52+lTGiW+y3g=n$ z5G?7L@~Gf}QjzT57cykZ-*R-!5~gl~bYyrI*AQ{h^f)8d=iD8fbv!ui;r4#>H+aRR)Fi(J+s+CRFcm0%-`Db75JDm!YAMC-VKpv^? z9E^;Vgz^hH13UJnP3`Gh@`SretQ#)9p=RLGXcN^s|{tknS;t`=_C$*9s4Gk{+Y7!k-n|Iqp z;yHFtMt@o0I*o34uHU=82QztA+h!Jy*$+8Ny|%7!v$W=GU!LKtE=o5{!2x+#C!oRz zxz>WNyYF%+(qxkI?4#{IUi|kwyNaxhGq%)wzNZ#t52yf`u5e;R^mjQ(>^D_LptQh$ zgGjB`(-}gP98RBYPnf5K{?;IC);q$CMKK2{P|iR0sHbSbijef#=Wb5>NV{7`qxqT9O`;mxGOF~iegyEbUnY42Hw+?2GV^eUR7mAfTF>b=|~mHU2~|4Q1^W5suSAsf3r0_5zn@m#`J?CB?mTdmBgFDS)!E10? zq_|)?=d&M$$2fzI$+X~vS1DEVI^})^?$@OUcC(+pmmT+d)D|_K>&!uvVsWWTpvWNq zfvfN(*%r;6G2HtR2V-ly=gz59%f;%{Q*Mv9)hB$xcB0rLHO_Y>V5K! zr>`xKs=dH%qoOI*t=?4_O9)R#7y*^Ny?R3HC{o0iW>~;Y+U8W;hh2R zR+kz$SHJh?*dBhitGlg9%e`>=+Pf{LYRz2!{gERIFIt+K4oQVBExDpWdDepCh|4k- zx(I}eDjSq%9sSRmyc#0s-#mE%uV+B)Kow3Rq3AmktM=3X-DOB)0lj$ZEk0)d+~|bL zLy7e@>U}&s-U&x&w$OU{*;!divK4X-W?3M|@dx44 zxFON`cNhe=SyVPO>{U=xKyEl3`QE0P;!wfy08k&u5SrN}kDr^$Ib9kA#As$e`|W#0 zxyJOxf{b;U?cM#NW2XX@2hJ}ZTAgc%GCJ|1Bem@ZrTd2wD%F%wF51++KYpE{G?u(g z|NT5;-+9t-dCA?=ngPpX+fKd{!>QmovBc(CIPa{!t-AbY$MnT2-)QQ=7eQPI3q{my z_%{TWpj)a@Kg;vHfAuR0EJQ1T0HY7UWEyxKI(MlGBHuIXN=9ZTnHnuHXOO#~0tW>y zXq_-)wqV+J=0N<@(+F7J_w|!ttY*vZ;7sL-nRkB8&(1B@&S=~6E}kQKtE={TiAg`Y zHk(4O3m0S}m@5N!Op#&gPf!dv<&iac}*;tAaAk z7Qto8!{s4=BDo*PKe(9N;Q5uS`N^L5i;lnc?ro#J{pXu11CPxajq`#&f&(gH#lAyt zwvl>OTY9Npc0a!2I31VmJ0dgp=*o8Wkm=wCH4=ea`B&d+f^%R*2U*fAQyaUG1bMG51BA z3LnbgzZ(=%iA;;yxdaWPt5>he`^vWO``fBRhm;q14Y$Z?w~Mp)B4+fBF;bNy)vA=B zfp{}c+MO`#u{inYmM~MshYwpwkl$b$t@FDvi6pDqn?7>*-4?pa*jQ>#BXQ|K!);N% zO1IA3dwV)NeXr&NpHCFUSu-V5uNJBlO$JEbR%;~BoFyvLU8+AvLe8)p>v>r5iPoKm z;aQv5nKHp^Sp2swg%UMFWJnHz)&Bcl?Jn}3yc=|?&3>>-ZfZ!~!0 zWaE&lqC&C1I8yyp)Q-EP_icPq@o)^mSS+2RMf~@hpxEPNTY=%@E2_K;&SJ5$9e1tD zIfx}iOEdLWZ_%+=hWgu?`s7jXGtnUh3cRls58wA%aA(+Xn-lE2IMiKtCT?GlsK-wE zx5nf;h_(3yV{Oo=PtO0mJBP+9Az=q>W=*9&%S2ox20X`|ke_1&t8@af*433qE|Vl% zPyLb-ZADVxy1lij{Q!0nYH!DyT!=FgZtDz?c!vJ)M2W4 z;YYQfw5hZ_E5+qUchLap5D6xs9Km0RX=RKWs2zpqU9#BkI)0?efdCh2 z7s~5#oA{YJQX|b{)L$qi_j;wQZkL%~-#Kkz#V&?Ri(N!U{RipLlU)lbsi|ZnxG>e+ z_9|e-6;amT# z`Q5h3KRoj#191iVDB)>u73b zC0X4h+u|^~t^SQ=xycxIm>B-l`WSxP_0h02-0naC#gDsNd3~6aoyJ>p6#V>5oAPLJo)V0lEDNq?E$7*CXdYK8=CP~SRw*H_g7)q{_Up#RSTiSAug+Q9h%Xu{n%J)>2RGdH zWo54%O`$x+Orn7sBApZhIQ1;4)nRC-HRWh&H-=#`FbBBxb7B0T1)f33fb zQSS?#USMQJU6D+gvv$dykycZ`&k^yCzgDJP8aM7;x2#HS387NCsG@RiSoKsYb2Icf zER?=u`r*wrCdZLb3APU$Mj8CL(bZ+-=Ofa_7s;FvX@iJ~BalEKytsj&xGK0#tsAS_ zOZlEv=~zI5!uI_nZSgyXTeNJ%`%iNRZ{;`@t9mL$^>cCE8|^rJ>=y?sjbtSmE?4#> zU+gWpYwl-ipGF=4ZIr~aOO*_spTsWG(AU4qApa@%H@7a3Y|j?tgoOuGC?#rT*szrCY_l(OtYT|O?Gm%A(z)7I<3i=rD!c{K;xpKX31B577Ym2$=HOLLxQNp?%E z8!_m~%p5mri@@%bl(?cus5voS^Z;!Mgdi}nfKOA-n-j@7o-w|5FW=n#XA5>S?W*51 zKfi1fq?UqxKV|jg+}Wy$f|t)5+S{2xB2cK&Lfa)ix3FM;O8E{rL70J)@&q0OA!Q`_&=Z0c`O$o z+9Lf(H)*15c7539_@AEbZ`KM71ja9z$v&1HI6CnmvedipN#~G7;>AYqv*FS{Uw)CV zwr>bMI$g`b|2B20VBSR{Q;x}M+~{G_!S~hv*JfFBD{hlz{hk^9sSV{@QYl(ph3KZ_~7jL|FWmuZm|C&yCE34Izjv1PjtX5!0d4#Ktk-4f8N0ZWt86~k>&(mz7o6I4mlTm|(~)FHxCP;H zfWw9^h46ikJk;gSdg!W^7n9w{v z11oQG4pBy%t5*Tk`68?sLncp(tuS}0^VzxtUhU7eE~B@5F6=-UDdSrso!Lb)lGU*e z9z(=58A??I4#U>^dskP{$Qt}l;;at91ezRK#K1FHvlsd~I}Tj-tGg;7?KAX-Cc}c3 zCnJ6Hly_5U3Hlu26cC=2%1Gcr&)Uv&HBO)vcIei@J zMr1UHW zPE8+^TbrHB=5H72{$@KLF2wX0#$#pu{riE1qeiN4Y&_ts(_wU!u^tbTNVPk@Pp{a0 zA9z6BiK96!x3=(Gy^k!lY^IrtFZwG`zs$~vt?xYbw8i;}nR!Y5A6tA&w(Zm0$+ogT z=52(^|0C;5;IVAC?jJ%)L`2D)q+UZQLy~055TPhzgP}4H5t)k2AtFUG7fDhcV;NEj z$q>mrB}Gpt^Y~wPecyL_&)?7Kob&#A>v7-LwfEXL>XQw1^e4>2eIR@SZMx&1tfph-C& zsRbLFM9}R@01VUMi`Uv}e82kP0S5WtwY1OmW!>wI_FfhUwuxC|)2e1YZFO2nRQUAq z%*OQH$(rX>gWew>-8-yA*k&ozZ@}NxR0KEl*on!@p1$$|l+$ z<@tcM*_a^Ls2+2^=*LDwSY9-L_5_@S29ID-j1L~7nc4a`08!d8D(w zoj$Ee*hR&-5Zl4OeLJzA0#YOmP5L*X)A#VPi4_)YiB0{EF&CGBVBtk~?)}|%{h3EF zA9|F7O?r{$2x^d+CzO4}{&SV zl2lE)8D==mlax$9cYXdN{ z6;*HbkF|4<^T(zpD(u>(FpQ3lqII$jho-r?nflKnU1%Eu0%-9>YE2E=^B!6|ws`G7 zU1s`2Z#o>PvU2^wmwQISg3WUT)8!XpNy*3Bu4tS3cV)08LX`QnR#;j0nrvEye|$ny z6JbSSE-Z4vJk_%xf z@5vJq3B`{;a@VS zFxobTy-vS!7eA?kL+-ncc8PFYfP2K1F1|O|nc?Oy?C14hI|=Yl)s^g(cmnQ&eG~5K zKMdh1#2#j8Ol%7W>JNk-2;X%>9h0tUAHESadwqO)em*hz-z~?M>TT}ox)G6kiy{}K zFOY6^S$$yCKXJkwDnJr0#O72H5CMdlWFcy!Smumh{$z_~}T1EY!d9d>^R-I4wJT=OpW#B(H^lQ$m z$bBL;pBw#X1x?Mcclx>+pTzk!_%0o=_wnHYm;=>}NVRQD)$rJ{RZtwj{78Y15cUv_ zppXCGLw8bM&B9{Z_UY5@y^Yy0<+=RA>`Q2Ym8B&u!QN~m3J^R)fDJJZwu5={SavH!n9U8FQ@e_Z zo>yIRRsW4*&Yc`r6;3N%c?wgiYJq&wg&oTDpL@2#!~kajidKRl^k5{q`*;#0HExRL z1@GYKHkH4zYVg`fehmSElKYSaUbtdewnu%NV`(>Luy2@s~5!y|{nIG*X;_1c5 zzl1`^?UzpQbUFrT@aAy(zIkHMuir5_EzO^5ZHENh@!_)o8(ZiV(6eEZ5amOg3feiK zZGl8>;vV32ILDFgpe_Pa*KCf91<{amoC*#8UDOdczh^L?3uPvxMK~)MsU~DVPBYkk zz6MT*&_ZP^h9j?`eg)|R2;H7Pnl2o=`|O1t$MbMaeA z>E#(38Gcx6mQ$c16e?g~U_ko(p5a%6D8&IPNkYR!t&0MXkV+Q{Ka`oXvF8l8I%S)N zaEd<)=@DEoiU)(A^h;>x11!T}0$EO@CpwUSE{G|MP6#$v^oQe<&ms zpT#a5Mcb+J=T8Y#u$X&7ew-74(aR)-ZY5F%sf8x&FyD@ZjZ?P&( zn~-V#7N;V;cXq-Qkk3Wm^Mo*)U&HV!5=?pHTCWhEP6+;Y4|uXeE_?Q@;)vHXeZUD^ z1wzA~zb@>xbJf+p|HDvGKg_{g>rFU@O^fTYfhiSqeO9+8p&oOKXTOHKSuTxkXI?Wt zb^J6!H)21b8b<8G8G!4jM9L=x1%Wun;LFvSGQY#_23I5NA4_>Id898gSrQ78 zN(%|QqDUNQzni%f8T!wPuMlXMf|S<2wR~oX(qV@nBKw=Od7^FByEdgqM9=w7T|TgS zKCbwptY~8SP=n2ekZTvc3O>Alu#hMmikP?RhNtg1Ck?Xa-TjxeFFWkxiU|GwMe8R6 z4Rte(^1?T{YO819>NRi1qXlK+LLGdTC{1&6;AOtUL%R0(PFm77-*^84qzkl%r&w8< z=pdm+UI6{1vd?wX^Lr4NMn$n)7=QBHh&uryF*_ieW{R^{IKen!#OzNf*~HEL8a8W% zts7sR%}XvW-i%oS^e7RrI`cha|7gvB3#MWlZ>W#Sq^P^_M)EzuMP(+K(In~VD$IL}cXROitQpkT7n+pE= z%9NQ^=VD<|$GlT|#2KXRjk`b04Gg5ReTDoQB+bB;UIF8S!li`N+1maQCc}u3ClFPE zh>3CR0&5I|K~+@o?ZX2UH3*m}!Q886dSU~ymgA=zvACg;ft7L&MMr*@!ntcTIoAb--rgJJ zww?Det@A>?SK+IvL}7^1M9BJ2QC{HhBo$Yzk32M;3$EkYxd!y>sNd2GW64yJcLq0v zV7MTpD-i2=&lq8V7K(hlJY|VH*E%V;h8ELWx`p@Lxqfl6`oFv1l?3#rdK+*GkD2t@ zs`SU#uQ!TQ>uF)Bcl7A0w~T`F@Qpk-A|`?8iN+k?jO>mXW?Z&67%73t&uS1+;8GH` z3v=GzK-~uX2P)-?aOnTU3u55bGYQMUfblR$jZZ!BbEpo!O*;HM8+6-|Isn~ZHqymB zO8|KsS0#<($45(_qV%BK6e`H8z^1~2Lqp7VO5Zll&?8WHoS3N}!sMMhm5q%z00Pko z1Ej1RoIoE_ga7W98mng~0z`fxQ{t@e*NhfqUW3jCsUnc1CQpLPs7(87sn>%}S+LW} zvf!xo2I<_lIQOf$p!D(M2r7*Z$?{%t%5aWB_Pf@%DAMT>5Pxf)3?CmXE7+3JJ0?ET zyERc;vvBi&sdt!!w1R_ST6^GtDB~kr2M6(mN=~GEAVa;ww|aVd7!R%888NjAxnXsT zMg~fn_lTt^_A%w6x5gRX*jCRx>gv$PL(BLLj&XENdj9n-jMu-zI}%+h8LmJqHG27y z8e`jQCvF7S;whXoG^|9r!WOVeZy55vfB)VtAU4F!dZ|E;iz&{#s9f*c)MfCOM9IM( zM$97ufe~O1844ULa1>AEgRiSnLLP7H-Pnjw!@NfAP(dQ>aWbKxP`qjN?9LhWlG=Ig zj8UZ+^rA>IRFzDCni_3KQE=JIR5DRaaak~|7~7+X0JTm>?~sW@>5C*x79eFq*Mc35 zaPO^oS`N34*b-ea5fQejt}{!nvCidUNB;_*%Ez;QtDyixL3t2I5=<}xmJ2vp2){^I zkdi~W-ku5}uvKU5TFBkt9`v((QQ0Y&8 z`#=EVJ9n)b`H`w}&jQt`fOp zv0h2-H2W8)?YnllEKFB0|r}s1k35&9qUDW*heYdRh z+7=NU{3I_g#jfG~`+~)5vxsdcMd*^*?_oYg(p|Yb#VE)6rV6~GJGDN?-@U7xbzE^T zr%JI2aXH}Ed8t1{9k>^n%6+_#3d|7`6B9UqU2<|>BW;=GN!AQs^j{_@=fH0LjJf%$ ztm7IBcj4C!A%cBZQ4>2Qzr_%X8)0ZJbn{H`(;C1LxID0gDC>x@vw$StyVqj!iC8_V zFa!{2C(tNl4}(1g=K&FG^C9QWb6z|cp~tVtx&exZ7&1+-ao(DQrBrD*;;)h8&slOi zd>N2l2n>m%U`-AMU_{~B_1uG1EH1mLRL$GUd5MbBD5UPal6qlJTdw0Sl0{BnU|H~Sc3?#FXywkDKz!8w>M~) zp?Bl2F>Zix#NOjI{e3fl%&e!ToeG-@Vi@0s5CvT}$}e0G5H7a61eD-ThI^(KeeG=C z+g)m`-9=8Tn$91$N#o+;vaK6`3l0G%C|P)IK|uj*)p~C&9BMm!%aScj1=DyXPb}n< z+TKTs*V;;S~w zuFUU>;B2J&r0k&^E!dAK$d2B{$;peIq9V$rMwZTS%Na zeVVj-^=e?FZx=gme4zlp!34ugKC-Gx2_aExDDN1C9L@LqhslEK)`ci@T3)w=3@YTP zU}1Z0A4{SGo)y+ck#@<;+rRyM$3COLcdg$Q)HVKxT_pYZPJ_OQPZm+Ecm@yL;O>a58)l6srRESHzNvygS;WA zzTgFf^N0C2@B12z>s(l13S^XOD-cw56;2>{)>stWkLg=c4g(xr*PM7nQE)n{>%-RF z7Y_Znd|a39|K71Src89Ly*%!MnXAo>Z^sMUDz*Ao3~eY7-f%2)G522p8P z7rDzZB~Q!rjxcnau9j4$Z&`M@ewoJ|1Os%FI&8G~$pFn5%h!8r?&VGRR~aAgk1{@0 z%+1j;SyBgcxUB)qMqrFv{Jh{3kBsn!DKiXO9y{vC4Z}8{K09oMc`(#M13<>Y>|rQp z+~+5E{OBrn>E|25#jPEB`f>3Wjyr~-6FZbqV?6wi3;lI?K<$JVbXH?u^ZMtEnr{xTnmhHNWIDyR>}&sNbd1?jqk6c`(ybQc`^C z8=Q-|c;vl;QM}>r+uir!b&HKmVW;UO#%erdoO+uE72waVGVjhlmL}Jmg7io4$sLkP zpw(f}5fc@yJlkLQPm2r=AyJ--&e~%mI#1L@%P?QvkOY{BV=u!v2vd=q98nCWKpg<{ zg1{B87Fs6ctw_C!!7XD@y#l!v$4N?B8nih4 zM|7WtH4v?1 zuBmc)S-y5i0;DXKIE3@CORABLTH^&rcAFg=dB*O*Lu_Iym_Qgc}Cd@fK zDJy%NSQ>;67WMAjN zg})zci=0`I@^~wiAJM7R!uOUqJ8IW#(KTb z)L_(e@DAcYI^?Ebhq;?tmc^sS|QJDA_jLWe;_I?@#Ywti&LyDi$HNIxy) z?<8`FALeyYC=OUSSsTJH72mNMD*I0)f8pfiZHw3l`qyqj2B$AjM>w5q&BO>d7n-yn z6^`R#ak?Vx*$*!3V_O?W zi9y=H659`@Dr!*qdzV^=0n2IqbaldP*l@u90IZd>GbmS|gF z(X(59Q8p39&F8$BcmbYBo6f5W6%|qWx9}%HMUp)2YoQ#xAyf2Z-isHE>d}slj+p8)L?y%#e?(*rwV5YH@_4pB>OUlMxyzGl z&{=w*eHlK0LJn+U1iCt{sgI7$rClmBZ1;Upj=JcTCxd8=lIUo zLbWynQ@2$>`0ZuyVP+b@euMxlJ{JxJMtJDW>-|sfMD8zlIRG@QM^$oga4@Dhhx`xv1+NwR zyGbMfSRh$cTqvD)xnH};jj(cvS({N;BGah^9Vqm|DU0q_R`<=>*;2!FbK6?Ww_(+a z=gbe+78ijQSwVG0i96WEIypH$`{)DO9?#kzE%8E9yIFz>%ml0-aLxXAo>!gS>%Mj%RVlm$4$Lz`XG<{;O13I#xrnuNP96ZJJd+#T34BeADJ3Bjevu6gRA!lMNeH|Bf(-25=h=$anX>{2<9y>Ckr$aWl zkB*#iq5WpL)a=c;9*R~NJ6osAslcd#fvqfGFWE@W7#vhk9iYpZX{e$FQ+}uF7Rg_U zudvYq`d7^DdiFjR^@gyz(7yX6a1&A}Jl=J(juWydL|r6!=ag$q4|vib@78Qvw069G z=E=>WUmiq=xq1t{5k@RH|6GipU%#$V5OsWBRP?rdvvs_?++%K+O`je=5Tipf1`5~7 zF<|r*^Tb0%1|{KMG(NGx7;(DYFQb1OT6h@kmsC<#X1w$~z}eRJ9q>wyUKa6a6zu%Y zWk(jWX5FN_`hJ}*^(mVeG}u%DQ^ew`z}Dpz6}hL>3_-eh=|@+SUkt!8R!Pe5QQHTm z)VcUNIuIHeskA%x8HPSqf~NpFaGI=BfZ_xUS#?{U(i2Z*=!>a4E2e}+#ju*Dh#9`zQ!UG7qLGr`g==8I8;KrYG za!=bI6+8(jJ2NNaU6+ofRn>!6J1IV`rgrr>kVN{pDQcf)JDRQdn(`|CqW1~egm8ep! z+tjh6#(Y1Qq&^ZuLHnj93AEjm1yT~LH*MVO`rFL5s;P+u#nI0>FQxaq3;~MW-v7D* z{{tBea}F2!7cBhVfRM7=G(s-Dcw{_FA!n`UZR3IHRt)|mxo;`E63EoMx?Db<|N+b z7f20^wluU!Ij*!P=aF6(vhu1-Efe$o9aA?2)f3*jJg-b=MIIu+A=0IctSqrz0O~60p{u?UiLfIB^lqtu+U4eC6MCZIU@B4TqDM|OKzn5 z7&CI226o#ARrO!_@XhO6y{(kZ%$>R+6k}1i+VxiAY`3uE)v-)*CIb@y9TUH*oP z`7TRA>v;*+3p`WN^0!Q;M}%%R6-1t@{-zYOSUMYz3KAdtyd8=-?;`Jog37ei(dorG z7u-JT%q4H&-wRYesa6=;YAG{|GSP?g+Nk|6v#rcag?WocUbT~zB)|_W8F3Ct#wTm%1b&7z> zg6cTfZ?I5h7ifhaZ3#z&a-z`ZNHq}~1Y!q3l*wzaMOlU+6ohgk{~_Y^kM$fVFm3!N z+aUW>cQ;&s{E)ndmwXN)oNwBY8d1rdu^X@vej9*-X!>AVTBleEFm<4X1U(5Ps%g8N zn?Zs_-brP$(TkQDRvId|Qd66l}=`gf4G&CqN)A%1&ZM$G+ zr?p?`A%nofPwM}4T1GrJ3F)S~Z`SkN<`1Mzf zKI^c0L|N|;Gx&Z+p8BbT_;^29N<;K(Vfd!MpC3OfsQ34Y$Kh2-&@A9o5)--cm=P?4 zQ{B&|4NcH#N~(Dvt31B@yci48xSt(ww>9WAJ9WzUn+;SBGAvvQXk5Q}6Zp}B)FSk@ z7c2_OcU#Hi2vl2}Q}mU{wF$gU6Q!qgzBV`nw+WXmW#Mk4UTdo^a2f@w)5q9NY);8iiu_eQZogmkoL$ zU|v+TXKih-4>Q@R`o8ySR+O2im70~NMJ33GNrTKpO$3sOm5e%Dd;0<43Cw3F05g1w zZSd9kl@-Pgdm3|F+jZ<=Dhy-PebmmwjVq>@wNX-v!NCG)^at>MyEtDv*mUqx)qjbG zT*$-kR3WL@i$a0~h{niO^E#9D6V0JML4j3Std1|t9NOp%F(C$;@1DH(TJTwQL*p=N zCg>Ina18q_ef}(n%VGB1ovQDcT7Tr;C8o>>b>3U=te)YH>aY!UEfk&< zaXq6RSJ&D)d`}hi)$M!th$aldy3||o|1OiA+}%-46+gDlaJV$jJft3$_ccMdQ*yFL z_zy3xAgWVRRJ5kF+a5QdX?l7Z;~*CYrUp=#;Qx@kD3|YofVl>OeVki*1yJ>1yXOi&K%hcDh7`joDiuc zUKO9Qg1(9gN&Qk4ar+qFF9c%EZxkUI!N;3Dw2L}dtV1K`zQm)ku6 z6QYCh=+Swqo2a=00s`WU&LFqo-Vit$r178p)d$8D2=PHrkf1vE#%Qb}t-z0!Vc(mB zp8osyOc3~+p4^5Af&|s|@p!6s$~|#hG>wersmhVjy#Oe{CBmW2ANe)lgO1~k>JH2y zxJH|#w~y#HXl68rIGkXl@1(eiZpxzD*81eL%9fFhDga*1oZDI(EmCxfbO=EO7Ous0 zY!kn{(&7anIQ(DUEs$9H#AD)^JmA77Hr;R$sRSOR*cs(-lE z*i>xo?9in^132r)?sJ}=TTo~KX7*!Wqh)Y-{6iD899yl)_LZdyd=+1YUBGE!XaHvx z=s7LOA9(~zFmaK=i9pd~cEQQ-7yH3~L88<*XCR!614)9d|(OaG?X=Ej_nc!E!Jcuu?JiO^HEhY5? znA-3bq%nBD&S!URLr)y>8qeZ#^^t3EGl4Om>&=??&EfnShPNPjdGhSpG3m`^D2u@E zEtY0HPFt^atIje|I5(=*I){NbH1$(K*lC1_L88vd(M3ML-#??9V?h3>=IxJseN8x& zW33<$obpCE1>v>w35q%ASZ?m`W}vHzQL^F2C=x&SLOQxg>9<)At$4_BX!n|n*??A_6DU2 z0}s0|&gQYFclGvG7k^AHKE3e=t6E(P9)-M*@WE7c@5%1|4<}TX(|c5v}rTxE=V-l9s*USiOIo@*WLY#5S7JEmLEJ}Jm2 zRWB{f5X9-9{t-$js4SqzIE!2G!v@z4j4Xgh4X* z9;%C|tH7QP2WrXopG*;6OT1acdTA`^X$ish4}w~CJNI`2MxfxtvI}V^Wr}+F6@$E!d*zfbkd46d!kCn(q)8DFM!l?VSX4C?`^qDc@`bS97@4;{` zsHl%Q#;!N-W9|Z{2zvlOJRpYqD4m61^gt{#spt~iBs^a+!j1^d#mx;_Cv_$*flt6x zgOO}%iu#zGB31wJ-a+38tWx?g9%2y=Vgs}kxQh4BO}FnAhwB?51<52I;c*ax4fLm; zp2rIw@Sy?1Kx4r5RYSs8eN=gIchZl9gCl{tAQ9UzfUe8d>CA%6X>{qwGqhk2&}H-2 zWXt>`2p~S{<14PI%NCrP8L)4P5}hh+Ry2pShE0-j@!L>*R7IOYxo{fFP|S@GBehZq zU{KvB2512a!0LQ5=@me7FYq=Ce!67^CS+?7>qspTby#I=bYl77#Z`v4$bB;xKnrZv zOS5sgqhbd0G`I|uN__R<@eY1^d?)$UTs2x!(4_G9-@=JIZ2T9E3lZqeR&L(_fMEnq@{PhHug}zBL`n zrpX_L2@nCQ5V?gI6o%dzy&SX`Q5ulc~^5P2-2bgEL#wX@%Gui*E`blV~eHE<^w zR&Tp%WFAqbujlO|!<8$iI${f)L7YF3*x<8(2LII_GA)*j!Xd^ZmQcUp4+~+j=TrB9Q=*| z-ZZfe3{(@efhZlo?)D?4gL!bhd4~#p_S0z9qo{*~_%+eQ1>=m;0zG2Lh*`&m@mtY6 zHmYm80GTb*`t|!$>m@g>gZVj!c!1GyN?9agoj9!(+E~DTgoVM27dcv!bkK(arW(udY>YO|{ZxqeXjVxaaZza2rNOXWc{Me+aZ~hv*v3 z4%<1E@$2cnwl=ZM+jKnbtuI~T0F51@JfJ9A7%g}qj6A-N=kFJhI!Xw;bb~OsWW;)- zlM>iA3O&W}v1*1Eq5hjrn^K?4p`ga02g5@=JNQeZuSEDogB*rV4>ts^{e*-JY#JWz z`{zk$1w!hYxc}bNlq+nC3mh)wpAN6kUgB77YY0s!Gt*FzJe?&+f5uAj5h`o2HFTRcA0Y+nct zQuMPtI2ml#3H*MTY;<6^a8_CQI*9ZOJIRg@Iw>DtM%%`wTS2@D{aD-kbLb`^WM)R@>|q=wc7HS#PN=F2+BRCwLIp=5fh&@(cc-{%yaX<^j;-AzY{|yazRdxm4(Htz9tjQ zh|=gVFgU%;$-_e~K~EpbdYpBedbtPfpFUlw>TeV}5e}6z+uFo^{l|1;N-8EU5D*I? z9+ty(6a@xOgp%FL?QLys1$IW5Nd>b!ER~8`BErM=>{&n77a?L55RRFM?NPpvj5X!B z9zf<65*{h^uR>Fk^|BzE6AjL=AFYZ$VF@_gvGu5RjGQ`l#ub}jiA%X-@XvfH^{FMx zgk4iqM_s$-lPwAZk~62k8M3{&iAmA!L1Nw!+G02YZkaw14r~anfvn#D&`qWw zG5w?nVP~JQw66vrDKbPku7WvZVzM#@4OH+Nx@FaB^`OyXy76M_v;~$XL7$Iz|NF&j;7UOv z2hqP=QZe0pfMb{aOjhCO8|I4Jg-`}SSjg-b+h=J0U#JIbsGpsJAQ42b(QUw z?~WW7QY_q~uRH1mBZineIYm*`YU*)N6^%%$J|jZ2iwi4GHD@^3*mo8Z9lsPQvt8_e zA3WXC0TC)>uk`htWX)sXD(G|))}V=LGk(4#ffJH%_S%0mgl=|({^Y>A)p0BelCq?} zEmDX6#B1R5&JsH-Ocek4bid$O0jqj6oNTL9bYH$Mgr4N)C} zeVbAnb!*@1h6K#XprJDNymMo|b#OC!lF;>_1VFnqL+@Kll7k#iTLH3Cu1)a2Y8q2w zbSahTqPzQ=I4d8sR~DTRuxZ1okchmKA`lR& zz!_$KUKUI;m{!!~0~0d#JkG_v5N;l2-0+VGX%v=&xX z86E0Vp|1t-Q~Fh&_CKuB;xWlOh-pz=ysK%&KEve058>GMGLLT!GCNcZ52V!4BFEZO znDv6mN2^)NcBN%kI%h;n`N15Op91(7rF>j_L83sw^6}atcF#FQ?`hfw;Vi+{VR3K; z5H1@2s7}#&AsT$h*N^ubNQZHz=C|9P3v6i}UK3v&teK4|x{kq@;65wUQmins;9765 zK*{q4*$Zv7$@eSkGJNmVqoVkIXHPWN^4B8T{2xL)8!VC3VAIgOnwm;%5uNG(d|eFx zO_1!GS2w3@DAF|+rgA)cnW0fyx5HLy)#2uQz?x;tqvbrnN@&{@n=s*5V0dhn=&GrO z@(HxBJ9ZKC|L!{A{U8W8f13LeyB4irj~+t{L!TX_%W}e5VkJ(7*8e2PbAb?+<%&2K z`3z+&gD$My?qzQyo0~Y~U%uR*mfjeyie})Sk=iriB z)lI~qP{_07?u!=(M0H+|3z9jfxVmkn5GPr9BCGpY$kJ02*&CC#L&}6HKQJrMOQUft zen2dH_>h9=#eaDmE4Kyx4g#!UuSqR_GCt+Kz&`7gVscb?Q!QABTG2ZNMl5mDSJ55u zi^YR4Hu;gEgYEN7I8G39=a21{muE7(g{m7zo-9rF_z9L7SQkGMRMOSozl-3auxBDp zgI+@>z_d*ldHK}dQ1mjY`p;+6H$rWVYD?U^2l7vfo6S{FP=`96WgXoF2t!dW7~Ka#+W;LC zUO8gREkX6>$2&HqKH9+^)-iaLkNNcN$NpHvf{AK`K8(1XMw6sXzeNv_6{HOWhpTei zY$hE$?p;o7dssaMC6lrMRdT_ne#pb79gwp&gpe{5IgqWS?EHMk{VXj;`pj?z3lZ<&t6DMP$h~q9kL0W(`uC5}S`F&9&t*_bIC8(_^!-#} zqq-BaiEmIh%JD=_k6EiZKp}(Fjx&Gw@L?PQyDcYqaLgdzY^o}{0fYnwiZYz+yWhci zKZ|L&k3ddS|BVkXqvq{&*~Hl*E|GbT#@us5%Y4b{^}eFp}nrW}PW{sX6(Bzh8(%`T6LHr-ud<*T^h#($drY>UsTUq4htipDB04CKX@9DbG{ zyivtt$KFgIldR(-@+%Kprjee=10a3PCMKGOGx{z{~l&J7B3ETn9MTfXc4};_3$T={Jy>aQVM~+-`k*BB3z6*KwYLgWvmK(63g@Y5 zy-mBvM2LefXVq=DBWG$}1go@hpQO!hQYy_q{y21Xw#V~Q!wT(_$~%o!%39j5Qo?p6 zu&FsSDRg~JX~{FDElRYyzP`iB<>l3d!misq7bvtz7KR^r$|u`=a`2)mpnd?VfvFms z3T3Vp^9SAb=g+^*20 zpESQpaA%NsuL7z076YBItMZ4<^*j0 zxE-dwR+a4;KhbpV%&PUSW!X|dF2^}SMWBjEQIiyG4|Ytiv1pFp*!rYTo%fu?=I7W8 zNFtUq0*^lb>7894_27l%PMU`WhYfaa6b_|E_ZMs3`ufZGGTwd93O_@D}ELeCB^*#5_Z!?uKRY*4(+t@V7qYd=C``n^LQnU8BfG5_R zPbK}+86G-2lcd>4iIo#9e&Neg&sUSvE+uTh796`XLPB58tYNTs$%&d($<6C?!s6`x z44(Y6>aa|0EifjBY{-=4+rELkF&}sYPzw4`!mq1^CjouHC?&zaLKu62@rH@9H2UX> zHA*Anw9)%Rg#Te4+8MD^U+(>viLq4rBQoD-)fyume$FJ*p7I&hpzJn}3J!j+pJNbJ z(?Y!;Ioxg!3xN?%2G8xA1knsR8# zqU%JlL)hz7TAEhrrRov4w5)}!A8iu~>C3%lu{9R5PUVx~(HN`pme&Xr9FCAX{uHKyGlfo9+?!UWJ__>w%J4H{q^-4J^dKRD4xu)wD z-fHY4DHzoD?>W4}l62IUg_p8oGkaysm_NTy)4DkITJKyM&GKyax03O6KGLD`js8CW zbZPUH8pocDimElp^F67WVYDzuQB__Xc(8T0>Y!$SP?-(snRyOb;_>|5ZH*lb#%SNd zR|u z)z3Oxeq43vMN+T5`YZ7tD&s*RY(D2LNY5UByu6gNr{jL+disZ=QNPV^fjVFoU`A+!I}38q?85ZCTJ$UC zZMuYJ3{BRv80AATgCl@e8mfP&RKQuHU9$J`ZP9PU8y<9*z9zinv+|F3?)8|;g9m31 z<{6oMkRRT&FizE5I3Vs`&LsVvHFt6;WYX>Rfknd~|IC`qGpOkwd#ho%s4;nB;`OBQ z?7~)FrQFx&CYdG2?Aga_dYQHw-^g#Mzb-p|b!Kk-i`{xJo-+4Nv7P#~4Fzl6M|J6Z zm-hxeOz(T`L(jW1WQtq6Fy2=FqTJGGN9Q)>3%~sb2%#}#zUcO0xoh&YmyNG4W`q8| zuLi&DA7458BQPpw#LU-a-}qH|-k$Fh73ca#9Vn@(!tS^J>C3U8^S$>z<)N^($WLvk(3uB|XHFj{1+I~yzP<1;om z+uy&k`BJyTrUOR=!aJff1NmElNk-){xF*iENp8#y8%-Fn6Z&IGU-EKJRAf-J;0w0J zmhx{ihPNy!qhPQednJvOC6XgY$|d8MyB_NZ=i5OwMbVT>$YB`Spz8v7*HwCnaOK3? zHM-)3hBky1Aa+ohs;+;QVRAo2Z>8w|N{Mz#!EI`C@3x@9k!+bCaZ0nrjpBVzHoyvy zhG98%Y}IVfayi|DkZdKrL9I{KyU*}epZc+|W|?o!a4{&YS4CayOwJ_r%K4eW*^s94 z$Q=vmO;xXkdDADd8n_grdyL=ZRQpBxcpfYp@`^*1N@{JLL4b6taBze~TFL8x? z6E+2Yuw5K==nnq22HXJl$x*e$J9k|0y9_9$lQ4VM>UB{+V6o!%MUTDjbtNNw%Vx?4 zGB>OyO&TstY^~z0N;m)57p41vm9KBp4SffKH6TW#CoV-~x7H(y7Xk9o}|saq$8u;fw zG*Nr7(tkBELIQaZhmS`j=R0Pa{;m~P?_)%m9x1w>%#(ffgiVTx_=}2_ycHMWTJo@n z75ARm(kkE8t3IAqdZT`kJ>hiKr5SIIvdRUHaq+DyoHnmrx%6+&-g%Mq`e^tvjs1QH zPN{;UzG7GLpA_%Keuv3H&y}+WZ4Cln%2u9E+Q_@`bytr^kN>H~i!^ho*AClwcnz#{ zR9CNjyxo7O){Q~;ac=G^(!fN=udC=ypsH473j2!%GB<}ZIuwPdy@~G{P!NCva>-0FU>>2^PO(o#PTqw1vVe)W#b$C zgVL$x*UU6|?Tgv3^YDjB-<4jbZi5YZVEeS}!foliSu;u;RZAh->u{4#a!5#`(k+Fx z2eA;|{4wFXJS9{i01?igPV8 zc%5B*u-jq_Mkk+7?MkB+t{0*@INQ%BKe^mv!@F9tceJo;wtdBk`ryncKi8|ePjbTj zH_N%-99^zh^Nz0UbgtR4HGYlo(1Pj+*3Twl4@4*T$jTZO-lqC1rMeatMsF5XxWG=c z*r&$KyLNo4PGVf#*b+iKYcw~xzq6_o9RI+YWbF# z?k5Rcv%XBe8>0pKkM$oN*uGuB1ZnN7wsMUC5f2t6S~e8_2tPF@d>)L-g$?gGxW%E%UlETH0PxQ-^_( z78fhaD^{c?J~$?r4Ey@i8Fq^eobZueo6MfPI5Easxs=fD*+rpKqWZ_@i|?lDqbs#M zOlK_#%-go&vhLtyKULM67?9^JoMT$|Kc0#$M0Xf8hXRGu{rAkoUoTEK`(!=G#6JsT zFP4SY%udv>bj|$4yOXkbHgL}B&BTW-o-)jJ?sw}4+p2aiHU>N8mb-4fzZEy{ifkp% z`CR6V4n_K1%I!NRsWwaLmX#FhCB1eo`xwlg&otn`=zEqdfwl}ZEMw=vT)gkK=D8h?u2Bjh%N@qPT0QjWd_&Sgg2};*2311u^(Cq4SKg$G=f9+u zzf|=0c}Q%=q7GipSt`Mu^m1zk-A3A#kq<1#AChf?co!XS zP}Pd{yWW{N=4;NjG8^X>RiioUFaE&M;eEI#-QuF9;m7w?otFJHOH&1%6f1_mJ>{rK zwNL$g$sC79BDC%haLOK~-n^)YLK@`bOT=RENjlAuqjpKt+e{o*12cV|9V?RQ)0c0b#Zr5Rv`jeqN_{orhlVlg)N|LN~v?<4c!UaKBR>9`-$9 z{(eDt7FASTSGCIYSia8Z3%nnOGWj*gQ_oDdGj-ZZ{U$=YoKm)?x|yRpgw_%w8PPun zJFLqFktWf^g-#yandIf$Z6g4fU>E)P6m(-E_TM8q@TIxAW6h_^xBeK2{BVjyT6fZa zc6Hhcg9vqQSeE4N(=S){E*4I#zqCRxFtn!Zh7UvUj|IN_+{d)a$9la-*GwFzC5=}C zQl`wzNG-`{xvrbdnf-J)Xd>iPcTg&+d^*XzX#b#JyVnaU7c}|LM>3-fmBFll{Et`D z=l)ab36#Y5hI8|q`HW2!%Ja&z^#LzfR3HTj1x|$2dkd3%D13pX(x$r@O#0?z9og5g z=q9kL=rU|AIL5F|r}uKDj-t(JR?ERfvw=%D;+#oWR!YXi%`2oZ786|dhK5yMcD!n~ z_mU5_en#ku^m4+C3v96-j3#v!6vjON;`OimARZgqs8RZ~)@%_wipdU85UHA05 zMh4a#L^TYLD&80=%j}%@wzXJw|6aT8$K_tAao|;_-F+gV{!Mj>P4X#WCAQZEjKER9 zTJ^G8e!rC=IGz?2fwa2{&Lzik4h?nmuMnyH+d8?!Zkq@x?^r{Py>2KNx?id$_I>@T z);Ybf6t_I@>p44mL)Z9P|7yRL16@LG`%WFY_~Ne6cAs6dOS2DBeCcS{E>rq*`_Bn2 zs~_vsGp||eGgjWRTyVL|%B%MhO@iC0mXa?IOlEH_9GD&0znSY*ElRed{rk)Ne^$4j zXtKvHlou~bM(L*Fi@D!u|A#nNu4nz{#JFePjG6DV+Y{bZUZ}e2JxylWeb<-We%GfU zGPs^~hu684sj}sdIRs+2cClvI*671uiwQ2f!ejnc+s#=m%`G18SiCU*i*&_jlqCOk zMa=)O^5j#h&Ru0WGv$>laf=7iv(>%!{ZjF=8N2knc_v1XJ}4*%C*xIfv!1_dM@fs6 z3VFwbyGyG45#i9Y#}uQi_oug7w{mWrs*jqFY*?$p;}D36BiF$;X{C`)aq&(jkInP9 z)JnS_ODaChxv`yc3f;jIWj{A!dB~<$EysT)czm^;50L11;jO~RjWV*u2(%(5gop+d z=1kBg#|RWL3j-X1fpBhLyEJ(oP@xRnWyd1Vp$i6|wr>~BMr=-mHRS1;(2}~GMEkt& zNps4}r>Yi>nZ5L$IUx7$;7g-#wD&d|Jn4&f=vZ1>P7>68+`_If_qA}Qic<8+DNwdy z##=ZzSH3PqCwk&eVf1Xo%#4}MmW<_n;|8Y$u~-}Mk}C7m*X?(XNMQc-|Grv=d=B1I zHY6@c%Kzi)E1;@ex2`uKl7e(23W79usVOqO!^6fNV+UjpBr3=~$VD_o+ET2?WVLgTO#&6iO&)7ctcjMr zC*2MZt&cmv(RxXEB79uM{e&~}^FNUt1rUZ8J%}N|# zF_yPKB$z|A#z7!`Cq<$@_PcG^kG0_q=WHpmhowV{I~x~yUvoUfjMu3R+-6nwFo9ri zdB5ISFCzSH7c>??j0*BFL>2ari39X3fx)`W!2xtfZ%Hi0;`E;UuDVgHl0*G!h+PA) z^pY6ocRESDwyL`Y^|a$4Vfi#M0{|WfG>|<) zp9l2##LT0oU1I?lMeVu6X|!sG%H=v0aW=MRL1|u;_!lmurUt##ruO1p)-Qa(Yf>|z z)8XOawRW6lR})?s#!o%`T`qrL-mZ6|ERk-Fw`>c&Ohw z4w(D9uSGX(>r$q(g~X9z!Z_Ku?@h-oc`^lhFK&6rIix(B!3_na8 z!6<v+dcOm$Ujs1k=u2&_)0vfb9R@P`cCXwR%rLrjLqmiohySMt40^X)Vl9)fw!T?kcP3_$VgxM?J3G7KgW2cL$-y@9lBg(+pr9~* z6Z%w$mN+1ti`oDNG^VDf1AhI)W9YQ$!b0^n_X>y|g*mP;u#WO7zKVX-icec`asLJ$)@QCNRjsvjk&Bn$?Mpcyr+DRSTVD*zQK0G9o*<%yZZV8){-HDYx zE^SeYP%dzhwWI5o19q;jA36xoruNwQ*3oB9Z#q+lxmQH7gc0c+H5gH*6Q2tJ;fpZ+ z6}j6=WOtO5WbEyExVX7Bjf_YVzvIE;Z%{zPgwF*I4vzVJz5U0>hjT0AQYW}7;z@<- zA)E#V5_sUSkk&P)m=}G`rlK4NrJxwKyi^yO;bd%W=aQE^wk6TrFN;JNqe`)JWM?JC1AQ-Rd-a%$LVZhVFctV3zk zprZ}_q>=A}H|Fi{JB6_B$CJxnJP-XgkTlT*%`}igKNwnX$QKVa{1dz`R|B229?!TD zU#}*T6(3vc;FP2DKd=oK`jJA!di+R98sS)&1iKE^K!OgBVLI ztDOjf0Dno(=_i-V^g(nh@8y-N3yZQ>kCaqYqPnQ+^So0Yxp}8V6A)M(bz8>gRx8TB z)Fx3t1u1dL=-7@EB)=$Zznzd)@;Rza=W5hthD zQIV0ie0;74#mvdFD*w-8%|z!388V)2$2+AwdP+PH467Q~2~ zZf>ROX`eRdx>~GCx4lEcr9J;f8=CvaFh~Q)%gSbxDV{b6vRixFX-yq$pvW+2lA| z2Tbyh2AsX_J`|T)Yn6L?;e6lqi@mIZ<mWF|^ z^-+OzM!pjP1O>Q+t5T;Izi2dt>2MO0-`JxWJeaWSk)QekEw<%X|DfhZ&Pjxjbcgbrh_BawZc ze3Jr&3%k00OjB9;;hdIgUT7W&i7SkVj{XeuP+$Wa1nB7>!&XWfnhdxJF!L4u^eLgc z=yCJO@urB}6-vVM%*^Lt;!X7Wy_~!GMQ6VZ=9$zB2n@tdT4IZbT}r#zCNXY0Qx{hA zqUXm(^2Lms;>|5+Nm`Y1X7r7C<jFq7f{b$ML z@tf?qm4(AcpBzWUTQL}m?Ztj%lk)oU?zqKpxdY0#X#BBVk#?GD_{WbzM_YaBm9DeO z30xEep|UmI7Z_sPLrLV{s$2$dH}Gx*Z@QX9@MY_?($u69{QtJE*<08`i zUE%me-)kNXkBb8Xt>(YF^n*!C2|N^3a%>N?_XO6BjaG_4=~tq$lLfI-2Ve5H_qw`< zJ!&0>bw^81eIuO$X0=TfyZl#Y^|vRtG<0`&3yo@uoyMh#etrG^{WDC^fm~Ii+o%Y5 znP~ooqmK-}mZz@s(UG2*UYCI^a;K3Ymu2>R$)hSC*ebaX@aMweXd*}s1I@+EG+HX$V?_UPzH z#;b(`a4tLu266V|`1H-{WoCI`nb-mL66Wl|#r0b(dwzD>>#^@=CW=ll> zMt_3);z=5Ll1L2uoL!cyBLOOTwR+#RsPojdrZ_|Ih=`3J{=$ zy+%D~AiUgIy=84EN#k`mI~^I=19}XDxIw| zjG1hCaw}IWJu?#*)>43s5|%`PIp!@mQGjA`Mpa`6yOirgIQQqy|FHG=lB_F0OKiB^ zJwHEh9AICf7uD9LU_VlM9^_?2)I2iE%7mzi`JN0&e@%JX`IXzd%R@LIuZ4x9>BYrl zFlzsK4Sjm3wvyLxi~KP-GhQPuPX;K|0gWyXmf&P%WzkCd3R`t0uk2RCPh%3WO$B=( z!hihG`u6TRg;U)&HF#A0{BR!!{_X^0Ujmqy<>cqbMA2O>HfzCyWqA{Da#y#G7>5mt zO|igt*=1{9^XOopp^dw!)_h>6)@Rdsc~J1i!F+~c3dl)L;D1d$I?L>=Kl^?7cy6_- zw99&`HDa*Rs{kq_ud_y6cKJ>cVZ|7k!t2ZC74*)aM)*Q`@%ALV- z$NGIM`>|R&5Wm5ekk7DWyKdDk2QD5b7gsY3q6wHbqImQ_g-bXdA8mGl48qK-&~&ug zqjKSWqJViT{_;o_1?+8qE#c*u?FrK35{F?C5GZ}nD{0O@E_0hx17HT@Dbq_u4d9o6 zN6l|+@5ML@KFi2q&dNGNaapAiY(TM4h(C~WR&#IG9V`@BmhSB~oJRNO>t5pJB|#Ot zOe=um40)2UJ7KWa=PE?v-V0v`0MgKp~+O?+rr!v|iklnNOo!<|+C zi(E3-+^%)b*xG;XAB?Nn;5ylRSL!M1G!_MpwBJ&sQ}=zLSi*NJw}aZz4dIh{d;8A*6OS?}0;vECtz(_U74_a)x12=-rq5sFoXBm9jg8?k8AeC4|9 z%C9oDe7r*aGD0Laz#5d0xn#d{DS-#Mn84x{$>Xg)@6+R5O#=g>G>vcwpLEd-(9m$sR^}3daApY+1xzcMV5Y66R9S z%nc{oMX*fe9HXQ!C75nv&?lQL6^AQX3C7LPm5Lyu;WM3Xi>`#9O4HDg815~&khZ`& zRoDjtu^edE!`(FuO#TI|?y5^4hky`ddT(PIyy+Qrij1SLT6cOMxC{&4iK4w`OW78~ z)WIZhcqdK6bn!>->l;2oZLut|f);J2KXNo_MeJ$Ai0K|f?-8k>@87=&Ol$xmx|Z}4IXRk>o(7NSN_Z_B zfWr>U3SklMw>MXj|HyzCy4G+iRe!L^t)-*$*o^j5S(!`Go91TOTKN6Q4|0x4yj44D zT3XtAg^HTmbqQSPJ!~b!#pz?EPsCt5W>p}Qm@~?$;aG&6g2HI^tomVBpBq09PwU%j zb^_L&jPI_y;jsknvBFslKg;Zma;o3IjD$ytwOWePP3cpd)alK}@1o;T1qKy}7qwoA z`59y$t)?77bMWy^yOJdltOpOPW~=nv8E_SEhCr=hXc$#yH-IF%5tk)6DlshRqaMd& zuupM0d;p$HgQeE$*&L!p!X_aIwLQC}D1bik2l_rXUYU)2(b^3ZeulsZ zcggH1KI2JD z>MYecyXaFh_3)^tfAC#C#zpj%;$tGCXDaxttWS^Eu|pigpV!6J7k&FQPNNYnRBZL_ z^&^fHe{vKum@)OnI=SgN`<)}lBFL&K=#%SDpFWLCNr6G~us2t&eajr~+#!PG27vc0 z3dzNAK7yyF%rmpIVFNPo8jg+7QK`DG1?y3*I^VT3@kBFA(zE!lV+HQkj8~1;r>3Hi zeH$MibT}{mxB@8y_DE7vQ=89xc?QdU1wXO@($W5u;?36&h=W6|- z!D zYsRY7$0Le~nmP=)J@~ScDf>+%7@dYKEC+LEkMK6cf%h^g&TFrz!=a`(O~K|U0Ac~`b$)I1t|+`G<*hIQ${EAtHPNRo zjm)Pm>~@J$8dkd#0OtuG7q)+Y>F8*I@4P-de)4lo!~`56A^)-@ia21S{2|3v&b~6J z{k78?L4iPT0I;y)GA<$E3B)&A^QCrLCQ7JnMgk94kaPF7qoeAi znnXQzBBu{Cg9R1%D40VxL<#DFm9J|G6?nTrwvluM!}b=34ER(pU;fAl zVEf;)aC}0n^OJ2qSAxa8&bBbavg!HR1QX9+tB@%-1}$RKGBZOMD2B=%7{>fJRV#+C zQ{Q&knu_E%2e_5=H0#EnFPHc*>k2W93-0gkTp+9TAM5m{N4sAW*#+x9i2z1*3m-P` zf0#u|3AaaJ(rCy>>g;rME1ol$G?Wu(34Yt$D!)NFvHFb-T-XV8sTw znY}sbQ-ahC@s5{Q?xprE6hpbiC)cin27ffy{FxF0^VCNDtsy_f!z4kvf^R^1m*!J zj?ixU1$Zq22-A1(9t9xUxVLZV=N*4d>aLdS@!%5?ZQ9n%&)dLt2et$%sEWx?rhsoN z4`EkZ-N7IP3Bw?A)GIzCTivow7UYfs4yf9^0Vk7_lXJatv|>Ckva(WawUTfipDF3O z+xvUry?xaPFiMw?tUZ?nEub1=4ea$Q$)AvbOCEGk^T}2D?K;K=8zt|gh#p>%lw^Y2 zit0Z94RZYjNMe`*X;>Liv*-=gko3_y4!k!cAH(jnRX-5U!p}1=rohL|y_r{(W{-fy z&8OkvjSdx~VHTJe4;X+!5+61v3SfO-VR~WqN%0z~prByo@y@UdQtH5|+JmIAUW7i5 zG!TWzb1z%%GdL~;!#2G$Fw`XGyT$qY+nZnj7Fgh{-U1~OtY~uHTQ?(S5(j@E?D4=u zUTR+b);a|+U(tm148WeiGej}Xk-sBRs#!|O03LY?;vTdl6dW81MrY)aqLld#Fi$`i z!DzeM?rl9i+V?7N9&6|8Ou~p!V+aAo*a6G#CmqOOG55LQoaJFBb?F4`Ogre67 zNU6$0fS0Jo@6~Hx64w=AaRU5+E3fulAL&4S>(v1KAgIv5V|eyeG~HD^KvkcH!6(#t z7g%}SvhGpj(s)liIt#ntH( z_b2#n;SNkdr+0OIraF;#vahi%drPGGXV(CEqEcAmfq3w@!b6hMzPtWo4a!hcnD0g^ zu9K~7>B&$UN!f$6y{fJTh{6r&KL_8atjV{_CnW)SEp8v8v$}z;B=73?@D; zHP+3W!Nb|vmM;>NJ*dyg;fw+V05dq1zS~@Y9N-I<3P%AG1%1Uz$)WMYJyzw?p=FQo z=O*W24V%}&2t6V296>R=)=nv2UXv_-C?*U`VazycEp~E`q8K&C)B@$_&8)jaOx!#M zH!@1!_cs8(@eunf zq__n%JOykmhD3B^!u5Ep?IZyEMnl&YkjNo`TiuF=mzV8}aOxn)KvID$1TMIeL#qFW z7h{dFU>}Q8_34Ybd^Y%EV=z?FwmVSTDRz$rh|#rJef&RqR9i z&SynSFB%atFeKzcm{}#!8NZrdY}U*Xkl(jtNe1zxa}B4*Ya0M6F2HTRefzdI zoHoG6kAXFl<)j4ghoF4VmC9dFjv|HX0{9AHXOkPv&!0bjpyqP~rk1B#Lqc$Ch)z*3 z&(93nF{v}0bt}72CLjd&ba&b~w) z%E}yQslhTk8laK{q27sYu=^Xv+Y{QE0nJA~VF{!~jCN6`P$hZ8bE~uM7*FxwT%Yr5 zc~SUo{O?Jve*Zo!pOcY=Wo_$q63GcQC8a4mF}SC%rP1IEyR$rm1ZZbqst}BW5;r#3 z9Y;$8$Fr=RQoF)(r)XfhY{0k$jJT@;k0wdc#lv3pYFaQh^k~4?j|2&P$=*{0Kri6~ zZ5Y{gyhh+#mwf1hX>G+lTH}c{qcyDcekQ@6^77@(ChlFx4M1FlsAUI3vvwPNLI1mX zPu5!l-eRIsmzUp*)Ch^pI@JIt*@m#D(6g`~uV(__pHefzqHEEf+_qkA@vdWZFGJMA z&A+}-9Xr1!kd%NmWb5LI3W@#fRavF^VW@9)P8Wu27{iE^&(~RNTzN ziBRLg=XwI|bjKm^Y(HKc{&2t4`Q*rlQObYNvFfw=!mAY`Lc(I`0z|P$Gs6$Bq^c^f zrgrY+cn$3q&jbwC$I?<(N>Bfg(K0*TY>Z18Y0YL8ytUw(20+c0*48!e(qQB8b%eo# zf3?6?m_SL#s#)qH=8lBGrEOowp&z;T1U(kDfU!L|5<4M}kV9evaCm|bdo$Ij4F5hM zS+M_*)zP5_V#98iPBB+&3hHEq`}f}rq_F#8pVp!nme<1!`G9G{LOHgzX|$|*1zzhM zyK7<+3*Ne}CQiRT5x_6-x&?2mKy~`JVcGNwChPs|-4MnR&e*Qo4;x|R?%i+{_1m$x z|MjVTb#8v~+QP$8s74^$Gr=}D&tbSCaPs*o7kPD8eEN0(W^6#sKQZjoux;x~3!Fj1 z@eB#%=#de_RXb};&dJWTmk6%_T`d%nl(q*fA1dc6(&PbNsy!g! zXwRjnrD_~~DhUNM777y1-?O>-T@(ieV8t4mZoof7ByDCYrJhgOHTbi6Newu1(GrKL ziNc0YSYua{2$2<_gz7o!DG3_@Ey$r19>$P8w=07?*GyFDx5?7^Dws=k8C zN?KUFSzL4cr-L6D_hokpza1XvR5^G_`21muVUZqN@B~D~c-^&i)pNd^71mRdAq|nV zTTd!yBk%?+-q)`Si_D6N{9sxEKX-EgYkSZz2!+q{ElFZv>7-I9;K1GgWPk22C;>|I zvp|%3*Dze6?2_vk%)+7`^Ma991R@QG{gk_xF~pI|)bU%1Hph@z-sUJJxOMjJRN!Ap3~9 zOyQ0N>>7Q0do90X7t z@e-tOSZWHJ#Zd_H4wr58<^?j`8Cg#x6~-mQE+awvK>=7rm=0wFoLAr+p{WE7iI&Dk zIM0%kJ5>*Q4EE-rC?TqC>YT_KSV|jM3V#19pW5rc-r z1?W3Qad&(fOll|ee(DbsG+-P!r&eK!iZ@EBD?{Ae0bN z62Q+(29y~V3c}_k;3ehdbT+tY zqJJW%=A;C;OC*{i`RLwzl_tPOz)h|7Z=MzJEUMl4WmgGvqAt_XqEkJJEJ&wB5H1DM z_FfySLx|Nn$081B2l44~zi5Zea*VR5ktXb(iBSbvy!W8In(`mSD$ljCns_t-=?RbJmlH^&FVfIn}UR$hc zGyCDb!I#s6-FNuwe(4_!sm+9~|fjguwuI8v)#om~~j0_AbT^ ztjM5iz401CV=@?d?s+ZUCD)34GDt2k*b#t=jF>iw@nGCxHck6;h5BIUlEQd3{qB0wzS@C%{-GfGO%1J5t) z<&u?uyo2x*(0JQ}I4$V&#}a8$c+#{N0F?)!XR1E=njJN4vhF$#+@DP-fr1wn_s$HoplO1*%>+T&cz+^6u<%Z{p$_ zL$#rYEhHpVUFIYi%`~yJGQrg?NG1%WGSX**!+I5nupnp*qL^3_jvWEX&_q#}+Gm5p zMAyinHT?V@V1)67Kshl%RINKNQ{V}5^75L2c3-v{pOvODIlzoN z!h_rc#s}H{dU{ZFDr;%U2FY{fw={W|TE4at3 zpB%3FUAw8{1WRCN`7R(1eNVgJLL(D`7?yj;JQA#7pt#}J^Nv}Vcq-Q88L49V@A_%M zA!br4FsM_|e~z}=g7*DAvhI70-S<v7lgEUaP5xz6>n#ZDMxE!9ybgY_=pwBuq&WtP0$_ZbfFOam zg#S!w#+A5hR4k!%ZslqAhN2e|2r#1uY?b)5CV_UhQ+|$&L_zh3GoRxwM>D!>M8j_^ z2W$e$6xu8|U0AUgNjTu*;AitRuq@zLHB9o@!eQoK+g3s1Tw}wQv z0ig(r{tM#b)w%}=fdqWJoT8$|)_jk#lQnc~p-h3=3oO}@c7Wty$0|l@4Z?Iy#BKi) z?JB0kmrNAjYoG1Y5WhS(-^u5h2n5LlkV8qY0Bh`RT_wGS{E+w5B|mEmEf*a&X%^(3 zLvy03QN?1DYCL!JdRJmMmK(Sbd`9 znFaZnN0OML0v+z%vTTphfbUM20f*7;_Ws=~;=Q8yp|aU?2}!(Qd6Og?T<XYj1c$h4`h%_#VST6qhEstP=i|?yGgLpLViJr|)(0T_7x}bsQds8m#Wz zL04Z$_}icIR^+5KZw$gxQd3g^NfYqskSm~C0%U>{D*Fhm6X z{?q4=lbJfZxtAu1;d*p*xLQ6Ldk7+e?4|4FbCpS@9;4dE%cK^nXTcKVH~RZnpuNo*o+hTPWyeR19T_fiQ^bJ7 zS=n&uqCwy)cX1;(Q;apF7->=>iKcrLUmTt}B$YMKu)m)qBnn}pnQy>IEgj@Hd1%C; zQh_l9-8k^mU%q`?F0t4H4hjl5IFu>DaX?WlUO79J1SQ+`ZlepMh*?%%9-$283;_-vZaEil z^9pdHX%_i`B&uVW(J9tst?WC{}Vf@rB&u>dEAL9#E094QR)1{ z>nxbWZKXA5;{J_buNX5~Oi)U;!@kAqn48k*md7!}dla6_ON=d%M`RfmN>* zjEAyk?gk1x3sAitNYc3AdNL5xq_A^sZO=pf9gU-|Eh@5Pc$mcMe;;Z|JiBl8^D}__ zm(nvbHWu@Xdj0tSUNe{5d%KRVbC2&FtF_# zg%q~H;TSt5#>E9eF^34?ZYhOwX5GDlG<}8X;ozTPJV0cM#EfEOAj`M{wG+eqY8+X) z^Q0`u49-+D@SX8H^}Pp@b{ai6tfcdSFh>O` z#E97Rd0we?B!yBth$MD+Ftx-4Oa?RxhR^dveHjCr7>vhAS^vE>1-RS)sGJ2sNEpv~ z<;yLl_488)5yT7@M5gLWUXd{|2;j#ajdsKs9-c+XVkLQBLfTOa=MX|m!jlJSof#W< zYKQY&xpEWWGw>wO;^Mj;Vrl5;+DBnQ+U^y(D=*qXZGi&-_2*ASIj)q|>$qf~ZhqJ< zKn#0yOpd7uy)n+I7L}$52&OUiW`#3vdo++oCh5k=Q7dxJp)_>$TPtKoVt1Mm!kv@r zE$HjvA){_3kNa)qf#eQ~AqvO7ANm|fs7mKYM4}4v@@9j@W~07o&tbO#@Fl=QDQ7K~ zd*1GvCn_za`1iRqn&tAISH+^cd{VaK1ZTkJCKimS<`Uwru7Two>cpGTW7rX=l-P|i#CJ&^W6 z85j!UKnb6}WTdSBB{F;na!)}X1}cs;xP4HoB3vm5_n?Om2R#iKQRkDUZpe#Q$k^~X zeEE_R28#uVgAr8{qgZiAz#<9Q=hYPT*c^$gUz}rVd0601tSB2CwyQte0ODoCpDr5_ zI_fkRo-GLzHHRze|E4r{ivB4OQbgC;rVbU z_8%Sinr`^rG>udsioi4#Xl_=DboUR93+f(Sa_!p=wyGXq62=F411@E9^#6&OrmWp0 z8@(b}Zn2kRWF4w+C-08?eO@)_*JTQn%th)8mp?8Q5!4xXX{WtZVgqsPyldi#DJ>qN zV}pJo>H=VH=-$njY_35&8OqYL-5a}+vj1NltkgAi7H7yd>}cWwnyy8_ld64iZG)Th zPePSli&0JMHEXJK`|-VdRQUU8GJ$bl5>`gan#R1euRV)1orL=zMpj3_BaTO7RM1ji z6w2jgCg&vzKFCnU8c=FnF8r(5zyCqQ;6pfd-yQ>&Z8XgIfM~tjE*;Y&Aq@0CEukhk z`N$MIVF=Ns)QX3i=?#?gt7KD}xswM=!fzvjnFqL;{~5YPR1_6KTfDF&`2y;;+)b^D z8hhAVCqbh3ad&9;Z(IBL4J>MmW4(n;ihwE~Qr2H-@!P~iLFWk>5R)7lZ2%4>1icJ= zQAd8xZn_R@Yyez9-v~OaaNI$Vxz`^%MoC9U0Md9vpYxwvRSgRz?j~X4OT<9(x8=obQUdgtyJ5G&_HfsECDH$22BMI-mqr$`6^7r`fb!qEi zhIS2k-H6x347&Ob(wO%a9Ana0Jl|wHryRbvP=xg&?@#k-5k&MH#%Dx zcr1V()%c8;$aE`w*$<1s(yHM%dc1@%W4ijN=*pf7b`vI3#Af_$)zF?qFd?tYAD7J3rq%hK<0-+l zHbUVy45@K!XR8fDD&5PEaZxfnaTi4Q@n|ztplyVFy-^uCJtAwk6!{q&zLM1DT$$1| zY;?arC(#ii=Z4y`q$%7$@(ep}=!!AMm!77pG8Ny*WRTNC zygw0vF?HMHtG`N7L6oO4w3?@v-~D)gk9_#cSdkTB7(#C(bOs;Yx5 z16?T;6S@VOIn^WYiww_j!gd|sEteV#a@488<9kb0+zhBC&^qq;ySKdpJMW# z#!$Y!9Dvm#0L(c;o}1lgTJa@}x+JjwLA5 zLYhpAiQoc7D`a#~phOa*C2migYsh1lc5g3ozKuRb8VS8LY;0^7`1sBN4UM!tKbt=S zwDu1J5*HsI3JIlX7Vqh)Vy{a~KI!a6!#`5X7g&zSE1%p3yA9WlDwW=gstY46)Z zQUV`hzE%;+DQ*SE%aGsLNz!oHt6Iq|G{3f{k#i?aTD9=$rX?Nb%`5D@x!tH|^Ltgwtrr^kWJnGTWJ%^rc zy$~^Lp*NLF%tOdDOOxq(HEeIg1sjS`xhR;mvyHlZlxd6ks&yv)v+&8!l$Cpb+Q!X& z1EZe)Bak_#ozBL#7aheIOY6d;^-6@%emL^+;B}=qZ}i4h*189FeR!)UpI#3+4p0$> z8pidEo(Z+@eomqb9YaJ5R-Dyt=~`1Ks?E#P5+9RxCs#|Ert&b|0z?FeAldxlu4b*d9KxcnaNVm(cvf6{W)RbRo7<=zCJ*tre$MTEvivE}Sj~|~)tg0(3FK#bl z;JsE>zRsT*NyJjtff+GjdJ^bCMJZS)sTg*%{DnaX2j4we`0;fq1DZj7$ydKfdg93$ zrWVndjy+MQ0k4X0_w~ZbdL;%0#299NKWSxZz|<>>>v-at(uBi@P9wCr&0v0;+~(i88P1*{aLa(Vja z8wV_@T!)bMHdD7-S69`uH!4o@^zt!Rw#zm|tBCJU3hVq}0Dcw08YU6XA@SmJl*mL4 zQ@olg4MVqldtIFM5JxBb7*OiP)=s+bE{46w*r+cAERWO9U#iYBD$)CvMC|IqYS{RrG6pIC^ zAISY3TA>ISVT4-=Q?MqF5M-jIrPXL73`E5_oU`YM58O!McmC7xhmNb9np#ZP%_q1n z*pAUj(M1NkG7mM)6+8G4&f}Kkqt88BJCABWN|i{e0JQxZ;mP1Ki$md zsm^=(C9vy$mYnCCeA~!EE&+1c$FVhW75R(N^*Wx!{kwW1mGd8Z)2DYC2V8a}F?lh| zew?gq!U%DHA-CVw45oeiZJ{|+7uZFCj|&eWsrfm`P)6oBy{y<LD*yu&8Um) z?4PqSz~>;p7s^o>4Yjqid-mqdP#H%*5op%oJ|o&jbN~>lI%8+J-TOA`E-T128DW-uEetvnp&jC*7&t5!h5MyUx0Z1WC!nqk2A{B zO!&|P{c$#k{6QJh3tClr>QIKW?KMA`4K`>|a3uY%-LL^(Yhy|t_$eHG5Qqhh?#IE0 zgv7Gt%MxzAY!}~2gaoUQIE_hK5qBza_oI{srU|J%_;c^@m=5W!vFJs_rfG%Tsk|)* zyr{lR>RP$m2a}P%9SJ3`BjEevWIxeULg>h;Ab%@Rq#h&05w+R*!cDxR-EScP~d|*!Q>AP zV0cncvr_OQ{JYi9y;UB$#gh0|q$mQ`rrRj2S62dqEAoFf;xUK_*FM3Gz`j1|^JtZR zVNONl(n-Tx(X@}Buu+8Oa~D*_1sdyIJBRaL#l-V4aT|J;D!^rXQTtQ5r@yD&Kg9$roChAv{)^?#)w_RMf=@y?u`XP@ zMin0)4+GaZg@sUMDRiSdZv%q{l`JA(87m@t5TX%NL)B4Icrq?<)v8u|^W4b|XA*LD z;ps~RwbXZr#y%WNsHk8XSD&_Kg_Fzs4(9nqG0;b7248aC`A9wMp>Sm9CYf9sXb<5~PVR%Ly!H zqX4lmy{gQC%nge!jvl?gRTKV3LXEQ7Sl9!@(F56>Hi|$hdFv(yby2USD!Uht#X`0u zlgF%?xP=e&hXh~di&PV`SLcn*FNss0;|STJgg(4>yydOu_BPLxE_6|p=Ve;x2|U^Ns88sy`UK`sHxdE@1mWC4HG(k(;#6OAG~z@vfZlntjAjFS8tew zXONTP0rVSHpi6&Yx}VV(q{HwZ}^0n7ULGyvVHuTKx< z3uqk??)wo=uv;&Q4p2(KECZB-Z$X^VGq3xgbfKqDBc16@Ya0PmSX%Gx7is>S%rNB)|@q+TKu^=H~s zRW!#v;S4O5{|q)mrIC5t-{&H?U=OUw9$0eOw#Dp2OChATb}Z2boWav_a>9wY!Bi)T zRuJ3OXToY5aLPX#Y?w|mUk(*P%roGGFEH%IQ|@EYS@+W$oq1@e?QB^zJ6X|Bv(C-` z@sudES*?Td^lW2Nse1*pK~|48Lr7eGbU?#QL$)}Pz@Gs(!{4itNyo-HX5&Od8tJ8R zq775LH6#7IjQLW%hdiuoKY)bgyU-qXd1&$Zn0dbP$9}ebvv!%J(*R3TLSw#M*}9&P zlzw`Dy}qEs-sh~DY!6aA%Z(yEw6{%B_-7g|aPB>${e8N}u))Oc{P$dN=p!}{Hm{i_ zXh`1c11uwo){Z_c^rdQ0^`X3U33ImEE;B{*zJ5vJj;a>zR}>1?vV2hUBR9W!y5~2g zu6+kn{6Jm1Y~~4HZr(f|g;IZN=Z=ofE0dKYk%v_D-$*!nlaQi^ zU#tGHb#Jm<3{Q=pgi1IKSG2Zw#*TwpmR`aGa`j3-e9gC*x`Q!#sCjNqaxth+W zkhN{>uT4i#J&fz%)cZjb;B_}N)>E|Ec17&O=(_Hs9-k9kdrMk8*p4$IZwDgw#j@LB z#CSL`p98rQ!ouVvt(3nQup@r68>40%QcwZHhj8zd#{U;$14a>#atKA-@F$^k?K;u; zdhpd4)^{4exrnD}r7UB)2jhsPd8Svph@`x%n79o(s6h|7X9 zN*5!^BU&xA4ZW7cbkLc*CbCNC&jQ4N4YP|gfxLS7nB241Oyt6qgpR6p%i;*~i1njX z_gbyH5uTA$hw)s(Z@+n)o6^r*6z3SF2^dIkR=gHnY+Q5V{vZ!KBjcC_ed#2vM+|17 z1%++Ym7L9J@qn=fRS$4Fp@w{lj*f++;&-Tan@#(sD-XyZ+K&|lFqBR?VroM^#}VM5 zo2VBKJ8fbt?oD%O808zL$7N1D+nOW0^7Nc@*W*ZjZQgC)I-|;7LHD8lyjRf5e#m}D z#Ik*i1FnbCDR{>tGwMJ|0Er9ZFW}~faOFT0A)^40ykP*5vm;`kxFw zaM}+{#`h|Zq$EeBorgM2H-|^ZKF6*(?I(Z$6g3BjX`nd}BjMf51-CxX_&U^2syCS7Aoq6QLHb|7j%F6NvA{c0xFv@xD8>GE-5DuE-o} zI>X+ixmUAcq@UM%PlE6@wNQT4zW~Umr;n^P6zY_H(&K^a14IBHOR(g9{&;297wzJq z|B58Nq9E$XeEXFQ{tw$23u0p6&KfS8AR~(b0g~|ibytL5w=jVP)IT-h z%;T3(>IIfjvA&%C9Ci8xE$SZtJ|rZ1BmkU*(JRRwGJz&0(9&9--aN z=Vt?%D`Fm1dos`}*j{>gmyPpRqsK^n`*_?1nWw31hizwiMP$0!LveQH?{Y*h(H5ud zb$+WWwV~t9lv5rNeKytUb|5P?$9$Jk{&uF4@;IrC;bPpy*x$-*UHixN4NfGdZhumy z#%E4>Ps-;S8Y?Kk2)?UBBcp0w4V)@^3Y-}-RZj5 z+(zu_z`b{u?ZVk?_YNCq+PaL@rkqal7>ws^aQo(W@~)jn@2zd_&7F!wyKcKaerL=v z;dOGAKX9S{nA-H~tSfY0QGBu4NQZFkcxBtC!GAyfT?K468~pW)KG(uBj8l;XV*v%A z&5vB1h@|GI#ndT}T|3gjD7Q*YCUJYxFQ3ML=6)~f3;4zIgv3nlN90XBMofXxZuPo( zcDH#p$};<~{d
g9{{s;>E#*~K%epK)x#8z@V)*Sv(YsU2h4Z{8+t_y!|=E_v#c z{;kZrE#uO})7Cq;kG|81*5bu9MCa#mPLcNc9BsFaVeEp-3#{=t$ zs|{yH<2c5o&eVO#0APoy=exx;^`ZH%X!kiHiDHj(`^#kB8ZL{JlH z{?D&ngYF!vxe>CZ;Yz%Z`LmdgYWL>E@{_JqFkDkO@)&TM9AH8}uzXx&oXvbXvDP`g zdm_(>K3Mo8Hlr?0wQik4G-y~p!CzodLNCxX-EGk;ByM)iR=XhL3-w$4WbO5h)Q}YP zl~k?$5+l=}4vlLkuW0f&cMWDMjf*U-trZEwM4a$yCXniTJTfO!}_YCz|ans&mLAC24oE^2}(#rI*Uc=7r-_c-)vOwFB6v|j=iB7 z{)tniQ==rC14@EjkkVqqhIY)ti80xqnf^Dn(_kqcW4JGBikL ziHsow2!Pb2<*sbKm!G z@3q%jdvE{23e(j(jX~E1**_3l&xGk+ym+z4jrPyN(^p5R*VWNgu?t*xy{S`dOm z$wh({ctSpUuj(J^pB_~7^bNf~*bJg850^Sj{P-m{+*T<(mi&I6v3jJ9rJvN&rmV2= z;c9RA7J8>>%$RSUnY$kn;-#C}WYET~mKMp7I2xmoUh<6>6SaX37ZYc9@xEsIUFym1 z_t~;qR$RTiQ2PdX_m!N$`jZG8M^Y67x+cXY_0ki*&Mf#2t_O?hn{IyA+{5fDk*Bd7 z0(;`I7@~e4yEMDT;(BGzX(9J>4c{Ie`q^ykPc56UT(|hw`7iCCHqR0$?jy<+bi*@7FB80!sYordVUuw z8x{O@56VbMDPZ{=*{M^fx?5je^!02X!TwXMnS7X-xStdo8+%Yzwr#tr`l(YKN%cn* z#IH9VNV`HDWNVSv!B#J}A9=RvNb?Pr>Wt4*#X;HeOclEyai;j0S4=4dP>I!&aNyY@ z`ET*Z)d|{1Vy7dvy|pb_jrHl)%)jgd9vX=1c()w5=kMUsM!!ViZqtj?Ek*otEMt{F zBKoXF&2}(T4mrveyxlL_L&r=xa%Z6}cuxRZ`RMB&y@#TwhFUlz_OIVzyAaLfyR ztqw=KE$u8oJBVFeZ_HG^Q?=sDuX|-EeabMgJhW@}w_xA_ITk${`mBT$f!Nb=FC1g` z4l8V;{=~HXp%?A1JKH@ROoHXUmv`wg**iz|sq;N-3y5t#YUH-^rzGFtnS7jG9+ng^ zv0!sG)|BHq{p{{O-YUfY7wZ`WgoG|QJLjfXW7?s=pHE`6V~@DO;KAfPGsTGyDVOMNpA3B6)_e5olLj(bZ}FQ+r4JQy z+TUxuywj`yPwRi zmGo-D8@fAcEtCUgYLZr4E~O89D~?0vN9daJa;?EPJb$j z`oPt?EB6t)#jphQ+;dCM;=uB$k$9={C1p%)9-WxjR45f(nv=8P_J_kS2Qqc`FU}4{ z<+g;QRr1#_-ch%eio{n*jekXV?b=196-Gx~slg0u+C~>!cf0beGp~A|=7+f2+S<_` zb=!8tZP_I3Je^i{-_;@sg%^I(V=g6L@!Tq`!aOLD9xj%jS1mTYZ^Sl;w?qjeow$ak- z+Ahe&!DQNv=6Cs5t=MjS{rk{p@xjW2s0Fd#@jRAbW0%%$Ds+{Yx0K9r*Cc(fvW)Q> zPQvChvsB+0tN*+J2Sc2Tp4;IBVbkP?ckedJR?2E)c_vO~ZP#yDT6>(tw#@qs3=Ay( zUOF;7CqY($k+|r!d6fLw@61Hz^2CjxaN>-LJnNghQ!MvfTK~JBq4#cWU*E>C=5Z#s zH~T166kMW6uSHB2nA*qYFMsWP?-3VNHDbWA zHQlO){e#wdZ5#fQ&)!S>eu*sZwrQJPzPI!btTM+gCNk_l?cAM0MZOW%12IWS`BIbW zbj_s6AA(Gg5PI-6mQmlO~duAErt8X0)hP=U454Z8u!wA}Ly zsIi?GTNJTQu`Nb}dM&ye3GKp5FLf_hae#@TASqse#4NPZVY3fU??mRmCO7f|Lr8k zIAbhL_^9_NKF*gfU%*olyQJ&-tDeM+9y%W~Jyc`$N(|3rj=oMl<|r-t$l%A!iioN7 z?!#trcXz!dZ&MSKp!xykmYI{OT9(OVWLWkGBk=B$8K2<=<0ADa#Z5%1^_0Dj@sRjO z{$salNH10lXgXeZ$*A_3-SLU2Jd{v2o;MT`@-)6Ah{e0ex6#C0a*sttM0O>jNUEAc z%;?V8(fmSRNzbsjb^;?scXMl%*9bl(!@jQZ(!ysQ4#Ci~v5c83q5^YU9e)2V#tM4u z^1^Ux{3&c&)=f;781gBv?5ThOJg1-__!RFZt(}*#Zqi349Lwze+}N)CE?2@YG*^q{ zewdWBH$h`>T%9q=`bmQ|`Ukt6#IP*4L^KnF?Ej+U^WLc^%$kK6hJpuTRI7vP90KAJ z3L(xbNsKreKgJXK$-il zGIz1)nPndt9v9Ecm#<};mS6DoT}}3Xo+v0R+>3rsGBT_u?Z&_kDmkfxe)(P!ZKh|g z*8Tl^WC)%nYexY%IQ_;175^4USLui;Yr4nnHo#VCWf>2fdbi)Js-gk2hXHtEb`L;7? z@r5eNZw=4f)YF{zOEuCZlcaQ?gHkobh>jdjd93~L-6dlO_Uc|^NCm~LMQ62Xlw(zS z`n|G~Zjj4e#rPbC*w+SGQq?N7st(EIWCf&-xax;E=RG}~3R((Sp`G)OHXXU0gTv32 ziEL2PDpT>2$sJjxZnZ_5YJ@xZOOx`5USI zi<3CopXZ+GX6C(C!9C%TYCVvkLGh{;v$h_Ks3N$5Y-ju1fL#pQWJ0n5k}P3mQcs#k zum?4e{}uw;$fdCBx|tv9;)JLEta|HYp2ZGC1QuYx`QLB+%Gr@cT3TC)P3UW2>}Kh@WF_41{h?`dF0aMSWHWSxr&S6KaKOL~k6wK%PH{YVpmQ02R&dAL&KhVz=H z!~ZUZV+R-j?HdzEoTw4rx5|-^$weI7;zkSv)p?_w6M)Bef(L_Fb}w6a@6Vqnwkp>G zPIQ*}-bOaT`1u3piKX*E5ImQ$NS=0UppLsWV@4ZeebPe7c%+&N&sp!Kg z*1+g;-7a3!a)*Yd;1mbC?;~@yu1j3O_KnR=q(;*#?+!G4|FQ4&QwO)vynZcK=V%hA zQi8-|4`XE`Ut_w!7X<|cl4!rCm)?m2Z+{F5$Np@`nW9f-2hFfyls76P&3O7r(HVtG zoh;oL&rXf>SB?YCb6(O?Y_v#I@Pbb-`Dk9*iJBolKcDD=Pi?jPxwyC+D{#;G6z{^- z^H`Y|q@ksy4^`w;iOl^tie1kGTf_FO;YCXM=vf`ye2k>Qf)eBw@I6z0_@A)W6)yma zzMGC*T-s=cwIwOH845OSsPoH1_4rybl^$=7$GS#W4W29OYsZgY+A0ZnwpFVZZw;?+ zLn2|};W5`j*UYY)gDbD$2|A^&4$}OBrR8SRazC6-JYsJ#Hb&9e={US@_-o(-go2Wi z65?HpFnxaMKBi)}qrdk|mhNRApF8>jKc@dSVIn8`M=drrHJT!`;+tzXicFKua-0|j zCfT{Ir>{?;^_P>_%d#@e_U&32VBUgtghrrfsaC=%iO=ozy|b?+Ye~yDo@EqP5_xHp z)5net&n+LY4;xdzJGOz&P)iUNL#zK>?j&PSS_swRX3Ijetj8mF~%f5m@7cPpUws~!Ng0&U>&x*%30LJ@d z?s$egciBApRHg9ds$dWnN%M87ur^KfJ*3njEwf zA9|=B9{wiRL5xK=AANe~0T($2hH#j$z}Dc)Kg+9rQr`2UT7plW&}hZhS%SbN$0pL* z7T0Z)PeHYC%*~$<_HE=;ay_#rAY9?`54ORweIHvghNg;tRBO2!Z#OR(aZWWaAoW-C zAV+!K!kX>>5P5-3OyiIXN_Xeeky(+mEgv~m<>8TanN?kYoDOvUva~exLQaTH-Yrb!W1E?oL3VyqsdTQ2T zC-{S7v2k{Dc%Qg9ZcoZ(Oi?^76sMJ;6J7BiBJVWE{AVkaOiWnByq@#LWMtqk ze~)n!kG>yza;$dIKRCqt)aB_tp{W>o!tii(*86#bH7;xPd{q3q12`0wF3q}i^It6s zbk$TM9Xf1U_u1_;<>N|82TX=zl@q0GR1F4(%r?642-`%}4-mn~PINmN28`f!4@V09 zNm;t`I8^{=y69nE?QMTxl3k4wC#STOS|yTrh6)_Jrb{nZ;HH>@Rr|M~z3*cq!i2MO z_5S@m8ee?4fSk}K&&{CqCl+xYT-=s#$M@e#IXox;JHk7xu1+(V>cXC$f^Ax; zaE0UQEb)NtynPaTtu9=-GV@~vH|!;Fc})#biW310s{m0qR#sJQ!P#+Gy*GPM>?dHF z6)+>W%0nMTbGiQm#S=74Nx7DX??-n(uI%aFp9==^>1>-#tF=hM<^jFnO9hoJCC3LZR_5BR{V%2lkAPWM=9@0M_OesXcnKMFbUed%*jMs8nnl8N1)HBoYI`@7FJ@RBpa>PPA!~? z{V^{@)NZA;d^i7?6*+cZ#q-)Zu3}6%+Sg3+PYMDVKxxQ_3m_u_gHeh}`~t&QqdR& z+&13tLoU_V{*j|Qc=YII?1nGt=sdHs6_1EHpXTWY_wF5k)v9wM8p}KHB_?i}?Byn+ zAjnFQbEtzdn}+j}{yC|okfvR9`NFt*R;<;l`|2!6Ss#0xUcc5#OiJqV+N^+meOTCx z>!-|((G!>ZrGP@ouSQU5zj*%q(b`J(?%%&z-kQ;YP^|3CQo7AqI~93~7mMQ!A520N zg>-=PQ9;+R1D$91Tl({XT>s+CA#EPnj^LxhWsuZbfv&QxvI;u6HpryljA@SiufL)fBE1$o7;bOeKfh?tA zFzZBgMgPwnL}T=vZGxD91c?RO(Mz5MmO1(ae}J7v0Hh}XUs3zvb7Nm0i}~(D52uuI zM8uZvC~Bo?Yh91Jf9gr^L^}M+>$tkE|H32|vJcYq@u~#8{pw1;(KRzo!fcj(Q}^PKTgEGhlG1Ce7rY9ip!KA!CdRl?{R)fqr60eIum~>?fW1waQ*oFp&yOcU`qB7nYSryrS2V z1!S_x^WqVJE!1&t56SG{YjSQu#@h^u+$k%l4{N*n9vSdk;+^5yS4cj6e18naNtMir zi-77Tm@MRUAWLs=Zy562g*Jb)$;0V64j%LE+YJc0pcp_A0Yfhu966ErWf1Zm;oXXk z8da#|_Fp`e{vF|R&?D*Q&8<8lo+P&&L`f{^n%VCP>Gqq2c!;jroXuCD+OzLshF|ud zdBCEsAY!*_ovMSrC;fBh-Xdmzh@qnij=91Jpx{4$(SHl@)p3r4hkLy6)aK<8>1=3Q#hAd55Jd>Xh2MAy zD#N*`eMT%wF;(jX=NgG4Crx3PtaoSxcoB^8v2%1hkZnHERbGwER#8P7bQ4pH2(kVIhaCcPgmKzk zHsQ6MbJ!(~Act_4-L6DOjzVJJTNUuVfv7aOQcOPbg*zGysjd;&FGP$w8*MUV?z7(h z@SIyEEbyHuc=2Rl5jE@uJer!Cm)+cg zK&_$R4S%1LvPKwe#6bppnH>7ghpzpgh%mDS4^XQ6qXl@)rb`%iL4cpauSLUKG#qv_PZ zo@d-9Kx4RJqh79NU*cC!P2AH*FPCVL-i$7k)e* zsfnhmt+Z%uK|WOGX21sd#l@+;(5XJCeDi(3H8C~q|1JE3nrv9VB{m#f<4==gIeH(( zEAyxTW??3gHt!o-5vFza7HOmEro@}}vBD6xFsUt-Gaa+h8S-igLJ1Dcvs^E)bGT5; zxRI*rpC}xQ;@%4TTklCf^+6Y7)?1@H@3Nd6yLK{5*E?HLX-UG=mbf(`es(d@n;;*m z6m^bV;Qt@2`(-;P)1f6Fll#oS+)CK{#PbXUpQNV)vj867tsg)MHa@G5$~uwz9v&D}%%yBe<6*Dl@KD_O-IJsqEn>|s>j&a( zqHr4Kedq&jB?$p?z`UA91-f-WG~5iBP$~T9r*MjPhS8;*XyJb6r8bqLk=*+hN-mj# zSomahMeS>DX-_0n6O7KPDsi76BSU+VBd2QX=%@hrNO%ilNOLcP;%s1oa)W7t!K2UOBqBCf$_g_3nw+b$RdZf7{k!p{sC6fo z6vc57UhRx%=hfsB(PZ6oUbqt*$a3^YznCZfU)d6TFD7ywJaXhp_UaCDxpN=gAcmyy zb44hl`R4qUD^X)b^6#|RQ5RP7sxk$trd#D7z-PxUpk{(iQ;OB5fIM~7~N9N||#DD$z^{9CS zjCcAQ2j);k6zF7e*Bv>;8Q`1n_4M65SGW_XHpJpdf)&mc0yK$nIK|IP0o8{VS4TiXMj0!}!*1e1dC!H{7H>{jSL zdlx_kj0PrH!tGsWPZPWe8Oe9g?@|rGo1UKYbpzu_0$^P3B&Cu*ZZG{k(&jn^tl*^|7g*G^KZ31@PvoikaI1GG*K zNH{obMna}V#wKGdWPX^b?tFL$P-5tF(rW{^ZHBeYB?*&pd@^~O$hNZ87^%GBw^+|d zEI_n4oEIq6AEZ`vHV7s`YzKq#g%p!)ko6OW1|$?;|3q9OOlb32n%<049ixgxr$5o} zipyPF8;$+iunj>}P`x*u{KXrzHKA@`9vx95D{y_a7ST5_@VYzT{~T!R5|2AGwNBLP-CGT zcE-A}(f^oT%Hxu|@@J;SDVKgS(8*5`QgHp?rqUMR6(&< zf#$T{MJdd_{%F2R2ytw`mr6~9;Yh{fD!^ExhkcURAObcLfdaqO| zw0oa_l}(%}$;jCE#%GBE58(-zUvQGh<#sE-oXs!`nLht9;Ck}ur~U2WSOdX9ceQI` zU|YQ=QEP}Wos?p8#Qf9iSMkGu8nNnxYIKP?bPKKS1?I_aN%MSiJYr{X1mWsy4H7Vk*{{5j;;}Z z=Ov8Ub@q<?TFBNV-cM?)?Wgg*&U9sDewE@o!tO`bxa6%aeRu?qq~ke~6k$KOBF zsNo1Y3SC?<8R`o>IrRWN)SynBN;(LqYGY&L@p*MC5Zus_pc~1f5NBtXrz3{|PBrVv zejtdSLiqkET!R!Np#z8~|IrUOsWh*)PkN)$0s$OLf>jW_M9;zsMVXnB6k9dIt6D%3 zrux;^ZUa8pvfLhig9V#XZSrc*l7f|2y+4uF^>Pb8eM}?wtlXizb7D$NoSf)mZ61jk z8MdE3Nn=Pa{d(j9Q^`@O{4QSqj!Vy-TgJb2Kcx|Q)e*6FdxO;1HFHt-IB~@^U@qep^=WK{>*)toZ$J{U=*g;;cjP|*>u6yb~~yoJ;v17fm?HRNQD^4O{78` zCEzTA&jwdPn_Dq^rs|akn42f1HzO$vSw4dKMP`M3$VxFAs<;=*wvkZtY1!w5SQWZ= zE)d0F$Z-y*ewpdVFaM*2I-fMN73 zzdLX^{XT1XUgt3L^YepVcQ4~Fd(PRcatInY-|$Sv*dtxbB+(+s8l}x{1!BO% zfS2Gk;qK|Y9}^4axMtmQSbcgM*1Xqf~h0)bMZbJst(pV!F!r|6qoYnNloWJdX>s(-+uJ*{09xe z(6Qv|`5#Jit9_)!W6JCKQ_gSrZ^xoueMVHLJkDw!DR? zfY@P`gns8D9y{@;{~=LsK%oN%4lH86-Uc#g_Fy45d52>9=;E(<$H}=7z4yJBMdH;_ z(O0e;698L4r^5Jy{#b(0Zfio?AdFAjZXg(LPpUt5x4RI%B^+F#gU`WPi((h4JT|+)zr!yfiEr&l4(>x0{=fCaTda8n z$PiK0ICbi^07#%lS{M#f8>s9eewiQ{0m(zVKwoCx%u?B>`|d?XAf16H@Sj>bJFBpn zYeiyI>t@Y zehV)!sybv~Y%=`HATvY((LOYk8lM7MJ*=j8W7LxtZ&aM*+7xx7DuBExbA) zEsX~Wm~(88G!~H%p+aZBD-S;gZuQK0K?7oYT!h`lh{;@R;RSXJ2oNSFR^C6Q4-z7X zxv&%)6O~G&!2?cGdUsCIt8M& z{V15ugxKVtRV|x|&URNv5ZrO_Oe~S$-vl zuaW$+pQ)v0#8rXB+K3AP+@LQI%Q?z}@Jc`T-PiyQq}rIEI-sB?bzO`XrNKOjCkLnr z1Fshgq7(Qqz-oYNB239#^YQaz1NljKHsFE~imL?Z%|Vy(;g=v1V3dJIa2ct~TIAWO z3o_EuA6i@Ypaek`iL~2PuzIDW!((Zh2NC6t)vKGx^IoN4xOXpFNCES7JRK(K`Lf;4 z2c4lJ=w`aY@)7`(I~{2Ft3?kuDB%=<#|HV8c3PYe)_|n($pz&!Ff+8jzrU<(UgqpD z9Z&r#ZCvq9?d)c#iB+0-ti^dt$G>HtJkiusJt9PPQby2OUyDW{pMt5R!_D}#v(Cq! zlj0R1pt8xC5KSElYD@``4`~7|Y9Qr_#){Xc=2cT0_&HTv^&#>qh-~X)RPD~qx!eNf ziD<~&AA>NFlbic3&McjS66T_6uotHR6>lmK?k~5Jm6y#~^{;YsH^Q2O@DG+5r~zdn zDC0@j^6+(s_V6_mQ7su0Dh(n~Y6*MU=h->VT00iLam-BPphN@|>`@gry960)vj3%C z;@*^TxafhBadu!D!JmX6_~#AkF~_d5f2}95<*o@c4h}Q~ZP>$sHxLu^4^RjPGK%lu?0 z^bZ6`PWuv%J$_=aD?EQ?U!y_^G;+qW~P6$2KYdF2YrT$Lr*3NHhD8Et1Twk z3vaI*|NoWC(h5cxLGMNh>v?z8V_V_XpM$6Wt{m}kS23wjl6hfgTA@@nyVvQ5pU*zi z371bbH}?{i;iFc&{kxWIUGL?5ADi~=i&gR@Jw^UPO2A9iOsh=j*s*8j<1UxVh1c#W zeJCRgFj=~WCkU%OQIAwVo%Sei=iNua)4E?pAyptj<3O_#CumEP>|M}`@D4L{wwYuX z2#15b%gM>P7S1kvB9a^O3M?ixeXea23zhJaqOQcZ!d%v5^AC`Y(QJ;USY-eaKfB1p zBYs{60EIUb|D6zAuFb;NzwTcNh$6Cd;||XowecFA9gQ}vY7TK0m-<(HZV2b-+wmNS}+=}EJJW;SwK$H1dYa6guJ5;o{ zv%oP3q6HEi8QGE#8(tXj0v;MnUFVKb?58I(fY0wm`X-yRmp-8y<@sbaQ_8lI1F{pE zY;z}Dc(q|!Z2X;!vun1evTyUp#Kmu7_-@3Wz{h{Ub_))WlLDd)vKWyMaLqt>yq#Bb z=#qv@XXy?a#R<(BE@07!h5IZlnav|o3$hl|<$up?73vt!pA_v=e4}xD0=td+MNv>T z$IzHeA$l*ZYWMs0Krm2 zsMrnGaIp7ca<#s(@mPx+FXcu!LGYShk^&;l9kxU^gmAQ;?>3cp`DcGkgtvltgAfQ{ zPypxVvpBf{BAeZ2@`KXSp{c2L!U_CB;@Bu;mbh#s_>&14$^`5Kw;m$;t*(-+gOl7UE3)@$aA1!&AL4ki1YO zi(4IttJ4eX8YgvPhKocHCn+G(Zjy~nyrPB8L5G561m>U$^Oc1=7Y4ODezdT;K~vUy zcQ?VIcY=5Q1a62M2*l%P@GjEXBUeu%VO%vHWWY73J1JTUv(`^{ZFVi`knfCV2k!?1 z3Yc^l0d)4qlnM2f6&8lz5yxLaGla`RG3tIysP{ z&q@}ATzOa5(Sx0#K-4gz5he{(vPgaiCIBmWBdW2mZObwD1-&&pNXQdWHM1`MK^ujS z#;fzZeB$SbOoUz;LZ0K(m0|#41jLH!F-FyuN)WaLz&#JCM2f#G-;t})p+XaEC=-lY z7F-`(qK7P|$pEOx^FYajhyhs;+R%ZHD3Rdx~X8hjP6dkGAQ?z3+R20UPP00j5?%G?ZjYD#e1 zzR}>eL0zZ5wy5g8Ojy3>rqE5h=7QDD>_JnUTZyk(Zzp=Dv8rnA3Bc&l-4Q{vZgfE2)o(B@vfI${~=2~aA+M6B%Snh1vJbB@~%RysUlIKX?ELZPt3qJlaI zX2GG_)!r$w`T6-ttkIHLu2RizCSlu}wTMjZKZn8la!^XIYN$j80{EQfZ*&gR%x*ql z?@!w*qa1)IiRhzIO~aoOTlmtSJc;h^^KEmUP^Fm;s_cpV&`D4PR#q=xzI3wpNLbcP zv}m#u1vFa{cUA5yzj0pO3;78_TMt_4$O3g$#;z1CVa3$Ws;+X<5TnCr<3>+o4riS< zHc~wEoYyK2sqi&rPv-SA*&q*d(3*#BS|}^hIsUPPK#jREm)A4Ig{px5<_}sw|F<+` zBlvLw<)B3u^%S}RZlRI{c9)Z`|;qIB>187))mQsCud{YANaOEe_+#Zv~@Ccak2$Cu;qx*QvWt;yQ6`X=h1!Km!9|5>d26)YuqZtL-LN`V%w&AHK?}8s~rayz~7_7#bp!o*(#>F zMawpsT&Owjy=`uYOW7%nNCPjaaZ6<@y40Ci9Ze&yH95>P%N6X1bGNl0im z=H{DF;w&!DWikZfTHy(*ggDso_mJX4Tz}G-q5$KFS9$gBl<3M*2;1P1SoM;>{J)JZ z`KzHth+h!pz*bKG)%$FdxBqsAw8bmO677sYxLZ7=XtZ|5jKN?8IObQLRDN6j@t=0X z%qB4{Tgt|2YWJ;LZW5vqo1!2FG}+93xh5&zZY9EGXt0;W%*{S>=q9&{;CZE@oIFzg zNSSW=A8NG%MI}UXqqg$#*P+SlIEl;aQ{U!{M*B#-Q9LfvNf#q_E!xu(ZAn6+Cly?_ zPm4(&e88znhRO;G5HT_Q(A~&Xc&L$di9VLK?mBZnzp{z?)ciMZFkvVpAYc<2WFAhO z1H?&+x;hdYdi z4~Ph=K%%UF=b6QZH8~$huosE|rv2VmW)H6hFhe;?a5Ziv-V%Q95(ysgd83Yb9LP%_Q zcCh8!Edk1nL>MkC{J3!A5ce7m1Zntxdq&>&JL5%tRBWq}=wxDIBJyYzb3`Zr zCYKl6d))U$IW(2anu#ysPec#*Ue|~#`Qr~hM3wRzfj*kzF0V3|s`r|EkE9lFoi3wJ zSmg+2akO#Kq2MAp>iN^I2X1=fNJAdU8$2a~u_VY5=+eNQp+O{Q5e1?% zST1J%QNJs7Tu0g87g@2IX>vhTx3Pg7&PvcSs9K410S$%5-oH<`HY#cd;vf_N5Vh!- zIgg?hbgFdLZadL8PV?2&H|m`){&bdzI?e~M znCMXKCT$8owwbGcVox*Ofq#=Se}o}V|5c*v_r-0(u?ZFYzY2$_RYi`&)*&7&^Gq;0 z7rYM9FpYX5{`0#bm-$t3kjr2=qmTC@@1e&Dlu{bO}4TxC8>Y0boM}7_-H^XL-~$$*0#_ z3yS8&c~ssZ7ZD$D_G;6kj{({VQcvhCxfzBQulyKsMQzlhYW=y#3C2`U3q8v;U1w#< zwG3=pa{M}6kLV);$ynL5`{vu4wMh}rs2&hLU!dmD-`(?PKG5}7p4R+>0`MZ!@wasCNlbvH=v>{h8s}K3tL+_t<{>XqSnhvyw(*Ap@#7ThL zI2!({H7dzvWb?DW9BtSCYMw)~^bK^6wfFTeKMg;UQJuNt=KJFS&wu>q$E8GHj2_(e z+ugQnA@nxCjjaj>=VWoyw1xGyXk6gCv^#8*y9oo|ao$Z9EZ%0cKP$Gd?3TVKn@g4` z^}eR=mIFl?wQQ<=r3#Ctl-$>#lHSXY8BeOJyWNgdzMSdXl{sEIL*eVFm!toI>*S9U zezK1q)jhi~g*K!N?=S8$=+VNP0)>nklW17L4p^n>9460F6Xe~WSbIn~2C93Bngq*t z?isgi(mO{_Pn}#v*DvQT{bUsz|Bz1bD#`zX@DJe=rHIf4UZQ-E_{C%>IOgU}T47bp zv=oXPu@O)$)IRsLV|OvjYh7k0nd=GEZ#rVwv_iYBIfN<~4EbgKw#_ev7rdJ*BHQ7*|(7f-wO1}hg zweZE{6UmL`Pe=1q(Dc3Y_J>&KTW-<1H3`Iwm$n5@egL;8f&2jV74^qp6oHWk9$Ba) zAt@dfJ@2sT06_sNBO+4em>W9fS!$|n`kcfFr5KweAQFJs$3>)osQu}%OGP#n9?8S^ zPYoZ6=MUFN)0UHBL%*A%Op;?!2SlTZg}pns9re{D5;|E0n6$RkNh` z5GGx=7Q?&1v*MH``Siyn7OEbLilFW`G0EiDPC3v(A=VH+)eDK&YcvG*!ZzgK5 zoVN?%6h(Y5cGW|xK!Ks>Uxn%$FUW*#X7}p{NTQ9d@N9!}4#R?L-|~q^5Rwtw1?47t zzn$0^SNvi>}Y~L@$E3qex8&0E&a@a$RS%4>*gmbFJEdg5mwhzyii{Zictm z!mPHEfnNTPA1SM<;76@yv3X2s=#SY@G)m|sJDNtD5baVFjZozRB7B~68L zOd`^Tra4D7z!OI+3(--mi?1+m5vCQ6my#1O$U7`P985SBP z&D_mc8_@j17;fo}Xc@#x2Bya>kC#5ly=$f7O5uErDYoB-8g+L_Na5n+wBQhA=sfFp z3wTRb-bGv9RXbOr-*f#pqV^o2kD`l5-sd-rK2GZ)wr{138QVE!JW|1^LBPrI4{u8 z!Tge41>{8s0jQ3-o4o9p`G(tjXj0OZ4dz0rSk79c3RuAMd*&7KmPO;UaMK)66oKej zYZ)BMFK6B?cNHSy$9xqS34q5LQyQ%6UW^0R;H{u8Y3DxwQDjTQGV2TG<#JKo|GWS@ zRZ}f`e@dmbc0ZC+No{D^$*5zni%mRB zro7fJ5dJXpu6#x`^Td7{m|2n71xEJ4Mq=~=wI=%ECbfUnY^WHRnY+y0aR!F``QmG- z4>R2)64c|h%kdxr?Mdf`H^Ugx)0Ss@FDZ%8aG+)-NV?XJWm|Fad!BKXRB5XV4>-L*VN%@i6I_7j^=SNy_?I~>q$0s;-{5f=*$yXxH&v6e7B z{HzLPu72@$9~~tT|AuYD&~vc-5{9D>rQQq0G-J>#fX*Mv`u_=0QXB(>03z1e-*iZ1 zt6h@gS-&404hzTsoI=t?BOmdjp}Tf~(DadE$52{A0uedkrL9`m#UZkDK9V6?=MSUw zAeVG^*45;1W*l{gxmB(U)Io(A-gvzfzsf_(?@@hvLI)EIbG9v&i>OI+3jT56J%Rtphbr5ZH zAFM_2xiYt#iC-%72Wf<()nL67LB8J&ULdoBA6ZFjx5}D-G`%SoA$v1|qfx%$YvH=w zWk2uGG~>*)Z+|Lx zJ9F~$gHSG>N!K`!Wtv@oy9)FLh|R$0rNFZS56bj=&N!$70LMl}&iyypE`CMZrbnrX z>k0c7Lw-yZKoikC>#x@K_V(6K zDUUZi?`_f3bolV~hzR;|Uhh+|s_A4l8P}hq-OEF_Uxh(6Ewat(5jihdx3+FFlBCN9Bq7-P%2Co=^w6#tG|C_c@ zCQ4&_iCIWwh_&**?b*?rpa1Uvk$^0ZD+gUfJEPILONGM2MI3pgv z7Y`{aDdF)cn_%TbUckRhEl%~y@395JJfsm_%0NjTb}|GH!g)WxKgX|~I~PloF=}x_ ztZzReDPfl5(>S)$f)A)r79T?w*b(=Lm2 zzSQOsNe7#T1FDN!J5S=Ne$t!pcYk%LV?x>pB8#>_pV3&c30`Xomb&d7I#HbDo4aj}UV=186gJFTNfH@Z}OFuW>cU~2~9Z-_y zSFY?x;ZMP`2>=jeAe(#6vfDRe%xamNoi3)a82byYr=ShNl{pjDEIN1}Pzabpt*m9U zVKQ1;TJrVHM#6!81wFH^cE4V<2R}8)dUmY_Lm6@|VTLHc;?rzRZ+nh|#8eJcOppfv znd-*S-H4BbRV3T*g&pE)`OD3z%0qT8v#F6$xxct-#Jw|rX4&twXj@BGPtKXW7QJ&6 ztE7W5su|S*?HcP(CQgQ0o`Jnh6vqA7c;p(YW?GoX6HXem7Ccit1gnKKj{=6gl!GbYuLMug;;wCfLZ$e313PPQ5jAGTY@zsM5grhvn!RIn4P~_3>Ee z1q#OWYDB%MJ@E&ZcU~rx=(D)g{1xJy#hGT#!%U%t9#bi8KQP5QkbNbGo#dWsE{wofz5Pz7DIZ(|u zUzUY81T$mW>Y)x2+|-zD^z`zD^~mz6Ii8QN?(p=|8>V}hO3hmN91Xwr4_u0jzy`}t z`69&tk)SexC@sibF*N6e$^;=NnezI#s0eNqPoAUmF=X)M-Z~=QZ z*?@y2Ba5p$8a-2ni-{YMD*)iZ;>pZIMl8g_vy5RG@S?%&GBi|Gf@`k#!bmFsF5q+2 z+KIF3+`$uj5HQIM;`uKb<{6v>9{UfEBa2vAkb}xL$jYbPyMBly&e62l6diGCwa>In z*F6lBAOv6Bdi+8}MElJSjNMpe`;iFN7Fp!-aN|DEE>eEKcSF2}ryX8CBmw+TKtKn{ zYej*pZ+A7D2p$f8_Z-HP^q^`$F%n>$Qw2;%bW~sf z$N|o{I?njd&*C(02SBX`{73H&{>1Rc(}BF##<~oVa&q*kU>iuAf?J~k70Pa^cLOuj zp9fqc_w}4qiR8F-;ml;t_qjX+b!vqlsH5q|+S`pZtGZf-pT4m=V6I!$657EybS~>h z^3uw)Ln8HX+OL1H-ar5Z^t_PsbPG>RY>mUdD~=@z!F#G^roc}XGTaQ5a0lnGEcGB@ zYRLy?pCExcSoWm1YGJ7g@r6`eb4LmR;L=>x&i<#HZ<_TCf(8abXOEjFjh8Q0I0@KAw0(5++mAG zLlzTi8-yJOi4WdVsAFEX2!C*My5t6tu` z^vRZgpzC!1hC1k>Mmp2O(SC=lU`(eWK69!T!n?8jC80PqYK_B>NrtMF+Lv7H zsATtVsP5Q!x3*leUS&bmd{Ha2NwhS}2(903^DQ2w9F#z+sNSK&;AQ+*=FGdu&|T=f zn`Pc5>Y!iaw&h<)F2R2;7OhJU-bI2JM^O&&HB#L$zVfy z^<^q6{@EJyv$nxkj;5nKi0_|B{o`i^9vO5h2+bwYkqbWmlHS9*L}zwybYU{=hD}~u z(L!2>5GgsO3^GTU1@;G zLlZ1t+G3ZV>`kqOyMh}D5N2`szVSpVIUg1Y-R$Vkix8+=*(NpaR&LVPI$LOnTk6^o zI74J+x->APb^UG4i?#i^Ows7;>kwfYf{fb*80)^)!&cWY6@7}gNqs|5-VJS-+H;^NnR!R`ncU!4=iTuo zK{A-gPDnvebg{_YrQUzRR)mQV`2bzO-{5$mjIPGrqp?@7d}&r37-Ai=k5e^G?*F6f zPr#{O_cvgCl|m&{LS!mawj>D|3k{T+l#I#LKq2$gWJpqkGDbzE2$jr9k%WXKQ!-~x zGV|Wg(mwn5|6lLxTGzhL*{7qmzUz5D!~MDM`_myaERSEE@#4i5)lEx|+S`kxoJGNm zi(~9et@u?{P5NHeJ7x=3lzy^$pldhfd$ME3wTW<4>+g2iTU6|66Yi~hq(@+)lv)HK zg0~=SejT>p3go3fS&O4ffQL;t1HU=uqF8|l41pHVCaGu35Mta0Uo;?0wru~HC%s{` zav`Ymi*%x-?8=L*QWH(zN9H9(Uv8m~?r5a_!gO3A*lU_qV$^qk&NGJhYb7!k*rw{3 z#2veR1Kw?~9p+=)2r!_!r{1L;bolMYjHjjZx9r*a;EdyKnuDkwFhS-HP0h<5!tp{3 z!3=fQXF=PyFwc(d;(!!;V+HelUV2Y|UO5wwbBu+fuJfi_@4P#n@yJ9Xp?Y`<0P90O zwXU8Um9$OOmR$}~RXY|B_?kHR|B%LaG%wVL7+{z3WgVL~Dw%e+(6V|<5YNhP%I^Y} zgoYQ`K9Cz+{j8nr$V*6_h_ZNcAQ6{fysD+>viZTyUqFlTOcC3mi;z3F=R>inyNaqR z*G|pOsEV%m205M=sJU_aD=RA_m#6&S_?owU@le$yVlamByr;hjpkoLeaqXm^M&=mX zS7%7RB(}nl{uMsiMw&P%U!ESrDFMEOu#cU_eNAqR=<{H2Kqf;(w2_nZ$Y-10BNp99 z`b`s0aiE~qxU!0k@pL*L~)OapEC$pvSl)G8?Za zDn%K>DHYrfs#%}Q>ZhR1;pm`8hl_FIZ7=;dKaj=*dcXGNY8G`|zX-*E1;TD zgY<@&Z~PH=JNFm~L`apFKI5;>V_s8pj<+H+_s+A=vGN1|i=6V@!$1N%VFysgMh9D#5ConLB*GVWSeZAvCmSfh$>B|2|$F^$dF+`PbQEOXsl#sw2t=2?B z`vaR9US{@5R>sBfF1sQAJ^>t4%e21z)oAOzaFIxQRci(%#D>+qE z+&w)iG%f$oleNqsHhy|Dzf_U`iOFMrqI|i3HvN1d>1A2;ZMdClm%x*Hw=FCyJ!u6s z1oiZ^E9|p*f}Py(F;KO(_Zf?2_cy!&pE*%2s-ix7xn79HfiBl7(>?D|araD2JR1;N z*7%k3=(OPBG6RC6v;Go@ZbHJ|{Iact^Ye!jv&YdMi zH$NZPg>M0r1Wga!`XN@g{U$dA0V>kR{jRW@uh&{kg!~ z+s-+&lf5#WK7F3)z3%Gr5$VJoZtcGoP8S8Z+TMz5i10_a%eFbP>Z|GQ=R3sRW0%^K z9!Miu_tDGr0>G}`CLnFh~ z|4l=l+b}frAfa!OZr^EplJKA3u5-P;&|n8nkAe;k1$woj4}x(3Je7b%?T_1B=s6*l z27`cso?ldK_js9r>YefvBbRt)?{;~hNC2FMj1hlhaV(IuZcj?>U}N*EEOH~VC5^fF zrdnC{X6mJOp`6E939tgnd`NGx39R0dZ2bCX&M<1F?qxyz46 zj(#tu0f(g5c`j&t5oTHs2m?65j9A3@fTpDWsw z|H}~7S^Iw9>*ak5oE(G2m!#m&3(*-aBh0Cgmv%j8e(+iBk*J97(qk>pS%w%6aW`C1 zMgM*0(7x50FIQ!33GoGyACn%Ga8xjhk0a#eWgbqNn_>K1eLcMN%1xi{{c_3c-|)Jh zt1Bnj7+U(W8&8le66DZq_TaXGI}%9^F>X=8l8WvG*wm{z+D=D)iidR zY83JEvcMTB&Vw6)4d&jev_^MD0sB3>`ra;MAY(AWT=uNxWg}uy{mFMgkQW^nMn~FJ zvv&|K)vi3fz91&=b_QuZXFOt0RBnVzwj^a!82S{U-*GlU3C4IJ~} z4G3ciarVxo+<#Ar%Cm&S6)kTfKb%W(5fu>C$NoN_SXdUK@c@e@^3$S!-Nwf)4B(u^ zCpgJLqB-7RR`y6QHwR^LDc(?z+{so@8 zQ+E6%ZI>MeiUw!S0aHd_4D3HfIRphc27zXw0u>TCG60Tpp8>}>|AHouDr-HdO{8+| z#5!_##)*R#Z700eCLR6gRjP+OkCKaoz;A;Z3PXOf?5gz=v@JQMuxb5G6RN_Vvq)d)2jwb58i zOT4R|k$|heKtv@6I{IE)v`Cbuv57f`39j|P&VVW31EnoabJ#PyNeC(VZ2Oz#pfyt{ zLv2N&040B)FGPF(0}t|*Qx7A*+8b0(0M~%TPD>@fN~C% zz_=`w-JxZ*+iweA-E`upeXdxXW=YRD@A`RG%I;6>?Ml1z_{RPBo$|+F=ga@4#9OiR z{-%YCuiq|Y_RPR%Ti)aML(5(rJ6U~~<9JURgJCU~AGw^0(r0B`orxxxOg#OYH{8%S zHN-)vsQzs6Z7ZI4)$>zVI^R4Ehp!&kfhfIp$~4-K?MCKdz!@jU+}3ehNO&iM&L7xm zA2!qbiU9!ir>+1^LY?5F*jo7msrNq%HnK-{c3a|qDyYYH&4zxipR12H>0pHF(r=xv zf=Q|e#15h8#ZgV5%|hk(+iPP8a(S9@&P7P8AiyC$I<}JBc~ZL60@Tt}ZF}n6xeT6?f1mT_PighKkyg;q<6EWq8qZAZyzriBbXs1L zEk=$x`8`Xom3B*qmp?!CRX0U$vhN&xr!(CkI3dL?L^Qy!VYxBjabZ876X%PQ8!6v^ z6>!Ryj7A5_*l%og-IOuD_GE-`X8CZ5()=3w=oT7hAe{)NFv)2fJBP8Hse4z%^$Vg` z)<)`o6NoriRHCFlqLU*@%jasEvXSTh=((a>+Hftn3~>bhX_{_Gb2DTC=Bt}|m{x~+ z6r}kJU?+lOj&T_!9pW98a3tP+_s+HPg!6r9J=Od=u`T`H;?q~XwC}&lv#lXV0m?%b zqC7ka7j)r#y|)7am23_Uh9~h8Y9SALqBpMP{vaquKd1)8Ks_< z!W9f0DNRR7BY+;K@Or=ab~5kj1m^3}tdUw`5pJ~s>;o|Sw>}L=p6MSy4yc+tG^NK9 zi~%T3os~C5*#bn=__rK3Mzx%LUkZ;P{Gn z%?d~28e)cYgjq&c!@Q==1vCudIe@mjip4 zb3MFZa0+n;Dk6ZWDYfNX{f|y93Nb)+1*a^g@}+kxfHVA=fRZKnW5^-Ge8&F5p6S}c z56k9E@9zG48MeW=^??SCE1Z1Jd$(#)H#Q~TxQ{Qo(zKLji2Yu#o57pj4={g1Th19JHb$W<=C~-zO4}5=XFFq!mq^8 zxnTxGl$|nPt^@pcda(9!v%4{(vDi>Aq7(DwlvSGYQQ zG-2v_)VZ{3iP{R5rO+Pl`ohU83~DsSMcylPmLiOh%3oG%eP|h7(vsg`QxJA|b2Hvi z32gV`eWv?V?qm;1Q{z!AwRQlet&u0d6M;4j(g8A3d&lpR#|1VTaNIM;IQ~v!dru(y zlTGXR>Q)_%Bq1Ic+biQV8ijaJ&Kpm+I+c}_9+BO1jGj?Cv|q&=MUr;nx^xp@q%HplQ>4W7D&GoQytFC?wW7UpP@sfB?te6epZzP4w>JR}MD1JD@C53;U|txcNi#RrK~>f|VCP zZf~bHun0dwg$m76XuFHvfZ-tbmr@5@56L4K%KXLd@AXhMCqzaYS_W5!#_SBT%RIf{ z4+qfmOLR;ybD=#xKZX#6dW}F#Q5CPyf59(FAjZF4$SZzoznwL#8D=M^M{-x#&T^RdA{p&!U z^h&zIm(`$rB%@1dX$Yf1_geybZ$>;#=iuIdJnk*L4%I3Upf~FMEmrqQw#@1P)g!_ zhnxum?fYq7+L@jEzo4+uEzZ!)CHOVKD2f^<)k!J$+8EYiO zEo7R(vhtjb^ zVY=-*lkFQE>ht^FnFP6(<{mZM=SnLVKDdLpW_+U=5ku!wNX0ow_wbcQv$IS9FU3r0Ep>&-kD&zUXrPWvOtm-+FmV6omb z#+|pFok3#>O8z8&5{Y|HKqHH;mI8p)eUnj&w_-wc5e_#y7uR6Z5oE_pD2o=OGkBPg z3;sSMzY>BpXhMIyXfTDx&K^-#a?dpr6kCQ9x!6fhT(-O8?R>buFr1EH(SuK_@FJ*2&bcXEV58yj)=v%*CwXyGyJ!(Yxh1s#mw?c}es=@Y!<4+yh@7Tn{>b2iZ z2`nV_2N>=)`E^#!IL~~Y5d!Q0XS;O>Xo#!<)4c`ssxLQRJ$`VvZVrI60-o>tT~-|w z(Fkv@jE~pHAY3qf52mo2ZraZ55T;)WkpM@uvuqsA%q)sQS41q2k8n$-{`^cq!9>gN z`tqR5!A9}3HdGlubk}N|ZfZ+!l%LJ1EAAY1LxMSRbjULh<^h)QxInRn!93wPk}*K` zs3fEVBtL?i0EQ;A7Rqr%5!?nE82<+LvfIXfb%-5l!aHcV-&3%0K2~ ze9)8N%Z(Km3$J=QV=JvodK4#eyjxP5%39NNZA*Uq*aT&p;b3qah+i0%VAmwn&OCN1 zshO9&aUM|DhH|#0HT2JT96}L;Z!N3w<1>D)4XAKFosf+KXx23DBWLE@V()5pEObI; z%Dqu5W*OI^4rP6k%*apg!!13XF8%^zQ(hI(1)3zz$J}=myAC%5ta)O_P7;Mb9tGYT z)rQdxF3NU6AU_aR*D&>Qbo3nf1z;TFpNI*HIvHOq;K=dHxo<6I19TKOunF)e>8!nG zwr|{V1z!ssl@Gfrf32?4qui+IdIr_Kt>m}N_Z5RKgzf%@4Q40C(xmfJc&>oX`lZD#BqB^RX$83$>7E-6CWa;+5&dDdFm6UbrE8&~9fm$# zhIMC?`PC*%r3)_rW9<-vS=2E>&p){Z;lsWQGbG%A<#nCOyI1Apj-EY3Ge1+)e?%CX zUH~FeJ=a{_j{jT?VNc=6m2Dt|w!8ZDxWa90et+ee{uD6s`QWzp3EzbYXqf7@&sDa~u7m9Zl3zQzXl8vqbN zK_(mL4`NHx5eyOF8GH_5p8}T>2_)Cn?9l;?TF-WW+<=yp9)@lh^SMp;rNl_x;HD+; z5f{yePM<{W-jnAd`PDFA0w){{T8CT>+)$hZ#4e$qp?~ibh*2e|{bO6F;Cmb*yOo7=9@@N}EjG+LwFv9W;BBT{L%w^4ej( z+u=uE+nktBJDbmvw%KlJ@XTUbUDKPIrb?7%Rq{vPta59cX${!sJ5@3HhON*q%FJhj zM}be<#N0<4#Y;u={Y9l&)r!F|qQYZ7D+A*goMgBQAadZb#QV;>KY8-R+`@w7SEvtu zjwc{WnoHa<;@%cs{(Upg6g~MfUIUgqB^YGKa5vd!cMLDg4{wJ}8k6s23FW0U=gef8 z(slgBQ@h*N;gF{{qz+Yq?Sza>T3|4;3=Uf5`Rl>?9R#$4Q17o)lQNaP;+2;uT15!{ zMIjf;TMFA$1D?Y52HW&t4uBmtXO08fCGMelEub4R{Q6wD#YqJAxgj}=8REGE+RZcJ z`T%Y~Py2UkF$%3`lYTfT*Nr9aAZ$`zUUC!)D(fhQQJLRhx{4CodY4rXp}mCu9(Hhx zjPm~5954idJ3DxeF!cJ4?;pH0uE$gBN#MD@0u_Ax4HToF`i#teq}Gc7564*Ai1h?C zI;6Z{XJD+~Ch@nv;IId(5+!Ex1_6;m{Fd?F`pwOhpgtu$E5?9(4o?ltral!J{T5`)TjHb zFB;`6%1ECP+q$(~Yra$K?987tSaSDp*ibBL^vX7`B?(g>ZO#H7qr65;LUW5Mx^Sjt zcu4l8OK3Kh#+ZAq`J6D{m+(^l50F8N{NJAso(%jY*EYonx*h~fsI0E%QnUj`BHA?q)qwm{8*S`05HZu!@EN+4yX5lq1Okfi1a z+sfrw{y9E~RtVa8I50%6lScJH)V2lUiv~$JJJ}F}pxy$_7URF>JXa>@94=K__fLFs zc`&fFRSO}4JRp!d>L~|M=P>z<&=5ivw!u(d(j@RqzNQ;_x6Nk_;&O?#YWN0Dq_To#_lg&o~Y5gDXy8F>{I>OEk2#zF3V$CB4h)d~R<`8^6~B!Jsa ze#tJpVm9AprZ_S*1YjGGDaOiYI0Yucs(Ub;pP2JO1%)AAUs6N=u{1D^ns1tq zHRc{39NG3QSWNSdx{gv#IZ+$TqQ#38RJ!*HItfe^pn1nJLa(kdQQzkbh6FngPeA#J zpX1tpVSqp*z-@Ppo}y8rL4%111?Q5UoM01(1v|Kg-RJ;pB6c&Pj4<~M`v(+db_S^y zB_y#j&z4qAkQ32oHaEw5wA5-Tg%ARLoAk{Ch{LX^|ZWXOd- z4h#Nfv+vB_lDO+N7Sq-|(QzP?(IJ17cGJ!GiOb?a^#nH>WNp)Q2U+`k%^VPZE`0O8 z^^gk@6^;o9_(67U@()3$x@ZZGyo1CPx?f#ruVqKyUHj(0uuH(f|3I(+pvX$ssYFdO zijpTVrKBh(w;=QSg*PZa(uM{P{ID5rSStc$2dj;!C7(VeXvp2}3S0=J_I5*@~3~MA{Ai#G#TJKNk@V8r=jaA14;X5FB%317YPITlRtvByv*R4d_?qR zPlt2A8uxHcPkc#3(foM~$l#-sKR4*mHeqRdSvKC|=N8z;FH(M>8>0#7fv!#^>!6U1 zG^*ooQkYD-tmXj21~>D?nJ^2fpAiu7i60tR92V(JK(hpwWJrKOYxLMGiPmRdaw*k` z|C<~>k}TrVzf8ONQ8#(!WlJzO$Bf>~E5A+UBE(eSTmT|x!d@E484x2Lx0RgyaaM-R zYvkQVD2o~Y)wvE@IJM)jt}%>fUcxBn3UInk z&E{mF1${iZJlFoYXa2rH?iuprXIdu|V`a~;EuEJ|~=N+C80-r&ZrAw~@yO7oVpNYSD`X!|)y&>tm# z49oVaGhTS+hx*QT{PdRO(5SGi{`m1blvs$ylRwys0@+O65}O=~;}`n{fI+m>mJ}fc zS6@!-``W#upGtSv{R0ky_w^KTA5}_#V?znvKmMl6F=IS*T9ak(i=DTt|9VmtCqGvg zSyB$fiQ6^L9V;&XRa8hZ2X~U_>ai8#p%@FyLe?p;4O6X%`6?tn_x;|@Vz}a>AE@t^ zAiiNl251{4{m{fSBT~5Fb0T)59mm*A#(UbiD4?E|I_W;ZvKNsFVF@kdphp7P>@-VA zc0oG_gwDSj#d@7M=S4PoF-$TRaeWX=u0ay|+tZe&U18Xr2~&vmvt_=sboi>{J%@IA zb^T+eLldwqe`G0A-~954p_Y>Lh3WJT47c3+9z@k)^XwlNQk%-p3}m@Ybw%ML_@L!q zKkU(vN1-6aB+NAT)K%uowy;s=XR8-BQV#@axZtEd`M_)%6_H`lw1L;)DKiz^12}S& zpE&7Z{H`iAyQyO^zq+dIu>3@`(`0bbWN`8*mmo^pglamx$R4bdcO^ijZ;67}CLnE8 zJE_$jE@!YLWDP7SsjieUtJY5Jneye8{<=#xB)teIW$0!SI`Fgi{|YPqPvv^HH3DDH zLnvJhLnGWjhJP4zNiBm_BQMebFmfVIz%j?YftF%*bF4pBvcd+HP!n`mpy*i|P*U@I zCl~+4kB!pPH(}C7L^oesx5zWo|8`e();IN?BdR#~HoF#%#m#Xu4w5<&SsM2Y@MerX zd=X(hiROlmLi%^~ES9%T5LgP4UqF*Y&0jy<&Pb#e>5_Dm34KNV~ z4C5Y&wda1`^al!S7)p1hVG&VH>VVOTG*uP;!iorm7ALFnRXw64+FUn+@lm2SAvnhR&Ms0}iJWVIq>m z>!;qGhXiX@NZD>XP$v>zPM%PZYEqvEK0-~64&=Uj(0euis41&=>HvxVRk-FdpfwuvS#&my9ti$Wnn+W0Hv?*@|vA|UKF zJ9q??SJxJi6{iEpVoZ?H59X2lxrVFIO+Jl##;Z{A`iZmDF;7Y@s$p;LnqxS@srLT) z=nIjv#@$u(;9us&E;sD2oEq0P^U(1fK>oUir6YmK0o}c`M*tTi8DAULr zngpN-Z(A^PYQ;W~lrB_!Zd%R|lepV*-gpm0hEC?6uEX4zXuxO?+m*M=%6=P8thoWK zk&JW{#~*36H~0)TOe<_mD#X}=gR~x7+{YT*(<=_bh#Ixb=6MG4upZvj9l@v>-6D#KV!+q+ z9T2Z-^I>xdrk!NBDyY6EBzE0slZH?MW+TnH=U1UQz?2V_4jOC7j;U3|79p{(wmXiX z(UjSU4PDTvsMntP>%TBF=c#xdV+NFy03~rpi_K*o^O5_$`c_9>>(^I1{t;S@gZt9G zz|^?VYXgvHw3tMKqnV<@%iKHhDL#-le>~4L@&V(-{gM+ej0ogE9mK6N=d+^u_eHE* zFg~n;(Vs`dyX#)S^TsgJq1lkM?B&4{G2>T$2)pky zi3+#*)j3P^cpCy=jUR=9BjP-G$3`ww07$XI@vGrUnHD_q(6i% zxanIQJmzpgjEt62u&!ngHup-!bLewCJ*p7-R+(qN@{B-`J0YC)jU5P-#j&HZ#Y9$n z$q^GkLMJwTIW~SL^WpO*DW-2cR_Ex+hIsN5Cy(&37WN*&KQs8xXP3t;M%1iEtak}r zjHpRML>n=MMBC6)!@!Cb1H~h#*~c^JgRRbXUjPsQF*mA1@DhP7y-o|KpI;bgQM+b* zDn{t{!mjNJw|m|<+RaRxHZ@G-mFzcsbd#B-l9%-pFY9vMpykJlm#$c{_TZNXtfy~q zsAlypKgnDlc=*zhPm(5Aa-$O!Tl$AR@?ETD>1?b&)^0d1OB4LWsgQnuGS{7|kL!ef zEQG6{x4+Ld_0>#vEOx?sp;}KAPR}r%Me}Xp>dFSp;cT8L1y6mefM!xG)77N!FeXO~ zTSv!-w~evWrw^A_|H}nHkOm&KZLTom$j6*Wt2-o0Z8GABC4`md8$kneHYtOzjA+Fh z%vGR*mCvL7F;>QR)#A1_Psw~xQ`e_!hg2>p%Ep}NW~%DxX4xuTD;f9w#M8rauEzm> zVP1nS4%G?@tbvE_n*0#wUVRH{mGYg{Up2uO_K<;;6q}H08A~6Zy!hof~q~v^2u?4b~T! z4mZE>8w*V8z06-$5*7=SCp;2)ju8K>eTqzaOL{c$Y~{HFL@Thj?wRPRAqi(U%RL)F82_g%?M3Vyiazugsb9rJ-C*T&uiRNayn)z8rwBp!(s2_RMntu>o>c zX^nZlLyq#a@t?7+Oc|y{_SyZ$o=z8cl5@XitBB|0&HxLwy*lWgtbKUk6Te;KGo!lW zV`|#2??2z;5ntkJkJUrS4*nLqBfD}=y%$zni>L&@YAC?+TH^c1)-*LW;UQ@otjEL) zc)}Is;uju>u|~?Vs_tXB-PpMTTirOCk=KoF?l4xzJRf^CL%ipYh;}=(<5%A~)Lp8` zhIdqxPY%Z1-A4s$I2dS6(k|l}&9@Z!@=&nWg`q@z1fGXPS%%CkW+;`XeS+rZSC!wl z47KI763eUk-n9(AKEQS=c6P;~EGEi>;qr>Io<;c)Q7m|LE%9AS z&hW2IwURIeT|&W5Nl!I4)Kl2nw)E`F6mhIkqXv#Z1$p^caCwEVPGX2P(h;ikCR3EG z0Eke}aS@|JSOA1V$i^Bhi|WlC%C`>?%6|FMzRTaztHVr(g&Hkvw}|QnhJ}+-SgdD$ zZU)E?)_)}2KG64o*UD$E?M-|C0)yX`pY3g>U+yXS^Nzf(&EN2+?VjEY9fjg69(-ax zJ;xZ|bw%c7Py4$&A$G!K!$&Fm1F32Qd%JNk zZKCgUMLsVH&-yhpr&o*kagkrm%bJ==587cJ33N3(@N%{{ev172E`r{2R2+++`VZ` z>t54r89N@pxnDx>pUx#VS=F#tY`i-=HA$E5N!=NT-#-zyOBTlvu8di&L*@<77KzK#fD;b&`YXdICxe2SE{O zNX{aBkeVMELTpPJbbPLXT953KB#e7#ALW#Y>Gbm^jJaxRZk|efd-Mz@)it)e4Ge6y zNhVacd2o?<;q4FH727`1lL*DGjOB7MgCXklbnZWK*YGG{*OF{^!)oe_k`n%+o1CS? zW%*v8oM-P!O7A0w!Ul%u6nW13AD=EXY0E0Tk(89I@MS6<5n0>lTRNCYPccu-Uy!b8 z_(P%S{#fy&ugx__&}bPxOKsm>IC~pCm0gm44m@@g`@lZ#9P(eiHj1KhOB$-tT@6SH z@6^dz2z-Ca*(Bk%pdFn+x`e^!c)?xVk)2~act>kmp6|Q2gaW{R9Zig_5e`Cl5QPM4!>Yxk}pV+&v~7Drj(CkJnv^ZhDQ9jEnI)hb;@ z3^yB3f9d+5SjqF=e0<0^up>^%-)h6djk8-PXLVG=m0p>A3(L}0m~OgpY+)OPms!Nz zYDVd7j^Hl|>V3v}05BY@_PYaQm|s)!h;`setuhFUc@^rkW8nJ7i@b#5O@8!HvzUwD zUU^XDs^d`B%-)N|-&J?(hVctgL2lJff6bH*$v+cs3Uit;lR^kw5mbFZR=8;P*TJZNreC3ThUd@UbOLkTY||YCc#6WMCDn!V@n?HCt-%cfk+HHe(I3di z$rmdr)Zkg#Mcw9V|HUov^PoR#!X;|3fY-?%DZE3hu{c!w7O)@uQY^KegdPZT(Ed8> zsw zR31R)Q3|ZO6b{rEXQlka=PM$1rf1i7jc18gtkA(7pPXwJ6e8i#=J5_ z1N;)}BX9AqfQh94!ZPYJjM@?JjTj_$_{Zvw5O%maVBTc%r29C2dl)}X45*mIcqUQ% z{a~izNt|@#7^uae40xd1cX(oNj-2ZA%U_Epe*pnyWMZlrbP+NQT^wE~YTwQ)s&9CwTd-nUG`*1Gg1F5~~fw!*21fBT4Gj&??%bp#o3teEO zEuiUaSfHP$2-&nm#{XLNIACEbZNX-WUo}t3&w>T^#P`V+5jPFRWz-B|UpO9a)i@=6 zTQkKZ&7XQ@?4uP7e&s*wbW^F-8l9P2N1`XHHR=a9MI2rd8@IQ^r!Hmr(j`K%U;CV! z#d_|Mqk-D$b*3me3xEWj^6rP?#+Z4HF87&-2Ih5BwgcHS(QL#Tz^9%hAmxx)&Qy=KoYE$}>4uvkv%$=Jx$APb+}pE0Bz$2_ zOLqc|%&7xx3=z*f7L@ji=l`%jCpqD4vL6c!@Jg+ZcGJvwcYHhWtQ0xXnt-niW7F7* z+T)RbNs>g4HSRGA2A>%ZkW8B}ama^z4>Mq(&;LT!v#=vW5W@Z*Ea-e+O%}n--NewMK3X-z2G9Z0L5!IE<0yS$h z*#akNMvg-sg#V9TI~-;R*%v5Klt@gR@Kp%-v{|f9UL@xEHJdmRer5{ueQ-DXgy{e4 zBCI@NUP4w;;EVB@f7n;2_NK~de=EB1#hX@6eg$O|W!;o_dq97F!fohA)H z8IX>!9xjg3EJH2gz@KK1y|49y|3iO+efE;r!4P+gQ1V>{1`4hYC<(F)i%#CvUVe0H zZvK&77%oj1fBZc{`%b!IrIonM&sePIxIinM{NVJtl7g({#F@mhY)OBA|JRn5D;DgU zHym3@i3RA_-@@G2mj_ob@l$1jJKSn)S7gAhW1u`7p5L0;%fAl{KLTjyKH?i`&ud&R({{91qG5wgz=N^4lvH16%{d+ zh@W+IyojAgIc=7JmWUfjYb!TeH#og=D|k3}Bmi_v5_rp4T8j!3j0#tKH^)<_DzfN| zF|KpkS|LGVxa#vyrP5jjUc8?Rh476z72SrjTBiU;4A9<@g=vdXn&P(Uz!rK%ey0Wb zT_9b3?2ptH)ZFgkRRe#@Vcfnm8hPv&LAt%je+cQDXk3ku3@xU)BZ2Z#x= z1GWTN>apaau!&_Bm^hcVKc)8Ed_l7AmZ;Q4RNkaPD4CSChwj8i2w&Bd`8>biVjEVi zON~f2({qX}dzVn)1K9eHnKFEDz*03A-;H0A7aIx&C6szHii)N9SGe1X39flhw2VL! z0?7IJF&Yn4d(wrWSiV}b_BdU~j)Z9WzOIq`XXI6}=0;((xcT%H|tIJv;WchWY}i@$&*PX%Hj@9 zc7>dw1M}X3EZT~-H#OpUIfimgKC{%YT~WHR@4z=z{y)r$zO%JOL6N1CZ_B|F8tPo7 z8GFC~#Be*MxhzMl(z-UsI_eC`P)SXQd$gB|^^fT4+&ZWc@q1=YbGO9WphJhENOij@ ziL9ZiIxiOGl(E)99gYZxQ$hN}N&^te?W3F%k*?9E(NHusHRW$|u35GO_*t2Q@60hs zvxdZcCffrz=VD23oM<&{p3l&(c8uyCbIAfNPvf8?IfC|en=T8_%oXn7veX$;L%i$O z0P{CoNNZ$v%8A|oLT#-c{+V7l{Xx$n!rX0r@yO#QD=%H_vD6vgK;ey?G9>3UEwHzi zJ(gcOL`%lx3$BB8fH2L4*Q#T%na9tx*Z)n#Y9C1=))tmrABjB=@hxLifk-qR%phMk zD!59;oX_DHhHnKvECu*7MCit8y~okMqdLTS8+75knuK*mIVN9(9_VgCT*p{g_$ur) zyzbeoq*ic$X!D~Oub2c_t<<_6T-Je8fg&Z+YHQ2F5V;EStbD4wd=hd4CzA1B$Kco9 z9^+703^w@Pep%!&TrOD9u^-8??(j|MDCSKfxedJ=?iW%#O3>+@kUb(sO?kyn^gCO! zC*_;Y`S3(1FQI@`FmZr9*1$AdnT@h~0%+_@+Rt`R;F|s0x#SyCtCL)7bRlt?bgvud zU$s?FezgjbwjOZFbK(LC0XoQ(j7~JI-12VU9rtGCfas1lfFcTj4Z3QFfmxx2^~_uO z@+ulKMHRQ6a{C;4fd7+ywnem{zQMTa{w3t_q_R7({;2nC@hKWM-u6pD1UW?>jpyW_ zCWq0nY9&jVjj+}H4qlYoug(=qFZeZeZ3Q}H*9vbtR9RSv18w1>(57`lkT3D8IVLI_ zNp*x9T6fvQ2|2>TDqjE5AbwPz*pJ2*y>v!i-l|$jl)Qcr4H+-=pqsfLj34AZ}A6J3y?pc z%3X&FX?%3?NVA5P#hp4D*`ufmy%sPpRMr@jv+Nx`MANt!r0=y2-!m429Cqv*=Oo%U zEX!dlE6scDX#&U+w_3*i*V0k9<~}hSc3L(W#9>>$zFfxFP2sZ0iIk6X$I0xGhzQ7K zH7)W9LGJ}L3PIWnd}WYH?4x>)qP57@XgCja7EMb^$&d_ml_)VW%|0Yp(k&qAI$(3` zbyIcr7&fWNHlRuU+gK}xE_MlLWn!niVJ`Dll6=!t>IpD9j8{klGv!XsAPNewiGu4t zTB9MJ;s6Z&j?K)g9YG4|2Xn;9t|&87(lauS;6Iu6_k6G7tO?to^zb=-fC?ZxY*lswB>$s}*$O_A_?}_KGKPIK(25c9u-tv`?={Uv0iuC$=9* z!*O!boKdX8L;`jH5^DL%5%R2{V9?R36=hBf3jn0kQs8<3Fi0*eT()O7SmGGDiA9YK zI4#|pFsgQIHn$+xK0CPBoZ_cP9cJ6kGyK2T>{Zq;X#RtXSdvA~y zF`oVRETO6HA0MeVG;?<}soaXFeICOwa5RxHuvG152S9*3GPrmq4{!92iM|;dlt=GX zwUa4`z+yK!57nyT4&N4hWXB&O+7l9ejyuT>dj6h@l|8bH-eL7$mI|xPr{?2c2~;u^UhF=-dEk|C<#7;= zt6qp!#J^92Y6H_4kimep0D9Hh*^z^DiU_-eA|oS13Zt|x?*jMCTY+gGPw}a1)Z&o@ zsy~nz^}v_`aF2B1Hk=q00|P|u>N#do#!lZt)K(9ByZRjR%C0aNq+kz8JJbPan$ZkS zj+XI^c9yRr$eepT81si}JNeafSxg!TFp8ty=bWs_z48he^(ZyvGj!A>Q%8G_`3tA- z(_sNUm11M^vfvrdKJux@{?EW^hgQV0D#q=hbpH*UR8rzXQQHCe7gD!2%W{;Zb3O}3@o|eE`t|)|<+)OTf&j<%54EpKuQ~61GW!1G$LJ6Asvoi;7~ec_LPT_nTA0wpv&9-ruC$@- z&iYr1u=@lVH#ZGmQg+3iqZo%^_=!vMKzCICFEWTVk;vV^gUP@#VJ^PeeY26om|~D4 zmgk~L0;sVr;BiuoFhq6K`W`4kkH@lr`k|FFU@=P zhw)H{+Xe3fZ+pfv8kdkKtC5kS9?upD@zjo@(6(U!!}zf4VyTVOCdW$!ibE4KIf_1& zc$>0u*HZ*_ro9v)QA24fe08aT0XFBgh@G-V84oB1PYpD1G}jRM&pw&>-CC}@XWm?Haf;8#Y81T$dnZ-ZgCFBX?CAJ+YB;6YnB2qkB~jZ}grq6AYU-jERi}6MEHpsR zt^B47tJ*_rNOs-UJEMDF zyML9DVxS?Fc1=yq+u{k-h~VubHqBFt1TXTU-AZg4Ollg;HDSb)uX(|dpxXCN}3dOE$Tvc5e#EJNd zQHSxbJ(sAwX`<0nfPu*@#G9Ey!H$FA2vHj-ay~hO% zEdzvA5}DCARn+6n)`+4<0VGI3b!vgXQloYRhBc6F=HQ%XG)&0^Iqo_dc?IkyXdY0d ztWRD|dx`jb^dz|FJ43Ib+VLA?Q6hxJ8 z-@Zk(g%a#&2NT~1l+QS_4UDK)bPPp2^}6(BfKvZ~?3Gb53JQ ztTM(AojcKxlkyw8xxlWc?9~~82B00;i{Vm;MWExZM~?~f*fB@`ToGfew+0F_94Peb zn&Z42C2F?}Z5-xlc1y){`4CpnO}f5ZMa+H+%knb|=kBFv{M2?^1xlV%-D}qcr#-?zPAj=Z; z4|3lFGC62MY5jn=P%&O_5-?HcWj=fHZgg^Di#?K#Nnb(!d8A{-7*4(qK1HE(b8|tJ zr@o8U_@D|AGi}A9`^$J0n}2tXAyY)7WiEjd%=B*dS1TvIkD?1Ay)rs0uoKPZej1Y9 zX%K}2YJjUm;$snvDf(U9(<}oWGwvh@;h5knMd>F=pRxSX9z1=}&ooVirk8Sske*bixq?&;NYPjThu5Fv>QMr85KO(^zoH0sI{cdZ_GF5IN z%EVOW8dv_f`tCTwF<#;fB|EAg{AswtrL1pI?^G*nXlNKG{~53dI%LV1CI+4BxZPY_ z?UR#kKgN==)~3KSiq6^?3={;syN^YjO?vh)kdI8?!Ka>{A@pL^MJ!bwqP{I>0~ksn zM5#ho1gvZk|I{~lhXO}F>w@FD0YNqf9Whp_{V=KmA;A(Fn+5L0R4j4lS`SAYbB+}t zo(5B|!t;75wR?)%=*~)A32SpD$=1FatrWf5w_1V0nXIFe|KZ}TP1H}k#`|(wKX55Z z700BLZ+rKmk)_%UIP7)s`$t-Q?48RFlgd<(WJi}Op^pTib|Wu?iq_w86dBME;C znFi_gNs=1tkdI~L@`hh0WU@5x+@0FV&Vb210q_kBQWUW# z8iN|V8uLSXSC-P0n|c{ zF2=U}+BV}>)rlEw@hT`N2(ovC4L_Psz{3NK(sZT1NB$SJ_}q4?+G)|zRmol;@9Q|U zP?PgB!=q@Ndv>=IoCK?C#JY?=Vse=&nzqK{TEWf3kMsqlEY9F}V&w>Ue}trAp!S>{ zKpzKcL^3t=*7`9R61O+nnC`YhOce2Q=KS|c}T}_fnpYl>9 zV`wL*@Zh^n{C}rvSHPxm*+t?<0{Z?Q-s}eM0lB#APJ<7s^zko$+W}c?^Pb=$%`)yT zcs~%TSYU>UANwfR)Y1l8joSR1-S*CN;H38TZK1-Sw*E(O58P=mm%7aSu9RbmJ*%GHXRnIU;l>zGUv-bvYhp~7A}Fmn-wKt8DQ*Z zd3nL0wjlTx6exhQxvgl{(eBOVjusxJ*y9Jrti;(tKlt(c_wVMABFJ~q2q-5$lQb(* z%`RtLx|I5%ALyP-Bi=gbWVlQkQj*mkKfVeo_Sjes1{en%O<1+~og2gLBi33b zR@q$+_A#}$-k(Cq0Ks4t1x0=QDxIZg;d|9M&x}v^Tc=@t(#HSw5l4un@<<=km4+r>v-r?Hg1z5eIcc6IgT0^ebzVDyN7N6e6X zvCetGaC@!@l*KrEUH$*Btdpirq=(Wl=(MuRsWuKzSVVWfV35k&ipv5}{Av=Ar8j8o z{ok8HsfQXHDFmnwL&+=sa3Lx-(Bm(B-UMaln${v;rBPGJ1Bk!=rkk%KW&5llLlwHv zHs})d;~6(@*H*D~&7WwI&?r)5u8@9t16-})Ny@g(^lsa*O0DGVWJf5WHnE;m!Q$Y= zwqY>WP%qU=3MD%X4-GB#8`}=V5!Gp$R?giPdq8lYfoNPghPDdK3ba+j20`{Wqhglj zJOB%&tprmyW9sOIC#!>jtO&D2uRI8Tfo8;Fi}8yc;ESy!g@S&H za6PX^mP|g&K;50=J#{y8NSZPTbN{$D*V0q4Qt$gqKk3ut>-WF?*l&gJuW=$zpK^ zQlj8K!wm<>lu0m%JeYNwPL7^@Av@Z3VYm75dqMVJ&dLzyA{+y7Bd6Vf5~1`Ki|SZn zw22L&X3odHqY7K&Xk=C`Gqw(o#Ral8{r?#4R%_f|WFsYwVNzgYW^pt6PgUONCp;<~ zaE$sug<2|eD!2cgQ}E(&oKhvB35cua$^i2NUiux|t^w+ci;D}oJ_^nc-Z=*3Jxf#R z5Fe;$@1>vx6LOpK-=~Jl0+)5dY9He#AmRnuhc8}gf}$hwFQEVmM0s8aDP^d?wP;23 z%!^mRwp&_S?xdK*6Fp~PhkKmWQN$o*4?KOaD1UTNO|Rh!0VQj$zQCF#MV^JLmo1%b zm7y^(0BGx%MYGA&XdOOcQkQkKAmm%9(==-F*D#da?o;^RbR%I9ZwNpC4`1&A&UN3n zkAF3kGNQ6aWR;LnS&@jyrlG8eDA{`^St%7lB2vjHLS|`ZmXU`H+{LYW-zV7FF zj{kA|JKWcCT^+abeSbdh*EnD2>pY{bBkh?4&mX>XWGnmth0Zt}!aJSBU%pOPfhFFt30h(%-raqP&*3frb-eaq5ENwO zq!X#eJ*q?#p^-FnSnUWIz;Q4L<-ssZY*888((IH`xA1>&(%&7xsGgBaLkE zrMQsc=7OdlBHC95hEC)?adm{?FM>TLhsnHA|M+`hB7qt`dOvp(&7C0ru@((Y&G-qO z)S-14QgNik+1oUhxDSyv`klBNR^fveYxEmeiB65ktZ5yf(*D{d^wl_dVq}5f9D*1P z^4+LQAu73u{KWr)EKsW~D3EHIF*6NB4@UQI1tTF5GinzNKhT+PMIp9-h73a#%k$mC z%^wCm$2ot@dC!;x+AJnQBsT)>c~gndTD&qXO}zie5?GJKTCpIipCfNS`eMiclV{Y! z96n1IGiX$ydi?M>XxVock9X9Is{BvQREjz{9jfsnY(9U<3)1rZ!O5GoQ0j9+BF?h@bL;aXv+PJ;Go@3RqhOjAbdh zAx>Se26FC(hKMkZsmHluH!DQuK%c0w7e*%oWVA$^VE?QC-}JObE`b=?ENP&pquxPyq;54l})q*4~TepvKvVtBWixXIZ5#nX98^a zdq^xXqJ9{9Jn~kO3FN%uHLBeku$YAT0Iox~m(j8R;Kc`=3Jr7X2)wI6RG3}#?TZb# z0mRIJKs<+F5*&nD4&&U5_(QXHTCF9id z@b$K?nd|=#gyQ;b;1c{9fR$g#_Q@T?XbB|WAJH_;iV;))@!s1a6D1b#PjJmK)?W5n zjVK9{wnNcVv11r2)M(UkIeDo~iB-Nr*CyR9&0`M0#tzW?AE;X&7~Fs1E~sb)&ixXW zSluL|@J_H2)#?XRx8->rjEyh|1jDf@-jaAl{`~GJdEDh0qLccwnYf&jw|+;XTEHlY zN+sN4n>J!HW_5Ux7z0J-vd|6Ux?%{+-pDf_Gq*3BnAE6#HwM!tr*jiQ*e9TT0Xzz> zOdP>iGK9#ut1AW#FaGyzU-};!qN3uri*h9!uorz%>@)*#UV}xCqu6_6NY9tSWEGQZ z>%)k=YArv9I-q+{0fNi*91{_u%QKfzbO$*ZBL@s!y<{+|N4bMq#pc1uT>k&5ka&F( z2@t_OpyPO?%i>@&F zLhtEnm;}%~*nkO+!(o?QC*Z&dP)4@|`Z2H;>;L()wR6{7ylvQw!nqg-ZIRz$^W252 zz-SNzEvk=Ap>VSv@o;u-Tc4;|e*3?<)8`*UnUD~)K&=s5DF3MyKXy&-i!9X-zHQU% zCe}q14%qPEQ?$~D6Rr{(^TKDRa#+q=#eV;zFZ=dvBb!7LkC`j)+0(lbDjFwHaDnxX zSJ~!)k`M|&6wl-&T#)r5;iIEki&N|kHy*`K)T39|e{WO<34kEVi!(C>@{^(L<%+Ir zXw`0}0*|qL$8fgoDBvj~FYnnwB7);h{tK_@kp!BkS|O5(!4Go5L(hv`1z+5P!`G69 zE%XWbIQ052%-7rrk&(-bTVj(zPJXl2CA(J)4(bxL_ujlX6~=Mp_l$llf4F z0$a}IT#|`ak8f8^^_5#%-HfOprFmO$h!duKwO*Vf-nXYS*J9ws^_D z&l~Y4G?`t#T&*9$iZo-GVkrxx?rf$J=+J83a1JxYz6c^QA0MA?i#Dzrh%o3rSsZo< z#>}bza{u#KRv1pOJ0%SD_4~ikBj?cpb^mWp4EaBc95@am>@L6O|q%u;<{H?f4 zg#3;rE~scbWrcTQHUk)&$S*rKm96*pmh4m0(^89+2}u)D-`>0XWB%W5cRHHy7T30b z^42#WFd7Q+%zXs%BGLSQ%=VhDrm83<>1KF|>`5C2`~iH_YrwzvW=*H?L!e=A}xVPp#pcJAo9e1nGh^EY=q|G!Lh zb3hqbjKZL+$HsTQ1Dx15eRzXV0>@>%e}}6DC767@-3<|dF07A_7Bq(K!rwZy&q(@` zlW5z!4M_~y_{m1S($e79 z+Qj-M2Tv6_jgu~ql*Z)h_+#zm15W#NpCZ9E`I*$#s9WvefSc z{k8ylE=6~OwyCx2Lk`nZM9VYjo7WdPWTm=qAYW~-!mbc2E3tpqm|`KngV1k74NjhY*^G`)y8)JA-9DoQmM5`giH8COF#zqjp&th41D@u@qj2KPl zcRfuY>Y$9>C*~$QPGiR{1JrO_)jE)-P^DZ>GBd`+6Wj-=)dA~|>u@IpS^s|vm0iLC z{M8KEQTD$HT+C1dTiN2wgc<-SKcIAB42yqKR!A%^B6cGpKoapsRQlgMWEqrgn7Mb} ziB6Z2ks+90LVs6~u_3Y2WZ|ZGs&ZOSW~S+#&A#Y5)c&QNyHthQl~91qORaM(zslF7 zs}VayVL?3ZVgK2a9yML?=*j=yDYn?DE+SY5tCRVmRs2lO4&1kr@(ddvpc-ECDh}af zV8Fh!B^loA_ueb?#1RQHQW941NH~pG2ZPexmIAFIu}U8bIPpIzXHp^Ar^I)9#-8}R zf-=MkU;^KctpaB+!?evB|YfWMuW4#Nak2cpwpQKCdkO^6jIzC>{ zI+5Hp6fkXG|J6KUvp8sxgh#)BUAzRD2O;G(@eRh^E`9?aF8POOX^RR2+K zVThdL9%HUAAt_mgGv}pGhj=GGc+jyu2j?c3lAeWvuKh8a(y#+ldE1wGe?N+WeD_xPM?l8?WsZg?zQZY zG}Z&#n#ZDuh}@Ip@})z`((xGTV0Kg5$^Ip1#TaMlYTW~Vm0*LO1sh8Y~-WhmD6`pHo0|oxy-M^vEqcK?Cu*exxYg6N<8(EdY z1C&YYu^B{V)R-({_ls&WRJb^AmgA3Gu)||&t@|s8SH$uN37V1nsB>_v&8DwuVjEXD zTU-jK4qUR|M!-{sFtH897jiU$BA=GKlhaLH>)bj=l-;SR4?{tT9KhIL6SRP*cWjDY(^GV6A*N?d&;)^N?Tdx<6lv>BrPUFTEeh)`Bo?Gl{{Qp>+b zP?XM!WK+tt{F>G4`B1pJul6aucn(d4sN5>c-|Mz}%H4j17`xVO+WPui{o&?I?8}>I z!x@!C?p5{7Zu8k)6lDAC+NPVm*WMy!KzaBp#c@#*hE;vswV{}qA-)nrE)==zXq>n& zAP1LYIxXTO9)IFK{%`JVhfA^IkwfBbFD%pK6qqKTW_Bd9Fq39v`NDHUj+1<}Z|pj+ zAmc>SIhuP?m4@^Bow4=0)3O-NFX^)9R-<^gJj<#@$Erp5_q=o=5*?v*Ns;Eu<;K-J zcyH3KAr!>g3>jjpEo5L9d7f>9yRqk<*RmGN4{^X@* zUfa2UUM}#W$D$UeAbSh*MN6lHtx}d(h3#8^8}FbVdL8vUIt%~Xv(2k&opj5!h?IGm z!>?gwq(Lu*b0`Ulo(A8yUX;uFDy zz+(|Bp~0?eHDUl_SxOo>cuR+fyXV*>5TpiHz=i~ak2r;-yICgvn$jg7e2v$XN14Yf zt4)iyw)?wRdebg#I(*X6|KdZf+w9+HuHL(oL&e=W+P{8c+9Uf`4=y$h(1iEO!;h7& zdDtygn=wCMcdg5QzY~iEo4qo!{WRkzNWZ1Ej6J)LrrYN@hrih9lShiMxv-bR} z?*@*Xq4-as&xiE>F!1>@WO^z$UR5#P<$LcBbqR-W@GGt6596Z>LH_$!Ifi$yHZ^Km zPHelRP|=(A$95^Fv1#e+HPzKM??j1EWa=;j_!e$j}b#$*T z`_A%i-2juK9NA%WVC6WzDD(cc%i!$}rpBj!IK^@_Zft-)CmQgu0E)KIQC*jDW&7)_Gp8fg5EQOu0&#dR%IF z=!j`lzUqW%2){CvSp3UMCyw}{tZi;@CpYOE(K-F0LywEA_9(RFc5S2Db_xLOn?ltM z8zT;+Yz&82%uT)=?F3(rU%7v!lk7Q2rHQ#uGlo1`cNvnY3=~tFb5Ka_I?tkIdF`0t z7?niZ53choYg?J@o!nPh{OqI~)ACs?HcCHTFLs-UbQ<@OHtN%`zxK(HD!u12YQvr?O-u8v#>y=r_vintxy%`7i8g|QTpZ1|r`r9XeRk8D9ifdx=z^Rl21_2wd$;t2eOkq2^%jHmyzxmt6 zGSioz@D~!lVviRT7JhKh*MAuJKx;n=R}vlbi(#(xwrzd&H%&UF>^n|IPLZx3+jDPz z{iUMNkHXUo#1ty@^;2$@l#Gn3m-;!P4mxr1{8kbWYk@0*QRcc>5LYb)oNqg&KE27w z(LHchZ?;?t;f-fJEN^zOedNUTd9RTTUQfrFV|bocJ!rOkz_i`I>E~KVwX{)%=d}0M zs*0uDcO!FaZ9Yt=lj&a7?M*uHg0(lc!QzfU4ZEPAAc>rJ^Q+X<<~(MEWHJAbIsrUw zJ6G>iLMr&m+j8`eiO=Zb>YX!=?WK-i)uc^~GkQbsxZlQalZMdA{A$Px4U4gtuD(l1 zl(Qo}u@wIGPWI-o*x|CooV)KgtRGDh<>=TL*+ILE_j!5e2CwixEIYWPrVi-$@87!! z{Hh-UmBc%<;PJux#EBCz(yl_*hc8q;#@-~eio84-%sc^+Zty!+&O)@d+V8ZY+7KUwc-OJ822o+s_3&`I?{eAq zi1LCd>)e6MzRES6wFb|je5EM49<>gp3#NN|)ZsYrz zV}DQ5Dl;*Wgw=HtDYpx&l=$P#55aBkmA~4`@86XNbSDW)l48x{F^??`Py8qt=+9ps zsN0=z@wzC@Nm8-i9MexlgQbtIn_l(X$n-4m{V^QA{8s2raJJq-#$9#!QaQHChmITx z9mY1yRRUxf&H-BcNu4;C*-HgDBl=Jt&I1q|c+nkmTY>E^7pvn&Qu1z}STfaG7O9%x z6K!kT3uApr#wip<#YZj2dT)FkNPmOBfcQ0U;Od%tPDntYR-2AE}%2Y>U^}4qJA)EEoOk*Z5EG_p5iZcDKs3!8aID*O*UmoZ^9>aon-?ix%<=+ zHIX~+z3H^(l2JMK;_{Z?f1&DdqCLPeW$9McZd&swqst%k+j^^lUaTHTnj>i}yuVp{ zIsAwU@#p?YMM@oF)=;a2e|0+F zR24yk)*GhfBy#F{HtHb!T)0e!m*wJZxu}^)vvPI9L59_Sxyw~)VuMlh0<&5ZIrlgR z*PMz&RxW#m^eBZ`?g-@HnOdj?7T=Zi7a$xz$FV)6l3w8(;i}O!PN1mLhU*3Kyf8gm z(;QsG$vX4fmqb$eY-Th3>Yjwkj$zKwtPNtPGCyQxtOZ$i-`&|$^5K1LNlO7y6yqn= z1^WeuP0~7dF6PtRy=-L%zFGrw(TDKx0o*IW+FlT6p9Kt3l93W^;IrqCAG5PcIzaQ# z(8wqZ9BhqRmPd3+^=*gC#3kc2_&hv45mcb9;x13TV%a+HXhf%`rgrlweIW+r!L8Jr zW9<%p+C(~M{V2eZ?FTX(Z>^~3(WuUetS;AGcgpBlXA>&9F2uK+(`rZ6{2J`48CqQV za8q&f=FR^GoLb)XB+PS@$G>dPdZaq}bppyA6g`B;te!6idph-^=T@aHQf95Yyvbc! zobCv4#Y!AHaW<)ELFiBa;W(GI-OkUClvbt z4jVMQmOF-*&V)ac&*|4V1a~jGIwFFIJMS~ZhfN&apLzghd2ia0N?|98R9eyB_pF7f zecFS8lo&x7qn&LucqN#(y|j0E#BTJb@9`)ziK*4?7E#up{(ayI7(<&r?LuCB$9kQ&m;|Kc&|hohG-) zYhpK*pK3Qtq8~zmVr4*FEb~x_OSCEJhaV)B)l#!9+k`!57OUTFxy^aNtXHIRNaAO> z#zb~7e<-Rf$Tt&3juK%OX=rFjf^SuoJSQe3$0S(k@ibpQqkF6tU1q}As{Yv`r_3Tp zeQdFpU6e--0{<*qx1i?@wzV;%cLWjeRR<2?t;exe0bWP)3Cb4SM( z66ERhJ58>G)_*x;C0Tm;>^o36NsZz*b*F1xNO*AKsW7iXLj1tONP?XcghCQiQcgz1 zMly(l7%fplu*SKPte>%;jJU>GOVl_zAhoOFtPz+Vy}4P?7qU!7s+(NE%M)S#u!vp# ziN?}^eB3r?lXvE^?L4&F^xC`>weQTjYT8>{H|a-_k#Mf9ME>zj{Z6!lzTLpVZbr=);z- zE`iv~_T^=hQJS2p&(ke3g7`Z_!cT6*-IH*cjB)!B&P{=#n=($heEaaFTh)UD133lP z4r+^H!?Cc3I-v>OHSzES&F`ghtLPum`VMa?68V+%l$1}zkBKbb(65mtQ?2vrB9Hh( zi*%okhJIr8@gxv|0n?v))YyRIbaHYcF~;0`^Zva75wk7d0F^v`M1_Z6G79G($ zopgJ8aT((jl>^d(j^ZzGS~^Gy<}?qkY`sqDo3dM@&id7<^(&bq^SP%-Fp4Ru-X@$o z#GEHRB0cgpJmN7%lCn+?D zP%MW#(u<#cRKzFHsO@7x8DS@S{3`H%=<=18svKC5C#=ry3yklqGp{;MCGez1&qm@$ z;h8n69ki+bJi5y=e;^V`SD>*PI;}Hs9gZ#3dX}ginlH84fr&J52PGc-Jr8 zuU%aq98RBp5J<3kwGVHry{z&1!n4WoWUw%kq<<7r*Z5y9nhMOzVgWX4H5Ef8G8Kzwn#fZ5LH=5$CqKbJNp=m=|4Ye@&NE^SmRz)AjC$mYKYN zRO7|zqU(5W7*8I5_;)^QCl3jqAf_STGo#w%ASF{$>vK05+B?wYugEYgq_e0IJaC}$ zh3vvUwFKFt0vjTanewSFY-iQpkFaj4-=j|`-}19y_9~)s@-W-Wy6oGHjT)ql&bt{H zuKp8L;wgMZYf^5H3(I5gU!4^0t4=`q zOCGk4c*4fRzEN`Iw&&4&@3Gs#qUvl(^~uO7t*x!x7MCp;pp{;;w@wt7|M&0TpT2&* zRaK=l*;B|M?J`;V?poLDs~tkDQchbzfE*nkztKCRDY>KGo@liH&vEH3-2!dT5j{5k@>t15GB=*O;6Kf zzHU+CHLm#ZZddrc*Y`^d3Xw=PN~ca?kzayyH6I&97EO=uShXZu8T6Qp@8A(u`*d=0 z-8uo=CP-c=tevyp>MEn|iz!OU&JN!wN6__-3!ZU49*3wsGd62{OJ?a z%AZ{{SJ0JOAR_sgy;S_@#Dssx#0eR8O*b=Q#QRz29ku9ba-R)-rJ6(>NCBX1w(@I= zkj#aLN*0iA;-N!6rg|#3Hw;XdfuWiR37AIBbvrh}9s42#dQ(zTO7TO70dq7P`}{m_ z;FbW1giX&6Av^i(noltFcV12isJT>*eZY7J2Z>?#;-Alj`w8j~-mb^)-$`u`(yE-!`7z}Sh6r2q7Jt)7PP*Cu9Q^RNm z7C@drL@4W`1S`O)q&Dg6o-A7YwjBzYE7OHEpiRL7wvzaNbvt($4y zH3^5It+-G6-R>iVuj;<^>2QWbH zHOpn{yvRdMUEQ5N^AQP&IXOEQdt5ojCnoG$)Q?c*KR#>Zz8MmzIF!xTBPYD^O(wZr zSvEaV+8s|6f@bl@_e~ehu+Oh3(P6TuN70cn^zkP%fG;(cq?E`@igB;#JwGHqI&t+c< z`EnQ<&O`_Z2nfjQ4`k8O(~JD|j(e?Mc}1GoBL}2$lKrl-!4VUN+U`Wz%TW_OEI+I+ z1a8+BrBx8$2CcCCe5OK|DLOLXQ`Z9n$qyL4m$#%ia_U2Pj2g;xrLqH5V_41Eq-cg5ldMuE|&HBm6H(AU}1JWJhNa=hpo>Z1)GZ(?g zQZh5!OB|9Hv|9G%7N(|BAU%}ha6>k3q3-*UuqHE|HyC!&x3~g>Ga7nfquX+S`f0wr zyT(HNw005)ii>S~Wes31yfk6Fb_+eyK%8SEZRU~GahCD9TX$uDZ#~lMB}UCA#T{0? z_x{%FemjPZ*M4{0{EhssZJ*Icc$pcx_5|QY^?iDxu!OV`f^*utW9zfGf>+G`vi-vg zQ0IQWo#)`EzR>IhkNL-56zm(20u&)cPon0Kr9^=;EwFE&yn=#4J7qUJwL+x$`EmNb z+C&LlwIu6%s3NgFC8)t}*T+ZHzVJLNx(N$ISnM546eUEcTh}rvUc2COQ)nB<;K7T!k3-|$Vll}Zq%}ujXy$KbUrlX6`3}${! zbb|52RcS4jMgu06*w%}eU*ytjyUd=2D1YBcUb(@LQNGZW;<=qP_gV&}X zw!MdW4aEd@vKAAkiWk3m+GBt=i0$7k2S2&nql?HJOMXODa>)yh+Ffs~cH&3iYhOfW z=*zAX+G#8|@iNB_zO{^$8x<%~%AHwvVH>)ytg~tq=<(;)Zd3)Jdsa0+RYthQEcu}A zHyN3~KU-e>6f~fb{44m6e@3jg2dd{bMy`59ssZOB{ znb%!J^-J|!!MjJc!#_y(`A#0xa8{PKw$)i?)s-I%pnNas_}v6uI`i46VoUM;Q4b;> zC{}1UC1pAp5wgm)I}bhyIZ&7635DHb?(X^jU{JF8li7842zcc-xn{(vY1})b ztLx8mDvCtHYhY0y<0p{$UdPM3?8asaw!IKA34;v-OKIum`@#tN{!;eO2CGd+gT>^xB9^yr-|p+k zz0$Vdy6c_#O@7GPF0m(0cA1$DL5!x>STW@XPCq{t{8vSFcv!Y?b0BCEbtK1fI`?g+tou z^jWyEQM>kfACdh%y4T6obr9dj?06K_2#7W!HpR;pe@2z%%26osk#mH-DVF;?rn!Vm z9pBzGjf%1g;lgpw9aml`e~9iqJ`k6pUbV5u*z?z&)+F*qL*iY*9asL!S$pVedvGs|nXBHr|ETmam+DGl z9C!VPaPe&SaQBXbpGF1Ro)tuTe+dzlCPtx35T*&DW>X!N)i*G>9T*rGS2$X#fuIQN z5@imk{?f&)p+x)}JF+i8Vf=T4$-HyJGP&kO9w@{Bcbd`Q}Ibn^d7cM%pEeWgQ zoUExRwA7ajUbH+(N#XBzT#!7z&_POk`I6Em*Ryq@2QE8HaO1fPm<_4>$%_|TP{y&% zt%UPE#zJXQF(9Wr10k$h%gd-L|~MdBsxy`Zh__wAd}+_F~u2W)R-ApsHfk-#s75dPeKhWvi1 z3`y2jRhESEfK$lZUd3=XMZ#;a&132t^Q$e+a`JuW!Q;w-5{Ut^y$;M-^%*>o%beK z#^!3`_0Z%HwG?MZw9FU#JV%PX*FwK)mHac)<$A?$$WKP;*?po@Is9214cmt0uG6|v z!#A6VR_Qn@qA*rTE{%5piCf#+s3cq5-|4z04F&8{jcyqOV^a~bL)>(JVE-1ZQ(M+!xfz8r<%Nic6E`att;eDWnUrvX^!7(`>_&o1`0^JE*t04ee9TW7TuQ9xPi z%{}2AW@%+rR^UAGdD}*+v$nYUL~TI0j9PVM;mUXWtW3GBOyv@7v!0$_-z|ZR(oCNP z0X+Pd=ihECEhRNzcjo5IQSaa4Xo!@&sMFhS^%T0AfhzBYTBN!)KO*>~$Z3U0OsZeK zdWAunBg|sjF^5W;(=AX<-gYXmqW?_?Hd5gVeM0Lq_-f`!UT5&SXTnq{@7LF>eAkLP zj64O4v5}JW{P|{(aH}@b$Q+#ZK-fEc?dwelRi$^}3rPtwx`UXAeY z+o$5LR)`u^yDg1hSXfz8Q?uN=R`Cbm%SVT=l_O%_K-woG!BBCP0*`lJ$AiYfhy>y# z!XH8+uQKNe;*ChSipN-S?NoNi???Z1yvzc_UthssLPaH{s%=Ndh*IFcT!3L=jR}=V zZn_YYwbj28PNVm>YSE)ZLtEO=N#eQpCFHY-iBIh3K_{sX*&P${uSaSYI=A7;S{$J*fu3F^nY!+#MdOfQOVNFtEGPlGYznE+i2!V3Ui3gAbZ4>G*VwDr z{fC8tQ}YS4^Bs4Nd<#DE&21w@_<1u*R)5=fxS(1glBMS8vnP+a8-d9}R+jQ)0wTix z{rhLJ^%klTf3^K(*~(1GUHowza4sMx5p^I@=k(9Hktm%c0hf$qA=J}Oq=Be`iea{L zr)D2fj-tE~oxaAClzNISNw0uieKTgI1BcMNjm0fR1UslgCa`)?9wjZ&oS_mmfivTm z0%rl2>FyAsYe!}!ZjZ6CF;WG$3i^9~At5Dobt-0N=GT{M=!ixvZ!{_NH9G$K1UU|* zB0R>CWu;g;AuM3ZtS${w44%h^3;14J46LCe^fhER!K8su1$xa7U}C_Cw!_oAW5FQ|(2!)J9Pnq@K) zF|RK6Ua2&L!J-uZL8=uo24}Zw*TnLdX&eADBLsprMQ?<9ZSL(=ollgtm&&em$`hfLa zIC!{{UOshtvMGD7V(RqqnrWug)Vt3w={Js<2~3yJ(cY(*MWTC}m&Zs%09Y;otMq?< zDth4K{k?P7&p*gCS)Lyzq5^=x*|IGhx2+5bq(Xt_=*?q$_7te!u0C5lznd@~ zMT<-!`{Q8~Y#IjCWA;_1Zi2Td3%#PBWVm&Oh!=Sa6jh zAi+RDf{D||tqwA}v8pTT3$Rl2t>akGJHpzORi*-ft!cvd4u}Ixkcu5^4KaeE52cFZ zyK~uMvWECD4+PElfS_N$T!0kNmKLIY&9Z9Y_3GblTv{HmeU7l4+dI*dXa97R zG4&e<%h-yJePNHKrDZ7$h_rQdZpf|9-OU@0y0Ay(bMS;G&da`rC)%Vf?R3l$TXvV3 zZ+D2;HS8j{)aRdvLY63A&8EBakzbG4bzRH7h_g2P-Pwy;B@ZV$_pr%}oJc9w)|Ds{ zNR+I)#tt<+sC7096)%~h0HZ=*N7wr(t+*eCm;|=8nZe-tcA-2{*Sl*Km;eyi3mKz? zkuh>{M*eqZ0vVFXtN1g%hT7dwJM0& z3b`(go=%Ca6||cMiFpLDzMI+EqUsYhXU63(;+tM<39(-Tdi-YgXN%_GtK4tLjg2|Z zygETs=&qaOW@oxljL!Z#m(J_dEepdnmJ`K@nZWn%k9o^+%4PSzy zx_U$6LTa=+?@pgte-4a+`1|wI($fJnf-eyMrtw8`nk%wVlF`%VV6;^xIJ7Uhwj9VF z(*+Ykv}c?oSn)FQ0ognau?P{BbyrMG2^j#VK0Y^-tp3PuY4)PtnKK(0CFFkpp2!?T zb5)J?A%sL`1J@pBxV|d1CwH&C&Gc6HT7Am#ck5l5`K=gEDIZEf@`Du{8RaH^$7KmC zaRemApoG|1=D<%OCw14Sq9OO5%{R|1@~LUb{O{3(`2ENqk+sl*qbd+?Q+GE=bH4pX zgGVOSPHz|4Q`Q>}4Tm~{2ZcY>KNOq8A(;I5-ax<^k|S{upO_pz+}cfGBeUpRF9N7g z$lzOEz2EK$5FrVG6zIbor;n!Y+P(WCz6~!X4W=%0NCjpMv4^Z)+2T7S?D|MXKFh=q zWB{;+qP{*80P-!@ToIaoP4|SNil${_VE-djcCzOEsE4 zH*$M@F39u(YMZSWYf8+_q* zL{*NPl;|uOsUZ7jRsmYRF>1Uo&t-8vo%n_h9pE|exGbl!&$lxkRV4$q@%%MOMnaKx z@q7Kl^}$SJN>LFT1eQtHa~h?#^YHM*wta4H_EQMLOfav{==U_w@N%FBfY%hMou@sw$=|9Qw2}YmBf`2bVL?Y66ppnCA*y6d#hL9DU(Rs zU;N#>KaSzb`YZ@Em^45U0Pz)~%)^vxwSE6i7-K9~TUY1kG2a6&(PVE42kA9}j-H;S zSQO_@YId1mVxUw?K(f#3ftQBglG03H-CJ`O12>ekc-iT@Yz{vX@m>8RFP1v8(fpm7 zOVYDu2l$#Tdm%NW3u2mDdS;+^i7#PNTT6?C-WyFQCczki2J=s(@X3KC!F*-|+7ZM{ zA5=D<-$YqQb%%&XuLmgpw*>4D;sDWT=4FC_ZhlfMS{TkY=BoU==sK>wk$o3`KwVv( z>!LdL zI7~b5TJ4W@kdl(J8~R8q5|IcL1%(a5*P#q+Qw%=uJZKr)RmXmp@2RvU>&?gU$Q38- zepQC-Bp9mNXSB&uO8c>tv#P<1SV>3T%+s{Z!6598@}}P8c>o?5C3!`n z4M?a|;GwqsxD~Ol<%!a;XE;ZM=98)?tB1j3fr97Tc-3>KAP9u7%nq6Y&HR0a^Wih6 zeBwX=ng};%+S0`l(EDN`iq5KTMt#i#Hl)fBI+tK&U--ejW*o+Q6N?`&>OI$eO|*qz zV>3E6wV7nUdMlV0MzGu|n!mmehD6|A0>A-88nSXLG*kpM_1iA(b!Q-sc}|j*8igA% zqmX%wsOSGFCjw0bWpvU20X zUs>}Dk%Pe9lbS!Pq%EGXJhJ416pzZWCa*&bNSoJUVQ<5+6U%~OVk^g_hI;c|xtNcF zEEVQ>^a5hE+nhrDjvt9T_};tfJf!B+Iv zy}Z3IsP|JZxGk7D{Ox|=fDu*;$bht8bnlvJSLFih#V5+TKBzVE(aFt0oUAHq6Kl29 zcje_rw?R}L-Mzjo3DM^*f)_&5{7R;3KRQr`S8BM6pZIwB+Y4@!N->$*wb$G#T#>Kd zhrKvOVG?%QAw@L4>5kH1OaifA3C=FO;`qY0gF|KM09K;zanREU^jC|2lS!XxEqW*| zB!p`hBNUJRcv@EK>&Xmfa@aCstR}{uq<6e1--lC}1NnG6bcv8p33Lv`w`9dWXli6% z0NZAT3g-&VVkH9Dzfk4g9+ zpp72`g-+*N(*f`KAr<=r=gyvuw!3{&Q5Qx(>Ucdj@l^kV{8FE?n0MwmeYWa})ZwZ@ zd#vVj79L7IuPo$ht#?CC)kKqRlPdL*w2fi4)y>w0^TkiR;wByK2gg21v<`+B9@9u} zCf}>95cZftKzYz7=4Ze|p#*+`69Y!1>zj_=<~@46tl#)W;5Id2rgM)iL?4>q3z}3a z;Y%fVl%7%?S@3?E|2@g8$?}`8pBURgUFQOo=JH&+CN zLC5cE1dxZTwS}6s6t&Ec?|=P*gB>D7KkmA2;jcD0mp7USX$UQCZ6xP>ZsMp{(?$FI zs=>(+KW|!rM)3rDEsqyL_KL*xR$n3L%y-%|z9rASo8FZc9_2e{qibNPH?$lgVTBsh< z+I#)xN~9| zUj)+RLP~qVv*(WuuA->4f_%`?vIr~pg=ei+u4 z?$+!a5tzBE&=a`*V)Dw@M4uuiD(540&0g!zAyzeV$MX-S4|O`}xdi7vM%*+g;J+7! ztscnRl~1{Zt{~_VP};sDpAIqKxiy^nZYq*V*=ed7bYwrQtHJHk;(T{;Ot z+a^uy?5*L7G7Ez+O{;TM>QNPb^jR{x3rCJA>P9KsSaFz|a2)8KijgR0`E zG47D>;r5p00BQQ`AQiU?ojgU6k+77_KC)75VrF(=QvV==jWxpmPEB1ZKO5VFYkKd_ zvN`DKPCuHYzB9&Xd)+=y=-x7WhDw_V*lAq5wmqL@f4C3r5if*qBXtXEQ>E)4Hdw?o ze3$pF@Lt_ou;!9CxQ$imzVpSZajsg6>0^6I$1-yg-@o5hc5KHJt&@LB!WPe;gfIh) zkE;h&@_KQUVf8?KK$HTSOkrmG`MFO6Q$w{=uP4~v(A+KGlscvrw7)H0xGh1z&&H*Q zcrHl>-?3USceGH8PW|y8*@~08?Vuyu{~Xn}AE>evPkQp?Vr_9*il)i%O2Fn=Mo_40 zYwIb0nFfm%s)Vo4r!Y}I&P^weejY}&fc4f1$jST*0cT#7UtLG>zVYEn97^TvNbye| zr!aE3@3D4h*S2*Y-_tXu{H0F1Oy|pczD!Bq3T6$^9#}5$qJLn9|J*=I5sgYLKlcp$ zlV@*D4)T+q9{C{>0AkqX%X}ofa!-?zj)RGI^2zj9#?TLRQlk6&w>q1gqPPZWr`u}x zc3f%uUC%;0S;vug3;oZ*p@(SE$H0!WMPZNMBD6BjOEDnJ|})q*3mjs#A5JhI=S9XC=DJp7OtL z)vR^gY4yBlO_M~vnpwv-^1|yjT`P8H6f%_EOU{(oY}()_pUFA)-dDgdju;TdNUDS@ zjwoS;B)x6Fkr-ZAY^=oa4xZg`>*@XOWzmTKIyV_19~++%xv6Vf-cHI5#!l)rxP&yHK19(p8a9AbmNI+?h0~~ID4ybR})5(cPYP{;du3k8Q zzEV_L?1g60f7qLL`u(DRid|Vu9ax)O*ETaqFq9vl>S4O>a8@yFAb(nJBgyIB>{z+^ zS9(Q7efgs)M~oFBK{%l#p`wpF@o4@rT|M-jk}f=@+oiRIrRDE=5aQ2`?r&*jV|j4> z@qGUL!caAztDPFP)c))u|3S-*x5vm?AFS|8KihU_Ur#$P7i%iD(ta{_XDyvjlOfB~ z42FI}GibZAGG1i8{I!LYopUB>ZrcgZPoLqUR+=JwEdR$1kxYRejeDsZx^POEPnDTy zO=>>ls>>doOnF?-bDHf;`sr3Pn65(@?2G8mj-jfr%Q~G$bZ$Ht>;C-kpnNC8sc3ws zq2PnQ=X6o(#hUJa*Qqqjx3V>9NY9@?*Y~W~jJ)giM#=pN8fr*6?Bh27(7LJc4oocnYq2)%us?1Co-s{<#y1lJ4++ z=KGru#Wrx>$w)+4m5PrrQpnJ8O{!n;mUYqL<4RKFKeVe)?8HbPjrYt`zVWIV&s;OJ zvHh>=k|<`c%uqWi{l*UQE!lu=dz+r_Xl@-nq5t*K?w zwiw=d_wIi2Sqg;>ox5FF|H&2aiyzAcPOw5@{(}Q=igYZ`mc0*#t*Mp5l(MeTs!m>h z+L5~@qmcM7)ntSPK$VlU=nL!$&T+DYgMm+;QQ`tYuh{7R)i-o-y zs6-KyOtVG^)Y$QSEX({_9IZ zL@Y|!OOl_}DK37m@Z3OLhUajtR6gKHcRZ=)LrxKQitvr0T6uRA5TKV}i>T5YLtO&c z6t+l75jI(Grlk1)saYuljt?4fsK10F7Yb}_;Gl7s?8>D9aZ4Ff?0;@Tq5(DuLO+O( zHT8CPABe(~T6U}{p)Rt_vbMC`po-`+Ya=IA&zh!t%5{ry7)|x~ng8;rfBU+{SyqzW zy88P!Ebat-yT!s7$&*xq6_EWK&41jf8zw-+>wYT1>$@Sr4iDF9#{fDgI3l7SG`0CD zFLXp+kdnVq^K5z`#feK#HriaWKeouB==Oeq&myuCU7SgY?5Sm-dpYE&GM?pn|GBFv96zd-!WjS<+)jCqm zdms>tV*<{>4ksITnOX1Ey@aLhx3BsJ6Vb^IPKCX+Pe+X@jYI zw)B5lwJnQbtD!dde!5Dvm+c1+|M-R*L*CqFRC-ZVO;0N z?eVZX<7K0BZU&n;A}a2VQ{OXV8j{nFv@=UH?^Dau*4N;B`GD$4Bc2A=@jP;h zLG1j63-*&=MC=`~RYAhEzef8U!Ln3Gd>nlCOLmZw|)Gs#~gmEnSo8h_gz7sHCA^s>`yC3 zf=%;YM^ zp3y^Fg>g@&laEgM*1gVt+@EjZ5-W1yXTp)}Y(J{QwqJV#&zW>*tz+R;wl1A(*N-@D z@Lv5p8yNe#WQy;c-e1j66Q5@`DM#M%dcy1V`IlMcu%8OoNTe?9^209I;?YEd7FeHv=x`H-=z>E&`)5YYVmWk zCv=ltKy!p^44QPv&d84We%=<=eS2c2IO{H{7Cm*R2~p(ow^5xHT^>By(GuDCa7@i8 zE#q`gn~we&-?;jF!g#{Xde1SRD-HP*B7V?ub|8E2de z4Liy4Ygsdqr#oQg@KL|Qv?Hcr&(BYMwxo1jBGU|pHr_8&FQX-IKNd{J z$y%4cgy{4HIDoqLb+_mV{wGzaWKVK)MLmE;9NWC3x&Cs@_Kpx`g`%T7-(IWfVTh0x zPm?~hzklPfE2ux%@Nz;r#0C#)+%Hou=MK;l|6+aEDEi4uF}-6tMKa&6Kcm~K9kjQ> z0@YpUxxV9z;=s%C!iypfTKvPwM!oE;mTNSM zgBw@oPH#@vzVJtX&KWTm6x_Ld(S7-7usSBtb+GJW*1K_Y+^+@8#MD6w@0+AqsU_kY zRUXbB3+I-I*N}+6%)78Hs3IvRneMfoQI1&_W4BGN+e?iX{Z zWMyZkjI<;xJF^g#6$(knh^)-Ax2&upl3lVQvPqFpMv^2e%1ZJ-ufD(EbNrvO`JD$oNziebz-i%;eWLNv)k&tr!n%T zlvv$x314gUu!93(OwkvsQ+XxI%&ys!B`Hp)*stGqq_=JXtG0u`!OKNp{% zarcIB3-3>VR%EXpcwy?ZBjU`$!WzB)S8SRtOTW(B2_XNb><-hLVCHx4vh26$P;C7& z^(7|v_g`-sxyv8aIa%WaqdEr%)@W8%3dj4P^G>>D^RT5Nm@5gJ~Yu7-wW0*TSg;lUXO6$y%0T0W=NmX)lSPta90 zv)DHke_hOd@rT*q*g0EMF8vRfI@4Ks5%G2G9FNr}pSmVbhOdTWN9G9Qfe7q5m6Zk~ zEVQ92S$(rBO|vU}^yK_=U08g>aNYpJKO~9YKU!Zjhc1nvDDm{%$olKs)N zX~9%1I^RFdT+E~Xoy32ah0*rn|EL2x)IaH;)C=P6961Y;nxF)P>irbbISM6$CJype ziHSvQbF!^V7}lrR)%<{l9i4{wW_8%)VL3aD03%FExKCZEPBO z#Bg&o&BqF>;M3!SX=dS zj#K$pPDFWZGiTc_jxQwYo%7;ExxJ&+DWug}3OA8IyE#Iv3sp7}bIw&vn`__WH&2>M z$X1N+AkFU=sWF7YM`yk9YQ0%zDb4p!4?rh&P3?|X#ds7#dNznpA)R!81nAqHNb5ng zO$CBxu{OtT$hxp(%3-jj;7y0ivCdxUjLB{^t7C(SaF%nc;}Fp*kTpAL`9?3~JKqzr z{h5c<39GO+icq4@^(Orzf8M@(wU2gpxuh~oTnH@nKO7&Z8=BEZD)ro~^f#Y0cCm}E zP-xi*Ml7A7Q_`J&z;45hq+-*RWC?{5fh>a?EcDVS4kWLAkjCx}*p(*Mgln>QcJ9(=7mHnw%4@>c_~NmMp=GjJdFp~FaH!im?Xvfbp0^6XhxXw^Th zbN8uUjN;+A@sh<}HPcVLMs_<=uTs~0^nv)RkudSx5l=YG+()Ed5&TJ0D1BR?Qe> zpI%v3pJhMzt+2S)LgE3nv7k6XZa$z3gwee`C1IVvjtBQq_DEEfcD+RyK$K=b$DA3u z=XLPS?CFx5ZBO?~S*O#kUAnP ?7H&&^XhVrsSe`O`}WIwPuUGfycq>K-S%uWKrd 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%0D^4(TvuZ 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

-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 Ivgh>w0~}DO-v9sr From f4422f13614757ea3c68f5b378fdaa47b7bfd346 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:17:30 +0000 Subject: [PATCH 354/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- Snakefile | 1 + doc/release_notes.rst | 2 +- doc/tutorial_sector.rst | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Snakefile b/Snakefile index ca3e4c49..a44f49ae 100644 --- a/Snakefile +++ b/Snakefile @@ -18,6 +18,7 @@ conf_default_file = os.path.join(workflow.current_basedir, "config/config.defaul if not exists(conf_file) and exists(conf_default_file): copyfile(conf_default_file, conf_file) + configfile: "config/config.default.yaml" configfile: "config/config.yaml" diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 02c686f6..bc1cd2c6 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,7 +9,7 @@ Release Notes .. Upcoming Release .. ================ -.. +.. PyPSA-Eur 0.10.0 (19th February 2024) ===================================== diff --git a/doc/tutorial_sector.rst b/doc/tutorial_sector.rst index 3598cdfb..a1556150 100644 --- a/doc/tutorial_sector.rst +++ b/doc/tutorial_sector.rst @@ -370,7 +370,7 @@ successfully. 4 -> 60 23 -> 61 4 -> 61 - } + } | @@ -809,7 +809,7 @@ workflow: 4 -> 85 71 -> 86 4 -> 86 - } + } | From f39fd1441a548d57d3f28e164f8251cf9a586f89 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 19 Feb 2024 17:23:41 +0100 Subject: [PATCH 355/591] update fixed versions environment.yaml --- envs/environment.fixed.yaml | 928 +++++++++++++++++------------------- 1 file changed, 439 insertions(+), 489 deletions(-) diff --git a/envs/environment.fixed.yaml b/envs/environment.fixed.yaml index 31a58835..cde0b801 100644 --- a/envs/environment.fixed.yaml +++ b/envs/environment.fixed.yaml @@ -4,493 +4,443 @@ name: pypsa-eur channels: -- bioconda -- gurobi -- http://conda.anaconda.org/gurobi -- conda-forge -- defaults + - bioconda + - http://conda.anaconda.org/gurobi + - conda-forge + - defaults dependencies: -- _libgcc_mutex=0.1 -- _openmp_mutex=4.5 -- affine=2.4.0 -- alsa-lib=1.2.10 -- ampl-mp=3.1.0 -- amply=0.1.6 -- anyio=4.2.0 -- appdirs=1.4.4 -- argon2-cffi=23.1.0 -- argon2-cffi-bindings=21.2.0 -- arrow=1.3.0 -- asttokens=2.4.1 -- async-lru=2.0.4 -- atk-1.0=2.38.0 -- atlite=0.2.12 -- attr=2.5.1 -- attrs=23.2.0 -- aws-c-auth=0.7.8 -- aws-c-cal=0.6.9 -- aws-c-common=0.9.10 -- aws-c-compression=0.2.17 -- aws-c-event-stream=0.3.2 -- aws-c-http=0.7.15 -- aws-c-io=0.13.36 -- aws-c-mqtt=0.10.0 -- aws-c-s3=0.4.7 -- aws-c-sdkutils=0.1.13 -- aws-checksums=0.1.17 -- aws-crt-cpp=0.25.1 -- aws-sdk-cpp=1.11.210 -- babel=2.14.0 -- beautifulsoup4=4.12.2 -- bleach=6.1.0 -- blosc=1.21.5 -- bokeh=3.3.2 -- bottleneck=1.3.7 -- branca=0.7.0 -- brotli=1.1.0 -- brotli-bin=1.1.0 -- brotli-python=1.1.0 -- bzip2=1.0.8 -- c-ares=1.24.0 -- c-blosc2=2.12.0 -- ca-certificates=2023.11.17 -- cached-property=1.5.2 -- cached_property=1.5.2 -- cairo=1.18.0 -- cartopy=0.22.0 -- cdsapi=0.6.1 -- certifi=2023.11.17 -- cffi=1.16.0 -- cfitsio=4.3.1 -- cftime=1.6.3 -- charset-normalizer=3.3.2 -- click=8.1.7 -- click-plugins=1.1.1 -- cligj=0.7.2 -- cloudpickle=3.0.0 -- coin-or-cbc=2.10.10 -- coin-or-cgl=0.60.7 -- coin-or-clp=1.17.8 -- coin-or-osi=0.108.8 -- coin-or-utils=2.11.9 -- coincbc=2.10.10 -- colorama=0.4.6 -- comm=0.1.4 -- configargparse=1.7 -- connection_pool=0.0.3 -- contourpy=1.2.0 -- country_converter=1.2 -- cycler=0.12.1 -- cytoolz=0.12.2 -- dask=2023.12.1 -- dask-core=2023.12.1 -- datrie=0.8.2 -- dbus=1.13.6 -- debugpy=1.8.0 -- decorator=5.1.1 -- defusedxml=0.7.1 -- deprecation=2.1.0 -- descartes=1.1.0 -- distributed=2023.12.1 -- distro=1.8.0 -- docutils=0.20.1 -- dpath=2.1.6 -- entrypoints=0.4 -- entsoe-py=0.6.1 -- et_xmlfile=1.1.0 -- exceptiongroup=1.2.0 -- executing=2.0.1 -- expat=2.5.0 -- fiona=1.9.5 -- folium=0.15.1 -- font-ttf-dejavu-sans-mono=2.37 -- font-ttf-inconsolata=3.000 -- font-ttf-source-code-pro=2.038 -- font-ttf-ubuntu=0.83 -- fontconfig=2.14.2 -- fonts-conda-ecosystem=1 -- fonts-conda-forge=1 -- fonttools=4.47.0 -- fqdn=1.5.1 -- freetype=2.12.1 -- freexl=2.0.0 -- fribidi=1.0.10 -- fsspec=2023.12.2 -- gdal=3.7.3 -- gdk-pixbuf=2.42.10 -- geographiclib=1.52 -- geojson-rewind=1.1.0 -- geopandas=0.14.1 -- geopandas-base=0.14.1 -- geopy=2.4.1 -- geos=3.12.1 -- geotiff=1.7.1 -- gettext=0.21.1 -- gflags=2.2.2 -- giflib=5.2.1 -- gitdb=4.0.11 -- gitpython=3.1.40 -- glib=2.78.3 -- glib-tools=2.78.3 -- glog=0.6.0 -- glpk=5.0 -- gmp=6.3.0 -- graphite2=1.3.13 -- graphviz=9.0.0 -- gst-plugins-base=1.22.8 -- gstreamer=1.22.8 -- gtk2=2.24.33 -- gts=0.7.6 -- gurobi=11.0.0 -- harfbuzz=8.3.0 -- hdf4=4.2.15 -- hdf5=1.14.3 -- humanfriendly=10.0 -- icu=73.2 -- idna=3.6 -- importlib-metadata=7.0.1 -- importlib_metadata=7.0.1 -- importlib_resources=6.1.1 -- iniconfig=2.0.0 -- ipopt=3.14.13 -- ipykernel=6.28.0 -- ipython=8.19.0 -- ipywidgets=8.1.1 -- isoduration=20.11.0 -- jedi=0.19.1 -- jinja2=3.1.2 -- joblib=1.3.2 -- json-c=0.17 -- json5=0.9.14 -- jsonpointer=2.4 -- jsonschema=4.20.0 -- jsonschema-specifications=2023.12.1 -- jsonschema-with-format-nongpl=4.20.0 -- jupyter=1.0.0 -- jupyter-lsp=2.2.1 -- jupyter_client=8.6.0 -- jupyter_console=6.6.3 -- jupyter_core=5.6.1 -- jupyter_events=0.9.0 -- jupyter_server=2.12.1 -- jupyter_server_terminals=0.5.1 -- jupyterlab=4.0.10 -- jupyterlab_pygments=0.3.0 -- jupyterlab_server=2.25.2 -- jupyterlab_widgets=3.0.9 -- kealib=1.5.3 -- keyutils=1.6.1 -- kiwisolver=1.4.5 -- krb5=1.21.2 -- lame=3.100 -- lcms2=2.16 -- ld_impl_linux-64=2.40 -- lerc=4.0.0 -- libabseil=20230802.1 -- libaec=1.1.2 -- libarchive=3.7.2 -- libarrow=14.0.2 -- libarrow-acero=14.0.2 -- libarrow-dataset=14.0.2 -- libarrow-flight=14.0.2 -- libarrow-flight-sql=14.0.2 -- libarrow-gandiva=14.0.2 -- libarrow-substrait=14.0.2 -- libblas=3.9.0 -- libboost-headers=1.84.0 -- libbrotlicommon=1.1.0 -- libbrotlidec=1.1.0 -- libbrotlienc=1.1.0 -- libcap=2.69 -- libcblas=3.9.0 -- libclang=15.0.7 -- libclang13=15.0.7 -- libcrc32c=1.1.2 -- libcups=2.3.3 -- libcurl=8.5.0 -- libdeflate=1.19 -- libedit=3.1.20191231 -- libev=4.33 -- libevent=2.1.12 -- libexpat=2.5.0 -- libffi=3.4.2 -- libflac=1.4.3 -- libgcc-ng=13.2.0 -- libgcrypt=1.10.3 -- libgd=2.3.3 -- libgdal=3.7.3 -- libgfortran-ng=13.2.0 -- libgfortran5=13.2.0 -- libglib=2.78.3 -- libgomp=13.2.0 -- libgoogle-cloud=2.12.0 -- libgpg-error=1.47 -- libgrpc=1.59.3 -- libhwloc=2.9.1 -- libiconv=1.17 -- libjpeg-turbo=3.0.0 -- libkml=1.3.0 -- liblapack=3.9.0 -- liblapacke=3.9.0 -- libllvm15=15.0.7 -- libnetcdf=4.9.2 -- libnghttp2=1.58.0 -- libnl=3.9.0 -- libnsl=2.0.1 -- libnuma=2.0.16 -- libogg=1.3.4 -- libopenblas=0.3.25 -- libopus=1.3.1 -- libparquet=14.0.2 -- libpng=1.6.39 -- libpq=16.1 -- libprotobuf=4.24.4 -- libre2-11=2023.06.02 -- librsvg=2.56.3 -- librttopo=1.1.0 -- libsndfile=1.2.2 -- libsodium=1.0.18 -- libspatialindex=1.9.3 -- libspatialite=5.1.0 -- libspral=2023.08.02 -- libsqlite=3.44.2 -- libssh2=1.11.0 -- libstdcxx-ng=13.2.0 -- libsystemd0=255 -- libthrift=0.19.0 -- libtiff=4.6.0 -- libutf8proc=2.8.0 -- libuuid=2.38.1 -- libvorbis=1.3.7 -- libwebp=1.3.2 -- libwebp-base=1.3.2 -- libxcb=1.15 -- libxcrypt=4.4.36 -- libxkbcommon=1.6.0 -- libxml2=2.11.6 -- libxslt=1.1.37 -- libzip=1.10.1 -- libzlib=1.2.13 -- linopy=0.3.2 -- locket=1.0.0 -- lxml=4.9.3 -- lz4=4.3.2 -- lz4-c=1.9.4 -- lzo=2.10 -- mapclassify=2.6.1 -- markupsafe=2.1.3 -- matplotlib=3.8.2 -- matplotlib-base=3.8.2 -- matplotlib-inline=0.1.6 -- memory_profiler=0.61.0 -- metis=5.1.0 -- minizip=4.0.4 -- mistune=3.0.2 -- mpg123=1.32.3 -- msgpack-python=1.0.7 -- mumps-include=5.2.1 -- mumps-seq=5.2.1 -- munch=4.0.0 -- munkres=1.1.4 -- mysql-common=8.0.33 -- mysql-libs=8.0.33 -- nbclient=0.8.0 -- nbconvert=7.14.0 -- nbconvert-core=7.14.0 -- nbconvert-pandoc=7.14.0 -- nbformat=5.9.2 -- ncurses=6.4 -- nest-asyncio=1.5.8 -- netcdf4=1.6.5 -- networkx=3.2.1 -- nomkl=1.0 -- notebook=7.0.6 -- notebook-shim=0.2.3 -- nspr=4.35 -- nss=3.96 -- numexpr=2.8.8 -- numpy=1.26.2 -- openjdk=21.0.1 -- openjpeg=2.5.0 -- openpyxl=3.1.2 -- openssl=3.2.0 -- orc=1.9.2 -- overrides=7.4.0 -- packaging=23.2 -- pandas=2.1.4 -- pandoc=3.1.3 -- pandocfilters=1.5.0 -- pango=1.50.14 -- parso=0.8.3 -- partd=1.4.1 -- patsy=0.5.5 -- pcre2=10.42 -- pexpect=4.8.0 -- pickleshare=0.7.5 -- pillow=10.2.0 -- pip=23.3.2 -- pixman=0.42.2 -- pkgutil-resolve-name=1.3.10 -- plac=1.4.2 -- platformdirs=4.1.0 -- pluggy=1.3.0 -- ply=3.11 -- poppler=23.12.0 -- poppler-data=0.4.12 -- postgresql=16.1 -- powerplantmatching=0.5.8 -- progressbar2=4.3.2 -- proj=9.3.0 -- prometheus_client=0.19.0 -- prompt-toolkit=3.0.42 -- prompt_toolkit=3.0.42 -- psutil=5.9.7 -- pthread-stubs=0.4 -- ptyprocess=0.7.0 -- pulp=2.7.0 -- pulseaudio-client=16.1 -- pure_eval=0.2.2 -- py-cpuinfo=9.0.0 -- pyarrow=14.0.2 -- pyarrow-hotfix=0.6 -- pycountry=22.3.5 -- pycparser=2.21 -- pygments=2.17.2 -- pyomo=6.6.1 -- pyparsing=3.1.1 -- pyproj=3.6.1 -- pypsa=0.26.2 -- pyqt=5.15.9 -- pyqt5-sip=12.12.2 -- pyshp=2.3.1 -- pysocks=1.7.1 -- pytables=3.9.2 -- pytest=7.4.4 -- python=3.11.7 -- python-dateutil=2.8.2 -- python-fastjsonschema=2.19.1 -- python-json-logger=2.0.7 -- python-tzdata=2023.4 -- python-utils=3.8.1 -- python_abi=3.11 -- pytz=2023.3.post1 -- pyxlsb=1.0.10 -- pyyaml=6.0.1 -- pyzmq=25.1.2 -- qt-main=5.15.8 -- qtconsole-base=5.5.1 -- qtpy=2.4.1 -- rasterio=1.3.9 -- rdma-core=49.0 -- re2=2023.06.02 -- readline=8.2 -- referencing=0.32.0 -- requests=2.31.0 -- reretry=0.11.8 -- rfc3339-validator=0.1.4 -- rfc3986-validator=0.1.1 -- rioxarray=0.15.0 -- rpds-py=0.16.2 -- rtree=1.1.0 -- s2n=1.4.1 -- scikit-learn=1.3.2 -- scipy=1.11.4 -- scotch=6.0.9 -- seaborn=0.13.0 -- seaborn-base=0.13.0 -- send2trash=1.8.2 -- setuptools=69.0.3 -- setuptools-scm=8.0.4 -- setuptools_scm=8.0.4 -- shapely=2.0.2 -- sip=6.7.12 -- six=1.16.0 -- smart_open=6.4.0 -- smmap=5.0.0 -- snakemake-minimal=7.32.4 -- snappy=1.1.10 -- sniffio=1.3.0 -- snuggs=1.4.7 -- sortedcontainers=2.4.0 -- soupsieve=2.5 -- sqlite=3.44.2 -- stack_data=0.6.2 -- statsmodels=0.14.1 -- stopit=1.1.2 -- tabula-py=2.7.0 -- tabulate=0.9.0 -- tblib=3.0.0 -- terminado=0.18.0 -- threadpoolctl=3.2.0 -- throttler=1.2.2 -- tiledb=2.18.2 -- tinycss2=1.2.1 -- tk=8.6.13 -- toml=0.10.2 -- tomli=2.0.1 -- toolz=0.12.0 -- toposort=1.10 -- tornado=6.3.3 -- tqdm=4.66.1 -- traitlets=5.14.1 -- types-python-dateutil=2.8.19.14 -- typing-extensions=4.9.0 -- typing_extensions=4.9.0 -- typing_utils=0.1.0 -- tzcode=2023d -- tzdata=2023d -- ucx=1.15.0 -- unidecode=1.3.7 -- unixodbc=2.3.12 -- uri-template=1.3.0 -- uriparser=0.9.7 -- urllib3=2.1.0 -- validators=0.22.0 -- wcwidth=0.2.12 -- webcolors=1.13 -- webencodings=0.5.1 -- websocket-client=1.7.0 -- wheel=0.42.0 -- widgetsnbextension=4.0.9 -- wrapt=1.16.0 -- xarray=2023.12.0 -- xcb-util=0.4.0 -- xcb-util-image=0.4.0 -- xcb-util-keysyms=0.4.0 -- xcb-util-renderutil=0.3.9 -- xcb-util-wm=0.4.1 -- xerces-c=3.2.5 -- xkeyboard-config=2.40 -- xlrd=2.0.1 -- xorg-fixesproto=5.0 -- xorg-inputproto=2.3.2 -- xorg-kbproto=1.0.7 -- xorg-libice=1.1.1 -- xorg-libsm=1.2.4 -- xorg-libx11=1.8.7 -- xorg-libxau=1.0.11 -- xorg-libxdmcp=1.1.3 -- xorg-libxext=1.3.4 -- xorg-libxfixes=5.0.3 -- xorg-libxi=1.7.10 -- xorg-libxrender=0.9.11 -- xorg-libxt=1.3.0 -- xorg-libxtst=1.2.3 -- xorg-recordproto=1.14.2 -- xorg-renderproto=0.11.1 -- xorg-xextproto=7.3.0 -- xorg-xf86vidmodeproto=2.3.1 -- xorg-xproto=7.0.31 -- xyzservices=2023.10.1 -- xz=5.2.6 -- yaml=0.2.5 -- yte=1.5.4 -- zeromq=4.3.5 -- zict=3.0.0 -- zipp=3.17.0 -- zlib=1.2.13 -- zlib-ng=2.0.7 -- zstd=1.5.5 -- pip: - - highspy==1.5.3 - - tsam==2.3.1 + - _libgcc_mutex=0.1 + - _openmp_mutex=4.5 + - affine=2.4.0 + - alsa-lib=1.2.10 + - ampl-mp=3.1.0 + - amply=0.1.6 + - appdirs=1.4.4 + - asttokens=2.4.1 + - atk-1.0=2.38.0 + - atlite=0.2.12 + - attr=2.5.1 + - attrs=23.2.0 + - aws-c-auth=0.7.15 + - aws-c-cal=0.6.9 + - aws-c-common=0.9.12 + - aws-c-compression=0.2.17 + - aws-c-event-stream=0.4.1 + - aws-c-http=0.8.0 + - aws-c-io=0.14.3 + - aws-c-mqtt=0.10.1 + - aws-c-s3=0.5.0 + - aws-c-sdkutils=0.1.14 + - aws-checksums=0.1.17 + - aws-crt-cpp=0.26.1 + - aws-sdk-cpp=1.11.242 + - azure-core-cpp=1.10.3 + - azure-storage-blobs-cpp=12.10.0 + - azure-storage-common-cpp=12.5.0 + - beautifulsoup4=4.12.3 + - blosc=1.21.5 + - bokeh=3.3.4 + - bottleneck=1.3.7 + - branca=0.7.1 + - brotli=1.1.0 + - brotli-bin=1.1.0 + - brotli-python=1.1.0 + - bzip2=1.0.8 + - c-ares=1.26.0 + - c-blosc2=2.13.2 + - ca-certificates=2024.2.2 + - cairo=1.18.0 + - cartopy=0.22.0 + - cdsapi=0.6.1 + - certifi=2024.2.2 + - cffi=1.16.0 + - cfgv=3.3.1 + - cfitsio=4.3.1 + - cftime=1.6.3 + - charset-normalizer=3.3.2 + - click=8.1.7 + - click-plugins=1.1.1 + - cligj=0.7.2 + - cloudpickle=3.0.0 + - coin-or-cbc=2.10.10 + - coin-or-cgl=0.60.7 + - coin-or-clp=1.17.8 + - coin-or-osi=0.108.8 + - coin-or-utils=2.11.9 + - coincbc=2.10.10 + - colorama=0.4.6 + - configargparse=1.7 + - connection_pool=0.0.3 + - contourpy=1.2.0 + - country_converter=1.2 + - cppad=20240000.2 + - cycler=0.12.1 + - cytoolz=0.12.3 + - dask=2024.2.0 + - dask-core=2024.2.0 + - datrie=0.8.2 + - dbus=1.13.6 + - decorator=5.1.1 + - deprecation=2.1.0 + - descartes=1.1.0 + - distlib=0.3.8 + - distributed=2024.2.0 + - distro=1.9.0 + - docutils=0.20.1 + - dpath=2.1.6 + - entsoe-py=0.6.6 + - et_xmlfile=1.1.0 + - exceptiongroup=1.2.0 + - executing=2.0.1 + - expat=2.5.0 + - filelock=3.13.1 + - fiona=1.9.5 + - folium=0.15.1 + - font-ttf-dejavu-sans-mono=2.37 + - font-ttf-inconsolata=3.000 + - font-ttf-source-code-pro=2.038 + - font-ttf-ubuntu=0.83 + - fontconfig=2.14.2 + - fonts-conda-ecosystem=1 + - fonts-conda-forge=1 + - fonttools=4.49.0 + - freetype=2.12.1 + - freexl=2.0.0 + - fribidi=1.0.10 + - fsspec=2024.2.0 + - gdal=3.8.4 + - gdk-pixbuf=2.42.10 + - geographiclib=1.52 + - geojson-rewind=1.1.0 + - geopandas=0.14.3 + - geopandas-base=0.14.3 + - geopy=2.4.1 + - geos=3.12.1 + - geotiff=1.7.1 + - gettext=0.21.1 + - gflags=2.2.2 + - giflib=5.2.1 + - gitdb=4.0.11 + - gitpython=3.1.42 + - glib=2.78.4 + - glib-tools=2.78.4 + - glog=0.6.0 + - glpk=5.0 + - gmp=6.3.0 + - graphite2=1.3.13 + - graphviz=9.0.0 + - gst-plugins-base=1.22.9 + - gstreamer=1.22.9 + - gtk2=2.24.33 + - gts=0.7.6 + - harfbuzz=8.3.0 + - hdf4=4.2.15 + - hdf5=1.14.3 + - humanfriendly=10.0 + - icu=73.2 + - identify=2.5.35 + - idna=3.6 + - importlib-metadata=7.0.1 + - importlib_metadata=7.0.1 + - importlib_resources=6.1.1 + - iniconfig=2.0.0 + - ipopt=3.14.14 + - ipython=8.21.0 + - jedi=0.19.1 + - jinja2=3.1.3 + - joblib=1.3.2 + - json-c=0.17 + - jsonschema=4.21.1 + - jsonschema-specifications=2023.12.1 + - jupyter_core=5.7.1 + - kealib=1.5.3 + - keyutils=1.6.1 + - kiwisolver=1.4.5 + - krb5=1.21.2 + - lame=3.100 + - lcms2=2.16 + - ld_impl_linux-64=2.40 + - lerc=4.0.0 + - libabseil=20230802.1 + - libaec=1.1.2 + - libarchive=3.7.2 + - libarrow=15.0.0 + - libarrow-acero=15.0.0 + - libarrow-dataset=15.0.0 + - libarrow-flight=15.0.0 + - libarrow-flight-sql=15.0.0 + - libarrow-gandiva=15.0.0 + - libarrow-substrait=15.0.0 + - libblas=3.9.0 + - libboost-headers=1.84.0 + - libbrotlicommon=1.1.0 + - libbrotlidec=1.1.0 + - libbrotlienc=1.1.0 + - libcap=2.69 + - libcblas=3.9.0 + - libclang=15.0.7 + - libclang13=15.0.7 + - libcrc32c=1.1.2 + - libcups=2.3.3 + - libcurl=8.5.0 + - libdeflate=1.19 + - libedit=3.1.20191231 + - libev=4.33 + - libevent=2.1.12 + - libexpat=2.5.0 + - libffi=3.4.2 + - libflac=1.4.3 + - libgcc-ng=13.2.0 + - libgcrypt=1.10.3 + - libgd=2.3.3 + - libgdal=3.8.4 + - libgfortran-ng=13.2.0 + - libgfortran5=13.2.0 + - libglib=2.78.4 + - libgomp=13.2.0 + - libgoogle-cloud=2.12.0 + - libgpg-error=1.47 + - libgrpc=1.60.1 + - libhwloc=2.9.3 + - libiconv=1.17 + - libjpeg-turbo=3.0.0 + - libkml=1.3.0 + - liblapack=3.9.0 + - liblapacke=3.9.0 + - libllvm15=15.0.7 + - libnetcdf=4.9.2 + - libnghttp2=1.58.0 + - libnl=3.9.0 + - libnsl=2.0.1 + - libnuma=2.0.16 + - libogg=1.3.4 + - libopenblas=0.3.26 + - libopus=1.3.1 + - libparquet=15.0.0 + - libpng=1.6.42 + - libpq=16.2 + - libprotobuf=4.25.1 + - libre2-11=2023.06.02 + - librsvg=2.56.3 + - librttopo=1.1.0 + - libscotch=7.0.4 + - libsndfile=1.2.2 + - libspatialindex=1.9.3 + - libspatialite=5.1.0 + - libspral=2023.09.07 + - libsqlite=3.45.1 + - libssh2=1.11.0 + - libstdcxx-ng=13.2.0 + - libsystemd0=255 + - libthrift=0.19.0 + - libtiff=4.6.0 + - libutf8proc=2.8.0 + - libuuid=2.38.1 + - libvorbis=1.3.7 + - libwebp=1.3.2 + - libwebp-base=1.3.2 + - libxcb=1.15 + - libxcrypt=4.4.36 + - libxkbcommon=1.6.0 + - libxml2=2.12.5 + - libxslt=1.1.39 + - libzip=1.10.1 + - libzlib=1.2.13 + - linopy=0.3.4 + - locket=1.0.0 + - lxml=5.1.0 + - lz4=4.3.3 + - lz4-c=1.9.4 + - lzo=2.10 + - mapclassify=2.6.1 + - markupsafe=2.1.5 + - matplotlib=3.8.3 + - matplotlib-base=3.8.3 + - matplotlib-inline=0.1.6 + - memory_profiler=0.61.0 + - metis=5.1.0 + - minizip=4.0.4 + - mpg123=1.32.4 + - msgpack-python=1.0.7 + - mumps-include=5.6.2 + - mumps-seq=5.6.2 + - munkres=1.1.4 + - mysql-common=8.0.33 + - mysql-libs=8.0.33 + - nbformat=5.9.2 + - ncurses=6.4 + - netcdf4=1.6.5 + - networkx=3.2.1 + - nodeenv=1.8.0 + - nomkl=1.0 + - nspr=4.35 + - nss=3.98 + - numexpr=2.9.0 + - numpy=1.26.4 + - openjdk=21.0.2 + - openjpeg=2.5.0 + - openpyxl=3.1.2 + - openssl=3.2.1 + - orc=1.9.2 + - packaging=23.2 + - pandas=2.2.0 + - pango=1.50.14 + - parso=0.8.3 + - partd=1.4.1 + - patsy=0.5.6 + - pcre2=10.42 + - pexpect=4.9.0 + - pickleshare=0.7.5 + - pillow=10.2.0 + - pip=24.0 + - pixman=0.43.2 + - pkgutil-resolve-name=1.3.10 + - plac=1.4.2 + - platformdirs=4.2.0 + - pluggy=1.4.0 + - ply=3.11 + - poppler=24.02.0 + - poppler-data=0.4.12 + - postgresql=16.2 + - powerplantmatching=0.5.11 + - pre-commit=3.6.2 + - progressbar2=4.3.2 + - proj=9.3.1 + - prompt-toolkit=3.0.42 + - psutil=5.9.8 + - pthread-stubs=0.4 + - ptyprocess=0.7.0 + - pulp=2.7.0 + - pulseaudio-client=16.1 + - pure_eval=0.2.2 + - py-cpuinfo=9.0.0 + - pyarrow=15.0.0 + - pyarrow-hotfix=0.6 + - pycountry=22.3.5 + - pycparser=2.21 + - pygments=2.17.2 + - pyomo=6.6.1 + - pyparsing=3.1.1 + - pyproj=3.6.1 + - pypsa=0.27.0 + - pyqt=5.15.9 + - pyqt5-sip=12.12.2 + - pyscipopt=4.4.0 + - pyshp=2.3.1 + - pysocks=1.7.1 + - pytables=3.9.2 + - pytest=8.0.0 + - python=3.11.8 + - python-dateutil=2.8.2 + - python-fastjsonschema=2.19.1 + - python-tzdata=2024.1 + - python-utils=3.8.2 + - python_abi=3.11 + - pytz=2024.1 + - pyxlsb=1.0.10 + - pyyaml=6.0.1 + - qt-main=5.15.8 + - rasterio=1.3.9 + - rdma-core=50.0 + - re2=2023.06.02 + - readline=8.2 + - referencing=0.33.0 + - requests=2.31.0 + - reretry=0.11.8 + - rioxarray=0.15.1 + - rpds-py=0.18.0 + - rtree=1.2.0 + - s2n=1.4.3 + - scikit-learn=1.4.1.post1 + - scip=8.1.0 + - scipy=1.12.0 + - scotch=7.0.4 + - seaborn=0.13.2 + - seaborn-base=0.13.2 + - setuptools=69.1.0 + - setuptools-scm=8.0.4 + - setuptools_scm=8.0.4 + - shapely=2.0.2 + - sip=6.7.12 + - six=1.16.0 + - smart_open=6.4.0 + - smmap=5.0.0 + - snakemake-minimal=7.32.4 + - snappy=1.1.10 + - snuggs=1.4.7 + - sortedcontainers=2.4.0 + - soupsieve=2.5 + - sqlite=3.45.1 + - stack_data=0.6.2 + - statsmodels=0.14.1 + - stopit=1.1.2 + - tabula-py=2.7.0 + - tabulate=0.9.0 + - tbb=2021.11.0 + - tblib=3.0.0 + - threadpoolctl=3.3.0 + - throttler=1.2.2 + - tiledb=2.20.0 + - tk=8.6.13 + - toml=0.10.2 + - tomli=2.0.1 + - toolz=0.12.1 + - toposort=1.10 + - tornado=6.3.3 + - tqdm=4.66.2 + - traitlets=5.14.1 + - typing-extensions=4.9.0 + - typing_extensions=4.9.0 + - tzcode=2024a + - tzdata=2024a + - ucx=1.15.0 + - ukkonen=1.0.1 + - unidecode=1.3.8 + - unixodbc=2.3.12 + - uriparser=0.9.7 + - urllib3=2.2.1 + - validators=0.22.0 + - virtualenv=20.25.0 + - wcwidth=0.2.13 + - wheel=0.42.0 + - wrapt=1.16.0 + - xarray=2024.2.0 + - xcb-util=0.4.0 + - xcb-util-image=0.4.0 + - xcb-util-keysyms=0.4.0 + - xcb-util-renderutil=0.3.9 + - xcb-util-wm=0.4.1 + - xerces-c=3.2.5 + - xkeyboard-config=2.41 + - xlrd=2.0.1 + - xorg-fixesproto=5.0 + - xorg-inputproto=2.3.2 + - xorg-kbproto=1.0.7 + - xorg-libice=1.1.1 + - xorg-libsm=1.2.4 + - xorg-libx11=1.8.7 + - xorg-libxau=1.0.11 + - xorg-libxdmcp=1.1.3 + - xorg-libxext=1.3.4 + - xorg-libxfixes=5.0.3 + - xorg-libxi=1.7.10 + - xorg-libxrender=0.9.11 + - xorg-libxt=1.3.0 + - xorg-libxtst=1.2.3 + - xorg-recordproto=1.14.2 + - xorg-renderproto=0.11.1 + - xorg-xextproto=7.3.0 + - xorg-xf86vidmodeproto=2.3.1 + - xorg-xproto=7.0.31 + - xyzservices=2023.10.1 + - xz=5.2.6 + - yaml=0.2.5 + - yte=1.5.4 + - zict=3.0.0 + - zipp=3.17.0 + - zlib=1.2.13 + - zlib-ng=2.0.7 + - zstd=1.5.5 + - pip: + - highspy==1.5.3 + - tsam==2.3.1 From 479bc707277b09182409ae5f4ec54879384eb5e4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 19:36:18 +0000 Subject: [PATCH 356/591] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 24.1.1 → 24.2.0](https://github.com/psf/black-pre-commit-mirror/compare/24.1.1...24.2.0) --- .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 5c41e781..28d0278a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,7 +51,7 @@ repos: # Formatting with "black" coding style - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.1.1 + rev: 24.2.0 hooks: # Format Python files - id: black From e68743ffa6601bcbdf02025372841211e58bac2e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 19:36:37 +0000 Subject: [PATCH 357/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- envs/environment.fixed.yaml | 878 ++++++++++++++++++------------------ 1 file changed, 439 insertions(+), 439 deletions(-) diff --git a/envs/environment.fixed.yaml b/envs/environment.fixed.yaml index cde0b801..8bbd70bf 100644 --- a/envs/environment.fixed.yaml +++ b/envs/environment.fixed.yaml @@ -4,443 +4,443 @@ name: pypsa-eur channels: - - bioconda - - http://conda.anaconda.org/gurobi - - conda-forge - - defaults +- bioconda +- http://conda.anaconda.org/gurobi +- conda-forge +- defaults dependencies: - - _libgcc_mutex=0.1 - - _openmp_mutex=4.5 - - affine=2.4.0 - - alsa-lib=1.2.10 - - ampl-mp=3.1.0 - - amply=0.1.6 - - appdirs=1.4.4 - - asttokens=2.4.1 - - atk-1.0=2.38.0 - - atlite=0.2.12 - - attr=2.5.1 - - attrs=23.2.0 - - aws-c-auth=0.7.15 - - aws-c-cal=0.6.9 - - aws-c-common=0.9.12 - - aws-c-compression=0.2.17 - - aws-c-event-stream=0.4.1 - - aws-c-http=0.8.0 - - aws-c-io=0.14.3 - - aws-c-mqtt=0.10.1 - - aws-c-s3=0.5.0 - - aws-c-sdkutils=0.1.14 - - aws-checksums=0.1.17 - - aws-crt-cpp=0.26.1 - - aws-sdk-cpp=1.11.242 - - azure-core-cpp=1.10.3 - - azure-storage-blobs-cpp=12.10.0 - - azure-storage-common-cpp=12.5.0 - - beautifulsoup4=4.12.3 - - blosc=1.21.5 - - bokeh=3.3.4 - - bottleneck=1.3.7 - - branca=0.7.1 - - brotli=1.1.0 - - brotli-bin=1.1.0 - - brotli-python=1.1.0 - - bzip2=1.0.8 - - c-ares=1.26.0 - - c-blosc2=2.13.2 - - ca-certificates=2024.2.2 - - cairo=1.18.0 - - cartopy=0.22.0 - - cdsapi=0.6.1 - - certifi=2024.2.2 - - cffi=1.16.0 - - cfgv=3.3.1 - - cfitsio=4.3.1 - - cftime=1.6.3 - - charset-normalizer=3.3.2 - - click=8.1.7 - - click-plugins=1.1.1 - - cligj=0.7.2 - - cloudpickle=3.0.0 - - coin-or-cbc=2.10.10 - - coin-or-cgl=0.60.7 - - coin-or-clp=1.17.8 - - coin-or-osi=0.108.8 - - coin-or-utils=2.11.9 - - coincbc=2.10.10 - - colorama=0.4.6 - - configargparse=1.7 - - connection_pool=0.0.3 - - contourpy=1.2.0 - - country_converter=1.2 - - cppad=20240000.2 - - cycler=0.12.1 - - cytoolz=0.12.3 - - dask=2024.2.0 - - dask-core=2024.2.0 - - datrie=0.8.2 - - dbus=1.13.6 - - decorator=5.1.1 - - deprecation=2.1.0 - - descartes=1.1.0 - - distlib=0.3.8 - - distributed=2024.2.0 - - distro=1.9.0 - - docutils=0.20.1 - - dpath=2.1.6 - - entsoe-py=0.6.6 - - et_xmlfile=1.1.0 - - exceptiongroup=1.2.0 - - executing=2.0.1 - - expat=2.5.0 - - filelock=3.13.1 - - fiona=1.9.5 - - folium=0.15.1 - - font-ttf-dejavu-sans-mono=2.37 - - font-ttf-inconsolata=3.000 - - font-ttf-source-code-pro=2.038 - - font-ttf-ubuntu=0.83 - - fontconfig=2.14.2 - - fonts-conda-ecosystem=1 - - fonts-conda-forge=1 - - fonttools=4.49.0 - - freetype=2.12.1 - - freexl=2.0.0 - - fribidi=1.0.10 - - fsspec=2024.2.0 - - gdal=3.8.4 - - gdk-pixbuf=2.42.10 - - geographiclib=1.52 - - geojson-rewind=1.1.0 - - geopandas=0.14.3 - - geopandas-base=0.14.3 - - geopy=2.4.1 - - geos=3.12.1 - - geotiff=1.7.1 - - gettext=0.21.1 - - gflags=2.2.2 - - giflib=5.2.1 - - gitdb=4.0.11 - - gitpython=3.1.42 - - glib=2.78.4 - - glib-tools=2.78.4 - - glog=0.6.0 - - glpk=5.0 - - gmp=6.3.0 - - graphite2=1.3.13 - - graphviz=9.0.0 - - gst-plugins-base=1.22.9 - - gstreamer=1.22.9 - - gtk2=2.24.33 - - gts=0.7.6 - - harfbuzz=8.3.0 - - hdf4=4.2.15 - - hdf5=1.14.3 - - humanfriendly=10.0 - - icu=73.2 - - identify=2.5.35 - - idna=3.6 - - importlib-metadata=7.0.1 - - importlib_metadata=7.0.1 - - importlib_resources=6.1.1 - - iniconfig=2.0.0 - - ipopt=3.14.14 - - ipython=8.21.0 - - jedi=0.19.1 - - jinja2=3.1.3 - - joblib=1.3.2 - - json-c=0.17 - - jsonschema=4.21.1 - - jsonschema-specifications=2023.12.1 - - jupyter_core=5.7.1 - - kealib=1.5.3 - - keyutils=1.6.1 - - kiwisolver=1.4.5 - - krb5=1.21.2 - - lame=3.100 - - lcms2=2.16 - - ld_impl_linux-64=2.40 - - lerc=4.0.0 - - libabseil=20230802.1 - - libaec=1.1.2 - - libarchive=3.7.2 - - libarrow=15.0.0 - - libarrow-acero=15.0.0 - - libarrow-dataset=15.0.0 - - libarrow-flight=15.0.0 - - libarrow-flight-sql=15.0.0 - - libarrow-gandiva=15.0.0 - - libarrow-substrait=15.0.0 - - libblas=3.9.0 - - libboost-headers=1.84.0 - - libbrotlicommon=1.1.0 - - libbrotlidec=1.1.0 - - libbrotlienc=1.1.0 - - libcap=2.69 - - libcblas=3.9.0 - - libclang=15.0.7 - - libclang13=15.0.7 - - libcrc32c=1.1.2 - - libcups=2.3.3 - - libcurl=8.5.0 - - libdeflate=1.19 - - libedit=3.1.20191231 - - libev=4.33 - - libevent=2.1.12 - - libexpat=2.5.0 - - libffi=3.4.2 - - libflac=1.4.3 - - libgcc-ng=13.2.0 - - libgcrypt=1.10.3 - - libgd=2.3.3 - - libgdal=3.8.4 - - libgfortran-ng=13.2.0 - - libgfortran5=13.2.0 - - libglib=2.78.4 - - libgomp=13.2.0 - - libgoogle-cloud=2.12.0 - - libgpg-error=1.47 - - libgrpc=1.60.1 - - libhwloc=2.9.3 - - libiconv=1.17 - - libjpeg-turbo=3.0.0 - - libkml=1.3.0 - - liblapack=3.9.0 - - liblapacke=3.9.0 - - libllvm15=15.0.7 - - libnetcdf=4.9.2 - - libnghttp2=1.58.0 - - libnl=3.9.0 - - libnsl=2.0.1 - - libnuma=2.0.16 - - libogg=1.3.4 - - libopenblas=0.3.26 - - libopus=1.3.1 - - libparquet=15.0.0 - - libpng=1.6.42 - - libpq=16.2 - - libprotobuf=4.25.1 - - libre2-11=2023.06.02 - - librsvg=2.56.3 - - librttopo=1.1.0 - - libscotch=7.0.4 - - libsndfile=1.2.2 - - libspatialindex=1.9.3 - - libspatialite=5.1.0 - - libspral=2023.09.07 - - libsqlite=3.45.1 - - libssh2=1.11.0 - - libstdcxx-ng=13.2.0 - - libsystemd0=255 - - libthrift=0.19.0 - - libtiff=4.6.0 - - libutf8proc=2.8.0 - - libuuid=2.38.1 - - libvorbis=1.3.7 - - libwebp=1.3.2 - - libwebp-base=1.3.2 - - libxcb=1.15 - - libxcrypt=4.4.36 - - libxkbcommon=1.6.0 - - libxml2=2.12.5 - - libxslt=1.1.39 - - libzip=1.10.1 - - libzlib=1.2.13 - - linopy=0.3.4 - - locket=1.0.0 - - lxml=5.1.0 - - lz4=4.3.3 - - lz4-c=1.9.4 - - lzo=2.10 - - mapclassify=2.6.1 - - markupsafe=2.1.5 - - matplotlib=3.8.3 - - matplotlib-base=3.8.3 - - matplotlib-inline=0.1.6 - - memory_profiler=0.61.0 - - metis=5.1.0 - - minizip=4.0.4 - - mpg123=1.32.4 - - msgpack-python=1.0.7 - - mumps-include=5.6.2 - - mumps-seq=5.6.2 - - munkres=1.1.4 - - mysql-common=8.0.33 - - mysql-libs=8.0.33 - - nbformat=5.9.2 - - ncurses=6.4 - - netcdf4=1.6.5 - - networkx=3.2.1 - - nodeenv=1.8.0 - - nomkl=1.0 - - nspr=4.35 - - nss=3.98 - - numexpr=2.9.0 - - numpy=1.26.4 - - openjdk=21.0.2 - - openjpeg=2.5.0 - - openpyxl=3.1.2 - - openssl=3.2.1 - - orc=1.9.2 - - packaging=23.2 - - pandas=2.2.0 - - pango=1.50.14 - - parso=0.8.3 - - partd=1.4.1 - - patsy=0.5.6 - - pcre2=10.42 - - pexpect=4.9.0 - - pickleshare=0.7.5 - - pillow=10.2.0 - - pip=24.0 - - pixman=0.43.2 - - pkgutil-resolve-name=1.3.10 - - plac=1.4.2 - - platformdirs=4.2.0 - - pluggy=1.4.0 - - ply=3.11 - - poppler=24.02.0 - - poppler-data=0.4.12 - - postgresql=16.2 - - powerplantmatching=0.5.11 - - pre-commit=3.6.2 - - progressbar2=4.3.2 - - proj=9.3.1 - - prompt-toolkit=3.0.42 - - psutil=5.9.8 - - pthread-stubs=0.4 - - ptyprocess=0.7.0 - - pulp=2.7.0 - - pulseaudio-client=16.1 - - pure_eval=0.2.2 - - py-cpuinfo=9.0.0 - - pyarrow=15.0.0 - - pyarrow-hotfix=0.6 - - pycountry=22.3.5 - - pycparser=2.21 - - pygments=2.17.2 - - pyomo=6.6.1 - - pyparsing=3.1.1 - - pyproj=3.6.1 - - pypsa=0.27.0 - - pyqt=5.15.9 - - pyqt5-sip=12.12.2 - - pyscipopt=4.4.0 - - pyshp=2.3.1 - - pysocks=1.7.1 - - pytables=3.9.2 - - pytest=8.0.0 - - python=3.11.8 - - python-dateutil=2.8.2 - - python-fastjsonschema=2.19.1 - - python-tzdata=2024.1 - - python-utils=3.8.2 - - python_abi=3.11 - - pytz=2024.1 - - pyxlsb=1.0.10 - - pyyaml=6.0.1 - - qt-main=5.15.8 - - rasterio=1.3.9 - - rdma-core=50.0 - - re2=2023.06.02 - - readline=8.2 - - referencing=0.33.0 - - requests=2.31.0 - - reretry=0.11.8 - - rioxarray=0.15.1 - - rpds-py=0.18.0 - - rtree=1.2.0 - - s2n=1.4.3 - - scikit-learn=1.4.1.post1 - - scip=8.1.0 - - scipy=1.12.0 - - scotch=7.0.4 - - seaborn=0.13.2 - - seaborn-base=0.13.2 - - setuptools=69.1.0 - - setuptools-scm=8.0.4 - - setuptools_scm=8.0.4 - - shapely=2.0.2 - - sip=6.7.12 - - six=1.16.0 - - smart_open=6.4.0 - - smmap=5.0.0 - - snakemake-minimal=7.32.4 - - snappy=1.1.10 - - snuggs=1.4.7 - - sortedcontainers=2.4.0 - - soupsieve=2.5 - - sqlite=3.45.1 - - stack_data=0.6.2 - - statsmodels=0.14.1 - - stopit=1.1.2 - - tabula-py=2.7.0 - - tabulate=0.9.0 - - tbb=2021.11.0 - - tblib=3.0.0 - - threadpoolctl=3.3.0 - - throttler=1.2.2 - - tiledb=2.20.0 - - tk=8.6.13 - - toml=0.10.2 - - tomli=2.0.1 - - toolz=0.12.1 - - toposort=1.10 - - tornado=6.3.3 - - tqdm=4.66.2 - - traitlets=5.14.1 - - typing-extensions=4.9.0 - - typing_extensions=4.9.0 - - tzcode=2024a - - tzdata=2024a - - ucx=1.15.0 - - ukkonen=1.0.1 - - unidecode=1.3.8 - - unixodbc=2.3.12 - - uriparser=0.9.7 - - urllib3=2.2.1 - - validators=0.22.0 - - virtualenv=20.25.0 - - wcwidth=0.2.13 - - wheel=0.42.0 - - wrapt=1.16.0 - - xarray=2024.2.0 - - xcb-util=0.4.0 - - xcb-util-image=0.4.0 - - xcb-util-keysyms=0.4.0 - - xcb-util-renderutil=0.3.9 - - xcb-util-wm=0.4.1 - - xerces-c=3.2.5 - - xkeyboard-config=2.41 - - xlrd=2.0.1 - - xorg-fixesproto=5.0 - - xorg-inputproto=2.3.2 - - xorg-kbproto=1.0.7 - - xorg-libice=1.1.1 - - xorg-libsm=1.2.4 - - xorg-libx11=1.8.7 - - xorg-libxau=1.0.11 - - xorg-libxdmcp=1.1.3 - - xorg-libxext=1.3.4 - - xorg-libxfixes=5.0.3 - - xorg-libxi=1.7.10 - - xorg-libxrender=0.9.11 - - xorg-libxt=1.3.0 - - xorg-libxtst=1.2.3 - - xorg-recordproto=1.14.2 - - xorg-renderproto=0.11.1 - - xorg-xextproto=7.3.0 - - xorg-xf86vidmodeproto=2.3.1 - - xorg-xproto=7.0.31 - - xyzservices=2023.10.1 - - xz=5.2.6 - - yaml=0.2.5 - - yte=1.5.4 - - zict=3.0.0 - - zipp=3.17.0 - - zlib=1.2.13 - - zlib-ng=2.0.7 - - zstd=1.5.5 - - pip: - - highspy==1.5.3 - - tsam==2.3.1 +- _libgcc_mutex=0.1 +- _openmp_mutex=4.5 +- affine=2.4.0 +- alsa-lib=1.2.10 +- ampl-mp=3.1.0 +- amply=0.1.6 +- appdirs=1.4.4 +- asttokens=2.4.1 +- atk-1.0=2.38.0 +- atlite=0.2.12 +- attr=2.5.1 +- attrs=23.2.0 +- aws-c-auth=0.7.15 +- aws-c-cal=0.6.9 +- aws-c-common=0.9.12 +- aws-c-compression=0.2.17 +- aws-c-event-stream=0.4.1 +- aws-c-http=0.8.0 +- aws-c-io=0.14.3 +- aws-c-mqtt=0.10.1 +- aws-c-s3=0.5.0 +- aws-c-sdkutils=0.1.14 +- aws-checksums=0.1.17 +- aws-crt-cpp=0.26.1 +- aws-sdk-cpp=1.11.242 +- azure-core-cpp=1.10.3 +- azure-storage-blobs-cpp=12.10.0 +- azure-storage-common-cpp=12.5.0 +- beautifulsoup4=4.12.3 +- blosc=1.21.5 +- bokeh=3.3.4 +- bottleneck=1.3.7 +- branca=0.7.1 +- brotli=1.1.0 +- brotli-bin=1.1.0 +- brotli-python=1.1.0 +- bzip2=1.0.8 +- c-ares=1.26.0 +- c-blosc2=2.13.2 +- ca-certificates=2024.2.2 +- cairo=1.18.0 +- cartopy=0.22.0 +- cdsapi=0.6.1 +- certifi=2024.2.2 +- cffi=1.16.0 +- cfgv=3.3.1 +- cfitsio=4.3.1 +- cftime=1.6.3 +- charset-normalizer=3.3.2 +- click=8.1.7 +- click-plugins=1.1.1 +- cligj=0.7.2 +- cloudpickle=3.0.0 +- coin-or-cbc=2.10.10 +- coin-or-cgl=0.60.7 +- coin-or-clp=1.17.8 +- coin-or-osi=0.108.8 +- coin-or-utils=2.11.9 +- coincbc=2.10.10 +- colorama=0.4.6 +- configargparse=1.7 +- connection_pool=0.0.3 +- contourpy=1.2.0 +- country_converter=1.2 +- cppad=20240000.2 +- cycler=0.12.1 +- cytoolz=0.12.3 +- dask=2024.2.0 +- dask-core=2024.2.0 +- datrie=0.8.2 +- dbus=1.13.6 +- decorator=5.1.1 +- deprecation=2.1.0 +- descartes=1.1.0 +- distlib=0.3.8 +- distributed=2024.2.0 +- distro=1.9.0 +- docutils=0.20.1 +- dpath=2.1.6 +- entsoe-py=0.6.6 +- et_xmlfile=1.1.0 +- exceptiongroup=1.2.0 +- executing=2.0.1 +- expat=2.5.0 +- filelock=3.13.1 +- fiona=1.9.5 +- folium=0.15.1 +- font-ttf-dejavu-sans-mono=2.37 +- font-ttf-inconsolata=3.000 +- font-ttf-source-code-pro=2.038 +- font-ttf-ubuntu=0.83 +- fontconfig=2.14.2 +- fonts-conda-ecosystem=1 +- fonts-conda-forge=1 +- fonttools=4.49.0 +- freetype=2.12.1 +- freexl=2.0.0 +- fribidi=1.0.10 +- fsspec=2024.2.0 +- gdal=3.8.4 +- gdk-pixbuf=2.42.10 +- geographiclib=1.52 +- geojson-rewind=1.1.0 +- geopandas=0.14.3 +- geopandas-base=0.14.3 +- geopy=2.4.1 +- geos=3.12.1 +- geotiff=1.7.1 +- gettext=0.21.1 +- gflags=2.2.2 +- giflib=5.2.1 +- gitdb=4.0.11 +- gitpython=3.1.42 +- glib=2.78.4 +- glib-tools=2.78.4 +- glog=0.6.0 +- glpk=5.0 +- gmp=6.3.0 +- graphite2=1.3.13 +- graphviz=9.0.0 +- gst-plugins-base=1.22.9 +- gstreamer=1.22.9 +- gtk2=2.24.33 +- gts=0.7.6 +- harfbuzz=8.3.0 +- hdf4=4.2.15 +- hdf5=1.14.3 +- humanfriendly=10.0 +- icu=73.2 +- identify=2.5.35 +- idna=3.6 +- importlib-metadata=7.0.1 +- importlib_metadata=7.0.1 +- importlib_resources=6.1.1 +- iniconfig=2.0.0 +- ipopt=3.14.14 +- ipython=8.21.0 +- jedi=0.19.1 +- jinja2=3.1.3 +- joblib=1.3.2 +- json-c=0.17 +- jsonschema=4.21.1 +- jsonschema-specifications=2023.12.1 +- jupyter_core=5.7.1 +- kealib=1.5.3 +- keyutils=1.6.1 +- kiwisolver=1.4.5 +- krb5=1.21.2 +- lame=3.100 +- lcms2=2.16 +- ld_impl_linux-64=2.40 +- lerc=4.0.0 +- libabseil=20230802.1 +- libaec=1.1.2 +- libarchive=3.7.2 +- libarrow=15.0.0 +- libarrow-acero=15.0.0 +- libarrow-dataset=15.0.0 +- libarrow-flight=15.0.0 +- libarrow-flight-sql=15.0.0 +- libarrow-gandiva=15.0.0 +- libarrow-substrait=15.0.0 +- libblas=3.9.0 +- libboost-headers=1.84.0 +- libbrotlicommon=1.1.0 +- libbrotlidec=1.1.0 +- libbrotlienc=1.1.0 +- libcap=2.69 +- libcblas=3.9.0 +- libclang=15.0.7 +- libclang13=15.0.7 +- libcrc32c=1.1.2 +- libcups=2.3.3 +- libcurl=8.5.0 +- libdeflate=1.19 +- libedit=3.1.20191231 +- libev=4.33 +- libevent=2.1.12 +- libexpat=2.5.0 +- libffi=3.4.2 +- libflac=1.4.3 +- libgcc-ng=13.2.0 +- libgcrypt=1.10.3 +- libgd=2.3.3 +- libgdal=3.8.4 +- libgfortran-ng=13.2.0 +- libgfortran5=13.2.0 +- libglib=2.78.4 +- libgomp=13.2.0 +- libgoogle-cloud=2.12.0 +- libgpg-error=1.47 +- libgrpc=1.60.1 +- libhwloc=2.9.3 +- libiconv=1.17 +- libjpeg-turbo=3.0.0 +- libkml=1.3.0 +- liblapack=3.9.0 +- liblapacke=3.9.0 +- libllvm15=15.0.7 +- libnetcdf=4.9.2 +- libnghttp2=1.58.0 +- libnl=3.9.0 +- libnsl=2.0.1 +- libnuma=2.0.16 +- libogg=1.3.4 +- libopenblas=0.3.26 +- libopus=1.3.1 +- libparquet=15.0.0 +- libpng=1.6.42 +- libpq=16.2 +- libprotobuf=4.25.1 +- libre2-11=2023.06.02 +- librsvg=2.56.3 +- librttopo=1.1.0 +- libscotch=7.0.4 +- libsndfile=1.2.2 +- libspatialindex=1.9.3 +- libspatialite=5.1.0 +- libspral=2023.09.07 +- libsqlite=3.45.1 +- libssh2=1.11.0 +- libstdcxx-ng=13.2.0 +- libsystemd0=255 +- libthrift=0.19.0 +- libtiff=4.6.0 +- libutf8proc=2.8.0 +- libuuid=2.38.1 +- libvorbis=1.3.7 +- libwebp=1.3.2 +- libwebp-base=1.3.2 +- libxcb=1.15 +- libxcrypt=4.4.36 +- libxkbcommon=1.6.0 +- libxml2=2.12.5 +- libxslt=1.1.39 +- libzip=1.10.1 +- libzlib=1.2.13 +- linopy=0.3.4 +- locket=1.0.0 +- lxml=5.1.0 +- lz4=4.3.3 +- lz4-c=1.9.4 +- lzo=2.10 +- mapclassify=2.6.1 +- markupsafe=2.1.5 +- matplotlib=3.8.3 +- matplotlib-base=3.8.3 +- matplotlib-inline=0.1.6 +- memory_profiler=0.61.0 +- metis=5.1.0 +- minizip=4.0.4 +- mpg123=1.32.4 +- msgpack-python=1.0.7 +- mumps-include=5.6.2 +- mumps-seq=5.6.2 +- munkres=1.1.4 +- mysql-common=8.0.33 +- mysql-libs=8.0.33 +- nbformat=5.9.2 +- ncurses=6.4 +- netcdf4=1.6.5 +- networkx=3.2.1 +- nodeenv=1.8.0 +- nomkl=1.0 +- nspr=4.35 +- nss=3.98 +- numexpr=2.9.0 +- numpy=1.26.4 +- openjdk=21.0.2 +- openjpeg=2.5.0 +- openpyxl=3.1.2 +- openssl=3.2.1 +- orc=1.9.2 +- packaging=23.2 +- pandas=2.2.0 +- pango=1.50.14 +- parso=0.8.3 +- partd=1.4.1 +- patsy=0.5.6 +- pcre2=10.42 +- pexpect=4.9.0 +- pickleshare=0.7.5 +- pillow=10.2.0 +- pip=24.0 +- pixman=0.43.2 +- pkgutil-resolve-name=1.3.10 +- plac=1.4.2 +- platformdirs=4.2.0 +- pluggy=1.4.0 +- ply=3.11 +- poppler=24.02.0 +- poppler-data=0.4.12 +- postgresql=16.2 +- powerplantmatching=0.5.11 +- pre-commit=3.6.2 +- progressbar2=4.3.2 +- proj=9.3.1 +- prompt-toolkit=3.0.42 +- psutil=5.9.8 +- pthread-stubs=0.4 +- ptyprocess=0.7.0 +- pulp=2.7.0 +- pulseaudio-client=16.1 +- pure_eval=0.2.2 +- py-cpuinfo=9.0.0 +- pyarrow=15.0.0 +- pyarrow-hotfix=0.6 +- pycountry=22.3.5 +- pycparser=2.21 +- pygments=2.17.2 +- pyomo=6.6.1 +- pyparsing=3.1.1 +- pyproj=3.6.1 +- pypsa=0.27.0 +- pyqt=5.15.9 +- pyqt5-sip=12.12.2 +- pyscipopt=4.4.0 +- pyshp=2.3.1 +- pysocks=1.7.1 +- pytables=3.9.2 +- pytest=8.0.0 +- python=3.11.8 +- python-dateutil=2.8.2 +- python-fastjsonschema=2.19.1 +- python-tzdata=2024.1 +- python-utils=3.8.2 +- python_abi=3.11 +- pytz=2024.1 +- pyxlsb=1.0.10 +- pyyaml=6.0.1 +- qt-main=5.15.8 +- rasterio=1.3.9 +- rdma-core=50.0 +- re2=2023.06.02 +- readline=8.2 +- referencing=0.33.0 +- requests=2.31.0 +- reretry=0.11.8 +- rioxarray=0.15.1 +- rpds-py=0.18.0 +- rtree=1.2.0 +- s2n=1.4.3 +- scikit-learn=1.4.1.post1 +- scip=8.1.0 +- scipy=1.12.0 +- scotch=7.0.4 +- seaborn=0.13.2 +- seaborn-base=0.13.2 +- setuptools=69.1.0 +- setuptools-scm=8.0.4 +- setuptools_scm=8.0.4 +- shapely=2.0.2 +- sip=6.7.12 +- six=1.16.0 +- smart_open=6.4.0 +- smmap=5.0.0 +- snakemake-minimal=7.32.4 +- snappy=1.1.10 +- snuggs=1.4.7 +- sortedcontainers=2.4.0 +- soupsieve=2.5 +- sqlite=3.45.1 +- stack_data=0.6.2 +- statsmodels=0.14.1 +- stopit=1.1.2 +- tabula-py=2.7.0 +- tabulate=0.9.0 +- tbb=2021.11.0 +- tblib=3.0.0 +- threadpoolctl=3.3.0 +- throttler=1.2.2 +- tiledb=2.20.0 +- tk=8.6.13 +- toml=0.10.2 +- tomli=2.0.1 +- toolz=0.12.1 +- toposort=1.10 +- tornado=6.3.3 +- tqdm=4.66.2 +- traitlets=5.14.1 +- typing-extensions=4.9.0 +- typing_extensions=4.9.0 +- tzcode=2024a +- tzdata=2024a +- ucx=1.15.0 +- ukkonen=1.0.1 +- unidecode=1.3.8 +- unixodbc=2.3.12 +- uriparser=0.9.7 +- urllib3=2.2.1 +- validators=0.22.0 +- virtualenv=20.25.0 +- wcwidth=0.2.13 +- wheel=0.42.0 +- wrapt=1.16.0 +- xarray=2024.2.0 +- xcb-util=0.4.0 +- xcb-util-image=0.4.0 +- xcb-util-keysyms=0.4.0 +- xcb-util-renderutil=0.3.9 +- xcb-util-wm=0.4.1 +- xerces-c=3.2.5 +- xkeyboard-config=2.41 +- xlrd=2.0.1 +- xorg-fixesproto=5.0 +- xorg-inputproto=2.3.2 +- xorg-kbproto=1.0.7 +- xorg-libice=1.1.1 +- xorg-libsm=1.2.4 +- xorg-libx11=1.8.7 +- xorg-libxau=1.0.11 +- xorg-libxdmcp=1.1.3 +- xorg-libxext=1.3.4 +- xorg-libxfixes=5.0.3 +- xorg-libxi=1.7.10 +- xorg-libxrender=0.9.11 +- xorg-libxt=1.3.0 +- xorg-libxtst=1.2.3 +- xorg-recordproto=1.14.2 +- xorg-renderproto=0.11.1 +- xorg-xextproto=7.3.0 +- xorg-xf86vidmodeproto=2.3.1 +- xorg-xproto=7.0.31 +- xyzservices=2023.10.1 +- xz=5.2.6 +- yaml=0.2.5 +- yte=1.5.4 +- zict=3.0.0 +- zipp=3.17.0 +- zlib=1.2.13 +- zlib-ng=2.0.7 +- zstd=1.5.5 +- pip: + - highspy==1.5.3 + - tsam==2.3.1 From ccb43a5612010d13db0b000dfabab673cd900aeb Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 19 Feb 2024 22:45:17 +0100 Subject: [PATCH 358/591] Allow absence of offshore wind from sector-coupled networks --- rules/build_sector.smk | 7 +++++-- scripts/prepare_sector_network.py | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index acdc3203..ff25af0e 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -808,6 +808,11 @@ rule prepare_sector_network: **rules.cluster_gas_network.output, **rules.build_gas_input_locations.output, **build_sequestration_potentials_output, + **{ + f"profile_offwind_{tech}": RESOURCES + f"profile_offwind-{tech}.nc" + for tech in ["ac", "dc"] + if (f"offwind-{tech}" in config["electricity"]["renewable_carriers"]) + }, network=RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", energy_totals_name=RESOURCES + "energy_totals.csv", eurostat=input_eurostat, @@ -833,8 +838,6 @@ rule prepare_sector_network: if config["foresight"] == "overnight" else "data/costs_{planning_horizons}.csv" ), - profile_offwind_ac=RESOURCES + "profile_offwind-ac.nc", - profile_offwind_dc=RESOURCES + "profile_offwind-dc.nc", h2_cavern=RESOURCES + "salt_cavern_potentials_s{simpl}_{clusters}.csv", busmap_s=RESOURCES + "busmap_elec_s{simpl}.csv", busmap=RESOURCES + "busmap_elec_s{simpl}_{clusters}.csv", diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index b1351089..21728f7c 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -423,6 +423,8 @@ def update_wind_solar_costs(n, costs): # code adapted from pypsa-eur/scripts/add_electricity.py for connection in ["dc", "ac"]: tech = "offwind-" + connection + if tech not in n.generators.carrier.values: + continue profile = snakemake.input["profile_offwind_" + connection] with xr.open_dataset(profile) as ds: From 4f91c6c43d706b49a2749f924ea7b89cdfa7bdd3 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Fri, 9 Feb 2024 19:03:39 +0100 Subject: [PATCH 359/591] bugfix: make sure coal demand is there with regional demand --- scripts/prepare_sector_network.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index b1351089..810257c0 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3059,6 +3059,9 @@ def add_industry(n, costs): + mwh_coal_per_mwh_coke * industrial_demand["coke"] ) / nhours + p_set.rename(lambda x: x + " coal for industry", + inplace=True) + if not options["regional_coal_demand"]: p_set = p_set.sum() From 3466027482b61d3c71a65144cbb07b00f49aea97 Mon Sep 17 00:00:00 2001 From: lumbric Date: Mon, 19 Feb 2024 18:58:23 +0100 Subject: [PATCH 360/591] Fix broken link to mamba installation guide in docs --- doc/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/installation.rst b/doc/installation.rst index b07fd290..fbabfd15 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -31,7 +31,7 @@ Install Python Dependencies PyPSA-Eur relies on a set of other Python packages to function. We recommend using the package manager `mamba `_ to install them and manage your environments. -For instructions for your operating system follow the ``mamba`` `installation guide `_. +For instructions for your operating system follow the ``mamba`` `installation guide `_. You can also use ``conda`` equivalently. The package requirements are curated in the `envs/environment.yaml `_ file. From ac2322cd16eff8f9d056f7021329d9e6b40b324d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 17:59:11 +0000 Subject: [PATCH 361/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- envs/environment.fixed.yaml | 878 ++++++++++++++++++------------------ 1 file changed, 439 insertions(+), 439 deletions(-) diff --git a/envs/environment.fixed.yaml b/envs/environment.fixed.yaml index cde0b801..8bbd70bf 100644 --- a/envs/environment.fixed.yaml +++ b/envs/environment.fixed.yaml @@ -4,443 +4,443 @@ name: pypsa-eur channels: - - bioconda - - http://conda.anaconda.org/gurobi - - conda-forge - - defaults +- bioconda +- http://conda.anaconda.org/gurobi +- conda-forge +- defaults dependencies: - - _libgcc_mutex=0.1 - - _openmp_mutex=4.5 - - affine=2.4.0 - - alsa-lib=1.2.10 - - ampl-mp=3.1.0 - - amply=0.1.6 - - appdirs=1.4.4 - - asttokens=2.4.1 - - atk-1.0=2.38.0 - - atlite=0.2.12 - - attr=2.5.1 - - attrs=23.2.0 - - aws-c-auth=0.7.15 - - aws-c-cal=0.6.9 - - aws-c-common=0.9.12 - - aws-c-compression=0.2.17 - - aws-c-event-stream=0.4.1 - - aws-c-http=0.8.0 - - aws-c-io=0.14.3 - - aws-c-mqtt=0.10.1 - - aws-c-s3=0.5.0 - - aws-c-sdkutils=0.1.14 - - aws-checksums=0.1.17 - - aws-crt-cpp=0.26.1 - - aws-sdk-cpp=1.11.242 - - azure-core-cpp=1.10.3 - - azure-storage-blobs-cpp=12.10.0 - - azure-storage-common-cpp=12.5.0 - - beautifulsoup4=4.12.3 - - blosc=1.21.5 - - bokeh=3.3.4 - - bottleneck=1.3.7 - - branca=0.7.1 - - brotli=1.1.0 - - brotli-bin=1.1.0 - - brotli-python=1.1.0 - - bzip2=1.0.8 - - c-ares=1.26.0 - - c-blosc2=2.13.2 - - ca-certificates=2024.2.2 - - cairo=1.18.0 - - cartopy=0.22.0 - - cdsapi=0.6.1 - - certifi=2024.2.2 - - cffi=1.16.0 - - cfgv=3.3.1 - - cfitsio=4.3.1 - - cftime=1.6.3 - - charset-normalizer=3.3.2 - - click=8.1.7 - - click-plugins=1.1.1 - - cligj=0.7.2 - - cloudpickle=3.0.0 - - coin-or-cbc=2.10.10 - - coin-or-cgl=0.60.7 - - coin-or-clp=1.17.8 - - coin-or-osi=0.108.8 - - coin-or-utils=2.11.9 - - coincbc=2.10.10 - - colorama=0.4.6 - - configargparse=1.7 - - connection_pool=0.0.3 - - contourpy=1.2.0 - - country_converter=1.2 - - cppad=20240000.2 - - cycler=0.12.1 - - cytoolz=0.12.3 - - dask=2024.2.0 - - dask-core=2024.2.0 - - datrie=0.8.2 - - dbus=1.13.6 - - decorator=5.1.1 - - deprecation=2.1.0 - - descartes=1.1.0 - - distlib=0.3.8 - - distributed=2024.2.0 - - distro=1.9.0 - - docutils=0.20.1 - - dpath=2.1.6 - - entsoe-py=0.6.6 - - et_xmlfile=1.1.0 - - exceptiongroup=1.2.0 - - executing=2.0.1 - - expat=2.5.0 - - filelock=3.13.1 - - fiona=1.9.5 - - folium=0.15.1 - - font-ttf-dejavu-sans-mono=2.37 - - font-ttf-inconsolata=3.000 - - font-ttf-source-code-pro=2.038 - - font-ttf-ubuntu=0.83 - - fontconfig=2.14.2 - - fonts-conda-ecosystem=1 - - fonts-conda-forge=1 - - fonttools=4.49.0 - - freetype=2.12.1 - - freexl=2.0.0 - - fribidi=1.0.10 - - fsspec=2024.2.0 - - gdal=3.8.4 - - gdk-pixbuf=2.42.10 - - geographiclib=1.52 - - geojson-rewind=1.1.0 - - geopandas=0.14.3 - - geopandas-base=0.14.3 - - geopy=2.4.1 - - geos=3.12.1 - - geotiff=1.7.1 - - gettext=0.21.1 - - gflags=2.2.2 - - giflib=5.2.1 - - gitdb=4.0.11 - - gitpython=3.1.42 - - glib=2.78.4 - - glib-tools=2.78.4 - - glog=0.6.0 - - glpk=5.0 - - gmp=6.3.0 - - graphite2=1.3.13 - - graphviz=9.0.0 - - gst-plugins-base=1.22.9 - - gstreamer=1.22.9 - - gtk2=2.24.33 - - gts=0.7.6 - - harfbuzz=8.3.0 - - hdf4=4.2.15 - - hdf5=1.14.3 - - humanfriendly=10.0 - - icu=73.2 - - identify=2.5.35 - - idna=3.6 - - importlib-metadata=7.0.1 - - importlib_metadata=7.0.1 - - importlib_resources=6.1.1 - - iniconfig=2.0.0 - - ipopt=3.14.14 - - ipython=8.21.0 - - jedi=0.19.1 - - jinja2=3.1.3 - - joblib=1.3.2 - - json-c=0.17 - - jsonschema=4.21.1 - - jsonschema-specifications=2023.12.1 - - jupyter_core=5.7.1 - - kealib=1.5.3 - - keyutils=1.6.1 - - kiwisolver=1.4.5 - - krb5=1.21.2 - - lame=3.100 - - lcms2=2.16 - - ld_impl_linux-64=2.40 - - lerc=4.0.0 - - libabseil=20230802.1 - - libaec=1.1.2 - - libarchive=3.7.2 - - libarrow=15.0.0 - - libarrow-acero=15.0.0 - - libarrow-dataset=15.0.0 - - libarrow-flight=15.0.0 - - libarrow-flight-sql=15.0.0 - - libarrow-gandiva=15.0.0 - - libarrow-substrait=15.0.0 - - libblas=3.9.0 - - libboost-headers=1.84.0 - - libbrotlicommon=1.1.0 - - libbrotlidec=1.1.0 - - libbrotlienc=1.1.0 - - libcap=2.69 - - libcblas=3.9.0 - - libclang=15.0.7 - - libclang13=15.0.7 - - libcrc32c=1.1.2 - - libcups=2.3.3 - - libcurl=8.5.0 - - libdeflate=1.19 - - libedit=3.1.20191231 - - libev=4.33 - - libevent=2.1.12 - - libexpat=2.5.0 - - libffi=3.4.2 - - libflac=1.4.3 - - libgcc-ng=13.2.0 - - libgcrypt=1.10.3 - - libgd=2.3.3 - - libgdal=3.8.4 - - libgfortran-ng=13.2.0 - - libgfortran5=13.2.0 - - libglib=2.78.4 - - libgomp=13.2.0 - - libgoogle-cloud=2.12.0 - - libgpg-error=1.47 - - libgrpc=1.60.1 - - libhwloc=2.9.3 - - libiconv=1.17 - - libjpeg-turbo=3.0.0 - - libkml=1.3.0 - - liblapack=3.9.0 - - liblapacke=3.9.0 - - libllvm15=15.0.7 - - libnetcdf=4.9.2 - - libnghttp2=1.58.0 - - libnl=3.9.0 - - libnsl=2.0.1 - - libnuma=2.0.16 - - libogg=1.3.4 - - libopenblas=0.3.26 - - libopus=1.3.1 - - libparquet=15.0.0 - - libpng=1.6.42 - - libpq=16.2 - - libprotobuf=4.25.1 - - libre2-11=2023.06.02 - - librsvg=2.56.3 - - librttopo=1.1.0 - - libscotch=7.0.4 - - libsndfile=1.2.2 - - libspatialindex=1.9.3 - - libspatialite=5.1.0 - - libspral=2023.09.07 - - libsqlite=3.45.1 - - libssh2=1.11.0 - - libstdcxx-ng=13.2.0 - - libsystemd0=255 - - libthrift=0.19.0 - - libtiff=4.6.0 - - libutf8proc=2.8.0 - - libuuid=2.38.1 - - libvorbis=1.3.7 - - libwebp=1.3.2 - - libwebp-base=1.3.2 - - libxcb=1.15 - - libxcrypt=4.4.36 - - libxkbcommon=1.6.0 - - libxml2=2.12.5 - - libxslt=1.1.39 - - libzip=1.10.1 - - libzlib=1.2.13 - - linopy=0.3.4 - - locket=1.0.0 - - lxml=5.1.0 - - lz4=4.3.3 - - lz4-c=1.9.4 - - lzo=2.10 - - mapclassify=2.6.1 - - markupsafe=2.1.5 - - matplotlib=3.8.3 - - matplotlib-base=3.8.3 - - matplotlib-inline=0.1.6 - - memory_profiler=0.61.0 - - metis=5.1.0 - - minizip=4.0.4 - - mpg123=1.32.4 - - msgpack-python=1.0.7 - - mumps-include=5.6.2 - - mumps-seq=5.6.2 - - munkres=1.1.4 - - mysql-common=8.0.33 - - mysql-libs=8.0.33 - - nbformat=5.9.2 - - ncurses=6.4 - - netcdf4=1.6.5 - - networkx=3.2.1 - - nodeenv=1.8.0 - - nomkl=1.0 - - nspr=4.35 - - nss=3.98 - - numexpr=2.9.0 - - numpy=1.26.4 - - openjdk=21.0.2 - - openjpeg=2.5.0 - - openpyxl=3.1.2 - - openssl=3.2.1 - - orc=1.9.2 - - packaging=23.2 - - pandas=2.2.0 - - pango=1.50.14 - - parso=0.8.3 - - partd=1.4.1 - - patsy=0.5.6 - - pcre2=10.42 - - pexpect=4.9.0 - - pickleshare=0.7.5 - - pillow=10.2.0 - - pip=24.0 - - pixman=0.43.2 - - pkgutil-resolve-name=1.3.10 - - plac=1.4.2 - - platformdirs=4.2.0 - - pluggy=1.4.0 - - ply=3.11 - - poppler=24.02.0 - - poppler-data=0.4.12 - - postgresql=16.2 - - powerplantmatching=0.5.11 - - pre-commit=3.6.2 - - progressbar2=4.3.2 - - proj=9.3.1 - - prompt-toolkit=3.0.42 - - psutil=5.9.8 - - pthread-stubs=0.4 - - ptyprocess=0.7.0 - - pulp=2.7.0 - - pulseaudio-client=16.1 - - pure_eval=0.2.2 - - py-cpuinfo=9.0.0 - - pyarrow=15.0.0 - - pyarrow-hotfix=0.6 - - pycountry=22.3.5 - - pycparser=2.21 - - pygments=2.17.2 - - pyomo=6.6.1 - - pyparsing=3.1.1 - - pyproj=3.6.1 - - pypsa=0.27.0 - - pyqt=5.15.9 - - pyqt5-sip=12.12.2 - - pyscipopt=4.4.0 - - pyshp=2.3.1 - - pysocks=1.7.1 - - pytables=3.9.2 - - pytest=8.0.0 - - python=3.11.8 - - python-dateutil=2.8.2 - - python-fastjsonschema=2.19.1 - - python-tzdata=2024.1 - - python-utils=3.8.2 - - python_abi=3.11 - - pytz=2024.1 - - pyxlsb=1.0.10 - - pyyaml=6.0.1 - - qt-main=5.15.8 - - rasterio=1.3.9 - - rdma-core=50.0 - - re2=2023.06.02 - - readline=8.2 - - referencing=0.33.0 - - requests=2.31.0 - - reretry=0.11.8 - - rioxarray=0.15.1 - - rpds-py=0.18.0 - - rtree=1.2.0 - - s2n=1.4.3 - - scikit-learn=1.4.1.post1 - - scip=8.1.0 - - scipy=1.12.0 - - scotch=7.0.4 - - seaborn=0.13.2 - - seaborn-base=0.13.2 - - setuptools=69.1.0 - - setuptools-scm=8.0.4 - - setuptools_scm=8.0.4 - - shapely=2.0.2 - - sip=6.7.12 - - six=1.16.0 - - smart_open=6.4.0 - - smmap=5.0.0 - - snakemake-minimal=7.32.4 - - snappy=1.1.10 - - snuggs=1.4.7 - - sortedcontainers=2.4.0 - - soupsieve=2.5 - - sqlite=3.45.1 - - stack_data=0.6.2 - - statsmodels=0.14.1 - - stopit=1.1.2 - - tabula-py=2.7.0 - - tabulate=0.9.0 - - tbb=2021.11.0 - - tblib=3.0.0 - - threadpoolctl=3.3.0 - - throttler=1.2.2 - - tiledb=2.20.0 - - tk=8.6.13 - - toml=0.10.2 - - tomli=2.0.1 - - toolz=0.12.1 - - toposort=1.10 - - tornado=6.3.3 - - tqdm=4.66.2 - - traitlets=5.14.1 - - typing-extensions=4.9.0 - - typing_extensions=4.9.0 - - tzcode=2024a - - tzdata=2024a - - ucx=1.15.0 - - ukkonen=1.0.1 - - unidecode=1.3.8 - - unixodbc=2.3.12 - - uriparser=0.9.7 - - urllib3=2.2.1 - - validators=0.22.0 - - virtualenv=20.25.0 - - wcwidth=0.2.13 - - wheel=0.42.0 - - wrapt=1.16.0 - - xarray=2024.2.0 - - xcb-util=0.4.0 - - xcb-util-image=0.4.0 - - xcb-util-keysyms=0.4.0 - - xcb-util-renderutil=0.3.9 - - xcb-util-wm=0.4.1 - - xerces-c=3.2.5 - - xkeyboard-config=2.41 - - xlrd=2.0.1 - - xorg-fixesproto=5.0 - - xorg-inputproto=2.3.2 - - xorg-kbproto=1.0.7 - - xorg-libice=1.1.1 - - xorg-libsm=1.2.4 - - xorg-libx11=1.8.7 - - xorg-libxau=1.0.11 - - xorg-libxdmcp=1.1.3 - - xorg-libxext=1.3.4 - - xorg-libxfixes=5.0.3 - - xorg-libxi=1.7.10 - - xorg-libxrender=0.9.11 - - xorg-libxt=1.3.0 - - xorg-libxtst=1.2.3 - - xorg-recordproto=1.14.2 - - xorg-renderproto=0.11.1 - - xorg-xextproto=7.3.0 - - xorg-xf86vidmodeproto=2.3.1 - - xorg-xproto=7.0.31 - - xyzservices=2023.10.1 - - xz=5.2.6 - - yaml=0.2.5 - - yte=1.5.4 - - zict=3.0.0 - - zipp=3.17.0 - - zlib=1.2.13 - - zlib-ng=2.0.7 - - zstd=1.5.5 - - pip: - - highspy==1.5.3 - - tsam==2.3.1 +- _libgcc_mutex=0.1 +- _openmp_mutex=4.5 +- affine=2.4.0 +- alsa-lib=1.2.10 +- ampl-mp=3.1.0 +- amply=0.1.6 +- appdirs=1.4.4 +- asttokens=2.4.1 +- atk-1.0=2.38.0 +- atlite=0.2.12 +- attr=2.5.1 +- attrs=23.2.0 +- aws-c-auth=0.7.15 +- aws-c-cal=0.6.9 +- aws-c-common=0.9.12 +- aws-c-compression=0.2.17 +- aws-c-event-stream=0.4.1 +- aws-c-http=0.8.0 +- aws-c-io=0.14.3 +- aws-c-mqtt=0.10.1 +- aws-c-s3=0.5.0 +- aws-c-sdkutils=0.1.14 +- aws-checksums=0.1.17 +- aws-crt-cpp=0.26.1 +- aws-sdk-cpp=1.11.242 +- azure-core-cpp=1.10.3 +- azure-storage-blobs-cpp=12.10.0 +- azure-storage-common-cpp=12.5.0 +- beautifulsoup4=4.12.3 +- blosc=1.21.5 +- bokeh=3.3.4 +- bottleneck=1.3.7 +- branca=0.7.1 +- brotli=1.1.0 +- brotli-bin=1.1.0 +- brotli-python=1.1.0 +- bzip2=1.0.8 +- c-ares=1.26.0 +- c-blosc2=2.13.2 +- ca-certificates=2024.2.2 +- cairo=1.18.0 +- cartopy=0.22.0 +- cdsapi=0.6.1 +- certifi=2024.2.2 +- cffi=1.16.0 +- cfgv=3.3.1 +- cfitsio=4.3.1 +- cftime=1.6.3 +- charset-normalizer=3.3.2 +- click=8.1.7 +- click-plugins=1.1.1 +- cligj=0.7.2 +- cloudpickle=3.0.0 +- coin-or-cbc=2.10.10 +- coin-or-cgl=0.60.7 +- coin-or-clp=1.17.8 +- coin-or-osi=0.108.8 +- coin-or-utils=2.11.9 +- coincbc=2.10.10 +- colorama=0.4.6 +- configargparse=1.7 +- connection_pool=0.0.3 +- contourpy=1.2.0 +- country_converter=1.2 +- cppad=20240000.2 +- cycler=0.12.1 +- cytoolz=0.12.3 +- dask=2024.2.0 +- dask-core=2024.2.0 +- datrie=0.8.2 +- dbus=1.13.6 +- decorator=5.1.1 +- deprecation=2.1.0 +- descartes=1.1.0 +- distlib=0.3.8 +- distributed=2024.2.0 +- distro=1.9.0 +- docutils=0.20.1 +- dpath=2.1.6 +- entsoe-py=0.6.6 +- et_xmlfile=1.1.0 +- exceptiongroup=1.2.0 +- executing=2.0.1 +- expat=2.5.0 +- filelock=3.13.1 +- fiona=1.9.5 +- folium=0.15.1 +- font-ttf-dejavu-sans-mono=2.37 +- font-ttf-inconsolata=3.000 +- font-ttf-source-code-pro=2.038 +- font-ttf-ubuntu=0.83 +- fontconfig=2.14.2 +- fonts-conda-ecosystem=1 +- fonts-conda-forge=1 +- fonttools=4.49.0 +- freetype=2.12.1 +- freexl=2.0.0 +- fribidi=1.0.10 +- fsspec=2024.2.0 +- gdal=3.8.4 +- gdk-pixbuf=2.42.10 +- geographiclib=1.52 +- geojson-rewind=1.1.0 +- geopandas=0.14.3 +- geopandas-base=0.14.3 +- geopy=2.4.1 +- geos=3.12.1 +- geotiff=1.7.1 +- gettext=0.21.1 +- gflags=2.2.2 +- giflib=5.2.1 +- gitdb=4.0.11 +- gitpython=3.1.42 +- glib=2.78.4 +- glib-tools=2.78.4 +- glog=0.6.0 +- glpk=5.0 +- gmp=6.3.0 +- graphite2=1.3.13 +- graphviz=9.0.0 +- gst-plugins-base=1.22.9 +- gstreamer=1.22.9 +- gtk2=2.24.33 +- gts=0.7.6 +- harfbuzz=8.3.0 +- hdf4=4.2.15 +- hdf5=1.14.3 +- humanfriendly=10.0 +- icu=73.2 +- identify=2.5.35 +- idna=3.6 +- importlib-metadata=7.0.1 +- importlib_metadata=7.0.1 +- importlib_resources=6.1.1 +- iniconfig=2.0.0 +- ipopt=3.14.14 +- ipython=8.21.0 +- jedi=0.19.1 +- jinja2=3.1.3 +- joblib=1.3.2 +- json-c=0.17 +- jsonschema=4.21.1 +- jsonschema-specifications=2023.12.1 +- jupyter_core=5.7.1 +- kealib=1.5.3 +- keyutils=1.6.1 +- kiwisolver=1.4.5 +- krb5=1.21.2 +- lame=3.100 +- lcms2=2.16 +- ld_impl_linux-64=2.40 +- lerc=4.0.0 +- libabseil=20230802.1 +- libaec=1.1.2 +- libarchive=3.7.2 +- libarrow=15.0.0 +- libarrow-acero=15.0.0 +- libarrow-dataset=15.0.0 +- libarrow-flight=15.0.0 +- libarrow-flight-sql=15.0.0 +- libarrow-gandiva=15.0.0 +- libarrow-substrait=15.0.0 +- libblas=3.9.0 +- libboost-headers=1.84.0 +- libbrotlicommon=1.1.0 +- libbrotlidec=1.1.0 +- libbrotlienc=1.1.0 +- libcap=2.69 +- libcblas=3.9.0 +- libclang=15.0.7 +- libclang13=15.0.7 +- libcrc32c=1.1.2 +- libcups=2.3.3 +- libcurl=8.5.0 +- libdeflate=1.19 +- libedit=3.1.20191231 +- libev=4.33 +- libevent=2.1.12 +- libexpat=2.5.0 +- libffi=3.4.2 +- libflac=1.4.3 +- libgcc-ng=13.2.0 +- libgcrypt=1.10.3 +- libgd=2.3.3 +- libgdal=3.8.4 +- libgfortran-ng=13.2.0 +- libgfortran5=13.2.0 +- libglib=2.78.4 +- libgomp=13.2.0 +- libgoogle-cloud=2.12.0 +- libgpg-error=1.47 +- libgrpc=1.60.1 +- libhwloc=2.9.3 +- libiconv=1.17 +- libjpeg-turbo=3.0.0 +- libkml=1.3.0 +- liblapack=3.9.0 +- liblapacke=3.9.0 +- libllvm15=15.0.7 +- libnetcdf=4.9.2 +- libnghttp2=1.58.0 +- libnl=3.9.0 +- libnsl=2.0.1 +- libnuma=2.0.16 +- libogg=1.3.4 +- libopenblas=0.3.26 +- libopus=1.3.1 +- libparquet=15.0.0 +- libpng=1.6.42 +- libpq=16.2 +- libprotobuf=4.25.1 +- libre2-11=2023.06.02 +- librsvg=2.56.3 +- librttopo=1.1.0 +- libscotch=7.0.4 +- libsndfile=1.2.2 +- libspatialindex=1.9.3 +- libspatialite=5.1.0 +- libspral=2023.09.07 +- libsqlite=3.45.1 +- libssh2=1.11.0 +- libstdcxx-ng=13.2.0 +- libsystemd0=255 +- libthrift=0.19.0 +- libtiff=4.6.0 +- libutf8proc=2.8.0 +- libuuid=2.38.1 +- libvorbis=1.3.7 +- libwebp=1.3.2 +- libwebp-base=1.3.2 +- libxcb=1.15 +- libxcrypt=4.4.36 +- libxkbcommon=1.6.0 +- libxml2=2.12.5 +- libxslt=1.1.39 +- libzip=1.10.1 +- libzlib=1.2.13 +- linopy=0.3.4 +- locket=1.0.0 +- lxml=5.1.0 +- lz4=4.3.3 +- lz4-c=1.9.4 +- lzo=2.10 +- mapclassify=2.6.1 +- markupsafe=2.1.5 +- matplotlib=3.8.3 +- matplotlib-base=3.8.3 +- matplotlib-inline=0.1.6 +- memory_profiler=0.61.0 +- metis=5.1.0 +- minizip=4.0.4 +- mpg123=1.32.4 +- msgpack-python=1.0.7 +- mumps-include=5.6.2 +- mumps-seq=5.6.2 +- munkres=1.1.4 +- mysql-common=8.0.33 +- mysql-libs=8.0.33 +- nbformat=5.9.2 +- ncurses=6.4 +- netcdf4=1.6.5 +- networkx=3.2.1 +- nodeenv=1.8.0 +- nomkl=1.0 +- nspr=4.35 +- nss=3.98 +- numexpr=2.9.0 +- numpy=1.26.4 +- openjdk=21.0.2 +- openjpeg=2.5.0 +- openpyxl=3.1.2 +- openssl=3.2.1 +- orc=1.9.2 +- packaging=23.2 +- pandas=2.2.0 +- pango=1.50.14 +- parso=0.8.3 +- partd=1.4.1 +- patsy=0.5.6 +- pcre2=10.42 +- pexpect=4.9.0 +- pickleshare=0.7.5 +- pillow=10.2.0 +- pip=24.0 +- pixman=0.43.2 +- pkgutil-resolve-name=1.3.10 +- plac=1.4.2 +- platformdirs=4.2.0 +- pluggy=1.4.0 +- ply=3.11 +- poppler=24.02.0 +- poppler-data=0.4.12 +- postgresql=16.2 +- powerplantmatching=0.5.11 +- pre-commit=3.6.2 +- progressbar2=4.3.2 +- proj=9.3.1 +- prompt-toolkit=3.0.42 +- psutil=5.9.8 +- pthread-stubs=0.4 +- ptyprocess=0.7.0 +- pulp=2.7.0 +- pulseaudio-client=16.1 +- pure_eval=0.2.2 +- py-cpuinfo=9.0.0 +- pyarrow=15.0.0 +- pyarrow-hotfix=0.6 +- pycountry=22.3.5 +- pycparser=2.21 +- pygments=2.17.2 +- pyomo=6.6.1 +- pyparsing=3.1.1 +- pyproj=3.6.1 +- pypsa=0.27.0 +- pyqt=5.15.9 +- pyqt5-sip=12.12.2 +- pyscipopt=4.4.0 +- pyshp=2.3.1 +- pysocks=1.7.1 +- pytables=3.9.2 +- pytest=8.0.0 +- python=3.11.8 +- python-dateutil=2.8.2 +- python-fastjsonschema=2.19.1 +- python-tzdata=2024.1 +- python-utils=3.8.2 +- python_abi=3.11 +- pytz=2024.1 +- pyxlsb=1.0.10 +- pyyaml=6.0.1 +- qt-main=5.15.8 +- rasterio=1.3.9 +- rdma-core=50.0 +- re2=2023.06.02 +- readline=8.2 +- referencing=0.33.0 +- requests=2.31.0 +- reretry=0.11.8 +- rioxarray=0.15.1 +- rpds-py=0.18.0 +- rtree=1.2.0 +- s2n=1.4.3 +- scikit-learn=1.4.1.post1 +- scip=8.1.0 +- scipy=1.12.0 +- scotch=7.0.4 +- seaborn=0.13.2 +- seaborn-base=0.13.2 +- setuptools=69.1.0 +- setuptools-scm=8.0.4 +- setuptools_scm=8.0.4 +- shapely=2.0.2 +- sip=6.7.12 +- six=1.16.0 +- smart_open=6.4.0 +- smmap=5.0.0 +- snakemake-minimal=7.32.4 +- snappy=1.1.10 +- snuggs=1.4.7 +- sortedcontainers=2.4.0 +- soupsieve=2.5 +- sqlite=3.45.1 +- stack_data=0.6.2 +- statsmodels=0.14.1 +- stopit=1.1.2 +- tabula-py=2.7.0 +- tabulate=0.9.0 +- tbb=2021.11.0 +- tblib=3.0.0 +- threadpoolctl=3.3.0 +- throttler=1.2.2 +- tiledb=2.20.0 +- tk=8.6.13 +- toml=0.10.2 +- tomli=2.0.1 +- toolz=0.12.1 +- toposort=1.10 +- tornado=6.3.3 +- tqdm=4.66.2 +- traitlets=5.14.1 +- typing-extensions=4.9.0 +- typing_extensions=4.9.0 +- tzcode=2024a +- tzdata=2024a +- ucx=1.15.0 +- ukkonen=1.0.1 +- unidecode=1.3.8 +- unixodbc=2.3.12 +- uriparser=0.9.7 +- urllib3=2.2.1 +- validators=0.22.0 +- virtualenv=20.25.0 +- wcwidth=0.2.13 +- wheel=0.42.0 +- wrapt=1.16.0 +- xarray=2024.2.0 +- xcb-util=0.4.0 +- xcb-util-image=0.4.0 +- xcb-util-keysyms=0.4.0 +- xcb-util-renderutil=0.3.9 +- xcb-util-wm=0.4.1 +- xerces-c=3.2.5 +- xkeyboard-config=2.41 +- xlrd=2.0.1 +- xorg-fixesproto=5.0 +- xorg-inputproto=2.3.2 +- xorg-kbproto=1.0.7 +- xorg-libice=1.1.1 +- xorg-libsm=1.2.4 +- xorg-libx11=1.8.7 +- xorg-libxau=1.0.11 +- xorg-libxdmcp=1.1.3 +- xorg-libxext=1.3.4 +- xorg-libxfixes=5.0.3 +- xorg-libxi=1.7.10 +- xorg-libxrender=0.9.11 +- xorg-libxt=1.3.0 +- xorg-libxtst=1.2.3 +- xorg-recordproto=1.14.2 +- xorg-renderproto=0.11.1 +- xorg-xextproto=7.3.0 +- xorg-xf86vidmodeproto=2.3.1 +- xorg-xproto=7.0.31 +- xyzservices=2023.10.1 +- xz=5.2.6 +- yaml=0.2.5 +- yte=1.5.4 +- zict=3.0.0 +- zipp=3.17.0 +- zlib=1.2.13 +- zlib-ng=2.0.7 +- zstd=1.5.5 +- pip: + - highspy==1.5.3 + - tsam==2.3.1 From d713e3c52b2e77b30816a3b829faee3fc3ebd381 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 09:03:54 +0000 Subject: [PATCH 362/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/prepare_sector_network.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 810257c0..f5e6604b 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3059,8 +3059,7 @@ def add_industry(n, costs): + mwh_coal_per_mwh_coke * industrial_demand["coke"] ) / nhours - p_set.rename(lambda x: x + " coal for industry", - inplace=True) + p_set.rename(lambda x: x + " coal for industry", inplace=True) if not options["regional_coal_demand"]: p_set = p_set.sum() From 26b202f46399efe53a10b5a1342e9059ffe8c867 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 20 Feb 2024 12:34:19 +0100 Subject: [PATCH 363/591] prepare_sector: automatically interpolate in config get() function --- doc/release_notes.rst | 8 +++++--- scripts/prepare_sector_network.py | 27 ++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index bc1cd2c6..15814036 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -7,9 +7,11 @@ Release Notes ########################################## -.. Upcoming Release -.. ================ -.. +Upcoming Release +================ + +* Linearly interpolate missing investment periods in year-dependent + configuration options. PyPSA-Eur 0.10.0 (19th February 2024) ===================================== diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index f5e6604b..3438e3d8 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -215,7 +215,32 @@ def get(item, investment_year=None): """ Check whether item depends on investment year. """ - return item[investment_year] if isinstance(item, dict) else item + if not isinstance(item, dict): + return item + elif investment_year in item.keys(): + return item[investment_year] + else: + logger.warning( + f"Investment key {investment_year} not found in dictionary {item}." + ) + keys = sorted(item.keys()) + if investment_year < keys[0]: + logger.warning(f"Lower than minimum key. Taking minimum key {keys[0]}") + return item[keys[0]] + elif investment_year > keys[-1]: + logger.warning(f"Higher than maximum key. Taking maximum key {keys[0]}") + return item[keys[-1]] + else: + logger.warning( + "Interpolate linearly between the next lower and next higher year." + ) + lower_key = max(k for k in keys if k < investment_year) + higher_key = min(k for k in keys if k > investment_year) + lower = item[lower_key] + higher = item[higher_key] + return lower + (higher - lower) * (investment_year - lower_key) / ( + higher_key - lower_key + ) def co2_emissions_year( From 66d078e4074986800c61e1df66d33b804a04782c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 20 Feb 2024 14:24:23 +0100 Subject: [PATCH 364/591] reorder release notes --- Snakefile | 1 - doc/release_notes.rst | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Snakefile b/Snakefile index b3d2735c..78a28373 100644 --- a/Snakefile +++ b/Snakefile @@ -26,7 +26,6 @@ for template, target in default_files.items(): copyfile(template, target) - configfile: "config/config.default.yaml" configfile: "config/config.yaml" diff --git a/doc/release_notes.rst b/doc/release_notes.rst index fee8186b..e60f4f95 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -13,11 +13,6 @@ Upcoming Release * Linearly interpolate missing investment periods in year-dependent configuration options. -PyPSA-Eur 0.10.0 (19th February 2024) -===================================== - -**New Features** - * Added new scenario management that supports the simultaneous execution of multiple scenarios with a single ``snakemake`` call. For this purpose, a ``scenarios.yaml`` file is introduced which contains customizable scenario @@ -84,6 +79,11 @@ PyPSA-Eur 0.10.0 (19th February 2024) * The outputs of the rule ``retrieve_gas_infrastructure_data`` no longer marked as ``protected()`` as the download size is small. +PyPSA-Eur 0.10.0 (19th February 2024) +===================================== + +**New Features** + * Improved representation of industry transition pathways. A new script was added to interpolate industry sector ratios from today's status quo to future systems (i.e. specific emissions and demands for energy and feedstocks). For From ef29be714ba96807bb6825066bb81dcf198b7b07 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 20 Feb 2024 14:43:10 +0100 Subject: [PATCH 365/591] Add release note --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index e60f4f95..d6072d7d 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -79,6 +79,8 @@ Upcoming Release * The outputs of the rule ``retrieve_gas_infrastructure_data`` no longer marked as ``protected()`` as the download size is small. +* Bugfix: allow modelling sector-coupled landlocked regions. (Fixed handling of offshore wind.) + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== From 1c9845afff70f9e5e461dac0864e355a851c071b Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 20 Feb 2024 17:52:57 +0100 Subject: [PATCH 366/591] Adapt offwind solution to new config management --- rules/build_sector.smk | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index c7c4662d..466d1713 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -808,6 +808,14 @@ rule build_existing_heating_distribution: "../scripts/build_existing_heating_distribution.py" +def input_profile_offwind(w): + return { + f"profile_{tech}": resources(f"profile_{tech}.nc") + for tech in ["offwind-ac", "offwind-dc"] + if (tech in config_provider("electricity", "renewable_carriers")(w)) + } + + rule prepare_sector_network: params: time_resolution=config_provider("clustering", "temporal", "resolution_sector"), @@ -829,13 +837,9 @@ rule prepare_sector_network: eurostat_report_year=config_provider("energy", "eurostat_report_year"), RDIR=RDIR, input: + unpack(input_profile_offwind), **rules.cluster_gas_network.output, **rules.build_gas_input_locations.output, - **{ - f"profile_offwind_{tech}": RESOURCES + f"profile_offwind-{tech}.nc" - for tech in ["ac", "dc"] - if (f"offwind-{tech}" in config["electricity"]["renewable_carriers"]) - }, retro_cost=lambda w: ( resources("retro_cost_elec_s{simpl}_{clusters}.csv") if config_provider("sector", "retrofitting", "retro_endogen")(w) From db9f234faddecb45f2b11498010f40ea084a6f75 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 20 Feb 2024 18:38:21 +0100 Subject: [PATCH 367/591] Fix typo 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 6128b873..9a9db36f 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -455,7 +455,7 @@ def update_wind_solar_costs(n, costs): tech = "offwind-" + connection if tech not in n.generators.carrier.values: continue - profile = snakemake.input["profile_offwind_" + connection] + profile = snakemake.input["profile_offwind-" + connection] with xr.open_dataset(profile) as ds: # if-statement for compatibility with old profiles From 3298572cedf955392359b04933471671edf2d6c3 Mon Sep 17 00:00:00 2001 From: toniseibold Date: Fri, 23 Feb 2024 13:53:28 +0100 Subject: [PATCH 368/591] new energy totals from eurostat 2023 report scaling JRC IDEES data from 2015 --- config/config.default.yaml | 4 +- data/switzerland-new_format-all_years.csv | 50 ++-- rules/common.smk | 9 +- scripts/build_energy_totals.py | 309 ++++++++++++++++++---- 4 files changed, 293 insertions(+), 79 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index ca2d1ba3..093b1aad 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -314,9 +314,9 @@ pypsa_eur: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#energy energy: - energy_totals_year: 2013 + energy_totals_year: 2019 base_emissions_year: 1990 - eurostat_report_year: 2016 + eurostat_report_year: 2023 emissions: CO2 # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#biomass diff --git a/data/switzerland-new_format-all_years.csv b/data/switzerland-new_format-all_years.csv index 93123009..d083e8a8 100644 --- a/data/switzerland-new_format-all_years.csv +++ b/data/switzerland-new_format-all_years.csv @@ -1,25 +1,25 @@ -country,item,2010,2011,2012,2013,2014,2015 -CH,total residential,268.2,223.4,243.4,261.3,214.2,229.1 -CH,total residential space,192.2,149.0,168.1,185.5,139.7,154.4 -CH,total residential water,32.2,31.6,31.9,32.2,31.7,31.9 -CH,total residential cooking,9.3,9.3,9.3,9.4,9.5,9.6 -CH,electricity residential,67.9,63.7,65.7,67.6,63.0,64.4 -CH,electricity residential space,15.9,12.8,14.3,15.8,12.3,13.5 -CH,electricity residential water,8.8,8.5,8.5,8.6,8.5,8.6 -CH,electricity residential cooking,4.9,4.9,4.9,4.9,5.0,5.0 -CH,total services,145.9,127.4,136.7,144.0,124.5,132.5 -CH,total services space,80.0,62.2,70.8,77.4,58.3,64.3 -CH,total services water,10.1,10.0,10.1,10.1,10.0,10.0 -CH,total services cooking,2.5,2.4,2.3,2.3,2.4,2.3 -CH,electricity services,60.5,59.2,60.3,61.4,60.3,62.6 -CH,electricity services space,4.0,3.2,3.8,4.2,3.3,3.6 -CH,electricity services water,0.7,0.7,0.7,0.7,0.7,0.7 -CH,electricity services cooking,2.5,2.4,2.3,2.3,2.4,2.3 -CH,total rail,11.5,11.1,11.2,11.4,11.1,11.4 -CH,total road,199.4,200.4,200.4,201.2,202.0,203.1 -CH,electricity road,0.,0.,0.,0.,0.,0. -CH,electricity rail,11.5,11.1,11.2,11.4,11.1,11.4 -CH,total domestic aviation,3.3,3.2,3.4,3.4,3.5,3.5 -CH,total international aviation,58.0,62.0,63.5,64.2,64.5,66.8 -CH,total domestic navigation,1.6,1.6,1.6,1.6,1.6,1.6 -CH,total international navigation,0.,0.,0.,0.,0.,0. +country,item,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022 +CH,total residential,268.2,223.4,243.4,261.3,214.2,229.1,241.2,236.5,223.7,226.5,219.1,241.2,211.3 +CH,total residential space,192.2,149,168.1,185.5,139.7,154.4,167.3,161.5,147.2,150.4,140.2,166.2,131.9 +CH,total residential water,32.2,31.6,31.9,32.2,31.7,31.9,31.8,31.8,31.8,31.7,33.3,32.5,32.5 +CH,total residential cooking,9.3,9.3,9.3,9.4,9.5,9.6,9.9,10,10.1,10.2,10.5,10.3,10.3 +CH,electricity residential,67.9,63.7,65.7,67.6,63,64.4,69.7,69.2,67.7,68.1,68.7,70.8,66.8 +CH,electricity residential space,15.9,12.8,14.3,15.8,12.3,13.5,15.8,15.6,14.7,15.3,14.8,17.8,14.8 +CH,electricity residential water,8.8,8.5,8.5,8.6,8.5,8.6,8.9,9,9.2,9.3,9.7,9.5,9.5 +CH,electricity residential cooking,4.9,4.9,4.9,4.9,5,5,5,5.1,5.1,5.1,5.4,5.2,5.3 +CH,total services,145.9,127.4,136.7,144,124.5,132.5,150.5,147.7,141.5,143.1,129.7,144.2,122.5 +CH,total services space,80,62.2,70.8,77.4,58.3,64.3,77,74.4,68.2,69.8,64.3,75.7,58.7 +CH,total services water,10.1,10,10.1,10.1,10,10,11.4,11.3,11.2,11.1,9.7,10.4,12 +CH,total services cooking,2.5,2.4,2.3,2.3,2.4,2.3,3.1,3.1,3.2,3.3,2.1,2.6,3.2 +CH,electricity services,60.5,59.2,60.3,61.4,60.3,62.6,65.9,65.7,65.5,65.6,58.8,61.6,61.6 +CH,electricity services space,4,3.2,3.8,4.2,3.3,3.6,2.7,2.5,2.3,2.3,2.2,2.5,2.5 +CH,electricity services water,0.7,0.7,0.7,0.7,0.7,0.7,1.2,1.1,1.1,1.1,0.9,1,1 +CH,electricity services cooking,2.5,2.4,2.3,2.3,2.4,2.3,3.1,3.1,3.1,3.2,3.3,2.1,3.2 +CH,total rail,11.5,11.1,11.2,11.4,11.1,11.4,11.6,11.4,11.2,11,10.2,10.6,10.8 +CH,total road,199.4,200.4,200.4,201.2,202,203.1,203.9,203.7,202.6,200.5,182.6,188.3,193.3 +CH,electricity road,0,0,0,0,0,0,0.1,0.2,0.3,0.4,0.5,0.8,1.3 +CH,electricity rail,11.5,11.1,11.2,11.4,11.1,11.4,11.5,11.3,11.1,11,10.1,10.6,10.7 +CH,total domestic aviation,3.3,3.2,3.4,3.4,3.5,3.5,3.6,3.1,3.1,2.9,2.5,2.8,3 +CH,total international aviation,58,62,63.5,64.2,64.5,66.8,70.6,72.8,77.2,78.2,28.2,31.2,56.8 +CH,total domestic navigation,1.6,1.6,1.6,1.6,1.6,1.6,1.4,1.4,1.4,1.4,1.4,1.4,1.4 +CH,total international navigation,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/rules/common.smk b/rules/common.smk index 618d746b..c3ce845c 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -131,10 +131,11 @@ def has_internet_access(url="www.zenodo.org") -> bool: def input_eurostat(w): - # 2016 includes BA, 2017 does not - report_year = config_provider("energy", "eurostat_report_year")(w) - return f"data/bundle-sector/eurostat-energy_balances-june_{report_year}_edition" - + if config["energy"]["eurostat_report_year"] != 2023: + report_year = config["energy"]["eurostat_report_year"] + return f"data/bundle-sector/eurostat-energy_balances-june_{report_year}_edition" + else: + return "data/bundle-sector/eurostat-energy_balances-april_2023_edition" def solved_previous_horizon(w): planning_horizons = config_provider("scenario", "planning_horizons")(w) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 960d1bbe..13a8c30d 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -16,6 +16,7 @@ import numpy as np import pandas as pd from _helpers import configure_logging, mute_print, set_scenario_config from tqdm import tqdm +import os cc = coco.CountryConverter() logger = logging.getLogger(__name__) @@ -120,36 +121,93 @@ def build_eurostat(input_eurostat, countries, report_year, year): """ Return multi-index for all countries' energy data in TWh/a. """ - filenames = { + if report_year != 2023: + filenames = { 2016: f"/{year}-Energy-Balances-June2016edition.xlsx", 2017: f"/{year}-ENERGY-BALANCES-June2017edition.xlsx", } - with mute_print(): - dfs = pd.read_excel( - input_eurostat + filenames[report_year], - sheet_name=None, - skiprows=1, - index_col=list(range(4)), - ) + with mute_print(): + dfs = pd.read_excel( + input_eurostat + filenames[report_year], + sheet_name=None, + skiprows=1, + index_col=list(range(4)), + ) - # sorted_index necessary for slicing - lookup = eurostat_codes - labelled_dfs = { - lookup[df.columns[0]]: df - for df in dfs.values() - if lookup[df.columns[0]] in countries - } - df = pd.concat(labelled_dfs, sort=True).sort_index() + # sorted_index necessary for slicing + lookup = eurostat_codes + labelled_dfs = { + lookup[df.columns[0]]: df + for df in dfs.values() + if lookup[df.columns[0]] in countries + } + df = pd.concat(labelled_dfs, sort=True).sort_index() + # drop non-numeric and country columns + non_numeric_cols = df.columns[df.dtypes != float] + country_cols = df.columns.intersection(lookup.keys()) + to_drop = non_numeric_cols.union(country_cols) + df.drop(to_drop, axis=1, inplace=True) - # drop non-numeric and country columns - non_numeric_cols = df.columns[df.dtypes != float] - country_cols = df.columns.intersection(lookup.keys()) - to_drop = non_numeric_cols.union(country_cols) - df.drop(to_drop, axis=1, inplace=True) + # convert ktoe/a to TWh/a + df *= 11.63 / 1e3 + + else: + # read in every country file in countries + eurostat = pd.DataFrame() + countries = [country if country != 'GB' else 'UK' for country in countries] + countries = [country if country != 'GR' else 'EL' for country in countries] + for country in countries: + filename = f"/{country}-Energy-balance-sheets-April-2023-edition.xlsb" + if os.path.exists(input_eurostat + filename): + df = pd.read_excel( + input_eurostat + filename, + engine='pyxlsb', + sheet_name=str(year), + skiprows=4, + index_col=list(range(4))) + # replace entry 'Z' with 0 + df.replace('Z', 0, inplace=True) + # write 'International aviation' to the 2nd level of the multiindex + index_number = (df.index.get_level_values(1) == 'International aviation').argmax() + new_index = ('-', 'International aviation', 'International aviation', 'ktoe') + modified_index = list(df.index) + modified_index[index_number] = new_index + df.index = pd.MultiIndex.from_tuples(modified_index, names=df.index.names) + # drop the annoying subhead line + df.drop(df[df[year] == year].index, inplace=True) + # replace 'Z' with 0 + df = df.replace('Z', 0) + # add country to the multiindex + new_tuple = [(country, *idx) for idx in df.index] + new_mindex = pd.MultiIndex.from_tuples(new_tuple, names=['country', None, 'name', None, 'unit']) + df.index = new_mindex + # make numeric values where possible + df = df.apply(pd.to_numeric, errors='coerce') + # drop non-numeric columns + non_numeric_cols = df.columns[df.dtypes != float] + df.drop(non_numeric_cols, axis=1, inplace=True) + # concatenate the dataframes + eurostat = pd.concat([eurostat, df], axis=0) + + eurostat.drop(["Unnamed: 4", year, "Unnamed: 6"], axis=1, inplace=True) + # Renaming some indices + rename = { + 'Households': 'Residential', + 'Commercial & public services': 'Services', + 'Domestic navigation': 'Domestic Navigation' + } + for name, rename in rename.items(): + eurostat.index = eurostat.index.set_levels( + eurostat.index.levels[3].where(eurostat.index.levels[3] != name, rename), + level=3) + new_index = eurostat.index.set_levels(eurostat.index.levels[2].where(eurostat.index.levels[2] != 'International maritime bunkers', 'Bunkers'), level=2) + eurostat.index = new_index - # convert ktoe/a to TWh/a - df *= 11.63 / 1e3 + eurostat.rename(columns={'Total': 'Total all products'}, inplace=True) + eurostat.index = eurostat.index.set_levels(eurostat.index.levels[0].where(eurostat.index.levels[0] != 'UK', 'GB'), level=0) + + df = eurostat * 11.63 / 1e3 return df @@ -669,31 +727,49 @@ def build_eurostat_co2(input_eurostat, countries, report_year, year=1990): return eurostat.multiply(specific_emissions).sum(axis=1) -def build_co2_totals(countries, eea_co2, eurostat_co2): +def build_co2_totals(countries, eea_co2, eurostat_co2, report_year): co2 = eea_co2.reindex(countries) for ct in pd.Index(countries).intersection(["BA", "RS", "AL", "ME", "MK"]): - mappings = { - "electricity": ( - ct, - "+", - "Conventional Thermal Power Stations", - "of which From Coal", - ), - "residential non-elec": (ct, "+", "+", "Residential"), - "services non-elec": (ct, "+", "+", "Services"), - "road non-elec": (ct, "+", "+", "Road"), - "rail non-elec": (ct, "+", "+", "Rail"), - "domestic navigation": (ct, "+", "+", "Domestic Navigation"), - "international navigation": (ct, "-", "Bunkers"), - "domestic aviation": (ct, "+", "+", "Domestic aviation"), - "international aviation": (ct, "+", "+", "International aviation"), - # does not include industrial process emissions or fuel processing/refining - "industrial non-elec": (ct, "+", "Industry"), - # does not include non-energy emissions - "agriculture": (eurostat_co2.index.get_level_values(0) == ct) - & eurostat_co2.index.isin(["Agriculture / Forestry", "Fishing"], level=3), - } + if report_year != 2023: + mappings = { + "electricity": ( + ct, + "+", + "Conventional Thermal Power Stations", + "of which From Coal", + ), + "residential non-elec": (ct, "+", "+", "Residential"), + "services non-elec": (ct, "+", "+", "Services"), + "road non-elec": (ct, "+", "+", "Road"), + "rail non-elec": (ct, "+", "+", "Rail"), + "domestic navigation": (ct, "+", "+", "Domestic Navigation"), + "international navigation": (ct, "-", "Bunkers"), + "domestic aviation": (ct, "+", "+", "Domestic aviation"), + "international aviation": (ct, "+", "+", "International aviation"), + # does not include industrial process emissions or fuel processing/refining + "industrial non-elec": (ct, "+", "Industry"), + # does not include non-energy emissions + "agriculture": (eurostat_co2.index.get_level_values(0) == ct) + & eurostat_co2.index.isin(["Agriculture / Forestry", "Fishing"], level=3), + } + else: + mappings = { + "electricity": (ct, "+", "Electricity & heat generation", np.nan), + "residential non-elec": (ct, "+", "+", "Residential"), + "services non-elec": (ct, "+", "+", "Services"), + "road non-elec": (ct, "+", "+", "Road"), + "rail non-elec": (ct, "+", "+", "Rail"), + "domestic navigation": (ct, "+", "+", "Domestic Navigation"), + "international navigation": (ct, "-", "Bunkers"), + "domestic aviation": (ct, "+", "+", "Domestic aviation"), + "international aviation": (ct, "-", "International aviation"), + # does not include industrial process emissions or fuel processing/refining + "industrial non-elec": (ct, "+", "Industry sector"), + # does not include non-energy emissions + "agriculture": (eurostat_co2.index.get_level_values(0) == ct) + & eurostat_co2.index.isin(["Agriculture & forestry", "Fishing"], level=3), + } for i, mi in mappings.items(): co2.at[ct, i] = eurostat_co2.loc[mi].sum() @@ -736,6 +812,133 @@ def build_transport_data(countries, population, idees): return transport_data +def rescale(idees_countries, energy, eurostat): + ''' + Takes JRC IDEES data from 2015 and rescales it by the ratio of the + eurostat data and the 2015 eurostat data. + missing data: ['passenger car efficiency', 'passenger cars'] + ''' + # read in the eurostat data for 2015 + eurostat_2015 = build_eurostat(input_eurostat, countries, 2023, 2015)[["Total all products", "Electricity"]] + # eurostat_2015 = eurostat_2015.rename(index={'GB': 'UK'}, level=0) + eurostat_year = eurostat[["Total all products", "Electricity"]] + # calculate the ratio of the two data sets + ratio = eurostat_year / eurostat_2015 + ratio = ratio.droplevel([1,4]) + ratio.rename(columns={"Total all products": "total", "Electricity": "ele"}, inplace=True) + ratio = ratio.rename(index={"GB": "UK"}, level=0) + + residential_total = [ + "total residential space", + "total residential water", + "total residential cooking", + "total residential", + "derived heat residential", + "thermal uses residential", + ] + residential_ele = [ + "electricity residential space", + "electricity residential water", + "electricity residential cooking", + "electricity residential", + ] + + service_total = [ + "total services space", + "total services water", + "total services cooking", + "total services", + "derived heat services", + "thermal uses services", + ] + service_ele = [ + "electricity services space", + "electricity services water", + "electricity services cooking", + "electricity services", + ] + + agri_total = [ + "total agriculture heat", + "total agriculture machinery", + "total agriculture", + ] + agri_ele = [ + "total agriculture electricity", + ] + + road_total = [ + "total road", + "total passenger cars", + "total other road passenger", + "total light duty road freight", + ] + road_ele = [ + "electricity road", + "electricity passenger cars", + "electricity other road passenger", + "electricity light duty road freight", + ] + + rail_total = [ + "total rail", + "total rail passenger", + "total rail freight", + ] + rail_ele = [ + "electricity rail", + "electricity rail passenger", + "electricity rail freight", + ] + + avia_inter = [ + 'total aviation passenger', + 'total aviation freight', + 'total international aviation passenger', + 'total international aviation freight', + 'total international aviation' + ] + avia_domestic = [ + 'total domestic aviation passenger', + 'total domestic aviation freight', + 'total domestic aviation', + ] + navigation = [ + "total domestic navigation", + ] + + idees_countries = idees_countries.repalce({'GB': 'UK', 'GR': 'EL'}) + + for country in idees_countries: + res = ratio.loc[(country, slice(None), 'Residential')] + energy.loc[country, residential_total] *= res[['total']].iloc[0,0] + energy.loc[country, residential_ele] *= res[['ele']].iloc[0,0] + + ser = ratio.loc[(country, slice(None), 'Services')] + energy.loc[country, service_total] *= ser[['total']].iloc[0,0] + energy.loc[country, service_ele] *= ser[['ele']].iloc[0,0] + + agri = ratio.loc[(country, slice(None), 'Agriculture & forestry')] + energy.loc[country, agri_total] *= agri[['total']].iloc[0,0] + energy.loc[country, agri_ele] *= agri[['ele']].iloc[0,0] + + road = ratio.loc[(country, slice(None), 'Road')] + energy.loc[country, road_total] *= road[['total']].iloc[0,0] + energy.loc[country, road_ele] *= road[['ele']].iloc[0,0] + + rail = ratio.loc[(country, slice(None), 'Rail')] + energy.loc[country, rail_total] *= rail[['total']].iloc[0,0] + energy.loc[country, rail_ele] *= rail[['ele']].iloc[0,0] + + avi_d = ratio.loc[(country, slice(None), 'Domestic aviation')] + avi_i = ratio.loc[(country, 'International aviation', slice(None))] + energy.loc[country, avia_inter] *= avi_i[['total']].iloc[0,0] + energy.loc[country, avia_domestic] *= avi_d[['total']].iloc[0,0] + + nav = ratio.loc[(country, slice(None), 'Domestic Navigation')] + energy.loc[country, navigation] *= nav[['total']].iloc[0,0] + + return energy if __name__ == "__main__": if "snakemake" not in globals(): @@ -759,12 +962,22 @@ if __name__ == "__main__": input_eurostat = snakemake.input.eurostat eurostat = build_eurostat(input_eurostat, countries, report_year, data_year) swiss = build_swiss(data_year) - idees = build_idees(idees_countries, data_year) + # data from idees only exists for 2015 + if data_year > 2015: + # read in latest data and rescale later + idees = build_idees(idees_countries, 2015) + else: + idees = build_idees(idees_countries, data_year) energy = build_energy_totals(countries, eurostat, swiss, idees) + + if data_year > 2015: + energy = rescale(idees_countries, energy, eurostat) + energy.to_csv(snakemake.output.energy_name) - district_heat_share = build_district_heat_share(countries, idees) + # use rescaled idees data to calculate district heat share + district_heat_share = build_district_heat_share(countries, energy.loc[idees_countries]) district_heat_share.to_csv(snakemake.output.district_heat_share) base_year_emissions = params["base_emissions_year"] @@ -774,7 +987,7 @@ if __name__ == "__main__": input_eurostat, countries, report_year, base_year_emissions ) - co2 = build_co2_totals(countries, eea_co2, eurostat_co2) + co2 = build_co2_totals(countries, eea_co2, eurostat_co2, report_year) co2.to_csv(snakemake.output.co2_name) transport = build_transport_data(countries, population, idees) From ace51b9e5547ec9c23730c832f4d9a7b5212d5a2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 12:56:43 +0000 Subject: [PATCH 369/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/common.smk | 1 + scripts/build_energy_totals.py | 174 ++++++++++++++++++++------------- 2 files changed, 106 insertions(+), 69 deletions(-) diff --git a/rules/common.smk b/rules/common.smk index c3ce845c..3484c207 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -137,6 +137,7 @@ def input_eurostat(w): else: return "data/bundle-sector/eurostat-energy_balances-april_2023_edition" + def solved_previous_horizon(w): planning_horizons = config_provider("scenario", "planning_horizons")(w) i = planning_horizons.index(int(w.planning_horizons)) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 13a8c30d..a1772143 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -8,6 +8,7 @@ Build total energy demands per country using JRC IDEES, eurostat, and EEA data. import logging import multiprocessing as mp +import os from functools import partial import country_converter as coco @@ -16,7 +17,6 @@ import numpy as np import pandas as pd from _helpers import configure_logging, mute_print, set_scenario_config from tqdm import tqdm -import os cc = coco.CountryConverter() logger = logging.getLogger(__name__) @@ -123,9 +123,9 @@ def build_eurostat(input_eurostat, countries, report_year, year): """ if report_year != 2023: filenames = { - 2016: f"/{year}-Energy-Balances-June2016edition.xlsx", - 2017: f"/{year}-ENERGY-BALANCES-June2017edition.xlsx", - } + 2016: f"/{year}-Energy-Balances-June2016edition.xlsx", + 2017: f"/{year}-ENERGY-BALANCES-June2017edition.xlsx", + } with mute_print(): dfs = pd.read_excel( @@ -151,62 +151,85 @@ def build_eurostat(input_eurostat, countries, report_year, year): # convert ktoe/a to TWh/a df *= 11.63 / 1e3 - + else: # read in every country file in countries eurostat = pd.DataFrame() - countries = [country if country != 'GB' else 'UK' for country in countries] - countries = [country if country != 'GR' else 'EL' for country in countries] + countries = [country if country != "GB" else "UK" for country in countries] + countries = [country if country != "GR" else "EL" for country in countries] for country in countries: filename = f"/{country}-Energy-balance-sheets-April-2023-edition.xlsb" if os.path.exists(input_eurostat + filename): df = pd.read_excel( input_eurostat + filename, - engine='pyxlsb', + engine="pyxlsb", sheet_name=str(year), skiprows=4, - index_col=list(range(4))) + index_col=list(range(4)), + ) # replace entry 'Z' with 0 - df.replace('Z', 0, inplace=True) + df.replace("Z", 0, inplace=True) # write 'International aviation' to the 2nd level of the multiindex - index_number = (df.index.get_level_values(1) == 'International aviation').argmax() - new_index = ('-', 'International aviation', 'International aviation', 'ktoe') + index_number = ( + df.index.get_level_values(1) == "International aviation" + ).argmax() + new_index = ( + "-", + "International aviation", + "International aviation", + "ktoe", + ) modified_index = list(df.index) modified_index[index_number] = new_index - df.index = pd.MultiIndex.from_tuples(modified_index, names=df.index.names) + df.index = pd.MultiIndex.from_tuples( + modified_index, names=df.index.names + ) # drop the annoying subhead line df.drop(df[df[year] == year].index, inplace=True) # replace 'Z' with 0 - df = df.replace('Z', 0) + df = df.replace("Z", 0) # add country to the multiindex new_tuple = [(country, *idx) for idx in df.index] - new_mindex = pd.MultiIndex.from_tuples(new_tuple, names=['country', None, 'name', None, 'unit']) + new_mindex = pd.MultiIndex.from_tuples( + new_tuple, names=["country", None, "name", None, "unit"] + ) df.index = new_mindex # make numeric values where possible - df = df.apply(pd.to_numeric, errors='coerce') + df = df.apply(pd.to_numeric, errors="coerce") # drop non-numeric columns non_numeric_cols = df.columns[df.dtypes != float] df.drop(non_numeric_cols, axis=1, inplace=True) # concatenate the dataframes eurostat = pd.concat([eurostat, df], axis=0) - + eurostat.drop(["Unnamed: 4", year, "Unnamed: 6"], axis=1, inplace=True) # Renaming some indices rename = { - 'Households': 'Residential', - 'Commercial & public services': 'Services', - 'Domestic navigation': 'Domestic Navigation' + "Households": "Residential", + "Commercial & public services": "Services", + "Domestic navigation": "Domestic Navigation", } for name, rename in rename.items(): eurostat.index = eurostat.index.set_levels( - eurostat.index.levels[3].where(eurostat.index.levels[3] != name, rename), - level=3) - new_index = eurostat.index.set_levels(eurostat.index.levels[2].where(eurostat.index.levels[2] != 'International maritime bunkers', 'Bunkers'), level=2) + eurostat.index.levels[3].where( + eurostat.index.levels[3] != name, rename + ), + level=3, + ) + new_index = eurostat.index.set_levels( + eurostat.index.levels[2].where( + eurostat.index.levels[2] != "International maritime bunkers", "Bunkers" + ), + level=2, + ) eurostat.index = new_index - eurostat.rename(columns={'Total': 'Total all products'}, inplace=True) - eurostat.index = eurostat.index.set_levels(eurostat.index.levels[0].where(eurostat.index.levels[0] != 'UK', 'GB'), level=0) - + eurostat.rename(columns={"Total": "Total all products"}, inplace=True) + eurostat.index = eurostat.index.set_levels( + eurostat.index.levels[0].where(eurostat.index.levels[0] != "UK", "GB"), + level=0, + ) + df = eurostat * 11.63 / 1e3 return df @@ -751,7 +774,9 @@ def build_co2_totals(countries, eea_co2, eurostat_co2, report_year): "industrial non-elec": (ct, "+", "Industry"), # does not include non-energy emissions "agriculture": (eurostat_co2.index.get_level_values(0) == ct) - & eurostat_co2.index.isin(["Agriculture / Forestry", "Fishing"], level=3), + & eurostat_co2.index.isin( + ["Agriculture / Forestry", "Fishing"], level=3 + ), } else: mappings = { @@ -768,7 +793,9 @@ def build_co2_totals(countries, eea_co2, eurostat_co2, report_year): "industrial non-elec": (ct, "+", "Industry sector"), # does not include non-energy emissions "agriculture": (eurostat_co2.index.get_level_values(0) == ct) - & eurostat_co2.index.isin(["Agriculture & forestry", "Fishing"], level=3), + & eurostat_co2.index.isin( + ["Agriculture & forestry", "Fishing"], level=3 + ), } for i, mi in mappings.items(): @@ -812,20 +839,26 @@ def build_transport_data(countries, population, idees): return transport_data + def rescale(idees_countries, energy, eurostat): - ''' - Takes JRC IDEES data from 2015 and rescales it by the ratio of the - eurostat data and the 2015 eurostat data. + """ + Takes JRC IDEES data from 2015 and rescales it by the ratio of the eurostat + data and the 2015 eurostat data. + missing data: ['passenger car efficiency', 'passenger cars'] - ''' + """ # read in the eurostat data for 2015 - eurostat_2015 = build_eurostat(input_eurostat, countries, 2023, 2015)[["Total all products", "Electricity"]] + eurostat_2015 = build_eurostat(input_eurostat, countries, 2023, 2015)[ + ["Total all products", "Electricity"] + ] # eurostat_2015 = eurostat_2015.rename(index={'GB': 'UK'}, level=0) eurostat_year = eurostat[["Total all products", "Electricity"]] # calculate the ratio of the two data sets ratio = eurostat_year / eurostat_2015 - ratio = ratio.droplevel([1,4]) - ratio.rename(columns={"Total all products": "total", "Electricity": "ele"}, inplace=True) + ratio = ratio.droplevel([1, 4]) + ratio.rename( + columns={"Total all products": "total", "Electricity": "ele"}, inplace=True + ) ratio = ratio.rename(index={"GB": "UK"}, level=0) residential_total = [ @@ -892,54 +925,55 @@ def rescale(idees_countries, energy, eurostat): ] avia_inter = [ - 'total aviation passenger', - 'total aviation freight', - 'total international aviation passenger', - 'total international aviation freight', - 'total international aviation' + "total aviation passenger", + "total aviation freight", + "total international aviation passenger", + "total international aviation freight", + "total international aviation", ] avia_domestic = [ - 'total domestic aviation passenger', - 'total domestic aviation freight', - 'total domestic aviation', + "total domestic aviation passenger", + "total domestic aviation freight", + "total domestic aviation", ] navigation = [ "total domestic navigation", ] - - idees_countries = idees_countries.repalce({'GB': 'UK', 'GR': 'EL'}) + + idees_countries = idees_countries.repalce({"GB": "UK", "GR": "EL"}) for country in idees_countries: - res = ratio.loc[(country, slice(None), 'Residential')] - energy.loc[country, residential_total] *= res[['total']].iloc[0,0] - energy.loc[country, residential_ele] *= res[['ele']].iloc[0,0] + res = ratio.loc[(country, slice(None), "Residential")] + energy.loc[country, residential_total] *= res[["total"]].iloc[0, 0] + energy.loc[country, residential_ele] *= res[["ele"]].iloc[0, 0] - ser = ratio.loc[(country, slice(None), 'Services')] - energy.loc[country, service_total] *= ser[['total']].iloc[0,0] - energy.loc[country, service_ele] *= ser[['ele']].iloc[0,0] + ser = ratio.loc[(country, slice(None), "Services")] + energy.loc[country, service_total] *= ser[["total"]].iloc[0, 0] + energy.loc[country, service_ele] *= ser[["ele"]].iloc[0, 0] - agri = ratio.loc[(country, slice(None), 'Agriculture & forestry')] - energy.loc[country, agri_total] *= agri[['total']].iloc[0,0] - energy.loc[country, agri_ele] *= agri[['ele']].iloc[0,0] + agri = ratio.loc[(country, slice(None), "Agriculture & forestry")] + energy.loc[country, agri_total] *= agri[["total"]].iloc[0, 0] + energy.loc[country, agri_ele] *= agri[["ele"]].iloc[0, 0] - road = ratio.loc[(country, slice(None), 'Road')] - energy.loc[country, road_total] *= road[['total']].iloc[0,0] - energy.loc[country, road_ele] *= road[['ele']].iloc[0,0] + road = ratio.loc[(country, slice(None), "Road")] + energy.loc[country, road_total] *= road[["total"]].iloc[0, 0] + energy.loc[country, road_ele] *= road[["ele"]].iloc[0, 0] - rail = ratio.loc[(country, slice(None), 'Rail')] - energy.loc[country, rail_total] *= rail[['total']].iloc[0,0] - energy.loc[country, rail_ele] *= rail[['ele']].iloc[0,0] + rail = ratio.loc[(country, slice(None), "Rail")] + energy.loc[country, rail_total] *= rail[["total"]].iloc[0, 0] + energy.loc[country, rail_ele] *= rail[["ele"]].iloc[0, 0] - avi_d = ratio.loc[(country, slice(None), 'Domestic aviation')] - avi_i = ratio.loc[(country, 'International aviation', slice(None))] - energy.loc[country, avia_inter] *= avi_i[['total']].iloc[0,0] - energy.loc[country, avia_domestic] *= avi_d[['total']].iloc[0,0] + avi_d = ratio.loc[(country, slice(None), "Domestic aviation")] + avi_i = ratio.loc[(country, "International aviation", slice(None))] + energy.loc[country, avia_inter] *= avi_i[["total"]].iloc[0, 0] + energy.loc[country, avia_domestic] *= avi_d[["total"]].iloc[0, 0] - nav = ratio.loc[(country, slice(None), 'Domestic Navigation')] - energy.loc[country, navigation] *= nav[['total']].iloc[0,0] + nav = ratio.loc[(country, slice(None), "Domestic Navigation")] + energy.loc[country, navigation] *= nav[["total"]].iloc[0, 0] return energy + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -970,14 +1004,16 @@ if __name__ == "__main__": idees = build_idees(idees_countries, data_year) energy = build_energy_totals(countries, eurostat, swiss, idees) - + if data_year > 2015: energy = rescale(idees_countries, energy, eurostat) - + energy.to_csv(snakemake.output.energy_name) # use rescaled idees data to calculate district heat share - district_heat_share = build_district_heat_share(countries, energy.loc[idees_countries]) + district_heat_share = build_district_heat_share( + countries, energy.loc[idees_countries] + ) district_heat_share.to_csv(snakemake.output.district_heat_share) base_year_emissions = params["base_emissions_year"] From c6ed36df625a382cf4451ddf0ef57448d5f8dd75 Mon Sep 17 00:00:00 2001 From: lisazeyen Date: Fri, 23 Feb 2024 15:23:55 +0100 Subject: [PATCH 370/591] adjust AC bus to low voltage --- scripts/add_existing_baseyear.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 750ab22f..d6f1802c 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -416,6 +416,11 @@ def add_heating_capacities_installed_before_baseyear( name_type = "central" if name == "urban central" else "decentral" nodes = pd.Index(n.buses.location[n.buses.index.str.contains(f"{name} heat")]) + + if (name_type != "central") and options["electricity_distribution_grid"]: + nodes_elec = nodes + " low voltage" + else: + nodes_elec = nodes heat_pump_type = "air" if "urban" in name else "ground" @@ -440,7 +445,7 @@ def add_heating_capacities_installed_before_baseyear( "Link", nodes, suffix=f" {name} {heat_pump_type} heat pump-{grouping_year}", - bus0=nodes, + bus0=nodes_elec, bus1=nodes + " " + name + " heat", carrier=f"{name} {heat_pump_type} heat pump", efficiency=efficiency, @@ -458,7 +463,7 @@ def add_heating_capacities_installed_before_baseyear( "Link", nodes, suffix=f" {name} resistive heater-{grouping_year}", - bus0=nodes, + bus0=nodes_elec, bus1=nodes + " " + name + " heat", carrier=name + " resistive heater", efficiency=costs.at[f"{name_type} resistive heater", "efficiency"], @@ -540,7 +545,7 @@ def add_heating_capacities_installed_before_baseyear( ], ) - +#%% if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -552,7 +557,7 @@ if __name__ == "__main__": clusters="37", ll="v1.0", opts="", - sector_opts="1p7-4380H-T-H-B-I-A-dist1", + sector_opts="8760-T-H-B-I-A-dist1", planning_horizons=2020, ) From 60653de9f628e911a50c06400614d72e4c527045 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:27:17 +0000 Subject: [PATCH 371/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/add_existing_baseyear.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index d6f1802c..44c9b20e 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -416,7 +416,7 @@ def add_heating_capacities_installed_before_baseyear( name_type = "central" if name == "urban central" else "decentral" nodes = pd.Index(n.buses.location[n.buses.index.str.contains(f"{name} heat")]) - + if (name_type != "central") and options["electricity_distribution_grid"]: nodes_elec = nodes + " low voltage" else: @@ -545,7 +545,8 @@ def add_heating_capacities_installed_before_baseyear( ], ) -#%% + +# %% if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake From 1db30ae63b0b9b1372d4174f11636d5770793af4 Mon Sep 17 00:00:00 2001 From: Adrian Odenweller Date: Sat, 24 Feb 2024 12:10:08 +0100 Subject: [PATCH 372/591] Allow CPELX for MIQP in cluster_network --- scripts/cluster_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index be315a63..95f36bb4 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -267,7 +267,7 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="scip"): m.objective = (clusters * clusters - 2 * clusters * L * n_clusters).sum() if solver_name == "gurobi": logging.getLogger("gurobipy").propagate = False - elif solver_name != "scip": + elif solver_name != "scip" and solver_name != "cplex": logger.info( f"The configured solver `{solver_name}` does not support quadratic objectives. Falling back to `scip`." ) From 58bcef4625f3d3e8aeaba4715d205e883e68a8c4 Mon Sep 17 00:00:00 2001 From: Fabian Hofmann Date: Tue, 27 Feb 2024 11:39:26 +0100 Subject: [PATCH 373/591] cluster_network: update solver_name if clause style --- scripts/cluster_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 95f36bb4..757184b2 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -267,7 +267,7 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="scip"): m.objective = (clusters * clusters - 2 * clusters * L * n_clusters).sum() if solver_name == "gurobi": logging.getLogger("gurobipy").propagate = False - elif solver_name != "scip" and solver_name != "cplex": + elif solver_name not in ["scip", "cplex"]: logger.info( f"The configured solver `{solver_name}` does not support quadratic objectives. Falling back to `scip`." ) From d363aeb57dac2370199b1a260e7c31c1014c074d Mon Sep 17 00:00:00 2001 From: toniseibold Date: Tue, 27 Feb 2024 12:04:07 +0100 Subject: [PATCH 374/591] removing old eurostat data reports as an option, cleaning up code --- config/config.default.yaml | 1 - rules/build_sector.smk | 4 +- rules/common.smk | 8 - rules/postprocess.smk | 2 +- rules/retrieve.smk | 3 + scripts/build_energy_totals.py | 354 ++++++++++---------------- scripts/retrieve_sector_databundle.py | 14 + 7 files changed, 152 insertions(+), 234 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 093b1aad..b2828a44 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -316,7 +316,6 @@ pypsa_eur: energy: energy_totals_year: 2019 base_emissions_year: 1990 - eurostat_report_year: 2023 emissions: CO2 # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#biomass diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 466d1713..6c542f4e 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -270,7 +270,7 @@ rule build_energy_totals: swiss="data/switzerland-new_format-all_years.csv", idees="data/bundle-sector/jrc-idees-2015", district_heat_share="data/district_heat_share.csv", - eurostat=input_eurostat, + eurostat="data/bundle-sector/eurostat-energy_balances-april_2023_edition", output: energy_name=resources("energy_totals.csv"), co2_name=resources("co2_totals.csv"), @@ -865,7 +865,7 @@ rule prepare_sector_network: ), network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), energy_totals_name=resources("energy_totals.csv"), - eurostat=input_eurostat, + eurostat="data/bundle-sector/eurostat-energy_balances-april_2023_edition", pop_weighted_energy_totals=resources( "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" ), diff --git a/rules/common.smk b/rules/common.smk index c3ce845c..8e0e1e66 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -129,14 +129,6 @@ def has_internet_access(url="www.zenodo.org") -> bool: finally: conn.close() - -def input_eurostat(w): - if config["energy"]["eurostat_report_year"] != 2023: - report_year = config["energy"]["eurostat_report_year"] - return f"data/bundle-sector/eurostat-energy_balances-june_{report_year}_edition" - else: - return "data/bundle-sector/eurostat-energy_balances-april_2023_edition" - def solved_previous_horizon(w): planning_horizons = config_provider("scenario", "planning_horizons")(w) i = planning_horizons.index(int(w.planning_horizons)) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index dc08699f..5f93540f 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -247,7 +247,7 @@ rule plot_summary: costs=RESULTS + "csvs/costs.csv", energy=RESULTS + "csvs/energy.csv", balances=RESULTS + "csvs/supply_energy.csv", - eurostat=input_eurostat, + eurostat="data/bundle-sector/eurostat-energy_balances-april_2023_edition", co2="data/bundle-sector/eea/UNFCCC_v23.csv", output: costs=RESULTS + "graphs/costs.pdf", diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 29d050ab..8ef373d1 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -142,6 +142,9 @@ if config["enable"]["retrieve"] and config["enable"].get( protected( directory("data/bundle-sector/eurostat-energy_balances-may_2018_edition") ), + protected( + directory("data/bundle-sector/eurostat-energy_balances-april_2023_edition") + ), protected(directory("data/bundle-sector/jrc-idees-2015")), ] diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 13a8c30d..16c99d8f 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -117,97 +117,65 @@ to_ipcc = { } -def build_eurostat(input_eurostat, countries, report_year, year): +def build_eurostat(input_eurostat, countries, year): """ Return multi-index for all countries' energy data in TWh/a. """ - if report_year != 2023: - filenames = { - 2016: f"/{year}-Energy-Balances-June2016edition.xlsx", - 2017: f"/{year}-ENERGY-BALANCES-June2017edition.xlsx", - } - - with mute_print(): - dfs = pd.read_excel( - input_eurostat + filenames[report_year], - sheet_name=None, - skiprows=1, - index_col=list(range(4)), - ) - - # sorted_index necessary for slicing - lookup = eurostat_codes - labelled_dfs = { - lookup[df.columns[0]]: df - for df in dfs.values() - if lookup[df.columns[0]] in countries - } - df = pd.concat(labelled_dfs, sort=True).sort_index() - # drop non-numeric and country columns - non_numeric_cols = df.columns[df.dtypes != float] - country_cols = df.columns.intersection(lookup.keys()) - to_drop = non_numeric_cols.union(country_cols) - df.drop(to_drop, axis=1, inplace=True) - - # convert ktoe/a to TWh/a - df *= 11.63 / 1e3 + # read in every country file in countries + eurostat = pd.DataFrame() + countries = [country if country != 'GB' else 'UK' for country in countries] + countries = [country if country != 'GR' else 'EL' for country in countries] + for country in countries: + filename = f"/{country}-Energy-balance-sheets-April-2023-edition.xlsb" + if os.path.exists(input_eurostat + filename): + df = pd.read_excel( + input_eurostat + filename, + engine='pyxlsb', + sheet_name=str(year), + skiprows=4, + index_col=list(range(4))) + # replace entry 'Z' with 0 + df.replace('Z', 0, inplace=True) + # write 'International aviation' to the 2nd level of the multiindex + index_number = (df.index.get_level_values(1) == 'International aviation').argmax() + new_index = ('-', 'International aviation', 'International aviation', 'ktoe') + modified_index = list(df.index) + modified_index[index_number] = new_index + df.index = pd.MultiIndex.from_tuples(modified_index, names=df.index.names) + # drop the annoying subhead line + df.drop(df[df[year] == year].index, inplace=True) + # replace 'Z' with 0 + df = df.replace('Z', 0) + # add country to the multiindex + new_tuple = [(country, *idx) for idx in df.index] + new_mindex = pd.MultiIndex.from_tuples(new_tuple, names=['country', None, 'name', None, 'unit']) + df.index = new_mindex + # make numeric values where possible + df = df.apply(pd.to_numeric, errors='coerce') + # drop non-numeric columns + non_numeric_cols = df.columns[df.dtypes != float] + df.drop(non_numeric_cols, axis=1, inplace=True) + # concatenate the dataframes + eurostat = pd.concat([eurostat, df], axis=0) - else: - # read in every country file in countries - eurostat = pd.DataFrame() - countries = [country if country != 'GB' else 'UK' for country in countries] - countries = [country if country != 'GR' else 'EL' for country in countries] - for country in countries: - filename = f"/{country}-Energy-balance-sheets-April-2023-edition.xlsb" - if os.path.exists(input_eurostat + filename): - df = pd.read_excel( - input_eurostat + filename, - engine='pyxlsb', - sheet_name=str(year), - skiprows=4, - index_col=list(range(4))) - # replace entry 'Z' with 0 - df.replace('Z', 0, inplace=True) - # write 'International aviation' to the 2nd level of the multiindex - index_number = (df.index.get_level_values(1) == 'International aviation').argmax() - new_index = ('-', 'International aviation', 'International aviation', 'ktoe') - modified_index = list(df.index) - modified_index[index_number] = new_index - df.index = pd.MultiIndex.from_tuples(modified_index, names=df.index.names) - # drop the annoying subhead line - df.drop(df[df[year] == year].index, inplace=True) - # replace 'Z' with 0 - df = df.replace('Z', 0) - # add country to the multiindex - new_tuple = [(country, *idx) for idx in df.index] - new_mindex = pd.MultiIndex.from_tuples(new_tuple, names=['country', None, 'name', None, 'unit']) - df.index = new_mindex - # make numeric values where possible - df = df.apply(pd.to_numeric, errors='coerce') - # drop non-numeric columns - non_numeric_cols = df.columns[df.dtypes != float] - df.drop(non_numeric_cols, axis=1, inplace=True) - # concatenate the dataframes - eurostat = pd.concat([eurostat, df], axis=0) - - eurostat.drop(["Unnamed: 4", year, "Unnamed: 6"], axis=1, inplace=True) - # Renaming some indices - rename = { - 'Households': 'Residential', - 'Commercial & public services': 'Services', - 'Domestic navigation': 'Domestic Navigation' - } - for name, rename in rename.items(): - eurostat.index = eurostat.index.set_levels( - eurostat.index.levels[3].where(eurostat.index.levels[3] != name, rename), - level=3) - new_index = eurostat.index.set_levels(eurostat.index.levels[2].where(eurostat.index.levels[2] != 'International maritime bunkers', 'Bunkers'), level=2) - eurostat.index = new_index + eurostat.drop(["Unnamed: 4", year, "Unnamed: 6"], axis=1, inplace=True) + # Renaming some indices + rename = { + 'Households': 'Residential', + 'Commercial & public services': 'Services', + 'Domestic navigation': 'Domestic Navigation' + } + for name, rename in rename.items(): + eurostat.index = eurostat.index.set_levels( + eurostat.index.levels[3].where(eurostat.index.levels[3] != name, rename), + level=3) + new_index = eurostat.index.set_levels(eurostat.index.levels[2].where(eurostat.index.levels[2] != 'International maritime bunkers', 'Bunkers'), level=2) + eurostat.index = new_index - eurostat.rename(columns={'Total': 'Total all products'}, inplace=True) - eurostat.index = eurostat.index.set_levels(eurostat.index.levels[0].where(eurostat.index.levels[0] != 'UK', 'GB'), level=0) - - df = eurostat * 11.63 / 1e3 + eurostat.rename(columns={'Total': 'Total all products'}, inplace=True) + eurostat.index = eurostat.index.set_levels(eurostat.index.levels[0].where(eurostat.index.levels[0] != 'UK', 'GB'), level=0) + + df = eurostat * 11.63 / 1e3 return df @@ -709,8 +677,8 @@ def build_eea_co2(input_co2, year=1990, emissions_scope="CO2"): return emissions / 1e3 -def build_eurostat_co2(input_eurostat, countries, report_year, year=1990): - eurostat = build_eurostat(input_eurostat, countries, report_year, year) +def build_eurostat_co2(input_eurostat, countries, year=1990): + eurostat = build_eurostat(input_eurostat, countries, year) specific_emissions = pd.Series(index=eurostat.columns, dtype=float) @@ -727,49 +695,26 @@ def build_eurostat_co2(input_eurostat, countries, report_year, year=1990): return eurostat.multiply(specific_emissions).sum(axis=1) -def build_co2_totals(countries, eea_co2, eurostat_co2, report_year): +def build_co2_totals(countries, eea_co2, eurostat_co2): co2 = eea_co2.reindex(countries) for ct in pd.Index(countries).intersection(["BA", "RS", "AL", "ME", "MK"]): - if report_year != 2023: - mappings = { - "electricity": ( - ct, - "+", - "Conventional Thermal Power Stations", - "of which From Coal", - ), - "residential non-elec": (ct, "+", "+", "Residential"), - "services non-elec": (ct, "+", "+", "Services"), - "road non-elec": (ct, "+", "+", "Road"), - "rail non-elec": (ct, "+", "+", "Rail"), - "domestic navigation": (ct, "+", "+", "Domestic Navigation"), - "international navigation": (ct, "-", "Bunkers"), - "domestic aviation": (ct, "+", "+", "Domestic aviation"), - "international aviation": (ct, "+", "+", "International aviation"), - # does not include industrial process emissions or fuel processing/refining - "industrial non-elec": (ct, "+", "Industry"), - # does not include non-energy emissions - "agriculture": (eurostat_co2.index.get_level_values(0) == ct) - & eurostat_co2.index.isin(["Agriculture / Forestry", "Fishing"], level=3), - } - else: - mappings = { - "electricity": (ct, "+", "Electricity & heat generation", np.nan), - "residential non-elec": (ct, "+", "+", "Residential"), - "services non-elec": (ct, "+", "+", "Services"), - "road non-elec": (ct, "+", "+", "Road"), - "rail non-elec": (ct, "+", "+", "Rail"), - "domestic navigation": (ct, "+", "+", "Domestic Navigation"), - "international navigation": (ct, "-", "Bunkers"), - "domestic aviation": (ct, "+", "+", "Domestic aviation"), - "international aviation": (ct, "-", "International aviation"), - # does not include industrial process emissions or fuel processing/refining - "industrial non-elec": (ct, "+", "Industry sector"), - # does not include non-energy emissions - "agriculture": (eurostat_co2.index.get_level_values(0) == ct) - & eurostat_co2.index.isin(["Agriculture & forestry", "Fishing"], level=3), - } + mappings = { + "electricity": (ct, "+", "Electricity & heat generation", np.nan), + "residential non-elec": (ct, "+", "+", "Residential"), + "services non-elec": (ct, "+", "+", "Services"), + "road non-elec": (ct, "+", "+", "Road"), + "rail non-elec": (ct, "+", "+", "Rail"), + "domestic navigation": (ct, "+", "+", "Domestic Navigation"), + "international navigation": (ct, "-", "Bunkers"), + "domestic aviation": (ct, "+", "+", "Domestic aviation"), + "international aviation": (ct, "-", "International aviation"), + # does not include industrial process emissions or fuel processing/refining + "industrial non-elec": (ct, "+", "Industry sector"), + # does not include non-energy emissions + "agriculture": (eurostat_co2.index.get_level_values(0) == ct) + & eurostat_co2.index.isin(["Agriculture & forestry", "Fishing"], level=3), + } for i, mi in mappings.items(): co2.at[ct, i] = eurostat_co2.loc[mi].sum() @@ -820,83 +765,65 @@ def rescale(idees_countries, energy, eurostat): ''' # read in the eurostat data for 2015 eurostat_2015 = build_eurostat(input_eurostat, countries, 2023, 2015)[["Total all products", "Electricity"]] - # eurostat_2015 = eurostat_2015.rename(index={'GB': 'UK'}, level=0) eurostat_year = eurostat[["Total all products", "Electricity"]] # calculate the ratio of the two data sets ratio = eurostat_year / eurostat_2015 ratio = ratio.droplevel([1,4]) ratio.rename(columns={"Total all products": "total", "Electricity": "ele"}, inplace=True) - ratio = ratio.rename(index={"GB": "UK"}, level=0) + ratio = ratio.rename(index={"EL": "GR"}, level=0) - residential_total = [ - "total residential space", - "total residential water", - "total residential cooking", - "total residential", - "derived heat residential", - "thermal uses residential", - ] - residential_ele = [ - "electricity residential space", - "electricity residential water", - "electricity residential cooking", - "electricity residential", - ] - - service_total = [ - "total services space", - "total services water", - "total services cooking", - "total services", - "derived heat services", - "thermal uses services", - ] - service_ele = [ - "electricity services space", - "electricity services water", - "electricity services cooking", - "electricity services", - ] - - agri_total = [ - "total agriculture heat", - "total agriculture machinery", - "total agriculture", - ] - agri_ele = [ - "total agriculture electricity", - ] - - road_total = [ - "total road", - "total passenger cars", - "total other road passenger", - "total light duty road freight", - ] - road_ele = [ - "electricity road", - "electricity passenger cars", - "electricity other road passenger", - "electricity light duty road freight", - ] - - rail_total = [ - "total rail", - "total rail passenger", - "total rail freight", - ] - rail_ele = [ - "electricity rail", - "electricity rail passenger", - "electricity rail freight", - ] + mappings = { + "Residential": { + "total": ["total residential space", + "total residential water", + "total residential cooking", + "total residential", + "derived heat residential", + "thermal uses residential",], + "elec": ["electricity residential space", + "electricity residential water", + "electricity residential cooking", + "electricity residential",]}, + "Services": { + "total": ["total services space", + "total services water", + "total services cooking", + "total services", + "derived heat services", + "thermal uses services",], + "elec": ["electricity services space", + "electricity services water", + "electricity services cooking", + "electricity services",]}, + "Agriculture & forestry": { + "total": ["total agriculture heat", + "total agriculture machinery", + "total agriculture",], + "elec": ["total agriculture electricity",]}, + "Road": { + "total": ["total road", + "total passenger cars", + "total other road passenger", + "total light duty road freight",], + "elec": ["electricity road", + "electricity passenger cars", + "electricity other road passenger", + "electricity light duty road freight",]}, + "Rail": { + "total": ["total rail", + "total rail passenger", + "total rail freight",], + "elec": ["electricity rail", + "electricity rail passenger", + "electricity rail freight",]}, + } avia_inter = [ - 'total aviation passenger', - 'total aviation freight', - 'total international aviation passenger', - 'total international aviation freight', - 'total international aviation' + 'total aviation passenger', + 'total aviation freight', + 'total international aviation passenger', + 'total international aviation freight', + 'total international aviation' ] avia_domestic = [ 'total domestic aviation passenger', @@ -906,30 +833,14 @@ def rescale(idees_countries, energy, eurostat): navigation = [ "total domestic navigation", ] - - idees_countries = idees_countries.repalce({'GB': 'UK', 'GR': 'EL'}) for country in idees_countries: - res = ratio.loc[(country, slice(None), 'Residential')] - energy.loc[country, residential_total] *= res[['total']].iloc[0,0] - energy.loc[country, residential_ele] *= res[['ele']].iloc[0,0] - - ser = ratio.loc[(country, slice(None), 'Services')] - energy.loc[country, service_total] *= ser[['total']].iloc[0,0] - energy.loc[country, service_ele] *= ser[['ele']].iloc[0,0] - - agri = ratio.loc[(country, slice(None), 'Agriculture & forestry')] - energy.loc[country, agri_total] *= agri[['total']].iloc[0,0] - energy.loc[country, agri_ele] *= agri[['ele']].iloc[0,0] - - road = ratio.loc[(country, slice(None), 'Road')] - energy.loc[country, road_total] *= road[['total']].iloc[0,0] - energy.loc[country, road_ele] *= road[['ele']].iloc[0,0] - - rail = ratio.loc[(country, slice(None), 'Rail')] - energy.loc[country, rail_total] *= rail[['total']].iloc[0,0] - energy.loc[country, rail_ele] *= rail[['ele']].iloc[0,0] + for sector, mapping in mappings.items(): + sector_ratio = ratio.loc[(country, slice(None), sector)] + energy.loc[country, mapping["total"]] *= sector_ratio[['total']].iloc[0,0] + energy.loc[country, mapping["elec"]] *= sector_ratio[['ele']].iloc[0,0] + avi_d = ratio.loc[(country, slice(None), 'Domestic aviation')] avi_i = ratio.loc[(country, 'International aviation', slice(None))] energy.loc[country, avia_inter] *= avi_i[['total']].iloc[0,0] @@ -958,9 +869,8 @@ if __name__ == "__main__": idees_countries = pd.Index(countries).intersection(eu28) data_year = params["energy_totals_year"] - report_year = snakemake.params.energy["eurostat_report_year"] input_eurostat = snakemake.input.eurostat - eurostat = build_eurostat(input_eurostat, countries, report_year, data_year) + eurostat = build_eurostat(input_eurostat, countries, data_year) swiss = build_swiss(data_year) # data from idees only exists for 2015 if data_year > 2015: @@ -984,10 +894,10 @@ if __name__ == "__main__": emissions_scope = snakemake.params.energy["emissions"] eea_co2 = build_eea_co2(snakemake.input.co2, base_year_emissions, emissions_scope) eurostat_co2 = build_eurostat_co2( - input_eurostat, countries, report_year, base_year_emissions + input_eurostat, countries, base_year_emissions ) - co2 = build_co2_totals(countries, eea_co2, eurostat_co2, report_year) + co2 = build_co2_totals(countries, eea_co2, eurostat_co2) co2.to_csv(snakemake.output.co2_name) transport = build_transport_data(countries, population, idees) diff --git a/scripts/retrieve_sector_databundle.py b/scripts/retrieve_sector_databundle.py index 3b825da2..a075119e 100644 --- a/scripts/retrieve_sector_databundle.py +++ b/scripts/retrieve_sector_databundle.py @@ -8,6 +8,7 @@ Retrieve and extract data bundle for sector-coupled studies. import logging import tarfile +import zipfile from pathlib import Path from _helpers import ( @@ -47,3 +48,16 @@ if __name__ == "__main__": tarball_fn.unlink() logger.info(f"Databundle available in '{to_fn}'.") + + url_eurostat = "https://ec.europa.eu/eurostat/documents/38154/4956218/Balances-December2022.zip/f7cf0d19-5c0f-60ad-4e48-098a5ddd6e48?t=1671184070589" + tarball_fn = Path(f"{rootpath}/data/bundle-sector/eurostat_2023.zip") + to_fn = Path(f"{rootpath}/data/bundle-sector/eurostat-energy_balances-april_2023_edition/") + + logger.info(f"Downloading Eurostat data from '{url_eurostat}'.") + progress_retrieve(url_eurostat, tarball_fn, disable=disable_progress) + + logger.info("Extracting Eurostat data.") + with zipfile.ZipFile(tarball_fn, 'r') as zip_ref: + zip_ref.extractall(to_fn) + + logger.info(f"Eurostat data available in '{to_fn}'.") \ No newline at end of file From 9182d6d667df59f435cd7d5d9c9f651665cd3df8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 12:14:41 +0000 Subject: [PATCH 375/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/common.smk | 1 + scripts/build_energy_totals.py | 197 ++++++++++++++++---------- scripts/retrieve_sector_databundle.py | 8 +- 3 files changed, 127 insertions(+), 79 deletions(-) diff --git a/rules/common.smk b/rules/common.smk index 8e0e1e66..2b8495e1 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -129,6 +129,7 @@ def has_internet_access(url="www.zenodo.org") -> bool: finally: conn.close() + def solved_previous_horizon(w): planning_horizons = config_provider("scenario", "planning_horizons")(w) i = planning_horizons.index(int(w.planning_horizons)) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 24e41451..d6c63f00 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -123,58 +123,76 @@ def build_eurostat(input_eurostat, countries, year): """ # read in every country file in countries eurostat = pd.DataFrame() - countries = [country if country != 'GB' else 'UK' for country in countries] - countries = [country if country != 'GR' else 'EL' for country in countries] + countries = [country if country != "GB" else "UK" for country in countries] + countries = [country if country != "GR" else "EL" for country in countries] for country in countries: filename = f"/{country}-Energy-balance-sheets-April-2023-edition.xlsb" if os.path.exists(input_eurostat + filename): df = pd.read_excel( input_eurostat + filename, - engine='pyxlsb', + engine="pyxlsb", sheet_name=str(year), skiprows=4, - index_col=list(range(4))) + index_col=list(range(4)), + ) # replace entry 'Z' with 0 - df.replace('Z', 0, inplace=True) + df.replace("Z", 0, inplace=True) # write 'International aviation' to the 2nd level of the multiindex - index_number = (df.index.get_level_values(1) == 'International aviation').argmax() - new_index = ('-', 'International aviation', 'International aviation', 'ktoe') + index_number = ( + df.index.get_level_values(1) == "International aviation" + ).argmax() + new_index = ( + "-", + "International aviation", + "International aviation", + "ktoe", + ) modified_index = list(df.index) modified_index[index_number] = new_index df.index = pd.MultiIndex.from_tuples(modified_index, names=df.index.names) # drop the annoying subhead line df.drop(df[df[year] == year].index, inplace=True) # replace 'Z' with 0 - df = df.replace('Z', 0) + df = df.replace("Z", 0) # add country to the multiindex new_tuple = [(country, *idx) for idx in df.index] - new_mindex = pd.MultiIndex.from_tuples(new_tuple, names=['country', None, 'name', None, 'unit']) + new_mindex = pd.MultiIndex.from_tuples( + new_tuple, names=["country", None, "name", None, "unit"] + ) df.index = new_mindex # make numeric values where possible - df = df.apply(pd.to_numeric, errors='coerce') + df = df.apply(pd.to_numeric, errors="coerce") # drop non-numeric columns non_numeric_cols = df.columns[df.dtypes != float] df.drop(non_numeric_cols, axis=1, inplace=True) # concatenate the dataframes eurostat = pd.concat([eurostat, df], axis=0) - + eurostat.drop(["Unnamed: 4", year, "Unnamed: 6"], axis=1, inplace=True) # Renaming some indices rename = { - 'Households': 'Residential', - 'Commercial & public services': 'Services', - 'Domestic navigation': 'Domestic Navigation' + "Households": "Residential", + "Commercial & public services": "Services", + "Domestic navigation": "Domestic Navigation", } for name, rename in rename.items(): eurostat.index = eurostat.index.set_levels( - eurostat.index.levels[3].where(eurostat.index.levels[3] != name, rename), - level=3) - new_index = eurostat.index.set_levels(eurostat.index.levels[2].where(eurostat.index.levels[2] != 'International maritime bunkers', 'Bunkers'), level=2) + eurostat.index.levels[3].where(eurostat.index.levels[3] != name, rename), + level=3, + ) + new_index = eurostat.index.set_levels( + eurostat.index.levels[2].where( + eurostat.index.levels[2] != "International maritime bunkers", "Bunkers" + ), + level=2, + ) eurostat.index = new_index - eurostat.rename(columns={'Total': 'Total all products'}, inplace=True) - eurostat.index = eurostat.index.set_levels(eurostat.index.levels[0].where(eurostat.index.levels[0] != 'UK', 'GB'), level=0) - + eurostat.rename(columns={"Total": "Total all products"}, inplace=True) + eurostat.index = eurostat.index.set_levels( + eurostat.index.levels[0].where(eurostat.index.levels[0] != "UK", "GB"), level=0 + ) + df = eurostat * 11.63 / 1e3 return df @@ -766,66 +784,95 @@ def rescale(idees_countries, energy, eurostat): missing data: ['passenger car efficiency', 'passenger cars'] """ # read in the eurostat data for 2015 - eurostat_2015 = build_eurostat(input_eurostat, countries, 2023, 2015)[["Total all products", "Electricity"]] + eurostat_2015 = build_eurostat(input_eurostat, countries, 2023, 2015)[ + ["Total all products", "Electricity"] + ] eurostat_year = eurostat[["Total all products", "Electricity"]] # calculate the ratio of the two data sets ratio = eurostat_year / eurostat_2015 - ratio = ratio.droplevel([1,4]) - ratio.rename(columns={"Total all products": "total", "Electricity": "ele"}, inplace=True) + ratio = ratio.droplevel([1, 4]) + ratio.rename( + columns={"Total all products": "total", "Electricity": "ele"}, inplace=True + ) ratio = ratio.rename(index={"EL": "GR"}, level=0) mappings = { "Residential": { - "total": ["total residential space", - "total residential water", - "total residential cooking", - "total residential", - "derived heat residential", - "thermal uses residential",], - "elec": ["electricity residential space", - "electricity residential water", - "electricity residential cooking", - "electricity residential",]}, + "total": [ + "total residential space", + "total residential water", + "total residential cooking", + "total residential", + "derived heat residential", + "thermal uses residential", + ], + "elec": [ + "electricity residential space", + "electricity residential water", + "electricity residential cooking", + "electricity residential", + ], + }, "Services": { - "total": ["total services space", - "total services water", - "total services cooking", - "total services", - "derived heat services", - "thermal uses services",], - "elec": ["electricity services space", - "electricity services water", - "electricity services cooking", - "electricity services",]}, + "total": [ + "total services space", + "total services water", + "total services cooking", + "total services", + "derived heat services", + "thermal uses services", + ], + "elec": [ + "electricity services space", + "electricity services water", + "electricity services cooking", + "electricity services", + ], + }, "Agriculture & forestry": { - "total": ["total agriculture heat", - "total agriculture machinery", - "total agriculture",], - "elec": ["total agriculture electricity",]}, + "total": [ + "total agriculture heat", + "total agriculture machinery", + "total agriculture", + ], + "elec": [ + "total agriculture electricity", + ], + }, "Road": { - "total": ["total road", - "total passenger cars", - "total other road passenger", - "total light duty road freight",], - "elec": ["electricity road", - "electricity passenger cars", - "electricity other road passenger", - "electricity light duty road freight",]}, + "total": [ + "total road", + "total passenger cars", + "total other road passenger", + "total light duty road freight", + ], + "elec": [ + "electricity road", + "electricity passenger cars", + "electricity other road passenger", + "electricity light duty road freight", + ], + }, "Rail": { - "total": ["total rail", - "total rail passenger", - "total rail freight",], - "elec": ["electricity rail", - "electricity rail passenger", - "electricity rail freight",]}, + "total": [ + "total rail", + "total rail passenger", + "total rail freight", + ], + "elec": [ + "electricity rail", + "electricity rail passenger", + "electricity rail freight", + ], + }, } avia_inter = [ - 'total aviation passenger', - 'total aviation freight', - 'total international aviation passenger', - 'total international aviation freight', - 'total international aviation' + "total aviation passenger", + "total aviation freight", + "total international aviation passenger", + "total international aviation freight", + "total international aviation", ] avia_domestic = [ "total domestic aviation passenger", @@ -840,13 +887,13 @@ def rescale(idees_countries, energy, eurostat): for sector, mapping in mappings.items(): sector_ratio = ratio.loc[(country, slice(None), sector)] - energy.loc[country, mapping["total"]] *= sector_ratio[['total']].iloc[0,0] - energy.loc[country, mapping["elec"]] *= sector_ratio[['ele']].iloc[0,0] - - avi_d = ratio.loc[(country, slice(None), 'Domestic aviation')] - avi_i = ratio.loc[(country, 'International aviation', slice(None))] - energy.loc[country, avia_inter] *= avi_i[['total']].iloc[0,0] - energy.loc[country, avia_domestic] *= avi_d[['total']].iloc[0,0] + energy.loc[country, mapping["total"]] *= sector_ratio[["total"]].iloc[0, 0] + energy.loc[country, mapping["elec"]] *= sector_ratio[["ele"]].iloc[0, 0] + + avi_d = ratio.loc[(country, slice(None), "Domestic aviation")] + avi_i = ratio.loc[(country, "International aviation", slice(None))] + energy.loc[country, avia_inter] *= avi_i[["total"]].iloc[0, 0] + energy.loc[country, avia_domestic] *= avi_d[["total"]].iloc[0, 0] nav = ratio.loc[(country, slice(None), "Domestic Navigation")] energy.loc[country, navigation] *= nav[["total"]].iloc[0, 0] @@ -898,9 +945,7 @@ if __name__ == "__main__": base_year_emissions = params["base_emissions_year"] emissions_scope = snakemake.params.energy["emissions"] eea_co2 = build_eea_co2(snakemake.input.co2, base_year_emissions, emissions_scope) - eurostat_co2 = build_eurostat_co2( - input_eurostat, countries, base_year_emissions - ) + eurostat_co2 = build_eurostat_co2(input_eurostat, countries, base_year_emissions) co2 = build_co2_totals(countries, eea_co2, eurostat_co2) co2.to_csv(snakemake.output.co2_name) diff --git a/scripts/retrieve_sector_databundle.py b/scripts/retrieve_sector_databundle.py index a075119e..2c9fea92 100644 --- a/scripts/retrieve_sector_databundle.py +++ b/scripts/retrieve_sector_databundle.py @@ -51,13 +51,15 @@ if __name__ == "__main__": url_eurostat = "https://ec.europa.eu/eurostat/documents/38154/4956218/Balances-December2022.zip/f7cf0d19-5c0f-60ad-4e48-098a5ddd6e48?t=1671184070589" tarball_fn = Path(f"{rootpath}/data/bundle-sector/eurostat_2023.zip") - to_fn = Path(f"{rootpath}/data/bundle-sector/eurostat-energy_balances-april_2023_edition/") + to_fn = Path( + f"{rootpath}/data/bundle-sector/eurostat-energy_balances-april_2023_edition/" + ) logger.info(f"Downloading Eurostat data from '{url_eurostat}'.") progress_retrieve(url_eurostat, tarball_fn, disable=disable_progress) logger.info("Extracting Eurostat data.") - with zipfile.ZipFile(tarball_fn, 'r') as zip_ref: + with zipfile.ZipFile(tarball_fn, "r") as zip_ref: zip_ref.extractall(to_fn) - logger.info(f"Eurostat data available in '{to_fn}'.") \ No newline at end of file + logger.info(f"Eurostat data available in '{to_fn}'.") From 5bcecc62c6abcfa78df6c2833bb22b0e40aab88a Mon Sep 17 00:00:00 2001 From: toniseibold Date: Tue, 27 Feb 2024 13:32:07 +0100 Subject: [PATCH 376/591] retrieve eurostat data is now outside of retrieve_sector_databundle --- rules/retrieve.smk | 13 ++++++-- scripts/retrieve_eurostat_data.py | 45 +++++++++++++++++++++++++++ scripts/retrieve_sector_databundle.py | 16 +--------- 3 files changed, 56 insertions(+), 18 deletions(-) create mode 100644 scripts/retrieve_eurostat_data.py diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 8ef373d1..9250e745 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -142,9 +142,6 @@ if config["enable"]["retrieve"] and config["enable"].get( protected( directory("data/bundle-sector/eurostat-energy_balances-may_2018_edition") ), - protected( - directory("data/bundle-sector/eurostat-energy_balances-april_2023_edition") - ), protected(directory("data/bundle-sector/jrc-idees-2015")), ] @@ -160,6 +157,16 @@ if config["enable"]["retrieve"] and config["enable"].get( script: "../scripts/retrieve_sector_databundle.py" + rule retrieve_eurostat_data: + output: + protected( + directory("data/bundle-sector/eurostat-energy_balances-april_2023_edition") + ), + log: + "logs/retrieve_eurostat_data.log", + retries: 2 + script: + "../scripts/retrieve_eurostat_data.py" if config["enable"]["retrieve"]: datafiles = [ diff --git a/scripts/retrieve_eurostat_data.py b/scripts/retrieve_eurostat_data.py new file mode 100644 index 00000000..aedc43c9 --- /dev/null +++ b/scripts/retrieve_eurostat_data.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2024- The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT +""" +Retrieve and extract eurostat energy balances data. +""" + + +import logging +import zipfile +from pathlib import Path + +from _helpers import ( + configure_logging, + progress_retrieve, + set_scenario_config, +) + +logger = logging.getLogger(__name__) + +if __name__ == "__main__": + if "snakemake" not in globals(): + from _helpers import mock_snakemake + + snakemake = mock_snakemake("retrieve_eurostat_data") + rootpath = ".." + else: + rootpath = "." + configure_logging(snakemake) + set_scenario_config(snakemake) + + disable_progress = snakemake.config["run"].get("disable_progressbar", False) + url_eurostat = "https://ec.europa.eu/eurostat/documents/38154/4956218/Balances-December2022.zip/f7cf0d19-5c0f-60ad-4e48-098a5ddd6e48?t=1671184070589" + tarball_fn = Path(f"{rootpath}/data/bundle-sector/eurostat_2023.zip") + to_fn = Path(f"{rootpath}/data/bundle-sector/eurostat-energy_balances-april_2023_edition/") + + logger.info(f"Downloading Eurostat data from '{url_eurostat}'.") + progress_retrieve(url_eurostat, tarball_fn, disable=disable_progress) + + logger.info("Extracting Eurostat data.") + with zipfile.ZipFile(tarball_fn, 'r') as zip_ref: + zip_ref.extractall(to_fn) + + logger.info(f"Eurostat data available in '{to_fn}'.") \ No newline at end of file diff --git a/scripts/retrieve_sector_databundle.py b/scripts/retrieve_sector_databundle.py index a075119e..d311dac7 100644 --- a/scripts/retrieve_sector_databundle.py +++ b/scripts/retrieve_sector_databundle.py @@ -8,7 +8,6 @@ Retrieve and extract data bundle for sector-coupled studies. import logging import tarfile -import zipfile from pathlib import Path from _helpers import ( @@ -47,17 +46,4 @@ if __name__ == "__main__": tarball_fn.unlink() - logger.info(f"Databundle available in '{to_fn}'.") - - url_eurostat = "https://ec.europa.eu/eurostat/documents/38154/4956218/Balances-December2022.zip/f7cf0d19-5c0f-60ad-4e48-098a5ddd6e48?t=1671184070589" - tarball_fn = Path(f"{rootpath}/data/bundle-sector/eurostat_2023.zip") - to_fn = Path(f"{rootpath}/data/bundle-sector/eurostat-energy_balances-april_2023_edition/") - - logger.info(f"Downloading Eurostat data from '{url_eurostat}'.") - progress_retrieve(url_eurostat, tarball_fn, disable=disable_progress) - - logger.info("Extracting Eurostat data.") - with zipfile.ZipFile(tarball_fn, 'r') as zip_ref: - zip_ref.extractall(to_fn) - - logger.info(f"Eurostat data available in '{to_fn}'.") \ No newline at end of file + logger.info(f"Databundle available in '{to_fn}'.") \ No newline at end of file From 8dfab454537fa3892cce1a939625e671aca3091e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 12:35:55 +0000 Subject: [PATCH 377/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/retrieve.smk | 7 +++++-- scripts/retrieve_eurostat_data.py | 14 ++++++-------- scripts/retrieve_sector_databundle.py | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 9250e745..cfe698fc 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -160,14 +160,17 @@ if config["enable"]["retrieve"] and config["enable"].get( rule retrieve_eurostat_data: output: protected( - directory("data/bundle-sector/eurostat-energy_balances-april_2023_edition") - ), + directory( + "data/bundle-sector/eurostat-energy_balances-april_2023_edition" + ) + ), log: "logs/retrieve_eurostat_data.log", retries: 2 script: "../scripts/retrieve_eurostat_data.py" + if config["enable"]["retrieve"]: datafiles = [ "IGGIELGN_LNGs.geojson", diff --git a/scripts/retrieve_eurostat_data.py b/scripts/retrieve_eurostat_data.py index aedc43c9..daee4fc4 100644 --- a/scripts/retrieve_eurostat_data.py +++ b/scripts/retrieve_eurostat_data.py @@ -11,11 +11,7 @@ import logging import zipfile from pathlib import Path -from _helpers import ( - configure_logging, - progress_retrieve, - set_scenario_config, -) +from _helpers import configure_logging, progress_retrieve, set_scenario_config logger = logging.getLogger(__name__) @@ -33,13 +29,15 @@ if __name__ == "__main__": disable_progress = snakemake.config["run"].get("disable_progressbar", False) url_eurostat = "https://ec.europa.eu/eurostat/documents/38154/4956218/Balances-December2022.zip/f7cf0d19-5c0f-60ad-4e48-098a5ddd6e48?t=1671184070589" tarball_fn = Path(f"{rootpath}/data/bundle-sector/eurostat_2023.zip") - to_fn = Path(f"{rootpath}/data/bundle-sector/eurostat-energy_balances-april_2023_edition/") + to_fn = Path( + f"{rootpath}/data/bundle-sector/eurostat-energy_balances-april_2023_edition/" + ) logger.info(f"Downloading Eurostat data from '{url_eurostat}'.") progress_retrieve(url_eurostat, tarball_fn, disable=disable_progress) logger.info("Extracting Eurostat data.") - with zipfile.ZipFile(tarball_fn, 'r') as zip_ref: + with zipfile.ZipFile(tarball_fn, "r") as zip_ref: zip_ref.extractall(to_fn) - logger.info(f"Eurostat data available in '{to_fn}'.") \ No newline at end of file + logger.info(f"Eurostat data available in '{to_fn}'.") diff --git a/scripts/retrieve_sector_databundle.py b/scripts/retrieve_sector_databundle.py index d311dac7..3b825da2 100644 --- a/scripts/retrieve_sector_databundle.py +++ b/scripts/retrieve_sector_databundle.py @@ -46,4 +46,4 @@ if __name__ == "__main__": tarball_fn.unlink() - logger.info(f"Databundle available in '{to_fn}'.") \ No newline at end of file + logger.info(f"Databundle available in '{to_fn}'.") From bd0880c02255e6214ba94a4b2ba2b8da7519c75e Mon Sep 17 00:00:00 2001 From: toniseibold Date: Tue, 27 Feb 2024 14:32:09 +0100 Subject: [PATCH 378/591] correcting misleading comment --- scripts/build_energy_totals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index d6c63f00..c114b707 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -922,7 +922,7 @@ if __name__ == "__main__": input_eurostat = snakemake.input.eurostat eurostat = build_eurostat(input_eurostat, countries, data_year) swiss = build_swiss(data_year) - # data from idees only exists for 2015 + # data from idees only exists from 2000-2015 if data_year > 2015: # read in latest data and rescale later idees = build_idees(idees_countries, 2015) From f08c6fe77239ee0c60f25cca41179cbbb2c09d97 Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:13:36 +0100 Subject: [PATCH 379/591] change technology data version to 0.8.1 --- 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 ca2d1ba3..ad4144d5 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -668,7 +668,7 @@ industry: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#costs costs: year: 2030 - version: v0.8.0 + version: v0.8.1 rooftop_share: 0.14 # based on the potentials, assuming (0.1 kW/m2 and 10 m2/person) social_discountrate: 0.02 fill_values: From e933acd9e866e55c607eb480d8e4fa5b7d59b6d4 Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:15:43 +0100 Subject: [PATCH 380/591] update release_notes.rst --- doc/release_notes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d6072d7d..8167f6dd 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,6 +9,7 @@ Release Notes Upcoming Release ================ +* Upgrade default techno-economic assumptions to ``technology-data`` v0.8.1. * Linearly interpolate missing investment periods in year-dependent configuration options. From 90fb0b13da3437cd3578eb8dae0b1ee9f64cbdc5 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 29 Feb 2024 11:38:21 +0100 Subject: [PATCH 381/591] Various bugfixes to make multiyear branch run --- rules/build_electricity.smk | 24 ++++++++++++------- rules/build_sector.smk | 13 ++++++---- rules/postprocess.smk | 8 +++---- rules/retrieve.smk | 3 --- scripts/base_network.py | 2 +- scripts/build_energy_totals.py | 10 ++++---- scripts/build_heat_totals.py | 8 +++++++ scripts/build_hydro_profile.py | 2 ++ ...build_population_weighted_energy_totals.py | 2 +- scripts/build_renewable_profiles.py | 10 +++++++- scripts/build_shipping_demand.py | 3 ++- 11 files changed, 55 insertions(+), 30 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 0c949193..99e671fd 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -202,12 +202,26 @@ if config["enable"].get("build_cutout", False): "../scripts/build_cutout.py" +# TODO: consider if it's fine to just use the default cutout instead, i.e.: +# cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", +def cutouts_for_extent_input(wildcards): + # We only need these cutouts in order to determine geographic + # boundaries, so just pick the first weather year available + weather_year = config["scenario"]["weather_year"][0] + cutouts = [] + for k in config["electricity"]["renewable_carriers"]: + cutout = config["renewable"][k]["cutout"] + cutout = cutout.replace("{weather_year}", weather_year) + cutouts.append(f"cutouts/{CDIR}{cutout}.nc") + return cutouts + + if config["enable"].get("build_natura_raster", False): rule build_natura_raster: input: natura=ancient("data/bundle/natura/Natura2000_end2015.shp"), - cutouts=expand("cutouts/" + CDIR + "{cutouts}.nc", **config["atlite"]), + cutouts=cutouts_for_extent_input, output: RESOURCES + "natura.tiff", resources: @@ -223,13 +237,7 @@ if config["enable"].get("build_natura_raster", False): rule build_ship_raster: input: ship_density="data/shipdensity_global.zip", - cutouts=expand( - "cutouts/" + CDIR + "{cutout}.nc", - cutout=[ - config["renewable"][k]["cutout"] - for k in config["electricity"]["renewable_carriers"] - ], - ), + cutouts=cutouts_for_extent_input, output: RESOURCES + "shipdensity_raster.tif", log: diff --git a/rules/build_sector.smk b/rules/build_sector.smk index c68e5a5a..ec5b09f9 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -150,7 +150,7 @@ rule build_heat_demands: params: snapshots=config["snapshots"], input: - pop_layout=RESOURCES + "pop_layout{weather_year}_{scope}.nc", + pop_layout=RESOURCES + "pop_layout_{scope}{weather_year}.nc", regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", @@ -174,7 +174,7 @@ rule build_temperature_profiles: params: snapshots=config["snapshots"], input: - pop_layout=RESOURCES + "pop_layout{weather_year}_{scope}.nc", + pop_layout=RESOURCES + "pop_layout_{scope}{weather_year}.nc", regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", @@ -246,7 +246,7 @@ rule build_solar_thermal_profiles: snapshots=config["snapshots"], solar_thermal=config["solar_thermal"], input: - pop_layout=RESOURCES + "pop_layout{weather_year}_{scope}.nc", + pop_layout=RESOURCES + "pop_layout_{scope}{weather_year}.nc", regions_onshore=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", @@ -684,7 +684,8 @@ if config["sector"]["retrofitting"]["retro_endogen"]: input: building_stock="data/retro/data_building_stock.csv", data_tabula="data/bundle-sector/retro/tabula-calculator-calcsetbuilding.csv", - air_temperature=RESOURCES + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", + air_temperature=RESOURCES + + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc", u_values_PL="data/retro/u_values_poland.csv", tax_w="data/retro/electricity_taxes_eu.csv", construction_index="data/retro/comparative_level_investment.csv", @@ -719,7 +720,7 @@ if not config["sector"]["retrofitting"]["retro_endogen"]: rule build_population_weighted_energy_totals: input: - energy_totals=RESOURCES + "{kind}}_totals.csv", + energy_totals=RESOURCES + "{kind}_totals.csv", clustered_pop_layout=RESOURCES + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv", output: @@ -743,6 +744,8 @@ rule build_shipping_demand: regions=RESOURCES + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson", demand=RESOURCES + "energy_totals.csv", + params: + energy_totals_year=config["energy"]["energy_totals_year"], output: RESOURCES + "shipping_demand{weather_year}_s{simpl}_{clusters}.csv", threads: 1 diff --git a/rules/postprocess.smk b/rules/postprocess.smk index ec6c21f7..aaecbca1 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -28,7 +28,7 @@ if config["foresight"] != "perfect": benchmark: ( BENCHMARKS - + "plot_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "plot_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -181,14 +181,14 @@ rule plot_elec_statistics: plotting=config["plotting"], barplots=STATISTICS_BARPLOTS, input: - network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=RESULTS + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", output: **{ f"{plot}_bar": RESULTS - + f"figures/statistics_{plot}_bar_elec_s{{simpl}}_{{clusters}}_ec_l{{ll}}_{{opts}}.pdf" + + f"figures/statistics_{plot}_bar_elec{{weather_year}}_s{{simpl}}_{{clusters}}_ec_l{{ll}}_{{opts}}.pdf" for plot in STATISTICS_BARPLOTS }, barplots_touch=RESULTS - + "figures/.statistics_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", + + "figures/.statistics_plots_elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}", script: "../scripts/plot_statistics.py" diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 63ba2e23..36c2ab91 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -144,9 +144,6 @@ if config["enable"]["retrieve"] and config["enable"].get( protected( directory("data/bundle-sector/eurostat-energy_balances-june_2016_edition") ), - protected( - directory("data/bundle-sector/eurostat-energy_balances-june_2021_edition") - ), protected( directory("data/bundle-sector/eurostat-energy_balances-may_2018_edition") ), diff --git a/scripts/base_network.py b/scripts/base_network.py index 663a0a15..98a7b7f4 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -558,7 +558,7 @@ def _set_countries_and_substations(n, config, country_shapes, offshore_shapes): ~buses["under_construction"] ) - c_nan_b = buses.country == "na" + c_nan_b = buses.country.fillna("na") == "na" if c_nan_b.sum() > 0: c_tag = _get_country(buses.loc[c_nan_b]) c_tag.loc[~c_tag.isin(countries)] = np.nan diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 1da5fa21..158e0d01 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -356,7 +356,7 @@ def build_idees(countries, year=None): func = partial(idees_per_country, year=year, base_dir=snakemake.input.idees) tqdm_kwargs = dict( ascii=False, - unit="" country", + unit=" country", total=len(countries), desc="Build from IDEES database", disable=disable_progress @@ -382,9 +382,6 @@ def build_idees(countries, year=None): total_heat = df[subset].sum(axis=1) df["district heat share"] = district_heat.div(total_heat) - if year: - df = df.xs(int(year), level='year') - df.columns.name = 'item' return df @@ -741,12 +738,13 @@ if __name__ == "__main__": countries = snakemake.params.countries idees_countries = pd.Index(countries).intersection(eu28) + countries_without_ch = pd.Index(countries).difference(["CH"]) data_year = params["energy_totals_year"] report_year = snakemake.params.energy["eurostat_report_year"] input_eurostat = snakemake.input.eurostat - eurostat = build_eurostat(input_eurostat, countries, report_year, data_year) - swiss = build_swiss(data_year) + eurostat = build_eurostat(countries_without_ch) + swiss = build_swiss() idees = build_idees(idees_countries, data_year) energy = build_energy_totals(countries, eurostat, swiss, idees) diff --git a/scripts/build_heat_totals.py b/scripts/build_heat_totals.py index 80f0fb30..93e8f9c7 100644 --- a/scripts/build_heat_totals.py +++ b/scripts/build_heat_totals.py @@ -29,6 +29,14 @@ def approximate_heat_demand(energy_totals, hdd): Y = demand[c].dropna() X = hdd.loc[Y.index, c] + # Sometimes (looking at you, Switzerland) we only have + # _one_ year of heating data to base the prediction on. In + # this case we add a point at 0, 0 to make a "polynomial" + # fit work. + if len(X) == len(Y) == 1: + X.loc[-1] = 0 + Y.loc[-1] = 0 + to_predict = hdd.index.difference(Y.index) X_pred = hdd.loc[to_predict, c] diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 055523c8..baa05ab9 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -184,6 +184,8 @@ if __name__ == "__main__": fn = snakemake.input.eia_hydro_generation eia_stats = get_eia_annual_hydro_generation(fn, countries) + config_hydro = snakemake.config["renewable"]["hydro"] + if config_hydro.get("eia_correct_by_capacity"): fn = snakemake.input.eia_hydro_capacity correct_eia_stats_by_capacity(eia_stats, fn, countries) diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index bc5f2d19..fd232c89 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -26,7 +26,7 @@ if __name__ == "__main__": pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) - totals = pd.read_csv(snakemake.input.totals, index_col=[0, 1]) + totals = pd.read_csv(snakemake.input.energy_totals, index_col=[0, 1]) totals = totals.xs(data_year, level="year") nodal_totals = totals.loc[pop_layout.ct].fillna(0.0) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 829c5347..48ba64a2 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -216,7 +216,15 @@ if __name__ == "__main__": else: client = None - sns = pd.date_range(freq="h", **snakemake.config["snapshots"]) + weather_year = snakemake.wildcards.weather_year + if weather_year: + snapshots = dict( + start=weather_year, end=str(int(weather_year) + 1), inclusive="left" + ) + else: + snapshots = snakemake.config["snapshots"] + sns = pd.date_range(freq="h", **snapshots) + cutout = atlite.Cutout(snakemake.input.cutout).sel(time=sns) regions = gpd.read_file(snakemake.input.regions) assert not regions.empty, ( diff --git a/scripts/build_shipping_demand.py b/scripts/build_shipping_demand.py index 8000c66c..f95f441a 100644 --- a/scripts/build_shipping_demand.py +++ b/scripts/build_shipping_demand.py @@ -24,9 +24,10 @@ if __name__ == "__main__": scope = gpd.read_file(snakemake.input.scope).geometry[0] regions = gpd.read_file(snakemake.input.regions).set_index("name") - demand = pd.read_csv(snakemake.input.demand, index_col=0)[ + demand = pd.read_csv(snakemake.input.demand, index_col=[0, 1])[ "total international navigation" ] + demand = demand.xs(snakemake.params.energy_totals_year, level=1) # read port data into GeoDataFrame with open(snakemake.input.ports, "r", encoding="latin_1") as f: From f6f98c102c134bccce33dca004a203fa2534dcc5 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 11:45:39 +0100 Subject: [PATCH 382/591] Use default cutout for ship and nature raster extents This avoids the need to either collect all cutouts for all weather years or arbitrarily pick all cutouts for a certain weather year. --- rules/build_electricity.smk | 24 ++++++++---------------- scripts/build_natura_raster.py | 5 ++--- scripts/build_ship_raster.py | 5 ++--- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 78904573..bcc69e2d 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -205,26 +205,15 @@ if config["enable"].get("build_cutout", False): "../scripts/build_cutout.py" -# TODO: consider if it's fine to just use the default cutout instead, i.e.: -# cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc", -def cutouts_for_extent_input(wildcards): - # We only need these cutouts in order to determine geographic - # boundaries, so just pick the first weather year available - weather_year = config_provider("scenario", "weather_year")(wildcards)[0] - cutouts = [] - for k in config_provider("electricity", "renewable_carriers")(wildcards): - cutout = config_provider("renewable", k, "cutout")(wildcards) - cutout = cutout.replace("{weather_year}", weather_year) - cutouts.append(f"cutouts/{CDIR}{cutout}.nc") - return cutouts - - if config["enable"].get("build_natura_raster", False): rule build_natura_raster: input: natura=ancient("data/bundle/natura/Natura2000_end2015.shp"), - cutouts=cutouts_for_extent_input, + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: resources("natura.tiff"), resources: @@ -240,7 +229,10 @@ if config["enable"].get("build_natura_raster", False): rule build_ship_raster: input: ship_density="data/shipdensity_global.zip", - cutouts=cutouts_for_extent_input, + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: resources("shipdensity_raster.tif"), log: diff --git a/scripts/build_natura_raster.py b/scripts/build_natura_raster.py index 2e2fcbbf..35fb0dbd 100644 --- a/scripts/build_natura_raster.py +++ b/scripts/build_natura_raster.py @@ -94,9 +94,8 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - cutouts = snakemake.input.cutouts - xs, Xs, ys, Ys = zip(*(determine_cutout_xXyY(cutout) for cutout in cutouts)) - bounds = transform_bounds(4326, 3035, min(xs), min(ys), max(Xs), max(Ys)) + x, X, y, Y = determine_cutout_xXyY(snakemake.input.cutout) + bounds = transform_bounds(4326, 3035, x, y, X, Y) transform, out_shape = get_transform_and_shape(bounds, res=100) # adjusted boundaries diff --git a/scripts/build_ship_raster.py b/scripts/build_ship_raster.py index c8285180..47d725d8 100644 --- a/scripts/build_ship_raster.py +++ b/scripts/build_ship_raster.py @@ -59,8 +59,7 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - cutouts = snakemake.input.cutouts - xs, Xs, ys, Ys = zip(*(determine_cutout_xXyY(cutout) for cutout in cutouts)) + x, X, y, Y = determine_cutout_xXyY(snakemake.input.cutout) with zipfile.ZipFile(snakemake.input.ship_density) as zip_f: resources = Path(snakemake.output[0]).parent @@ -68,7 +67,7 @@ if __name__ == "__main__": zip_f.extract(fn, resources) with rioxarray.open_rasterio(resources / fn) as ship_density: ship_density = ship_density.drop_vars(["band"]).sel( - x=slice(min(xs), max(Xs)), y=slice(max(Ys), min(ys)) + x=slice(x, X), y=slice(Y, y) ) ship_density.rio.to_raster(snakemake.output[0]) From 0debf66169fbc85b3c642fdbca33b19a9e85eee0 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 11:50:35 +0100 Subject: [PATCH 383/591] Fix summary plot output --- rules/postprocess.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index ab08912d..8b968681 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -175,7 +175,7 @@ rule make_summary: ) ), ac_plot=expand( - resources("maps/power-network-s{simpl}-{clusters}.pdf"), + resources("maps/power-network{weather_year}-s{simpl}-{clusters}.pdf"), **config["scenario"], allow_missing=True, ), From 3c31caf9937bcd8f9fb43078bdc8ab70702febf0 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 11:59:04 +0100 Subject: [PATCH 384/591] Fix typos in rule inputs --- rules/build_sector.smk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 8e6587dd..f9edad14 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -54,9 +54,9 @@ rule build_clustered_population_layouts: rule build_simplified_population_layouts: input: - pop_layout_total=resources("pop_layout_total{weather_year}"), - pop_layout_urban=resources("pop_layout_urban{weather_year}"), - pop_layout_rural=resources("pop_layout_rural{weather_year}"), + pop_layout_total=resources("pop_layout_total{weather_year}.nc"), + pop_layout_urban=resources("pop_layout_urban{weather_year}.nc"), + pop_layout_rural=resources("pop_layout_rural{weather_year}.nc"), regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}.geojson"), cutout=lambda w: "cutouts/" + CDIR @@ -398,8 +398,8 @@ rule build_sequestration_potentials: rule build_salt_cavern_potentials: input: salt_caverns="data/bundle-sector/h2_salt_caverns_GWh_per_sqkm.geojson", - regions_onshore=resources("regions_onshore{weather_year}_elec_s{simpl}_{clusters}.geojson"), - regions_offshore=resources("regions_offshore{weather_year}_elec_s{simpl}_{clusters}.geojson"), + regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), output: h2_cavern_potential=resources("salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv"), threads: 1 From c2e7c125c7ae25a8213f5a6af8ad7cde7af043f2 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 13:24:02 +0100 Subject: [PATCH 385/591] Automatic formatting of snakemake rules --- rules/build_electricity.smk | 43 +++-- rules/build_sector.smk | 310 ++++++++++++++++++++++++++---------- rules/collect.smk | 7 +- rules/postprocess.smk | 25 ++- rules/retrieve.smk | 28 +++- rules/solve_electricity.smk | 9 +- rules/solve_myopic.smk | 20 ++- 7 files changed, 325 insertions(+), 117 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index bcc69e2d..3f353dd9 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -19,6 +19,7 @@ if config["enable"].get("prepare_links_p_nom", False): if config["enable"].get("retrieve_opsd_load_data", True): + rule build_electricity_demand: params: snapshots=config_provider("snapshots"), @@ -37,7 +38,7 @@ if config["enable"].get("retrieve_opsd_load_data", True): script: "../scripts/build_electricity_demand.py" - + if config["enable"].get("retrieve_artificial_load_data", False): rule build_artificial_load_data: @@ -390,7 +391,7 @@ rule build_hydro_profile: + ".nc", output: profile=resources("profile{weather_year}_hydro.nc"), - eia_hydro=resources("eia_hydro_stats{weather_year}.csv") + eia_hydro=resources("eia_hydro_stats{weather_year}.csv"), log: logs("build_hydro_profile{weather_year}.log"), resources: @@ -427,7 +428,7 @@ rule build_line_rating: def input_profile_tech(w): return { - f"profile_{tech}": resources(f"profile{{weather_year}}_{tech}.nc") + f"profile_{tech}": resources(f"profile{weather_year}_{tech}.nc") for tech in config_provider("electricity", "renewable_carriers")(w) } @@ -462,7 +463,7 @@ rule add_electricity: else resources("networks/base.nc") ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs' , 'year') (w)}.csv" ), regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), @@ -507,14 +508,16 @@ rule simplify_network: input: network=resources("networks/elec{weather_year}.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs' , 'year') (w)}.csv" ), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), output: network=resources("networks/elec{weather_year}_s{simpl}.nc"), regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}.geojson"), - regions_offshore=resources("regions_offshore_elec{weather_year}_s{simpl}.geojson"), + regions_offshore=resources( + "regions_offshore_elec{weather_year}_s{simpl}.geojson" + ), busmap=resources("busmap_elec{weather_year}_s{simpl}.csv"), connection_costs=resources("connection_costs{weather_year}_s{simpl}.csv"), log: @@ -548,7 +551,9 @@ rule cluster_network: input: network=resources("networks/elec{weather_year}_s{simpl}.nc"), regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}.geojson"), - regions_offshore=resources("regions_offshore_elec{weather_year}_s{simpl}.geojson"), + regions_offshore=resources( + "regions_offshore_elec{weather_year}_s{simpl}.geojson" + ), busmap=ancient(resources("busmap_elec{weather_year}_s{simpl}.csv")), custom_busmap=lambda w: ( "data/custom_busmap_elec_s{simpl}_{clusters}.csv" @@ -556,12 +561,16 @@ rule cluster_network: else [] ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs' , 'year') (w)}.csv" ), output: network=resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), - regions_offshore=resources("regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), + regions_offshore=resources( + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), busmap=resources("busmap_elec{weather_year}_s{simpl}_{clusters}.csv"), linemap=resources("linemap_elec{weather_year}_s{simpl}_{clusters}.csv"), log: @@ -585,7 +594,7 @@ rule add_extra_components: input: network=resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs' , 'year') (w)}.csv" ), output: resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc"), @@ -619,15 +628,21 @@ rule prepare_network: input: resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs' , 'year') (w)}.csv" ), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), log: - logs("prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.log"), + logs( + "prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" + ), benchmark: - (benchmarks("prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}")) + ( + benchmarks( + "prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + ) + ) threads: 1 resources: mem_mb=4000, diff --git a/rules/build_sector.smk b/rules/build_sector.smk index f9edad14..9fb6876b 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -33,19 +33,25 @@ rule build_clustered_population_layouts: pop_layout_total=resources("pop_layout_total{weather_year}.nc"), pop_layout_urban=resources("pop_layout_urban{weather_year}.nc"), pop_layout_rural=resources("pop_layout_rural{weather_year}.nc"), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), cutout=lambda w: "cutouts/" + CDIR + config_provider("atlite", "default_cutout")(w) + ".nc", output: - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources( + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + ), log: logs("build_clustered_population_layouts{weather_year}_{simpl}_{clusters}.log"), resources: mem_mb=10000, benchmark: - benchmarks("build_clustered_population_layouts/{weather_year}s{simpl}_{clusters}") + benchmarks( + "build_clustered_population_layouts/{weather_year}s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -99,10 +105,16 @@ rule build_gas_input_locations: ), entry="data/gas_network/scigrid-gas/data/IGGIELGN_BorderPoints.geojson", storage="data/gas_network/scigrid-gas/data/IGGIELGN_Storages.geojson", - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), - regions_offshore=resources("regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), + regions_offshore=resources( + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), output: - gas_input_nodes=resources("gas_input_locations{weather_year}_s{simpl}_{clusters}.geojson"), + gas_input_nodes=resources( + "gas_input_locations{weather_year}_s{simpl}_{clusters}.geojson" + ), gas_input_nodes_simplified=resources( "gas_input_locations{weather_year}_s{simpl}_{clusters}_simplified.csv" ), @@ -119,10 +131,16 @@ rule build_gas_input_locations: rule cluster_gas_network: input: cleaned_gas_network=resources("gas_network.csv"), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), - regions_offshore=resources("regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), + regions_offshore=resources( + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), output: - clustered_gas_network=resources("gas_network_elec{weather_year}_s{simpl}_{clusters}.csv"), + clustered_gas_network=resources( + "gas_network_elec{weather_year}_s{simpl}_{clusters}.csv" + ), resources: mem_mb=4000, log: @@ -139,13 +157,19 @@ rule build_daily_heat_demand: drop_leap_day=config_provider("enable", "drop_leap_day"), input: pop_layout=resources("pop_layout_{scope}{weather_year}.nc"), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), - cutout=lambda w: "cutouts/" - + CDIR - + config_provider("atlite", "default_cutout")(w) - + ".nc", + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), + cutout=( + lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", + ), output: - heat_demand=resources("daily_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc"), + heat_demand=resources( + "daily_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + ), resources: mem_mb=20000, threads: 8 @@ -164,9 +188,13 @@ rule build_hourly_heat_demand: snapshots=config_provider("snapshots"), input: heat_profile="data/heat_load_profile_BDEW.csv", - heat_demand=resources("daily_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc"), + heat_demand=resources( + "daily_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + ), output: - heat_demand=resources("hourly_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc"), + heat_demand=resources( + "hourly_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + ), resources: mem_mb=2000, threads: 8 @@ -186,13 +214,17 @@ rule build_temperature_profiles: drop_leap_day=config_provider("enable", "drop_leap_day"), input: pop_layout=resources("pop_layout_{scope}{weather_year}.nc"), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), cutout=lambda w: "cutouts/" + CDIR + config_provider("atlite", "default_cutout")(w) + ".nc", output: - temp_soil=resources("temp_soil_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc"), + temp_soil=resources( + "temp_soil_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + ), temp_air=resources("temp_air_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, @@ -200,7 +232,9 @@ rule build_temperature_profiles: log: logs("build_temperature_profiles_{scope}_{weather_year}_{simpl}_{clusters}.log"), benchmark: - benchmarks("build_temperature_profiles/{scope}_{weather_year}_s{simpl}_{clusters}") + benchmarks( + "build_temperature_profiles/{scope}_{weather_year}_s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -211,19 +245,43 @@ rule build_cop_profiles: params: heat_pump_sink_T=config_provider("sector", "heat_pump_sink_T"), input: - temp_soil_total=resources("temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_soil_rural=resources("temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_soil_urban=resources("temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_air_total=resources("temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_air_rural=resources("temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_air_urban=resources("temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc"), + temp_soil_total=resources( + "temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_soil_rural=resources( + "temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_soil_urban=resources( + "temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_air_total=resources( + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_air_rural=resources( + "temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_air_urban=resources( + "temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + ), output: - cop_soil_total=resources("cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_soil_rural=resources("cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_soil_urban=resources("cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_air_total=resources("cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_air_rural=resources("cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_air_urban=resources("cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc"), + cop_soil_total=resources( + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_soil_rural=resources( + "cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_soil_urban=resources( + "cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_air_total=resources( + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_air_rural=resources( + "cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_air_urban=resources( + "cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + ), resources: mem_mb=20000, log: @@ -243,20 +301,28 @@ rule build_solar_thermal_profiles: solar_thermal=config_provider("solar_thermal"), input: pop_layout=resources("pop_layout_{scope}{weather_year}.nc"), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), cutout=lambda w: "cutouts/" + CDIR + config_provider("atlite", "default_cutout")(w) + ".nc", output: - solar_thermal=resources("solar_thermal_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc"), + solar_thermal=resources( + "solar_thermal_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + ), resources: mem_mb=20000, threads: 16 log: - logs("build_solar_thermal_profiles_{scope}_{weather_year}_s{simpl}_{clusters}.log"), + logs( + "build_solar_thermal_profiles_{scope}_{weather_year}_s{simpl}_{clusters}.log" + ), benchmark: - benchmarks("build_solar_thermal_profiles/{scope}_{weather_year}_s{simpl}_{clusters}") + benchmarks( + "build_solar_thermal_profiles/{scope}_{weather_year}_s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -304,7 +370,7 @@ rule build_heat_totals: log: logs("build_heat_totals.log"), benchmark: - benchmarks("build_heat_totals"), + benchmarks("build_heat_totals") conda: "../envs/environment.yaml" script: @@ -320,7 +386,9 @@ rule build_biomass_potentials: keep_local=True, ), nuts2="data/bundle-sector/nuts/NUTS_RG_10M_2013_4326_LEVL_2.geojson", # https://gisco-services.ec.europa.eu/distribution/v2/nuts/download/#nuts21 - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), nuts3_population=ancient("data/bundle/nama_10r_3popgdp.tsv.gz"), swiss_cantons=ancient("data/bundle/ch_cantons.csv"), swiss_population=ancient("data/bundle/je-e-21.03.02.xls"), @@ -336,9 +404,13 @@ rule build_biomass_potentials: resources: mem_mb=1000, log: - logs("build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log"), + logs( + "build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log" + ), benchmark: - benchmarks("build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}") + benchmarks( + "build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}" + ) conda: "../envs/environment.yaml" script: @@ -376,8 +448,12 @@ rule build_sequestration_potentials: "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", keep_local=True, ), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), - regions_offshore=resources("regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), + regions_offshore=resources( + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), output: sequestration_potential=resources( "co2_sequestration_potential_elec{weather_year}_s{simpl}_{clusters}.csv" @@ -398,10 +474,16 @@ rule build_sequestration_potentials: rule build_salt_cavern_potentials: input: salt_caverns="data/bundle-sector/h2_salt_caverns_GWh_per_sqkm.geojson", - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), - regions_offshore=resources("regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), + regions_offshore=resources( + "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), output: - h2_cavern_potential=resources("salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv"), + h2_cavern_potential=resources( + "salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv" + ), threads: 1 resources: mem_mb=2000, @@ -543,8 +625,12 @@ rule build_industrial_distribution_key: ), countries=config_provider("countries"), input: - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv"), + regions_onshore=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), + clustered_pop_layout=resources( + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + ), hotmaps_industrial_database="data/bundle-sector/Industrial_Database.csv", output: industrial_distribution_key=resources( @@ -556,7 +642,9 @@ rule build_industrial_distribution_key: log: logs("build_industrial_distribution_key{weather_year}_s{simpl}_{clusters}.log"), benchmark: - benchmarks("build_industrial_distribution_key/{weather_year}s{simpl}_{clusters}") + benchmarks( + "build_industrial_distribution_key/{weather_year}s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -670,9 +758,13 @@ rule build_industrial_energy_demand_per_node_today: resources: mem_mb=1000, log: - logs("build_industrial_energy_demand_per_node_today{weather_year}_s{simpl}_{clusters}.log"), + logs( + "build_industrial_energy_demand_per_node_today{weather_year}_s{simpl}_{clusters}.log" + ), benchmark: - benchmarks("build_industrial_energy_demand_per_node_today/{weather_year}s{simpl}_{clusters}") + benchmarks( + "build_industrial_energy_demand_per_node_today/{weather_year}s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -686,12 +778,16 @@ rule build_retro_cost: input: building_stock="data/retro/data_building_stock.csv", data_tabula="data/bundle-sector/retro/tabula-calculator-calcsetbuilding.csv", - air_temperature=resources("temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc"), + air_temperature=resources( + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), u_values_PL="data/retro/u_values_poland.csv", tax_w="data/retro/elec{weather_year}tricity_taxes_eu.csv", construction_index="data/retro/comparative_level_investment.csv", floor_area_missing="data/retro/floor_area_missing.csv", - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources( + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + ), cost_germany="data/retro/retro_cost_germany.csv", window_assumptions="data/retro/window_assumptions.csv", output: @@ -712,14 +808,18 @@ rule build_retro_cost: rule build_population_weighted_energy_totals: input: energy_totals=resources("{kind}_totals.csv"), - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources( + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + ), output: resources("pop_weighted_{kind}_totals{weather_year}_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, log: - logs("build_population_weighted_{kind}_totals{weather_year}_s{simpl}_{clusters}.log"), + logs( + "build_population_weighted_{kind}_totals{weather_year}_s{simpl}_{clusters}.log" + ), conda: "../envs/environment.yaml" script: @@ -730,7 +830,9 @@ rule build_shipping_demand: input: ports="data/attributed_ports.json", scope=resources("europe_shape.geojson"), - regions=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), demand=resources("energy_totals.csv"), params: energy_totals_year=config_provider("energy", "energy_totals_year"), @@ -753,16 +855,22 @@ rule build_transport_demand: drop_leap_day=config_provider("enable", "drop_leap_day"), sector=config_provider("sector"), input: - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources( + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + ), pop_weighted_energy_totals=resources( "pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv" ), transport_data=resources("transport_data.csv"), traffic_data_KFZ="data/bundle-sector/emobility/KFZ__count", traffic_data_Pkw="data/bundle-sector/emobility/Pkw__count", - temp_air_total=resources("temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc"), + temp_air_total=resources( + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), output: - transport_demand=resources("transport_demand{weather_year}_s{simpl}_{clusters}.csv"), + transport_demand=resources( + "transport_demand{weather_year}_s{simpl}_{clusters}.csv" + ), transport_data=resources("transport_data{weather_year}_s{simpl}_{clusters}.csv"), avail_profile=resources("avail_profile{weather_year}_s{simpl}_{clusters}.csv"), dsm_profile=resources("dsm_profile{weather_year}_s{simpl}_{clusters}.csv"), @@ -782,7 +890,9 @@ rule build_district_heat_share: sector=config_provider("sector"), input: district_heat_share=resources("district_heat_share.csv"), - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources( + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + ), output: district_heat_share=resources( "district_heat_share_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" @@ -791,7 +901,9 @@ rule build_district_heat_share: resources: mem_mb=1000, log: - logs("build_district_heat_share{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log"), + logs( + "build_district_heat_share{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log" + ), conda: "../envs/environment.yaml" script: @@ -805,7 +917,9 @@ rule build_existing_heating_distribution: existing_capacities=config_provider("existing_capacities"), input: existing_heating="data/existing_infrastructure/existing_heating_raw.csv", - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources( + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + ), clustered_pop_energy_layout=resources( "pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv" ), @@ -835,7 +949,7 @@ rule build_existing_heating_distribution: def input_profile_offwind(w): return { - f"profile_{tech}": resources(f"profile{{weather_year}}_{tech}.nc") + f"profile_{tech}": resources(f"profile{weather_year}_{tech}.nc") for tech in ["offwind-ac", "offwind-dc"] if (tech in config_provider("electricity", "renewable_carriers")(w)) } @@ -883,13 +997,17 @@ rule prepare_sector_network: else [] ), sequestration_potential=lambda w: ( - resources("co2_sequestration_potential_elec{weather_year}_s{simpl}_{clusters}.csv") + resources( + "co2_sequestration_potential_elec{weather_year}_s{simpl}_{clusters}.csv" + ) if config_provider( "sector", "regional_co2_sequestration_potential", "enable" )(w) else [] ), - network=resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), + network=resources( + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + ), energy_totals_name=resources("energy_totals.csv"), eurostat=input_eurostat, pop_weighted_energy_totals=resources( @@ -898,8 +1016,12 @@ rule prepare_sector_network: pop_weighted_heat_totals=resources( "pop_weighted_heat_totals{weather_year}_s{simpl}_{clusters}.csv" ), - shipping_demand=resources("shipping_demand{weather_year}_s{simpl}_{clusters}.csv"), - transport_demand=resources("transport_demand{weather_year}_s{simpl}_{clusters}.csv"), + shipping_demand=resources( + "shipping_demand{weather_year}_s{simpl}_{clusters}.csv" + ), + transport_demand=resources( + "transport_demand{weather_year}_s{simpl}_{clusters}.csv" + ), transport_data=resources("transport_data{weather_year}_s{simpl}_{clusters}.csv"), avail_profile=resources("avail_profile{weather_year}_s{simpl}_{clusters}.csv"), dsm_profile=resources("dsm_profile{weather_year}_s{simpl}_{clusters}.csv"), @@ -920,10 +1042,14 @@ rule prepare_sector_network: if config_provider("foresight")(w) == "overnight" else resources("costs_{planning_horizons}.csv") ), - h2_cavern=resources("salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv"), + h2_cavern=resources( + "salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv" + ), busmap_s=resources("busmap_elec{weather_year}_s{simpl}.csv"), busmap=resources("busmap_elec{weather_year}_s{simpl}_{clusters}.csv"), - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources( + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + ), simplified_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}.csv"), industrial_demand=resources( "industrial_energy_demand_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" @@ -934,18 +1060,42 @@ rule prepare_sector_network: district_heat_share=resources( "district_heat_share_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" ), - temp_soil_total=resources("temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_soil_rural=resources("temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_soil_urban=resources("temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_air_total=resources("temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_air_rural=resources("temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc"), - temp_air_urban=resources("temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_soil_total=resources("cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_soil_rural=resources("cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_soil_urban=resources("cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_air_total=resources("cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_air_rural=resources("cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_air_urban=resources("cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc"), + temp_soil_total=resources( + "temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_soil_rural=resources( + "temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_soil_urban=resources( + "temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_air_total=resources( + "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_air_rural=resources( + "temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + temp_air_urban=resources( + "temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_soil_total=resources( + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_soil_rural=resources( + "cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_soil_urban=resources( + "cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_air_total=resources( + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_air_rural=resources( + "cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_air_urban=resources( + "cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + ), solar_thermal_total=lambda w: ( resources("solar_thermal_total_elec{weather_year}_s{simpl}_{clusters}.nc") if config_provider("sector", "solar_thermal")(w) diff --git a/rules/collect.smk b/rules/collect.smk index d04ce9cb..e31434f5 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -34,7 +34,9 @@ rule extra_components_networks: rule prepare_elec_networks: input: expand( - resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), + resources( + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + ), **config["scenario"], run=config["run"]["name"], ), @@ -53,7 +55,8 @@ rule prepare_sector_networks: rule solve_elec_networks: input: expand( - RESULTS + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + RESULTS + + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config["scenario"], run=config["run"]["name"], ), diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 8b968681..cee07ea6 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -23,7 +23,9 @@ if config["foresight"] != "perfect": resources: mem_mb=4000, benchmark: - benchmarks("plot_power_network_clustered/elec{weather_year}_s{simpl}_{clusters}") + benchmarks( + "plot_power_network_clustered/elec{weather_year}_s{simpl}_{clusters}" + ) conda: "../envs/environment.yaml" script: @@ -35,7 +37,9 @@ if config["foresight"] != "perfect": input: network=RESULTS + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), output: map=RESULTS + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", @@ -62,7 +66,9 @@ if config["foresight"] != "perfect": input: network=RESULTS + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), output: map=RESULTS + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", @@ -88,7 +94,9 @@ if config["foresight"] != "perfect": input: network=RESULTS + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), output: map=RESULTS + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", @@ -125,7 +133,9 @@ if config["foresight"] == "perfect": input: network=RESULTS + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", - regions=resources("regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson"), + regions=resources( + "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + ), output: unpack(output_map_year), threads: 2 @@ -282,11 +292,12 @@ rule plot_elec_statistics: plotting=config_provider("plotting"), barplots=STATISTICS_BARPLOTS, input: - network=RESULTS + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=RESULTS + + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", output: **{ f"{plot}_bar": RESULTS - + f"figures/statistics_{plot}_bar_elec{{weather_year}}_s{{simpl}}_{{clusters}}_ec_l{{ll}}_{{opts}}.pdf" + + f"figures/statistics_{plot}_bar_elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.pdf" for plot in STATISTICS_BARPLOTS }, barplots_touch=RESULTS diff --git a/rules/retrieve.smk b/rules/retrieve.smk index f2d4f993..000d475e 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -179,7 +179,10 @@ if config["enable"]["retrieve"]: script: "../scripts/retrieve_gas_infrastructure_data.py" -if config["enable"]["retrieve"] and config["enable"].get("retrieve_opsd_load_data", True): + +if config["enable"]["retrieve"] and config["enable"].get( + "retrieve_opsd_load_data", True +): rule retrieve_electricity_demand: params: @@ -197,15 +200,26 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_opsd_load_dat "../scripts/retrieve_electricity_demand.py" -if config["enable"]["retrieve"] and config["enable"].get('retrieve_artificial_load_data', False): +if config["enable"]["retrieve"] and config["enable"].get( + "retrieve_artificial_load_data", False +): rule retrieve_artificial_load_data: - input: HTTP.remote("https://zenodo.org/record/7070438/files/demand_hourly.csv", keep_local=True, static=True) - output: "data/load_artificial_raw.csv" - log: logs("retrieve_artificial_load_data.log") - resources: mem_mb=5000, + input: + HTTP.remote( + "https://zenodo.org/record/7070438/files/demand_hourly.csv", + keep_local=True, + static=True, + ), + output: + "data/load_artificial_raw.csv", + log: + logs("retrieve_artificial_load_data.log"), + resources: + mem_mb=5000, retries: 2 - run: move(input[0], output[0]) + run: + move(input[0], output[0]) if config["enable"]["retrieve"]: diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index b404adf3..c69dfb88 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -13,7 +13,9 @@ rule solve_network: ), custom_extra_functionality=input_custom_extra_functionality, input: - network=resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), + network=resources( + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + ), config=RESULTS + "config.yaml", output: network=RESULTS @@ -26,7 +28,10 @@ rule solve_network: python=RESULTS + "logs/solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", benchmark: - RESULTS + "benchmarks/solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + ( + RESULTS + + "benchmarks/solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + ) threads: solver_threads resources: mem_mb=memory, diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 26dbf0ef..da31ac46 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -15,14 +15,20 @@ rule add_existing_baseyear: powerplants=resources("powerplants.csv"), busmap_s=resources("busmap_elec{weather_year}_s{simpl}.csv"), busmap=resources("busmap_elec{weather_year}_s{simpl}_{clusters}.csv"), - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv"), + clustered_pop_layout=resources( + "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + ), costs=lambda w: resources( "costs_{}.csv".format( config_provider("scenario", "planning_horizons", 0)(w) ) ), - cop_soil_total=resources("cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_air_total=resources("cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc"), + cop_soil_total=resources( + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_air_total=resources( + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), existing_heating_distribution=resources( "existing_heating_distribution_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" ), @@ -79,8 +85,12 @@ rule add_brownfield: + "prenetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", network_p=solved_previous_horizon, #solved network at previous time step costs=resources("costs_{planning_horizons}.csv"), - cop_soil_total=resources("cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc"), - cop_air_total=resources("cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc"), + cop_soil_total=resources( + "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), + cop_air_total=resources( + "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + ), output: RESULTS + "prenetworks-brownfield/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", From fa88e411d797d9b502a794367650a22b98b1f4ec Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 13:25:38 +0100 Subject: [PATCH 386/591] Automatic formatting --- scripts/prepare_sector_network.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 985bfa5c..bc714096 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3515,7 +3515,9 @@ def set_temporal_aggregation(n, resolution, solver_name, drop_leap_day=False): elif "seg" in resolution.lower(): segments = int(resolution[:-3]) logger.info("Use temporal segmentation with %s segments", segments) - n = apply_time_segmentation(n, segments, solver_name=solver_name, drop_leap_day=drop_leap_day) + n = apply_time_segmentation( + n, segments, solver_name=solver_name, drop_leap_day=drop_leap_day + ) # temporal averaging elif "h" in resolution.lower(): From d2527ed0ad1b48281949cb75d6d2b8cad9348da1 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 13:30:01 +0100 Subject: [PATCH 387/591] Add copyright headers --- scripts/build_heat_totals.py | 3 +++ scripts/solve_operations_network_other_year.py | 3 +++ scripts/solve_operations_network_other_year_myopic.py | 3 +++ 3 files changed, 9 insertions(+) diff --git a/scripts/build_heat_totals.py b/scripts/build_heat_totals.py index 93e8f9c7..e49ae635 100644 --- a/scripts/build_heat_totals.py +++ b/scripts/build_heat_totals.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT """ Approximate heat demand for all weather years. """ diff --git a/scripts/solve_operations_network_other_year.py b/scripts/solve_operations_network_other_year.py index f7d8f1e8..91f067cc 100644 --- a/scripts/solve_operations_network_other_year.py +++ b/scripts/solve_operations_network_other_year.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT """ Solve operations network. """ diff --git a/scripts/solve_operations_network_other_year_myopic.py b/scripts/solve_operations_network_other_year_myopic.py index 5fc8e6be..5858d79f 100644 --- a/scripts/solve_operations_network_other_year_myopic.py +++ b/scripts/solve_operations_network_other_year_myopic.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors +# +# SPDX-License-Identifier: MIT """ Solve myopic operations network. """ From e891305c9dd30fd6d09884f071f2f05ac8a5d023 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 14:37:16 +0100 Subject: [PATCH 388/591] Add selection of cutouts for heat to config --- config/config.default.yaml | 2 ++ rules/build_sector.smk | 45 ++++++++++++++++--------- scripts/build_solar_thermal_profiles.py | 1 + 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 60c492b1..bb714027 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -359,6 +359,7 @@ solar_thermal: orientation: slope: 45. azimuth: 180. + cutout: default # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#existing-capacities existing_capacities: @@ -391,6 +392,7 @@ sector: 2050: 1.0 district_heating_loss: 0.15 cluster_heat_buses: true + heat_demand_cutout: default bev_dsm_restriction_value: 0.75 bev_dsm_restriction_time: 7 transport_heating_deadband_upper: 20. diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 9fb6876b..e8af7f7b 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -151,6 +151,19 @@ rule cluster_gas_network: "../scripts/cluster_gas_network.py" +def heat_demand_cutout(wildcards): + c = config_provider("sector", "heat_demand_cutout")(wildcards) + if c == "default": + return ( + "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(wildcards) + + ".nc" + ) + else: + return "cutouts/" + CDIR + c + ".nc" + + rule build_daily_heat_demand: params: snapshots=config_provider("snapshots"), @@ -160,12 +173,7 @@ rule build_daily_heat_demand: regions_onshore=resources( "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" ), - cutout=( - lambda w: "cutouts/" - + CDIR - + config_provider("atlite", "default_cutout")(w) - + ".nc", - ), + cutout=heat_demand_cutout, output: heat_demand=resources( "daily_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" @@ -217,10 +225,7 @@ rule build_temperature_profiles: regions_onshore=resources( "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" ), - cutout=lambda w: "cutouts/" - + CDIR - + config_provider("atlite", "default_cutout")(w) - + ".nc", + cutout=heat_demand_cutout, output: temp_soil=resources( "temp_soil_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" @@ -294,6 +299,19 @@ rule build_cop_profiles: "../scripts/build_cop_profiles.py" +def solar_thermal_cutout(wildcards): + c = config_provider("solar_thermal", "cutout")(wildcards) + if c == "default": + return ( + "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(wildcards) + + ".nc" + ) + else: + return "cutouts/" + CDIR + c + ".nc" + + rule build_solar_thermal_profiles: params: snapshots=config_provider("snapshots"), @@ -304,10 +322,7 @@ rule build_solar_thermal_profiles: regions_onshore=resources( "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" ), - cutout=lambda w: "cutouts/" - + CDIR - + config_provider("atlite", "default_cutout")(w) - + ".nc", + cutout=solar_thermal_cutout, output: solar_thermal=resources( "solar_thermal_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" @@ -949,7 +964,7 @@ rule build_existing_heating_distribution: def input_profile_offwind(w): return { - f"profile_{tech}": resources(f"profile{weather_year}_{tech}.nc") + f"profile_{tech}": resources(f"profile{{weather_year}}_{tech}.nc") for tech in ["offwind-ac", "offwind-dc"] if (tech in config_provider("electricity", "renewable_carriers")(w)) } diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index b0896fa7..db56a401 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -31,6 +31,7 @@ if __name__ == "__main__": client = Client(cluster, asynchronous=True) config = snakemake.params.solar_thermal + config.pop("cutout", None) cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year From 0c7c0a8585f2f35bd7ae52e333f1950a979728fd Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 14:37:45 +0100 Subject: [PATCH 389/591] Minor bugfixes in postprocessing code --- rules/postprocess.smk | 2 +- scripts/make_summary.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index cee07ea6..67b71503 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -297,7 +297,7 @@ rule plot_elec_statistics: output: **{ f"{plot}_bar": RESULTS - + f"figures/statistics_{plot}_bar_elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.pdf" + + f"figures/statistics_{plot}_bar_elec{{weather_year}}_s{{simpl}}_{{clusters}}_ec_l{{ll}}_{{opts}}.pdf" for plot in STATISTICS_BARPLOTS }, barplots_touch=RESULTS diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 5dc18ec9..67089f92 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -681,7 +681,7 @@ if __name__ == "__main__": networks_dict = { (weather_year, cluster, ll, opt + sector_opt, planning_horizon): "results/" + snakemake.params.RDIR - + f"/postnetworks/elec_s{simpl}_{cluster}_l{ll}_{opt}_{sector_opt}_{planning_horizon}.nc" + + f"postnetworks/elec{weather_year}_s{simpl}_{cluster}_l{ll}_{opt}_{sector_opt}_{planning_horizon}.nc" for weather_year in snakemake.params.scenario["weather_year"] for simpl in snakemake.params.scenario["simpl"] for cluster in snakemake.params.scenario["clusters"] From 61d565ec0995498fea28d3bccbb836bb12b16449 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 15:26:16 +0100 Subject: [PATCH 390/591] Correct formatting in build_electricity.smk --- rules/build_electricity.smk | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 3f353dd9..3c8969aa 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -428,7 +428,7 @@ rule build_line_rating: def input_profile_tech(w): return { - f"profile_{tech}": resources(f"profile{weather_year}_{tech}.nc") + f"profile_{tech}": resources(f"profile{{weather_year}}_{tech}.nc") for tech in config_provider("electricity", "renewable_carriers")(w) } @@ -463,7 +463,7 @@ rule add_electricity: else resources("networks/base.nc") ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs' , 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), @@ -508,7 +508,7 @@ rule simplify_network: input: network=resources("networks/elec{weather_year}.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs' , 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), @@ -561,7 +561,7 @@ rule cluster_network: else [] ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs' , 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), output: network=resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), @@ -594,7 +594,7 @@ rule add_extra_components: input: network=resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs' , 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), output: resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc"), @@ -628,7 +628,7 @@ rule prepare_network: input: resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs' , 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: From 75ff4134fb39a17a26f3c0b86463fd29f0ed856e Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 15:26:47 +0100 Subject: [PATCH 391/591] Select correct snapshots for hourly heating demand --- rules/build_sector.smk | 1 + scripts/build_hourly_heat_demand.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index e8af7f7b..b4e41df8 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -194,6 +194,7 @@ rule build_daily_heat_demand: rule build_hourly_heat_demand: params: snapshots=config_provider("snapshots"), + drop_leap_day=config_provider("enable", "drop_leap_day"), input: heat_profile="data/heat_load_profile_BDEW.csv", heat_demand=resources( diff --git a/scripts/build_hourly_heat_demand.py b/scripts/build_hourly_heat_demand.py index a1dacd51..664b4499 100644 --- a/scripts/build_hourly_heat_demand.py +++ b/scripts/build_hourly_heat_demand.py @@ -24,7 +24,16 @@ if __name__ == "__main__": ) set_scenario_config(snakemake) - snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) + year = snakemake.wildcards.weather_year + + if year: + snapshots = dict(start=year, end=str(int(year) + 1), inclusive="left") + else: + snapshots = snakemake.params.snapshots + + snapshots = pd.date_range(freq="h", **snapshots) + if snakemake.params.drop_leap_day: + snapshots = snapshots[~((snapshots.month == 2) & (snapshots.day == 29))] daily_space_heat_demand = ( xr.open_dataarray(snakemake.input.heat_demand) From 9a69f88a36bdeb958e1c763646652a4a98eb2f96 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 15:49:39 +0100 Subject: [PATCH 392/591] Fix bug bug in time segmentation function signature --- 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 bc714096..6ca06c9a 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3425,7 +3425,7 @@ def cluster_heat_buses(n): def apply_time_segmentation( - n, segments, solver_name="cbc", overwrite_time_dependent=True + n, segments, solver_name="cbc", overwrite_time_dependent=True, drop_leap_day=False ): """ Aggregating time series to segments with different lengths. From e48b25f777a9c53364988d97a87b21673a1425b5 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 15:50:21 +0100 Subject: [PATCH 393/591] Fix unresolved or faulty merge conflicts in documentation --- doc/_static/theme_overrides.css | 74 --------------------------------- doc/configtables/enable.csv | 1 + doc/configtables/hydro.csv | 15 ++----- doc/configtables/toplevel.csv | 28 ------------- doc/configuration.rst | 6 +-- doc/tutorial.rst | 12 ------ 6 files changed, 5 insertions(+), 131 deletions(-) delete mode 100644 doc/_static/theme_overrides.css diff --git a/doc/_static/theme_overrides.css b/doc/_static/theme_overrides.css deleted file mode 100644 index 827dbbad..00000000 --- a/doc/_static/theme_overrides.css +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-FileCopyrightText: 2017-2020 The PyPSA-Eur Authors - SPDX-License-Identifier: MIT -*/ - -.wy-side-nav-search { - background-color: #eeeeee; -} - -.wy-side-nav-search .wy-dropdown>a, -.wy-side-nav-search>a { - color: rgb(34, 97, 156) -} - -.wy-side-nav-search>div.version { - color: rgb(34, 97, 156) -} - -.wy-menu-vertical header, -.wy-menu-vertical p.caption, -.rst-versions a { - color: #999999; -} - -.wy-menu-vertical a.reference:hover, -.wy-menu-vertical a.reference.internal:hover { - background: #dddddd; - color: #fff; -} - -.wy-nav-side { - background: #efefef; -} - -.wy-menu-vertical a.reference { - color: #000; -} - -.rst-versions .rst-current-version, -.wy-nav-top, -.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a:hover { - background: #002221; -} - -.wy-nav-content .highlight { - background: #ffffff; -} - -.rst-content code.literal, -.rst-content tt.literal { - color: rgb(34, 97, 156) -} - -.wy-nav-content a.reference { - color: rgb(34, 97, 156); -} - - -/* override table width restrictions */ - -@media screen and (min-width: 767px) { - .wy-table-responsive table td { - /* !important prevents the common CSS stylesheets from overriding - this as on RTD they are loaded after this stylesheet */ - white-space: normal !important; - background: rgb(250, 250, 250) !important; - } - .wy-table-responsive { - max-width: 100%; - overflow: visible !important; - } - .wy-nav-content { - max-width: 910px !important; - } -} diff --git a/doc/configtables/enable.csv b/doc/configtables/enable.csv index 8dd476cb..1e5571b3 100644 --- a/doc/configtables/enable.csv +++ b/doc/configtables/enable.csv @@ -10,3 +10,4 @@ retrieve_cutout,bool,"{true, false}","Switch to enable the retrieval of cutouts build_natura_raster,bool,"{true, false}","Switch to enable the creation of the raster ``natura.tiff`` via the rule :mod:`build_natura_raster`." retrieve_natura_raster,bool,"{true, false}","Switch to enable the retrieval of ``natura.tiff`` from zenodo with :mod:`retrieve_natura_raster`." custom_busmap,bool,"{true, false}","Switch to enable the use of custom busmaps in rule :mod:`cluster_network`. If activated the rule looks for provided busmaps at ``data/custom_busmap_elec_s{simpl}_{clusters}.csv`` which should have the same format as ``resources/busmap_elec_s{simpl}_{clusters}.csv``, i.e. the index should contain the buses of ``networks/elec_s{simpl}.nc``." +drop_leap_day,bool,"{true, false}","Switch to drop February 29 from all time-dependent data in leap years" diff --git a/doc/configtables/hydro.csv b/doc/configtables/hydro.csv index f9c8f0d5..790029d1 100644 --- a/doc/configtables/hydro.csv +++ b/doc/configtables/hydro.csv @@ -1,14 +1,3 @@ -<<<<<<< HEAD -,Unit,Values,Description -cutout,--,"Must be 'europe-2013-era5'","Specifies the directory where the relevant weather data ist stored." -carriers,--,"Any subset of {'ror', 'PHS', 'hydro'}","Specifies the types of hydro power plants to build per-unit availability time series for. 'ror' stands for run-of-river plants, 'PHS' represents pumped-hydro storage, and 'hydro' stands for hydroelectric dams." -PHS_max_hours,h,float,"Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom``. Cf. `PyPSA documentation `_." -hydro_max_hours,h,"Any of {float, 'energy_capacity_totals_by_country', 'estimate_by_large_installations'}","Maximum state of charge capacity of the pumped-hydro storage (PHS) in terms of hours at full output capacity ``p_nom`` or heuristically determined. Cf. `PyPSA documentation `_." -clip_min_inflow,MW,float,"To avoid too small values in the inflow time series, values below this threshold are set to zero." -eia_norm_year,--,"Year in EIA hydro generation dataset; or False to disable","To specify a specific year by which hydro inflow is normed that deviates from the snapshots' year" -eia_correct_by_capacity,--,boolean,"Correct EIA annual hydro generation data by installed capacity." -eia_approximate_missing,--,boolean,"Approximate hydro generation data for years not included in EIA dataset through a regression based on annual runoff." -======= ,Unit,Values,Description cutout,--,Must be 'europe-2013-era5',Specifies the directory where the relevant weather data ist stored. carriers,--,"Any subset of {'ror', 'PHS', 'hydro'}","Specifies the types of hydro power plants to build per-unit availability time series for. 'ror' stands for run-of-river plants, 'PHS' represents pumped-hydro storage, and 'hydro' stands for hydroelectric dams." @@ -17,4 +6,6 @@ hydro_max_hours,h,"Any of {float, 'energy_capacity_totals_by_country', 'estimate flatten_dispatch,bool,"{true, false}",Consider an upper limit for the hydro dispatch. The limit is given by the average capacity factor plus the buffer given in ``flatten_dispatch_buffer`` flatten_dispatch_buffer,--,float,"If ``flatten_dispatch`` is true, specify the value added above the average capacity factor." clip_min_inflow,MW,float,"To avoid too small values in the inflow time series, values below this threshold are set to zero." ->>>>>>> master +eia_norm_year,--,"Year in EIA hydro generation dataset; or False to disable","To specify a specific year by which hydro inflow is normed that deviates from the snapshots' year" +eia_correct_by_capacity,--,boolean,"Correct EIA annual hydro generation data by installed capacity." +eia_approximate_missing,--,boolean,"Approximate hydro generation data for years not included in EIA dataset through a regression based on annual runoff." diff --git a/doc/configtables/toplevel.csv b/doc/configtables/toplevel.csv index 74cc45d8..418acbab 100644 --- a/doc/configtables/toplevel.csv +++ b/doc/configtables/toplevel.csv @@ -1,40 +1,12 @@ -<<<<<<< HEAD ,Unit,Values,Description version,--,0.x.x,"Version of PyPSA-Eur. Descriptive only." tutorial,bool,"{true, false}","Switch to retrieve the tutorial data set instead of the full data set." logging,,, -- level,--,"Any of {'INFO', 'WARNING', 'ERROR'}","Restrict console outputs to all infos, warning or errors only" -- format,--,"","Custom format for log messages. See `LogRecord `_ attributes." -<<<<<<< HEAD -foresight,string,"{overnight, myopic, perfect}","Defaults to overnight scenarios." -countries,--,"Subset of {'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'}","European countries defined by their `Two-letter country codes (ISO 3166-1) `_ which should be included in the energy system model." -focus_weights,--,"Keys should be two-digit country codes (e.g. DE) and values should range between 0 and 1","Ratio of total clusters for particular countries. the remaining weight is distributed according to mean load. An example: ``focus_weights: 'DE': 0.6 'FR': 0.2``." -<<<<<<< HEAD -enable,,, --- prepare_links_p_nom,bool,"{true, false}","Switch to retrieve current HVDC projects from `Wikipedia `_" --- retrieve_databundle,bool,"{true, false}","Switch to retrieve databundle from zenodo via the rule :mod:`retrieve_databundle` or whether to keep a custom databundle located in the corresponding folder." --- build_cutout,bool,"{true, false}","Switch to enable the building of cutouts via the rule :mod:`build_cutout`." --- retrieve_cutout,bool,"{true, false}","Switch to enable the retrieval of cutouts from zenodo with :mod:`retrieve_cutout`." --- build_natura_raster,bool,"{true, false}","Switch to enable the creation of the raster ``natura.tiff`` via the rule :mod:`build_natura_raster`." --- retrieve_natura_raster,bool,"{true, false}","Switch to enable the retrieval of ``natura.tiff`` from zenodo with :mod:`retrieve_natura_raster`." --- custom_busmap,bool,"{true, false}","Switch to enable the use of custom busmaps in rule :mod:`cluster_network`. If activated the rule looks for provided busmaps at ``data/custom_busmap_elec{weather_year}_s{simpl}_{clusters}.csv`` which should have the same format as ``resources/busmap_elec{weather_year}_s{simpl}_{clusters}.csv``, i.e. the index should contain the buses of ``networks/elec_s{simpl}.nc``." --- drop_leap_day,bool,"{true, false}","Switch to drop February 29 from all time-dependent data in leap years" -======= -co2_budget,--,"Dictionary with planning horizons as keys.","CO2 budget as a fraction of 1990 emissions. Overwritten if ``CO2Lx`` or ``cb`` are set in ``{sector_opts}`` wildcard" ->>>>>>> master -======= ->>>>>>> origin/master -======= -,Unit,Values,Description -version,--,0.x.x,Version of PyPSA-Eur. Descriptive only. -tutorial,bool,"{true, false}",Switch to retrieve the tutorial data set instead of the full data set. -logging,,, --- level,--,"Any of {'INFO', 'WARNING', 'ERROR'}","Restrict console outputs to all infos, warning or errors only" --- format,--,,Custom format for log messages. See `LogRecord `_ attributes. private,,, -- keys,,, -- -- entsoe_api,--,,Optionally specify the ENTSO-E API key. See the guidelines to get `ENTSO-E API key `_ remote,,, -- ssh,--,,Optionally specify the SSH of a remote cluster to be synchronized. -- path,--,,Optionally specify the file path within the remote cluster to be synchronized. ->>>>>>> master diff --git a/doc/configuration.rst b/doc/configuration.rst index 91e6f1ad..9eba4284 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -82,22 +82,18 @@ facilitate running multiple scenarios through a single command # for electricity-only studies snakemake -call solve_elec_networks -<<<<<<< HEAD -For each wildcard, a **list of values** is provided. The rule ``solve_all_networks`` will trigger the rules for creating ``results/networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc`` for **all combinations** of the provided wildcard values as defined by Python's `itertools.product(...) `_ function that snakemake's `expand(...) function `_ uses. -======= # for sector-coupling studies snakemake -call solve_sector_networks For each wildcard, a **list of values** is provided. The rule ``solve_all_elec_networks`` will trigger the rules for creating -``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc`` for **all +``results/networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc`` for **all combinations** of the provided wildcard values as defined by Python's `itertools.product(...) `_ function that snakemake's `expand(...) function `_ uses. ->>>>>>> master An exemplary dependency graph (starting from the simplification rules) then looks like this: diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 9fc91174..4f272292 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -119,21 +119,9 @@ clustered down to 6 buses and every 24 hours aggregated to one snapshot. The com orders ``snakemake`` to run the rule :mod:`solve_network` that produces the solved network and stores it in ``results/networks`` with the name ``elec_s_6_ec_lcopt_Co2L-24H.nc``: -<<<<<<< HEAD -.. code:: - - rule solve_network: - input: "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - output: "results/networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - [...] - script: "scripts/solve_network.py" - -.. until https://github.com/snakemake/snakemake/issues/46 closed -======= .. literalinclude:: ../rules/solve_electricity.smk :start-at: rule solve_network: :end-before: rule solve_operations_network: ->>>>>>> master This triggers a workflow of multiple preceding jobs that depend on each rule's inputs and outputs: From 1ff8321c5e875ebd37b4b2d17ecc5db980ac1cf8 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 1 Mar 2024 15:54:42 +0100 Subject: [PATCH 394/591] Remove erroneous automatic snakefmt formatting --- rules/build_electricity.smk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 3c8969aa..a83a9d93 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -463,7 +463,7 @@ rule add_electricity: else resources("networks/base.nc") ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year')(w)}.csv" ), regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), @@ -508,7 +508,7 @@ rule simplify_network: input: network=resources("networks/elec{weather_year}.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year')(w)}.csv" ), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), @@ -561,7 +561,7 @@ rule cluster_network: else [] ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year')(w)}.csv" ), output: network=resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), @@ -594,7 +594,7 @@ rule add_extra_components: input: network=resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year')(w)}.csv" ), output: resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc"), @@ -628,7 +628,7 @@ rule prepare_network: input: resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year') (w)}.csv" + f"costs_{config_provider('costs', 'year')(w)}.csv" ), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: From 9607eb0e6bd2171914741a68eaf0da1798cb56fa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:16:26 +0000 Subject: [PATCH 395/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/build_clustered_population_layouts.py | 2 +- scripts/build_energy_totals.py | 140 ++++++++++++------ scripts/build_hydro_profile.py | 2 +- scripts/cluster_gas_network.py | 4 +- 4 files changed, 102 insertions(+), 46 deletions(-) diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index d4cfb96d..619acee8 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -25,7 +25,7 @@ if __name__ == "__main__": ) set_scenario_config(snakemake) - + cutout_name = snakemake.input.cutout year = snakemake.wildcards.weather_year if year: diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 00e9179c..954769ea 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -35,6 +35,7 @@ def reverse(dictionary): """ return {v: k for k, v in dictionary.items()} + non_EU = ["NO", "CH", "ME", "MK", "RS", "BA", "AL"] idees_rename = {"GR": "EL", "GB": "UK"} @@ -72,7 +73,10 @@ to_ipcc = { def eurostat_per_country(country): country_fn = idees_rename.get(country, country) - fn = snakemake.input.eurostat + f"/{country_fn}-Energy-balance-sheets-June-2021-edition.xlsb" + fn = ( + snakemake.input.eurostat + + f"/{country_fn}-Energy-balance-sheets-June-2021-edition.xlsb" + ) df = pd.read_excel( fn, @@ -93,27 +97,31 @@ def build_eurostat(countries, year=None): """ nprocesses = snakemake.threads - tqdm_kwargs = dict(ascii=False, unit=' country', total=len(countries), - desc='Build from eurostat database') + tqdm_kwargs = dict( + ascii=False, + unit=" country", + total=len(countries), + desc="Build from eurostat database", + ) with mp.Pool(processes=nprocesses) as pool: dfs = list(tqdm(pool.imap(eurostat_per_country, countries), **tqdm_kwargs)) - index_names = ['country', 'year', 'lvl1', 'lvl2', 'lvl3'] + index_names = ["country", "year", "lvl1", "lvl2", "lvl3"] df = pd.concat(dfs, keys=countries, names=index_names) - df.dropna(how='all', axis=0, inplace=True) - df.dropna(how='all', axis=1, inplace=True) - df = df[df.index.get_level_values('lvl1') != 'ktoe'] + df.dropna(how="all", axis=0, inplace=True) + df.dropna(how="all", axis=1, inplace=True) + df = df[df.index.get_level_values("lvl1") != "ktoe"] i = df.index.to_frame(index=False) - i.loc[i.lvl2 == 'Primary production', ['lvl1', 'lvl3']] = 'Main' - i.loc[i.lvl2 == 'Gross electricity production', 'lvl1'] = "Gross production" + i.loc[i.lvl2 == "Primary production", ["lvl1", "lvl3"]] = "Main" + i.loc[i.lvl2 == "Gross electricity production", "lvl1"] = "Gross production" i.ffill(inplace=True) df.index = pd.MultiIndex.from_frame(i) df.drop(list(range(1990, 2020)), axis=1, inplace=True) df.drop("Unnamed: 7", axis=1, inplace=True) - df.fillna(0., inplace=True) + df.fillna(0.0, inplace=True) # convert ktoe/a to TWh/a df *= 11.63 / 1e3 @@ -121,7 +129,7 @@ def build_eurostat(countries, year=None): df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1) if year: - df = df.xs(year, level='year') + df = df.xs(year, level="year") return df @@ -133,12 +141,12 @@ def build_swiss(year=None): fn = snakemake.input.swiss - df = pd.read_csv(fn, index_col=[0,1]).stack().unstack('item') + df = pd.read_csv(fn, index_col=[0, 1]).stack().unstack("item") df.index.names = ["country", "year"] df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1) if year: - df = df.xs(year, level='year') + df = df.xs(year, level="year") # convert PJ/a to TWh/a df /= 3.6 @@ -356,14 +364,14 @@ def build_idees(countries, year=None): unit=" country", total=len(countries), desc="Build from IDEES database", - disable=disable_progress + disable=disable_progress, ) with mute_print(): with mp.Pool(processes=nprocesses) as pool: totals_list = list(tqdm(pool.imap(func, countries), **tqdm_kwargs)) - totals = pd.concat(totals_list, keys=countries, names=['country', 'year']) + totals = pd.concat(totals_list, keys=countries, names=["country", "year"]) # convert ktoe to TWh exclude = totals.columns.str.fullmatch("passenger cars") @@ -377,23 +385,19 @@ def build_idees(countries, year=None): def build_energy_totals(countries, eurostat, swiss, idees): - eurostat_fuels = dict( - electricity="Electricity", - total="Total" - ) + eurostat_fuels = dict(electricity="Electricity", total="Total") eurostat_sectors = dict( residential="Households", services="Commercial & public services", road="Road", - rail="Rail" + rail="Rail", ) to_drop = ["passenger cars", "passenger car efficiency"] new_index = pd.MultiIndex.from_product( - [countries, eurostat.index.levels[1]], - names=["country", "year"] + [countries, eurostat.index.levels[1]], names=["country", "year"] ) df = idees.reindex(new_index).drop(to_drop, axis=1) @@ -404,7 +408,7 @@ def build_energy_totals(countries, eurostat, swiss, idees): # add international navigation slicer = idx[in_eurostat, :, :, "International maritime bunkers", :] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum() + fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0, 1]).sum() df.loc[in_eurostat, "total international navigation"] = fill_values # add swiss energy data @@ -414,11 +418,14 @@ def build_energy_totals(countries, eurostat, swiss, idees): # get values for missing countries based on Eurostat EnergyBalances # divide cooking/space/water according to averages in EU28 - to_fill = df.index[df["total residential"].isna() & df.index.get_level_values('country').isin(eurostat_countries)] + to_fill = df.index[ + df["total residential"].isna() + & df.index.get_level_values("country").isin(eurostat_countries) + ] uses = ["space", "cooking", "water"] - c = to_fill.get_level_values('country') - y = to_fill.get_level_values('year') + c = to_fill.get_level_values("country") + y = to_fill.get_level_values("year") for sector in ["residential", "services", "road", "rail"]: @@ -427,7 +434,9 @@ def build_energy_totals(countries, eurostat, swiss, idees): for fuel in ["electricity", "total"]: slicer = idx[c, y, :, :, eurostat_sectors[sector]] - fill_values = eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=[0,1]).sum() + fill_values = ( + eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=[0, 1]).sum() + ) df.loc[to_fill, f"{fuel} {sector}"] = fill_values for sector in ["residential", "services"]: @@ -488,7 +497,9 @@ def build_energy_totals(countries, eurostat, swiss, idees): no_norway[f"total {sector}"] - no_norway[f"electricity {sector}"] ) fraction = nonelectric_use.div(nonelectric).mean() - df.loc["NO", f"total {sector} {use}"] = (total_heating * fraction).values + df.loc["NO", f"total {sector} {use}"] = ( + total_heating * fraction + ).values df.loc["NO", f"electricity {sector} {use}"] = ( total_heating * fraction * elec_fraction ).values @@ -496,17 +507,17 @@ def build_energy_totals(countries, eurostat, swiss, idees): # Missing aviation slicer = idx[c, y, :, :, "Domestic aviation"] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum() + fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0, 1]).sum() df.loc[to_fill, "total domestic aviation"] = fill_values slicer = idx[c, y, :, "International aviation", :] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum() + fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0, 1]).sum() df.loc[to_fill, "total international aviation"] = fill_values # missing domestic navigation slicer = idx[c, y, :, :, "Domestic navigation"] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum() + fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0, 1]).sum() df.loc[to_fill, "total domestic navigation"] = fill_values # split road traffic for non-IDEES @@ -653,13 +664,15 @@ def build_eurostat_co2(countries, eurostat=None, year=1990): if eurostat is None: df = build_eurostat(countries, year) else: - df = eurostat.xs(year, level='year') + df = eurostat.xs(year, level="year") specific_emissions = pd.Series(index=df.columns, dtype=float) # emissions in tCO2_equiv per MWh_th specific_emissions["Solid fossil fuels"] = 0.36 # Approximates coal - specific_emissions["Oil and petroleum products"] = 0.285 # Average of distillate and residue + specific_emissions["Oil and petroleum products"] = ( + 0.285 # Average of distillate and residue + ) specific_emissions["Natural gas"] = 0.2 # For natural gas # oil values from https://www.eia.gov/tools/faqs/faq.cfm?id=74&t=11 @@ -675,19 +688,60 @@ def build_co2_totals(countries, eea_co2, eurostat_co2): for ct in pd.Index(countries).intersection(["BA", "RS", "AL", "ME", "MK"]): mappings = { - "electricity": (ct, "Transformation input", "Electricity & heat generation", "Main"), - "residential non-elec": (ct, "Final energy consumption", "Other sectors", "Households"), - "services non-elec": (ct, "Final energy consumption", "Other sectors", "Commercial & public services"), - "road non-elec": (ct, "Final energy consumption", "Transport sector", "Road"), - "rail non-elec": (ct, "Final energy consumption", "Transport sector", "Rail"), - "domestic navigation": (ct, "Final energy consumption", "Transport sector", "Domestic navigation"), + "electricity": ( + ct, + "Transformation input", + "Electricity & heat generation", + "Main", + ), + "residential non-elec": ( + ct, + "Final energy consumption", + "Other sectors", + "Households", + ), + "services non-elec": ( + ct, + "Final energy consumption", + "Other sectors", + "Commercial & public services", + ), + "road non-elec": ( + ct, + "Final energy consumption", + "Transport sector", + "Road", + ), + "rail non-elec": ( + ct, + "Final energy consumption", + "Transport sector", + "Rail", + ), + "domestic navigation": ( + ct, + "Final energy consumption", + "Transport sector", + "Domestic navigation", + ), "international navigation": (ct, "Main", "International maritime bunkers"), - "domestic aviation": (ct, "Final energy consumption", "Transport sector", "Domestic aviation"), + "domestic aviation": ( + ct, + "Final energy consumption", + "Transport sector", + "Domestic aviation", + ), "international aviation": (ct, "Main", "International aviation"), # does not include industrial process emissions or fuel processing/refining - "industrial non-elec": (ct, "Final energy consumption", "Industry sector", "Non-energy use in industry sector"), + "industrial non-elec": ( + ct, + "Final energy consumption", + "Industry sector", + "Non-energy use in industry sector", + ), # does not include non-energy emissions - "agriculture": (eurostat_co2.index.get_level_values(0) == ct) & eurostat_co2.index.isin(["Agriculture & forestry", "Fishing"], level=3), + "agriculture": (eurostat_co2.index.get_level_values(0) == ct) + & eurostat_co2.index.isin(["Agriculture & forestry", "Fishing"], level=3), } for i, mi in mappings.items(): @@ -771,6 +825,6 @@ if __name__ == "__main__": co2 = build_co2_totals(countries, eea_co2, eurostat_co2) co2.to_csv(snakemake.output.co2_name) - idees_transport = idees.xs(data_year, level='year') + idees_transport = idees.xs(data_year, level="year") transport = build_transport_data(countries, population, idees_transport) transport.to_csv(snakemake.output.transport_name) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 5571e9d7..af5f0ee6 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -65,8 +65,8 @@ import atlite import country_converter as coco import geopandas as gpd import pandas as pd -from numpy.polynomial import Polynomial from _helpers import configure_logging, set_scenario_config +from numpy.polynomial import Polynomial cc = coco.CountryConverter() diff --git a/scripts/cluster_gas_network.py b/scripts/cluster_gas_network.py index fd335cd3..8c03665b 100755 --- a/scripts/cluster_gas_network.py +++ b/scripts/cluster_gas_network.py @@ -105,7 +105,9 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("cluster_gas_network", weather_year="", simpl="", clusters="37") + snakemake = mock_snakemake( + "cluster_gas_network", weather_year="", simpl="", clusters="37" + ) configure_logging(snakemake) set_scenario_config(snakemake) From e6347621f9a81825a6fd3b7c0d64c8269dadcdce Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 4 Mar 2024 17:42:35 +0100 Subject: [PATCH 396/591] remove operations rules to reduce amount of simultaneous changes --- config/config.default.yaml | 15 -- rules/solve_overnight.smk | 58 ------ .../solve_operations_network_other_year.py | 147 ---------------- ...ve_operations_network_other_year_myopic.py | 166 ------------------ 4 files changed, 386 deletions(-) delete mode 100644 scripts/solve_operations_network_other_year.py delete mode 100644 scripts/solve_operations_network_other_year_myopic.py diff --git a/config/config.default.yaml b/config/config.default.yaml index bb714027..892a1e74 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -828,21 +828,6 @@ solving: walltime: "12:00:00" -operations: - rolling_horizon: - window: 10 # days - overlap: 8 # days - bidding_prices: # EUR/MW - H2 Electrolysis: -10 - H2 Fuel Cell: 200 - urban central water tanks charger: -10 - urban central water tanks discharger: 10 - hydro: 70 - solid biomass: 150 - biogas: 100 - co2_price: 500 # EUR/t - co2_sequestation_limit: 200 # Mt/a - # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#plotting plotting: map: diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index c190c14f..21fce682 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -41,61 +41,3 @@ rule solve_sector_network: "../envs/environment.yaml" script: "../scripts/solve_network.py" - - -rule solve_operations_network_other_year: - input: - pre=RDIR - + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - post=RDIR - + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", - output: - RDIR - + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}.nc", - shadow: - "shallow" - log: - solver=RDIR - + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", - python=RDIR - + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", - threads: 4 - resources: - mem_mb=10000, - benchmark: - ( - RDIR - + "/benchmarks/solve_operations_network/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" - ) - script: - "../scripts/solve_operations_network_other_year.py" - - -# rule solve_operations_network_other_year_myopic: -# input: -# overrides="data/override_component_attrs", -# pre=RDIR -# + "/prenetworks/elec{weather_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", -# post=RDIR -# + "/postnetworks/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc", -# previous=solved_previous_year, -# output: -# RDIR -# + "/operations/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_myopic.nc", -# shadow: -# "shallow" -# log: -# solver=RDIR -# + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_solver.log", -# python=RDIR -# + "/logs/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}_python.log", -# threads: 4 -# resources: -# mem_mb=10000, -# benchmark: -# ( -# RDIR -# + "/benchmarks/solve_operations_network_myopic/elec{capacity_year}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_{weather_year}" -# ) -# script: -# "../scripts/solve_operations_network_other_year_myopic.py" diff --git a/scripts/solve_operations_network_other_year.py b/scripts/solve_operations_network_other_year.py deleted file mode 100644 index 91f067cc..00000000 --- a/scripts/solve_operations_network_other_year.py +++ /dev/null @@ -1,147 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT -""" -Solve operations network. -""" - - -import logging - -import numpy as np -import pypsa -from solve_network import prepare_network, solve_network - -logger = logging.getLogger(__name__) -pypsa.pf.logger.setLevel(logging.WARNING) - - -def set_parameters_from_optimized(n, n_optim): - lines_typed_i = n.lines.index[n.lines.type != ""] - n.lines.loc[lines_typed_i, "num_parallel"] = n_optim.lines["num_parallel"].reindex( - lines_typed_i, fill_value=0.0 - ) - n.lines.loc[lines_typed_i, "s_nom"] = ( - np.sqrt(3) - * n.lines["type"].map(n.line_types.i_nom) - * n.lines.bus0.map(n.buses.v_nom) - * n.lines.num_parallel - ) - - lines_untyped_i = n.lines.index[n.lines.type == ""] - for attr in ("s_nom", "r", "x"): - n.lines.loc[lines_untyped_i, attr] = n_optim.lines[attr].reindex( - lines_untyped_i, fill_value=0.0 - ) - n.lines["s_nom_extendable"] = False - - links_dc_i = n.links.index[n.links.p_nom_extendable] - n.links.loc[links_dc_i, "p_nom"] = n_optim.links["p_nom_opt"].reindex( - links_dc_i, fill_value=0.0 - ) - n.links.loc[links_dc_i, "p_nom_extendable"] = False - - gen_extend_i = n.generators.index[n.generators.p_nom_extendable] - n.generators.loc[gen_extend_i, "p_nom"] = n_optim.generators["p_nom_opt"].reindex( - gen_extend_i, fill_value=0.0 - ) - n.generators.loc[gen_extend_i, "p_nom_extendable"] = False - - stor_units_extend_i = n.storage_units.index[n.storage_units.p_nom_extendable] - n.storage_units.loc[stor_units_extend_i, "p_nom"] = n_optim.storage_units[ - "p_nom_opt" - ].reindex(stor_units_extend_i, fill_value=0.0) - n.storage_units.loc[stor_units_extend_i, "p_nom_extendable"] = False - - stor_extend_i = n.stores.index[n.stores.e_nom_extendable] - n.stores.loc[stor_extend_i, "e_nom"] = n_optim.stores["e_nom_opt"].reindex( - stor_extend_i, fill_value=0.0 - ) - n.stores.loc[stor_extend_i, "e_nom_extendable"] = False - - return n - - -def remove_unused_components(n, threshold=50): - logger.info("Remove assets that are barely used to speed things up.") - - for c in n.iterate_components({"Store", "Link", "Generator"}): - attr = "e_nom" if c.name == "Store" else "p_nom" - to_remove = c.df.loc[c.df[attr] < threshold].index - logger.info(f"Removing barely used {c.name}s:\n{to_remove}") - n.mremove(c.name, to_remove) - - return n - - -def add_load_shedding(n, voll=1e4): - logger.info("Add load shedding to all buses.") - - if "load" in n.generators.carrier.unique(): - to_remove = n.generators.query("carrier == 'load'").index - logger.info(f"Removing pre-existing load shedding:\n{to_remove}") - n.mremove("Generator", to_remove) - - n.madd( - "Generator", - n.buses.index, - suffix=" load", - bus=n.buses.index, - carrier="load", - marginal_cost=voll, - p_nom=1e6, - ) - - return n - - -if __name__ == "__main__": - if "snakemake" not in globals(): - from helper import mock_snakemake - - snakemake = mock_snakemake( - "solve_operations_network", - capacity_year=1952, - simpl="", - opts="", - clusters=37, - lv=2.0, - sector_opts="Co2L0-25H-T-H-B-I-A", - planning_horizons=2030, - weather_year=2013, - ) - - logging.basicConfig( - filename=snakemake.log.python, level=snakemake.config["logging_level"] - ) - - tmpdir = snakemake.config["solving"].get("tmpdir") - if tmpdir is not None: - from pathlib import Path - - Path(tmpdir).mkdir(parents=True, exist_ok=True) - - n = pypsa.Network(snakemake.input.pre) - n_post = pypsa.Network(snakemake.input.post) - n = set_parameters_from_optimized(n, n_post) - del n_post - - n = remove_unused_components(n) - n = add_load_shedding(n) - - opts = snakemake.wildcards.sector_opts.split("-") - solve_opts = snakemake.config["solving"]["options"] - solve_opts["skip_iterations"] = True - - n = prepare_network(n, solve_opts) - - n = solve_network( - n, - config=snakemake.config, - opts=opts, - solver_dir=tmpdir, - solver_logfile=snakemake.log.solver, - ) - - n.export_to_netcdf(snakemake.output[0]) diff --git a/scripts/solve_operations_network_other_year_myopic.py b/scripts/solve_operations_network_other_year_myopic.py deleted file mode 100644 index 5858d79f..00000000 --- a/scripts/solve_operations_network_other_year_myopic.py +++ /dev/null @@ -1,166 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT -""" -Solve myopic operations network. -""" - - -import logging - -import pandas as pd -import pypsa -from solve_network import prepare_network, solve_network -from solve_operations_network import ( - add_load_shedding, - remove_unused_components, - set_parameters_from_optimized, -) - -logger = logging.getLogger(__name__) -pypsa.pf.logger.setLevel(logging.WARNING) - - -def prepare_myopic(n, config, store_soc, storage_unit_soc): - n.stores.e_cyclic = False - n.storage_units.cyclic_state_of_charge = False - - biomass_stores = n.stores.carrier.str.isin(["solid biomass", "biogas"]) - biomass_potential = n.stores.loc[biomass_stores, "e_initial"] - - # storage level contiguity across years - n.stores.e_initial = store_soc - n.storage_units.state_of_charge_initial = storage_unit_soc - - # replace co2 limit with co2 price - n.remove("GlobalConstraint", "CO2Limit") - n.stores.at["co2 atmosphere", "marginal_cost"] = -config["co2_price"] - - # handle co2 sequestration - assert ( - sum(n.stores.carriers == "co2 stored") == 1 - ), "Myopic operation not implemented for spatially resolved CO2 sequestration." - n.stores.at["co2 stored", "e_nom"] = config["co2_sequestration_limit"] * 1e6 # t/a - - # reset co2 emissions - n.stores.loc[n.stores.carrier == "co2 stored", "e_initial"] = 0.0 - n.stores.at["co2 atmosphere", "e_initial"] = 0.0 - - # replenish fossil gas and oil with 1000 TWh each - fossil_stores = n.stores.carrier.str.isin(["gas", "oil"]) - n.stores.loc[fossil_stores, "e_initial"] = 1e9 - n.stores.loc[fossil_stores, "e_nom"] = 10e9 - - # replenish annual solid biomass and biogas potentials - n.stores.loc[biomass_stores, "e_initial"] = biomass_potential - - # set storage bidding prices - bidding_prices = config["bidding_prices"] - for c in n.iterate_components({"Store", "Link", "StorageUnit"}): - c.df.marginal_cost.update(c.df.carrier.map(bidding_prices).dropna()) - - # deduct industry solid biomass - assert ( - sum(n.stores.carriers == "solid biomass") == 1 - ), "Myopic operation not implemented for spatially resolved solid biomass." - n.stores.at["EU solid biomass", "e_initial"] -= ( - n.loads.at["solid biomass for industry", "p_set"] * 8760 - ) - n.remove("Load", "solid biomass for industry") - - return n - - -def solve_network_myopic(n, config, opts="", **kwargs): - rolling_horizon = config["operations"]["rolling_horizon"] - - freq = int(pd.infer_freq(n.snapshots)[:-1]) - window = rolling_horizon["window"] * 24 // freq - overlap = rolling_horizon["overlap"] * 24 // freq - kept = window - overlap - length = len(n.snapshots) - - assert ( - kept > 0 - ), f"Overlap ({overlap} days) must be smaller than windows ({window} days)." - - for i in range(length // kept): - snapshots = n.snapshots[i * kept : (i + 1) * kept + overlap] - logger.info(f"Optimising operations from {snapshots[0]} to {snapshots[-1]}") - - n = solve_network(n, config, opts=opts, snapshots=snapshots, **kwargs) - - last_kept = n.snapshots[(i + 1) * kept - 1] - logger.info(f"Setting initial SOCs from {last_kept} for next iteration.\n") - - n.stores.e_initial = n.stores_t.e.loc[last_kept] - n.storage_units.state_of_charge_initial = n.storage_units_t.state_of_charge.loc[ - last_kept - ] - - # final segment until end of year - snapshots = n.snapshots[(i + 1) * kept :] - n = solve_network(n, config, opts=opts, snapshots=snapshots, **kwargs) - - return n - - -if __name__ == "__main__": - if "snakemake" not in globals(): - from helper import mock_snakemake - - snakemake = mock_snakemake( - "solve_operations_network_myopic", - capacity_year=1952, - simpl="", - opts="", - clusters=37, - lv=2.0, - sector_opts="Co2L0-25H-T-H-B-I-A", - planning_horizons=2030, - weather_year=2013, - ) - - logging.basicConfig( - filename=snakemake.log.python, level=snakemake.config["logging_level"] - ) - - tmpdir = snakemake.config["solving"].get("tmpdir") - if tmpdir is not None: - from pathlib import Path - - Path(tmpdir).mkdir(parents=True, exist_ok=True) - - config = snakemake.config["operations"] - - n = pypsa.Network(snakemake.input.pre) - - n_post = pypsa.Network(snakemake.input.post) - n = set_parameters_from_optimized(n, n_post) - del n_post - - n_previous = pypsa.Network(snakemake.input.previous) - store_soc = n_previous.stores_t.e.iloc[-1] - storage_unit_soc = n_previous.storage_units_t.state_of_charge.iloc[-1] - del n_previous - - n = remove_unused_components(n) - n = add_load_shedding(n) - n = prepare_myopic(n, config, store_soc, storage_unit_soc) - - opts = snakemake.wildcards.sector_opts.split("-") - solve_opts = snakemake.config["solving"]["options"] - solve_opts["skip_iterations"] = True - - n = prepare_network(n, solve_opts) - - n = solve_network_myopic( - n, - config=snakemake.config, - opts=opts, - solver_dir=tmpdir, - solver_logfile=snakemake.log.solver, - ) - - n.export_to_netcdf(snakemake.output[0]) From c2011bce49021a8365954a1a70e6a6f2b0117563 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 4 Mar 2024 17:48:56 +0100 Subject: [PATCH 397/591] remove {weather_year} wildcard --- Snakefile | 1 - config/config.default.yaml | 1 - config/test/config.electricity.yaml | 2 - config/test/config.myopic.yaml | 2 - config/test/config.overnight.yaml | 2 - doc/configuration.rst | 2 +- rules/build_electricity.smk | 90 ++--- rules/build_sector.smk | 330 +++++++++--------- rules/collect.smk | 18 +- rules/common.smk | 2 +- rules/postprocess.smk | 60 ++-- rules/solve_electricity.smk | 20 +- rules/solve_myopic.smk | 46 +-- rules/solve_overnight.smk | 12 +- scripts/add_brownfield.py | 1 - scripts/add_electricity.py | 2 +- scripts/add_existing_baseyear.py | 1 - scripts/add_extra_components.py | 6 +- scripts/build_artificial_load_data.py | 2 +- scripts/build_biomass_potentials.py | 1 - scripts/build_clustered_population_layouts.py | 1 - scripts/build_cop_profiles.py | 1 - scripts/build_daily_heat_demand.py | 1 - scripts/build_electricity_demand.py | 2 +- scripts/build_industrial_distribution_key.py | 1 - ...industrial_energy_demand_per_node_today.py | 1 - scripts/build_population_layouts.py | 1 - ...build_population_weighted_energy_totals.py | 1 - scripts/build_renewable_profiles.py | 2 +- scripts/build_solar_thermal_profiles.py | 1 - scripts/build_transport_demand.py | 1 - scripts/cluster_gas_network.py | 2 +- scripts/cluster_network.py | 22 +- scripts/make_summary.py | 7 +- scripts/prepare_links_p_nom.py | 2 +- scripts/prepare_network.py | 5 +- scripts/prepare_sector_network.py | 1 - scripts/simplify_network.py | 10 +- scripts/solve_network.py | 1 - scripts/solve_operations_network.py | 1 - 40 files changed, 320 insertions(+), 345 deletions(-) diff --git a/Snakefile b/Snakefile index f1bd459f..78a28373 100644 --- a/Snakefile +++ b/Snakefile @@ -56,7 +56,6 @@ localrules: wildcard_constraints: - weather_year="[0-9]{4}|", simpl="[a-zA-Z0-9]*", clusters="[0-9]+(m|c)?|all", ll="(v|c)([0-9\.]+|opt)", diff --git a/config/config.default.yaml b/config/config.default.yaml index 892a1e74..a9166560 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -34,7 +34,6 @@ 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: - weather_year: [''] # for backwards compatibility simpl: - '' ll: diff --git a/config/test/config.electricity.yaml b/config/test/config.electricity.yaml index 95405878..57964415 100644 --- a/config/test/config.electricity.yaml +++ b/config/test/config.electricity.yaml @@ -12,8 +12,6 @@ run: shared_cutouts: true scenario: - weather_year: - - "" clusters: - 5 opts: diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index 1157a7c6..5abae36d 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -13,8 +13,6 @@ run: foresight: myopic scenario: - weather_year: - - "" ll: - v1.5 clusters: diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index 0e2b6d6b..7fb53e42 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -12,8 +12,6 @@ run: scenario: - weather_year: - - "" ll: - v1.5 clusters: diff --git a/doc/configuration.rst b/doc/configuration.rst index 9eba4284..dae91380 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -87,7 +87,7 @@ facilitate running multiple scenarios through a single command For each wildcard, a **list of values** is provided. The rule ``solve_all_elec_networks`` will trigger the rules for creating -``results/networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc`` for **all +``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc`` for **all combinations** of the provided wildcard values as defined by Python's `itertools.product(...) `_ function diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index a83a9d93..53c2df0b 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -28,9 +28,9 @@ if config["enable"].get("retrieve_opsd_load_data", True): input: ancient("data/electricity_demand_raw.csv"), output: - resources("electricity_demand{weather_year}.csv"), + resources("electricity_demand.csv"), log: - logs("build_electricity_demand{weather_year}.log"), + logs("build_electricity_demand.log"), resources: mem_mb=5000, conda: @@ -45,9 +45,9 @@ if config["enable"].get("retrieve_artificial_load_data", False): input: ancient("data/load_artificial_raw.csv"), output: - resources("electricity_demand{weather_year}.csv"), + resources("electricity_demand.csv"), log: - logs("build_artificial_load_data{weather_year}.log"), + logs("build_artificial_load_data.log"), resources: mem_mb=5000, conda: @@ -192,11 +192,11 @@ if config["enable"].get("build_cutout", False): input: rules.build_cutout.input, output: - protected("cutouts/" + CDIR + "{cutout}-{weather_year}.nc"), + protected("cutouts/" + CDIR + "{cutout}-.nc"), log: - logs(CDIR + "build_cutout/{cutout}-{weather_year}.log"), + logs(CDIR + "build_cutout/{cutout}-.log"), benchmark: - benchmarks(CDIR + "build_cutout_{cutout}-{weather_year}") + benchmarks(CDIR + "build_cutout_{cutout}-") threads: ATLITE_NPROCESSES resources: mem_mb=ATLITE_NPROCESSES * 1000, @@ -342,11 +342,11 @@ rule build_renewable_profiles: + config_provider("renewable", w.technology, "cutout")(w) + ".nc", output: - profile=resources("profile{weather_year}_{technology}.nc"), + profile=resources("profile_{technology}.nc"), log: - logs("build_renewable_profile{weather_year}_{technology}.log"), + logs("build_renewable_profile_{technology}.log"), benchmark: - benchmarks("build_renewable_profiles{weather_year}_{technology}") + benchmarks("build_renewable_profiles_{technology}") threads: config["atlite"].get("nprocesses", 4) resources: mem_mb=config["atlite"].get("nprocesses", 4) * 5000, @@ -390,10 +390,10 @@ rule build_hydro_profile: + config_provider("renewable", "hydro", "cutout")(w) + ".nc", output: - profile=resources("profile{weather_year}_hydro.nc"), - eia_hydro=resources("eia_hydro_stats{weather_year}.csv"), + profile=resources("profile_hydro.nc"), + eia_hydro=resources("eia_hydro_stats.csv"), log: - logs("build_hydro_profile{weather_year}.log"), + logs("build_hydro_profile.log"), resources: mem_mb=5000, conda: @@ -428,7 +428,7 @@ rule build_line_rating: def input_profile_tech(w): return { - f"profile_{tech}": resources(f"profile{{weather_year}}_{tech}.nc") + f"profile_{tech}": resources(f"profile{}_{tech}.nc") for tech in config_provider("electricity", "renewable_carriers")(w) } @@ -475,15 +475,15 @@ rule add_electricity: if config_provider("conventional", "dynamic_fuel_price")(w) else [] ), - load=resources("electricity_demand{weather_year}.csv"), + load=resources("electricity_demand.csv"), nuts3_shapes=resources("nuts3_shapes.geojson"), ua_md_gdp="data/GDP_PPP_30arcsec_v3_mapped_default.csv", output: - resources("networks/elec{weather_year}.nc"), + resources("networks/elec.nc"), log: - logs("add_electricity{weather_year}.log"), + logs("add_electricity.log"), benchmark: - benchmarks("add_electricity{weather_year}") + benchmarks("add_electricity") threads: 1 resources: mem_mb=10000, @@ -506,24 +506,24 @@ rule simplify_network: p_max_pu=config_provider("links", "p_max_pu", default=1.0), costs=config_provider("costs"), input: - network=resources("networks/elec{weather_year}.nc"), + network=resources("networks/elec.nc"), tech_costs=lambda w: resources( f"costs_{config_provider('costs', 'year')(w)}.csv" ), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), output: - network=resources("networks/elec{weather_year}_s{simpl}.nc"), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}.geojson"), + network=resources("networks/elec_s{simpl}.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), regions_offshore=resources( - "regions_offshore_elec{weather_year}_s{simpl}.geojson" + "regions_offshore_elec_s{simpl}.geojson" ), - busmap=resources("busmap_elec{weather_year}_s{simpl}.csv"), - connection_costs=resources("connection_costs{weather_year}_s{simpl}.csv"), + busmap=resources("busmap_elec_s{simpl}.csv"), + connection_costs=resources("connection_costs_s{simpl}.csv"), log: - logs("simplify_network/elec{weather_year}_s{simpl}.log"), + logs("simplify_network/elec_s{simpl}.log"), benchmark: - benchmarks("simplify_network/elec{weather_year}_s{simpl}") + benchmarks("simplify_network/elec_s{simpl}") threads: 1 resources: mem_mb=12000, @@ -549,12 +549,12 @@ rule cluster_network: length_factor=config_provider("lines", "length_factor"), costs=config_provider("costs"), input: - network=resources("networks/elec{weather_year}_s{simpl}.nc"), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}.geojson"), + network=resources("networks/elec_s{simpl}.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), regions_offshore=resources( - "regions_offshore_elec{weather_year}_s{simpl}.geojson" + "regions_offshore_elec_s{simpl}.geojson" ), - busmap=ancient(resources("busmap_elec{weather_year}_s{simpl}.csv")), + busmap=ancient(resources("busmap_elec_s{simpl}.csv")), custom_busmap=lambda w: ( "data/custom_busmap_elec_s{simpl}_{clusters}.csv" if config_provider("enable", "custom_busmap", default=False)(w) @@ -564,19 +564,19 @@ rule cluster_network: f"costs_{config_provider('costs', 'year')(w)}.csv" ), output: - network=resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), + network=resources("networks/elec_s{simpl}_{clusters}.nc"), regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), regions_offshore=resources( - "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_offshore_elec_s{simpl}_{clusters}.geojson" ), - busmap=resources("busmap_elec{weather_year}_s{simpl}_{clusters}.csv"), - linemap=resources("linemap_elec{weather_year}_s{simpl}_{clusters}.csv"), + busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), + linemap=resources("linemap_elec_s{simpl}_{clusters}.csv"), log: - logs("cluster_network/elec{weather_year}_s{simpl}_{clusters}.log"), + logs("cluster_network/elec_s{simpl}_{clusters}.log"), benchmark: - benchmarks("cluster_network/elec{weather_year}_s{simpl}_{clusters}") + benchmarks("cluster_network/elec_s{simpl}_{clusters}") threads: 1 resources: mem_mb=10000, @@ -592,16 +592,16 @@ rule add_extra_components: max_hours=config_provider("electricity", "max_hours"), costs=config_provider("costs"), input: - network=resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), + network=resources("networks/elec_s{simpl}_{clusters}.nc"), tech_costs=lambda w: resources( f"costs_{config_provider('costs', 'year')(w)}.csv" ), output: - resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc"), + resources("networks/elec_s{simpl}_{clusters}_ec.nc"), log: - logs("add_extra_components/elec{weather_year}_s{simpl}_{clusters}.log"), + logs("add_extra_components/elec_s{simpl}_{clusters}.log"), benchmark: - benchmarks("add_extra_components/elec{weather_year}_s{simpl}_{clusters}_ec") + benchmarks("add_extra_components/elec_s{simpl}_{clusters}_ec") threads: 1 resources: mem_mb=4000, @@ -626,21 +626,21 @@ rule prepare_network: adjustments=config_provider("adjustments", "electricity"), autarky=config_provider("electricity", "autarky", default={}), input: - resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc"), + resources("networks/elec_s{simpl}_{clusters}_ec.nc"), tech_costs=lambda w: resources( f"costs_{config_provider('costs', 'year')(w)}.csv" ), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: - resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), + resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), log: logs( - "prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" + "prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" ), benchmark: ( benchmarks( - "prepare_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + "prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" ) ) threads: 1 diff --git a/rules/build_sector.smk b/rules/build_sector.smk index b4e41df8..ab296565 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -12,15 +12,15 @@ rule build_population_layouts: + config_provider("atlite", "default_cutout")(w) + ".nc", output: - pop_layout_total=resources("pop_layout_total{weather_year}.nc"), - pop_layout_urban=resources("pop_layout_urban{weather_year}.nc"), - pop_layout_rural=resources("pop_layout_rural{weather_year}.nc"), + pop_layout_total=resources("pop_layout_total.nc"), + pop_layout_urban=resources("pop_layout_urban.nc"), + pop_layout_rural=resources("pop_layout_rural.nc"), log: - logs("build_population_layouts{weather_year}.log"), + logs("build_population_layouts.log"), resources: mem_mb=20000, benchmark: - benchmarks("build_population_layouts{weather_year}") + benchmarks("build_population_layouts") threads: 8 conda: "../envs/environment.yaml" @@ -30,11 +30,11 @@ rule build_population_layouts: rule build_clustered_population_layouts: input: - pop_layout_total=resources("pop_layout_total{weather_year}.nc"), - pop_layout_urban=resources("pop_layout_urban{weather_year}.nc"), - pop_layout_rural=resources("pop_layout_rural{weather_year}.nc"), + pop_layout_total=resources("pop_layout_total.nc"), + pop_layout_urban=resources("pop_layout_urban.nc"), + pop_layout_rural=resources("pop_layout_rural.nc"), regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), cutout=lambda w: "cutouts/" + CDIR @@ -42,15 +42,15 @@ rule build_clustered_population_layouts: + ".nc", output: clustered_pop_layout=resources( - "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + "pop_layout_elec_s{simpl}_{clusters}.csv" ), log: - logs("build_clustered_population_layouts{weather_year}_{simpl}_{clusters}.log"), + logs("build_clustered_population_layouts_{simpl}_{clusters}.log"), resources: mem_mb=10000, benchmark: benchmarks( - "build_clustered_population_layouts/{weather_year}s{simpl}_{clusters}" + "build_clustered_population_layouts/s{simpl}_{clusters}" ) conda: "../envs/environment.yaml" @@ -60,22 +60,22 @@ rule build_clustered_population_layouts: rule build_simplified_population_layouts: input: - pop_layout_total=resources("pop_layout_total{weather_year}.nc"), - pop_layout_urban=resources("pop_layout_urban{weather_year}.nc"), - pop_layout_rural=resources("pop_layout_rural{weather_year}.nc"), - regions_onshore=resources("regions_onshore_elec{weather_year}_s{simpl}.geojson"), + pop_layout_total=resources("pop_layout_total.nc"), + pop_layout_urban=resources("pop_layout_urban.nc"), + pop_layout_rural=resources("pop_layout_rural.nc"), + regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), cutout=lambda w: "cutouts/" + CDIR + config_provider("atlite", "default_cutout")(w) + ".nc", output: - clustered_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}.csv"), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}.csv"), resources: mem_mb=10000, log: - logs("build_simplified_population_layouts{weather_year}_{simpl}"), + logs("build_simplified_population_layouts_{simpl}"), benchmark: - benchmarks("build_simplified_population_layouts/{weather_year}s{simpl}") + benchmarks("build_simplified_population_layouts/s{simpl}") conda: "../envs/environment.yaml" script: @@ -106,22 +106,22 @@ rule build_gas_input_locations: entry="data/gas_network/scigrid-gas/data/IGGIELGN_BorderPoints.geojson", storage="data/gas_network/scigrid-gas/data/IGGIELGN_Storages.geojson", regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), regions_offshore=resources( - "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_offshore_elec_s{simpl}_{clusters}.geojson" ), output: gas_input_nodes=resources( - "gas_input_locations{weather_year}_s{simpl}_{clusters}.geojson" + "gas_input_locations_s{simpl}_{clusters}.geojson" ), gas_input_nodes_simplified=resources( - "gas_input_locations{weather_year}_s{simpl}_{clusters}_simplified.csv" + "gas_input_locations_s{simpl}_{clusters}_simplified.csv" ), resources: mem_mb=2000, log: - logs("build_gas_input_locations{weather_year}_s{simpl}_{clusters}.log"), + logs("build_gas_input_locations_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -132,19 +132,19 @@ rule cluster_gas_network: input: cleaned_gas_network=resources("gas_network.csv"), regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), regions_offshore=resources( - "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_offshore_elec_s{simpl}_{clusters}.geojson" ), output: clustered_gas_network=resources( - "gas_network_elec{weather_year}_s{simpl}_{clusters}.csv" + "gas_network_elec_s{simpl}_{clusters}.csv" ), resources: mem_mb=4000, log: - logs("cluster_gas_network{weather_year}_s{simpl}_{clusters}.log"), + logs("cluster_gas_network_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -169,22 +169,22 @@ rule build_daily_heat_demand: snapshots=config_provider("snapshots"), drop_leap_day=config_provider("enable", "drop_leap_day"), input: - pop_layout=resources("pop_layout_{scope}{weather_year}.nc"), + pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), cutout=heat_demand_cutout, output: heat_demand=resources( - "daily_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc" ), resources: mem_mb=20000, threads: 8 log: - logs("build_daily_heat_demand_{scope}_{weather_year}_{simpl}_{clusters}.loc"), + logs("build_daily_heat_demand_{scope}__{simpl}_{clusters}.loc"), benchmark: - benchmarks("build_daily_heat_demand/{scope}_{weather_year}_s{simpl}_{clusters}") + benchmarks("build_daily_heat_demand/{scope}__s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -198,19 +198,19 @@ rule build_hourly_heat_demand: input: heat_profile="data/heat_load_profile_BDEW.csv", heat_demand=resources( - "daily_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc" ), output: heat_demand=resources( - "hourly_heat_demand_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + "hourly_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc" ), resources: mem_mb=2000, threads: 8 log: - logs("build_hourly_heat_demand_{scope}{weather_year}_{simpl}_{clusters}.loc"), + logs("build_hourly_heat_demand_{scope}_{simpl}_{clusters}.loc"), benchmark: - benchmarks("build_hourly_heat_demand/{scope}{weather_year}_s{simpl}_{clusters}") + benchmarks("build_hourly_heat_demand/{scope}_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -222,24 +222,24 @@ rule build_temperature_profiles: snapshots=config_provider("snapshots"), drop_leap_day=config_provider("enable", "drop_leap_day"), input: - pop_layout=resources("pop_layout_{scope}{weather_year}.nc"), + pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), cutout=heat_demand_cutout, output: temp_soil=resources( - "temp_soil_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_soil_{scope}_elec_s{simpl}_{clusters}.nc" ), - temp_air=resources("temp_air_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc"), + temp_air=resources("temp_air_{scope}_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, threads: 8 log: - logs("build_temperature_profiles_{scope}_{weather_year}_{simpl}_{clusters}.log"), + logs("build_temperature_profiles_{scope}__{simpl}_{clusters}.log"), benchmark: benchmarks( - "build_temperature_profiles/{scope}_{weather_year}_s{simpl}_{clusters}" + "build_temperature_profiles/{scope}__s{simpl}_{clusters}" ) conda: "../envs/environment.yaml" @@ -252,48 +252,48 @@ rule build_cop_profiles: heat_pump_sink_T=config_provider("sector", "heat_pump_sink_T"), input: temp_soil_total=resources( - "temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_soil_total_elec_s{simpl}_{clusters}.nc" ), temp_soil_rural=resources( - "temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_soil_rural_elec_s{simpl}_{clusters}.nc" ), temp_soil_urban=resources( - "temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_soil_urban_elec_s{simpl}_{clusters}.nc" ), temp_air_total=resources( - "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_air_total_elec_s{simpl}_{clusters}.nc" ), temp_air_rural=resources( - "temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_air_rural_elec_s{simpl}_{clusters}.nc" ), temp_air_urban=resources( - "temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_air_urban_elec_s{simpl}_{clusters}.nc" ), output: cop_soil_total=resources( - "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_soil_total_elec_s{simpl}_{clusters}.nc" ), cop_soil_rural=resources( - "cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_soil_rural_elec_s{simpl}_{clusters}.nc" ), cop_soil_urban=resources( - "cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_soil_urban_elec_s{simpl}_{clusters}.nc" ), cop_air_total=resources( - "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_air_total_elec_s{simpl}_{clusters}.nc" ), cop_air_rural=resources( - "cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_air_rural_elec_s{simpl}_{clusters}.nc" ), cop_air_urban=resources( - "cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_air_urban_elec_s{simpl}_{clusters}.nc" ), resources: mem_mb=20000, log: - logs("build_cop_profiles{weather_year}_s{simpl}_{clusters}.log"), + logs("build_cop_profiles_s{simpl}_{clusters}.log"), benchmark: - benchmarks("build_cop_profiles/{weather_year}s{simpl}_{clusters}") + benchmarks("build_cop_profiles/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -319,25 +319,25 @@ rule build_solar_thermal_profiles: drop_leap_day=config_provider("enable", "drop_leap_day"), solar_thermal=config_provider("solar_thermal"), input: - pop_layout=resources("pop_layout_{scope}{weather_year}.nc"), + pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), cutout=solar_thermal_cutout, output: solar_thermal=resources( - "solar_thermal_{scope}_elec{weather_year}_s{simpl}_{clusters}.nc" + "solar_thermal_{scope}_elec_s{simpl}_{clusters}.nc" ), resources: mem_mb=20000, threads: 16 log: logs( - "build_solar_thermal_profiles_{scope}_{weather_year}_s{simpl}_{clusters}.log" + "build_solar_thermal_profiles_{scope}__s{simpl}_{clusters}.log" ), benchmark: benchmarks( - "build_solar_thermal_profiles/{scope}_{weather_year}_s{simpl}_{clusters}" + "build_solar_thermal_profiles/{scope}__s{simpl}_{clusters}" ) conda: "../envs/environment.yaml" @@ -403,7 +403,7 @@ rule build_biomass_potentials: ), nuts2="data/bundle-sector/nuts/NUTS_RG_10M_2013_4326_LEVL_2.geojson", # https://gisco-services.ec.europa.eu/distribution/v2/nuts/download/#nuts21 regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), nuts3_population=ancient("data/bundle/nama_10r_3popgdp.tsv.gz"), swiss_cantons=ancient("data/bundle/ch_cantons.csv"), @@ -411,21 +411,21 @@ rule build_biomass_potentials: country_shapes=resources("country_shapes.geojson"), output: biomass_potentials_all=resources( - "biomass_potentials_all{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "biomass_potentials_all_s{simpl}_{clusters}_{planning_horizons}.csv" ), biomass_potentials=resources( - "biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv" ), threads: 1 resources: mem_mb=1000, log: logs( - "build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log" + "build_biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.log" ), benchmark: benchmarks( - "build_biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}" + "build_biomass_potentials_s{simpl}_{clusters}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -465,22 +465,22 @@ rule build_sequestration_potentials: keep_local=True, ), regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), regions_offshore=resources( - "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_offshore_elec_s{simpl}_{clusters}.geojson" ), output: sequestration_potential=resources( - "co2_sequestration_potential_elec{weather_year}_s{simpl}_{clusters}.csv" + "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv" ), threads: 1 resources: mem_mb=4000, log: - logs("build_sequestration_potentials{weather_year}_s{simpl}_{clusters}.log"), + logs("build_sequestration_potentials_s{simpl}_{clusters}.log"), benchmark: - benchmarks("build_sequestration_potentials{weather_year}_s{simpl}_{clusters}") + benchmarks("build_sequestration_potentials_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -491,22 +491,22 @@ rule build_salt_cavern_potentials: input: salt_caverns="data/bundle-sector/h2_salt_caverns_GWh_per_sqkm.geojson", regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), regions_offshore=resources( - "regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_offshore_elec_s{simpl}_{clusters}.geojson" ), output: h2_cavern_potential=resources( - "salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv" + "salt_cavern_potentials_s{simpl}_{clusters}.csv" ), threads: 1 resources: mem_mb=2000, log: - logs("build_salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.log"), + logs("build_salt_cavern_potentials_s{simpl}_{clusters}.log"), benchmark: - benchmarks("build_salt_cavern_potentials{weather_year}_s{simpl}_{clusters}") + benchmarks("build_salt_cavern_potentials_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -642,24 +642,24 @@ rule build_industrial_distribution_key: countries=config_provider("countries"), input: regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), clustered_pop_layout=resources( - "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + "pop_layout_elec_s{simpl}_{clusters}.csv" ), hotmaps_industrial_database="data/bundle-sector/Industrial_Database.csv", output: industrial_distribution_key=resources( - "industrial_distribution_key_elec{weather_year}_s{simpl}_{clusters}.csv" + "industrial_distribution_key_elec_s{simpl}_{clusters}.csv" ), threads: 1 resources: mem_mb=1000, log: - logs("build_industrial_distribution_key{weather_year}_s{simpl}_{clusters}.log"), + logs("build_industrial_distribution_key_s{simpl}_{clusters}.log"), benchmark: benchmarks( - "build_industrial_distribution_key/{weather_year}s{simpl}_{clusters}" + "build_industrial_distribution_key/s{simpl}_{clusters}" ) conda: "../envs/environment.yaml" @@ -670,26 +670,26 @@ rule build_industrial_distribution_key: rule build_industrial_production_per_node: input: industrial_distribution_key=resources( - "industrial_distribution_key_elec{weather_year}_s{simpl}_{clusters}.csv" + "industrial_distribution_key_elec_s{simpl}_{clusters}.csv" ), industrial_production_per_country_tomorrow=resources( "industrial_production_per_country_tomorrow_{planning_horizons}.csv" ), output: industrial_production_per_node=resources( - "industrial_production_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), threads: 1 resources: mem_mb=1000, log: logs( - "build_industrial_production_per_node{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log" + "build_industrial_production_per_node_s{simpl}_{clusters}_{planning_horizons}.log" ), benchmark: ( benchmarks( - "build_industrial_production_per_node/{weather_year}s{simpl}_{clusters}_{planning_horizons}" + "build_industrial_production_per_node/s{simpl}_{clusters}_{planning_horizons}" ) ) conda: @@ -704,26 +704,26 @@ rule build_industrial_energy_demand_per_node: "industry_sector_ratios_{planning_horizons}.csv" ), industrial_production_per_node=resources( - "industrial_production_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), industrial_energy_demand_per_node_today=resources( - "industrial_energy_demand_today_elec{weather_year}_s{simpl}_{clusters}.csv" + "industrial_energy_demand_today_elec_s{simpl}_{clusters}.csv" ), output: industrial_energy_demand_per_node=resources( - "industrial_energy_demand_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), threads: 1 resources: mem_mb=1000, log: logs( - "build_industrial_energy_demand_per_node{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log" + "build_industrial_energy_demand_per_node_s{simpl}_{clusters}_{planning_horizons}.log" ), benchmark: ( benchmarks( - "build_industrial_energy_demand_per_node/{weather_year}s{simpl}_{clusters}_{planning_horizons}" + "build_industrial_energy_demand_per_node/s{simpl}_{clusters}_{planning_horizons}" ) ) conda: @@ -761,25 +761,25 @@ rule build_industrial_energy_demand_per_country_today: rule build_industrial_energy_demand_per_node_today: input: industrial_distribution_key=resources( - "industrial_distribution_key_elec{weather_year}_s{simpl}_{clusters}.csv" + "industrial_distribution_key_elec_s{simpl}_{clusters}.csv" ), industrial_energy_demand_per_country_today=resources( "industrial_energy_demand_per_country_today.csv" ), output: industrial_energy_demand_per_node_today=resources( - "industrial_energy_demand_today_elec{weather_year}_s{simpl}_{clusters}.csv" + "industrial_energy_demand_today_elec_s{simpl}_{clusters}.csv" ), threads: 1 resources: mem_mb=1000, log: logs( - "build_industrial_energy_demand_per_node_today{weather_year}_s{simpl}_{clusters}.log" + "build_industrial_energy_demand_per_node_today_s{simpl}_{clusters}.log" ), benchmark: benchmarks( - "build_industrial_energy_demand_per_node_today/{weather_year}s{simpl}_{clusters}" + "build_industrial_energy_demand_per_node_today/s{simpl}_{clusters}" ) conda: "../envs/environment.yaml" @@ -795,26 +795,26 @@ rule build_retro_cost: building_stock="data/retro/data_building_stock.csv", data_tabula="data/bundle-sector/retro/tabula-calculator-calcsetbuilding.csv", air_temperature=resources( - "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_air_total_elec_s{simpl}_{clusters}.nc" ), u_values_PL="data/retro/u_values_poland.csv", - tax_w="data/retro/elec{weather_year}tricity_taxes_eu.csv", + tax_w="data/retro/electricity_taxes_eu.csv", construction_index="data/retro/comparative_level_investment.csv", floor_area_missing="data/retro/floor_area_missing.csv", clustered_pop_layout=resources( - "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + "pop_layout_elec_s{simpl}_{clusters}.csv" ), cost_germany="data/retro/retro_cost_germany.csv", window_assumptions="data/retro/window_assumptions.csv", output: - retro_cost=resources("retro_cost_elec{weather_year}_s{simpl}_{clusters}.csv"), - floor_area=resources("floor_area_elec{weather_year}_s{simpl}_{clusters}.csv"), + retro_cost=resources("retro_cost_elec_s{simpl}_{clusters}.csv"), + floor_area=resources("floor_area_elec_s{simpl}_{clusters}.csv"), resources: mem_mb=1000, log: - logs("build_retro_cost{weather_year}_s{simpl}_{clusters}.log"), + logs("build_retro_cost_s{simpl}_{clusters}.log"), benchmark: - benchmarks("build_retro_cost/{weather_year}s{simpl}_{clusters}") + benchmarks("build_retro_cost/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -825,16 +825,16 @@ rule build_population_weighted_energy_totals: input: energy_totals=resources("{kind}_totals.csv"), clustered_pop_layout=resources( - "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + "pop_layout_elec_s{simpl}_{clusters}.csv" ), output: - resources("pop_weighted_{kind}_totals{weather_year}_s{simpl}_{clusters}.csv"), + resources("pop_weighted_{kind}_totals_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, log: logs( - "build_population_weighted_{kind}_totals{weather_year}_s{simpl}_{clusters}.log" + "build_population_weighted_{kind}_totals_s{simpl}_{clusters}.log" ), conda: "../envs/environment.yaml" @@ -847,18 +847,18 @@ rule build_shipping_demand: ports="data/attributed_ports.json", scope=resources("europe_shape.geojson"), regions=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), demand=resources("energy_totals.csv"), params: energy_totals_year=config_provider("energy", "energy_totals_year"), output: - resources("shipping_demand{weather_year}_s{simpl}_{clusters}.csv"), + resources("shipping_demand_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, log: - logs("build_shipping_demand{weather_year}_s{simpl}_{clusters}.log"), + logs("build_shipping_demand_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -872,29 +872,29 @@ rule build_transport_demand: sector=config_provider("sector"), input: clustered_pop_layout=resources( - "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + "pop_layout_elec_s{simpl}_{clusters}.csv" ), pop_weighted_energy_totals=resources( - "pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv" + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" ), transport_data=resources("transport_data.csv"), traffic_data_KFZ="data/bundle-sector/emobility/KFZ__count", traffic_data_Pkw="data/bundle-sector/emobility/Pkw__count", temp_air_total=resources( - "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_air_total_elec_s{simpl}_{clusters}.nc" ), output: transport_demand=resources( - "transport_demand{weather_year}_s{simpl}_{clusters}.csv" + "transport_demand_s{simpl}_{clusters}.csv" ), - transport_data=resources("transport_data{weather_year}_s{simpl}_{clusters}.csv"), - avail_profile=resources("avail_profile{weather_year}_s{simpl}_{clusters}.csv"), - dsm_profile=resources("dsm_profile{weather_year}_s{simpl}_{clusters}.csv"), + transport_data=resources("transport_data_s{simpl}_{clusters}.csv"), + avail_profile=resources("avail_profile_s{simpl}_{clusters}.csv"), + dsm_profile=resources("dsm_profile_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, log: - logs("build_transport_demand{weather_year}_s{simpl}_{clusters}.log"), + logs("build_transport_demand_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -907,18 +907,18 @@ rule build_district_heat_share: input: district_heat_share=resources("district_heat_share.csv"), clustered_pop_layout=resources( - "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + "pop_layout_elec_s{simpl}_{clusters}.csv" ), output: district_heat_share=resources( - "district_heat_share_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), threads: 1 resources: mem_mb=1000, log: logs( - "build_district_heat_share{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log" + "build_district_heat_share_s{simpl}_{clusters}_{planning_horizons}.log" ), conda: "../envs/environment.yaml" @@ -934,28 +934,28 @@ rule build_existing_heating_distribution: input: existing_heating="data/existing_infrastructure/existing_heating_raw.csv", clustered_pop_layout=resources( - "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + "pop_layout_elec_s{simpl}_{clusters}.csv" ), clustered_pop_energy_layout=resources( - "pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv" + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" ), district_heat_share=resources( - "district_heat_share_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), output: existing_heating_distribution=resources( - "existing_heating_distribution_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), threads: 1 resources: mem_mb=2000, log: logs( - "build_existing_heating_distribution_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.log" + "build_existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.log" ), benchmark: benchmarks( - "build_existing_heating_distribution/elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}" + "build_existing_heating_distribution/elec_s{simpl}_{clusters}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -965,7 +965,7 @@ rule build_existing_heating_distribution: def input_profile_offwind(w): return { - f"profile_{tech}": resources(f"profile{{weather_year}}_{tech}.nc") + f"profile_{tech}": resources(f"profile{}_{tech}.nc") for tech in ["offwind-ac", "offwind-dc"] if (tech in config_provider("electricity", "renewable_carriers")(w)) } @@ -997,12 +997,12 @@ rule prepare_sector_network: **rules.cluster_gas_network.output, **rules.build_gas_input_locations.output, retro_cost=lambda w: ( - resources("retro_cost_elec{weather_year}_s{simpl}_{clusters}.csv") + resources("retro_cost_elec_s{simpl}_{clusters}.csv") if config_provider("sector", "retrofitting", "retro_endogen")(w) else [] ), floor_area=lambda w: ( - resources("floor_area_elec{weather_year}_s{simpl}_{clusters}.csv") + resources("floor_area_elec_s{simpl}_{clusters}.csv") if config_provider("sector", "retrofitting", "retro_endogen")(w) else [] ), @@ -1014,7 +1014,7 @@ rule prepare_sector_network: ), sequestration_potential=lambda w: ( resources( - "co2_sequestration_potential_elec{weather_year}_s{simpl}_{clusters}.csv" + "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv" ) if config_provider( "sector", "regional_co2_sequestration_potential", "enable" @@ -1022,35 +1022,35 @@ rule prepare_sector_network: else [] ), network=resources( - "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" ), energy_totals_name=resources("energy_totals.csv"), eurostat=input_eurostat, pop_weighted_energy_totals=resources( - "pop_weighted_energy_totals{weather_year}_s{simpl}_{clusters}.csv" + "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" ), pop_weighted_heat_totals=resources( - "pop_weighted_heat_totals{weather_year}_s{simpl}_{clusters}.csv" + "pop_weighted_heat_totals_s{simpl}_{clusters}.csv" ), shipping_demand=resources( - "shipping_demand{weather_year}_s{simpl}_{clusters}.csv" + "shipping_demand_s{simpl}_{clusters}.csv" ), transport_demand=resources( - "transport_demand{weather_year}_s{simpl}_{clusters}.csv" + "transport_demand_s{simpl}_{clusters}.csv" ), - transport_data=resources("transport_data{weather_year}_s{simpl}_{clusters}.csv"), - avail_profile=resources("avail_profile{weather_year}_s{simpl}_{clusters}.csv"), - dsm_profile=resources("dsm_profile{weather_year}_s{simpl}_{clusters}.csv"), + transport_data=resources("transport_data_s{simpl}_{clusters}.csv"), + avail_profile=resources("avail_profile_s{simpl}_{clusters}.csv"), + dsm_profile=resources("dsm_profile_s{simpl}_{clusters}.csv"), co2_totals_name=resources("co2_totals.csv"), co2="data/bundle-sector/eea/UNFCCC_v23.csv", biomass_potentials=lambda w: ( resources( - "biomass_potentials{weather_year}_s{simpl}_{clusters}_" + "biomass_potentials_s{simpl}_{clusters}_" + "{}.csv".format(config_provider("biomass", "year")(w)) ) if config_provider("foresight")(w) == "overnight" else resources( - "biomass_potentials{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv" ) ), costs=lambda w: ( @@ -1059,87 +1059,87 @@ rule prepare_sector_network: else resources("costs_{planning_horizons}.csv") ), h2_cavern=resources( - "salt_cavern_potentials{weather_year}_s{simpl}_{clusters}.csv" + "salt_cavern_potentials_s{simpl}_{clusters}.csv" ), - busmap_s=resources("busmap_elec{weather_year}_s{simpl}.csv"), - busmap=resources("busmap_elec{weather_year}_s{simpl}_{clusters}.csv"), + busmap_s=resources("busmap_elec_s{simpl}.csv"), + busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources( - "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + "pop_layout_elec_s{simpl}_{clusters}.csv" ), - simplified_pop_layout=resources("pop_layout_elec{weather_year}_s{simpl}.csv"), + simplified_pop_layout=resources("pop_layout_elec_s{simpl}.csv"), industrial_demand=resources( - "industrial_energy_demand_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), hourly_heat_demand_total=resources( - "hourly_heat_demand_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc" ), district_heat_share=resources( - "district_heat_share_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), temp_soil_total=resources( - "temp_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_soil_total_elec_s{simpl}_{clusters}.nc" ), temp_soil_rural=resources( - "temp_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_soil_rural_elec_s{simpl}_{clusters}.nc" ), temp_soil_urban=resources( - "temp_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_soil_urban_elec_s{simpl}_{clusters}.nc" ), temp_air_total=resources( - "temp_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_air_total_elec_s{simpl}_{clusters}.nc" ), temp_air_rural=resources( - "temp_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_air_rural_elec_s{simpl}_{clusters}.nc" ), temp_air_urban=resources( - "temp_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + "temp_air_urban_elec_s{simpl}_{clusters}.nc" ), cop_soil_total=resources( - "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_soil_total_elec_s{simpl}_{clusters}.nc" ), cop_soil_rural=resources( - "cop_soil_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_soil_rural_elec_s{simpl}_{clusters}.nc" ), cop_soil_urban=resources( - "cop_soil_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_soil_urban_elec_s{simpl}_{clusters}.nc" ), cop_air_total=resources( - "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_air_total_elec_s{simpl}_{clusters}.nc" ), cop_air_rural=resources( - "cop_air_rural_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_air_rural_elec_s{simpl}_{clusters}.nc" ), cop_air_urban=resources( - "cop_air_urban_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_air_urban_elec_s{simpl}_{clusters}.nc" ), solar_thermal_total=lambda w: ( - resources("solar_thermal_total_elec{weather_year}_s{simpl}_{clusters}.nc") + resources("solar_thermal_total_elec_s{simpl}_{clusters}.nc") if config_provider("sector", "solar_thermal")(w) else [] ), solar_thermal_urban=lambda w: ( - resources("solar_thermal_urban_elec{weather_year}_s{simpl}_{clusters}.nc") + resources("solar_thermal_urban_elec_s{simpl}_{clusters}.nc") if config_provider("sector", "solar_thermal")(w) else [] ), solar_thermal_rural=lambda w: ( - resources("solar_thermal_rural_elec{weather_year}_s{simpl}_{clusters}.nc") + resources("solar_thermal_rural_elec_s{simpl}_{clusters}.nc") if config_provider("sector", "solar_thermal")(w) else [] ), output: RESULTS - + "prenetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", threads: 1 resources: mem_mb=2000, log: RESULTS - + "logs/prepare_sector_network_elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + + "logs/prepare_sector_network_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: ( RESULTS - + "benchmarks/prepare_sector_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "benchmarks/prepare_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" diff --git a/rules/collect.smk b/rules/collect.smk index e31434f5..ef63df0f 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -16,7 +16,7 @@ localrules: rule cluster_networks: input: expand( - resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), + resources("networks/elec_s{simpl}_{clusters}.nc"), **config["scenario"], run=config["run"]["name"], ), @@ -25,7 +25,7 @@ rule cluster_networks: rule extra_components_networks: input: expand( - resources("networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc"), + resources("networks/elec_s{simpl}_{clusters}_ec.nc"), **config["scenario"], run=config["run"]["name"], ), @@ -35,7 +35,7 @@ rule prepare_elec_networks: input: expand( resources( - "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" ), **config["scenario"], run=config["run"]["name"], @@ -46,7 +46,7 @@ rule prepare_sector_networks: input: expand( RESULTS - + "prenetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", **config["scenario"], run=config["run"]["name"], ), @@ -56,7 +56,7 @@ rule solve_elec_networks: input: expand( RESULTS - + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config["scenario"], run=config["run"]["name"], ), @@ -66,7 +66,7 @@ rule solve_sector_networks: input: expand( RESULTS - + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", **config["scenario"], run=config["run"]["name"], ), @@ -76,7 +76,7 @@ rule solve_sector_networks_perfect: input: expand( RESULTS - + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", **config["scenario"], run=config["run"]["name"], ), @@ -86,13 +86,13 @@ rule validate_elec_networks: input: expand( RESULTS - + "figures/.statistics_plots_elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}", + + "figures/.statistics_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", **config["scenario"], run=config["run"]["name"], ), expand( RESULTS - + "figures/.validation_{kind}_plots_elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}", + + "figures/.validation_{kind}_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", **config["scenario"], run=config["run"]["name"], kind=["production", "prices", "cross_border"], diff --git a/rules/common.smk b/rules/common.smk index b298d743..618d746b 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -143,7 +143,7 @@ def solved_previous_horizon(w): return ( RESULTS - + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_" + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_" + planning_horizon_p + ".nc" ) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 67b71503..2eba1591 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -13,18 +13,18 @@ if config["foresight"] != "perfect": params: plotting=config_provider("plotting"), input: - network=resources("networks/elec{weather_year}_s{simpl}_{clusters}.nc"), + network=resources("networks/elec_s{simpl}_{clusters}.nc"), regions_onshore=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), output: - map=resources("maps/power-network{weather_year}-s{simpl}-{clusters}.pdf"), + map=resources("maps/power-network-s{simpl}-{clusters}.pdf"), threads: 1 resources: mem_mb=4000, benchmark: benchmarks( - "plot_power_network_clustered/elec{weather_year}_s{simpl}_{clusters}" + "plot_power_network_clustered/elec_s{simpl}_{clusters}" ) conda: "../envs/environment.yaml" @@ -36,23 +36,23 @@ if config["foresight"] != "perfect": plotting=config_provider("plotting"), input: network=RESULTS - + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", regions=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), output: map=RESULTS - + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", threads: 2 resources: mem_mb=10000, log: RESULTS - + "logs/plot_power_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + + "logs/plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: ( RESULTS - + "benchmarksplot_power_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "benchmarksplot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -65,23 +65,23 @@ if config["foresight"] != "perfect": foresight=config_provider("foresight"), input: network=RESULTS - + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", regions=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), output: map=RESULTS - + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", threads: 2 resources: mem_mb=10000, log: RESULTS - + "logs/plot_hydrogen_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + + "logs/plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: ( RESULTS - + "benchmarks/plot_hydrogen_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "benchmarks/plot_hydrogen_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -93,23 +93,23 @@ if config["foresight"] != "perfect": plotting=config_provider("plotting"), input: network=RESULTS - + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", regions=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), output: map=RESULTS - + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", threads: 2 resources: mem_mb=10000, log: RESULTS - + "logs/plot_gas_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + + "logs/plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: ( RESULTS - + "benchmarks/plot_gas_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "benchmarks/plot_gas_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -122,7 +122,7 @@ if config["foresight"] == "perfect": def output_map_year(w): return { f"map_{year}": RESULTS - + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_" + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_" + f"{year}.pdf" for year in config_provider("scenario", "planning_horizons")(w) } @@ -132,9 +132,9 @@ if config["foresight"] == "perfect": plotting=config_provider("plotting"), input: network=RESULTS - + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", regions=resources( - "regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson" + "regions_onshore_elec_s{simpl}_{clusters}.geojson" ), output: unpack(output_map_year), @@ -171,7 +171,7 @@ rule make_summary: input: networks=expand( RESULTS - + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", **config["scenario"], allow_missing=True, ), @@ -185,20 +185,20 @@ rule make_summary: ) ), ac_plot=expand( - resources("maps/power-network{weather_year}-s{simpl}-{clusters}.pdf"), + resources("maps/power-network-s{simpl}-{clusters}.pdf"), **config["scenario"], allow_missing=True, ), costs_plot=expand( RESULTS - + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", **config["scenario"], allow_missing=True, ), h2_plot=lambda w: expand( ( RESULTS - + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf" + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf" if config_provider("sector", "H2_network")(w) else [] ), @@ -208,7 +208,7 @@ rule make_summary: ch4_plot=lambda w: expand( ( RESULTS - + "maps/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf" + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf" if config_provider("sector", "gas_network")(w) else [] ), @@ -293,14 +293,14 @@ rule plot_elec_statistics: barplots=STATISTICS_BARPLOTS, input: network=RESULTS - + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", output: **{ f"{plot}_bar": RESULTS - + f"figures/statistics_{plot}_bar_elec{{weather_year}}_s{{simpl}}_{{clusters}}_ec_l{{ll}}_{{opts}}.pdf" + + f"figures/statistics_{plot}_bar_elec{}_s{{simpl}}_{{clusters}}_ec_l{{ll}}_{{opts}}.pdf" for plot in STATISTICS_BARPLOTS }, barplots_touch=RESULTS - + "figures/.statistics_plots_elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}", + + "figures/.statistics_plots_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}", script: "../scripts/plot_statistics.py" diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index c69dfb88..5c6777d4 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -14,23 +14,23 @@ rule solve_network: custom_extra_functionality=input_custom_extra_functionality, input: network=resources( - "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" ), config=RESULTS + "config.yaml", output: network=RESULTS - + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", log: solver=normpath( RESULTS - + "logs/solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log" + + "logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_solver.log" ), python=RESULTS - + "logs/solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", + + "logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", benchmark: ( RESULTS - + "benchmarks/solve_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + + "benchmarks/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" ) threads: solver_threads resources: @@ -49,21 +49,21 @@ rule solve_operations_network: options=config_provider("solving", "options"), input: network=RESULTS - + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", output: network=RESULTS - + "networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc", + + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc", log: solver=normpath( RESULTS - + "logs/solve_operations_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log" + + "logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_solver.log" ), python=RESULTS - + "logs/solve_operations_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log", + + "logs/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op_python.log", benchmark: ( RESULTS - + "benchmarks/solve_operations_network/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}" + + "benchmarks/solve_operations_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" ) threads: 4 resources: diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index da31ac46..eae1d990 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -11,12 +11,12 @@ rule add_existing_baseyear: costs=config_provider("costs"), input: network=RESULTS - + "prenetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", powerplants=resources("powerplants.csv"), - busmap_s=resources("busmap_elec{weather_year}_s{simpl}.csv"), - busmap=resources("busmap_elec{weather_year}_s{simpl}_{clusters}.csv"), + busmap_s=resources("busmap_elec_s{simpl}.csv"), + busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), clustered_pop_layout=resources( - "pop_layout_elec{weather_year}_s{simpl}_{clusters}.csv" + "pop_layout_elec_s{simpl}_{clusters}.csv" ), costs=lambda w: resources( "costs_{}.csv".format( @@ -24,20 +24,20 @@ rule add_existing_baseyear: ) ), cop_soil_total=resources( - "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_soil_total_elec_s{simpl}_{clusters}.nc" ), cop_air_total=resources( - "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_air_total_elec_s{simpl}_{clusters}.nc" ), existing_heating_distribution=resources( - "existing_heating_distribution_elec{weather_year}_s{simpl}_{clusters}_{planning_horizons}.csv" + "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", existing_offwind="data/existing_infrastructure/offwind_capacity_IRENA.csv", output: RESULTS - + "prenetworks-brownfield/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", wildcard_constraints: # TODO: The first planning_horizon needs to be aligned across scenarios # snakemake does not support passing functions to wildcard_constraints @@ -48,11 +48,11 @@ rule add_existing_baseyear: mem_mb=2000, log: RESULTS - + "logs/add_existing_baseyear_elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + + "logs/add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: ( RESULTS - + "benchmarks/add_existing_baseyear/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "benchmarks/add_existing_baseyear/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -79,31 +79,31 @@ rule add_brownfield: carriers=config_provider("electricity", "renewable_carriers"), input: unpack(input_profile_tech_brownfield), - simplify_busmap=resources("busmap_elec{weather_year}_s{simpl}.csv"), - cluster_busmap=resources("busmap_elec{weather_year}_s{simpl}_{clusters}.csv"), + simplify_busmap=resources("busmap_elec_s{simpl}.csv"), + cluster_busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), network=RESULTS - + "prenetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", network_p=solved_previous_horizon, #solved network at previous time step costs=resources("costs_{planning_horizons}.csv"), cop_soil_total=resources( - "cop_soil_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_soil_total_elec_s{simpl}_{clusters}.nc" ), cop_air_total=resources( - "cop_air_total_elec{weather_year}_s{simpl}_{clusters}.nc" + "cop_air_total_elec_s{simpl}_{clusters}.nc" ), output: RESULTS - + "prenetworks-brownfield/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", threads: 4 resources: mem_mb=10000, log: RESULTS - + "logs/add_brownfield_elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", + + "logs/add_brownfield_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log", benchmark: ( RESULTS - + "benchmarks/add_brownfield/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "benchmarks/add_brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" @@ -125,19 +125,19 @@ rule solve_sector_network_myopic: custom_extra_functionality=input_custom_extra_functionality, input: network=RESULTS - + "prenetworks-brownfield/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", costs=resources("costs_{planning_horizons}.csv"), config=RESULTS + "config.yaml", output: RESULTS - + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", shadow: "shallow" log: solver=RESULTS - + "logs/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_solver.log", + + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_solver.log", python=RESULTS - + "logs/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", + + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", threads: solver_threads resources: mem_mb=config_provider("solving", "mem"), @@ -145,7 +145,7 @@ rule solve_sector_network_myopic: benchmark: ( RESULTS - + "benchmarks/solve_sector_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "benchmarks/solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index 21fce682..b212d453 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -14,20 +14,20 @@ rule solve_sector_network: custom_extra_functionality=input_custom_extra_functionality, input: network=RESULTS - + "prenetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", config=RESULTS + "config.yaml", output: RESULTS - + "postnetworks/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", shadow: "shallow" log: solver=RESULTS - + "logs/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_solver.log", + + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_solver.log", memory=RESULTS - + "logs/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_memory.log", + + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_memory.log", python=RESULTS - + "logs/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", + + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", threads: solver_threads resources: mem_mb=config_provider("solving", "mem"), @@ -35,7 +35,7 @@ rule solve_sector_network: benchmark: ( RESULTS - + "benchmarks/solve_sector_network/elec{weather_year}_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "benchmarks/solve_sector_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index c33012cd..1e175d87 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -206,7 +206,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "add_brownfield", - weather_year="", simpl="", clusters="37", opts="", diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index f997d852..91fc04ea 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -797,7 +797,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("add_electricity", weather_year="") + snakemake = mock_snakemake("add_electricity") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 43d287cd..de3c10f0 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -553,7 +553,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "add_existing_baseyear", - weather_year="", configfiles="config/test/config.myopic.yaml", simpl="", clusters="37", diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index 464b5f9f..9e3f9772 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -38,13 +38,13 @@ Inputs Outputs ------- -- ``networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc``: +- ``networks/elec_s{simpl}_{clusters}_ec.nc``: Description ----------- -The rule :mod:`add_extra_components` attaches additional extendable components to the clustered and simplified network. These can be configured in the ``config/config.yaml`` at ``electricity: extendable_carriers:``. It processes ``networks/elec{weather_year}_s{simpl}_{clusters}.nc`` to build ``networks/elec{weather_year}_s{simpl}_{clusters}_ec.nc``, which in contrast to the former (depending on the configuration) contain with **zero** initial capacity +The rule :mod:`add_extra_components` attaches additional extendable components to the clustered and simplified network. These can be configured in the ``config/config.yaml`` at ``electricity: extendable_carriers:``. It processes ``networks/elec_s{simpl}_{clusters}.nc`` to build ``networks/elec_s{simpl}_{clusters}_ec.nc``, which in contrast to the former (depending on the configuration) contain with **zero** initial capacity - ``StorageUnits`` of carrier 'H2' and/or 'battery'. If this option is chosen, every bus is given an extendable ``StorageUnit`` of the corresponding carrier. The energy and power capacities are linked through a parameter that specifies the energy capacity as maximum hours at full dispatch power and is configured in ``electricity: max_hours:``. This linkage leads to one investment variable per storage unit. The default ``max_hours`` lead to long-term hydrogen and short-term battery storage units. @@ -229,7 +229,7 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "add_extra_components", weather_year="", simpl="", clusters=5 + "add_extra_components", simpl="", clusters=5 ) configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/build_artificial_load_data.py b/scripts/build_artificial_load_data.py index 7703ff28..51c07291 100755 --- a/scripts/build_artificial_load_data.py +++ b/scripts/build_artificial_load_data.py @@ -16,7 +16,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_artificial_load_data", weather_year="") + snakemake = mock_snakemake("build_artificial_load_data") configure_logging(snakemake) diff --git a/scripts/build_biomass_potentials.py b/scripts/build_biomass_potentials.py index 3f8c35a8..79e2c203 100644 --- a/scripts/build_biomass_potentials.py +++ b/scripts/build_biomass_potentials.py @@ -218,7 +218,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_biomass_potentials", - weather_year="", simpl="", clusters="5", planning_horizons=2050, diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index d4cfb96d..5ec60349 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -19,7 +19,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_clustered_population_layouts", - weather_year="", simpl="", clusters=48, ) diff --git a/scripts/build_cop_profiles.py b/scripts/build_cop_profiles.py index af678978..16e44c18 100644 --- a/scripts/build_cop_profiles.py +++ b/scripts/build_cop_profiles.py @@ -32,7 +32,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_cop_profiles", - weather_year="", simpl="", clusters=48, ) diff --git a/scripts/build_daily_heat_demand.py b/scripts/build_daily_heat_demand.py index 8fe946a5..0ba47771 100644 --- a/scripts/build_daily_heat_demand.py +++ b/scripts/build_daily_heat_demand.py @@ -21,7 +21,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_daily_heat_demands", scope="total", - weather_year="", simpl="", clusters=48, ) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 90454700..4328b842 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -258,7 +258,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_electricity_demand", weather_year="") + snakemake = mock_snakemake("build_electricity_demand") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/build_industrial_distribution_key.py b/scripts/build_industrial_distribution_key.py index e2461a7c..7cba0af5 100644 --- a/scripts/build_industrial_distribution_key.py +++ b/scripts/build_industrial_distribution_key.py @@ -146,7 +146,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_industrial_distribution_key", - weather_year="", simpl="", clusters=128, ) diff --git a/scripts/build_industrial_energy_demand_per_node_today.py b/scripts/build_industrial_energy_demand_per_node_today.py index ebfe562f..8b2b70a0 100644 --- a/scripts/build_industrial_energy_demand_per_node_today.py +++ b/scripts/build_industrial_energy_demand_per_node_today.py @@ -73,7 +73,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_industrial_energy_demand_per_node_today", - weather_year="", simpl="", clusters=48, ) diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index 6552eeb2..64e70366 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -23,7 +23,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_population_layouts", - weather_year="", ) configure_logging(snakemake) diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 0cb3e61e..bf4a6118 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -15,7 +15,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_population_weighted_energy_totals", - weather_year="", simpl="", clusters=48, ) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index d31c13f0..3380a947 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -201,7 +201,7 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "build_renewable_profiles", technology="offwind-dc", weather_year="" + "build_renewable_profiles", technology="offwind-dc" ) configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index db56a401..dc921ff5 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -20,7 +20,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_solar_thermal_profiles", - weather_year="", simpl="", clusters=48, ) diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index fc13893f..9a64801f 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -167,7 +167,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_transport_demand", - weather_year="", simpl="", clusters=48, ) diff --git a/scripts/cluster_gas_network.py b/scripts/cluster_gas_network.py index fd335cd3..19585aa9 100755 --- a/scripts/cluster_gas_network.py +++ b/scripts/cluster_gas_network.py @@ -105,7 +105,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("cluster_gas_network", weather_year="", simpl="", clusters="37") + snakemake = mock_snakemake("cluster_gas_network", simpl="", clusters="37") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 8ba3e7b3..5682c337 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -32,28 +32,28 @@ Relevant Settings Inputs ------ -- ``resources/regions_onshore_elec{weather_year}_s{simpl}.geojson``: confer :ref:`simplify` -- ``resources/regions_offshore_elec{weather_year}_s{simpl}.geojson``: confer :ref:`simplify` -- ``networks/elec{weather_year}_s{simpl}.nc``: confer :ref:`simplify` -- ``resources/busmap_elec{weather_year}_s{simpl}.csv``: confer :ref:`simplify` -- ``data/custom_busmap_elec{weather_year}_s{simpl}_{clusters}.csv``: optional input +- ``resources/regions_onshore_elec_s{simpl}.geojson``: confer :ref:`simplify` +- ``resources/regions_offshore_elec_s{simpl}.geojson``: confer :ref:`simplify` +- ``networks/elec_s{simpl}.nc``: confer :ref:`simplify` +- ``resources/busmap_elec_s{simpl}.csv``: confer :ref:`simplify` +- ``data/custom_busmap_elec_s{simpl}_{clusters}.csv``: optional input Outputs ------- -- ``resources/regions_onshore_elec{weather_year}_s{simpl}_{clusters}.geojson``: +- ``resources/regions_onshore_elec_s{simpl}_{clusters}.geojson``: .. image:: img/regions_onshore_elec_s_X.png :scale: 33 % -- ``resources/regions_offshore_elec{weather_year}_s{simpl}_{clusters}.geojson``: +- ``resources/regions_offshore_elec_s{simpl}_{clusters}.geojson``: .. image:: img/regions_offshore_elec_s_X.png :scale: 33 % -- ``resources/busmap_elec{weather_year}_s{simpl}_{clusters}.csv``: Mapping of buses from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; -- ``resources/linemap{weather_year}_elec_s{simpl}_{clusters}.csv``: Mapping of lines from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; -- ``networks/elec{weather_year}_s{simpl}_{clusters}.nc``: +- ``resources/busmap_elec_s{simpl}_{clusters}.csv``: Mapping of buses from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; +- ``resources/linemap_elec_s{simpl}_{clusters}.csv``: Mapping of lines from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; +- ``networks/elec_s{simpl}_{clusters}.nc``: .. image:: img/elec_s_X.png :scale: 40 % @@ -455,7 +455,7 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "cluster_network", simpl="", clusters="5", weather_year="" + "cluster_network", simpl="", clusters="5", ) configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 67089f92..27ce91d3 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -646,7 +646,7 @@ def make_summaries(networks_dict): columns = pd.MultiIndex.from_tuples( networks_dict.keys(), - names=["weather_year", "cluster", "ll", "opt", "planning_horizon"], + names=["cluster", "ll", "opt", "planning_horizon"], ) df = {output: pd.DataFrame(columns=columns, dtype=float) for output in outputs} @@ -679,10 +679,9 @@ if __name__ == "__main__": set_scenario_config(snakemake) networks_dict = { - (weather_year, cluster, ll, opt + sector_opt, planning_horizon): "results/" + (cluster, ll, opt + sector_opt, planning_horizon): "results/" + snakemake.params.RDIR - + f"postnetworks/elec{weather_year}_s{simpl}_{cluster}_l{ll}_{opt}_{sector_opt}_{planning_horizon}.nc" - for weather_year in snakemake.params.scenario["weather_year"] + + f"postnetworks/elec_s{simpl}_{cluster}_l{ll}_{opt}_{sector_opt}_{planning_horizon}.nc" for simpl in snakemake.params.scenario["simpl"] for cluster in snakemake.params.scenario["clusters"] for opt in snakemake.params.scenario["opts"] diff --git a/scripts/prepare_links_p_nom.py b/scripts/prepare_links_p_nom.py index 627122e7..7c1ed211 100644 --- a/scripts/prepare_links_p_nom.py +++ b/scripts/prepare_links_p_nom.py @@ -67,7 +67,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake # rule must be enabled in config - snakemake = mock_snakemake("prepare_links_p_nom", simpl="", weather_year="") + snakemake = mock_snakemake("prepare_links_p_nom", simpl="") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 928fa577..f38a3619 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -41,12 +41,12 @@ Inputs ------ - ``resources/costs.csv``: The database of cost assumptions for all included technologies for specific years from various sources; e.g. discount rate, lifetime, investment (CAPEX), fixed operation and maintenance (FOM), variable operation and maintenance (VOM), fuel costs, efficiency, carbon-dioxide intensity. -- ``networks/elec{weather_year}_s{simpl}_{clusters}.nc``: confer :ref:`cluster` +- ``networks/elec_s{simpl}_{clusters}.nc``: confer :ref:`cluster` Outputs ------- -- ``networks/elec{weather_year}_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Complete PyPSA network that will be handed to the ``solve_network`` rule. +- ``networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc``: Complete PyPSA network that will be handed to the ``solve_network`` rule. Description ----------- @@ -305,7 +305,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "prepare_network", - weather_year="", simpl="", clusters="37", ll="v1.0", diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 6ca06c9a..3a1158b9 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3584,7 +3584,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "prepare_sector_network", configfiles="test/config.overnight.yaml", - weather_year="", simpl="", opts="", clusters="37", diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 5a4c792e..4de17704 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -55,18 +55,18 @@ Inputs Outputs ------- -- ``resources/regions_onshore_elec{weather_year}_s{simpl}.geojson``: +- ``resources/regions_onshore_elec_s{simpl}.geojson``: .. image:: img/regions_onshore_elec_s.png :scale: 33 % -- ``resources/regions_offshore_elec{weather_year}_s{simpl}.geojson``: +- ``resources/regions_offshore_elec_s{simpl}.geojson``: .. image:: img/regions_offshore_elec_s .png :scale: 33 % -- ``resources/busmap_elec{weather_year}_s{simpl}.h5``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec{weather_year}_s{simpl}.nc``; has keys ['/busmap_s'] -- ``networks/elec{weather_year}_s{simpl}.nc``: +- ``resources/busmap_elec_s{simpl}.h5``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec_s{simpl}.nc``; has keys ['/busmap_s'] +- ``networks/elec_s{simpl}.nc``: .. image:: img/elec_s.png :scale: 33 % @@ -527,7 +527,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("simplify_network", weather_year="", simpl="") + snakemake = mock_snakemake("simplify_network", simpl="") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index aed78824..7e53e606 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -929,7 +929,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "solve_sector_network", configfiles="../config/test/config.perfect.yaml", - weather_year="", simpl="", opts="", clusters="37", diff --git a/scripts/solve_operations_network.py b/scripts/solve_operations_network.py index fdc2feb6..bd4ce7aa 100644 --- a/scripts/solve_operations_network.py +++ b/scripts/solve_operations_network.py @@ -29,7 +29,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "solve_operations_network", configfiles="test/config.electricity.yaml", - weather_year="", simpl="", opts="", clusters="5", From 030e5b15ade0adf593609e6698c45038888e6492 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 4 Mar 2024 17:51:32 +0100 Subject: [PATCH 398/591] remove rule build_cutout_year --- rules/build_electricity.smk | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 53c2df0b..ab7b1913 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -165,8 +165,6 @@ rule build_bus_regions: if config["enable"].get("build_cutout", False): - ruleorder: build_cutout_year > build_cutout - rule build_cutout: params: snapshots=config_provider("snapshots"), @@ -188,23 +186,6 @@ if config["enable"].get("build_cutout", False): script: "../scripts/build_cutout.py" - rule build_cutout_year: - input: - rules.build_cutout.input, - output: - protected("cutouts/" + CDIR + "{cutout}-.nc"), - log: - logs(CDIR + "build_cutout/{cutout}-.log"), - benchmark: - benchmarks(CDIR + "build_cutout_{cutout}-") - threads: ATLITE_NPROCESSES - resources: - mem_mb=ATLITE_NPROCESSES * 1000, - conda: - "../envs/environment.yaml" - script: - "../scripts/build_cutout.py" - if config["enable"].get("build_natura_raster", False): From 7b584f16bbb467f24ac44bba7fbdd497581f2394 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:55:57 +0000 Subject: [PATCH 399/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_sector.smk | 296 +++++++--------------------- rules/solve_myopic.smk | 20 +- scripts/add_extra_components.py | 4 +- scripts/build_renewable_profiles.py | 4 +- scripts/cluster_network.py | 4 +- 5 files changed, 84 insertions(+), 244 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index ab296565..686bb9a1 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -33,25 +33,19 @@ rule build_clustered_population_layouts: pop_layout_total=resources("pop_layout_total.nc"), pop_layout_urban=resources("pop_layout_urban.nc"), pop_layout_rural=resources("pop_layout_rural.nc"), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), cutout=lambda w: "cutouts/" + CDIR + config_provider("atlite", "default_cutout")(w) + ".nc", output: - clustered_pop_layout=resources( - "pop_layout_elec_s{simpl}_{clusters}.csv" - ), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), log: logs("build_clustered_population_layouts_{simpl}_{clusters}.log"), resources: mem_mb=10000, benchmark: - benchmarks( - "build_clustered_population_layouts/s{simpl}_{clusters}" - ) + benchmarks("build_clustered_population_layouts/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -105,16 +99,10 @@ rule build_gas_input_locations: ), entry="data/gas_network/scigrid-gas/data/IGGIELGN_BorderPoints.geojson", storage="data/gas_network/scigrid-gas/data/IGGIELGN_Storages.geojson", - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), output: - gas_input_nodes=resources( - "gas_input_locations_s{simpl}_{clusters}.geojson" - ), + gas_input_nodes=resources("gas_input_locations_s{simpl}_{clusters}.geojson"), gas_input_nodes_simplified=resources( "gas_input_locations_s{simpl}_{clusters}_simplified.csv" ), @@ -131,16 +119,10 @@ rule build_gas_input_locations: rule cluster_gas_network: input: cleaned_gas_network=resources("gas_network.csv"), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), output: - clustered_gas_network=resources( - "gas_network_elec_s{simpl}_{clusters}.csv" - ), + clustered_gas_network=resources("gas_network_elec_s{simpl}_{clusters}.csv"), resources: mem_mb=4000, log: @@ -170,14 +152,10 @@ rule build_daily_heat_demand: drop_leap_day=config_provider("enable", "drop_leap_day"), input: pop_layout=resources("pop_layout_{scope}.nc"), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), cutout=heat_demand_cutout, output: - heat_demand=resources( - "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc" - ), + heat_demand=resources("daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, threads: 8 @@ -197,13 +175,9 @@ rule build_hourly_heat_demand: drop_leap_day=config_provider("enable", "drop_leap_day"), input: heat_profile="data/heat_load_profile_BDEW.csv", - heat_demand=resources( - "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc" - ), + heat_demand=resources("daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), output: - heat_demand=resources( - "hourly_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc" - ), + heat_demand=resources("hourly_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=2000, threads: 8 @@ -223,14 +197,10 @@ rule build_temperature_profiles: drop_leap_day=config_provider("enable", "drop_leap_day"), input: pop_layout=resources("pop_layout_{scope}.nc"), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), cutout=heat_demand_cutout, output: - temp_soil=resources( - "temp_soil_{scope}_elec_s{simpl}_{clusters}.nc" - ), + temp_soil=resources("temp_soil_{scope}_elec_s{simpl}_{clusters}.nc"), temp_air=resources("temp_air_{scope}_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, @@ -238,9 +208,7 @@ rule build_temperature_profiles: log: logs("build_temperature_profiles_{scope}__{simpl}_{clusters}.log"), benchmark: - benchmarks( - "build_temperature_profiles/{scope}__s{simpl}_{clusters}" - ) + benchmarks("build_temperature_profiles/{scope}__s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -251,43 +219,19 @@ rule build_cop_profiles: params: heat_pump_sink_T=config_provider("sector", "heat_pump_sink_T"), input: - temp_soil_total=resources( - "temp_soil_total_elec_s{simpl}_{clusters}.nc" - ), - temp_soil_rural=resources( - "temp_soil_rural_elec_s{simpl}_{clusters}.nc" - ), - temp_soil_urban=resources( - "temp_soil_urban_elec_s{simpl}_{clusters}.nc" - ), - temp_air_total=resources( - "temp_air_total_elec_s{simpl}_{clusters}.nc" - ), - temp_air_rural=resources( - "temp_air_rural_elec_s{simpl}_{clusters}.nc" - ), - temp_air_urban=resources( - "temp_air_urban_elec_s{simpl}_{clusters}.nc" - ), + temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"), + temp_soil_rural=resources("temp_soil_rural_elec_s{simpl}_{clusters}.nc"), + temp_soil_urban=resources("temp_soil_urban_elec_s{simpl}_{clusters}.nc"), + temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), + temp_air_rural=resources("temp_air_rural_elec_s{simpl}_{clusters}.nc"), + temp_air_urban=resources("temp_air_urban_elec_s{simpl}_{clusters}.nc"), output: - cop_soil_total=resources( - "cop_soil_total_elec_s{simpl}_{clusters}.nc" - ), - cop_soil_rural=resources( - "cop_soil_rural_elec_s{simpl}_{clusters}.nc" - ), - cop_soil_urban=resources( - "cop_soil_urban_elec_s{simpl}_{clusters}.nc" - ), - cop_air_total=resources( - "cop_air_total_elec_s{simpl}_{clusters}.nc" - ), - cop_air_rural=resources( - "cop_air_rural_elec_s{simpl}_{clusters}.nc" - ), - cop_air_urban=resources( - "cop_air_urban_elec_s{simpl}_{clusters}.nc" - ), + cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), + cop_soil_rural=resources("cop_soil_rural_elec_s{simpl}_{clusters}.nc"), + cop_soil_urban=resources("cop_soil_urban_elec_s{simpl}_{clusters}.nc"), + cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), + cop_air_rural=resources("cop_air_rural_elec_s{simpl}_{clusters}.nc"), + cop_air_urban=resources("cop_air_urban_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, log: @@ -320,25 +264,17 @@ rule build_solar_thermal_profiles: solar_thermal=config_provider("solar_thermal"), input: pop_layout=resources("pop_layout_{scope}.nc"), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), cutout=solar_thermal_cutout, output: - solar_thermal=resources( - "solar_thermal_{scope}_elec_s{simpl}_{clusters}.nc" - ), + solar_thermal=resources("solar_thermal_{scope}_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, threads: 16 log: - logs( - "build_solar_thermal_profiles_{scope}__s{simpl}_{clusters}.log" - ), + logs("build_solar_thermal_profiles_{scope}__s{simpl}_{clusters}.log"), benchmark: - benchmarks( - "build_solar_thermal_profiles/{scope}__s{simpl}_{clusters}" - ) + benchmarks("build_solar_thermal_profiles/{scope}__s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -402,9 +338,7 @@ rule build_biomass_potentials: keep_local=True, ), nuts2="data/bundle-sector/nuts/NUTS_RG_10M_2013_4326_LEVL_2.geojson", # https://gisco-services.ec.europa.eu/distribution/v2/nuts/download/#nuts21 - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), nuts3_population=ancient("data/bundle/nama_10r_3popgdp.tsv.gz"), swiss_cantons=ancient("data/bundle/ch_cantons.csv"), swiss_population=ancient("data/bundle/je-e-21.03.02.xls"), @@ -420,13 +354,9 @@ rule build_biomass_potentials: resources: mem_mb=1000, log: - logs( - "build_biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.log" - ), + logs("build_biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.log"), benchmark: - benchmarks( - "build_biomass_potentials_s{simpl}_{clusters}_{planning_horizons}" - ) + benchmarks("build_biomass_potentials_s{simpl}_{clusters}_{planning_horizons}") conda: "../envs/environment.yaml" script: @@ -464,12 +394,8 @@ rule build_sequestration_potentials: "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", keep_local=True, ), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), output: sequestration_potential=resources( "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv" @@ -490,16 +416,10 @@ rule build_sequestration_potentials: rule build_salt_cavern_potentials: input: salt_caverns="data/bundle-sector/h2_salt_caverns_GWh_per_sqkm.geojson", - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), output: - h2_cavern_potential=resources( - "salt_cavern_potentials_s{simpl}_{clusters}.csv" - ), + h2_cavern_potential=resources("salt_cavern_potentials_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, @@ -641,12 +561,8 @@ rule build_industrial_distribution_key: ), countries=config_provider("countries"), input: - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), - clustered_pop_layout=resources( - "pop_layout_elec_s{simpl}_{clusters}.csv" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), hotmaps_industrial_database="data/bundle-sector/Industrial_Database.csv", output: industrial_distribution_key=resources( @@ -658,9 +574,7 @@ rule build_industrial_distribution_key: log: logs("build_industrial_distribution_key_s{simpl}_{clusters}.log"), benchmark: - benchmarks( - "build_industrial_distribution_key/s{simpl}_{clusters}" - ) + benchmarks("build_industrial_distribution_key/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -774,13 +688,9 @@ rule build_industrial_energy_demand_per_node_today: resources: mem_mb=1000, log: - logs( - "build_industrial_energy_demand_per_node_today_s{simpl}_{clusters}.log" - ), + logs("build_industrial_energy_demand_per_node_today_s{simpl}_{clusters}.log"), benchmark: - benchmarks( - "build_industrial_energy_demand_per_node_today/s{simpl}_{clusters}" - ) + benchmarks("build_industrial_energy_demand_per_node_today/s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -794,16 +704,12 @@ rule build_retro_cost: input: building_stock="data/retro/data_building_stock.csv", data_tabula="data/bundle-sector/retro/tabula-calculator-calcsetbuilding.csv", - air_temperature=resources( - "temp_air_total_elec_s{simpl}_{clusters}.nc" - ), + air_temperature=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), u_values_PL="data/retro/u_values_poland.csv", tax_w="data/retro/electricity_taxes_eu.csv", construction_index="data/retro/comparative_level_investment.csv", floor_area_missing="data/retro/floor_area_missing.csv", - clustered_pop_layout=resources( - "pop_layout_elec_s{simpl}_{clusters}.csv" - ), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), cost_germany="data/retro/retro_cost_germany.csv", window_assumptions="data/retro/window_assumptions.csv", output: @@ -824,18 +730,14 @@ rule build_retro_cost: rule build_population_weighted_energy_totals: input: energy_totals=resources("{kind}_totals.csv"), - clustered_pop_layout=resources( - "pop_layout_elec_s{simpl}_{clusters}.csv" - ), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), output: resources("pop_weighted_{kind}_totals_s{simpl}_{clusters}.csv"), threads: 1 resources: mem_mb=2000, log: - logs( - "build_population_weighted_{kind}_totals_s{simpl}_{clusters}.log" - ), + logs("build_population_weighted_{kind}_totals_s{simpl}_{clusters}.log"), conda: "../envs/environment.yaml" script: @@ -846,9 +748,7 @@ rule build_shipping_demand: input: ports="data/attributed_ports.json", scope=resources("europe_shape.geojson"), - regions=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), demand=resources("energy_totals.csv"), params: energy_totals_year=config_provider("energy", "energy_totals_year"), @@ -871,22 +771,16 @@ rule build_transport_demand: drop_leap_day=config_provider("enable", "drop_leap_day"), sector=config_provider("sector"), input: - clustered_pop_layout=resources( - "pop_layout_elec_s{simpl}_{clusters}.csv" - ), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), pop_weighted_energy_totals=resources( "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" ), transport_data=resources("transport_data.csv"), traffic_data_KFZ="data/bundle-sector/emobility/KFZ__count", traffic_data_Pkw="data/bundle-sector/emobility/Pkw__count", - temp_air_total=resources( - "temp_air_total_elec_s{simpl}_{clusters}.nc" - ), + temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), output: - transport_demand=resources( - "transport_demand_s{simpl}_{clusters}.csv" - ), + transport_demand=resources("transport_demand_s{simpl}_{clusters}.csv"), transport_data=resources("transport_data_s{simpl}_{clusters}.csv"), avail_profile=resources("avail_profile_s{simpl}_{clusters}.csv"), dsm_profile=resources("dsm_profile_s{simpl}_{clusters}.csv"), @@ -906,9 +800,7 @@ rule build_district_heat_share: sector=config_provider("sector"), input: district_heat_share=resources("district_heat_share.csv"), - clustered_pop_layout=resources( - "pop_layout_elec_s{simpl}_{clusters}.csv" - ), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), output: district_heat_share=resources( "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv" @@ -917,9 +809,7 @@ rule build_district_heat_share: resources: mem_mb=1000, log: - logs( - "build_district_heat_share_s{simpl}_{clusters}_{planning_horizons}.log" - ), + logs("build_district_heat_share_s{simpl}_{clusters}_{planning_horizons}.log"), conda: "../envs/environment.yaml" script: @@ -933,9 +823,7 @@ rule build_existing_heating_distribution: existing_capacities=config_provider("existing_capacities"), input: existing_heating="data/existing_infrastructure/existing_heating_raw.csv", - clustered_pop_layout=resources( - "pop_layout_elec_s{simpl}_{clusters}.csv" - ), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), clustered_pop_energy_layout=resources( "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" ), @@ -1013,17 +901,13 @@ rule prepare_sector_network: else [] ), sequestration_potential=lambda w: ( - resources( - "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv" - ) + resources("co2_sequestration_potential_elec_s{simpl}_{clusters}.csv") if config_provider( "sector", "regional_co2_sequestration_potential", "enable" )(w) else [] ), - network=resources( - "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - ), + network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), energy_totals_name=resources("energy_totals.csv"), eurostat=input_eurostat, pop_weighted_energy_totals=resources( @@ -1032,12 +916,8 @@ rule prepare_sector_network: pop_weighted_heat_totals=resources( "pop_weighted_heat_totals_s{simpl}_{clusters}.csv" ), - shipping_demand=resources( - "shipping_demand_s{simpl}_{clusters}.csv" - ), - transport_demand=resources( - "transport_demand_s{simpl}_{clusters}.csv" - ), + shipping_demand=resources("shipping_demand_s{simpl}_{clusters}.csv"), + transport_demand=resources("transport_demand_s{simpl}_{clusters}.csv"), transport_data=resources("transport_data_s{simpl}_{clusters}.csv"), avail_profile=resources("avail_profile_s{simpl}_{clusters}.csv"), dsm_profile=resources("dsm_profile_s{simpl}_{clusters}.csv"), @@ -1058,14 +938,10 @@ rule prepare_sector_network: if config_provider("foresight")(w) == "overnight" else resources("costs_{planning_horizons}.csv") ), - h2_cavern=resources( - "salt_cavern_potentials_s{simpl}_{clusters}.csv" - ), + h2_cavern=resources("salt_cavern_potentials_s{simpl}_{clusters}.csv"), busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), - clustered_pop_layout=resources( - "pop_layout_elec_s{simpl}_{clusters}.csv" - ), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), simplified_pop_layout=resources("pop_layout_elec_s{simpl}.csv"), industrial_demand=resources( "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv" @@ -1076,42 +952,18 @@ rule prepare_sector_network: district_heat_share=resources( "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), - temp_soil_total=resources( - "temp_soil_total_elec_s{simpl}_{clusters}.nc" - ), - temp_soil_rural=resources( - "temp_soil_rural_elec_s{simpl}_{clusters}.nc" - ), - temp_soil_urban=resources( - "temp_soil_urban_elec_s{simpl}_{clusters}.nc" - ), - temp_air_total=resources( - "temp_air_total_elec_s{simpl}_{clusters}.nc" - ), - temp_air_rural=resources( - "temp_air_rural_elec_s{simpl}_{clusters}.nc" - ), - temp_air_urban=resources( - "temp_air_urban_elec_s{simpl}_{clusters}.nc" - ), - cop_soil_total=resources( - "cop_soil_total_elec_s{simpl}_{clusters}.nc" - ), - cop_soil_rural=resources( - "cop_soil_rural_elec_s{simpl}_{clusters}.nc" - ), - cop_soil_urban=resources( - "cop_soil_urban_elec_s{simpl}_{clusters}.nc" - ), - cop_air_total=resources( - "cop_air_total_elec_s{simpl}_{clusters}.nc" - ), - cop_air_rural=resources( - "cop_air_rural_elec_s{simpl}_{clusters}.nc" - ), - cop_air_urban=resources( - "cop_air_urban_elec_s{simpl}_{clusters}.nc" - ), + temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"), + temp_soil_rural=resources("temp_soil_rural_elec_s{simpl}_{clusters}.nc"), + temp_soil_urban=resources("temp_soil_urban_elec_s{simpl}_{clusters}.nc"), + temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), + temp_air_rural=resources("temp_air_rural_elec_s{simpl}_{clusters}.nc"), + temp_air_urban=resources("temp_air_urban_elec_s{simpl}_{clusters}.nc"), + cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), + cop_soil_rural=resources("cop_soil_rural_elec_s{simpl}_{clusters}.nc"), + cop_soil_urban=resources("cop_soil_urban_elec_s{simpl}_{clusters}.nc"), + cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), + cop_air_rural=resources("cop_air_rural_elec_s{simpl}_{clusters}.nc"), + cop_air_urban=resources("cop_air_urban_elec_s{simpl}_{clusters}.nc"), solar_thermal_total=lambda w: ( resources("solar_thermal_total_elec_s{simpl}_{clusters}.nc") if config_provider("sector", "solar_thermal")(w) diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index eae1d990..5eb30233 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -15,20 +15,14 @@ rule add_existing_baseyear: powerplants=resources("powerplants.csv"), busmap_s=resources("busmap_elec_s{simpl}.csv"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), - clustered_pop_layout=resources( - "pop_layout_elec_s{simpl}_{clusters}.csv" - ), + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), costs=lambda w: resources( "costs_{}.csv".format( config_provider("scenario", "planning_horizons", 0)(w) ) ), - cop_soil_total=resources( - "cop_soil_total_elec_s{simpl}_{clusters}.nc" - ), - cop_air_total=resources( - "cop_air_total_elec_s{simpl}_{clusters}.nc" - ), + cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), + cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), existing_heating_distribution=resources( "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), @@ -85,12 +79,8 @@ rule add_brownfield: + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", network_p=solved_previous_horizon, #solved network at previous time step costs=resources("costs_{planning_horizons}.csv"), - cop_soil_total=resources( - "cop_soil_total_elec_s{simpl}_{clusters}.nc" - ), - cop_air_total=resources( - "cop_air_total_elec_s{simpl}_{clusters}.nc" - ), + cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"), + cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), output: RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index 9e3f9772..eb14436e 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -228,9 +228,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake( - "add_extra_components", simpl="", clusters=5 - ) + snakemake = mock_snakemake("add_extra_components", simpl="", clusters=5) configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 3380a947..a4822921 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -200,9 +200,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake( - "build_renewable_profiles", technology="offwind-dc" - ) + snakemake = mock_snakemake("build_renewable_profiles", technology="offwind-dc") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 5682c337..47b65359 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -455,7 +455,9 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "cluster_network", simpl="", clusters="5", + "cluster_network", + simpl="", + clusters="5", ) configure_logging(snakemake) set_scenario_config(snakemake) From 249cfab4292f11e2efdaa70e6ca104d297a48570 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 4 Mar 2024 18:24:01 +0100 Subject: [PATCH 400/591] remove remaining {weather_year} wildcard usages --- scripts/add_electricity.py | 9 +-------- scripts/build_artificial_load_data.py | 9 +-------- scripts/build_clustered_population_layouts.py | 6 +----- scripts/build_cutout.py | 4 ---- scripts/build_daily_heat_demand.py | 11 ++--------- scripts/build_electricity_demand.py | 9 +-------- scripts/build_hourly_heat_demand.py | 9 +-------- scripts/build_hydro_profile.py | 12 ++++++------ scripts/build_population_layouts.py | 6 +----- scripts/build_population_weighted_energy_totals.py | 10 +++++++--- scripts/build_renewable_profiles.py | 9 +-------- scripts/build_solar_thermal_profiles.py | 13 ++----------- scripts/build_temperature_profiles.py | 13 ++----------- scripts/build_transport_demand.py | 8 +------- 14 files changed, 27 insertions(+), 101 deletions(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 91fc04ea..c0076293 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -805,14 +805,7 @@ if __name__ == "__main__": n = pypsa.Network(snakemake.input.base_network) - weather_year = snakemake.wildcards.weather_year - if weather_year: - snapshots = dict( - start=weather_year, end=str(int(weather_year) + 1), inclusive="left" - ) - else: - snapshots = snakemake.config["snapshots"] - n.set_snapshots(pd.date_range(freq="h", **snapshots)) + n.set_snapshots(pd.date_range(freq="h", **snakemake.params.snapshots)) Nyears = n.snapshot_weightings.objective.sum() / 8760.0 diff --git a/scripts/build_artificial_load_data.py b/scripts/build_artificial_load_data.py index 51c07291..a12ac917 100755 --- a/scripts/build_artificial_load_data.py +++ b/scripts/build_artificial_load_data.py @@ -20,14 +20,7 @@ if __name__ == "__main__": configure_logging(snakemake) - weather_year = snakemake.wildcards.weather_year - if weather_year: - snapshots = dict( - start=weather_year, end=str(int(weather_year) + 1), inclusive="left" - ) - else: - snapshots = snakemake.config["snapshots"] - snapshots = pd.date_range(freq="h", **snapshots) + snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) fixed_year = snakemake.config["load"].get("fixed_year", False) years = ( diff --git a/scripts/build_clustered_population_layouts.py b/scripts/build_clustered_population_layouts.py index 21ff02be..2d9c6acb 100644 --- a/scripts/build_clustered_population_layouts.py +++ b/scripts/build_clustered_population_layouts.py @@ -25,11 +25,7 @@ if __name__ == "__main__": set_scenario_config(snakemake) - cutout_name = snakemake.input.cutout - year = snakemake.wildcards.weather_year - if year: - cutout_name = cutout_name.format(weather_year=year) - cutout = atlite.Cutout(cutout_name) + cutout = atlite.Cutout(snakemake.input.cutout) clustered_regions = ( gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0) diff --git a/scripts/build_cutout.py b/scripts/build_cutout.py index 039f645c..80ddae34 100644 --- a/scripts/build_cutout.py +++ b/scripts/build_cutout.py @@ -109,10 +109,6 @@ if __name__ == "__main__": cutout_params = snakemake.params.cutouts[snakemake.wildcards.cutout] - if hasattr(snakemake.wildcards, "weather_year"): - time = snakemake.wildcards.weather_year - cutout_params["time"] = [time, time] - if "time" not in cutout_params: snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) cutout_params["time"] = [snapshots[0], snapshots[-1]] diff --git a/scripts/build_daily_heat_demand.py b/scripts/build_daily_heat_demand.py index 0ba47771..c08cfe33 100644 --- a/scripts/build_daily_heat_demand.py +++ b/scripts/build_daily_heat_demand.py @@ -31,16 +31,9 @@ if __name__ == "__main__": client = Client(cluster, asynchronous=True) cutout_name = snakemake.input.cutout - year = snakemake.wildcards.weather_year - if year: - snapshots = dict(start=year, end=str(int(year) + 1), inclusive="left") - cutout_name = cutout_name.format(weather_year=year) - else: - snapshots = snakemake.params.snapshots - - time = pd.date_range(freq="h", **snapshots) - daily = pd.date_range(freq="D", **snapshots) + time = pd.date_range(freq="h", **snakemake.params.snapshots) + daily = pd.date_range(freq="D", **snakemake.params.snapshots) if snakemake.params.drop_leap_day: time = time[~((time.month == 2) & (time.day == 29))] daily = daily[~((daily.month == 2) & (daily.day == 29))] diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 4328b842..f5bd744a 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -263,14 +263,7 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - weather_year = snakemake.wildcards.weather_year - if weather_year: - snapshots = dict( - start=weather_year, end=str(int(weather_year) + 1), inclusive="left" - ) - else: - snapshots = snakemake.params.snapshots - snapshots = pd.date_range(freq="h", **snapshots) + snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) fixed_year = snakemake.config["load"].get("fixed_year", False) years = ( diff --git a/scripts/build_hourly_heat_demand.py b/scripts/build_hourly_heat_demand.py index 664b4499..c3916b54 100644 --- a/scripts/build_hourly_heat_demand.py +++ b/scripts/build_hourly_heat_demand.py @@ -24,14 +24,7 @@ if __name__ == "__main__": ) set_scenario_config(snakemake) - year = snakemake.wildcards.weather_year - - if year: - snapshots = dict(start=year, end=str(int(year) + 1), inclusive="left") - else: - snapshots = snakemake.params.snapshots - - snapshots = pd.date_range(freq="h", **snapshots) + snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) if snakemake.params.drop_leap_day: snapshots = snapshots[~((snapshots.month == 2) & (snapshots.day == 29))] diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index af5f0ee6..a732cf45 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -65,8 +65,8 @@ import atlite import country_converter as coco import geopandas as gpd import pandas as pd -from _helpers import configure_logging, set_scenario_config from numpy.polynomial import Polynomial +from _helpers import configure_logging, set_scenario_config cc = coco.CountryConverter() @@ -167,7 +167,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("build_hydro_profile", weather_year="") + snakemake = mock_snakemake("build_hydro_profile") configure_logging(snakemake) set_scenario_config(snakemake) @@ -197,12 +197,12 @@ if __name__ == "__main__": eia_stats.to_csv(snakemake.output.eia_hydro) - weather_year = snakemake.wildcards.weather_year + contained_years = pd.date_range(freq="YE", **snakemake.params.snapshots).year norm_year = config_hydro.get("eia_norm_year") if norm_year: - eia_stats.loc[weather_year] = eia_stats.loc[norm_year] - elif weather_year and weather_year not in eia_stats.index: - eia_stats.loc[weather_year] = eia_stats.median() + eia_stats.loc[contained_years] = eia_stats.loc[norm_year] + elif missing_years := eia_stats.index.difference(contained_years): + eia_stats.loc[missing_years] = eia_stats.median() inflow = cutout.runoff( shapes=country_shapes, diff --git a/scripts/build_population_layouts.py b/scripts/build_population_layouts.py index 64e70366..dc4cf2f8 100644 --- a/scripts/build_population_layouts.py +++ b/scripts/build_population_layouts.py @@ -28,11 +28,7 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - cutout_name = snakemake.input.cutout - year = snakemake.wildcards.weather_year - if year: - cutout_name = cutout_name.format(weather_year=year) - cutout = atlite.Cutout(cutout_name) + cutout = atlite.Cutout(snakemake.input.cutout) grid_cells = cutout.grid.geometry diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index bf4a6118..e055a4c2 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -21,9 +21,13 @@ if __name__ == "__main__": set_scenario_config(snakemake) config = snakemake.config["energy"] - data_year = int(config["energy_totals_year"]) - if snakemake.wildcards.weather_year and snakemake.wildcards.kind == "heat": - data_year = int(snakemake.wildcards.weather_year) + + if snakemake.wildcards.kind == "heat": + years = pd.date_range(freq="YE", **snakemake.config["snapshots"]).year + assert len(years) == 1, "Currently only works for single year." + data_year = years[0] + else: + data_year = int(config["energy_totals_year"]) pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 3380a947..ae7ba2c2 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -229,14 +229,7 @@ if __name__ == "__main__": else: client = None - weather_year = snakemake.wildcards.weather_year - if weather_year: - snapshots = dict( - start=weather_year, end=str(int(weather_year) + 1), inclusive="left" - ) - else: - snapshots = snakemake.params.snapshots - sns = pd.date_range(freq="h", **snapshots) + sns = pd.date_range(freq="h", **snakemake.params.snapshots) cutout = atlite.Cutout(snakemake.input.cutout).sel(time=sns) regions = gpd.read_file(snakemake.input.regions) diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index dc921ff5..c9eaffcc 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -32,20 +32,11 @@ if __name__ == "__main__": config = snakemake.params.solar_thermal config.pop("cutout", None) - cutout_name = snakemake.input.cutout - year = snakemake.wildcards.weather_year - - if year: - snapshots = dict(start=year, end=str(int(year) + 1), inclusive="left") - cutout_name = cutout_name.format(weather_year=year) - else: - snapshots = snakemake.params.snapshots - - time = pd.date_range(freq="h", **snapshots) + time = pd.date_range(freq="h", **snakemake.params.snapshots) if snakemake.params.drop_leap_day: time = time[~((time.month == 2) & (time.day == 29))] - cutout = atlite.Cutout(cutout_name).sel(time=time) + cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) clustered_regions = ( gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0) diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index eefc2616..e5fa0b38 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -20,7 +20,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_temperature_profiles", - weather_year="", simpl="", clusters=48, ) @@ -29,20 +28,12 @@ if __name__ == "__main__": nprocesses = int(snakemake.threads) cluster = LocalCluster(n_workers=nprocesses, threads_per_worker=1) client = Client(cluster, asynchronous=True) - cutout_name = snakemake.input.cutout - year = snakemake.wildcards.weather_year - if year: - snapshots = dict(start=year, end=str(int(year) + 1), inclusive="left") - cutout_name = cutout_name.format(weather_year=year) - else: - snapshots = snakemake.params.snapshots - - time = pd.date_range(freq="h", **snapshots) + time = pd.date_range(freq="h", **snakemake.params.snapshots) if snakemake.params.drop_leap_day: time = time[~((time.month == 2) & (time.day == 29))] - cutout = atlite.Cutout(cutout_name).sel(time=time) + cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) clustered_regions = ( gpd.read_file(snakemake.input.regions_onshore).set_index("name").buffer(0) diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index 9a64801f..d3c740be 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -183,13 +183,7 @@ if __name__ == "__main__": options = snakemake.params.sector - year = snakemake.wildcards.weather_year - snapshots = ( - dict(start=year, end=str(int(year) + 1), inclusive="left") - if year - else snakemake.params.snapshots - ) - snapshots = pd.date_range(freq="h", **snapshots, tz="UTC") + snapshots = pd.date_range(freq="h", **snakemake.params.snapshots, tz="UTC") if snakemake.params.drop_leap_day: leap_day = (snapshots.month == 2) & (snapshots.day == 29) snapshots = snapshots[~leap_day] From f4f4c1bf375eff2cedf15027afd889db1041a527 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 17:26:39 +0000 Subject: [PATCH 401/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 26 ++++++-------------------- rules/collect.smk | 7 ++----- rules/solve_electricity.smk | 18 +++++------------- scripts/build_hydro_profile.py | 2 +- 4 files changed, 14 insertions(+), 39 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index ab7b1913..a9499428 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -496,9 +496,7 @@ rule simplify_network: output: network=resources("networks/elec_s{simpl}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}.geojson" - ), + regions_offshore=resources("regions_offshore_elec_s{simpl}.geojson"), busmap=resources("busmap_elec_s{simpl}.csv"), connection_costs=resources("connection_costs_s{simpl}.csv"), log: @@ -532,9 +530,7 @@ rule cluster_network: input: network=resources("networks/elec_s{simpl}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}.geojson" - ), + regions_offshore=resources("regions_offshore_elec_s{simpl}.geojson"), busmap=ancient(resources("busmap_elec_s{simpl}.csv")), custom_busmap=lambda w: ( "data/custom_busmap_elec_s{simpl}_{clusters}.csv" @@ -546,12 +542,8 @@ rule cluster_network: ), output: network=resources("networks/elec_s{simpl}_{clusters}.nc"), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), linemap=resources("linemap_elec_s{simpl}_{clusters}.csv"), log: @@ -615,15 +607,9 @@ rule prepare_network: output: resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), log: - logs( - "prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" - ), + logs("prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.log"), benchmark: - ( - benchmarks( - "prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" - ) - ) + (benchmarks("prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}")) threads: 1 resources: mem_mb=4000, diff --git a/rules/collect.smk b/rules/collect.smk index ef63df0f..214b8102 100644 --- a/rules/collect.smk +++ b/rules/collect.smk @@ -34,9 +34,7 @@ rule extra_components_networks: rule prepare_elec_networks: input: expand( - resources( - "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - ), + resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), **config["scenario"], run=config["run"]["name"], ), @@ -55,8 +53,7 @@ rule prepare_sector_networks: rule solve_elec_networks: input: expand( - RESULTS - + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", **config["scenario"], run=config["run"]["name"], ), diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index 5c6777d4..81d07993 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -13,13 +13,10 @@ rule solve_network: ), custom_extra_functionality=input_custom_extra_functionality, input: - network=resources( - "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc" - ), + network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), config=RESULTS + "config.yaml", output: - network=RESULTS - + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", log: solver=normpath( RESULTS @@ -28,10 +25,7 @@ rule solve_network: python=RESULTS + "logs/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_python.log", benchmark: - ( - RESULTS - + "benchmarks/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" - ) + (RESULTS + "benchmarks/solve_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}") threads: solver_threads resources: mem_mb=memory, @@ -48,11 +42,9 @@ rule solve_operations_network: params: options=config_provider("solving", "options"), input: - network=RESULTS - + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", output: - network=RESULTS - + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc", + network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_op.nc", log: solver=normpath( RESULTS diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index a732cf45..ce8f3a4c 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -65,8 +65,8 @@ import atlite import country_converter as coco import geopandas as gpd import pandas as pd -from numpy.polynomial import Polynomial from _helpers import configure_logging, set_scenario_config +from numpy.polynomial import Polynomial cc = coco.CountryConverter() From 9d913bcb38aba2165021296523649f4921df7cc2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 4 Mar 2024 19:36:41 +0100 Subject: [PATCH 402/591] smaller fixes and reduction of diff --- doc/configtables/load.csv | 1 - rules/build_electricity.smk | 28 +++++-------------- rules/build_sector.smk | 14 +++++----- rules/postprocess.smk | 2 +- scripts/build_district_heat_share.py | 1 - ...build_industrial_energy_demand_per_node.py | 1 - ...build_population_weighted_energy_totals.py | 2 +- scripts/cluster_network.py | 8 ++---- scripts/make_summary.py | 2 +- scripts/simplify_network.py | 2 +- 10 files changed, 20 insertions(+), 41 deletions(-) diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index 204b79d8..a4de8323 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -1,5 +1,4 @@ ,Unit,Values,Description -url,--,string,"Link to open power system data time series data." power_statistics,bool,"{true, false}",Whether to load the electricity consumption data of the ENTSOE power statistics (only for files from 2019 and before) or from the ENTSOE transparency data (only has load data from 2015 onwards). interpolate_limit,hours,integer,"Maximum gap size (consecutive nans) which interpolated linearly." time_shift_for_large_gaps,string,string,"Periods which are used for copying time-slices in order to fill large gaps of nans. Have to be valid ``pandas`` period strings." diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index ab7b1913..b2b5b3d5 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -409,7 +409,7 @@ rule build_line_rating: def input_profile_tech(w): return { - f"profile_{tech}": resources(f"profile{}_{tech}.nc") + f"profile_{tech}": resources(f"profile_{tech}.nc") for tech in config_provider("electricity", "renewable_carriers")(w) } @@ -496,9 +496,7 @@ rule simplify_network: output: network=resources("networks/elec_s{simpl}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}.geojson" - ), + regions_offshore=resources("regions_offshore_elec_s{simpl}.geojson"), busmap=resources("busmap_elec_s{simpl}.csv"), connection_costs=resources("connection_costs_s{simpl}.csv"), log: @@ -532,9 +530,7 @@ rule cluster_network: input: network=resources("networks/elec_s{simpl}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}.geojson" - ), + regions_offshore=resources("regions_offshore_elec_s{simpl}.geojson"), busmap=ancient(resources("busmap_elec_s{simpl}.csv")), custom_busmap=lambda w: ( "data/custom_busmap_elec_s{simpl}_{clusters}.csv" @@ -546,12 +542,8 @@ rule cluster_network: ), output: network=resources("networks/elec_s{simpl}_{clusters}.nc"), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}_{clusters}.geojson" - ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), linemap=resources("linemap_elec_s{simpl}_{clusters}.csv"), log: @@ -615,15 +607,9 @@ rule prepare_network: output: resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), log: - logs( - "prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.log" - ), + logs("prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.log"), benchmark: - ( - benchmarks( - "prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}" - ) - ) + (benchmarks("prepare_network/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}")) threads: 1 resources: mem_mb=4000, diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 686bb9a1..eecd0fce 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -160,9 +160,9 @@ rule build_daily_heat_demand: mem_mb=20000, threads: 8 log: - logs("build_daily_heat_demand_{scope}__{simpl}_{clusters}.loc"), + logs("build_daily_heat_demand_{scope}_{simpl}_{clusters}.loc"), benchmark: - benchmarks("build_daily_heat_demand/{scope}__s{simpl}_{clusters}") + benchmarks("build_daily_heat_demand/{scope}_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -206,9 +206,9 @@ rule build_temperature_profiles: mem_mb=20000, threads: 8 log: - logs("build_temperature_profiles_{scope}__{simpl}_{clusters}.log"), + logs("build_temperature_profiles_{scope}_{simpl}_{clusters}.log"), benchmark: - benchmarks("build_temperature_profiles/{scope}__s{simpl}_{clusters}") + benchmarks("build_temperature_profiles/{scope}_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -272,9 +272,9 @@ rule build_solar_thermal_profiles: mem_mb=20000, threads: 16 log: - logs("build_solar_thermal_profiles_{scope}__s{simpl}_{clusters}.log"), + logs("build_solar_thermal_profiles_{scope}_s{simpl}_{clusters}.log"), benchmark: - benchmarks("build_solar_thermal_profiles/{scope}__s{simpl}_{clusters}") + benchmarks("build_solar_thermal_profiles/{scope}_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -853,7 +853,7 @@ rule build_existing_heating_distribution: def input_profile_offwind(w): return { - f"profile_{tech}": resources(f"profile{}_{tech}.nc") + f"profile_{tech}": resources(f"profile_{tech}.nc") for tech in ["offwind-ac", "offwind-dc"] if (tech in config_provider("electricity", "renewable_carriers")(w)) } diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 2eba1591..ac7bf983 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -297,7 +297,7 @@ rule plot_elec_statistics: output: **{ f"{plot}_bar": RESULTS - + f"figures/statistics_{plot}_bar_elec{}_s{{simpl}}_{{clusters}}_ec_l{{ll}}_{{opts}}.pdf" + + f"figures/statistics_{plot}_bar_elec_s{{simpl}}_{{clusters}}_ec_l{{ll}}_{{opts}}.pdf" for plot in STATISTICS_BARPLOTS }, barplots_touch=RESULTS diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index 0adf81ed..3cf88466 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -35,7 +35,6 @@ if __name__ == "__main__": district_heat_share = pd.read_csv(snakemake.input.district_heat_share, index_col=0)[ "district heat share" ] - district_heat_share = district_heat_share.groupby("country").max() # make ct-based share nodal district_heat_share = district_heat_share.reindex(pop_layout.ct).fillna(0) diff --git a/scripts/build_industrial_energy_demand_per_node.py b/scripts/build_industrial_energy_demand_per_node.py index 3987c975..ce72ea7a 100644 --- a/scripts/build_industrial_energy_demand_per_node.py +++ b/scripts/build_industrial_energy_demand_per_node.py @@ -15,7 +15,6 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_industrial_energy_demand_per_node", - weather_year="", simpl="", clusters=48, planning_horizons=2030, diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index e055a4c2..b26f289d 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -23,7 +23,7 @@ if __name__ == "__main__": config = snakemake.config["energy"] if snakemake.wildcards.kind == "heat": - years = pd.date_range(freq="YE", **snakemake.config["snapshots"]).year + years = pd.date_range(freq="YE", **snakemake.params.snapshots).year assert len(years) == 1, "Currently only works for single year." data_year = years[0] else: diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 47b65359..270774af 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -34,8 +34,8 @@ Inputs - ``resources/regions_onshore_elec_s{simpl}.geojson``: confer :ref:`simplify` - ``resources/regions_offshore_elec_s{simpl}.geojson``: confer :ref:`simplify` -- ``networks/elec_s{simpl}.nc``: confer :ref:`simplify` - ``resources/busmap_elec_s{simpl}.csv``: confer :ref:`simplify` +- ``networks/elec_s{simpl}.nc``: confer :ref:`simplify` - ``data/custom_busmap_elec_s{simpl}_{clusters}.csv``: optional input Outputs @@ -454,11 +454,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake( - "cluster_network", - simpl="", - clusters="5", - ) + snakemake = mock_snakemake("cluster_network", simpl="", clusters="5") configure_logging(snakemake) set_scenario_config(snakemake) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 27ce91d3..b9e1a8af 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -681,7 +681,7 @@ if __name__ == "__main__": networks_dict = { (cluster, ll, opt + sector_opt, planning_horizon): "results/" + snakemake.params.RDIR - + f"postnetworks/elec_s{simpl}_{cluster}_l{ll}_{opt}_{sector_opt}_{planning_horizon}.nc" + + f"/postnetworks/elec_s{simpl}_{cluster}_l{ll}_{opt}_{sector_opt}_{planning_horizon}.nc" for simpl in snakemake.params.scenario["simpl"] for cluster in snakemake.params.scenario["clusters"] for opt in snakemake.params.scenario["opts"] diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 4de17704..eac026a4 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -65,7 +65,7 @@ Outputs .. image:: img/regions_offshore_elec_s .png :scale: 33 % -- ``resources/busmap_elec_s{simpl}.h5``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec_s{simpl}.nc``; has keys ['/busmap_s'] +- ``resources/busmap_elec_s{simpl}.csv``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec_s{simpl}.nc``; - ``networks/elec_s{simpl}.nc``: .. image:: img/elec_s.png From 96f71d7e9c7cb8d2d4d92e9f738ee6ff8231b926 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 4 Mar 2024 19:37:02 +0100 Subject: [PATCH 403/591] outsource drop_leap_day in temporal aggregation --- scripts/prepare_sector_network.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 3a1158b9..802066b9 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -813,7 +813,7 @@ def add_co2limit(n, options, nyears=1.0, limit=0.0): # TODO PyPSA-Eur merge issue -def average_every_nhours(n, offset, drop_leap_day=False): +def average_every_nhours(n, offset): logger.info(f"Resampling the network to {offset}") m = n.copy(with_time=False) @@ -832,10 +832,6 @@ def average_every_nhours(n, offset, drop_leap_day=False): else: pnl[k] = df.resample(offset).mean() - if drop_leap_day: - sns = m.snapshots[~((m.snapshots.month == 2) & (m.snapshots.day == 29))] - m.set_snapshots(sns) - return m @@ -3425,7 +3421,7 @@ def cluster_heat_buses(n): def apply_time_segmentation( - n, segments, solver_name="cbc", overwrite_time_dependent=True, drop_leap_day=False + n, segments, solver_name="cbc", overwrite_time_dependent=True ): """ Aggregating time series to segments with different lengths. @@ -3489,11 +3485,6 @@ def apply_time_segmentation( for component, key in values_t.columns.droplevel(2).unique(): n.pnl(component)[key] = values_t[component, key] - # TODO: need to check that this actually works as intended. - if drop_leap_day: - sns = n.snapshots[~((n.snapshots.month == 2) & (n.snapshots.day == 29))] - n.set_snapshots(sns) - return n @@ -3515,14 +3506,16 @@ def set_temporal_aggregation(n, resolution, solver_name, drop_leap_day=False): elif "seg" in resolution.lower(): segments = int(resolution[:-3]) logger.info("Use temporal segmentation with %s segments", segments) - n = apply_time_segmentation( - n, segments, solver_name=solver_name, drop_leap_day=drop_leap_day - ) + n = apply_time_segmentation(n, segments, solver_name=solver_name) # temporal averaging elif "h" in resolution.lower(): logger.info("Aggregate to frequency %s", resolution) - n = average_every_nhours(n, resolution, drop_leap_day) + n = average_every_nhours(n, resolution) + + if drop_leap_day: + sns = n.snapshots[~((n.snapshots.month == 2) & (n.snapshots.day == 29))] + n.set_snapshots(sns) return n From 8904943a87addc393cb23e7c88638323e12d3093 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 4 Mar 2024 19:37:52 +0100 Subject: [PATCH 404/591] integrate artificial load data supplement into build_electricity_demand --- config/config.default.yaml | 3 +- rules/build_electricity.smk | 59 +++++++++------------------ rules/retrieve.smk | 9 ++-- scripts/build_artificial_load_data.py | 42 ------------------- scripts/build_electricity_demand.py | 16 +++++--- 5 files changed, 35 insertions(+), 94 deletions(-) delete mode 100755 scripts/build_artificial_load_data.py diff --git a/config/config.default.yaml b/config/config.default.yaml index a9166560..d19b7f0e 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -73,8 +73,6 @@ enable: build_cutout: false retrieve_irena: false retrieve_cutout: true - retrieve_opsd_load_data: true - retrieve_artificial_load_data: false build_natura_raster: false retrieve_natura_raster: true custom_busmap: false @@ -295,6 +293,7 @@ load: manual_adjustments: true # false scaling_factor: 1.0 fixed_year: false # false or year (e.g. 2013) + supplement_missing_data_artificially: true # docs # TODO: PyPSA-Eur merge issue in prepare_sector_network.py diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index b2b5b3d5..e0517933 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -18,45 +18,26 @@ if config["enable"].get("prepare_links_p_nom", False): "../scripts/prepare_links_p_nom.py" -if config["enable"].get("retrieve_opsd_load_data", True): - - rule build_electricity_demand: - params: - snapshots=config_provider("snapshots"), - countries=config_provider("countries"), - load=config_provider("load"), - input: - ancient("data/electricity_demand_raw.csv"), - output: - resources("electricity_demand.csv"), - log: - logs("build_electricity_demand.log"), - resources: - mem_mb=5000, - conda: - "../envs/environment.yaml" - script: - "../scripts/build_electricity_demand.py" - - -if config["enable"].get("retrieve_artificial_load_data", False): - - rule build_artificial_load_data: - input: - ancient("data/load_artificial_raw.csv"), - output: - resources("electricity_demand.csv"), - log: - logs("build_artificial_load_data.log"), - resources: - mem_mb=5000, - conda: - "../envs/environment.yaml" - script: - "../scripts/build_artificial_load_data.py" - - -ruleorder: build_artificial_load_data > build_electricity_demand +rule build_electricity_demand: + params: + snapshots=config_provider("snapshots"), + countries=config_provider("countries"), + load=config_provider("load"), + input: + reported=ancient("data/electricity_demand_raw.csv"), + artificial=lambda w: ancient("data/load_artificial_raw.csv") + if config_provider("load", "supplement_missing_data_artificially")(w) + else [], + output: + resources("electricity_demand.csv"), + log: + logs("build_electricity_demand.log"), + resources: + mem_mb=5000, + conda: + "../envs/environment.yaml" + script: + "../scripts/build_electricity_demand.py" rule build_powerplants: diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 000d475e..24093670 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -180,9 +180,7 @@ if config["enable"]["retrieve"]: "../scripts/retrieve_gas_infrastructure_data.py" -if config["enable"]["retrieve"] and config["enable"].get( - "retrieve_opsd_load_data", True -): +if config["enable"]["retrieve"]: rule retrieve_electricity_demand: params: @@ -200,9 +198,7 @@ if config["enable"]["retrieve"] and config["enable"].get( "../scripts/retrieve_electricity_demand.py" -if config["enable"]["retrieve"] and config["enable"].get( - "retrieve_artificial_load_data", False -): +if config["enable"]["retrieve"]: rule retrieve_artificial_load_data: input: @@ -220,6 +216,7 @@ if config["enable"]["retrieve"] and config["enable"].get( retries: 2 run: move(input[0], output[0]) + validate_checksum(output[0], input[0]) if config["enable"]["retrieve"]: diff --git a/scripts/build_artificial_load_data.py b/scripts/build_artificial_load_data.py deleted file mode 100755 index a12ac917..00000000 --- a/scripts/build_artificial_load_data.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: 2022 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT -""" -This rule downloads the load data. -""" - -import logging - -logger = logging.getLogger(__name__) -import pandas as pd -from _helpers import configure_logging - -if __name__ == "__main__": - if "snakemake" not in globals(): - from _helpers import mock_snakemake - - snakemake = mock_snakemake("build_artificial_load_data") - - configure_logging(snakemake) - - snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) - - fixed_year = snakemake.config["load"].get("fixed_year", False) - years = ( - slice(str(fixed_year), str(fixed_year)) - if fixed_year - else slice(snapshots[0], snapshots[-1]) - ) - countries = snakemake.config["countries"] - - load = pd.read_csv(snakemake.input[0], index_col=0, parse_dates=True).loc[ - snapshots, countries - ] - - assert not load.isna().any().any(), "Load data contains nans." - - if fixed_year: - load.index = load.index.map(lambda t: t.replace(year=snapshots.year[0])) - - load.to_csv(snakemake.output[0]) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index f5bd744a..68df4bac 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -277,16 +277,15 @@ if __name__ == "__main__": time_shift = snakemake.params.load["time_shift_for_large_gaps"] - load = load_timeseries(snakemake.input[0], years, countries) + load = load_timeseries(snakemake.input.reported, years, countries) if "UA" in countries: # attach load of UA (best data only for entsoe transparency) - load_ua = load_timeseries(snakemake.input[0], "2018", ["UA"], False) + load_ua = load_timeseries(snakemake.input.reported, "2018", ["UA"]) snapshot_year = str(snapshots.year.unique().item()) time_diff = pd.Timestamp("2018") - pd.Timestamp(snapshot_year) - load_ua.index -= ( - time_diff # hack indices (currently, UA is manually set to 2018) - ) + # hack indices (currently, UA is manually set to 2018) + load_ua.index -= time_diff load["UA"] = load_ua # attach load of MD (no time-series available, use 2020-totals and distribute according to UA): # https://www.iea.org/data-and-statistics/data-browser/?country=MOLDOVA&fuel=Energy%20consumption&indicator=TotElecCons @@ -307,6 +306,13 @@ if __name__ == "__main__": ) load = load.apply(fill_large_gaps, shift=time_shift) + if snakemake.params.load["supplement_missing_data_artificially"]: + logger.info("Supplement missing data with artificial data.") + fn = snakemake.input.artificial + artificial_load = pd.read_csv(fn, index_col=0, parse_dates=True) + artificial_load = artificial_load.loc[snapshots, countries] + load = load.combine_first(artificial_load) + assert not load.isna().any().any(), ( "Load data contains nans. Adjust the parameters " "`time_shift_for_large_gaps` or modify the `manual_adjustment` function " From 8aa6d98f5635064262b43bac526674b3fe4ac631 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 18:38:29 +0000 Subject: [PATCH 405/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 8 +++++--- rules/postprocess.smk | 23 ++++++----------------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index e0517933..a9e111ea 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -25,9 +25,11 @@ rule build_electricity_demand: load=config_provider("load"), input: reported=ancient("data/electricity_demand_raw.csv"), - artificial=lambda w: ancient("data/load_artificial_raw.csv") - if config_provider("load", "supplement_missing_data_artificially")(w) - else [], + artificial=lambda w: ( + ancient("data/load_artificial_raw.csv") + if config_provider("load", "supplement_missing_data_artificially")(w) + else [] + ), output: resources("electricity_demand.csv"), log: diff --git a/rules/postprocess.smk b/rules/postprocess.smk index ac7bf983..dc08699f 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -23,9 +23,7 @@ if config["foresight"] != "perfect": resources: mem_mb=4000, benchmark: - benchmarks( - "plot_power_network_clustered/elec_s{simpl}_{clusters}" - ) + benchmarks("plot_power_network_clustered/elec_s{simpl}_{clusters}") conda: "../envs/environment.yaml" script: @@ -37,9 +35,7 @@ if config["foresight"] != "perfect": input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: map=RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf", @@ -66,9 +62,7 @@ if config["foresight"] != "perfect": input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: map=RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-h2_network_{planning_horizons}.pdf", @@ -94,9 +88,7 @@ if config["foresight"] != "perfect": input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - regions=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: map=RESULTS + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-ch4_network_{planning_horizons}.pdf", @@ -133,9 +125,7 @@ if config["foresight"] == "perfect": input: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", - regions=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), + regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: unpack(output_map_year), threads: 2 @@ -292,8 +282,7 @@ rule plot_elec_statistics: plotting=config_provider("plotting"), barplots=STATISTICS_BARPLOTS, input: - network=RESULTS - + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", output: **{ f"{plot}_bar": RESULTS From 3af878d69c9ba3968b828f1270383cf7ca6072a1 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 5 Mar 2024 10:33:41 +0100 Subject: [PATCH 406/591] remove power statistics references --- config/config.default.yaml | 1 - config/config.validation.yaml | 3 --- doc/configtables/load.csv | 1 - 3 files changed, 5 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index d19b7f0e..99ebae88 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -287,7 +287,6 @@ transformers: # 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 diff --git a/config/config.validation.yaml b/config/config.validation.yaml index c8fb2fa5..062e82f5 100644 --- a/config/config.validation.yaml +++ b/config/config.validation.yaml @@ -69,9 +69,6 @@ conventional: biomass: p_max_pu: 0.65 -load: - power_statistics: false - lines: s_max_pu: 0.23 under_construction: 'remove' diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index a4de8323..0a62aeef 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -1,5 +1,4 @@ ,Unit,Values,Description -power_statistics,bool,"{true, false}",Whether to load the electricity consumption data of the ENTSOE power statistics (only for files from 2019 and before) or from the ENTSOE transparency data (only has load data from 2015 onwards). interpolate_limit,hours,integer,"Maximum gap size (consecutive nans) which interpolated linearly." time_shift_for_large_gaps,string,string,"Periods which are used for copying time-slices in order to fill large gaps of nans. Have to be valid ``pandas`` period strings." manual_adjustments,bool,"{true, false}","Whether to adjust the load data manually according to the function in :func:`manual_adjustment`." From 7f5f0ee45eee98d99d425e6e2e927f99087f97b9 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Tue, 5 Mar 2024 12:00:50 +0100 Subject: [PATCH 407/591] compute lifetime after grouping DateIn --- scripts/add_existing_baseyear.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 44c9b20e..eea1b3cf 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -171,9 +171,7 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas phased_out = df_agg[df_agg["DateOut"] < baseyear].index df_agg.drop(phased_out, inplace=True) - # calculate remaining lifetime before phase-out (+1 because assuming - # phase out date at the end of the year) - df_agg["lifetime"] = df_agg.DateOut - df_agg.DateIn + 1 + # assign clustered bus busmap_s = pd.read_csv(snakemake.input.busmap_s, index_col=0).squeeze() @@ -195,6 +193,10 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas grouping_years, np.digitize(df_agg.DateIn, grouping_years, right=True) ) + # calculate (adjusted) remaining lifetime before phase-out (+1 because assuming + # phase out date at the end of the year) + df_agg["lifetime"] = df_agg.DateOut - df_agg["grouping_year"] + 1 + df = df_agg.pivot_table( index=["grouping_year", "Fueltype"], columns="cluster_bus", From 8c465dbe3cbadb54a61336b9f75b94d454fdea97 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:49:33 +0000 Subject: [PATCH 408/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/add_existing_baseyear.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index eea1b3cf..0bbe19f0 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -171,8 +171,6 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas phased_out = df_agg[df_agg["DateOut"] < baseyear].index df_agg.drop(phased_out, inplace=True) - - # assign clustered bus busmap_s = pd.read_csv(snakemake.input.busmap_s, index_col=0).squeeze() busmap = pd.read_csv(snakemake.input.busmap, index_col=0).squeeze() @@ -195,7 +193,7 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas # calculate (adjusted) remaining lifetime before phase-out (+1 because assuming # phase out date at the end of the year) - df_agg["lifetime"] = df_agg.DateOut - df_agg["grouping_year"] + 1 + df_agg["lifetime"] = df_agg.DateOut - df_agg["grouping_year"] + 1 df = df_agg.pivot_table( index=["grouping_year", "Fueltype"], From 3c24ae9204df81cfba9abd08181c919fe11a27c0 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Tue, 5 Mar 2024 13:51:24 +0100 Subject: [PATCH 409/591] add release note --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 8167f6dd..3471c0b0 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,6 +9,8 @@ Release Notes Upcoming Release ================ +* Corrected a bug leading to power plants operating after their DateOut (https://github.com/PyPSA/pypsa-eur/pull/958). + * Upgrade default techno-economic assumptions to ``technology-data`` v0.8.1. * Linearly interpolate missing investment periods in year-dependent From 1e25f3adafd4f14cedd960b72151e5b4022a6f2f Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Tue, 5 Mar 2024 14:07:46 +0100 Subject: [PATCH 410/591] add grouping years 1960-1975 --- config/config.default.yaml | 2 +- doc/release_notes.rst | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index ad4144d5..b0b389b8 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -354,7 +354,7 @@ solar_thermal: # 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_power: [1960, 1965, 1970, 1975, 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 default_heating_lifetime: 20 diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 3471c0b0..b1234da1 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,7 +9,9 @@ Release Notes Upcoming Release ================ -* Corrected a bug leading to power plants operating after their DateOut (https://github.com/PyPSA/pypsa-eur/pull/958). +* Corrected a bug leading to power plants operating after their DateOut + (https://github.com/PyPSA/pypsa-eur/pull/958). Added additional grouping years + before 1980. * Upgrade default techno-economic assumptions to ``technology-data`` v0.8.1. From 3da649c13fbd48ed9d7d7c602bb0bf436eba35e2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:08:14 +0000 Subject: [PATCH 411/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/release_notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b1234da1..3ae2d09d 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,7 +9,7 @@ Release Notes Upcoming Release ================ -* Corrected a bug leading to power plants operating after their DateOut +* Corrected a bug leading to power plants operating after their DateOut (https://github.com/PyPSA/pypsa-eur/pull/958). Added additional grouping years before 1980. From 41f23f9589669147f5dfef96e42fe68bceabd595 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 5 Mar 2024 18:40:06 +0100 Subject: [PATCH 412/591] change eurostat year in build_industrial_production_per_country --- rules/build_sector.smk | 2 +- ...build_industrial_production_per_country.py | 50 +++++++------------ 2 files changed, 20 insertions(+), 32 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 6c542f4e..5e19a4bb 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -468,7 +468,7 @@ rule build_industrial_production_per_country: input: ammonia_production=resources("ammonia_production.csv"), jrc="data/bundle-sector/jrc-idees-2015", - eurostat="data/bundle-sector/eurostat-energy_balances-may_2018_edition", + eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition", output: industrial_production_per_country=resources( "industrial_production_per_country.csv" diff --git a/scripts/build_industrial_production_per_country.py b/scripts/build_industrial_production_per_country.py index 2ad37d3f..5c14b065 100644 --- a/scripts/build_industrial_production_per_country.py +++ b/scripts/build_industrial_production_per_country.py @@ -97,33 +97,18 @@ fields = { "Other Industrial Sectors": "Physical output (index)", } -eb_names = { - "NO": "Norway", - "AL": "Albania", - "BA": "Bosnia and Herzegovina", - "MK": "FYR of Macedonia", - "GE": "Georgia", - "IS": "Iceland", - "KO": "Kosovo", - "MD": "Moldova", - "ME": "Montenegro", - "RS": "Serbia", - "UA": "Ukraine", - "TR": "Turkey", -} - eb_sectors = { - "Iron & steel industry": "Iron and steel", - "Chemical and Petrochemical industry": "Chemicals Industry", - "Non-ferrous metal industry": "Non-metallic mineral products", - "Paper, Pulp and Print": "Pulp, paper and printing", - "Food and Tabacco": "Food, beverages and tobacco", - "Non-metallic Minerals (Glass, pottery & building mat. Industry)": "Non Ferrous Metals", - "Transport Equipment": "Transport Equipment", + "Iron & steel": "Iron and steel", + "Chemical & petrochemical": "Chemicals Industry", + "Non-ferrous metals": "Non-metallic mineral products", + "Paper, pulp & printing": "Pulp, paper and printing", + "Food, beverages & tobacco": "Food, beverages and tobacco", + "Non-metallic minerals": "Non Ferrous Metals", + "Transport equipment": "Transport Equipment", "Machinery": "Machinery Equipment", - "Textile and Leather": "Textiles and leather", - "Wood and Wood Products": "Wood and wood products", - "Non-specified (Industry)": "Other Industrial Sectors", + "Textile & leather": "Textiles and leather", + "Wood & wood products": "Wood and wood products", + "Not elsewhere specified (industry)": "Other Industrial Sectors", } # TODO: this should go in a csv in `data` @@ -160,12 +145,15 @@ def get_energy_ratio(country, eurostat_dir, jrc_dir, year): e_country = e_switzerland * tj_to_ktoe else: # estimate physical output, energy consumption in the sector and country - fn = f"{eurostat_dir}/{eb_names[country]}.XLSX" - with mute_print(): - df = pd.read_excel( - fn, sheet_name="2016", index_col=2, header=0, skiprows=1 - ).squeeze("columns") - e_country = df.loc[eb_sectors.keys(), "Total all products"].rename(eb_sectors) + fn = f"{eurostat_dir}/{country}-Energy-balance-sheets-April-2023-edition.xlsb" + df = pd.read_excel( + fn, + sheet_name=str(min(2021, year)), + index_col=2, + header=0, + skiprows=4, + ) + e_country = df.loc[eb_sectors.keys(), "Total"].rename(eb_sectors) fn = f"{jrc_dir}/JRC-IDEES-2015_Industry_EU28.xlsx" From 5b513f81db7b52d79eb4f316df08d7bbe232ec9c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 5 Mar 2024 18:42:15 +0100 Subject: [PATCH 413/591] move eurostat into data/eurostat subdirectory from sector-bundle --- doc/configtables/energy.csv | 3 --- rules/build_sector.smk | 4 ++-- rules/postprocess.smk | 2 +- rules/retrieve.smk | 18 ++---------------- scripts/retrieve_eurostat_data.py | 4 ++-- 5 files changed, 7 insertions(+), 24 deletions(-) diff --git a/doc/configtables/energy.csv b/doc/configtables/energy.csv index 8718d75e..3d13b9c3 100644 --- a/doc/configtables/energy.csv +++ b/doc/configtables/energy.csv @@ -1,7 +1,4 @@ ,Unit,Values,Description energy_totals_year ,--,"{1990,1995,2000,2005,2010,2011,…} ",The year for the sector energy use. The year must be avaliable in the Eurostat report base_emissions_year ,--,"YYYY; e.g. 1990","The base year for the sector emissions. See `European Environment Agency (EEA) `_." - -eurostat_report_year ,--,"{2016,2017,2018}","The publication year of the Eurostat report. 2016 includes Bosnia and Herzegovina, 2017 does not" - emissions ,--,"{CO2, All greenhouse gases - (CO2 equivalent)}","Specify which sectoral emissions are taken into account. Data derived from EEA. Currently only CO2 is implemented." diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 5e19a4bb..2ca0d9a4 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -270,7 +270,7 @@ rule build_energy_totals: swiss="data/switzerland-new_format-all_years.csv", idees="data/bundle-sector/jrc-idees-2015", district_heat_share="data/district_heat_share.csv", - eurostat="data/bundle-sector/eurostat-energy_balances-april_2023_edition", + eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition", output: energy_name=resources("energy_totals.csv"), co2_name=resources("co2_totals.csv"), @@ -865,7 +865,7 @@ rule prepare_sector_network: ), network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), energy_totals_name=resources("energy_totals.csv"), - eurostat="data/bundle-sector/eurostat-energy_balances-april_2023_edition", + eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition", pop_weighted_energy_totals=resources( "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" ), diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 5f93540f..ecfc5b74 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -247,7 +247,7 @@ rule plot_summary: costs=RESULTS + "csvs/costs.csv", energy=RESULTS + "csvs/energy.csv", balances=RESULTS + "csvs/supply_energy.csv", - eurostat="data/bundle-sector/eurostat-energy_balances-april_2023_edition", + eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition", co2="data/bundle-sector/eea/UNFCCC_v23.csv", output: costs=RESULTS + "graphs/costs.pdf", diff --git a/rules/retrieve.smk b/rules/retrieve.smk index cfe698fc..b516a0cd 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -135,20 +135,10 @@ if config["enable"]["retrieve"] and config["enable"].get( "h2_salt_caverns_GWh_per_sqkm.geojson", ] - datafolders = [ - protected( - directory("data/bundle-sector/eurostat-energy_balances-june_2016_edition") - ), - protected( - directory("data/bundle-sector/eurostat-energy_balances-may_2018_edition") - ), - protected(directory("data/bundle-sector/jrc-idees-2015")), - ] - rule retrieve_sector_databundle: output: protected(expand("data/bundle-sector/{files}", files=datafiles)), - *datafolders, + protected(directory("data/bundle-sector/jrc-idees-2015")), log: "logs/retrieve_sector_databundle.log", retries: 2 @@ -159,11 +149,7 @@ if config["enable"]["retrieve"] and config["enable"].get( rule retrieve_eurostat_data: output: - protected( - directory( - "data/bundle-sector/eurostat-energy_balances-april_2023_edition" - ) - ), + directory("data/eurostat/eurostat-energy_balances-april_2023_edition"), log: "logs/retrieve_eurostat_data.log", retries: 2 diff --git a/scripts/retrieve_eurostat_data.py b/scripts/retrieve_eurostat_data.py index daee4fc4..4b4cea4a 100644 --- a/scripts/retrieve_eurostat_data.py +++ b/scripts/retrieve_eurostat_data.py @@ -28,9 +28,9 @@ if __name__ == "__main__": disable_progress = snakemake.config["run"].get("disable_progressbar", False) url_eurostat = "https://ec.europa.eu/eurostat/documents/38154/4956218/Balances-December2022.zip/f7cf0d19-5c0f-60ad-4e48-098a5ddd6e48?t=1671184070589" - tarball_fn = Path(f"{rootpath}/data/bundle-sector/eurostat_2023.zip") + tarball_fn = Path(f"{rootpath}/data/eurostat/eurostat_2023.zip") to_fn = Path( - f"{rootpath}/data/bundle-sector/eurostat-energy_balances-april_2023_edition/" + f"{rootpath}/data/eurostat/eurostat-energy_balances-april_2023_edition/" ) logger.info(f"Downloading Eurostat data from '{url_eurostat}'.") From bf60da973b0370dcce3b5b7d7fd166cd73839351 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 5 Mar 2024 18:43:24 +0100 Subject: [PATCH 414/591] build_energy_totals: revision of eurostat report upgrade --- scripts/build_energy_totals.py | 200 +++++++++++---------------------- 1 file changed, 63 insertions(+), 137 deletions(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index c114b707..1ffc4ae2 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -37,54 +37,6 @@ def reverse(dictionary): return {v: k for k, v in dictionary.items()} -eurostat_codes = { - "EU28": "EU", - "EA19": "EA", - "Belgium": "BE", - "Bulgaria": "BG", - "Czech Republic": "CZ", - "Denmark": "DK", - "Germany": "DE", - "Estonia": "EE", - "Ireland": "IE", - "Greece": "GR", - "Spain": "ES", - "France": "FR", - "Croatia": "HR", - "Italy": "IT", - "Cyprus": "CY", - "Latvia": "LV", - "Lithuania": "LT", - "Luxembourg": "LU", - "Hungary": "HU", - "Malta": "MA", - "Netherlands": "NL", - "Austria": "AT", - "Poland": "PL", - "Portugal": "PT", - "Romania": "RO", - "Slovenia": "SI", - "Slovakia": "SK", - "Finland": "FI", - "Sweden": "SE", - "United Kingdom": "GB", - "Iceland": "IS", - "Norway": "NO", - "Montenegro": "ME", - "FYR of Macedonia": "MK", - "Albania": "AL", - "Serbia": "RS", - "Turkey": "TU", - "Bosnia and Herzegovina": "BA", - "Kosovo\n(UNSCR 1244/99)": "KO", # 2017 version - # 2016 version - "Kosovo\n(under United Nations Security Council Resolution 1244/99)": "KO", - "Moldova": "MO", - "Ukraine": "UK", - "Switzerland": "CH", -} - - idees_rename = {"GR": "EL", "GB": "UK"} eu28 = cc.EU28as("ISO2").ISO2.tolist() @@ -121,79 +73,54 @@ def build_eurostat(input_eurostat, countries, year): """ Return multi-index for all countries' energy data in TWh/a. """ - # read in every country file in countries - eurostat = pd.DataFrame() - countries = [country if country != "GB" else "UK" for country in countries] - countries = [country if country != "GR" else "EL" for country in countries] + df = {} + countries = {idees_rename.get(country, country) for country in countries} - {"CH"} for country in countries: - filename = f"/{country}-Energy-balance-sheets-April-2023-edition.xlsb" - if os.path.exists(input_eurostat + filename): - df = pd.read_excel( - input_eurostat + filename, - engine="pyxlsb", - sheet_name=str(year), - skiprows=4, - index_col=list(range(4)), - ) - # replace entry 'Z' with 0 - df.replace("Z", 0, inplace=True) - # write 'International aviation' to the 2nd level of the multiindex - index_number = ( - df.index.get_level_values(1) == "International aviation" - ).argmax() - new_index = ( - "-", - "International aviation", - "International aviation", - "ktoe", - ) - modified_index = list(df.index) - modified_index[index_number] = new_index - df.index = pd.MultiIndex.from_tuples(modified_index, names=df.index.names) - # drop the annoying subhead line - df.drop(df[df[year] == year].index, inplace=True) - # replace 'Z' with 0 - df = df.replace("Z", 0) - # add country to the multiindex - new_tuple = [(country, *idx) for idx in df.index] - new_mindex = pd.MultiIndex.from_tuples( - new_tuple, names=["country", None, "name", None, "unit"] - ) - df.index = new_mindex - # make numeric values where possible - df = df.apply(pd.to_numeric, errors="coerce") - # drop non-numeric columns - non_numeric_cols = df.columns[df.dtypes != float] - df.drop(non_numeric_cols, axis=1, inplace=True) - # concatenate the dataframes - eurostat = pd.concat([eurostat, df], axis=0) + filename = ( + f"{input_eurostat}/{country}-Energy-balance-sheets-April-2023-edition.xlsb" + ) + sheet = pd.read_excel( + filename, + engine="pyxlsb", + sheet_name=str(year), + skiprows=4, + index_col=list(range(4)), + ) + df[country] = sheet + df = pd.concat(df, axis=0) + + # drop columns with all NaNs + unnamed_cols = df.columns[df.columns.astype(str).str.startswith("Unnamed")] + df.drop(unnamed_cols, axis=1, inplace=True) + df.drop(year, axis=1, inplace=True) + + # make numeric values where possible + df.replace("Z", 0, inplace=True) + df = df.apply(pd.to_numeric, errors="coerce") + df = df.select_dtypes(include=[np.number]) + + # write 'International aviation' to the 2nd level of the multiindex + int_avia = df.index.get_level_values(2) == "International aviation" + temp = df.loc[int_avia] + temp.index = pd.MultiIndex.from_frame( + temp.index.to_frame().fillna("International aviation") + ) + df = pd.concat([temp, df.loc[~int_avia]]) - eurostat.drop(["Unnamed: 4", year, "Unnamed: 6"], axis=1, inplace=True) # Renaming some indices - rename = { + index_rename = { "Households": "Residential", "Commercial & public services": "Services", "Domestic navigation": "Domestic Navigation", + "International maritime bunkers": "Bunkers", } - for name, rename in rename.items(): - eurostat.index = eurostat.index.set_levels( - eurostat.index.levels[3].where(eurostat.index.levels[3] != name, rename), - level=3, - ) - new_index = eurostat.index.set_levels( - eurostat.index.levels[2].where( - eurostat.index.levels[2] != "International maritime bunkers", "Bunkers" - ), - level=2, - ) - eurostat.index = new_index + columns_rename = {"Total": "Total all products", "UK": "GB"} + df.rename(index=index_rename, columns=columns_rename, inplace=True) + df.sort_index(inplace=True) + df.index.names = [None] * len(df.index.names) - eurostat.rename(columns={"Total": "Total all products"}, inplace=True) - eurostat.index = eurostat.index.set_levels( - eurostat.index.levels[0].where(eurostat.index.levels[0] != "UK", "GB"), level=0 - ) - - df = eurostat * 11.63 / 1e3 + # convert to TWh/a from ktoe/a + df *= 11.63 / 1e3 return df @@ -776,25 +703,25 @@ def build_transport_data(countries, population, idees): return transport_data -def rescale(idees_countries, energy, eurostat): +def rescale_idees_from_eurostat( + idees_countries, energy, eurostat, input_eurostat, countries +): """ Takes JRC IDEES data from 2015 and rescales it by the ratio of the eurostat data and the 2015 eurostat data. missing data: ['passenger car efficiency', 'passenger cars'] """ + main_cols = ["Total all products", "Electricity"] # read in the eurostat data for 2015 - eurostat_2015 = build_eurostat(input_eurostat, countries, 2023, 2015)[ - ["Total all products", "Electricity"] - ] - eurostat_year = eurostat[["Total all products", "Electricity"]] + eurostat_2015 = build_eurostat(input_eurostat, countries, 2015)[main_cols] + eurostat_year = eurostat[main_cols] # calculate the ratio of the two data sets ratio = eurostat_year / eurostat_2015 ratio = ratio.droplevel([1, 4]) - ratio.rename( - columns={"Total all products": "total", "Electricity": "ele"}, inplace=True - ) - ratio = ratio.rename(index={"EL": "GR"}, level=0) + cols_rename = {"Total all products": "total", "Electricity": "ele"} + index_rename = {v: k for k, v in idees_rename.items()} + ratio.rename(columns=cols_rename, index=index_rename, inplace=True) mappings = { "Residential": { @@ -887,16 +814,16 @@ def rescale(idees_countries, energy, eurostat): for sector, mapping in mappings.items(): sector_ratio = ratio.loc[(country, slice(None), sector)] - energy.loc[country, mapping["total"]] *= sector_ratio[["total"]].iloc[0, 0] - energy.loc[country, mapping["elec"]] *= sector_ratio[["ele"]].iloc[0, 0] + energy.loc[country, mapping["total"]] *= sector_ratio["total"].iloc[0] + energy.loc[country, mapping["elec"]] *= sector_ratio["ele"].iloc[0] - avi_d = ratio.loc[(country, slice(None), "Domestic aviation")] - avi_i = ratio.loc[(country, "International aviation", slice(None))] - energy.loc[country, avia_inter] *= avi_i[["total"]].iloc[0, 0] - energy.loc[country, avia_domestic] *= avi_d[["total"]].iloc[0, 0] + avi_d = ratio.loc[(country, slice(None), "Domestic aviation"), "total"] + avi_i = ratio.loc[(country, "International aviation", slice(None)), "total"] + energy.loc[country, avia_inter] *= avi_i.iloc[0] + energy.loc[country, avia_domestic] *= avi_d.iloc[0] - nav = ratio.loc[(country, slice(None), "Domestic Navigation")] - energy.loc[country, navigation] *= nav[["total"]].iloc[0, 0] + nav = ratio.loc[(country, slice(None), "Domestic Navigation"), "total"] + energy.loc[country, navigation] *= nav.iloc[0] return energy @@ -922,17 +849,16 @@ if __name__ == "__main__": input_eurostat = snakemake.input.eurostat eurostat = build_eurostat(input_eurostat, countries, data_year) swiss = build_swiss(data_year) - # data from idees only exists from 2000-2015 - if data_year > 2015: - # read in latest data and rescale later - idees = build_idees(idees_countries, 2015) - else: - idees = build_idees(idees_countries, data_year) + # data from idees only exists from 2000-2015. read in latest data and rescale later + idees = build_idees(idees_countries, min(2015, data_year)) energy = build_energy_totals(countries, eurostat, swiss, idees) if data_year > 2015: - energy = rescale(idees_countries, energy, eurostat) + logger.info("Data year is after 2015. Rescaling IDEES data based on eurostat.") + energy = rescale_idees_from_eurostat( + idees_countries, energy, eurostat, input_eurostat, countries + ) energy.to_csv(snakemake.output.energy_name) From c13e0b83cff1f8a7ac2d6c9cd07ba01bd2b235f8 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 5 Mar 2024 18:55:59 +0100 Subject: [PATCH 415/591] remove remaining references of eurostat report year --- rules/build_sector.smk | 1 - rules/postprocess.smk | 1 - scripts/plot_summary.py | 2 -- scripts/prepare_sector_network.py | 14 ++++---------- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 2ca0d9a4..9147a623 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -834,7 +834,6 @@ rule prepare_sector_network: countries=config_provider("countries"), adjustments=config_provider("adjustments", "sector"), emissions_scope=config_provider("energy", "emissions"), - eurostat_report_year=config_provider("energy", "eurostat_report_year"), RDIR=RDIR, input: unpack(input_profile_offwind), diff --git a/rules/postprocess.smk b/rules/postprocess.smk index ecfc5b74..1b188829 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -237,7 +237,6 @@ rule plot_summary: countries=config_provider("countries"), planning_horizons=config_provider("scenario", "planning_horizons"), emissions_scope=config_provider("energy", "emissions"), - eurostat_report_year=config_provider("energy", "eurostat_report_year"), plotting=config_provider("plotting"), foresight=config_provider("foresight"), co2_budget=config_provider("co2_budget"), diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index c2fd7e04..bfe9995f 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -462,7 +462,6 @@ def plot_carbon_budget_distribution(input_eurostat, options): plt.rcParams["ytick.labelsize"] = 20 emissions_scope = snakemake.params.emissions_scope - report_year = snakemake.params.eurostat_report_year input_co2 = snakemake.input.co2 # historic emissions @@ -472,7 +471,6 @@ def plot_carbon_budget_distribution(input_eurostat, options): input_eurostat, options, emissions_scope, - report_year, input_co2, year=1990, ) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 9a9db36f..8b001da3 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -248,7 +248,7 @@ def get(item, investment_year=None): def co2_emissions_year( - countries, input_eurostat, options, emissions_scope, report_year, input_co2, year + countries, input_eurostat, options, emissions_scope, input_co2, year ): """ Calculate CO2 emissions in one specific year (e.g. 1990 or 2018). @@ -258,11 +258,9 @@ def co2_emissions_year( # TODO: read Eurostat data from year > 2014 # this only affects the estimation of CO2 emissions for BA, RS, AL, ME, MK if year > 2014: - eurostat_co2 = build_eurostat_co2( - input_eurostat, countries, report_year, year=2014 - ) + eurostat_co2 = build_eurostat_co2(input_eurostat, countries, 2014) else: - eurostat_co2 = build_eurostat_co2(input_eurostat, countries, report_year, year) + eurostat_co2 = build_eurostat_co2(input_eurostat, countries, year) co2_totals = build_co2_totals(countries, eea_co2, eurostat_co2) @@ -278,7 +276,7 @@ def co2_emissions_year( # TODO: move to own rule with sector-opts wildcard? def build_carbon_budget( - o, input_eurostat, fn, emissions_scope, report_year, input_co2, options + o, input_eurostat, fn, emissions_scope, input_co2, options ): """ Distribute carbon budget following beta or exponential transition path. @@ -300,7 +298,6 @@ def build_carbon_budget( input_eurostat, options, emissions_scope, - report_year, input_co2, year=1990, ) @@ -311,7 +308,6 @@ def build_carbon_budget( input_eurostat, options, emissions_scope, - report_year, input_co2, year=2018, ) @@ -3669,14 +3665,12 @@ if __name__ == "__main__": fn = "results/" + snakemake.params.RDIR + "/csvs/carbon_budget_distribution.csv" if not os.path.exists(fn): emissions_scope = snakemake.params.emissions_scope - report_year = snakemake.params.eurostat_report_year input_co2 = snakemake.input.co2 build_carbon_budget( co2_budget, snakemake.input.eurostat, fn, emissions_scope, - report_year, input_co2, options, ) From ca91c02bf77e5d33c787d2e4b78f65e2c694dfce Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 17:56:39 +0000 Subject: [PATCH 416/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/prepare_sector_network.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 8b001da3..2e8bf6fd 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -275,9 +275,7 @@ def co2_emissions_year( # TODO: move to own rule with sector-opts wildcard? -def build_carbon_budget( - o, input_eurostat, fn, emissions_scope, input_co2, options -): +def build_carbon_budget(o, input_eurostat, fn, emissions_scope, input_co2, options): """ Distribute carbon budget following beta or exponential transition path. """ From 85ceb9ad54875f84fd52ea643fd0f0f333d19ed1 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 5 Mar 2024 19:03:48 +0100 Subject: [PATCH 417/591] add release notes --- doc/release_notes.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 8167f6dd..de08873d 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,6 +9,19 @@ Release Notes Upcoming Release ================ + +* The Eurostat data was updated to the 2023 version in :mod:`build_energy_totals`. + +* The latest `Swiss energy totals + `_ + have been updated to the 2023 version. + +* The JRC-IDEES data is only available until 2015. For energy totals years (``energy: energy_totals_year``) after + 2015, the data scaled using the ratio of Eurostat data reported for the energy + totals year and 2015. + +* The default energy totals year (``energy: energy_totals_year``) was updated to 2019. + * Upgrade default techno-economic assumptions to ``technology-data`` v0.8.1. * Linearly interpolate missing investment periods in year-dependent From da8119e47ee2e686fe063d31ac9ff3e79b2f6508 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 5 Mar 2024 19:08:22 +0100 Subject: [PATCH 418/591] reset CI data cache --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index bad6039f..c17c0425 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,7 +19,7 @@ on: - cron: "0 5 * * TUE" env: - DATA_CACHE_NUMBER: 2 + DATA_CACHE_NUMBER: 1 jobs: build: From 7abbb47efda6a51d1d1ef1b6f66e5a04bb4919e6 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 6 Mar 2024 16:42:33 +0100 Subject: [PATCH 419/591] revert to master version of build_energy_totals --- scripts/build_energy_totals.py | 208 +++++++++++++-------------------- 1 file changed, 83 insertions(+), 125 deletions(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index b14644d5..1ffc4ae2 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -122,27 +122,16 @@ def build_eurostat(input_eurostat, countries, year): # convert to TWh/a from ktoe/a df *= 11.63 / 1e3 - df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1) - - if year: - df = df.xs(year, level="year") - return df -def build_swiss(year=None): +def build_swiss(year): """ - Return a pd.DataFrame of Swiss energy data in TWh/a. + Return a pd.Series of Swiss energy data in TWh/a. """ - fn = snakemake.input.swiss - df = pd.read_csv(fn, index_col=[0, 1]).stack().unstack("item") - df.index.names = ["country", "year"] - df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1) - - if year: - df = df.xs(year, level="year") + df = pd.read_csv(fn, index_col=[0, 1]).loc["CH", str(year)] # convert PJ/a to TWh/a df /= 3.6 @@ -151,7 +140,6 @@ def build_swiss(year=None): def idees_per_country(ct, year, base_dir): - ct_totals = {} ct_idees = idees_rename.get(ct, ct) fn_residential = f"{base_dir}/JRC-IDEES-2015_Residential_{ct_idees}.xlsx" fn_tertiary = f"{base_dir}/JRC-IDEES-2015_Tertiary_{ct_idees}.xlsx" @@ -159,27 +147,27 @@ def idees_per_country(ct, year, base_dir): # residential - df = pd.read_excel(fn_residential, "RES_hh_fec", index_col=0) - - ct_totals["total residential space"] = df.loc["Space heating"] + df = pd.read_excel(fn_residential, "RES_hh_fec", index_col=0)[year] rows = ["Advanced electric heating", "Conventional electric heating"] - ct_totals["electricity residential space"] = df.loc[rows].sum() - - ct_totals["total residential water"] = df.loc["Water heating"] + ct_totals = { + "total residential space": df["Space heating"], + "electricity residential space": df[rows].sum(), + } + ct_totals["total residential water"] = df.at["Water heating"] assert df.index[23] == "Electricity" ct_totals["electricity residential water"] = df.iloc[23] - ct_totals["total residential cooking"] = df.loc["Cooking"] + ct_totals["total residential cooking"] = df["Cooking"] assert df.index[30] == "Electricity" ct_totals["electricity residential cooking"] = df.iloc[30] - df = pd.read_excel(fn_residential, "RES_summary", index_col=0) + df = pd.read_excel(fn_residential, "RES_summary", index_col=0)[year] row = "Energy consumption by fuel - Eurostat structure (ktoe)" - ct_totals["total residential"] = df.loc[row] + ct_totals["total residential"] = df[row] assert df.index[47] == "Electricity" ct_totals["electricity residential"] = df.iloc[47] @@ -192,27 +180,27 @@ def idees_per_country(ct, year, base_dir): # services - df = pd.read_excel(fn_tertiary, "SER_hh_fec", index_col=0) + df = pd.read_excel(fn_tertiary, "SER_hh_fec", index_col=0)[year] - ct_totals["total services space"] = df.loc["Space heating"] + ct_totals["total services space"] = df["Space heating"] rows = ["Advanced electric heating", "Conventional electric heating"] - ct_totals["electricity services space"] = df.loc[rows].sum() + ct_totals["electricity services space"] = df[rows].sum() - ct_totals["total services water"] = df.loc["Hot water"] + ct_totals["total services water"] = df["Hot water"] assert df.index[24] == "Electricity" ct_totals["electricity services water"] = df.iloc[24] - ct_totals["total services cooking"] = df.loc["Catering"] + ct_totals["total services cooking"] = df["Catering"] assert df.index[31] == "Electricity" ct_totals["electricity services cooking"] = df.iloc[31] - df = pd.read_excel(fn_tertiary, "SER_summary", index_col=0) + df = pd.read_excel(fn_tertiary, "SER_summary", index_col=0)[year] row = "Energy consumption by fuel - Eurostat structure (ktoe)" - ct_totals["total services"] = df.loc[row] + ct_totals["total services"] = df[row] assert df.index[50] == "Electricity" ct_totals["electricity services"] = df.iloc[50] @@ -228,7 +216,7 @@ def idees_per_country(ct, year, base_dir): start = "Detailed split of energy consumption (ktoe)" end = "Market shares of energy uses (%)" - df = pd.read_excel(fn_tertiary, "AGR_fec", index_col=0).loc[start:end] + df = pd.read_excel(fn_tertiary, "AGR_fec", index_col=0).loc[start:end, year] rows = [ "Lighting", @@ -236,30 +224,30 @@ def idees_per_country(ct, year, base_dir): "Specific electricity uses", "Pumping devices (electric)", ] - ct_totals["total agriculture electricity"] = df.loc[rows].sum() + ct_totals["total agriculture electricity"] = df[rows].sum() rows = ["Specific heat uses", "Low enthalpy heat"] - ct_totals["total agriculture heat"] = df.loc[rows].sum() + ct_totals["total agriculture heat"] = df[rows].sum() rows = [ "Motor drives", "Farming machine drives (diesel oil incl. biofuels)", "Pumping devices (diesel oil incl. biofuels)", ] - ct_totals["total agriculture machinery"] = df.loc[rows].sum() + ct_totals["total agriculture machinery"] = df[rows].sum() row = "Agriculture, forestry and fishing" - ct_totals["total agriculture"] = df.loc[row] + ct_totals["total agriculture"] = df[row] # transport - df = pd.read_excel(fn_transport, "TrRoad_ene", index_col=0) + df = pd.read_excel(fn_transport, "TrRoad_ene", index_col=0)[year] - ct_totals["total road"] = df.loc["by fuel (EUROSTAT DATA)"] + ct_totals["total road"] = df["by fuel (EUROSTAT DATA)"] - ct_totals["electricity road"] = df.loc["Electricity"] + ct_totals["electricity road"] = df["Electricity"] - ct_totals["total two-wheel"] = df.loc["Powered 2-wheelers (Gasoline)"] + ct_totals["total two-wheel"] = df["Powered 2-wheelers (Gasoline)"] assert df.index[19] == "Passenger cars" ct_totals["total passenger cars"] = df.iloc[19] @@ -280,16 +268,16 @@ def idees_per_country(ct, year, base_dir): ct_totals["electricity light duty road freight"] = df.iloc[49] row = "Heavy duty vehicles (Diesel oil incl. biofuels)" - ct_totals["total heavy duty road freight"] = df.loc[row] + ct_totals["total heavy duty road freight"] = df[row] assert df.index[61] == "Passenger cars" ct_totals["passenger car efficiency"] = df.iloc[61] - df = pd.read_excel(fn_transport, "TrRail_ene", index_col=0) + df = pd.read_excel(fn_transport, "TrRail_ene", index_col=0)[year] - ct_totals["total rail"] = df.loc["by fuel (EUROSTAT DATA)"] + ct_totals["total rail"] = df["by fuel (EUROSTAT DATA)"] - ct_totals["electricity rail"] = df.loc["Electricity"] + ct_totals["electricity rail"] = df["Electricity"] assert df.index[15] == "Passenger transport" ct_totals["total rail passenger"] = df.iloc[15] @@ -305,7 +293,7 @@ def idees_per_country(ct, year, base_dir): assert df.index[23] == "Electric" ct_totals["electricity rail freight"] = df.iloc[23] - df = pd.read_excel(fn_transport, "TrAvia_ene", index_col=0) + df = pd.read_excel(fn_transport, "TrAvia_ene", index_col=0)[year] assert df.index[6] == "Passenger transport" ct_totals["total aviation passenger"] = df.iloc[6] @@ -336,21 +324,20 @@ def idees_per_country(ct, year, base_dir): + ct_totals["total international aviation passenger"] ) - df = pd.read_excel(fn_transport, "TrNavi_ene", index_col=0) + df = pd.read_excel(fn_transport, "TrNavi_ene", index_col=0)[year] # coastal and inland - ct_totals["total domestic navigation"] = df.loc["by fuel (EUROSTAT DATA)"] + ct_totals["total domestic navigation"] = df["by fuel (EUROSTAT DATA)"] - df = pd.read_excel(fn_transport, "TrRoad_act", index_col=0) + df = pd.read_excel(fn_transport, "TrRoad_act", index_col=0)[year] assert df.index[85] == "Passenger cars" ct_totals["passenger cars"] = df.iloc[85] - return pd.DataFrame(ct_totals) + return pd.Series(ct_totals, name=ct) -def build_idees(countries, year=None): - +def build_idees(countries, year): nprocesses = snakemake.threads disable_progress = snakemake.config["run"].get("disable_progressbar", False) @@ -362,49 +349,35 @@ def build_idees(countries, year=None): desc="Build from IDEES database", disable=disable_progress, ) - with mute_print(): with mp.Pool(processes=nprocesses) as pool: totals_list = list(tqdm(pool.imap(func, countries), **tqdm_kwargs)) - totals = pd.concat(totals_list, keys=countries, names=["country", "year"]) + totals = pd.concat(totals_list, axis=1) # convert ktoe to TWh - exclude = totals.columns.str.fullmatch("passenger cars") - totals.loc[:, ~exclude] *= 11.63 / 1e3 + exclude = totals.index.str.fullmatch("passenger cars") + totals.loc[~exclude] *= 11.63 / 1e3 # convert TWh/100km to kWh/km - totals.loc[:, "passenger car efficiency"] *= 10 + totals.loc["passenger car efficiency"] *= 10 - return totals + return totals.T def build_energy_totals(countries, eurostat, swiss, idees): - - eurostat_fuels = dict(electricity="Electricity", total="Total") - - eurostat_sectors = dict( - residential="Households", - services="Commercial & public services", - road="Road", - rail="Rail", - ) + eurostat_fuels = {"electricity": "Electricity", "total": "Total all products"} to_drop = ["passenger cars", "passenger car efficiency"] - - new_index = pd.MultiIndex.from_product( - [countries, eurostat.index.levels[1]], names=["country", "year"] - ) - - df = idees.reindex(new_index).drop(to_drop, axis=1) + df = idees.reindex(countries).drop(to_drop, axis=1) eurostat_countries = eurostat.index.levels[0] - in_eurostat = df.index.levels[0].intersection(eurostat_countries) + in_eurostat = df.index.intersection(eurostat_countries) # add international navigation - slicer = idx[in_eurostat, :, :, "International maritime bunkers", :] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0, 1]).sum() + slicer = idx[in_eurostat, :, "Bunkers", :] + fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() df.loc[in_eurostat, "total international navigation"] = fill_values # add swiss energy data @@ -414,24 +387,19 @@ def build_energy_totals(countries, eurostat, swiss, idees): # get values for missing countries based on Eurostat EnergyBalances # divide cooking/space/water according to averages in EU28 - to_fill = df.index[ - df["total residential"].isna() - & df.index.get_level_values("country").isin(eurostat_countries) - ] + missing = df.index[df["total residential"].isna()] + to_fill = missing.intersection(eurostat_countries) uses = ["space", "cooking", "water"] - c = to_fill.get_level_values("country") - y = to_fill.get_level_values("year") - for sector in ["residential", "services", "road", "rail"]: + eurostat_sector = sector.capitalize() # fuel use for fuel in ["electricity", "total"]: - - slicer = idx[c, y, :, :, eurostat_sectors[sector]] + slicer = idx[to_fill, :, :, eurostat_sector] fill_values = ( - eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=[0, 1]).sum() + eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=0).sum() ) df.loc[to_fill, f"{fuel} {sector}"] = fill_values @@ -493,32 +461,30 @@ def build_energy_totals(countries, eurostat, swiss, idees): no_norway[f"total {sector}"] - no_norway[f"electricity {sector}"] ) fraction = nonelectric_use.div(nonelectric).mean() - df.loc["NO", f"total {sector} {use}"] = ( - total_heating * fraction - ).values + df.loc["NO", f"total {sector} {use}"] = total_heating * fraction df.loc["NO", f"electricity {sector} {use}"] = ( total_heating * fraction * elec_fraction - ).values + ) # Missing aviation - slicer = idx[c, y, :, :, "Domestic aviation"] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0, 1]).sum() + slicer = idx[to_fill, :, :, "Domestic aviation"] + fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() df.loc[to_fill, "total domestic aviation"] = fill_values - slicer = idx[c, y, :, "International aviation", :] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0, 1]).sum() + slicer = idx[to_fill, :, :, "International aviation"] + fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() df.loc[to_fill, "total international aviation"] = fill_values # missing domestic navigation - slicer = idx[c, y, :, :, "Domestic navigation"] - fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0, 1]).sum() + slicer = idx[to_fill, :, :, "Domestic Navigation"] + fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() df.loc[to_fill, "total domestic navigation"] = fill_values # split road traffic for non-IDEES missing = df.index[df["total passenger cars"].isna()] - for fuel in ["electricity", "total"]: + for fuel in ["total", "electricity"]: selection = [ f"{fuel} passenger cars", f"{fuel} other road passenger", @@ -564,9 +530,11 @@ def build_energy_totals(countries, eurostat, swiss, idees): ) if "BA" in df.index: - # fill missing data for BA proportional to RS - ratio = (df.loc["BA"].loc[2014:2020] / df.loc["RS"].loc[2014:2020]).mean() - df.loc["BA"] = (ratio * df.loc["RS"]).values + # fill missing data for BA (services and road energy data) + # proportional to RS with ratio of total residential demand + missing = df.loc["BA"] == 0.0 + ratio = df.at["BA", "total residential"] / df.at["RS", "total residential"] + df.loc["BA", missing] = ratio * df.loc["RS", missing] return df @@ -582,21 +550,18 @@ def build_district_heat_share(countries, idees): district_heat_share = district_heat / total_heat - district_heat_share = district_heat_share.reindex(countries, level="country") + district_heat_share = district_heat_share.reindex(countries) # Missing district heating share - dh_share = pd.read_csv( - snakemake.input.district_heat_share, index_col=0, usecols=[0, 1] + dh_share = ( + pd.read_csv(snakemake.input.district_heat_share, index_col=0, usecols=[0, 1]) + .div(100) + .squeeze() ) - - dh_share = pd.concat( - {y: dh_share for y in range(1990, 2021)}, names=["year", "country"] - ).swaplevel() - dh_share = dh_share.div(100) - dh_share = dh_share.reindex(district_heat_share.index) - # make conservative assumption and take minimum from both data sets - district_heat_share = pd.concat([district_heat_share, dh_share], axis=1).min(axis=1) + district_heat_share = pd.concat( + [district_heat_share, dh_share.reindex_like(district_heat_share)], axis=1 + ).min(axis=1) district_heat_share.name = "district heat share" @@ -613,6 +578,8 @@ def build_eea_co2(input_co2, year=1990, emissions_scope="CO2"): index_col = ["Country_code", "Pollutant_name", "Year", "Sector_name"] df = df.set_index(index_col).sort_index() + emissions_scope = emissions_scope + cts = ["CH", "EUA", "NO"] + eu28_eea slicer = idx[cts, emissions_scope, year, to_ipcc.values()] @@ -658,26 +625,19 @@ def build_eea_co2(input_co2, year=1990, emissions_scope="CO2"): def build_eurostat_co2(input_eurostat, countries, year=1990): eurostat = build_eurostat(input_eurostat, countries, year) - if eurostat is None: - df = build_eurostat(countries, year) - else: - df = eurostat.xs(year, level="year") - - specific_emissions = pd.Series(index=df.columns, dtype=float) + specific_emissions = pd.Series(index=eurostat.columns, dtype=float) # emissions in tCO2_equiv per MWh_th - specific_emissions["Solid fossil fuels"] = 0.36 # Approximates coal - specific_emissions["Oil and petroleum products"] = ( - 0.285 # Average of distillate and residue - ) - specific_emissions["Natural gas"] = 0.2 # For natural gas + specific_emissions["Solid fuels"] = 0.36 # Approximates coal + specific_emissions["Oil (total)"] = 0.285 # Average of distillate and residue + specific_emissions["Gas"] = 0.2 # For natural gas # oil values from https://www.eia.gov/tools/faqs/faq.cfm?id=74&t=11 # Distillate oil (No. 2) 0.276 # Residual oil (No. 6) 0.298 # https://www.eia.gov/electricity/annual/html/epa_a_03.html - return df.multiply(specific_emissions).sum(axis=1) + return eurostat.multiply(specific_emissions).sum(axis=1) def build_co2_totals(countries, eea_co2, eurostat_co2): @@ -884,7 +844,6 @@ if __name__ == "__main__": countries = snakemake.params.countries idees_countries = pd.Index(countries).intersection(eu28) - countries_without_ch = pd.Index(countries).difference(["CH"]) data_year = params["energy_totals_year"] input_eurostat = snakemake.input.eurostat @@ -917,6 +876,5 @@ if __name__ == "__main__": co2 = build_co2_totals(countries, eea_co2, eurostat_co2) co2.to_csv(snakemake.output.co2_name) - idees_transport = idees.xs(data_year, level="year") - transport = build_transport_data(countries, population, idees_transport) + transport = build_transport_data(countries, population, idees) transport.to_csv(snakemake.output.transport_name) From a8682db4fc14c0f6688cccf1de53d6555063c71d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 6 Mar 2024 20:42:45 +0100 Subject: [PATCH 420/591] build_energy_totals: pre-process data for all years first [incomplete] --- scripts/build_energy_totals.py | 303 ++++++++++++++++++++------------- 1 file changed, 186 insertions(+), 117 deletions(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 1ffc4ae2..8e9abb69 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -69,38 +69,58 @@ to_ipcc = { } -def build_eurostat(input_eurostat, countries, year): +def eurostat_per_country(input_eurostat, country): + filename = ( + f"{input_eurostat}/{country}-Energy-balance-sheets-April-2023-edition.xlsb" + ) + sheet = pd.read_excel( + filename, + engine="pyxlsb", + sheet_name=None, + skiprows=4, + index_col=list(range(4)), + ) + sheet.pop("Cover") + return pd.concat(sheet) + + +def build_eurostat(input_eurostat, countries): """ Return multi-index for all countries' energy data in TWh/a. """ - df = {} countries = {idees_rename.get(country, country) for country in countries} - {"CH"} - for country in countries: - filename = ( - f"{input_eurostat}/{country}-Energy-balance-sheets-April-2023-edition.xlsb" - ) - sheet = pd.read_excel( - filename, - engine="pyxlsb", - sheet_name=str(year), - skiprows=4, - index_col=list(range(4)), - ) - df[country] = sheet - df = pd.concat(df, axis=0) + + nprocesses = snakemake.threads + disable_progress = snakemake.config["run"].get("disable_progressbar", False) + + func = partial(eurostat_per_country, input_eurostat) + tqdm_kwargs = dict( + ascii=False, + unit=" country", + total=len(countries), + desc="Build from eurostat database", + disable=disable_progress, + ) + with mute_print(): + with mp.Pool(processes=nprocesses) as pool: + dfs = list(tqdm(pool.imap(func, countries), **tqdm_kwargs)) + + index_names = ["country", "year", "lvl1", "lvl2", "lvl3", "lvl4"] + df = pd.concat(dfs, keys=countries, names=index_names) + df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1) # drop columns with all NaNs unnamed_cols = df.columns[df.columns.astype(str).str.startswith("Unnamed")] df.drop(unnamed_cols, axis=1, inplace=True) - df.drop(year, axis=1, inplace=True) + df.drop(list(range(1990, 2022)), axis=1, inplace=True, errors="ignore") # make numeric values where possible df.replace("Z", 0, inplace=True) df = df.apply(pd.to_numeric, errors="coerce") df = df.select_dtypes(include=[np.number]) - # write 'International aviation' to the 2nd level of the multiindex - int_avia = df.index.get_level_values(2) == "International aviation" + # write 'International aviation' to the lower level of the multiindex + int_avia = df.index.get_level_values(3) == "International aviation" temp = df.loc[int_avia] temp.index = pd.MultiIndex.from_frame( temp.index.to_frame().fillna("International aviation") @@ -113,11 +133,11 @@ def build_eurostat(input_eurostat, countries, year): "Commercial & public services": "Services", "Domestic navigation": "Domestic Navigation", "International maritime bunkers": "Bunkers", + "UK": "GB", } - columns_rename = {"Total": "Total all products", "UK": "GB"} + columns_rename = {"Total": "Total all products"} df.rename(index=index_rename, columns=columns_rename, inplace=True) df.sort_index(inplace=True) - df.index.names = [None] * len(df.index.names) # convert to TWh/a from ktoe/a df *= 11.63 / 1e3 @@ -125,13 +145,21 @@ def build_eurostat(input_eurostat, countries, year): return df -def build_swiss(year): +def build_swiss(): """ - Return a pd.Series of Swiss energy data in TWh/a. + Return a pd.DataFrame of Swiss energy data in TWh/a. """ fn = snakemake.input.swiss - df = pd.read_csv(fn, index_col=[0, 1]).loc["CH", str(year)] + df = pd.read_csv(fn, index_col=[0, 1]) + + df.columns = df.columns.astype(int) + + df.columns.name = "year" + + df = df.stack().unstack("item") + + df.columns.name = None # convert PJ/a to TWh/a df /= 3.6 @@ -139,35 +167,35 @@ def build_swiss(year): return df -def idees_per_country(ct, year, base_dir): +def idees_per_country(ct, base_dir): ct_idees = idees_rename.get(ct, ct) fn_residential = f"{base_dir}/JRC-IDEES-2015_Residential_{ct_idees}.xlsx" fn_tertiary = f"{base_dir}/JRC-IDEES-2015_Tertiary_{ct_idees}.xlsx" fn_transport = f"{base_dir}/JRC-IDEES-2015_Transport_{ct_idees}.xlsx" + ct_totals = {} + # residential - df = pd.read_excel(fn_residential, "RES_hh_fec", index_col=0)[year] + df = pd.read_excel(fn_residential, "RES_hh_fec", index_col=0) rows = ["Advanced electric heating", "Conventional electric heating"] - ct_totals = { - "total residential space": df["Space heating"], - "electricity residential space": df[rows].sum(), - } - ct_totals["total residential water"] = df.at["Water heating"] + ct_totals["electricity residential space"] = df.loc[rows].sum() + ct_totals["total residential space"] = df.loc["Space heating"] + ct_totals["total residential water"] = df.loc["Water heating"] assert df.index[23] == "Electricity" ct_totals["electricity residential water"] = df.iloc[23] - ct_totals["total residential cooking"] = df["Cooking"] + ct_totals["total residential cooking"] = df.loc["Cooking"] assert df.index[30] == "Electricity" ct_totals["electricity residential cooking"] = df.iloc[30] - df = pd.read_excel(fn_residential, "RES_summary", index_col=0)[year] + df = pd.read_excel(fn_residential, "RES_summary", index_col=0) row = "Energy consumption by fuel - Eurostat structure (ktoe)" - ct_totals["total residential"] = df[row] + ct_totals["total residential"] = df.loc[row] assert df.index[47] == "Electricity" ct_totals["electricity residential"] = df.iloc[47] @@ -180,27 +208,27 @@ def idees_per_country(ct, year, base_dir): # services - df = pd.read_excel(fn_tertiary, "SER_hh_fec", index_col=0)[year] + df = pd.read_excel(fn_tertiary, "SER_hh_fec", index_col=0) - ct_totals["total services space"] = df["Space heating"] + ct_totals["total services space"] = df.loc["Space heating"] rows = ["Advanced electric heating", "Conventional electric heating"] - ct_totals["electricity services space"] = df[rows].sum() + ct_totals["electricity services space"] = df.loc[rows].sum() - ct_totals["total services water"] = df["Hot water"] + ct_totals["total services water"] = df.loc["Hot water"] assert df.index[24] == "Electricity" ct_totals["electricity services water"] = df.iloc[24] - ct_totals["total services cooking"] = df["Catering"] + ct_totals["total services cooking"] = df.loc["Catering"] assert df.index[31] == "Electricity" ct_totals["electricity services cooking"] = df.iloc[31] - df = pd.read_excel(fn_tertiary, "SER_summary", index_col=0)[year] + df = pd.read_excel(fn_tertiary, "SER_summary", index_col=0) row = "Energy consumption by fuel - Eurostat structure (ktoe)" - ct_totals["total services"] = df[row] + ct_totals["total services"] = df.loc[row] assert df.index[50] == "Electricity" ct_totals["electricity services"] = df.iloc[50] @@ -216,7 +244,7 @@ def idees_per_country(ct, year, base_dir): start = "Detailed split of energy consumption (ktoe)" end = "Market shares of energy uses (%)" - df = pd.read_excel(fn_tertiary, "AGR_fec", index_col=0).loc[start:end, year] + df = pd.read_excel(fn_tertiary, "AGR_fec", index_col=0).loc[start:end] rows = [ "Lighting", @@ -224,30 +252,30 @@ def idees_per_country(ct, year, base_dir): "Specific electricity uses", "Pumping devices (electric)", ] - ct_totals["total agriculture electricity"] = df[rows].sum() + ct_totals["total agriculture electricity"] = df.loc[rows].sum() rows = ["Specific heat uses", "Low enthalpy heat"] - ct_totals["total agriculture heat"] = df[rows].sum() + ct_totals["total agriculture heat"] = df.loc[rows].sum() rows = [ "Motor drives", "Farming machine drives (diesel oil incl. biofuels)", "Pumping devices (diesel oil incl. biofuels)", ] - ct_totals["total agriculture machinery"] = df[rows].sum() + ct_totals["total agriculture machinery"] = df.loc[rows].sum() row = "Agriculture, forestry and fishing" - ct_totals["total agriculture"] = df[row] + ct_totals["total agriculture"] = df.loc[row] # transport - df = pd.read_excel(fn_transport, "TrRoad_ene", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrRoad_ene", index_col=0) - ct_totals["total road"] = df["by fuel (EUROSTAT DATA)"] + ct_totals["total road"] = df.loc["by fuel (EUROSTAT DATA)"] - ct_totals["electricity road"] = df["Electricity"] + ct_totals["electricity road"] = df.loc["Electricity"] - ct_totals["total two-wheel"] = df["Powered 2-wheelers (Gasoline)"] + ct_totals["total two-wheel"] = df.loc["Powered 2-wheelers (Gasoline)"] assert df.index[19] == "Passenger cars" ct_totals["total passenger cars"] = df.iloc[19] @@ -268,16 +296,16 @@ def idees_per_country(ct, year, base_dir): ct_totals["electricity light duty road freight"] = df.iloc[49] row = "Heavy duty vehicles (Diesel oil incl. biofuels)" - ct_totals["total heavy duty road freight"] = df[row] + ct_totals["total heavy duty road freight"] = df.loc[row] assert df.index[61] == "Passenger cars" ct_totals["passenger car efficiency"] = df.iloc[61] - df = pd.read_excel(fn_transport, "TrRail_ene", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrRail_ene", index_col=0) - ct_totals["total rail"] = df["by fuel (EUROSTAT DATA)"] + ct_totals["total rail"] = df.loc["by fuel (EUROSTAT DATA)"] - ct_totals["electricity rail"] = df["Electricity"] + ct_totals["electricity rail"] = df.loc["Electricity"] assert df.index[15] == "Passenger transport" ct_totals["total rail passenger"] = df.iloc[15] @@ -293,7 +321,7 @@ def idees_per_country(ct, year, base_dir): assert df.index[23] == "Electric" ct_totals["electricity rail freight"] = df.iloc[23] - df = pd.read_excel(fn_transport, "TrAvia_ene", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrAvia_ene", index_col=0) assert df.index[6] == "Passenger transport" ct_totals["total aviation passenger"] = df.iloc[6] @@ -324,24 +352,24 @@ def idees_per_country(ct, year, base_dir): + ct_totals["total international aviation passenger"] ) - df = pd.read_excel(fn_transport, "TrNavi_ene", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrNavi_ene", index_col=0) # coastal and inland - ct_totals["total domestic navigation"] = df["by fuel (EUROSTAT DATA)"] + ct_totals["total domestic navigation"] = df.loc["by fuel (EUROSTAT DATA)"] - df = pd.read_excel(fn_transport, "TrRoad_act", index_col=0)[year] + df = pd.read_excel(fn_transport, "TrRoad_act", index_col=0) assert df.index[85] == "Passenger cars" ct_totals["passenger cars"] = df.iloc[85] - return pd.Series(ct_totals, name=ct) + return pd.DataFrame(ct_totals) -def build_idees(countries, year): +def build_idees(countries): nprocesses = snakemake.threads disable_progress = snakemake.config["run"].get("disable_progressbar", False) - func = partial(idees_per_country, year=year, base_dir=snakemake.input.idees) + func = partial(idees_per_country, base_dir=snakemake.input.idees) tqdm_kwargs = dict( ascii=False, unit=" country", @@ -353,53 +381,67 @@ def build_idees(countries, year): with mp.Pool(processes=nprocesses) as pool: totals_list = list(tqdm(pool.imap(func, countries), **tqdm_kwargs)) - totals = pd.concat(totals_list, axis=1) + totals = pd.concat( + totals_list, + keys=countries, + names=["country", "year"], + ) # convert ktoe to TWh - exclude = totals.index.str.fullmatch("passenger cars") - totals.loc[~exclude] *= 11.63 / 1e3 + exclude = totals.columns.str.fullmatch("passenger cars") + totals.loc[:, ~exclude] *= 11.63 / 1e3 # convert TWh/100km to kWh/km - totals.loc["passenger car efficiency"] *= 10 + totals.loc[:, "passenger car efficiency"] *= 10 - return totals.T + return totals def build_energy_totals(countries, eurostat, swiss, idees): eurostat_fuels = {"electricity": "Electricity", "total": "Total all products"} + eurostat_countries = eurostat.index.levels[0] + eurostat_years = eurostat.index.levels[1] to_drop = ["passenger cars", "passenger car efficiency"] - df = idees.reindex(countries).drop(to_drop, axis=1) + new_index = pd.MultiIndex.from_product( + [countries, eurostat_years], names=["country", "year"] + ) - eurostat_countries = eurostat.index.levels[0] - in_eurostat = df.index.intersection(eurostat_countries) + df = idees.reindex(new_index).drop(to_drop, axis=1) + + in_eurostat = df.index.levels[0].intersection(eurostat_countries) # add international navigation - slicer = idx[in_eurostat, :, "Bunkers", :] - fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() + slicer = idx[in_eurostat, :, :, "Bunkers", :] + fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=[0, 1]).sum() df.loc[in_eurostat, "total international navigation"] = fill_values # add swiss energy data - df.loc["CH"] = swiss + df = pd.concat([df.drop("CH"), swiss]).sort_index() # get values for missing countries based on Eurostat EnergyBalances # divide cooking/space/water according to averages in EU28 - missing = df.index[df["total residential"].isna()] - to_fill = missing.intersection(eurostat_countries) uses = ["space", "cooking", "water"] + to_fill = df.index[ + df["total residential"].isna() + & df.index.get_level_values("country").isin(eurostat_countries) + ] + c = to_fill.get_level_values("country") + y = to_fill.get_level_values("year") + for sector in ["residential", "services", "road", "rail"]: eurostat_sector = sector.capitalize() # fuel use for fuel in ["electricity", "total"]: - slicer = idx[to_fill, :, :, eurostat_sector] + slicer = idx[c, y, :, :, eurostat_sector] fill_values = ( - eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=0).sum() + eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=[0, 1]).sum() ) df.loc[to_fill, f"{fuel} {sector}"] = fill_values @@ -461,25 +503,27 @@ def build_energy_totals(countries, eurostat, swiss, idees): no_norway[f"total {sector}"] - no_norway[f"electricity {sector}"] ) fraction = nonelectric_use.div(nonelectric).mean() - df.loc["NO", f"total {sector} {use}"] = total_heating * fraction + df.loc["NO", f"total {sector} {use}"] = ( + total_heating * fraction + ).values df.loc["NO", f"electricity {sector} {use}"] = ( total_heating * fraction * elec_fraction - ) + ).values # Missing aviation - slicer = idx[to_fill, :, :, "Domestic aviation"] - fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() + slicer = idx[c, y, :, :, "Domestic aviation"] + fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=[0, 1]).sum() df.loc[to_fill, "total domestic aviation"] = fill_values - slicer = idx[to_fill, :, :, "International aviation"] - fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() + slicer = idx[c, y, :, :, "International aviation"] + fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=[0, 1]).sum() df.loc[to_fill, "total international aviation"] = fill_values # missing domestic navigation - slicer = idx[to_fill, :, :, "Domestic Navigation"] - fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=0).sum() + slicer = idx[c, y, :, :, "Domestic Navigation"] + fill_values = eurostat.loc[slicer, "Total all products"].groupby(level=[0, 1]).sum() df.loc[to_fill, "total domestic navigation"] = fill_values # split road traffic for non-IDEES @@ -532,9 +576,11 @@ def build_energy_totals(countries, eurostat, swiss, idees): if "BA" in df.index: # fill missing data for BA (services and road energy data) # proportional to RS with ratio of total residential demand - missing = df.loc["BA"] == 0.0 - ratio = df.at["BA", "total residential"] / df.at["RS", "total residential"] - df.loc["BA", missing] = ratio * df.loc["RS", missing] + mean_BA = df.loc["BA"].loc[2014:2021, "total residential"].mean() + mean_RS = df.loc["RS"].loc[2014:2021, "total residential"].mean() + ratio = mean_BA / mean_RS + df.loc["BA"] = df.loc["BA"].replace(0.0, np.nan).values + df.loc["BA"] = df.loc["BA"].combine_first(ratio * df.loc["RS"]).values return df @@ -550,7 +596,7 @@ def build_district_heat_share(countries, idees): district_heat_share = district_heat / total_heat - district_heat_share = district_heat_share.reindex(countries) + district_heat_share = district_heat_share.reindex(countries, level="country") # Missing district heating share dh_share = ( @@ -578,8 +624,6 @@ def build_eea_co2(input_co2, year=1990, emissions_scope="CO2"): index_col = ["Country_code", "Pollutant_name", "Year", "Sector_name"] df = df.set_index(index_col).sort_index() - emissions_scope = emissions_scope - cts = ["CH", "EUA", "NO"] + eu28_eea slicer = idx[cts, emissions_scope, year, to_ipcc.values()] @@ -622,8 +666,8 @@ def build_eea_co2(input_co2, year=1990, emissions_scope="CO2"): return emissions / 1e3 -def build_eurostat_co2(input_eurostat, countries, year=1990): - eurostat = build_eurostat(input_eurostat, countries, year) +def build_eurostat_co2(eurostat, year=1990): + eurostat_year = eurostat.xs(year, level="year") specific_emissions = pd.Series(index=eurostat.columns, dtype=float) @@ -637,7 +681,7 @@ def build_eurostat_co2(input_eurostat, countries, year=1990): # Residual oil (No. 6) 0.298 # https://www.eia.gov/electricity/annual/html/epa_a_03.html - return eurostat.multiply(specific_emissions).sum(axis=1) + return eurostat_year.multiply(specific_emissions).sum(axis=1) def build_co2_totals(countries, eea_co2, eurostat_co2): @@ -704,7 +748,9 @@ def build_transport_data(countries, population, idees): def rescale_idees_from_eurostat( - idees_countries, energy, eurostat, input_eurostat, countries + idees_countries, + energy, + eurostat, ): """ Takes JRC IDEES data from 2015 and rescales it by the ratio of the eurostat @@ -714,11 +760,10 @@ def rescale_idees_from_eurostat( """ main_cols = ["Total all products", "Electricity"] # read in the eurostat data for 2015 - eurostat_2015 = build_eurostat(input_eurostat, countries, 2015)[main_cols] - eurostat_year = eurostat[main_cols] + eurostat_2015 = eurostat.xs(2015, level="year")[main_cols] # calculate the ratio of the two data sets - ratio = eurostat_year / eurostat_2015 - ratio = ratio.droplevel([1, 4]) + ratio = eurostat[main_cols] / eurostat_2015 + ratio = ratio.droplevel([2, 5]) cols_rename = {"Total all products": "total", "Electricity": "ele"} index_rename = {v: k for k, v in idees_rename.items()} ratio.rename(columns=cols_rename, index=index_rename, inplace=True) @@ -811,19 +856,45 @@ def rescale_idees_from_eurostat( ] for country in idees_countries: + slicer_target = idx[country, 2016:2021, :, :] + slicer_source = idx[country, 2015, :, :] for sector, mapping in mappings.items(): - sector_ratio = ratio.loc[(country, slice(None), sector)] + sector_ratio = ratio.loc[(country, slice(None), slice(None), sector)].droplevel("lvl2") - energy.loc[country, mapping["total"]] *= sector_ratio["total"].iloc[0] - energy.loc[country, mapping["elec"]] *= sector_ratio["ele"].iloc[0] + energy.loc[slicer_target, mapping["total"]] = cartesian( + sector_ratio.loc[2016:2021, "total"], + energy.loc[slicer_source, mapping["total"]].squeeze() + ).values + energy.loc[slicer_target, mapping["elec"]] = cartesian( + sector_ratio.loc[2016:2021, "ele"], + energy.loc[slicer_source, mapping["elec"]].squeeze() + ).values - avi_d = ratio.loc[(country, slice(None), "Domestic aviation"), "total"] - avi_i = ratio.loc[(country, "International aviation", slice(None)), "total"] - energy.loc[country, avia_inter] *= avi_i.iloc[0] - energy.loc[country, avia_domestic] *= avi_d.iloc[0] + level_drops = ["country", "lvl2", "lvl3"] - nav = ratio.loc[(country, slice(None), "Domestic Navigation"), "total"] - energy.loc[country, navigation] *= nav.iloc[0] + slicer = idx[country, :, :, "Domestic aviation"] + avi_d = ratio.loc[slicer, "total"].droplevel(level_drops) + + slicer = idx[country, :, :, "International aviation"] + avi_i = ratio.loc[slicer, "total"].droplevel(level_drops) + + slicer = idx[country, :, :, "Domestic Navigation"] + nav = ratio.loc[slicer, "total"].droplevel(level_drops) + + energy.loc[slicer_target, avia_inter] = cartesian( + avi_i.loc[2016:2021], + energy.loc[slicer_source, avia_inter].squeeze() + ).values + + energy.loc[slicer_target, avia_domestic] = cartesian( + avi_d.loc[2016:2021], + energy.loc[slicer_source, avia_domestic].squeeze() + ).values + + energy.loc[slicer_target, navigation] = cartesian( + nav.loc[2016:2021], + energy.loc[slicer_source, navigation] + ).values return energy @@ -845,20 +916,18 @@ if __name__ == "__main__": countries = snakemake.params.countries idees_countries = pd.Index(countries).intersection(eu28) - data_year = params["energy_totals_year"] input_eurostat = snakemake.input.eurostat - eurostat = build_eurostat(input_eurostat, countries, data_year) - swiss = build_swiss(data_year) - # data from idees only exists from 2000-2015. read in latest data and rescale later - idees = build_idees(idees_countries, min(2015, data_year)) + eurostat = build_eurostat(input_eurostat, countries) + swiss = build_swiss() + idees = build_idees(idees_countries) energy = build_energy_totals(countries, eurostat, swiss, idees) - if data_year > 2015: - logger.info("Data year is after 2015. Rescaling IDEES data based on eurostat.") - energy = rescale_idees_from_eurostat( - idees_countries, energy, eurostat, input_eurostat, countries - ) + # Data from IDEES only exists from 2000-2015. + logger.info("Extrapolate IDEES data based on eurostat for years 2015-2021.") + energy = rescale_idees_from_eurostat( + idees_countries, energy, eurostat + ) energy.to_csv(snakemake.output.energy_name) @@ -871,7 +940,7 @@ if __name__ == "__main__": base_year_emissions = params["base_emissions_year"] emissions_scope = snakemake.params.energy["emissions"] eea_co2 = build_eea_co2(snakemake.input.co2, base_year_emissions, emissions_scope) - eurostat_co2 = build_eurostat_co2(input_eurostat, countries, base_year_emissions) + eurostat_co2 = build_eurostat_co2(eurostat, base_year_emissions) co2 = build_co2_totals(countries, eea_co2, eurostat_co2) co2.to_csv(snakemake.output.co2_name) From d2968230bbdfa07324c37b383f2a16211fdb7780 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 19:43:30 +0000 Subject: [PATCH 421/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/build_energy_totals.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 8e9abb69..368d7206 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -859,15 +859,17 @@ def rescale_idees_from_eurostat( slicer_target = idx[country, 2016:2021, :, :] slicer_source = idx[country, 2015, :, :] for sector, mapping in mappings.items(): - sector_ratio = ratio.loc[(country, slice(None), slice(None), sector)].droplevel("lvl2") + sector_ratio = ratio.loc[ + (country, slice(None), slice(None), sector) + ].droplevel("lvl2") energy.loc[slicer_target, mapping["total"]] = cartesian( sector_ratio.loc[2016:2021, "total"], - energy.loc[slicer_source, mapping["total"]].squeeze() + energy.loc[slicer_source, mapping["total"]].squeeze(), ).values energy.loc[slicer_target, mapping["elec"]] = cartesian( sector_ratio.loc[2016:2021, "ele"], - energy.loc[slicer_source, mapping["elec"]].squeeze() + energy.loc[slicer_source, mapping["elec"]].squeeze(), ).values level_drops = ["country", "lvl2", "lvl3"] @@ -882,18 +884,15 @@ def rescale_idees_from_eurostat( nav = ratio.loc[slicer, "total"].droplevel(level_drops) energy.loc[slicer_target, avia_inter] = cartesian( - avi_i.loc[2016:2021], - energy.loc[slicer_source, avia_inter].squeeze() + avi_i.loc[2016:2021], energy.loc[slicer_source, avia_inter].squeeze() ).values energy.loc[slicer_target, avia_domestic] = cartesian( - avi_d.loc[2016:2021], - energy.loc[slicer_source, avia_domestic].squeeze() + avi_d.loc[2016:2021], energy.loc[slicer_source, avia_domestic].squeeze() ).values energy.loc[slicer_target, navigation] = cartesian( - nav.loc[2016:2021], - energy.loc[slicer_source, navigation] + nav.loc[2016:2021], energy.loc[slicer_source, navigation] ).values return energy @@ -925,9 +924,7 @@ if __name__ == "__main__": # Data from IDEES only exists from 2000-2015. logger.info("Extrapolate IDEES data based on eurostat for years 2015-2021.") - energy = rescale_idees_from_eurostat( - idees_countries, energy, eurostat - ) + energy = rescale_idees_from_eurostat(idees_countries, energy, eurostat) energy.to_csv(snakemake.output.energy_name) From 3d94e8161bada538b08d2fbed1de3ada01c00e58 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 28 Feb 2024 14:01:36 +0000 Subject: [PATCH 422/591] Adapt disabling transmission expansion to also handle cost limit --- scripts/add_brownfield.py | 66 ++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 1e175d87..1bccf563 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -124,29 +124,57 @@ def add_brownfield(n, n_p, year): n.links.loc[new_pipes, "p_nom_min"] = 0.0 -def disable_grid_expansion_if_LV_limit_hit(n): - if "lv_limit" not in n.global_constraints.index: - return +def disable_grid_expansion_if_limit_hit(n): + """ + Check if transmission expansion limit is already reached; then turn off. - total_expansion = ( - n.lines.eval("s_nom_min * length").sum() - + n.links.query("carrier == 'DC'").eval("p_nom_min * length").sum() - ).sum() + In particular, this function checks if the total transmission + capital cost or volume implied by s_nom_min and p_nom_min are + numerically close to the respective global limit set in + n.global_constraints. If so, the nominal capacities are set to the + minimum and extendable is turned off; the corresponding global + constraint is then dropped. + """ + cols = {"cost": "capital_cost", "volume": "length"} + for limit_type in ["cost", "volume"]: + glcs = n.global_constraints.query( + f"type == 'transmission_expansion_{limit_type}_limit'" + ) - lv_limit = n.global_constraints.at["lv_limit", "constant"] + for name, glc in glcs.iterrows(): + total_expansion = ( + ( + n.lines.query("p_nom_extendable") + .eval(f"s_nom_min * {cols[limit_type]}") + .sum() + ) + + ( + n.links.query("carrier == 'DC' and p_nom_extendable") + .eval(f"p_nom_min * {cols[limit_type]}") + .sum() + ) + ).sum() - # allow small numerical differences - if lv_limit - total_expansion < 1: - logger.info("LV is already reached, disabling expansion and LV limit") - extendable_acs = n.lines.query("s_nom_extendable").index - n.lines.loc[extendable_acs, "s_nom_extendable"] = False - n.lines.loc[extendable_acs, "s_nom"] = n.lines.loc[extendable_acs, "s_nom_min"] + # Allow small numerical differences + if np.abs(glc.constant - total_expansion) / glc.constant < 1e-6: + logger.info( + f"Transmission expansion {limit_type} is already reached, disabling expansion and limit" + ) + extendable_acs = n.lines.query("s_nom_extendable").index + n.lines.loc[extendable_acs, "s_nom_extendable"] = False + n.lines.loc[extendable_acs, "s_nom"] = n.lines.loc[ + extendable_acs, "s_nom_min" + ] - extendable_dcs = n.links.query("carrier == 'DC' and p_nom_extendable").index - n.links.loc[extendable_dcs, "p_nom_extendable"] = False - n.links.loc[extendable_dcs, "p_nom"] = n.links.loc[extendable_dcs, "p_nom_min"] + extendable_dcs = n.links.query( + "carrier == 'DC' and p_nom_extendable" + ).index + n.links.loc[extendable_dcs, "p_nom_extendable"] = False + n.links.loc[extendable_dcs, "p_nom"] = n.links.loc[ + extendable_dcs, "p_nom_min" + ] - n.global_constraints.drop("lv_limit", inplace=True) + n.global_constraints.drop(name, inplace=True) def adjust_renewable_profiles(n, input_profiles, params, year): @@ -233,7 +261,7 @@ if __name__ == "__main__": add_brownfield(n, n_p, year) - disable_grid_expansion_if_LV_limit_hit(n) + disable_grid_expansion_if_limit_hit(n) n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) n.export_to_netcdf(snakemake.output[0]) From 61e4123176cc97cb7d9942e7e9e4ede04d13a42d Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 28 Feb 2024 15:11:32 +0100 Subject: [PATCH 423/591] Add release note --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d6072d7d..612cb1a5 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -81,6 +81,8 @@ Upcoming Release * Bugfix: allow modelling sector-coupled landlocked regions. (Fixed handling of offshore wind.) +* Adapt the disabling of transmission expansion in myopic foresight optimisations when limit is already reached to also handle cost limits. + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== From 09502cfbfa6034023505403449ff9db8135a7de7 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 8 Mar 2024 11:26:00 +0100 Subject: [PATCH 424/591] add memory logger to solve_sector_network_myopic rule --- rules/solve_myopic.smk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 5eb30233..a081fbe6 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -126,6 +126,8 @@ rule solve_sector_network_myopic: log: solver=RESULTS + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_solver.log", + memory=RESULTS + + "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: solver_threads From b6542d275f20696a3d223b24d3ee76a50e734ae2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 8 Mar 2024 17:45:54 +0100 Subject: [PATCH 425/591] add snakemake slurm plugin to env --- envs/environment.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/envs/environment.yaml b/envs/environment.yaml index 36dbfcae..3b85f7a9 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -60,3 +60,4 @@ dependencies: - pip: - tsam>=2.3.1 - snakemake-storage-plugin-http + - snakemake-executor-plugin-slurm From 105dc6470aeb48bf64fbdc2f0bc3c89dcc61bca5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 8 Mar 2024 17:51:02 +0100 Subject: [PATCH 426/591] replace remaining instances of HTTP.remote --- rules/build_sector.smk | 4 ++-- rules/retrieve.smk | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 36e20590..13565111 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -325,7 +325,7 @@ rule build_biomass_potentials: rule build_biomass_transport_costs: input: - transport_cost_data=HTTP.remote( + transport_cost_data=storage( "publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", keep_local=True, ), @@ -350,7 +350,7 @@ rule build_sequestration_potentials: "sector", "regional_co2_sequestration_potential" ), input: - sequestration_potential=HTTP.remote( + sequestration_potential=storage( "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", keep_local=True, ), diff --git a/rules/retrieve.smk b/rules/retrieve.smk index beae4f9c..6a54b4d1 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -236,7 +236,7 @@ if config["enable"]["retrieve"]: # Website: https://ec.europa.eu/jrc/en/luisa rule retrieve_luisa_land_cover: input: - HTTP.remote( + storage( "jeodpp.jrc.ec.europa.eu/ftp/jrc-opendata/LUISA/EUROPE/Basemaps/LandUse/2018/LATEST/LUISA_basemap_020321_50m.tif", static=True, ), From ab14c31f551fa6f461b9fc0b792eb4c606688562 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 8 Mar 2024 19:15:51 +0100 Subject: [PATCH 427/591] build_electricity_demand adjustment to reduced function arguments --- scripts/build_electricity_demand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 47befb8a..51dc6efd 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -273,7 +273,7 @@ if __name__ == "__main__": if "UA" in countries: # attach load of UA (best data only for entsoe transparency) - load_ua = load_timeseries(snakemake.input[0], "2018", ["UA"], False) + load_ua = load_timeseries(snakemake.input[0], "2018", ["UA"]) snapshot_year = str(snapshots.year.unique().item()) time_diff = pd.Timestamp("2018") - pd.Timestamp(snapshot_year) load_ua.index -= ( From d7ebeb384338a79b8e191dd5c4df62f33de60902 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 8 Mar 2024 19:16:30 +0100 Subject: [PATCH 428/591] custom_powerplants: correct coordinates of some UA powerplants --- data/custom_powerplants.csv | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/data/custom_powerplants.csv b/data/custom_powerplants.csv index 4fd47498..84553a74 100644 --- a/data/custom_powerplants.csv +++ b/data/custom_powerplants.csv @@ -2,36 +2,36 @@ 1266,Khmelnitskiy,Nuclear,,PP,UA,1901.8916595755832,,0.0,0.0,0.0,0.0,1988.0,2005.0,,,50.3023,26.6466,[nan],"{'GEO': ['GEO3842'], 'GPD': ['WRI1005111'], 'CARMA': ['CARMA22000']}" 1268,Kaniv,Hydro,Reservoir,PP,UA,452.1656050955414,,0.0,0.0,0.0,0.0,1972.0,2003.0,,,49.76653,31.47165,[nan],"{'GEO': ['GEO43017'], 'GPD': ['WRI1005122'], 'CARMA': ['CARMA21140']}" 1269,Kahovska kakhovka,Hydro,Reservoir,PP,UA,352.45222929936307,,0.0,0.0,0.0,0.0,1955.0,1956.0,,,46.77858,33.36965,[nan],"{'GEO': ['GEO43018'], 'GPD': ['WRI1005118'], 'CARMA': ['CARMA20855']}" -1347,Kharkiv,Natural Gas,Steam Turbine,CHP,UA,494.94274967602314,,0.0,0.0,0.0,0.0,1979.0,1980.0,,,49.9719,36107,[nan],"{'GEO': ['GEO43027'], 'GPD': ['WRI1005126'], 'CARMA': ['CARMA21972']}" +1347,Kharkiv,Natural Gas,Steam Turbine,CHP,UA,494.94274967602314,,0.0,0.0,0.0,0.0,1979.0,1980.0,,,49.9719,36.107,[nan],"{'GEO': ['GEO43027'], 'GPD': ['WRI1005126'], 'CARMA': ['CARMA21972']}" 1348,Kremenchuk,Hydro,Reservoir,PP,UA,617.0382165605096,,0.0,0.0,0.0,0.0,1959.0,1960.0,,,49.07759,33.2505,[nan],"{'GEO': ['GEO43019'], 'GPD': ['WRI1005121'], 'CARMA': ['CARMA23072']}" 1377,Krivorozhskaya,Hard Coal,Steam Turbine,PP,UA,2600.0164509342876,,0.0,0.0,0.0,0.0,1965.0,1992.0,,,47.5432,33.6583,[nan],"{'GEO': ['GEO42989'], 'GPD': ['WRI1005100'], 'CARMA': ['CARMA23176']}" 1407,Zmiyevskaya zmiivskaya,Hard Coal,Steam Turbine,PP,UA,2028.3816283884514,,0.0,0.0,0.0,0.0,1960.0,2005.0,,,49.5852,36.5231,[nan],"{'GEO': ['GEO42999'], 'GPD': ['WRI1005103'], 'CARMA': ['CARMA51042']}" 1408,Pridneprovskaya,Hard Coal,Steam Turbine,CHP,UA,1627.3152609570984,,0.0,0.0,0.0,0.0,1959.0,1966.0,,,48.4051,35.1131,[nan],"{'GEO': ['GEO42990'], 'GPD': ['WRI1005102'], 'CARMA': ['CARMA35874']}" 1409,Kurakhovskaya,Hard Coal,Steam Turbine,PP,UA,1371.0015824607397,,0.0,0.0,0.0,0.0,1972.0,2003.0,,,47.9944,37.24022,[nan],"{'GEO': ['GEO42994'], 'GPD': ['WRI1005104'], 'CARMA': ['CARMA23339']}" -1410,Dobrotvorsky,Hard Coal,Steam Turbine,PP,UA,553.1949895604868,,0.0,0.0,0.0,0.0,1960.0,1964.0,,,50.2133,24375,[nan],"{'GEO': ['GEO42992'], 'GPD': ['WRI1005096'], 'CARMA': ['CARMA10971']}" +1410,Dobrotvorsky,Hard Coal,Steam Turbine,PP,UA,553.1949895604868,,0.0,0.0,0.0,0.0,1960.0,1964.0,,,50.2133,24.375,[nan],"{'GEO': ['GEO42992'], 'GPD': ['WRI1005096'], 'CARMA': ['CARMA10971']}" 1422,Zuyevskaya,Hard Coal,Steam Turbine,PP,UA,1147.87960333801,,0.0,0.0,0.0,0.0,1982.0,2007.0,,,48.0331,38.28615,[nan],"{'GEO': ['GEO42995'], 'GPD': ['WRI1005106'], 'CARMA': ['CARMA51083']}" 1423,Zaporozhye,Nuclear,,PP,UA,5705.67497872675,,0.0,0.0,0.0,0.0,1985.0,1996.0,,,47.5119,34.5863,[nan],"{'GEO': ['GEO6207'], 'GPD': ['WRI1005114'], 'CARMA': ['CARMA50875']}" 1424,Trypilska,Hard Coal,Steam Turbine,PP,UA,1659.5849686814602,,0.0,0.0,0.0,0.0,1969.0,1972.0,,,50.1344,30.7468,[nan],"{'GEO': ['GEO43000'], 'GPD': ['WRI1005099'], 'CARMA': ['CARMA46410']}" 1425,Tashlyk,Hydro,Pumped Storage,Store,UA,285.55968954109585,,0.0,0.0,0.0,0.0,2006.0,2007.0,,,47.7968,31.1811,[nan],"{'GEO': ['GEO43025'], 'GPD': ['WRI1005117'], 'CARMA': ['CARMA44696']}" 1426,Starobeshivska,Hard Coal,Steam Turbine,PP,UA,1636.5351774497733,,0.0,0.0,0.0,0.0,1961.0,1967.0,,,47.7997,38.00612,[nan],"{'GEO': ['GEO43003'], 'GPD': ['WRI1005105'], 'CARMA': ['CARMA43083']}" -1427,South,Nuclear,,PP,UA,2852.837489363375,,0.0,0.0,0.0,0.0,1983.0,1989.0,,,47812,31.22,[nan],"{'GEO': ['GEO5475'], 'GPD': ['WRI1005113'], 'CARMA': ['CARMA42555']}" +1427,South,Nuclear,,PP,UA,2852.837489363375,,0.0,0.0,0.0,0.0,1983.0,1989.0,,,47.812,31.22,[nan],"{'GEO': ['GEO5475'], 'GPD': ['WRI1005113'], 'CARMA': ['CARMA42555']}" 1428,Rovno rivne,Nuclear,,PP,UA,2695.931427448389,,0.0,0.0,0.0,0.0,1981.0,2006.0,,,51.3245,25.89744,[nan],"{'GEO': ['GEO5174'], 'GPD': ['WRI1005112'], 'CARMA': ['CARMA38114']}" -1429,Ladyzhinska,Hard Coal,Steam Turbine,PP,UA,1659.5849686814602,,0.0,0.0,0.0,0.0,1970.0,1971.0,,,48706,29.2202,[nan],"{'GEO': ['GEO42993'], 'GPD': ['WRI1005098'], 'CARMA': ['CARMA24024']}" -1430,Kiev,Hydro,Pumped Storage,PP,UA,635.8694635681177,,0.0,0.0,0.0,0.0,1964.0,1972.0,,,50.5998,30501,"[nan, nan]","{'GEO': ['GEO43024', 'GEO43023'], 'GPD': ['WRI1005123', 'WRI1005124'], 'CARMA': ['CARMA23516', 'CARMA23517']}" +1429,Ladyzhinska,Hard Coal,Steam Turbine,PP,UA,1659.5849686814602,,0.0,0.0,0.0,0.0,1970.0,1971.0,,,48.706,29.2202,[nan],"{'GEO': ['GEO42993'], 'GPD': ['WRI1005098'], 'CARMA': ['CARMA24024']}" +1430,Kiev,Hydro,Pumped Storage,PP,UA,635.8694635681177,,0.0,0.0,0.0,0.0,1964.0,1972.0,,,50.5998,30.501,"[nan, nan]","{'GEO': ['GEO43024', 'GEO43023'], 'GPD': ['WRI1005123', 'WRI1005124'], 'CARMA': ['CARMA23516', 'CARMA23517']}" 2450,Cet chisinau,Natural Gas,,PP,MD,306.0,,0.0,0.0,0.0,0.0,,,,,47.027550000000005,28.8801,"[nan, nan]","{'GPD': ['WRI1002985', 'WRI1002984'], 'CARMA': ['CARMA8450', 'CARMA8451']}" 2460,Hydropower che costesti,Hydro,,PP,MD,16.0,,0.0,0.0,0.0,0.0,1978.0,,,,47.8381,27.2246,[nan],"{'GPD': ['WRI1002987'], 'CARMA': ['CARMA9496']}" 2465,Moldavskaya gres,Hard Coal,,PP,MD,2520.0,,0.0,0.0,0.0,0.0,,,,,46.6292,29.9407,[nan],"{'GPD': ['WRI1002989'], 'CARMA': ['CARMA28979']}" -2466,Hydropower dubasari,Hydro,,PP,MD,48.0,,0.0,0.0,0.0,0.0,,,,,47.2778,29123,[nan],"{'GPD': ['WRI1002988'], 'CARMA': ['CARMA11384']}" +2466,Hydropower dubasari,Hydro,,PP,MD,48.0,,0.0,0.0,0.0,0.0,,,,,47.2778,29.123,[nan],"{'GPD': ['WRI1002988'], 'CARMA': ['CARMA11384']}" 2676,Cet nord balti,Natural Gas,,PP,MD,24.0,,0.0,0.0,0.0,0.0,,,,,47.7492,27.8938,[nan],"{'GPD': ['WRI1002986'], 'CARMA': ['CARMA3071']}" 2699,Dniprodzerzhynsk,Hydro,Reservoir,PP,UA,360.3503184713376,,0.0,0.0,0.0,0.0,1963.0,1964.0,,,48.5485,34.541015,[nan],"{'GEO': ['GEO43020'], 'GPD': ['WRI1005119']}" 2707,Burshtynska tes,Hard Coal,Steam Turbine,PP,UA,2212.779958241947,,0.0,0.0,0.0,0.0,1965.0,1984.0,,,49.21038,24.66654,[nan],"{'GEO': ['GEO42991'], 'GPD': ['WRI1005097']}" 2708,Danipro dnieper,Hydro,Reservoir,PP,UA,1484.8407643312103,,0.0,0.0,0.0,0.0,1932.0,1947.0,,,47.86944,35.08611,[nan],"{'GEO': ['GEO43016'], 'GPD': ['WRI1005120']}" 2709,Dniester,Hydro,Pumped Storage,Store,UA,612.7241020616891,,0.0,0.0,0.0,0.0,2009.0,2011.0,,,48.51361,27.47333,[nan],"{'GEO': ['GEO43022'], 'GPD': ['WRI1005116', 'WRI1005115']}" -2710,Kiev,Natural Gas,Steam Turbine,CHP,UA,458.2803237740955,,0.0,0.0,0.0,0.0,1982.0,1984.0,,,50532,30.6625,[nan],"{'GEO': ['GEO42998'], 'GPD': ['WRI1005125']}" +2710,Kiev,Natural Gas,Steam Turbine,CHP,UA,458.2803237740955,,0.0,0.0,0.0,0.0,1982.0,1984.0,,,50.532,30.6625,[nan],"{'GEO': ['GEO42998'], 'GPD': ['WRI1005125']}" 2712,Luganskaya,Hard Coal,Steam Turbine,PP,UA,1060.2903966575996,,0.0,0.0,0.0,0.0,1962.0,1969.0,,,48.74781,39.2624,[nan],"{'GEO': ['GEO42996'], 'GPD': ['WRI1005110']}" -2713,Slavyanskaya,Hard Coal,Steam Turbine,PP,UA,737.5933194139823,,0.0,0.0,0.0,0.0,1971.0,1971.0,,,48872,37.76567,[nan],"{'GEO': ['GEO43002'], 'GPD': ['WRI1005109']}" +2713,Slavyanskaya,Hard Coal,Steam Turbine,PP,UA,737.5933194139823,,0.0,0.0,0.0,0.0,1971.0,1971.0,,,48.872,37.76567,[nan],"{'GEO': ['GEO43002'], 'GPD': ['WRI1005109']}" 2714,Vuhlehirska uglegorskaya,Hard Coal,Steam Turbine,PP,UA,3319.1699373629203,,0.0,0.0,0.0,0.0,1972.0,1977.0,,,48.4633,38.20328,[nan],"{'GEO': ['GEO43001'], 'GPD': ['WRI1005107']}" 2715,Zaporiska,Hard Coal,Steam Turbine,PP,UA,3319.1699373629203,,0.0,0.0,0.0,0.0,1972.0,1977.0,,,47.5089,34.6253,[nan],"{'GEO': ['GEO42988'], 'GPD': ['WRI1005101']}" 3678,Mironovskaya,Hard Coal,,PP,UA,815.0,,0.0,0.0,0.0,0.0,,,,,48.3407,38.4049,[nan],"{'GPD': ['WRI1005108'], 'CARMA': ['CARMA28679']}" 3679,Kramatorskaya,Hard Coal,,PP,UA,120.0,,0.0,0.0,0.0,0.0,1974.0,,,,48.7477,37.5723,[nan],"{'GPD': ['WRI1075856'], 'CARMA': ['CARMA54560']}" -3680,Chernihiv,Hard Coal,,PP,UA,200.0,,0.0,0.0,0.0,0.0,1968.0,,,,51455,31.2602,[nan],"{'GPD': ['WRI1075853'], 'CARMA': ['CARMA8190']}" +3680,Chernihiv,Hard Coal,,PP,UA,200.0,,0.0,0.0,0.0,0.0,1968.0,,,,51.455,31.2602,[nan],"{'GPD': ['WRI1075853'], 'CARMA': ['CARMA8190']}" From 008539d635c1da9fff3d4852bd0ac0444e9cd52c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 8 Mar 2024 19:29:25 +0100 Subject: [PATCH 429/591] add_electricity: fill max_hours also for nan values --- scripts/add_electricity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index a799caec..06f6348d 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -586,7 +586,7 @@ def attach_hydro(n, costs, ppl, profile_hydro, hydro_capacities, carriers, **par # fill missing max hours to params value and # assume no natural inflow due to lack of data max_hours = params.get("PHS_max_hours", 6) - phs = phs.replace({"max_hours": {0: max_hours}}) + phs = phs.replace({"max_hours": {0: max_hours, np.nan: max_hours}}) n.madd( "StorageUnit", phs.index, From c8eb46a39c7bced4c8038c627ff373c3cbe2ea4f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 9 Mar 2024 12:07:15 +0100 Subject: [PATCH 430/591] add generic cluster snakemake plugin --- envs/environment.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/envs/environment.yaml b/envs/environment.yaml index 316a662c..a5323923 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -62,4 +62,5 @@ dependencies: - tsam>=2.3.1 - snakemake-storage-plugin-http - snakemake-executor-plugin-slurm + - snakemake-executor-plugin-cluster-generic - highspy From 45e955a0d894f8885c73a5c8cb5664f3ea90b3f3 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 9 Mar 2024 12:07:47 +0100 Subject: [PATCH 431/591] add https:// prefix for all storage() calls --- rules/build_sector.smk | 2 +- rules/retrieve.smk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 13565111..8d41e893 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -326,7 +326,7 @@ rule build_biomass_potentials: rule build_biomass_transport_costs: input: transport_cost_data=storage( - "publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", + "https://publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", keep_local=True, ), output: diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 6a54b4d1..4cffc314 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -237,7 +237,7 @@ if config["enable"]["retrieve"]: rule retrieve_luisa_land_cover: input: storage( - "jeodpp.jrc.ec.europa.eu/ftp/jrc-opendata/LUISA/EUROPE/Basemaps/LandUse/2018/LATEST/LUISA_basemap_020321_50m.tif", + "https://jeodpp.jrc.ec.europa.eu/ftp/jrc-opendata/LUISA/EUROPE/Basemaps/LandUse/2018/LATEST/LUISA_basemap_020321_50m.tif", static=True, ), output: From bcd02d94d613b1779cc900d24ded9b590e5f29d6 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 9 Mar 2024 12:10:45 +0100 Subject: [PATCH 432/591] retrieve: remove storage(static=True) call --- rules/retrieve.smk | 1 - 1 file changed, 1 deletion(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 4cffc314..c452969d 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -238,7 +238,6 @@ if config["enable"]["retrieve"]: input: storage( "https://jeodpp.jrc.ec.europa.eu/ftp/jrc-opendata/LUISA/EUROPE/Basemaps/LandUse/2018/LATEST/LUISA_basemap_020321_50m.tif", - static=True, ), output: "data/LUISA_basemap_020321_50m.tif", From ed71978b92554af6bd240cbc072e2dfabd9e0ad8 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 9 Mar 2024 14:47:01 +0100 Subject: [PATCH 433/591] use humanfriendly walltime specifications --- Snakefile | 2 +- config/config.default.yaml | 4 ++-- envs/environment.yaml | 2 +- rules/solve_electricity.smk | 4 ++-- rules/solve_myopic.smk | 4 ++-- rules/solve_overnight.smk | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Snakefile b/Snakefile index c2d71cfd..58cb6677 100644 --- a/Snakefile +++ b/Snakefile @@ -9,7 +9,7 @@ import yaml from snakemake.utils import min_version -min_version("8") +min_version("8.5") from scripts._helpers import path_provider diff --git a/config/config.default.yaml b/config/config.default.yaml index e7bfe18f..d9f69206 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -813,8 +813,8 @@ solving: cbc-default: {} # Used in CI glpk-default: {} # Used in CI - mem: 30000 #memory in MB; 20 GB enough for 50+B+I+H2; 100 GB for 181+B+I+H2 - walltime: "12:00:00" + mem_mb: 30000 #memory in MB; 20 GB enough for 50+B+I+H2; 100 GB for 181+B+I+H2 + runtime: 6h #runtime in humanfriendly style https://humanfriendly.readthedocs.io/en/latest/ # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#plotting plotting: diff --git a/envs/environment.yaml b/envs/environment.yaml index a5323923..ee1d1605 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -20,7 +20,7 @@ dependencies: - openpyxl!=3.1.1 - pycountry - seaborn -- snakemake-minimal>=8 +- snakemake-minimal>=8.5 - memory_profiler - yaml - pytables diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index d0cab34c..8481c75b 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -29,7 +29,7 @@ rule solve_network: threads: solver_threads resources: mem_mb=memory, - walltime=config_provider("solving", "walltime", default="12:00:00"), + runtime=config_provider("solving", "runtime", default="6h"), shadow: "minimal" conda: @@ -60,7 +60,7 @@ rule solve_operations_network: threads: 4 resources: mem_mb=(lambda w: 10000 + 372 * int(w.clusters)), - walltime=config_provider("solving", "walltime", default="12:00:00"), + runtime=config_provider("solving", "runtime", default="6h"), shadow: "minimal" conda: diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index a081fbe6..57b8a9d3 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -132,8 +132,8 @@ rule solve_sector_network_myopic: + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", threads: solver_threads resources: - mem_mb=config_provider("solving", "mem"), - walltime=config_provider("solving", "walltime", default="12:00:00"), + mem_mb=config_provider("solving", "mem_mb"), + runtime=config_provider("solving", "runtime", default="6h"), benchmark: ( RESULTS diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index b212d453..26e6e220 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -30,8 +30,8 @@ rule solve_sector_network: + "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log", threads: solver_threads resources: - mem_mb=config_provider("solving", "mem"), - walltime=config_provider("solving", "walltime", default="12:00:00"), + mem_mb=config_provider("solving", "mem_mb"), + runtime=config_provider("solving", "runtime", default="6h"), benchmark: ( RESULTS From 887aa532901027a02adccffa08367d331955399b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Sat, 9 Mar 2024 15:29:39 +0100 Subject: [PATCH 434/591] build_gas_input_locations: remove unnecessary [0] with new storage plugin --- scripts/build_gas_input_locations.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/build_gas_input_locations.py b/scripts/build_gas_input_locations.py index 6543d950..67dbc986 100644 --- a/scripts/build_gas_input_locations.py +++ b/scripts/build_gas_input_locations.py @@ -25,7 +25,7 @@ def read_scigrid_gas(fn): def build_gem_lng_data(fn): - df = pd.read_excel(fn[0], sheet_name="LNG terminals - data") + df = pd.read_excel(fn, sheet_name="LNG terminals - data") df = df.set_index("ComboID") remove_country = ["Cyprus", "Turkey"] # noqa: F841 @@ -46,7 +46,7 @@ def build_gem_lng_data(fn): def build_gem_prod_data(fn): - df = pd.read_excel(fn[0], sheet_name="Gas extraction - main") + df = pd.read_excel(fn, sheet_name="Gas extraction - main") df = df.set_index("GEM Unit ID") remove_country = ["Cyprus", "Türkiye"] # noqa: F841 @@ -60,7 +60,7 @@ def build_gem_prod_data(fn): & ~Longitude.isna()" ).copy() - p = pd.read_excel(fn[0], sheet_name="Gas extraction - production") + p = pd.read_excel(fn, sheet_name="Gas extraction - production") p = p.set_index("GEM Unit ID") p = p[p["Fuel description"] == "gas"] From e96a9896cbbc62d3d84d241379964d44ad4cb6e0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 11 Mar 2024 08:59:11 +0100 Subject: [PATCH 435/591] add release notes --- doc/release_notes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 4500cbc9..9b494b32 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,11 @@ Release Notes Upcoming Release ================ +* Upgrade to Snakemake v8.5+. This version is the new minimum version required. + To upgrade an existing environment, run ``conda install -c bioconda + snakemake-minimal">=8.5"`` and ``pip install snakemake-storage-plugin-http`` + (https://github.com/PyPSA/pypsa-eur/pull/825). + * Corrected a bug leading to power plants operating after their DateOut (https://github.com/PyPSA/pypsa-eur/pull/958). Added additional grouping years before 1980. From e19e38b149f72ea2bed44f0ce5cf7f30cce95cad Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 11 Mar 2024 08:59:26 +0100 Subject: [PATCH 436/591] update version requirements for retrieve.yaml --- envs/retrieve.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/envs/retrieve.yaml b/envs/retrieve.yaml index b5db795d..a3c4828c 100644 --- a/envs/retrieve.yaml +++ b/envs/retrieve.yaml @@ -8,6 +8,11 @@ channels: - bioconda dependencies: - python>=3.8 -- snakemake-minimal>=7.7.0,<8.0.0 +- pip +- snakemake-minimal>=8.5 - pandas>=2.1 - tqdm +- pip: + - snakemake-storage-plugin-http + - snakemake-executor-plugin-slurm + - snakemake-executor-plugin-cluster-generic From 06fa9c92dad45eca5f0211a9f44c736b7c337282 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 13 Mar 2024 08:57:57 +0100 Subject: [PATCH 437/591] remove copy_config rule and write config for each solved network --- doc/release_notes.rst | 3 +++ doc/sector.rst | 5 ----- rules/postprocess.smk | 18 ------------------ rules/solve_electricity.smk | 2 +- rules/solve_myopic.smk | 5 +++-- rules/solve_overnight.smk | 5 +++-- rules/solve_perfect.smk | 4 ++-- scripts/copy_config.py | 28 ---------------------------- scripts/solve_network.py | 12 +++++++++++- 9 files changed, 23 insertions(+), 59 deletions(-) delete mode 100644 scripts/copy_config.py diff --git a/doc/release_notes.rst b/doc/release_notes.rst index ad1bbf4f..7edc7ac6 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,9 @@ Release Notes Upcoming Release ================ +* Removed rule ``copy_config``. Instead, a config file is created for each + network output of the ``solve_*`` rules, with the same content as ``n.meta``. + * Upgrade to Snakemake v8.5+. This version is the new minimum version required. To upgrade an existing environment, run ``conda install -c bioconda snakemake-minimal">=8.5"`` and ``pip install snakemake-storage-plugin-http`` diff --git a/doc/sector.rst b/doc/sector.rst index 84a5fdc9..71a2acb8 100644 --- a/doc/sector.rst +++ b/doc/sector.rst @@ -171,11 +171,6 @@ Rule ``cluster_gas_network`` .. automodule:: cluster_gas_network -Rule ``copy_config`` -============================================================================== - -.. automodule:: copy_config - Rule ``prepare_sector_network`` ============================================================================== diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 1b188829..30de78bb 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -3,10 +3,6 @@ # SPDX-License-Identifier: MIT -localrules: - copy_config, - - if config["foresight"] != "perfect": rule plot_power_network_clustered: @@ -137,20 +133,6 @@ if config["foresight"] == "perfect": "../scripts/plot_power_network_perfect.py" -rule copy_config: - params: - RDIR=RDIR, - output: - RESULTS + "config.yaml", - threads: 1 - resources: - mem_mb=1000, - conda: - "../envs/environment.yaml" - script: - "../scripts/copy_config.py" - - rule make_summary: params: foresight=config_provider("foresight"), diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index 8481c75b..06d2f4aa 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -14,9 +14,9 @@ rule solve_network: custom_extra_functionality=input_custom_extra_functionality, input: network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), - config=RESULTS + "config.yaml", output: network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc", + config=RESULTS + "configs/config.elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.yaml", log: solver=normpath( RESULTS diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 57b8a9d3..28c0313f 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -117,10 +117,11 @@ rule solve_sector_network_myopic: network=RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", costs=resources("costs_{planning_horizons}.csv"), - config=RESULTS + "config.yaml", output: - RESULTS + network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + config=RESULTS + + "configs/config.elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.yaml", shadow: "shallow" log: diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index 26e6e220..26dee7a6 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -15,10 +15,11 @@ rule solve_sector_network: input: network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", - config=RESULTS + "config.yaml", output: - RESULTS + network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", + config=RESULTS + + "configs/config.elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.yaml", shadow: "shallow" log: diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index a565d978..215757fe 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -107,10 +107,10 @@ rule solve_sector_network_perfect: network=RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", costs=resources("costs_2030.csv"), - config=RESULTS + "config.yaml", output: - RESULTS + network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", + config="configs/config.elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.yaml", threads: solver_threads resources: mem_mb=config_provider("solving", "mem"), diff --git a/scripts/copy_config.py b/scripts/copy_config.py deleted file mode 100644 index 0a5fe10b..00000000 --- a/scripts/copy_config.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT -""" -Copy used configuration files and important scripts for archiving. -""" - - -import yaml -from _helpers import set_scenario_config - -if __name__ == "__main__": - if "snakemake" not in globals(): - from _helpers import mock_snakemake - - snakemake = mock_snakemake("copy_config") - - set_scenario_config(snakemake) - - with open(snakemake.output[0], "w") as yaml_file: - yaml.dump( - snakemake.config, - yaml_file, - default_flow_style=False, - allow_unicode=True, - sort_keys=False, - ) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 7e53e606..6cb9a054 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -36,6 +36,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr +import yaml from _benchmark import memory_logger from _helpers import ( configure_logging, @@ -968,4 +969,13 @@ if __name__ == "__main__": logger.info(f"Maximum memory usage: {mem.mem_usage}") n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) - n.export_to_netcdf(snakemake.output[0]) + n.export_to_netcdf(snakemake.output.network) + + with open(snakemake.output.config, "w") as file: + yaml.dump( + n.meta, + file, + default_flow_style=False, + allow_unicode=True, + sort_keys=False, + ) From a429b488746115ffe9279223f87df64460af9e7d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 13 Mar 2024 09:19:10 +0100 Subject: [PATCH 438/591] update storage provider for snakemake 8 --- rules/retrieve.smk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 30f35aa8..76069c6f 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -198,10 +198,9 @@ if config["enable"]["retrieve"]: rule retrieve_artificial_load_data: input: - HTTP.remote( + storage( "https://zenodo.org/record/7070438/files/demand_hourly.csv", keep_local=True, - static=True, ), output: "data/load_artificial_raw.csv", From 2eb159af7ca5605d9c786360a7b59e56c09a679c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 13 Mar 2024 13:40:23 +0100 Subject: [PATCH 439/591] idees eurostat rescaling also for period 1990-1999 --- scripts/build_energy_totals.py | 76 +++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 368d7206..1b36ec1b 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -856,44 +856,52 @@ def rescale_idees_from_eurostat( ] for country in idees_countries: - slicer_target = idx[country, 2016:2021, :, :] - slicer_source = idx[country, 2015, :, :] - for sector, mapping in mappings.items(): - sector_ratio = ratio.loc[ - (country, slice(None), slice(None), sector) - ].droplevel("lvl2") + filling_years = [(2015, slice(2016, 2021)), (2000, slice(1990, 1999))] - energy.loc[slicer_target, mapping["total"]] = cartesian( - sector_ratio.loc[2016:2021, "total"], - energy.loc[slicer_source, mapping["total"]].squeeze(), - ).values - energy.loc[slicer_target, mapping["elec"]] = cartesian( - sector_ratio.loc[2016:2021, "ele"], - energy.loc[slicer_source, mapping["elec"]].squeeze(), + for source_year, target_years in filling_years: + + slicer_source = idx[country, source_year, :, :] + slicer_target = idx[country, target_years, :, :] + + for sector, mapping in mappings.items(): + sector_ratio = ratio.loc[ + (country, slice(None), slice(None), sector) + ].droplevel("lvl2") + + energy.loc[slicer_target, mapping["total"]] = cartesian( + sector_ratio.loc[target_years, "total"], + energy.loc[slicer_source, mapping["total"]].squeeze(axis=0), + ).values + energy.loc[slicer_target, mapping["elec"]] = cartesian( + sector_ratio.loc[target_years, "ele"], + energy.loc[slicer_source, mapping["elec"]].squeeze(axis=0), + ).values + + level_drops = ["country", "lvl2", "lvl3"] + + slicer = idx[country, :, :, "Domestic aviation"] + avi_d = ratio.loc[slicer, "total"].droplevel(level_drops) + + slicer = idx[country, :, :, "International aviation"] + avi_i = ratio.loc[slicer, "total"].droplevel(level_drops) + + slicer = idx[country, :, :, "Domestic Navigation"] + nav = ratio.loc[slicer, "total"].droplevel(level_drops) + + energy.loc[slicer_target, avia_inter] = cartesian( + avi_i.loc[target_years], + energy.loc[slicer_source, avia_inter].squeeze(axis=0), ).values - level_drops = ["country", "lvl2", "lvl3"] + energy.loc[slicer_target, avia_domestic] = cartesian( + avi_d.loc[target_years], + energy.loc[slicer_source, avia_domestic].squeeze(axis=0), + ).values - slicer = idx[country, :, :, "Domestic aviation"] - avi_d = ratio.loc[slicer, "total"].droplevel(level_drops) - - slicer = idx[country, :, :, "International aviation"] - avi_i = ratio.loc[slicer, "total"].droplevel(level_drops) - - slicer = idx[country, :, :, "Domestic Navigation"] - nav = ratio.loc[slicer, "total"].droplevel(level_drops) - - energy.loc[slicer_target, avia_inter] = cartesian( - avi_i.loc[2016:2021], energy.loc[slicer_source, avia_inter].squeeze() - ).values - - energy.loc[slicer_target, avia_domestic] = cartesian( - avi_d.loc[2016:2021], energy.loc[slicer_source, avia_domestic].squeeze() - ).values - - energy.loc[slicer_target, navigation] = cartesian( - nav.loc[2016:2021], energy.loc[slicer_source, navigation] - ).values + energy.loc[slicer_target, navigation] = cartesian( + nav.loc[target_years], + energy.loc[slicer_source, navigation].squeeze(axis=0), + ).values return energy From 5b5d308bf70f15dd0b107d8a19c121093dcdd5bd Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 13 Mar 2024 13:42:03 +0100 Subject: [PATCH 440/591] adapt transport data to multiyear setup with new swiss data --- data/gr-e-11.03.02.01.01-cc.csv | 45 +++++++++++++++++++++++++++++++++ rules/build_sector.smk | 1 + scripts/build_energy_totals.py | 22 +++++++++++----- 3 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 data/gr-e-11.03.02.01.01-cc.csv diff --git a/data/gr-e-11.03.02.01.01-cc.csv b/data/gr-e-11.03.02.01.01-cc.csv new file mode 100644 index 00000000..47567275 --- /dev/null +++ b/data/gr-e-11.03.02.01.01-cc.csv @@ -0,0 +1,45 @@ +year,passenger cars,passenger vehicles,goods vehicles,agricultural vehicles,industrial vehicles,motorcycles,mopeds (incl. fast e-bikes)¹ +1980,2246752,11087,169402,137685,0,137340,671473 +1981,2394455,11122,167846,151238,0,152508,687517 +1982,2473318,11341,178313,156631,0,178398,656102 +1983,2520610,11255,189920,165332,0,187090,674710 +1984,2552132,10853,192708,164078,0,199302,647391 +1985,2617164,10771,200537,175161,0,217974,644175 +1986,2678911,10800,207014,183689,0,225676,627523 +1987,2732720,11027,217750,189984,0,240102,613093 +1988,2819548,26869,236649,152693,43519,219987,581270 +1989,2895842,29270,241488,157867,44326,261715,551808 +1990,2985397,31180,252136,162932,45920,299264,464609 +1991,3057798,32968,257646,165571,46938,319779,418251 +1992,3091228,34136,256611,169277,47281,336448,381236 +1993,3109523,34852,253461,171414,47229,348159,358732 +1994,3165042,35676,256285,172300,47373,357252,336367 +1995,3229176,36517,262352,174026,47693,370700,317783 +1996,3268093,37662,263020,174247,47622,381986,301009 +1997,3323455,38508,264200,175689,47743,410750,280467 +1998,3383307,39012,267380,176712,47754,435042,265422 +1999,3467311,39692,273954,177148,48265,464357,246018 +2000,3545247,40260,278518,177963,48949,493781,218932 +2001,3629713,41342,285246,179321,49549,521390,199033 +2002,3700951,42401,290142,180063,50227,545132,186811 +2003,3753890,43629,292329,180295,50795,567358,173486 +2004,3811351,44784,298193,180898,50957,583010,165000 +2005,3863807,45785,307264,182093,51860,592194,156095 +2006,3899917,46445,314020,185450,53437,608648,150563 +2007,3955787,48026,324153,184062,55149,619166,144704 +2008,3989811,48536,326232,188218,55808,636540,141549 +2009,4009602,50675,327808,185902,56533,642777,139220 +2010,4075825,52751,335200,186485,58492,651202,139548 +2011,4163003,55422,348553,187130,60324,665870,142834 +2012,4254725,58278,361926,188358,62219,679822,145984 +2013,4320885,60151,371361,189305,63950,687990,147247 +2014,4384490,62436,382281,190095,65563,699219,152962 +2015,4458069,65720,393598,191132,67101,710022,161292 +2016,4524029,69676,405566,192139,68721,720381,176030 +2017,4570823,73814,416501,192858,70113,729149,188053 +2018,4602688,77985,428808,193283,71683,739344,201423 +2019,4623952,83054,440795,193834,74085,744542,211480 +2020,4658335,88293,452186,195082,75659,771586,229421 +2021,4709366,97805,466857,196530,77672,791323,244572 +2022,4721280,105158,475714,196942,79691,789794,257753 +2023,4760948,114299,485303,197678,81241,805653, \ No newline at end of file diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 3a0fda21..e41d0224 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -289,6 +289,7 @@ rule build_energy_totals: nuts3_shapes=resources("nuts3_shapes.geojson"), co2="data/bundle-sector/eea/UNFCCC_v23.csv", swiss="data/switzerland-new_format-all_years.csv", + swiss_transport="data/gr-e-11.03.02.01.01-cc.csv", idees="data/bundle-sector/jrc-idees-2015", district_heat_share="data/district_heat_share.csv", eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition", diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 1b36ec1b..29cf8182 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -712,15 +712,25 @@ def build_co2_totals(countries, eea_co2, eurostat_co2): def build_transport_data(countries, population, idees): - transport_data = pd.DataFrame(index=countries) + # first collect number of cars - # collect number of cars + transport_data = pd.DataFrame(idees["passenger cars"]) - transport_data["number cars"] = idees["passenger cars"] - - # CH from http://ec.europa.eu/eurostat/statistics-explained/index.php/Passenger_cars_in_the_EU#Luxembourg_has_the_highest_number_of_passenger_cars_per_inhabitant +# https://www.bfs.admin.ch/bfs/en/home/statistics/mobility-transport/transport-infrastructure-vehicles/vehicles/road-vehicles-stock-level-motorisation.html if "CH" in countries: - transport_data.at["CH", "number cars"] = 4.136e6 + fn = snakemake.input.swiss_transport + swiss_cars = pd.read_csv(fn, index_col=0).loc[1990:2021, ["passenger cars"]] + + swiss_cars.index = pd.MultiIndex.from_product( + [["CH"], swiss_cars.index], + names=["country", "year"] + ) + + transport_data = pd.concat([transport_data, swiss_cars]).sort_index() + + transport_data.rename( + columns={"passenger cars": "number cars"}, inplace=True + ) missing = transport_data.index[transport_data["number cars"].isna()] if not missing.empty: From 955d6837fda2e9b2142e291c28078067f5b9752c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 13 Mar 2024 13:42:29 +0100 Subject: [PATCH 441/591] district heating: handle missing GB data for 2020-2021 --- scripts/build_energy_totals.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 29cf8182..9282c0e7 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -611,6 +611,11 @@ def build_district_heat_share(countries, idees): district_heat_share.name = "district heat share" + # restrict to available years + district_heat_share = ( + district_heat_share.unstack().dropna(how="all", axis=1).ffill(axis=1) + ) + return district_heat_share From 721c64a5bda180301e0bead5e5b8b21c4cf8dbb0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 12:42:57 +0000 Subject: [PATCH 442/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data/gr-e-11.03.02.01.01-cc.csv | 2 +- scripts/build_energy_totals.py | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/data/gr-e-11.03.02.01.01-cc.csv b/data/gr-e-11.03.02.01.01-cc.csv index 47567275..0ba695de 100644 --- a/data/gr-e-11.03.02.01.01-cc.csv +++ b/data/gr-e-11.03.02.01.01-cc.csv @@ -42,4 +42,4 @@ 2020,4658335,88293,452186,195082,75659,771586,229421 2021,4709366,97805,466857,196530,77672,791323,244572 2022,4721280,105158,475714,196942,79691,789794,257753 -2023,4760948,114299,485303,197678,81241,805653, \ No newline at end of file +2023,4760948,114299,485303,197678,81241,805653, diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 9282c0e7..48df4625 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -721,21 +721,18 @@ def build_transport_data(countries, population, idees): transport_data = pd.DataFrame(idees["passenger cars"]) -# https://www.bfs.admin.ch/bfs/en/home/statistics/mobility-transport/transport-infrastructure-vehicles/vehicles/road-vehicles-stock-level-motorisation.html + # https://www.bfs.admin.ch/bfs/en/home/statistics/mobility-transport/transport-infrastructure-vehicles/vehicles/road-vehicles-stock-level-motorisation.html if "CH" in countries: fn = snakemake.input.swiss_transport swiss_cars = pd.read_csv(fn, index_col=0).loc[1990:2021, ["passenger cars"]] swiss_cars.index = pd.MultiIndex.from_product( - [["CH"], swiss_cars.index], - names=["country", "year"] + [["CH"], swiss_cars.index], names=["country", "year"] ) transport_data = pd.concat([transport_data, swiss_cars]).sort_index() - transport_data.rename( - columns={"passenger cars": "number cars"}, inplace=True - ) + transport_data.rename(columns={"passenger cars": "number cars"}, inplace=True) missing = transport_data.index[transport_data["number cars"].isna()] if not missing.empty: From 74339b5648d7244360164ac403e422e909545064 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 12:01:57 +0100 Subject: [PATCH 443/591] update data/era5-annual-{runoff,HDD}-per-country.csv --- data/era5-annual-HDD-per-country.csv | 68 ++++++++++++------------- data/era5-annual-runoff-per-country.csv | 68 ++++++++++++------------- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/data/era5-annual-HDD-per-country.csv b/data/era5-annual-HDD-per-country.csv index 472257c6..5f6ad45d 100644 --- a/data/era5-annual-HDD-per-country.csv +++ b/data/era5-annual-HDD-per-country.csv @@ -1,34 +1,34 @@ -name,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021 -AL,56,58,65,67,55,70,58,59,61,54,54,62,62,62,68,59,60,57,57,58,61,57,64,60,61,61,54,63,57,65,63,58,61,57,57,58,61,62,56,53,67,62,62,53,61,61,60,60,56,58,57,53,61,58,65,64,55,55,54,53,58,58,50,46,54,50,54,47,49,50,54 -AT,374,416,379,422,419,449,387,393,378,389,367,437,425,406,424,376,385,400,409,413,394,407,408,379,384,400,380,414,405,428,397,384,377,411,420,406,409,378,369,372,415,373,383,334,380,416,371,373,368,343,371,337,370,370,384,362,333,340,351,388,337,353,358,302,324,336,347,315,320,322,358 -BE,95,105,94,102,109,113,91,97,88,89,84,111,114,100,100,91,94,101,102,101,96,102,101,90,97,97,92,103,108,105,99,94,96,99,112,107,108,85,84,83,101,92,94,82,89,110,90,89,84,79,89,78,89,90,87,86,76,87,87,107,75,90,99,69,81,88,82,81,80,71,89 -BG,283,294,334,367,295,363,306,283,320,268,277,303,324,313,323,259,297,292,320,286,300,306,323,303,296,314,287,310,293,326,301,312,295,306,326,313,333,320,276,272,332,303,318,266,307,335,325,303,273,275,284,272,322,277,298,296,259,266,266,273,313,295,258,250,261,265,281,261,232,250,277 -BA,144,164,167,183,158,194,157,157,152,143,141,173,180,176,176,155,162,157,165,165,163,154,170,156,153,168,145,170,153,176,163,154,157,159,167,160,166,158,146,139,174,152,162,143,157,171,156,158,147,132,145,130,156,146,164,148,134,132,139,147,144,147,133,113,137,134,144,128,125,127,141 -CH,214,225,210,226,221,240,211,215,203,214,200,234,231,214,229,213,217,219,225,227,217,221,224,213,216,220,208,219,220,229,216,208,208,227,224,217,217,200,202,200,217,204,208,183,206,217,195,205,203,192,200,189,199,204,209,193,187,194,193,213,179,196,204,178,181,189,191,174,184,176,197 -CZ,297,344,307,351,350,377,313,322,301,314,294,358,361,345,351,297,296,320,342,336,319,326,322,282,296,315,299,330,328,347,316,308,298,323,350,326,346,297,280,283,333,299,316,279,312,364,319,296,288,265,309,285,308,302,311,300,269,275,289,338,281,298,306,242,261,283,287,262,255,259,302 -DE,1254,1428,1237,1416,1484,1567,1282,1342,1229,1266,1183,1486,1528,1390,1399,1269,1211,1341,1447,1429,1300,1388,1356,1184,1258,1339,1221,1377,1433,1433,1348,1288,1273,1384,1492,1425,1491,1201,1156,1135,1367,1241,1312,1155,1295,1548,1288,1220,1172,1085,1250,1168,1269,1236,1239,1198,1072,1159,1202,1459,1112,1232,1305,992,1095,1188,1148,1092,1070,1019,1230 -DK,160,176,152,175,186,190,163,178,154,169,154,184,194,176,182,181,153,170,182,186,159,166,159,147,147,172,161,171,190,177,175,164,155,162,191,181,190,151,137,132,160,147,166,154,162,191,162,154,147,134,161,148,158,151,150,144,134,137,150,193,144,159,160,125,138,145,139,142,134,125,150 -ES,962,911,927,948,785,1092,934,848,821,890,742,952,981,967,949,878,890,839,933,899,971,961,943,931,928,928,797,906,887,911,793,787,807,920,860,891,781,783,684,767,911,852,889,724,627,759,605,735,796,750,757,677,746,813,856,714,776,785,736,856,673,810,830,649,684,722,688,768,708,672,728 -EE,297,310,283,297,321,336,278,310,281,305,253,298,323,292,306,324,283,310,333,317,285,285,289,256,245,327,302,324,299,313,289,278,260,271,328,294,332,281,232,240,257,257,285,288,265,306,281,278,262,235,273,271,278,270,270,260,250,230,268,315,253,286,259,254,225,261,255,254,235,209,270 -FI,3285,3442,3085,3179,3880,3819,3296,3626,3180,3386,3065,3513,3467,3329,3526,3873,3284,3693,3640,3494,3572,3178,3458,2963,3074,3691,3490,3743,3419,3607,3572,3331,3296,3192,3894,3516,3793,3402,2888,3075,3209,3163,3319,3341,3213,3343,3302,3468,3259,2915,3303,3307,3231,3159,2998,3101,3018,3009,3219,3604,2961,3351,2985,2983,2795,3030,3127,3061,3116,2726,3260 -FR,1430,1480,1422,1489,1396,1633,1338,1378,1240,1332,1196,1584,1630,1499,1471,1331,1408,1412,1473,1469,1475,1453,1545,1356,1462,1445,1312,1454,1502,1545,1396,1315,1424,1484,1599,1518,1520,1269,1237,1227,1501,1375,1389,1168,1280,1454,1222,1337,1263,1190,1299,1132,1294,1346,1376,1263,1199,1301,1277,1522,1060,1300,1408,1034,1143,1266,1236,1150,1165,1043,1279 -GB,906,934,809,901,925,935,813,890,787,849,825,1000,1046,912,970,917,839,874,894,869,805,880,862,842,838,851,863,873,972,880,896,823,824,838,923,944,903,801,764,746,859,824,857,793,794,886,738,752,745,771,816,726,751,743,748,734,706,790,777,930,707,832,841,683,759,769,720,764,750,725,764 -GR,166,162,210,211,160,215,184,169,196,164,172,182,184,192,199,162,185,176,171,164,184,185,195,186,188,190,160,186,172,191,184,192,190,179,174,180,194,193,176,165,206,197,195,161,179,191,192,180,167,177,174,164,191,172,184,189,161,158,155,143,188,179,148,136,165,150,164,139,146,148,156 -HR,116,140,140,155,137,166,131,132,122,119,114,149,158,152,144,124,133,129,143,138,137,131,144,124,124,139,121,140,130,149,133,132,130,133,148,141,144,128,118,114,143,123,138,115,126,145,132,129,124,106,120,109,135,127,140,123,109,110,116,130,123,123,118,92,114,116,119,111,102,105,119 -HU,236,291,282,321,289,333,272,273,246,248,235,288,321,309,298,244,272,268,293,283,276,264,283,244,255,281,267,287,271,311,272,282,265,274,313,294,305,274,243,238,299,262,288,240,271,310,291,272,267,232,269,243,300,267,289,265,229,230,243,275,267,259,250,198,235,251,255,234,211,228,259 -IE,216,215,191,208,213,211,190,204,184,205,195,234,250,208,232,210,216,213,222,214,190,226,204,213,198,211,210,205,239,212,209,204,201,211,229,241,217,200,192,192,209,209,213,201,195,219,180,186,191,204,206,189,192,193,187,188,173,202,204,241,192,205,210,186,205,199,184,200,191,194,189 -IT,652,683,660,700,615,778,640,653,616,631,587,715,726,674,710,665,655,656,682,672,678,639,695,659,655,670,604,681,675,729,684,645,657,695,688,671,676,630,616,610,712,626,650,555,623,639,578,618,619,563,585,546,629,612,675,597,548,568,590,637,562,602,587,481,541,528,570,529,540,520,577 -LT,344,371,342,368,368,405,318,353,329,346,303,355,386,362,371,354,322,365,401,372,330,345,339,312,289,388,348,370,370,382,342,326,301,326,393,352,397,335,275,272,313,311,336,329,325,377,335,325,306,274,323,313,328,324,325,316,299,277,316,366,305,332,314,298,273,308,296,302,267,252,327 -LU,8,9,8,9,10,10,8,9,8,8,7,10,10,9,9,8,8,9,9,9,9,9,9,8,9,9,8,9,10,10,9,9,9,9,10,10,10,8,8,8,9,8,9,8,8,10,8,8,8,7,8,7,8,8,8,8,7,8,8,9,7,8,9,6,7,8,8,7,7,7,8 -LV,383,402,372,394,407,439,351,391,361,384,326,386,420,385,402,401,360,401,434,407,361,372,371,337,316,424,385,411,392,411,372,357,330,354,425,379,428,362,300,301,334,337,366,366,348,402,365,358,334,302,353,346,357,352,354,337,324,300,346,402,330,365,342,329,297,337,330,328,297,272,351 -MK,64,66,74,79,66,79,67,66,71,63,64,72,73,70,77,66,69,66,67,67,70,67,75,69,70,69,62,72,66,73,71,69,70,67,69,67,70,71,65,63,76,68,69,59,69,70,71,68,64,65,65,62,69,64,70,68,60,59,61,59,67,66,56,53,61,58,62,54,55,57,63 -ME,40,43,45,48,41,50,42,42,42,39,39,44,45,45,48,43,43,42,42,43,43,41,44,43,42,45,39,45,42,46,45,41,43,42,42,41,44,44,42,39,47,43,43,38,43,44,42,43,39,39,40,37,42,41,45,43,38,38,38,38,39,40,36,32,37,36,39,34,35,35,39 -NL,113,126,110,121,130,137,108,118,107,107,104,132,141,121,120,114,105,119,124,122,111,120,116,104,111,116,107,120,133,122,118,112,110,118,134,127,130,99,99,94,119,106,113,102,109,138,111,102,97,93,106,98,109,103,100,100,87,102,103,131,93,108,117,82,95,104,96,98,93,85,105 -NO,3339,3541,3020,3307,3639,3731,3315,3547,3122,3353,3400,3807,3641,3496,3783,3951,3259,3533,3425,3431,3339,3128,3312,3028,3094,3405,3369,3436,3457,3380,3502,3181,3141,3117,3541,3359,3449,3200,2890,2848,3057,3032,3196,3207,3170,3301,3060,3203,3062,2878,3166,3028,2983,2943,2874,2828,2918,2954,3018,3442,2796,3157,2946,2754,2793,2859,2963,2930,2981,2711,3035 -PL,1249,1438,1294,1478,1446,1586,1279,1349,1269,1305,1215,1435,1527,1450,1467,1280,1193,1321,1504,1431,1293,1347,1314,1200,1184,1419,1270,1393,1431,1491,1336,1265,1178,1304,1494,1377,1507,1255,1077,1078,1312,1252,1310,1197,1302,1512,1326,1249,1171,1052,1268,1192,1296,1230,1262,1244,1117,1092,1220,1426,1177,1274,1251,1068,1063,1163,1158,1120,1019,1017,1252 -PT,107,103,99,109,80,131,106,93,93,97,78,106,104,115,103,98,103,97,112,110,115,116,106,109,109,109,99,139,107,102,89,90,95,104,99,108,85,89,75,87,104,96,104,85,66,88,62,82,96,90,90,78,87,97,103,90,91,91,84,96,80,101,100,81,79,87,79,96,81,72,78 -RO,736,811,883,948,822,968,810,789,826,731,744,826,890,867,873,706,791,776,858,792,787,798,838,782,752,855,772,836,780,880,801,811,763,807,917,815,882,827,710,700,846,801,848,701,806,869,842,805,740,710,760,721,844,754,799,780,684,695,695,757,793,781,709,662,681,721,720,690,624,648,740 -RS,222,252,273,300,249,313,248,249,254,231,226,270,283,271,274,233,253,243,267,254,251,246,272,242,243,265,233,265,241,273,251,255,244,253,275,256,268,254,231,220,275,243,263,223,250,270,259,250,237,217,234,217,262,238,265,247,217,214,222,229,251,244,214,192,222,223,232,211,197,212,234 -SK,178,210,195,217,208,228,192,193,185,185,178,208,213,211,219,179,187,192,203,200,192,188,195,178,178,197,188,204,193,215,191,190,180,193,212,198,207,187,172,173,202,186,191,171,186,204,193,184,177,162,184,174,190,184,191,182,163,161,170,188,175,179,174,142,161,170,176,157,152,158,180 -SI,61,72,67,73,69,78,65,66,62,61,59,75,75,73,73,62,65,67,71,69,67,68,71,62,61,69,62,71,68,74,67,65,65,69,73,71,71,63,59,58,70,61,63,55,61,71,63,62,62,54,59,55,65,63,67,61,54,57,57,65,58,59,59,46,55,57,58,53,52,53,61 -SE,3891,4219,3560,3919,4426,4488,3950,4223,3662,3988,3814,4451,4260,4021,4358,4613,3929,4280,4255,4254,4043,3806,3975,3634,3625,4238,4132,4314,4246,4287,4301,3913,3840,3819,4588,4139,4376,3931,3476,3446,3785,3695,3893,3991,3916,4073,3757,3950,3781,3446,3898,3778,3755,3769,3632,3561,3606,3590,3806,4397,3474,3935,3675,3452,3421,3635,3693,3705,3689,3247,3807 +name,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023 +AL,73,70,62,70,74,64,59,65,62,57,56,58,65,67,55,70,58,59,61,54,54,62,62,62,68,59,60,57,57,58,61,57,64,60,61,61,54,63,57,65,63,58,61,57,57,58,61,62,56,53,67,62,62,53,61,61,60,60,56,58,57,53,61,58,65,64,55,55,54,53,58,58,50,46,54,50,54,47,49,50,54,74,47 +AT,448,429,391,433,413,406,403,399,376,383,374,416,379,422,419,449,387,393,378,389,367,437,425,406,424,376,385,400,409,413,394,407,408,379,384,400,380,414,405,428,397,384,377,411,420,406,409,378,369,372,415,373,383,334,380,416,371,373,368,343,371,337,370,370,384,362,333,340,351,388,337,353,358,302,324,336,347,315,320,322,358,456,307 +BE,107,109,89,104,96,100,101,90,92,101,95,105,94,102,109,113,91,97,88,89,84,111,114,100,100,91,94,101,102,101,96,102,101,90,97,97,92,103,108,105,99,94,96,99,112,107,108,85,84,83,101,92,94,82,89,110,90,89,84,79,89,78,89,90,87,86,76,87,87,107,75,90,99,69,81,88,82,81,80,71,89,107,74 +BG,358,373,318,329,339,331,304,319,305,299,283,294,334,367,295,363,306,283,320,268,277,303,324,313,323,259,297,292,320,286,300,306,323,303,296,314,287,310,293,326,301,312,295,306,326,313,333,320,276,272,332,303,318,266,307,335,325,303,273,275,284,272,322,277,298,296,259,266,266,273,313,295,258,250,261,265,281,261,232,250,277,372,228 +BA,192,189,158,181,181,174,168,168,167,155,144,164,167,183,158,194,157,157,152,143,141,173,180,176,176,155,162,157,165,165,163,154,170,156,153,168,145,170,153,176,163,154,157,159,167,160,166,158,146,139,174,152,162,143,157,171,156,158,147,132,145,130,156,146,164,148,134,132,139,147,144,147,133,113,137,134,144,128,125,127,141,179,116 +CH,245,231,213,239,230,222,215,217,210,212,214,225,210,226,221,240,211,215,203,214,200,234,231,214,229,213,217,219,225,227,217,221,224,213,216,220,208,219,220,229,216,208,208,227,224,217,217,200,202,200,217,204,208,183,206,217,195,205,203,192,200,189,199,204,209,193,187,194,193,213,179,196,204,178,181,189,191,174,184,176,197,245,171 +CZ,373,366,311,341,326,330,353,313,299,316,297,344,307,351,350,377,313,322,301,314,294,358,361,345,351,297,296,320,342,336,319,326,322,282,296,315,299,330,328,347,316,308,298,323,350,326,346,297,280,283,333,299,316,279,312,364,319,296,288,265,309,285,308,302,311,300,269,275,289,338,281,298,306,242,261,283,287,262,255,259,302,378,248 +DE,1563,1537,1250,1388,1316,1354,1464,1255,1205,1315,1254,1428,1237,1416,1484,1567,1282,1342,1229,1266,1183,1486,1528,1390,1399,1269,1211,1341,1447,1429,1300,1388,1356,1184,1258,1339,1221,1377,1433,1433,1348,1288,1273,1384,1492,1425,1491,1201,1156,1135,1367,1241,1312,1155,1295,1548,1288,1220,1172,1085,1250,1168,1269,1236,1239,1198,1072,1159,1202,1459,1112,1232,1305,992,1095,1188,1148,1092,1070,1019,1230,1509,1021 +DK,200,198,151,167,158,171,185,158,142,164,160,176,152,175,186,190,163,178,154,169,154,184,194,176,182,181,153,170,182,186,159,166,159,147,147,172,161,171,190,177,175,164,155,162,191,181,190,151,137,132,160,147,166,154,162,191,162,154,147,134,161,148,158,151,150,144,134,137,150,193,144,159,160,125,138,145,139,142,134,125,150,193,138 +ES,1045,986,927,1012,830,994,860,807,904,853,962,911,927,948,785,1092,934,848,821,890,742,952,981,967,949,878,890,839,933,899,971,961,943,931,928,928,797,906,887,911,793,787,807,920,860,891,781,783,684,767,911,852,889,724,627,759,605,735,796,750,757,677,746,813,856,714,776,785,736,856,673,810,830,649,684,722,688,768,708,672,728,933,655 +EE,373,352,266,284,307,298,320,274,250,285,297,310,283,297,321,336,278,310,281,305,253,298,323,292,306,324,283,310,333,317,285,285,289,256,245,327,302,324,299,313,289,278,260,271,328,294,332,281,232,240,257,257,285,288,265,306,281,278,262,235,273,271,278,270,270,260,250,230,268,315,253,286,259,254,225,261,255,254,235,209,270,365,246 +FI,3989,3729,3012,3160,3611,3348,3577,3151,3012,3213,3285,3442,3085,3179,3880,3819,3296,3626,3180,3386,3065,3513,3467,3329,3526,3873,3284,3693,3640,3494,3572,3178,3458,2963,3074,3691,3490,3743,3419,3607,3572,3331,3296,3192,3894,3516,3793,3402,2888,3075,3209,3163,3319,3341,3213,3343,3302,3468,3259,2915,3303,3307,3231,3159,2998,3101,3018,3009,3219,3604,2961,3351,2985,2983,2795,3030,3127,3061,3116,2726,3260,4325,3109 +FR,1671,1578,1350,1586,1458,1490,1421,1336,1381,1447,1430,1480,1422,1489,1396,1633,1338,1378,1240,1332,1196,1584,1630,1499,1471,1331,1408,1412,1473,1469,1475,1453,1545,1356,1462,1445,1312,1454,1502,1545,1396,1315,1424,1484,1599,1518,1520,1269,1237,1227,1501,1375,1389,1168,1280,1454,1222,1337,1263,1190,1299,1132,1294,1346,1376,1263,1199,1301,1277,1522,1060,1300,1408,1034,1143,1266,1236,1150,1165,1043,1279,1535,1075 +GB,946,965,835,869,773,860,910,819,781,890,906,934,809,901,925,935,813,890,787,849,825,1000,1046,912,970,917,839,874,894,869,805,880,862,842,838,851,863,873,972,880,896,823,824,838,923,944,903,801,764,746,859,824,857,793,794,886,738,752,745,771,816,726,751,743,748,734,706,790,777,930,707,832,841,683,759,769,720,764,750,725,764,985,690 +GR,218,222,205,217,223,201,166,200,192,177,166,162,210,211,160,215,184,169,196,164,172,182,184,192,199,162,185,176,171,164,184,185,195,186,188,190,160,186,172,191,184,192,190,179,174,180,194,193,176,165,206,197,195,161,179,191,192,180,167,177,174,164,191,172,184,189,161,158,155,143,188,179,148,136,165,150,164,139,146,148,156,230,138 +HR,160,166,131,147,151,147,145,138,127,131,116,140,140,155,137,166,131,132,122,119,114,149,158,152,144,124,133,129,143,138,137,131,144,124,124,139,121,140,130,149,133,132,130,133,148,141,144,128,118,114,143,123,138,115,126,145,132,129,124,106,120,109,135,127,140,123,109,110,116,130,123,123,118,92,114,116,119,111,102,105,119,153,96 +HU,304,332,268,281,302,285,297,277,251,262,236,291,282,321,289,333,272,273,246,248,235,288,321,309,298,244,272,268,293,283,276,264,283,244,255,281,267,287,271,311,272,282,265,274,313,294,305,274,243,238,299,262,288,240,271,310,291,272,267,232,269,243,300,267,289,265,229,230,243,275,267,259,250,198,235,251,255,234,211,228,259,331,211 +IE,219,217,194,196,175,204,220,191,176,210,216,215,191,208,213,211,190,204,184,205,195,234,250,208,232,210,216,213,222,214,190,226,204,213,198,211,210,205,239,212,209,204,201,211,229,241,217,200,192,192,209,209,213,201,195,219,180,186,191,204,206,189,192,193,187,188,173,202,204,241,192,205,210,186,205,199,184,200,191,194,189,258,166 +IT,806,757,663,758,734,704,693,675,666,652,652,683,660,700,615,778,640,653,616,631,587,715,726,674,710,665,655,656,682,672,678,639,695,659,655,670,604,681,675,729,684,645,657,695,688,671,676,630,616,610,712,626,650,555,623,639,578,618,619,563,585,546,629,612,675,597,548,568,590,637,562,602,587,481,541,528,570,529,540,520,577,746,495 +LT,439,424,323,336,358,357,382,323,303,336,344,371,342,368,368,405,318,353,329,346,303,355,386,362,371,354,322,365,401,372,330,345,339,312,289,388,348,370,370,382,342,326,301,326,393,352,397,335,275,272,313,311,336,329,325,377,335,325,306,274,323,313,328,324,325,316,299,277,316,366,305,332,314,298,273,308,296,302,267,252,327,431,273 +LU,10,10,8,9,9,9,9,8,8,9,8,9,8,9,10,10,8,9,8,8,7,10,10,9,9,8,8,9,9,9,9,9,9,8,9,9,8,9,10,10,9,9,9,9,10,10,10,8,8,8,9,8,9,8,8,10,8,8,8,7,8,7,8,8,8,8,7,8,8,9,7,8,9,6,7,8,8,7,7,7,8,10,7 +LV,489,461,348,366,392,389,413,352,325,369,383,402,372,394,407,439,351,391,361,384,326,386,420,385,402,401,360,401,434,407,361,372,371,337,316,424,385,411,392,411,372,357,330,354,425,379,428,362,300,301,334,337,366,366,348,402,365,358,334,302,353,346,357,352,354,337,324,300,346,402,330,365,342,329,297,337,330,328,297,272,351,473,308 +MK,83,80,72,80,83,75,69,73,72,67,64,66,74,79,66,79,67,66,71,63,64,72,73,70,77,66,69,66,67,67,70,67,75,69,70,69,62,72,66,73,71,69,70,67,69,67,70,71,65,63,76,68,69,59,69,70,71,68,64,65,65,62,69,64,70,68,60,59,61,59,67,66,56,53,61,58,62,54,55,57,63,85,54 +ME,52,48,43,48,49,45,43,46,46,41,40,43,45,48,41,50,42,42,42,39,39,44,45,45,48,43,43,42,42,43,43,41,44,43,42,45,39,45,42,46,45,41,43,42,42,41,44,44,42,39,47,43,43,38,43,44,42,43,39,39,40,37,42,41,45,43,38,38,38,38,39,40,36,32,37,36,39,34,35,35,39,53,34 +NL,132,136,106,120,109,119,129,107,106,119,113,126,110,121,130,137,108,118,107,107,104,132,141,121,120,114,105,119,124,122,111,120,116,104,111,116,107,120,133,122,118,112,110,118,134,127,130,99,99,94,119,106,113,102,109,138,111,102,97,93,106,98,109,103,100,100,87,102,103,131,93,108,117,82,95,104,96,98,93,85,105,128,87 +NO,3658,3823,3379,3441,3537,3479,3726,3442,3268,3480,3339,3541,3020,3307,3639,3731,3315,3547,3122,3353,3400,3807,3641,3496,3783,3951,3259,3533,3425,3431,3339,3128,3312,3028,3094,3405,3369,3436,3457,3380,3502,3181,3141,3117,3541,3359,3449,3200,2890,2848,3057,3032,3196,3207,3170,3301,3060,3203,3062,2878,3166,3028,2983,2943,2874,2828,2918,2954,3018,3442,2796,3157,2946,2754,2793,2859,2963,2930,2981,2711,3035,4108,3040 +PL,1615,1584,1275,1356,1364,1378,1517,1290,1230,1296,1249,1438,1294,1478,1446,1586,1279,1349,1269,1305,1215,1435,1527,1450,1467,1280,1193,1321,1504,1431,1293,1347,1314,1200,1184,1419,1270,1393,1431,1491,1336,1265,1178,1304,1494,1377,1507,1255,1077,1078,1312,1252,1310,1197,1302,1512,1326,1249,1171,1052,1268,1192,1296,1230,1262,1244,1117,1092,1220,1426,1177,1274,1251,1068,1063,1163,1158,1120,1019,1017,1252,1599,1033 +PT,114,114,102,113,86,110,95,79,94,96,107,103,99,109,80,131,106,93,93,97,78,106,104,115,103,98,103,97,112,110,115,116,106,109,109,109,99,139,107,102,89,90,95,104,99,108,85,89,75,87,104,96,104,85,66,88,62,82,96,90,90,78,87,97,103,90,91,91,84,96,80,101,100,81,79,87,79,96,81,72,78,98,75 +RO,931,939,801,813,874,851,839,815,799,780,736,811,883,948,822,968,810,789,826,731,744,826,890,867,873,706,791,776,858,792,787,798,838,782,752,855,772,836,780,880,801,811,763,807,917,815,882,827,710,700,846,801,848,701,806,869,842,805,740,710,760,721,844,754,799,780,684,695,695,757,793,781,709,662,681,721,720,690,624,648,740,973,611 +RS,292,305,246,274,285,276,265,263,261,239,222,252,273,300,249,313,248,249,254,231,226,270,283,271,274,233,253,243,267,254,251,246,272,242,243,265,233,265,241,273,251,255,244,253,275,256,268,254,231,220,275,243,263,223,250,270,259,250,237,217,234,217,262,238,265,247,217,214,222,229,251,244,214,192,222,223,232,211,197,212,234,306,192 +SK,221,219,199,207,209,201,212,202,189,189,178,210,195,217,208,228,192,193,185,185,178,208,213,211,219,179,187,192,203,200,192,188,195,178,178,197,188,204,193,215,191,190,180,193,212,198,207,187,172,173,202,186,191,171,186,204,193,184,177,162,184,174,190,184,191,182,163,161,170,188,175,179,174,142,161,170,176,157,152,158,180,231,150 +SI,81,77,66,74,72,71,72,69,61,65,61,72,67,73,69,78,65,66,62,61,59,75,75,73,73,62,65,67,71,69,67,68,71,62,61,69,62,71,68,74,67,65,65,69,73,71,71,63,59,58,70,61,63,55,61,71,63,62,62,54,59,55,65,63,67,61,54,57,57,65,58,59,59,46,55,57,58,53,52,53,61,77,51 +SE,4509,4537,3713,3939,4134,4059,4374,3918,3633,4015,3891,4219,3560,3919,4426,4488,3950,4223,3662,3988,3814,4451,4260,4021,4358,4613,3929,4280,4255,4254,4043,3806,3975,3634,3625,4238,4132,4314,4246,4287,4301,3913,3840,3819,4588,4139,4376,3931,3476,3446,3785,3695,3893,3991,3916,4073,3757,3950,3781,3446,3898,3778,3755,3769,3632,3561,3606,3590,3806,4397,3474,3935,3675,3452,3421,3635,3693,3705,3689,3247,3807,5084,3769 diff --git a/data/era5-annual-runoff-per-country.csv b/data/era5-annual-runoff-per-country.csv index 44055ee7..862ff743 100644 --- a/data/era5-annual-runoff-per-country.csv +++ b/data/era5-annual-runoff-per-country.csv @@ -1,34 +1,34 @@ -name,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021 -AL,9921.845743062182,13900.722955927391,9710.931748556879,10574.663320350839,19341.246363906943,17818.135264440367,11442.713887022777,18086.801216289034,15090.128262650946,21363.26299103702,9091.698545327283,15645.252953546536,26744.08978638467,15193.032691775385,15984.127347228396,21350.165383112253,12855.252167834218,13420.929958145927,18491.92173822311,23127.97840031047,15647.322475185589,18621.138651647332,15899.845988546795,17394.46706381624,9941.517004312835,15056.517227865626,13546.145796746823,19078.487245825123,21734.889469128113,18681.018783118114,17330.7404590047,11854.58505075189,8621.019687739607,10958.633158319248,11928.114867207425,14053.437518158384,11478.547049310142,9794.162917024925,9309.704198107493,7531.383319836307,13417.032891488734,9396.693750356952,9409.269914411027,9602.245346872442,13721.093186096236,18546.848247572612,10075.274288997707,13160.130634381218,14979.3178626011,11173.442130939595,10656.167120597063,11333.102860367679,12218.649211273396,16968.134523176956,13531.444805168734,12351.485474236735,7777.709342414358,9395.578415692386,13162.74078695902,21279.522933687273,7131.262505063414,9979.8596278608,14852.708775826433,10550.911120633964,9976.081734060937,14930.01135394502,8322.107101243482,14871.511785547276,8735.240828081134,9201.521447196284,15965.927842545672 -AT,82083.36248472283,77811.80736180999,72623.28291775129,92135.9214601233,96990.37023646115,85097.60090834703,90540.2512560922,87926.80279582532,87840.33332785149,95771.51050456028,80100.0597367668,89961.83970292915,94250.95465501286,83836.27750897587,127502.64206362939,114305.16098508416,109841.9915507258,94950.56912780282,78607.44609072198,109558.29937241938,70075.51296406337,91798.91825728992,87743.39136454638,99172.3185471974,112079.92282492586,77403.35720896415,141634.05110901658,127491.44958971704,103513.31397365611,94072.4808516721,90719.06004331182,74178.70850428617,71954.43763473642,75430.93523721115,83080.51606488624,68680.54577957527,88997.37641681913,78365.83036558417,88108.35920540475,70055.7892534604,83590.790849829,80943.05621285089,88054.73669568839,64323.72991620271,76516.31784700113,88537.52869871816,74980.7275243927,76703.23963260197,90699.65433828124,82618.46892777775,70279.06284438398,76864.90473420777,38883.771847486016,64333.37459685728,71147.24783545699,61897.64030624322,56722.92181769331,64364.47029441406,80300.64217575881,73731.45518976511,60840.309523971024,77575.9681355992,74925.98195655535,87076.27014563217,55659.14157544586,71826.27744178762,65790.17399828041,62758.61938425757,63451.07652587882,63443.71962749899,60531.78695214822 -BE,2265.3933295931465,2299.7187477495568,1601.6287456097295,903.9162052526016,1681.6717933948885,1553.0826978024484,2040.8513201770277,2596.453742857211,1572.1256345899858,1777.5813929080084,2626.96550179367,2109.9419394561014,1095.552430877252,1153.3090754765356,2926.2047527605378,3273.3444811813465,2455.1462895729287,2709.4254348359373,2044.223080485547,3206.6821776003253,1403.4368531879622,1739.01009962226,1509.0861879549796,2489.4865224203572,2440.1073430603583,1152.6261514941527,2218.937185944037,2759.156597708309,2657.6330859359005,2904.764428136616,3657.83503348807,2493.2486286738635,2917.270148862828,2660.3113890881846,1897.0141168954808,2027.0116832611525,2822.5902787959144,2964.8457470488684,1943.761175974426,1192.1713008070133,1419.0119225208746,1475.2557281855488,1769.9742186132778,2647.8931490311224,2842.9882619071104,880.5015070232031,1197.5019163599245,2093.4616667083587,2614.387699318041,2455.605567526133,2964.8707630509653,2512.265466519676,1585.2842393930487,929.2255532772314,1281.2863306004592,1121.936801130382,2183.018089275124,2209.175694512598,1603.8823576630593,1544.7801250586733,1495.8450265096008,1698.4561860883377,1826.3476500921734,1803.4120415623293,1828.4613155494794,2424.4009518987536,1091.1596112517386,1814.2183897620703,1171.4609814371709,2056.8674333110275,2031.8962335362714 -BG,7806.165358407907,7617.879584469116,9313.915986883927,12665.103843530671,18165.703005314856,20925.111917073817,12315.95137614649,14307.215196342033,11652.743586791588,16042.778215050708,15000.011504505326,15411.367697482856,23959.284980030086,13749.537818599603,14477.782616320155,19301.913180173906,18779.64649297375,14471.754083245778,21905.976678210158,20337.934359162857,20009.368056844236,22642.8256575709,23291.544303799303,14596.266505770593,16672.574320967968,18465.93977853061,15123.0740003407,16401.953223276385,17509.31598177905,19228.19892146255,14599.539868168713,16192.551398587811,14129.882713144674,15395.87601647586,11853.583066311567,12273.885630367266,13296.879487675578,12962.17913948413,10178.141531948864,10101.748861881337,17833.95419276747,11290.360773903032,7050.797194092144,7109.831367133397,12879.727662239184,15849.231621819281,14036.330428384765,14600.701492135015,14377.532715491632,7705.7385359122845,8414.14109970378,12768.14503989922,11390.56673556146,10492.153643864705,15665.526881990423,13518.231074072748,9896.670696858979,8514.724851169687,10495.74229946015,14331.982881842356,7228.669024198985,6779.132502990354,8418.829006301234,16447.848686603495,15740.35987338571,11179.883037182273,8789.581276892988,11591.504961624405,6993.71096793164,8046.946588923506,10797.966046345515 -BA,23467.52324346034,27732.028396263388,21355.39127202247,21518.57483169428,38198.02048713121,26864.382517947488,20815.045478598513,30820.77172304343,26041.454718573805,32434.848569531026,20613.68138756547,29427.6067241259,33216.04695823398,35126.00882914745,35434.02869793576,33198.240125653894,27292.13451964922,28870.288475787063,34855.527471322755,40158.11721181478,26000.45986387781,30818.815452611776,25386.059210704487,29741.547122355205,28211.934365516674,30030.474291377286,28262.88980319508,36551.088477619196,29006.131913946814,27659.528119372964,23600.138376555304,18313.888493525537,16009.416242480263,24722.92263318226,19189.890721764787,24683.705818314953,20989.732351804592,20569.866983400992,18470.90664070533,14851.755901997987,25891.954823722892,19819.186826010166,18921.820235243023,20522.576037546467,27525.961934821684,30713.034955646464,21412.918614981576,21344.870107122344,26543.94285666588,19942.69654945001,23180.52553450498,25225.421682786062,17217.841128593398,25342.758536033023,22647.27040540609,20311.586220306715,13360.715771642963,18725.9052067595,21814.111731615874,31110.03238839381,11170.209355889527,11624.972537489217,20618.808518471225,26321.87815471064,18023.46871599901,20293.60245322545,15351.515268991054,23732.8659965382,19641.494693119246,14018.69083089969,18476.061736021245 -CH,96134.70662377033,78280.50065735803,75567.82823680741,75624.52378636891,84437.3353706146,82858.22758683441,70824.92066589095,89311.09471805945,65693.73271567532,95736.9646979805,81823.38979168108,71941.93730231738,93291.72439376163,67130.87226350856,103459.16116112942,100678.84780651607,97724.23622167954,103707.47043615916,84031.35407618036,103162.60292359442,67550.72288370335,80436.85045155323,87045.62560332651,91431.67032188186,103676.61542793321,68303.04781353423,112322.8911282786,90003.61666202937,91028.65800738563,79435.56403729375,84362.27602442491,71967.17653868764,71356.17066607098,70327.74412176231,72852.24726422041,60501.17532436925,83372.98013161327,74234.0349385613,61890.14596593614,54336.52856303606,58271.018596959824,62644.46734396249,75790.31562737533,69637.43067630196,63290.99710001813,60360.96649160057,57476.7610131337,62343.013781750116,78693.52307555292,73667.98513148604,75122.7031133837,70327.33051388402,33043.59766466136,48968.55545142022,47632.62274536815,48588.59714178414,58398.342285916435,57742.38347363473,42559.51792407362,59408.23894223828,57129.80243604273,71163.63652517287,70858.4268509181,119263.66699527185,55000.17388464577,60563.73895679769,51249.64855691976,45607.547672961526,60542.786248766475,50488.945849740405,62587.04259357905 -CZ,5741.811363153907,6430.8701452824125,6608.002211449021,5547.98412657507,11139.03676570244,9975.869136026628,10340.80877548634,13532.930674695574,7705.735677184478,7812.801872929193,10964.355351867012,10646.504003233118,9719.560436989883,9722.51782291833,19015.37334991238,15549.667939948402,15927.255735311868,12882.876953226223,10353.403919517015,11853.576269226234,10677.61771918624,10413.95103805089,6895.283030051313,9424.903567027312,12922.392855988994,9137.874616036986,17532.348544152504,18533.830228515635,15250.542039808313,10190.043701741004,11537.335951365127,9452.574932230946,5833.228549596612,5329.206957903766,7580.6976645678615,7069.4638232187235,11641.01844987317,9790.145937530902,7320.767578365769,5406.873869997462,5625.637231646826,7239.835546851702,6440.471526964078,10089.617439184036,12468.55796361433,12603.058166229213,11520.381274473184,9364.18293733304,10411.740148030329,8903.525346614548,9434.353552398077,14463.707947162726,8297.335864348554,6305.0428212307515,9383.102792968806,9420.905095490103,7053.530866655102,7934.504156979587,9131.766698685136,11027.709419784474,7973.011990884055,6406.065926850977,10728.184944007047,6645.433895571247,6345.82145823084,6499.675988954033,7016.463805946017,5619.135413529,4807.786670051716,5785.96568493957,7986.497102061061 -DE,37514.09293381361,41854.44001450301,38958.042582957896,35908.26729908446,54302.825387264325,53900.0627595872,49537.22949846474,58655.764340031456,37627.8257805545,42967.11131060519,58392.899587658314,47246.42956098116,36543.949785170116,36184.44504543948,76454.75505815547,77563.28089874369,65706.46393994696,62713.75591115003,50646.052126013274,74501.93068438585,33965.80961685558,36936.195615288314,42537.597915180464,56616.68921207296,56744.68927682596,34807.98202654087,56642.02192030585,72249.78534694383,61866.53633607989,55155.47864420242,60392.13262306467,54016.67652252674,53772.61604029787,44957.681101902934,45340.54136937088,48213.458592237475,66703.44582319073,60862.17019199549,41014.24992391146,32890.656129618095,33561.7114818598,35496.398391557115,43529.12222860253,55750.09930602895,59293.24549493131,37708.06634825865,37073.71374151417,42227.76427477898,55642.269571505705,50261.32889407123,50099.1653624443,63663.80803911536,33932.84222448403,24148.0930626651,39327.588161226195,34424.75266875371,37774.7468462978,39904.36386097259,38761.37664135111,43371.39725264248,35879.97041420226,37163.99533546333,50391.241894760955,37073.97568394232,36139.75677566728,42435.96482981362,34097.15586833773,36767.50341472353,28228.762854078665,31841.550922412007,39703.58319343355 -DK,540.6494487174206,225.87222027671936,240.57818634617777,370.37587945377,297.48979685029366,176.69208006156848,208.79213770008658,418.4554011794129,292.8102234525168,354.1220188699609,405.97396851309696,497.6042583966885,394.062076725445,291.3295691524654,304.5438623304028,591.4756757289098,629.1912050409122,479.19182164984767,353.75286712188796,454.0799499391422,338.48620130918835,357.676218196066,271.5200039604648,288.04880490856954,389.1757124784286,200.03398963977796,391.555913715114,397.29527898061724,379.8043799580585,514.7861201159348,505.7304478209306,381.57816134966373,489.3522161731293,301.717309458533,340.1024114463131,377.00536197863613,349.05617800662674,489.4227950883326,223.23589869898433,269.17110101837187,288.12441629799764,229.5796362727797,293.635637901186,464.89056739838395,386.583686695923,100.62743648672041,155.50324274468716,357.89273417380645,451.04208007822723,403.3432275318107,376.8995908622044,395.3896113505339,169.30459202493293,211.16687292699712,238.87912856891634,225.9981737610454,469.5229598902774,334.5021223766927,213.88993390188736,267.6283833775911,319.04746406617295,376.09256801086406,317.617725512616,353.26516627601364,404.2285931109035,408.5235836651241,351.86517079981496,305.15203377590285,361.8170659996248,441.45504335438466,312.14518786073575 -ES,49381.7181466273,42506.42487287232,29823.22966835847,33520.89863652133,42189.87541544434,45018.59980204108,27387.4917761516,45602.58407624375,62626.425244916936,94141.56249288519,66884.65469167147,67115.06386526441,82553.38984370838,62483.82642486853,54633.78478265801,97009.71651609142,47073.863176177474,55800.125131342014,85746.55555964066,72028.42027117872,75395.28981871007,97165.39237066667,52196.13272216457,55183.75674414718,44434.367388636274,45688.29479796517,107175.1885102772,376352.4882722023,122222.92956502433,46652.32256081546,42283.296882354574,45745.627884904505,49745.69531403085,62249.891346371536,58920.93920695715,48705.91089393512,49506.55303300167,60104.870297070986,41417.79510072781,40561.22111509541,48584.70074175896,41980.59062088254,40901.640882458836,43899.80095828514,42846.07384845135,68844.74333042726,58684.98840324564,44556.941393617584,38670.78308215774,46815.51322723987,68212.19494117319,35011.91030341564,50475.76713743041,37227.78564631605,21874.579431867896,35771.95151620915,29462.81813629621,28957.890173503936,32351.242924601538,48787.03990347552,31409.59113067243,24367.630996980257,54440.48961905899,50212.19464108009,33563.81874118821,47043.00929278407,21662.04001863739,49011.344970588914,40719.843457258816,40971.905822060144,45241.676643808205 -EE,1013.5168183220601,680.8524541483096,896.074617741102,657.0814978199126,1138.8891299468455,1033.2360728791764,1360.240006093535,1004.6950457068739,934.8774758153143,610.9977141696028,1048.0576885162222,1477.5046721309996,819.8347754595931,595.9919701101757,664.1717649435486,1178.672290642306,1112.7122616720162,1003.3658496852601,739.8499843054013,970.7396668771637,1156.5986195943308,988.0643633892423,963.0153554345143,973.0118510683724,980.7669857762866,637.7376743732589,1121.0664931638019,1485.3090062847518,1014.4287893275732,701.3843644468006,1196.8127434491068,1136.1215677919786,956.0911286121622,761.6620263988196,1109.6559596693944,945.8137139982223,1246.4435124663337,1081.0063689141978,1180.9951778617858,1433.4526339800395,1044.4962572791317,875.9289554452553,699.3911738148247,770.5276589427534,923.6083617038047,353.16555295606884,572.4961222214871,770.5595680360855,811.3520528619258,480.6204379373417,526.2783934002991,624.0252970776874,317.7449195254128,502.6073570248072,523.2149143909173,201.10844695565802,516.5064948459781,787.1638506300568,929.6905631193786,943.6792182991617,682.831069893961,933.1072250631543,692.097322772721,449.72254117947216,392.4173074585239,635.9676582877272,753.2897252561945,692.2577760060705,496.359994444626,685.8431112730673,512.1207984775516 -FI,37605.30609105331,44212.92045299994,43354.55443946037,40909.90249435943,45502.4817028443,31224.476747778986,41198.39417754888,37433.6293362709,28205.152814527217,22733.614552593714,36790.55908786393,45364.155643266684,28818.806516416316,35920.468538637644,43898.27049057533,41064.81684006838,48740.383821508905,37939.33952866352,30918.72594548001,32676.177851908644,33754.05667642144,33605.2810320407,40213.26757169686,46999.65997165162,40988.91471061698,26205.15827640759,41167.74001571865,25866.031354509407,34538.39918373158,28474.82496101674,52752.27216474974,31970.598763267328,35752.18054352296,34628.515223969094,27958.317625583102,31764.196982878522,30015.16030263079,26346.04561795855,37548.80632649389,27745.021972655202,27337.35846234453,42346.93155636462,32896.698992597754,22520.879762748657,23208.41547315833,19884.31515309925,22475.195958848508,33947.011695157635,26939.65172877202,32198.274008146243,28319.0878193112,25068.601753935876,16735.56947336933,29510.104024439464,31518.153863523567,22455.334677451585,28461.18834411878,38706.997170480194,29619.48059832548,29700.763598820195,30127.95453034573,45678.82538666528,31580.034602099753,29256.819253905658,43076.06538538077,49489.04536337738,37281.852766328535,33818.560580958125,35465.53242057822,41410.545080415,41567.72109759498 -FR,135094.49763612094,106772.95460342853,80280.31347296045,74490.3783289433,106687.24245156738,78827.6552216503,82482.11027901788,110101.24506868717,102231.57173723538,134019.59611286796,107848.78158188045,101612.59295931137,120079.53146371644,89568.66448178052,139585.30725052828,153772.55334552698,108799.90779570332,132530.25240249874,145056.24077647954,157344.40874499045,121182.68180087653,135378.15307040678,100408.75538533325,132164.7891142495,122382.6612084835,103706.50937621434,174240.52624537304,149853.10658224527,139992.58441391244,124892.14391178945,138893.07653615897,136102.17909683278,136298.85434619425,112484.75227834118,103842.75366698352,105453.40277549413,121935.76619549586,138379.45234918175,71924.60006455882,68830.14474115185,82603.77634528138,113556.04015089742,104293.46882473862,133822.28230897718,106263.7222156586,102481.34621013676,87080.48957235571,78895.08319488679,105735.9820525235,105626.7734987112,124313.3006359069,92144.11932119,73537.29646152578,78137.60525599915,58286.814348802,68928.05802270533,75743.7796112372,83489.37862547796,61518.93775410048,71311.23184506799,58810.65089438103,62581.66694545332,108566.1756738168,106810.3035898108,64981.51870529863,80829.27869961815,55203.39988738071,99034.47679069567,69318.43286028007,80169.78942387344,91015.86505778233 -GB,30949.55733300973,26701.9428167181,24834.423901258084,36292.29933386541,21223.79048684261,23695.358277919488,25987.57619398849,29907.138025215598,20532.262685247148,29689.355990879158,29755.7349738537,26456.609914217806,26827.642866860373,23873.145060634775,28779.074240844395,32368.78110647752,35977.394307138864,31071.326823875082,26446.212227329706,32888.07880400224,26015.735528737063,30161.596277105604,23017.874991984525,33287.290870143,28286.810808036254,25581.658649545065,33234.01349421005,31886.616851943854,36147.13303532815,34133.94123938026,36553.158784009356,34512.41082508442,31536.090754720717,28572.314934249887,33275.60304522956,33665.001595891976,29575.879486696827,34513.91395990196,28917.71257427291,33609.176553253485,26240.381135352633,32589.192149993025,28862.78621634025,32807.4074928576,28488.125666145854,20034.93309228305,23116.389736102017,36396.90134863421,35532.192401610075,39288.48780281492,29384.81519197965,36157.931892943554,21622.405196644995,32040.743170655453,30471.91526631006,28610.855281883465,33870.42864117695,37281.10394972126,33227.13302814586,22275.90424618414,30588.672790028984,34121.358436958675,27706.739428180073,37230.134388487466,33699.78058075289,31403.25713954576,26791.643973463473,25928.83232662774,30294.933954035565,36884.703709615125,29006.326905891798 -GR,10056.853784361187,12820.948661755581,12880.09713386794,18009.367077161973,21378.182658177288,29473.438101212807,11770.791493072751,17561.986308683798,14068.336209442465,21036.22984593777,10600.651816726047,19253.94027167335,33903.71393281602,18899.558983910043,17444.093386496537,23383.013428670623,15695.74724949063,19981.88173635776,22837.72155515553,20477.278624856677,21882.21250746782,25630.65513791745,23207.036995448034,22044.998521881807,12010.599831751206,19432.667576547075,10483.216379681078,17709.119022396855,23856.615736538963,24868.152661457774,21212.948012018598,19349.21918097175,12988.230031417628,16765.76278511076,15711.921661553248,14768.388537620414,15953.652684601051,12434.694106124754,8265.22849298033,8609.897588471382,14667.4570613014,8511.641075667938,10022.119539267658,13526.966234241496,13788.166042309897,20514.65575034389,13890.655920759986,13637.35506363307,17713.539092926785,10603.937587040999,9085.188935046803,13431.534902143163,18237.093734480102,15007.784707319466,15322.74478671021,15189.508916238075,9627.363919501071,7964.610286111404,17730.814440852053,21625.83796282357,10692.331430067703,11630.957871879938,16037.311332863352,13770.795305947142,17211.823293162783,14042.921372422215,9179.230226001768,15781.789228215457,11036.807907632012,8148.5700551254695,17837.056638784255 -HR,11579.119396857217,11616.785819262946,7841.411279590863,7071.274416413621,12992.083400898755,8164.444623202054,7347.788717816701,10332.483465428491,10537.238741811467,14479.677080073134,8479.661662510043,11787.072656273116,12862.758623825672,13371.003032039336,15990.668161905827,14470.61427957732,10644.752476691014,11929.91211438134,13611.162472968235,14159.968181810045,8748.9998436583,15752.17883640428,8576.387915317433,13121.48137750286,9754.915357083264,10574.934113880938,12339.192872828058,13526.82683401755,12407.125261525374,13314.467203516846,10589.407510915647,8240.264291214513,7438.667886688274,10422.72691638502,8167.94266416981,9179.047407118169,8517.079324039581,8574.526688740114,7000.526114186264,6044.501432950472,8424.638032244015,7640.079353180473,8493.38568955205,7673.466816227631,10113.96973112034,10475.583854629525,8161.447547783003,7730.598307694147,9688.392563588315,7721.732973546704,8547.91442119075,9110.630144082634,5654.409914846469,10449.908940883637,8544.776426500835,7703.363550389989,5356.181480736791,7888.76450496884,7981.496673656482,12159.302077747214,4232.3935344941665,4890.509308451722,11184.320641158047,12936.9950624162,6984.475921997467,9245.055929521772,6446.204647314787,9728.03403894923,7468.897556955247,6117.536838412799,7342.634549696792 -HU,455.56009955160323,446.6314758325084,756.8984035642842,450.9800559529234,596.2398492658431,618.0772176598714,433.5306920564666,626.6699838105968,736.6623236995524,901.6628598550868,955.0588428000881,1010.9577650474141,1739.1969813800204,989.7527773708749,1794.409065735425,2141.779921355298,1587.224990709883,671.8419282109866,1725.8355118081338,2716.2211930211206,1024.7764676942138,1478.4297579371664,1174.856199808959,1380.70450266654,1412.5023358393119,740.4722294240396,2077.892875467242,1382.2122922975911,1644.3319455706533,1323.8387691522125,1268.4319727220777,1050.1561979992803,938.7640185853782,701.18673897032,1176.2218406698482,1296.5341770126697,1360.4975641937087,1113.61620590335,686.0888933448485,340.9577501900905,585.7771480398817,710.4671894364953,683.5190908209308,901.0768559915952,882.6855336512624,1696.8667744778322,1072.391017559335,1091.9628754375356,1986.255314199332,1224.1891103332646,723.3105004079888,525.4091579835733,484.84230756145246,965.526984284363,1182.1048527111184,1188.8833398485922,413.588170351592,480.2721461089437,695.3047160171476,1875.1966820116616,1424.9690036241302,335.4105482008909,1504.9089491398734,1485.372787096725,1238.0161031995012,1379.3214547239281,769.0933902263423,1164.4795232335282,401.1056623458921,586.967649321741,686.5594518266915 -IE,4646.742323576806,3498.3840852321937,2544.6578209214726,5419.077105100732,3195.826410242899,2135.0862825425293,3896.6031468108818,5166.0575828547335,3059.5430902455864,4420.523688067632,3920.565970045664,2677.658691610785,3238.0778129090736,2814.899041865502,4169.640537659651,4975.659864222032,4131.237385306254,4051.6063579500055,3501.9810380506974,4162.222738923252,3277.97066925379,4149.907266073347,3535.126191101705,5127.397347805918,3672.8392481603883,3233.4968306810615,4670.955668853978,4602.662496185422,5486.794576286672,5974.860239294209,4958.279351735843,5539.220771177308,4814.939874910363,4704.080605250908,5214.372862088697,5579.052373684467,4424.669817520398,5645.170219782959,4099.107666436778,4291.534915722901,4394.7348113611615,4474.842169491055,4574.431496810677,5809.6920444413845,4586.044007664658,4500.049573188483,4158.002042556449,5864.151573833777,5389.317421868625,5602.682945402753,3910.7950042057882,5664.313605042361,3809.963053559503,4119.424688220842,4183.3641097691625,4756.243128847813,4885.19842669336,5839.576896771334,6529.030637616166,3851.468550158534,4739.247453475783,5116.873230654843,4346.868803644192,5780.6460718128965,5283.18966576195,5253.677788447396,4182.318532051922,4579.528423701424,5332.55258145869,6160.501534866154,5064.7000821427855 -IT,172598.9057049173,100312.33974168803,109683.21050744873,113141.95504995789,104153.60992530867,105687.75931391625,108887.88674499927,120408.08444781008,120463.4718424679,176044.98820314519,110983.47718210719,108661.3888675,154479.99952596257,116866.21274767391,140970.07450678368,148795.1431459142,123467.91624840492,141856.2012294592,135145.74559391223,121025.70232844367,123064.2692081519,158675.8479818625,126408.22188494769,122698.61897984576,134048.90222163082,141351.40587318933,183551.69201916258,152672.0987165877,152463.24070715246,129214.69623803807,126406.52003570941,111266.52387106014,105493.22493839792,124930.0152276459,118811.00097800085,107475.13484215035,108705.61617459086,105553.12911266208,89696.47047566871,79022.57929325203,102862.21537887226,110384.19134436303,114736.91039530469,100806.28542965792,84803.88252804938,120635.19844583895,89284.70639754581,91327.36842742827,112272.49254052607,121214.98394688763,100240.69732658492,110327.24980482439,67667.3134977533,93496.05161894935,74054.55044130566,77775.69469931335,75858.44303177306,92083.61659880447,94760.12813659209,130298.81027721112,113068.08204604911,102862.27823880903,124544.42911673438,173919.9577739064,87247.90399947706,91232.2769509342,68511.40136893332,110593.38607511377,103785.63569256017,87869.12433673623,92697.61009264145 -LT,3126.90226977831,1475.6787373817235,2475.307120672793,1105.461669987713,2895.355169108127,2328.291848466701,2773.100951693534,3565.1300060634676,1726.340017569786,2441.2869150017605,2739.255286641479,3393.627534013301,1948.972938917477,1503.9304931932238,2081.2181025571476,2387.4356286402945,2953.7202011167815,2442.643404228762,1575.9037853337413,3106.077653607497,2438.6998492607095,2321.3335398002305,2455.4955733417105,2703.979150849733,2983.428649152806,1271.81865757996,2291.2165997279003,3624.3054978962264,3066.52482874976,2692.4730181815085,3077.131323187848,2583.193918114293,2346.227785803459,1679.5438811966314,3224.9829735377853,3118.546035682447,2841.2519919875017,2793.689370450914,2688.2457239306805,3241.443663108373,2559.3234295762136,1702.002348908642,2110.46892607847,2728.2093372090403,2507.383271401867,987.8894968242066,1210.6320667482842,2619.0625969612056,2041.7494156189375,1077.1024719580128,1501.0630179433206,2093.0805484121715,761.1714789679556,1438.6161577229564,2052.75406588365,780.7629955514127,1806.053023318598,1637.6952437203324,1294.75789506843,2045.7605537026564,2014.9263059368886,1513.2399919084748,1700.3251444304037,1310.6134461272318,707.068706016363,991.8607300754669,2210.5243412620116,1945.761381971759,656.9514438734058,938.7049363615082,1091.9224609932446 -LU,418.42920407960173,402.65326898169104,245.66041042705334,140.5213247873591,281.65083355306945,239.8578158452654,369.22101543741394,483.78479198242695,296.9130979040409,276.1232951910135,459.8791399297912,360.88050800564,165.48000564979304,183.08661927563494,549.4327262552889,615.540914852196,430.5724249074097,464.9649192455573,366.43220700786026,562.8555247965114,228.93628708423907,211.2546971696525,190.68337965968735,337.11947715404034,376.86900759463407,153.06162250371963,361.9412034686643,457.17182659872975,474.4467062976349,501.35146460886807,586.4359860050876,446.87720467222556,554.4763793156474,495.34599197145104,293.22338952418016,311.9404169698979,470.26963100793296,539.1966800252237,318.1508533879876,216.80440341571304,213.96493869659722,161.79868975175182,244.05142665329072,449.452274496719,514.0163752203341,140.3179752581265,173.96942733863747,312.73695003201067,389.83220575942556,401.09422881834865,533.6829497064967,363.9324325652479,243.9448809708681,141.83825708815394,174.8785415794147,180.93947242990794,337.92060394534246,342.3576188750888,243.21751195509597,234.05807708972188,220.32797632404777,264.38928306703747,336.6463620917912,349.32621250528973,289.85643977541105,421.5786735040934,195.16848080033785,348.6723038250213,181.01976524286118,391.4073725411393,335.53788814460387 -LV,2742.6556866506367,1837.8325027812643,2554.170761349389,1408.345733539928,2983.189997195677,2825.061612760662,3252.3974243255384,2886.2924715658505,1956.4363533791625,2047.5738516633846,2396.823663944175,4066.8157610189646,1865.1937720377932,1213.3814003625498,1799.0008428733133,2700.1570058485836,2685.678969351212,2489.884608424664,1643.1417843905015,2409.13500668555,2592.9272177648704,2235.207139152776,2147.227486416904,2582.289866216919,2592.1022950383003,1400.2389662856958,2360.0229699498527,4017.8529783072768,2384.614549536931,2229.7220033855633,3208.439621353169,2678.7332051326716,2668.5315414635693,1705.3124319563372,2816.1467857724074,2779.7212753206704,2548.8356765576805,2583.5815153824487,2861.3233286998366,3801.9993997175525,2885.329135114707,2265.350140707051,1837.2956559244064,2087.5337557102102,2249.8356476827344,853.5386928200795,1689.684828383291,2653.3751344813045,2109.0096432617606,1182.3316650686795,1487.9132295244858,1974.1178903388873,1027.3242775723352,1736.361793878124,1741.9204323497202,701.3946960765046,1526.0106468283361,1844.9956663852768,1722.690767934754,2194.735679264339,1757.0892689497684,1974.9007736328324,1883.6056453393867,1405.6090440523008,1355.4439688992024,1295.7921755717964,2182.9434502570357,1620.95881111662,955.2966396067089,1490.1655775988,1270.5915407733335 -MK,3934.258904454459,3692.0813330320566,3668.815892166788,5481.091007849558,8488.277349663611,8514.814821434962,4861.071723840239,6878.625964986481,6399.572820343104,7510.160197503697,3410.068805763449,5394.1653784487335,11852.098687247973,6238.562291909563,5957.282159254423,7239.168545674971,6704.994620967638,5343.254672711665,7690.122171456297,7543.1707758996035,6080.923842798452,9518.22452251825,7931.36999814296,7898.373553315725,5296.06496225987,7158.993856907015,5568.700579027411,6653.618095140364,7658.60790313609,7384.3372015299765,6359.355811805509,6311.4116310067075,4303.248848133382,4384.047563174607,4091.082807237865,4939.915122052565,4226.085259691547,2768.0039025432975,3428.9467644601264,2294.222990992098,4834.495252793617,3325.6396521134557,2522.690466358069,2976.927612194815,4721.490759581051,6218.919122814915,3840.4729075548557,4211.680380445357,5623.802967061423,3683.311545054556,3010.5387111938044,4030.600677147787,3746.016920616422,4369.907262961726,4375.170573617275,4171.022704527618,2702.082556773276,2500.5709190188645,4370.4076446296785,5204.859735574909,2501.3689966568136,2522.4142074268602,3898.568577966785,4120.496629723428,4145.529030725163,3980.5145191045517,2967.8383253548755,4325.530795978238,2351.320803369623,2869.298937488066,4644.825806471018 -ME,11787.036249138713,18552.496612764233,11097.228684668844,11567.930061084586,19293.29710814638,13959.20571478613,13046.18440612437,18177.491235848003,15681.709335959564,19349.950981118494,11658.5954682407,15979.557715971854,21966.784229466284,16319.44299708603,17409.40677448169,19267.118980997075,14169.834731486397,15882.152400499632,19649.60512617265,23317.326436161944,15993.83236649745,16724.197023812518,13680.494674103275,16947.38155713745,13396.216553276576,17144.464963358845,16187.204710073258,20417.876685607593,22530.120155126962,16197.908505488407,14818.545420474018,12719.274460270883,9622.464989039141,13369.875886578782,13078.849292203078,14951.85122042927,13681.691957367619,12435.207850184568,11885.89235643587,9516.042262408026,16926.063160570764,13462.909968102742,10042.999218445517,11916.714437943356,15158.632522247093,19735.53511234594,11491.695345503264,14075.890065382568,13952.132515246369,11677.32833931845,13022.018989752623,13358.031703205903,11534.177624564669,17635.48411958614,14124.491791464301,12392.738752899031,9187.905148236658,11106.432128782126,13780.482580236776,19889.70854314474,7004.765863876614,8204.168680103983,13925.208337027952,12712.182323875111,8528.030231315688,13924.890575378206,9037.809310147335,13972.095665379566,11360.358971424077,10280.43536084397,13775.545442858487 -NL,132.53876435280281,105.25304624029256,97.45390390948565,59.629996943856206,126.17294913858377,100.92785922135535,110.87608266899032,166.47617616014315,115.03831975395074,102.21679880589629,222.71184206736731,164.32395798051633,88.95057195947412,70.61286255591416,116.64203846425596,229.2598570422647,176.71083656110923,163.34614915846544,135.23541074052787,153.03725726999411,84.2996330000842,75.50229060079856,87.79575328623356,149.0911400069578,185.89892961221338,65.86854604814957,122.15247506918442,163.86971747802477,177.38160465294413,173.97671792234624,210.94537197363266,138.15528852664815,157.7989701791954,164.8431327190436,156.27033317337316,144.7881412408737,172.55396177597567,195.57239229094031,113.32208112175368,57.91841778157319,69.80575559844598,81.95247611107445,154.25504072397393,213.16593963287744,185.6861094126344,50.88580789479815,88.6770750590963,180.59511129061775,175.09641999581325,134.73866646771805,175.89672487625361,170.10222446753016,112.93557838603432,69.46018341018433,89.82211025011819,57.645723008783136,122.86182387892966,128.20825436811367,82.72980960226074,90.07937846739043,113.22245968360778,109.86527486394354,113.13774281842522,111.87536788688416,113.53271254663122,140.01537175074324,68.64291161119651,101.90820271032081,52.313311323047174,116.8375292031251,120.98114114085548 -NO,268338.23623559956,311516.6976002237,354741.82081862347,287750.3093395867,277336.7794878445,277384.3177020413,343804.7636848019,309909.39898200217,279870.8316011512,240316.6988310159,337135.04130569333,320967.163231472,302346.276731951,373063.16157364036,335043.0981929385,271478.1367425455,378240.8226290755,318135.4534804216,235625.6466770364,244547.82624561962,342177.033729037,330660.24479289196,373161.4848287328,318697.1789732917,345399.49658985186,314419.8189439592,230963.73709983748,236070.00307120252,312676.53469423676,195102.01076090848,231756.2941107393,196457.66930311252,255890.52889680286,207980.18388759278,250218.19793663023,221472.83820330602,212315.28230042476,222774.69138098884,210372.25250462766,210846.3448041017,177438.35447152023,214108.95671057343,190417.02324135366,175558.31404488848,199041.30532793878,154342.13931409398,175902.47007757265,215120.2640019617,216733.8944940455,261370.58822336013,212333.63219332727,174324.40313248086,166539.1770850326,202012.88317391058,238213.58919108333,170401.06338583003,217109.81457913358,185684.48673203168,210764.408869451,180452.94255978477,359959.68381729786,220133.80814962948,201815.91045998363,193256.2376798832,225141.35101977925,194502.14845672756,241700.45583039062,203049.47691663646,189440.21996991744,241270.48318453485,196628.83730256284 -PL,10323.210329129464,10102.880830361863,15243.556644277647,6316.576710839603,13844.440254769646,15125.266765937784,15697.445163802722,20547.692524530372,11483.751822471613,12736.801698643669,14242.313560202334,19975.533453959804,14197.61841088385,13385.258603233342,17555.946503015533,19526.389852009346,24990.22970093532,18554.95543612019,10610.557656768206,19356.459381427685,19657.930603206125,18732.50311338716,16842.606570419066,21220.5523273715,24157.44207211756,15607.0096942104,21677.41127186343,21298.26291533998,22732.35472759213,23096.919661671975,20539.587419825057,15690.593097829358,10514.527177352287,9757.003902443616,18214.127020951153,14743.470132504332,14160.372458977477,15574.81487531224,12340.373515759937,8851.92371521615,10791.411372967183,10330.247763133175,10795.54750377256,14738.227630388099,14374.438386354948,12177.648415014886,14450.3889852054,16473.394758962142,14491.781691174727,11650.64866730713,13724.64695911459,14468.081620316902,7425.533290488975,8039.550610683221,9468.54351850099,6656.34004885665,7842.310345436549,9593.638690519654,8828.256800239144,15874.058827778785,13537.338641985261,6174.396712827303,9509.500411581042,9436.102173346171,5360.954908688417,6309.399306468634,12402.024613286878,10602.512257049677,4725.103685514244,6963.3130148445025,9124.964758601689 -PT,8372.129135066036,5969.31083523099,2397.6586063764958,3916.9962424030286,9654.699566273128,9603.363148222781,4163.162870337118,9179.465624121007,12131.854156488425,23406.646477036124,10635.077955993413,11029.404714084018,16475.917880350513,12087.55769685171,9804.492049893286,26178.184180984652,5669.820254013018,7559.528320921835,15405.930172416956,11163.387795923936,7088.025310785357,10191.330496756716,7128.069257230898,9335.631563569985,5236.13128329125,4572.251664471752,32605.577182903042,149323.86523586328,34294.81803755196,6061.11721308257,5836.654497517657,4843.7020037722705,7814.782411245904,9395.759000250582,14057.157961109715,8192.288977642056,7655.760207241933,9203.645337709624,7637.7450966202805,7971.812432879156,7421.37678917759,2935.2871895485287,6329.939163930326,8820.796560748415,8944.109217212255,14719.27363438586,11050.779819799696,8379.75073967695,5590.525909815882,10485.131539563748,20476.028147427794,7715.162648805314,11939.81827695821,5116.2596877306005,3047.0903835389504,9273.489011971804,5135.313604526994,3331.418010762715,6338.048693933388,12105.616460835923,7097.468638389797,3348.213951094401,11773.920694867731,13465.586888738457,4379.602415677836,11394.463621230614,3104.8789319036796,7216.150544702967,6653.765864361187,5720.580737490315,6685.493238874142 -RO,19346.344374357534,19295.50358149612,27702.617554877004,24644.67023787785,52797.882559506776,42262.7162454671,34689.01143849651,42583.74114324521,28973.147767939397,36882.64868179707,29063.471368254675,39575.626278602576,31898.858414072816,36283.98261870408,42207.50410750205,41714.957670180156,43270.313090823794,40474.54716426176,53565.91349208634,74865.02611452111,48190.11154819992,57257.26135564704,46523.80416861758,44300.83791323246,54901.1701096736,47361.27151969814,49156.09266449866,56461.30009557872,56062.45724028393,58506.511677323855,48499.732173446595,45901.64074770707,33171.12855766741,38310.49272614435,39377.41586450999,28638.803870927226,29424.553978129992,39429.14347226504,39300.73151290347,27525.04968129815,47095.77682827757,30948.90232192865,32939.14262154816,30155.99148400138,35067.04977301419,35592.25066656211,45790.67404045973,42596.77718301701,39223.35618808953,25767.93476452563,30963.38609617001,30034.908201595936,23323.05819720473,28517.276888551194,41560.85308154171,43999.15897330077,21427.19650317167,25084.131072037453,18450.764512377853,38182.39266803458,20422.517191285966,14090.243196787245,21998.55223596247,30809.187151501046,22071.90474198888,31906.454754357772,20763.073093214778,25620.747974742615,19248.368008063957,23289.011422937554,26669.846131314298 -RS,5968.673897869134,7450.873145908507,8457.218084424714,10466.134979346216,18700.932768467817,18783.264457747777,9647.157790116991,14650.396388121844,12360.14810912279,11640.673528541236,8882.446980807292,14762.619600006037,18399.930168952076,13646.806400326906,14489.119148714197,14104.804002759012,15462.34970923992,10894.228431882033,15095.088711819322,17853.281396922546,12916.46431873845,14207.379133135786,14418.834370720482,12752.5957180177,15544.588217112372,15820.904121022999,13534.055257847373,15215.146639151637,12996.626380040323,13029.919161637963,10196.668003968522,10284.440766030819,7022.693160251435,8401.249663323453,8435.803252725058,10265.915943082338,8623.546341166757,7782.429841191159,9309.259412625106,4849.32865233776,9480.40891035497,8237.330612702019,6688.9341497267815,7113.796951355988,8945.392918392941,11391.406447517316,8770.78174795334,7797.074404297926,11205.567652241964,7490.638744688466,6890.626375097134,8721.152535625733,6986.899718851523,10014.515393386338,11863.685949406314,12576.12226693591,6930.903954576986,6933.68818306879,8436.351253425808,11680.836931112251,5673.257881932308,4512.930178739657,6094.8735580904795,11616.485592765608,8423.704814584986,9582.260510301834,6280.960312130538,10196.683253538626,5869.428152205924,6637.126459584064,8223.324863109141 -SK,6885.47211985414,6956.591212284293,7116.928783228905,4573.269245439668,8169.130903254093,6799.092645889461,7190.199390340817,8819.311158887818,6679.080394471699,8681.76846617681,6714.688996801623,8780.135433744465,9674.052829336924,7510.89080672348,12315.672504913706,11551.288938768861,10658.095118642217,7760.467099195778,7334.701885838525,11743.053621084162,9101.455526104724,11252.254293590808,7089.2297957961755,11692.575497480175,11870.620362608648,8320.411050776946,12664.612697391287,10840.053026355938,9544.145158945727,8285.851845920657,6554.955003499832,6014.385824757616,5119.229272436076,5566.197178944401,8283.751441606055,4576.739002618681,5529.727054286627,4884.285979430572,7030.767074231632,6380.185010419688,6092.06334940043,4789.6919845964085,3988.728835990378,6100.445127127096,6174.336930810738,5839.492530664778,6739.897695678873,6073.547495791424,6239.663814901599,5985.626769812626,5946.910319392802,5350.4706690989715,2897.742723724252,3812.447551889599,5110.734824948982,5466.7571969447445,3822.1224333717755,4189.745228198809,3608.9397299109723,8925.718578619328,5520.297117401385,2338.023634704523,3634.014208205775,5079.021357670912,3789.3939110245783,3599.858750509022,4222.707040620564,3096.1701009538024,2158.8092391216674,4542.203594136759,4220.210061470592 -SI,11752.798116380785,9378.602450871665,7169.30972105447,8221.267552376507,10568.142173580174,7705.119699907013,8559.440940655051,9496.2682906945,10641.418485889739,13644.09405840664,8756.865265119286,10877.994032024846,13095.473005855994,10408.222250010325,17110.767148034232,13257.44359305617,10163.420442559087,10743.809603872312,11213.570708968457,12419.028940460184,8518.188189494229,14975.496301661744,10217.449212514946,10521.007791805137,10759.209828867228,9699.803414833696,14530.647692616923,14530.715084460895,12439.143395173185,11990.046930204517,9001.647305603035,10111.423546501868,6824.172499114327,10267.968760960974,10233.709492652128,9562.175707725224,11231.941186997657,8178.692540046128,8568.526412713521,8103.883097000008,9639.895318751553,9157.43571368136,6814.50158997294,8089.913064615838,8170.645053083449,10765.044719853075,6713.170108103339,8936.8362631332,9542.147586182518,8964.110093884974,8653.114721452737,8353.75428643612,4558.589088593759,9432.405903987477,6927.92152111369,7408.760392367348,5834.871486466167,9336.912851251047,8839.494837985663,10766.693939731143,5073.937522450624,6475.598951785893,9482.419717110955,13414.771212079502,5906.5584945059145,9942.151265372298,7696.092255607837,9521.835825354157,8476.124990692872,6361.010018809483,7504.908031281684 -SE,134822.12256461562,136958.6213484757,175679.6273876132,133962.36617697845,126787.36233921513,130861.49290945902,151133.2982760823,140247.52694114187,130508.52271890236,137421.63579450184,164132.0529341604,142467.57286064525,135886.87305352974,163762.3962091317,161128.38161511483,148196.28633931337,167892.87677861055,132017.696130452,105953.99289036485,119407.22923207263,147139.6039546916,151309.55114963037,164893.61323375857,137608.18237925606,149284.78771947857,108749.15747050248,131859.531763871,117290.48017785426,131751.97960784068,111117.27409251402,110551.615114603,81550.1135393761,114677.940027603,102356.46697333359,128977.80283219383,94483.98267503879,114937.96457142044,93256.91327642264,96751.29026217168,91074.34139788701,87931.96567208324,96560.83822983531,116746.94389793588,64626.25905820224,75156.91767736348,51489.37512699482,74729.26978432719,134673.01513808029,110440.65771030058,149033.9827088587,143576.83069821307,93040.02354987273,64075.160200006496,102493.08906248632,106664.82884715112,90351.43771324471,94801.81222609026,92445.93458012305,88919.20770998915,108111.72872590217,127440.80298482065,124444.06618883039,98961.91573013023,87913.90602563386,115956.48217115598,95526.84265190935,103459.08985036932,86058.90377748368,99040.9103276256,110493.22773914765,94182.7249029169 +name,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023 +AL,18102.536984526414,9362.260840506311,6061.862820153789,14283.904408113205,9819.184491956023,10228.254519456263,13788.284450369407,9581.270108803017,7938.384836547995,9040.045836743586,9921.845743062182,13900.722955927391,9710.931748556879,10574.663320350839,19341.246363906943,17818.135264440367,11442.713887022777,18086.801216289034,15090.128262650946,21363.26299103702,9091.698545327283,15645.252953546536,26744.08978638467,15193.032691775385,15984.127347228396,21350.165383112253,12855.252167834218,13420.929958145927,18491.92173822311,23127.97840031047,15647.322475185589,18621.138651647332,15899.845988546795,17394.46706381624,9941.517004312835,15056.517227865626,13546.145796746823,19078.487245825123,21734.889469128113,18681.018783118114,17330.7404590047,11854.58505075189,8621.019687739607,10958.633158319248,11928.114867207425,14053.437518158384,11478.547049310142,9794.162917024925,9309.704198107493,7531.383319836307,13417.032891488734,9396.693750356952,9409.269914411027,9602.245346872442,13721.093186096236,18546.848247572612,10075.274288997707,13160.130634381218,14979.3178626011,11173.442130939595,10656.167120597063,11333.102860367679,12218.649211273396,16968.134523176956,13531.444805168734,12351.485474236735,7777.709342414358,9395.578415692386,13162.74078695902,21279.522933687273,7131.262505063414,9979.8596278608,14852.708775826433,10550.911120633964,9976.081734060937,14930.01135394502,8322.107101243482,14871.511785547276,8735.240828081134,9201.521447196284,15965.927842545672,17077.541703886527,14104.446634983404 +AT,86531.51734236983,70042.82795415918,55673.922583448926,73201.56141483008,77917.51024365649,61393.73261184873,55048.20583071285,91666.41522182143,63572.87951011166,70463.32537160354,82083.36248472283,77811.80736180999,72623.28291775129,92135.9214601233,96990.37023646115,85097.60090834703,90540.2512560922,87926.80279582532,87840.33332785149,95771.51050456028,80100.0597367668,89961.83970292915,94250.95465501286,83836.27750897587,127502.64206362939,114305.16098508416,109841.9915507258,94950.56912780282,78607.44609072198,109558.29937241938,70075.51296406337,91798.91825728992,87743.39136454638,99172.3185471974,112079.92282492586,77403.35720896415,141634.05110901658,127491.44958971704,103513.31397365611,94072.4808516721,90719.06004331182,74178.70850428617,71954.43763473642,75430.93523721115,83080.51606488624,68680.54577957527,88997.37641681913,78365.83036558417,88108.35920540475,70055.7892534604,83590.790849829,80943.05621285089,88054.73669568839,64323.72991620271,76516.31784700113,88537.52869871816,74980.7275243927,76703.23963260197,90699.65433828124,82618.46892777775,70279.06284438398,76864.90473420777,38883.771847486016,64333.37459685728,71147.24783545699,61897.64030624322,56722.92181769331,64364.47029441406,80300.64217575881,73731.45518976511,60840.309523971024,77575.9681355992,74925.98195655535,87076.27014563217,55659.14157544586,71826.27744178762,65790.17399828041,62758.61938425757,63451.07652587882,63443.71962749899,60531.78695214822,73567.34222821795,63977.67627260971 +BE,1961.4766789766115,1152.2739476527088,818.2925521347668,792.0469723263222,1593.7272156934505,1164.481755817633,873.079191781097,1304.591358175381,1034.616549532147,1222.8331458954544,2265.3933295931465,2299.7187477495568,1601.6287456097295,903.9162052526016,1681.6717933948885,1553.0826978024484,2040.8513201770277,2596.453742857211,1572.1256345899858,1777.5813929080084,2626.96550179367,2109.9419394561014,1095.552430877252,1153.3090754765356,2926.2047527605378,3273.3444811813465,2455.1462895729287,2709.4254348359373,2044.223080485547,3206.6821776003253,1403.4368531879622,1739.01009962226,1509.0861879549796,2489.4865224203572,2440.1073430603583,1152.6261514941527,2218.937185944037,2759.156597708309,2657.6330859359005,2904.764428136616,3657.83503348807,2493.2486286738635,2917.270148862828,2660.3113890881846,1897.0141168954808,2027.0116832611525,2822.5902787959144,2964.8457470488684,1943.761175974426,1192.1713008070133,1419.0119225208746,1475.2557281855488,1769.9742186132778,2647.8931490311224,2842.9882619071104,880.5015070232031,1197.5019163599245,2093.4616667083587,2614.387699318041,2455.605567526133,2964.8707630509653,2512.265466519676,1585.2842393930487,929.2255532772314,1281.2863306004592,1121.936801130382,2183.018089275124,2209.175694512598,1603.8823576630593,1544.7801250586733,1495.8450265096008,1698.4561860883377,1826.3476500921734,1803.4120415623293,1828.4613155494794,2424.4009518987536,1091.1596112517386,1814.2183897620703,1171.4609814371709,2056.8674333110275,2031.8962335362714,2907.836627473,2067.170862372187 +BG,17071.604805088016,14499.026058918833,7232.927769745818,11963.806716811183,6134.985167502051,6976.20752617876,9144.48113078865,10476.930594688338,7275.174931794049,5983.600586215025,7806.165358407907,7617.879584469116,9313.915986883927,12665.103843530671,18165.703005314856,20925.111917073817,12315.95137614649,14307.215196342033,11652.743586791588,16042.778215050708,15000.011504505326,15411.367697482856,23959.284980030086,13749.537818599603,14477.782616320155,19301.913180173906,18779.64649297375,14471.754083245778,21905.976678210158,20337.934359162857,20009.368056844236,22642.8256575709,23291.544303799303,14596.266505770593,16672.574320967968,18465.93977853061,15123.0740003407,16401.953223276385,17509.31598177905,19228.19892146255,14599.539868168713,16192.551398587811,14129.882713144674,15395.87601647586,11853.583066311567,12273.885630367266,13296.879487675578,12962.17913948413,10178.141531948864,10101.748861881337,17833.95419276747,11290.360773903032,7050.797194092144,7109.831367133397,12879.727662239184,15849.231621819281,14036.330428384765,14600.701492135015,14377.532715491632,7705.7385359122845,8414.14109970378,12768.14503989922,11390.56673556146,10492.153643864705,15665.526881990423,13518.231074072748,9896.670696858979,8514.724851169687,10495.74229946015,14331.982881842356,7228.669024198985,6779.132502990354,8418.829006301234,16447.848686603495,15740.35987338571,11179.883037182273,8789.581276892988,11591.504961624405,6993.71096793164,8046.946588923506,10797.966046345515,10462.980330774792,8581.638814176174 +BA,31614.29255116213,25762.18251896169,12898.683737355397,30643.34571996033,20289.25506629573,16692.532556519098,20416.06449106326,23823.10383354778,16264.762900161431,21522.105898137404,23467.52324346034,27732.028396263388,21355.39127202247,21518.57483169428,38198.02048713121,26864.382517947488,20815.045478598513,30820.77172304343,26041.454718573805,32434.848569531026,20613.68138756547,29427.6067241259,33216.04695823398,35126.00882914745,35434.02869793576,33198.240125653894,27292.13451964922,28870.288475787063,34855.527471322755,40158.11721181478,26000.45986387781,30818.815452611776,25386.059210704487,29741.547122355205,28211.934365516674,30030.474291377286,28262.88980319508,36551.088477619196,29006.131913946814,27659.528119372964,23600.138376555304,18313.888493525537,16009.416242480263,24722.92263318226,19189.890721764787,24683.705818314953,20989.732351804592,20569.866983400992,18470.90664070533,14851.755901997987,25891.954823722892,19819.186826010166,18921.820235243023,20522.576037546467,27525.961934821684,30713.034955646464,21412.918614981576,21344.870107122344,26543.94285666588,19942.69654945001,23180.52553450498,25225.421682786062,17217.841128593398,25342.758536033023,22647.27040540609,20311.586220306715,13360.715771642963,18725.9052067595,21814.111731615874,31110.03238839381,11170.209355889527,11624.972537489217,20618.808518471225,26321.87815471064,18023.46871599901,20293.60245322545,15351.515268991054,23732.8659965382,19641.494693119246,14018.69083089969,18476.061736021245,20106.92588679312,25396.55419340511 +CH,71147.26157637448,54904.32201155619,50017.90208838156,60290.759721214985,73027.45831149221,73481.642346746,55618.537744757035,90032.09246974687,51962.38939916655,67177.84116696635,96134.70662377033,78280.50065735803,75567.82823680741,75624.52378636891,84437.3353706146,82858.22758683441,70824.92066589095,89311.09471805945,65693.73271567532,95736.9646979805,81823.38979168108,71941.93730231738,93291.72439376163,67130.87226350856,103459.16116112942,100678.84780651607,97724.23622167954,103707.47043615916,84031.35407618036,103162.60292359442,67550.72288370335,80436.85045155323,87045.62560332651,91431.67032188186,103676.61542793321,68303.04781353423,112322.8911282786,90003.61666202937,91028.65800738563,79435.56403729375,84362.27602442491,71967.17653868764,71356.17066607098,70327.74412176231,72852.24726422041,60501.17532436925,83372.98013161327,74234.0349385613,61890.14596593614,54336.52856303606,58271.018596959824,62644.46734396249,75790.31562737533,69637.43067630196,63290.99710001813,60360.96649160057,57476.7610131337,62343.013781750116,78693.52307555292,73667.98513148604,75122.7031133837,70327.33051388402,33043.59766466136,48968.55545142022,47632.62274536815,48588.59714178414,58398.342285916435,57742.38347363473,42559.51792407362,59408.23894223828,57129.80243604273,71163.63652517287,70858.4268509181,119263.66699527185,55000.17388464577,60563.73895679769,51249.64855691976,45607.547672961526,60542.786248766475,50488.945849740405,62587.04259357905,67091.5970044437,65549.52567888667 +CZ,21212.78579882691,10928.058379661825,3384.888399390222,4480.397678992209,6399.719467990146,6768.6515946008185,5799.446185009577,9411.786777037812,5860.23463242501,5599.396992120427,5741.811363153907,6430.8701452824125,6608.002211449021,5547.98412657507,11139.03676570244,9975.869136026628,10340.80877548634,13532.930674695574,7705.735677184478,7812.801872929193,10964.355351867012,10646.504003233118,9719.560436989883,9722.51782291833,19015.37334991238,15549.667939948402,15927.255735311868,12882.876953226223,10353.403919517015,11853.576269226234,10677.61771918624,10413.95103805089,6895.283030051313,9424.903567027312,12922.392855988994,9137.874616036986,17532.348544152504,18533.830228515635,15250.542039808313,10190.043701741004,11537.335951365127,9452.574932230946,5833.228549596612,5329.206957903766,7580.6976645678615,7069.4638232187235,11641.01844987317,9790.145937530902,7320.767578365769,5406.873869997462,5625.637231646826,7239.835546851702,6440.471526964078,10089.617439184036,12468.55796361433,12603.058166229213,11520.381274473184,9364.18293733304,10411.740148030329,8903.525346614548,9434.353552398077,14463.707947162726,8297.335864348554,6305.0428212307515,9383.102792968806,9420.905095490103,7053.530866655102,7934.504156979587,9131.766698685136,11027.709419784474,7973.011990884055,6406.065926850977,10728.184944007047,6645.433895571247,6345.82145823084,6499.675988954033,7016.463805946017,5619.135413529,4807.786670051716,5785.96568493957,7986.497102061061,9207.147123091028,7072.340654546769 +DE,60501.03103951161,38175.41955606091,20879.426305645527,28284.75340336476,36103.32351052005,34891.089702429555,28788.726755549767,47593.248184570766,29278.51011479424,29170.60074491641,37514.09293381361,41854.44001450301,38958.042582957896,35908.26729908446,54302.825387264325,53900.0627595872,49537.22949846474,58655.764340031456,37627.8257805545,42967.11131060519,58392.899587658314,47246.42956098116,36543.949785170116,36184.44504543948,76454.75505815547,77563.28089874369,65706.46393994696,62713.75591115003,50646.052126013274,74501.93068438585,33965.80961685558,36936.195615288314,42537.597915180464,56616.68921207296,56744.68927682596,34807.98202654087,56642.02192030585,72249.78534694383,61866.53633607989,55155.47864420242,60392.13262306467,54016.67652252674,53772.61604029787,44957.681101902934,45340.54136937088,48213.458592237475,66703.44582319073,60862.17019199549,41014.24992391146,32890.656129618095,33561.7114818598,35496.398391557115,43529.12222860253,55750.09930602895,59293.24549493131,37708.06634825865,37073.71374151417,42227.76427477898,55642.269571505705,50261.32889407123,50099.1653624443,63663.80803911536,33932.84222448403,24148.0930626651,39327.588161226195,34424.75266875371,37774.7468462978,39904.36386097259,38761.37664135111,43371.39725264248,35879.97041420226,37163.99533546333,50391.241894760955,37073.97568394232,36139.75677566728,42435.96482981362,34097.15586833773,36767.50341472353,28228.762854078665,31841.550922412007,39703.58319343355,47521.52513933251,37833.900158720804 +DK,200.778317198711,183.58783222570864,184.92589840547043,103.64850861603549,315.2220887719417,314.1000544312628,214.28103955721934,161.43191114338694,185.2111475627714,358.69279426367336,540.6494487174206,225.87222027671936,240.57818634617777,370.37587945377,297.48979685029366,176.69208006156848,208.79213770008658,418.4554011794129,292.8102234525168,354.1220188699609,405.97396851309696,497.6042583966885,394.062076725445,291.3295691524654,304.5438623304028,591.4756757289098,629.1912050409122,479.19182164984767,353.75286712188796,454.0799499391422,338.48620130918835,357.676218196066,271.5200039604648,288.04880490856954,389.1757124784286,200.03398963977796,391.555913715114,397.29527898061724,379.8043799580585,514.7861201159348,505.7304478209306,381.57816134966373,489.3522161731293,301.717309458533,340.1024114463131,377.00536197863613,349.05617800662674,489.4227950883326,223.23589869898433,269.17110101837187,288.12441629799764,229.5796362727797,293.635637901186,464.89056739838395,386.583686695923,100.62743648672041,155.50324274468716,357.89273417380645,451.04208007822723,403.3432275318107,376.8995908622044,395.3896113505339,169.30459202493293,211.16687292699712,238.87912856891634,225.9981737610454,469.5229598902774,334.5021223766927,213.88993390188736,267.6283833775911,319.04746406617295,376.09256801086406,317.617725512616,353.26516627601364,404.2285931109035,408.5235836651241,351.86517079981496,305.15203377590285,361.8170659996248,441.45504335438466,312.14518786073575,466.99320427604425,510.02659659134173 +ES,78876.635611407,38950.09623429436,33841.47292664868,23156.438140457663,24925.319205598968,36553.92702862067,59420.41145835762,44448.20001757085,23003.718514410986,25989.029770929596,49381.7181466273,42506.42487287232,29823.22966835847,33520.89863652133,42189.87541544434,45018.59980204108,27387.4917761516,45602.58407624375,62626.425244916936,94141.56249288519,66884.65469167147,67115.06386526441,82553.38984370838,62483.82642486853,54633.78478265801,97009.71651609142,47073.863176177474,55800.125131342014,85746.55555964066,72028.42027117872,75395.28981871007,97165.39237066667,52196.13272216457,55183.75674414718,44434.367388636274,45688.29479796517,107175.1885102772,376352.4882722023,122222.92956502433,46652.32256081546,42283.296882354574,45745.627884904505,49745.69531403085,62249.891346371536,58920.93920695715,48705.91089393512,49506.55303300167,60104.870297070986,41417.79510072781,40561.22111509541,48584.70074175896,41980.59062088254,40901.640882458836,43899.80095828514,42846.07384845135,68844.74333042726,58684.98840324564,44556.941393617584,38670.78308215774,46815.51322723987,68212.19494117319,35011.91030341564,50475.76713743041,37227.78564631605,21874.579431867896,35771.95151620915,29462.81813629621,28957.890173503936,32351.242924601538,48787.03990347552,31409.59113067243,24367.630996980257,54440.48961905899,50212.19464108009,33563.81874118821,47043.00929278407,21662.04001863739,49011.344970588914,40719.843457258816,40971.905822060144,45241.676643808205,43434.78481736922,37030.44475893774 +EE,539.9157561831089,506.40067622283726,641.2579701177458,634.8633672657788,801.3715228148297,966.9758840524717,584.81736437269,583.7023862826877,945.7850249371241,794.7615397417561,1013.5168183220601,680.8524541483096,896.074617741102,657.0814978199126,1138.8891299468455,1033.2360728791764,1360.240006093535,1004.6950457068739,934.8774758153143,610.9977141696028,1048.0576885162222,1477.5046721309996,819.8347754595931,595.9919701101757,664.1717649435486,1178.672290642306,1112.7122616720162,1003.3658496852601,739.8499843054013,970.7396668771637,1156.5986195943308,988.0643633892423,963.0153554345143,973.0118510683724,980.7669857762866,637.7376743732589,1121.0664931638019,1485.3090062847518,1014.4287893275732,701.3843644468006,1196.8127434491068,1136.1215677919786,956.0911286121622,761.6620263988196,1109.6559596693944,945.8137139982223,1246.4435124663337,1081.0063689141978,1180.9951778617858,1433.4526339800395,1044.4962572791317,875.9289554452553,699.3911738148247,770.5276589427534,923.6083617038047,353.16555295606884,572.4961222214871,770.5595680360855,811.3520528619258,480.6204379373417,526.2783934002991,624.0252970776874,317.7449195254128,502.6073570248072,523.2149143909173,201.10844695565802,516.5064948459781,787.1638506300568,929.6905631193786,943.6792182991617,682.831069893961,933.1072250631543,692.097322772721,449.72254117947216,392.4173074585239,635.9676582877272,753.2897252561945,692.2577760060705,496.359994444626,685.8431112730673,512.1207984775516,963.0464221974397,483.833486345915 +FI,19863.633124385666,19889.46363566243,43612.48513693398,40476.15110774358,37963.60387525601,30946.988617446677,26642.94999177761,35266.32524904611,44524.796955378566,33134.502072929165,37605.30609105331,44212.92045299994,43354.55443946037,40909.90249435943,45502.4817028443,31224.476747778986,41198.39417754888,37433.6293362709,28205.152814527217,22733.614552593714,36790.55908786393,45364.155643266684,28818.806516416316,35920.468538637644,43898.27049057533,41064.81684006838,48740.383821508905,37939.33952866352,30918.72594548001,32676.177851908644,33754.05667642144,33605.2810320407,40213.26757169686,46999.65997165162,40988.91471061698,26205.15827640759,41167.74001571865,25866.031354509407,34538.39918373158,28474.82496101674,52752.27216474974,31970.598763267328,35752.18054352296,34628.515223969094,27958.317625583102,31764.196982878522,30015.16030263079,26346.04561795855,37548.80632649389,27745.021972655202,27337.35846234453,42346.93155636462,32896.698992597754,22520.879762748657,23208.41547315833,19884.31515309925,22475.195958848508,33947.011695157635,26939.65172877202,32198.274008146243,28319.0878193112,25068.601753935876,16735.56947336933,29510.104024439464,31518.153863523567,22455.334677451585,28461.18834411878,38706.997170480194,29619.48059832548,29700.763598820195,30127.95453034573,45678.82538666528,31580.034602099753,29256.819253905658,43076.06538538077,49489.04536337738,37281.852766328535,33818.560580958125,35465.53242057822,41410.545080415,41567.72109759498,59630.270126901065,45592.22770628446 +FR,104970.07553291276,54987.520121202884,58127.609672438644,63952.96688103039,76761.15501948349,76267.11605975665,80986.06867218221,93733.93578796726,58479.255039973585,73543.6737690567,135094.49763612094,106772.95460342853,80280.31347296045,74490.3783289433,106687.24245156738,78827.6552216503,82482.11027901788,110101.24506868717,102231.57173723538,134019.59611286796,107848.78158188045,101612.59295931137,120079.53146371644,89568.66448178052,139585.30725052828,153772.55334552698,108799.90779570332,132530.25240249874,145056.24077647954,157344.40874499045,121182.68180087653,135378.15307040678,100408.75538533325,132164.7891142495,122382.6612084835,103706.50937621434,174240.52624537304,149853.10658224527,139992.58441391244,124892.14391178945,138893.07653615897,136102.17909683278,136298.85434619425,112484.75227834118,103842.75366698352,105453.40277549413,121935.76619549586,138379.45234918175,71924.60006455882,68830.14474115185,82603.77634528138,113556.04015089742,104293.46882473862,133822.28230897718,106263.7222156586,102481.34621013676,87080.48957235571,78895.08319488679,105735.9820525235,105626.7734987112,124313.3006359069,92144.11932119,73537.29646152578,78137.60525599915,58286.814348802,68928.05802270533,75743.7796112372,83489.37862547796,61518.93775410048,71311.23184506799,58810.65089438103,62581.66694545332,108566.1756738168,106810.3035898108,64981.51870529863,80829.27869961815,55203.39988738071,99034.47679069567,69318.43286028007,80169.78942387344,91015.86505778233,86376.11895764538,79293.98493428944 +GB,22702.364220315787,23680.52284249295,26272.032009932474,26333.09456007779,26845.290009259897,23656.475751452526,24568.79566354481,30136.97835561064,27079.44100895935,30643.318549445074,30949.55733300973,26701.9428167181,24834.423901258084,36292.29933386541,21223.79048684261,23695.358277919488,25987.57619398849,29907.138025215598,20532.262685247148,29689.355990879158,29755.7349738537,26456.609914217806,26827.642866860373,23873.145060634775,28779.074240844395,32368.78110647752,35977.394307138864,31071.326823875082,26446.212227329706,32888.07880400224,26015.735528737063,30161.596277105604,23017.874991984525,33287.290870143,28286.810808036254,25581.658649545065,33234.01349421005,31886.616851943854,36147.13303532815,34133.94123938026,36553.158784009356,34512.41082508442,31536.090754720717,28572.314934249887,33275.60304522956,33665.001595891976,29575.879486696827,34513.91395990196,28917.71257427291,33609.176553253485,26240.381135352633,32589.192149993025,28862.78621634025,32807.4074928576,28488.125666145854,20034.93309228305,23116.389736102017,36396.90134863421,35532.192401610075,39288.48780281492,29384.81519197965,36157.931892943554,21622.405196644995,32040.743170655453,30471.91526631006,28610.855281883465,33870.42864117695,37281.10394972126,33227.13302814586,22275.90424618414,30588.672790028984,34121.358436958675,27706.739428180073,37230.134388487466,33699.78058075289,31403.25713954576,26791.643973463473,25928.83232662774,30294.933954035565,36884.703709615125,29006.326905891798,39928.21741502616,32593.01729082114 +GR,21241.640655847503,17837.993739159116,8331.553303186349,18980.73391736116,15389.589824927982,17680.338927422024,17876.06808235439,10232.387409542045,7698.396804685536,9934.422230608423,10056.853784361187,12820.948661755581,12880.09713386794,18009.367077161973,21378.182658177288,29473.438101212807,11770.791493072751,17561.986308683798,14068.336209442465,21036.22984593777,10600.651816726047,19253.94027167335,33903.71393281602,18899.558983910043,17444.093386496537,23383.013428670623,15695.74724949063,19981.88173635776,22837.72155515553,20477.278624856677,21882.21250746782,25630.65513791745,23207.036995448034,22044.998521881807,12010.599831751206,19432.667576547075,10483.216379681078,17709.119022396855,23856.615736538963,24868.152661457774,21212.948012018598,19349.21918097175,12988.230031417628,16765.76278511076,15711.921661553248,14768.388537620414,15953.652684601051,12434.694106124754,8265.22849298033,8609.897588471382,14667.4570613014,8511.641075667938,10022.119539267658,13526.966234241496,13788.166042309897,20514.65575034389,13890.655920759986,13637.35506363307,17713.539092926785,10603.937587040999,9085.188935046803,13431.534902143163,18237.093734480102,15007.784707319466,15322.74478671021,15189.508916238075,9627.363919501071,7964.610286111404,17730.814440852053,21625.83796282357,10692.331430067703,11630.957871879938,16037.311332863352,13770.795305947142,17211.823293162783,14042.921372422215,9179.230226001768,15781.789228215457,11036.807907632012,8148.5700551254695,17837.056638784255,15741.120020191216,14783.113316616393 +HR,10616.868981781858,8773.16604903597,5244.73498702366,9536.576803956808,6559.078522391053,5970.043528122038,9472.615822894124,8274.401876717038,4545.145600490753,7872.286618923516,11579.119396857217,11616.785819262946,7841.411279590863,7071.274416413621,12992.083400898755,8164.444623202054,7347.788717816701,10332.483465428491,10537.238741811467,14479.677080073134,8479.661662510043,11787.072656273116,12862.758623825672,13371.003032039336,15990.668161905827,14470.61427957732,10644.752476691014,11929.91211438134,13611.162472968235,14159.968181810045,8748.9998436583,15752.17883640428,8576.387915317433,13121.48137750286,9754.915357083264,10574.934113880938,12339.192872828058,13526.82683401755,12407.125261525374,13314.467203516846,10589.407510915647,8240.264291214513,7438.667886688274,10422.72691638502,8167.94266416981,9179.047407118169,8517.079324039581,8574.526688740114,7000.526114186264,6044.501432950472,8424.638032244015,7640.079353180473,8493.38568955205,7673.466816227631,10113.96973112034,10475.583854629525,8161.447547783003,7730.598307694147,9688.392563588315,7721.732973546704,8547.91442119075,9110.630144082634,5654.409914846469,10449.908940883637,8544.776426500835,7703.363550389989,5356.181480736791,7888.76450496884,7981.496673656482,12159.302077747214,4232.3935344941665,4890.509308451722,11184.320641158047,12936.9950624162,6984.475921997467,9245.055929521772,6446.204647314787,9728.03403894923,7468.897556955247,6117.536838412799,7342.634549696792,8157.817278196762,11474.85293662869 +HU,1086.1958142470096,978.3249526234807,212.97414604675294,340.3983517473703,430.1881201465951,194.65656630284064,473.19850543225607,261.9192709197555,196.10367582160737,215.18183697898402,455.56009955160323,446.6314758325084,756.8984035642842,450.9800559529234,596.2398492658431,618.0772176598714,433.5306920564666,626.6699838105968,736.6623236995524,901.6628598550868,955.0588428000881,1010.9577650474141,1739.1969813800204,989.7527773708749,1794.409065735425,2141.779921355298,1587.224990709883,671.8419282109866,1725.8355118081338,2716.2211930211206,1024.7764676942138,1478.4297579371664,1174.856199808959,1380.70450266654,1412.5023358393119,740.4722294240396,2077.892875467242,1382.2122922975911,1644.3319455706533,1323.8387691522125,1268.4319727220777,1050.1561979992803,938.7640185853782,701.18673897032,1176.2218406698482,1296.5341770126697,1360.4975641937087,1113.61620590335,686.0888933448485,340.9577501900905,585.7771480398817,710.4671894364953,683.5190908209308,901.0768559915952,882.6855336512624,1696.8667744778322,1072.391017559335,1091.9628754375356,1986.255314199332,1224.1891103332646,723.3105004079888,525.4091579835733,484.84230756145246,965.526984284363,1182.1048527111184,1188.8833398485922,413.588170351592,480.2721461089437,695.3047160171476,1875.1966820116616,1424.9690036241302,335.4105482008909,1504.9089491398734,1485.372787096725,1238.0161031995012,1379.3214547239281,769.0933902263423,1164.4795232335282,401.1056623458921,586.967649321741,686.5594518266915,503.19975913371877,1084.6060135452235 +IE,2938.9562959168748,3198.9169680516616,3187.5912945813584,2803.8552573374072,3777.1449651405105,4362.104175198847,3412.9484028266015,4033.7677356343165,3724.1620931207913,4522.92029724601,4646.742323576806,3498.3840852321937,2544.6578209214726,5419.077105100732,3195.826410242899,2135.0862825425293,3896.6031468108818,5166.0575828547335,3059.5430902455864,4420.523688067632,3920.565970045664,2677.658691610785,3238.0778129090736,2814.899041865502,4169.640537659651,4975.659864222032,4131.237385306254,4051.6063579500055,3501.9810380506974,4162.222738923252,3277.97066925379,4149.907266073347,3535.126191101705,5127.397347805918,3672.8392481603883,3233.4968306810615,4670.955668853978,4602.662496185422,5486.794576286672,5974.860239294209,4958.279351735843,5539.220771177308,4814.939874910363,4704.080605250908,5214.372862088697,5579.052373684467,4424.669817520398,5645.170219782959,4099.107666436778,4291.534915722901,4394.7348113611615,4474.842169491055,4574.431496810677,5809.6920444413845,4586.044007664658,4500.049573188483,4158.002042556449,5864.151573833777,5389.317421868625,5602.682945402753,3910.7950042057882,5664.313605042361,3809.963053559503,4119.424688220842,4183.3641097691625,4756.243128847813,4885.19842669336,5839.576896771334,6529.030637616166,3851.468550158534,4739.247453475783,5116.873230654843,4346.868803644192,5780.6460718128965,5283.18966576195,5253.677788447396,4182.318532051922,4579.528423701424,5332.55258145869,6160.501534866154,5064.7000821427855,7011.136828867076,6289.684272273017 +IT,111872.14392769105,83456.12455924545,65177.42783168641,92174.45776985734,93705.54545517343,102552.6760192628,102231.02170173851,123449.91092719955,75535.87312511557,87009.71778444933,172598.9057049173,100312.33974168803,109683.21050744873,113141.95504995789,104153.60992530867,105687.75931391625,108887.88674499927,120408.08444781008,120463.4718424679,176044.98820314519,110983.47718210719,108661.3888675,154479.99952596257,116866.21274767391,140970.07450678368,148795.1431459142,123467.91624840492,141856.2012294592,135145.74559391223,121025.70232844367,123064.2692081519,158675.8479818625,126408.22188494769,122698.61897984576,134048.90222163082,141351.40587318933,183551.69201916258,152672.0987165877,152463.24070715246,129214.69623803807,126406.52003570941,111266.52387106014,105493.22493839792,124930.0152276459,118811.00097800085,107475.13484215035,108705.61617459086,105553.12911266208,89696.47047566871,79022.57929325203,102862.21537887226,110384.19134436303,114736.91039530469,100806.28542965792,84803.88252804938,120635.19844583895,89284.70639754581,91327.36842742827,112272.49254052607,121214.98394688763,100240.69732658492,110327.24980482439,67667.3134977533,93496.05161894935,74054.55044130566,77775.69469931335,75858.44303177306,92083.61659880447,94760.12813659209,130298.81027721112,113068.08204604911,102862.27823880903,124544.42911673438,173919.9577739064,87247.90399947706,91232.2769509342,68511.40136893332,110593.38607511377,103785.63569256017,87869.12433673623,92697.61009264145,89877.21983741673,96543.33467044581 +LT,2330.311115607803,1278.321859711663,1329.382406669865,1835.9539018834093,1806.4585215317375,2463.9928727279507,1216.0039899784208,1896.293414052239,1974.9185999663864,2624.3584436168967,3126.90226977831,1475.6787373817235,2475.307120672793,1105.461669987713,2895.355169108127,2328.291848466701,2773.100951693534,3565.1300060634676,1726.340017569786,2441.2869150017605,2739.255286641479,3393.627534013301,1948.972938917477,1503.9304931932238,2081.2181025571476,2387.4356286402945,2953.7202011167815,2442.643404228762,1575.9037853337413,3106.077653607497,2438.6998492607095,2321.3335398002305,2455.4955733417105,2703.979150849733,2983.428649152806,1271.81865757996,2291.2165997279003,3624.3054978962264,3066.52482874976,2692.4730181815085,3077.131323187848,2583.193918114293,2346.227785803459,1679.5438811966314,3224.9829735377853,3118.546035682447,2841.2519919875017,2793.689370450914,2688.2457239306805,3241.443663108373,2559.3234295762136,1702.002348908642,2110.46892607847,2728.2093372090403,2507.383271401867,987.8894968242066,1210.6320667482842,2619.0625969612056,2041.7494156189375,1077.1024719580128,1501.0630179433206,2093.0805484121715,761.1714789679556,1438.6161577229564,2052.75406588365,780.7629955514127,1806.053023318598,1637.6952437203324,1294.75789506843,2045.7605537026564,2014.9263059368886,1513.2399919084748,1700.3251444304037,1310.6134461272318,707.068706016363,991.8607300754669,2210.5243412620116,1945.761381971759,656.9514438734058,938.7049363615082,1091.9224609932446,2359.271808740987,1316.3428075862207 +LU,410.92374814105005,160.31307322354917,118.4486719933025,98.1780404815946,219.99495836090017,162.18791666671726,138.32051761008012,209.31021249802274,188.8584966582342,199.41682878475427,418.42920407960173,402.65326898169104,245.66041042705334,140.5213247873591,281.65083355306945,239.8578158452654,369.22101543741394,483.78479198242695,296.9130979040409,276.1232951910135,459.8791399297912,360.88050800564,165.48000564979304,183.08661927563494,549.4327262552889,615.540914852196,430.5724249074097,464.9649192455573,366.43220700786026,562.8555247965114,228.93628708423907,211.2546971696525,190.68337965968735,337.11947715404034,376.86900759463407,153.06162250371963,361.9412034686643,457.17182659872975,474.4467062976349,501.35146460886807,586.4359860050876,446.87720467222556,554.4763793156474,495.34599197145104,293.22338952418016,311.9404169698979,470.26963100793296,539.1966800252237,318.1508533879876,216.80440341571304,213.96493869659722,161.79868975175182,244.05142665329072,449.452274496719,514.0163752203341,140.3179752581265,173.96942733863747,312.73695003201067,389.83220575942556,401.09422881834865,533.6829497064967,363.9324325652479,243.9448809708681,141.83825708815394,174.8785415794147,180.93947242990794,337.92060394534246,342.3576188750888,243.21751195509597,234.05807708972188,220.32797632404777,264.38928306703747,336.6463620917912,349.32621250528973,289.85643977541105,421.5786735040934,195.16848080033785,348.6723038250213,181.01976524286118,391.4073725411393,335.53788814460387,454.30136063817054,354.9932023222274 +LV,2075.0062187312337,1183.1651412244635,1388.2608755110323,1633.9975845005233,2100.728221746779,2307.307714455485,1183.142585833944,1669.1622848941527,2049.0129879285278,2215.5671267410553,2742.6556866506367,1837.8325027812643,2554.170761349389,1408.345733539928,2983.189997195677,2825.061612760662,3252.3974243255384,2886.2924715658505,1956.4363533791625,2047.5738516633846,2396.823663944175,4066.8157610189646,1865.1937720377932,1213.3814003625498,1799.0008428733133,2700.1570058485836,2685.678969351212,2489.884608424664,1643.1417843905015,2409.13500668555,2592.9272177648704,2235.207139152776,2147.227486416904,2582.289866216919,2592.1022950383003,1400.2389662856958,2360.0229699498527,4017.8529783072768,2384.614549536931,2229.7220033855633,3208.439621353169,2678.7332051326716,2668.5315414635693,1705.3124319563372,2816.1467857724074,2779.7212753206704,2548.8356765576805,2583.5815153824487,2861.3233286998366,3801.9993997175525,2885.329135114707,2265.350140707051,1837.2956559244064,2087.5337557102102,2249.8356476827344,853.5386928200795,1689.684828383291,2653.3751344813045,2109.0096432617606,1182.3316650686795,1487.9132295244858,1974.1178903388873,1027.3242775723352,1736.361793878124,1741.9204323497202,701.3946960765046,1526.0106468283361,1844.9956663852768,1722.690767934754,2194.735679264339,1757.0892689497684,1974.9007736328324,1883.6056453393867,1405.6090440523008,1355.4439688992024,1295.7921755717964,2182.9434502570357,1620.95881111662,955.2966396067089,1490.1655775988,1270.5915407733335,2073.003327028273,1565.9994997763404 +MK,6885.807602475421,5074.413420314535,2741.8766807152024,6785.078522769966,3818.8527078184798,3928.4886922987157,5350.383608273902,4779.5936944428995,3468.062322874052,3554.9350756385556,3934.258904454459,3692.0813330320566,3668.815892166788,5481.091007849558,8488.277349663611,8514.814821434962,4861.071723840239,6878.625964986481,6399.572820343104,7510.160197503697,3410.068805763449,5394.1653784487335,11852.098687247973,6238.562291909563,5957.282159254423,7239.168545674971,6704.994620967638,5343.254672711665,7690.122171456297,7543.1707758996035,6080.923842798452,9518.22452251825,7931.36999814296,7898.373553315725,5296.06496225987,7158.993856907015,5568.700579027411,6653.618095140364,7658.60790313609,7384.3372015299765,6359.355811805509,6311.4116310067075,4303.248848133382,4384.047563174607,4091.082807237865,4939.915122052565,4226.085259691547,2768.0039025432975,3428.9467644601264,2294.222990992098,4834.495252793617,3325.6396521134557,2522.690466358069,2976.927612194815,4721.490759581051,6218.919122814915,3840.4729075548557,4211.680380445357,5623.802967061423,3683.311545054556,3010.5387111938044,4030.600677147787,3746.016920616422,4369.907262961726,4375.170573617275,4171.022704527618,2702.082556773276,2500.5709190188645,4370.4076446296785,5204.859735574909,2501.3689966568136,2522.4142074268602,3898.568577966785,4120.496629723428,4145.529030725163,3980.5145191045517,2967.8383253548755,4325.530795978238,2351.320803369623,2869.298937488066,4644.825806471018,4443.426947798344,4862.542134317402 +ME,17887.124634490927,10608.377394539566,7624.148328862119,18300.25523347599,11276.651201832965,10903.50785537606,13234.193237094172,12631.716364532,11223.474429487562,12340.195715253074,11787.036249138713,18552.496612764233,11097.228684668844,11567.930061084586,19293.29710814638,13959.20571478613,13046.18440612437,18177.491235848003,15681.709335959564,19349.950981118494,11658.5954682407,15979.557715971854,21966.784229466284,16319.44299708603,17409.40677448169,19267.118980997075,14169.834731486397,15882.152400499632,19649.60512617265,23317.326436161944,15993.83236649745,16724.197023812518,13680.494674103275,16947.38155713745,13396.216553276576,17144.464963358845,16187.204710073258,20417.876685607593,22530.120155126962,16197.908505488407,14818.545420474018,12719.274460270883,9622.464989039141,13369.875886578782,13078.849292203078,14951.85122042927,13681.691957367619,12435.207850184568,11885.89235643587,9516.042262408026,16926.063160570764,13462.909968102742,10042.999218445517,11916.714437943356,15158.632522247093,19735.53511234594,11491.695345503264,14075.890065382568,13952.132515246369,11677.32833931845,13022.018989752623,13358.031703205903,11534.177624564669,17635.48411958614,14124.491791464301,12392.738752899031,9187.905148236658,11106.432128782126,13780.482580236776,19889.70854314474,7004.765863876614,8204.168680103983,13925.208337027952,12712.182323875111,8528.030231315688,13924.890575378206,9037.809310147335,13972.095665379566,11360.358971424077,10280.43536084397,13775.545442858487,18675.41168703515,16242.925847180693 +NL,99.18845393334344,83.88743307052296,56.20087850777987,37.585642699707755,99.89955066870836,85.24103376999277,67.24342284849837,62.39508342046794,36.26442939184667,68.54685542245758,132.53876435280281,105.25304624029256,97.45390390948565,59.629996943856206,126.17294913858377,100.92785922135535,110.87608266899032,166.47617616014315,115.03831975395074,102.21679880589629,222.71184206736731,164.32395798051633,88.95057195947412,70.61286255591416,116.64203846425596,229.2598570422647,176.71083656110923,163.34614915846544,135.23541074052787,153.03725726999411,84.2996330000842,75.50229060079856,87.79575328623356,149.0911400069578,185.89892961221338,65.86854604814957,122.15247506918442,163.86971747802477,177.38160465294413,173.97671792234624,210.94537197363266,138.15528852664815,157.7989701791954,164.8431327190436,156.27033317337316,144.7881412408737,172.55396177597567,195.57239229094031,113.32208112175368,57.91841778157319,69.80575559844598,81.95247611107445,154.25504072397393,213.16593963287744,185.6861094126344,50.88580789479815,88.6770750590963,180.59511129061775,175.09641999581325,134.73866646771805,175.89672487625361,170.10222446753016,112.93557838603432,69.46018341018433,89.82211025011819,57.645723008783136,122.86182387892966,128.20825436811367,82.72980960226074,90.07937846739043,113.22245968360778,109.86527486394354,113.13774281842522,111.87536788688416,113.53271254663122,140.01537175074324,68.64291161119651,101.90820271032081,52.313311323047174,116.8375292031251,120.98114114085548,164.29761287763637,131.20083352074832 +NO,210079.934684001,272449.26769557595,393598.97632244934,344434.1421584134,309228.23588460323,302048.4910019859,239994.31574717446,322040.9441520717,407801.21594778565,321823.44753004133,268338.23623559956,311516.6976002237,354741.82081862347,287750.3093395867,277336.7794878445,277384.3177020413,343804.7636848019,309909.39898200217,279870.8316011512,240316.6988310159,337135.04130569333,320967.163231472,302346.276731951,373063.16157364036,335043.0981929385,271478.1367425455,378240.8226290755,318135.4534804216,235625.6466770364,244547.82624561962,342177.033729037,330660.24479289196,373161.4848287328,318697.1789732917,345399.49658985186,314419.8189439592,230963.73709983748,236070.00307120252,312676.53469423676,195102.01076090848,231756.2941107393,196457.66930311252,255890.52889680286,207980.18388759278,250218.19793663023,221472.83820330602,212315.28230042476,222774.69138098884,210372.25250462766,210846.3448041017,177438.35447152023,214108.95671057343,190417.02324135366,175558.31404488848,199041.30532793878,154342.13931409398,175902.47007757265,215120.2640019617,216733.8944940455,261370.58822336013,212333.63219332727,174324.40313248086,166539.1770850326,202012.88317391058,238213.58919108333,170401.06338583003,217109.81457913358,185684.48673203168,210764.408869451,180452.94255978477,359959.68381729786,220133.80814962948,201815.91045998363,193256.2376798832,225141.35101977925,194502.14845672756,241700.45583039062,203049.47691663646,189440.21996991744,241270.48318453485,196628.83730256284,369452.758534526,226746.71170530186 +PL,19040.141287526196,13600.003649707409,4232.940272903036,6263.550300160282,11725.980915175824,9423.536450722735,7520.9931031649085,15128.087437533712,12302.274212909391,11903.809643162125,10323.210329129464,10102.880830361863,15243.556644277647,6316.576710839603,13844.440254769646,15125.266765937784,15697.445163802722,20547.692524530372,11483.751822471613,12736.801698643669,14242.313560202334,19975.533453959804,14197.61841088385,13385.258603233342,17555.946503015533,19526.389852009346,24990.22970093532,18554.95543612019,10610.557656768206,19356.459381427685,19657.930603206125,18732.50311338716,16842.606570419066,21220.5523273715,24157.44207211756,15607.0096942104,21677.41127186343,21298.26291533998,22732.35472759213,23096.919661671975,20539.587419825057,15690.593097829358,10514.527177352287,9757.003902443616,18214.127020951153,14743.470132504332,14160.372458977477,15574.81487531224,12340.373515759937,8851.92371521615,10791.411372967183,10330.247763133175,10795.54750377256,14738.227630388099,14374.438386354948,12177.648415014886,14450.3889852054,16473.394758962142,14491.781691174727,11650.64866730713,13724.64695911459,14468.081620316902,7425.533290488975,8039.550610683221,9468.54351850099,6656.34004885665,7842.310345436549,9593.638690519654,8828.256800239144,15874.058827778785,13537.338641985261,6174.396712827303,9509.500411581042,9436.102173346171,5360.954908688417,6309.399306468634,12402.024613286878,10602.512257049677,4725.103685514244,6963.3130148445025,9124.964758601689,11007.49968811077,9338.109838427506 +PT,17389.910347609384,7956.13238827081,8339.728858321132,2075.556471824434,3081.9400195534536,5428.965709165979,13519.093138173732,8266.183051247071,2305.611210847845,4751.414112923152,8372.129135066036,5969.31083523099,2397.6586063764958,3916.9962424030286,9654.699566273128,9603.363148222781,4163.162870337118,9179.465624121007,12131.854156488425,23406.646477036124,10635.077955993413,11029.404714084018,16475.917880350513,12087.55769685171,9804.492049893286,26178.184180984652,5669.820254013018,7559.528320921835,15405.930172416956,11163.387795923936,7088.025310785357,10191.330496756716,7128.069257230898,9335.631563569985,5236.13128329125,4572.251664471752,32605.577182903042,149323.86523586328,34294.81803755196,6061.11721308257,5836.654497517657,4843.7020037722705,7814.782411245904,9395.759000250582,14057.157961109715,8192.288977642056,7655.760207241933,9203.645337709624,7637.7450966202805,7971.812432879156,7421.37678917759,2935.2871895485287,6329.939163930326,8820.796560748415,8944.109217212255,14719.27363438586,11050.779819799696,8379.75073967695,5590.525909815882,10485.131539563748,20476.028147427794,7715.162648805314,11939.81827695821,5116.2596877306005,3047.0903835389504,9273.489011971804,5135.313604526994,3331.418010762715,6338.048693933388,12105.616460835923,7097.468638389797,3348.213951094401,11773.920694867731,13465.586888738457,4379.602415677836,11394.463621230614,3104.8789319036796,7216.150544702967,6653.765864361187,5720.580737490315,6685.493238874142,8486.079863634486,8329.192253601708 +RO,46545.50823036229,35517.718755954746,12007.97895282227,19448.903832688356,20440.973051620913,15132.394486734484,21523.767710605425,32075.68337603852,20312.088233477134,14653.654680967496,19346.344374357534,19295.50358149612,27702.617554877004,24644.67023787785,52797.882559506776,42262.7162454671,34689.01143849651,42583.74114324521,28973.147767939397,36882.64868179707,29063.471368254675,39575.626278602576,31898.858414072816,36283.98261870408,42207.50410750205,41714.957670180156,43270.313090823794,40474.54716426176,53565.91349208634,74865.02611452111,48190.11154819992,57257.26135564704,46523.80416861758,44300.83791323246,54901.1701096736,47361.27151969814,49156.09266449866,56461.30009557872,56062.45724028393,58506.511677323855,48499.732173446595,45901.64074770707,33171.12855766741,38310.49272614435,39377.41586450999,28638.803870927226,29424.553978129992,39429.14347226504,39300.73151290347,27525.04968129815,47095.77682827757,30948.90232192865,32939.14262154816,30155.99148400138,35067.04977301419,35592.25066656211,45790.67404045973,42596.77718301701,39223.35618808953,25767.93476452563,30963.38609617001,30034.908201595936,23323.05819720473,28517.276888551194,41560.85308154171,43999.15897330077,21427.19650317167,25084.131072037453,18450.764512377853,38182.39266803458,20422.517191285966,14090.243196787245,21998.55223596247,30809.187151501046,22071.90474198888,31906.454754357772,20763.073093214778,25620.747974742615,19248.368008063957,23289.011422937554,26669.846131314298,27207.74766143675,29386.08741874402 +RS,12898.821957973714,11760.375115749226,5762.823681912337,10868.645457667955,6851.647476795101,6489.091511565737,8016.427124526303,11096.059611708006,8784.092785314235,6844.044739629848,5968.673897869134,7450.873145908507,8457.218084424714,10466.134979346216,18700.932768467817,18783.264457747777,9647.157790116991,14650.396388121844,12360.14810912279,11640.673528541236,8882.446980807292,14762.619600006037,18399.930168952076,13646.806400326906,14489.119148714197,14104.804002759012,15462.34970923992,10894.228431882033,15095.088711819322,17853.281396922546,12916.46431873845,14207.379133135786,14418.834370720482,12752.5957180177,15544.588217112372,15820.904121022999,13534.055257847373,15215.146639151637,12996.626380040323,13029.919161637963,10196.668003968522,10284.440766030819,7022.693160251435,8401.249663323453,8435.803252725058,10265.915943082338,8623.546341166757,7782.429841191159,9309.259412625106,4849.32865233776,9480.40891035497,8237.330612702019,6688.9341497267815,7113.796951355988,8945.392918392941,11391.406447517316,8770.78174795334,7797.074404297926,11205.567652241964,7490.638744688466,6890.626375097134,8721.152535625733,6986.899718851523,10014.515393386338,11863.685949406314,12576.12226693591,6930.903954576986,6933.68818306879,8436.351253425808,11680.836931112251,5673.257881932308,4512.930178739657,6094.8735580904795,11616.485592765608,8423.704814584986,9582.260510301834,6280.960312130538,10196.683253538626,5869.428152205924,6637.126459584064,8223.324863109141,9163.49600405833,11744.973584261521 +SK,10526.703178382486,6581.841291454129,2779.6437301689157,6043.293021386589,8068.711762338472,4716.572547513843,4263.788112757618,7436.446538154413,5733.7942336519345,5091.94458281141,6885.47211985414,6956.591212284293,7116.928783228905,4573.269245439668,8169.130903254093,6799.092645889461,7190.199390340817,8819.311158887818,6679.080394471699,8681.76846617681,6714.688996801623,8780.135433744465,9674.052829336924,7510.89080672348,12315.672504913706,11551.288938768861,10658.095118642217,7760.467099195778,7334.701885838525,11743.053621084162,9101.455526104724,11252.254293590808,7089.2297957961755,11692.575497480175,11870.620362608648,8320.411050776946,12664.612697391287,10840.053026355938,9544.145158945727,8285.851845920657,6554.955003499832,6014.385824757616,5119.229272436076,5566.197178944401,8283.751441606055,4576.739002618681,5529.727054286627,4884.285979430572,7030.767074231632,6380.185010419688,6092.06334940043,4789.6919845964085,3988.728835990378,6100.445127127096,6174.336930810738,5839.492530664778,6739.897695678873,6073.547495791424,6239.663814901599,5985.626769812626,5946.910319392802,5350.4706690989715,2897.742723724252,3812.447551889599,5110.734824948982,5466.7571969447445,3822.1224333717755,4189.745228198809,3608.9397299109723,8925.718578619328,5520.297117401385,2338.023634704523,3634.014208205775,5079.021357670912,3789.3939110245783,3599.858750509022,4222.707040620564,3096.1701009538024,2158.8092391216674,4542.203594136759,4220.210061470592,2961.7796555712353,3705.0055429796116 +SI,8932.252857660058,6769.672897729603,3971.443731895907,6727.0196008878875,5996.060296331706,4552.96378417224,7787.375795346372,9548.071392837826,4890.204133819321,7094.028640574649,11752.798116380785,9378.602450871665,7169.30972105447,8221.267552376507,10568.142173580174,7705.119699907013,8559.440940655051,9496.2682906945,10641.418485889739,13644.09405840664,8756.865265119286,10877.994032024846,13095.473005855994,10408.222250010325,17110.767148034232,13257.44359305617,10163.420442559087,10743.809603872312,11213.570708968457,12419.028940460184,8518.188189494229,14975.496301661744,10217.449212514946,10521.007791805137,10759.209828867228,9699.803414833696,14530.647692616923,14530.715084460895,12439.143395173185,11990.046930204517,9001.647305603035,10111.423546501868,6824.172499114327,10267.968760960974,10233.709492652128,9562.175707725224,11231.941186997657,8178.692540046128,8568.526412713521,8103.883097000008,9639.895318751553,9157.43571368136,6814.50158997294,8089.913064615838,8170.645053083449,10765.044719853075,6713.170108103339,8936.8362631332,9542.147586182518,8964.110093884974,8653.114721452737,8353.75428643612,4558.589088593759,9432.405903987477,6927.92152111369,7408.760392367348,5834.871486466167,9336.912851251047,8839.494837985663,10766.693939731143,5073.937522450624,6475.598951785893,9482.419717110955,13414.771212079502,5906.5584945059145,9942.151265372298,7696.092255607837,9521.835825354157,8476.124990692872,6361.010018809483,7504.908031281684,6349.444363482254,12494.86342976942 +SE,97729.33612275522,104893.13349064675,152164.30605691054,147567.81837152236,172633.569885874,142454.06079467706,109264.12507808255,145966.80578917114,158733.59492028368,161670.6171803483,134822.12256461562,136958.6213484757,175679.6273876132,133962.36617697845,126787.36233921513,130861.49290945902,151133.2982760823,140247.52694114187,130508.52271890236,137421.63579450184,164132.0529341604,142467.57286064525,135886.87305352974,163762.3962091317,161128.38161511483,148196.28633931337,167892.87677861055,132017.696130452,105953.99289036485,119407.22923207263,147139.6039546916,151309.55114963037,164893.61323375857,137608.18237925606,149284.78771947857,108749.15747050248,131859.531763871,117290.48017785426,131751.97960784068,111117.27409251402,110551.615114603,81550.1135393761,114677.940027603,102356.46697333359,128977.80283219383,94483.98267503879,114937.96457142044,93256.91327642264,96751.29026217168,91074.34139788701,87931.96567208324,96560.83822983531,116746.94389793588,64626.25905820224,75156.91767736348,51489.37512699482,74729.26978432719,134673.01513808029,110440.65771030058,149033.9827088587,143576.83069821307,93040.02354987273,64075.160200006496,102493.08906248632,106664.82884715112,90351.43771324471,94801.81222609026,92445.93458012305,88919.20770998915,108111.72872590217,127440.80298482065,124444.06618883039,98961.91573013023,87913.90602563386,115956.48217115598,95526.84265190935,103459.08985036932,86058.90377748368,99040.9103276256,110493.22773914765,94182.7249029169,169752.66741900297,99896.09236620825 From cbeb9834ac441ae8d54ba6e62f3f12804af7b031 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 14:08:58 +0100 Subject: [PATCH 444/591] update hydro capacity and generation data --- data/eia_hydro_annual_capacity.csv | 103 +++++++++++++------------- data/eia_hydro_annual_generation.csv | 106 +++++++++++++-------------- rules/build_electricity.smk | 1 + scripts/build_hydro_profile.py | 11 ++- 4 files changed, 114 insertions(+), 107 deletions(-) diff --git a/data/eia_hydro_annual_capacity.csv b/data/eia_hydro_annual_capacity.csv index e14697bc..8092096d 100644 --- a/data/eia_hydro_annual_capacity.csv +++ b/data/eia_hydro_annual_capacity.csv @@ -1,50 +1,53 @@ -# https://www.eia.gov/international/data/world/electricity/electricity-generation?pd=2&p=00000000000000000000008&u=1&f=A&v=mapbubble&a=-&i=none&vo=value&t=R&g=000000000000002&l=73-1028i008017kg6368g80a4k000e0ag00gg0004g8g0ho00g000400008&s=315532800000&e=1577836800000&ev=false& -Report generated on: 07-21-2022 16:15:18 -"API","","1980","1981","1982","1983","1984","1985","1986","1987","1988","1989","1990","1991","1992","1993","1994","1995","1996","1997","1998","1999","2000","2001","2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012","2013","2014","2015","2016","2017","2018","2019","2020" -"","hydroelectricity installed capacity (million kW)","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","" -"INTL.33-7-EURO-MK.A"," Europe","136.143","137.425","141.734","143.763","142.894","144.738","147.631","150.428","153.428","153.345","139.346","134.524","137.463","138.338","139.688","141.47","142.121","143.595","143.957","146.4204","147.3512","147.736","152.173","152.938","150.4894","151.424","152.276","154.198","155.405","156.988","159.495","162.112","165.452","170.146","171.588","174.906","176.998","178.221","180.846","181.68","184.909" -"INTL.33-7-ALB-MK.A"," Albania","0.5","0.525","0.55","0.6","0.625","0.65","0.675","0.68","0.69","0.69","1.668","1.668","1.668","1.668","1.668","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.432","1.432","1.432","1.45","1.45","1.461","1.508","1.628","1.781","1.725","1.798","1.913","2.047","2.105","2.193","2.39" -"INTL.33-7-AUT-MK.A"," Austria","8.206","9.157","9.51","9.582","10.034","10.171","10.423","10.691","10.762","10.858","7.028","7.129","7.204","7.202","7.245","7.323","7.385","7.54","7.685","7.669","7.676","7.703","7.567","7.607","7.613","7.667","7.684","7.845","7.848","7.827","7.913","7.947","7.97","8.272","8.321","8.457","8.493","8.506","8.591","8.63","9.001" -"INTL.33-7-BEL-MK.A"," Belgium","0.073","0.08","0.086","0.086","0.086","0.087","0.089","0.09","0.093","0.095","0.094","0.094","0.094","0.095","0.095","0.096","0.096","0.096","0.097","0.103","0.103","0.111","0.111","0.11","0.115","0.105","0.107","0.11","0.111","0.11","0.118","0.119","0.12","0.119","0.121","0.112","0.115","0.107","0.108","0.108","0.12" -"INTL.33-7-BIH-MK.A"," Bosnia and Herzegovina","--","--","--","--","--","--","--","--","--","--","--","--","1.2","1.2","1.139","1.219","1.219","1.219","1.624","1.983","1.983","1.993","2.38","2.38","2.38","2.38","2.411","2.411","2.117","2.117","2.117","2.117","2.12","2.12","2.049","2.055","2.084","2.084","2.09","2.09","2.093" -"INTL.33-7-BGR-MK.A"," Bulgaria","1.895","1.895","1.895","1.975","1.975","1.975","1.975","1.975","1.975","1.973","1.973","1.401","1.401","1.401","1.401","1.401","1.401","1.803","1.803","1.803","1.881","1.706","1.948","1.984","1.984","1.984","1.984","2.012","2.12","2.137","2.184","2.035","2.095","2.165","2.19","2.206","2.206","2.21","2.359","2.366","1.725" -"INTL.33-7-HRV-MK.A"," Croatia","--","--","--","--","--","--","--","--","--","--","--","--","1.769","1.77","1.77","1.781","1.785","1.785","1.785","1.785","1.785","1.785","1.775","1.783","1.79","1.804","1.804","1.782","1.782","1.799","1.848","1.848","1.848","1.897","1.9","1.915","1.912","1.912","1.913","1.913","1.848" -"INTL.33-7-CYP-MK.A"," Cyprus","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" -"INTL.33-7-CZE-MK.A"," Czech Republic","--","--","--","--","--","--","--","--","--","--","--","--","--","0.911","0.906","0.908","0.868","0.905","0.888","1.008","0.952","1","1","1.004","1.015","1.02","1.016","1.024","1.029","1.037","1.049","1.05","1.065","1.08","1.08","1.088","1.09","1.093","1.094","1.096","1.097" -"INTL.33-7-DNK-MK.A"," Denmark","0.008","0.008","0.01","0.009","0.009","0.009","0.009","0.009","0.009","0.011","0.01","0.01","0.01","0.01","0.008","0.01","0.01","0.01","0.011","0.011","0.01","0.011","0.011","0.011","0.011","0.011","0.009","0.009","0.009","0.009","0.009","0.009","0.009","0.009","0.009","0.007","0.009","0.009","0.009","0.009","0.009" -"INTL.33-7-EST-MK.A"," Estonia","--","--","--","--","--","--","--","--","--","--","--","--","0.001","0.001","0.001","0.001","0.001","0.001","0.001","0.0012","0.0012","0.003","0.003","0.004","0.004","0.005","0.005","0.005","0.005","0.007","0.006","0.005","0.008","0.008","0.005","0.006","0.006","0.007","0.007","0.007","0.008" -"INTL.33-7-FRO-MK.A"," Faroe Islands","0.018","0.018","0.018","0.018","0.018","0.018","0.018","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.0314","0.032","0.032","0.032","0.032","0.0314","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.039","0.039","0.04","0.04","0.04","0.04","0.04","0.04","0.039" -"INTL.33-7-FIN-MK.A"," Finland","2.42","2.467","2.474","2.503","2.497","2.505","2.555","2.586","2.597","2.586","2.621","2.648","2.679","2.731","2.736","2.777","2.785","2.861","2.881","2.881","2.882","2.926","2.964","2.966","2.999","3.035","3.062","3.102","3.122","3.145","3.155","3.196","3.196","3.224","3.248","3.249","3.249","3.272","3.287","3.287","3.263" -"INTL.33-7-CSK-MK.A"," Former Czechoslovakia","2.578","2.832","2.84","2.84","2.875","2.897","2.89","2.975","2.988","3.042","3.036","3.061","3.061","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" -"INTL.33-7-SCG-MK.A"," Former Serbia and Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","2.25","2.25","2.25","2.25","2.25","2.25","2.25","2.296","2.296","2.296","2.296","2.296","2.206","2.206","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" -"INTL.33-7-YUG-MK.A"," Former Yugoslavia","6.2","6.25","5.886","5.886","6.386","6.736","7.086","7.386","7.625","7.686","7.386","7.386","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" -"INTL.33-7-FRA-MK.A"," France","17.431","17.63","18.247","18.4","18.661","19.034","19.786","19.991","20.174","20.338","17.717","17.655","17.767","17.837","17.902","17.898","18","18.018","18.024","17.947","17.646","17.674","17.775","17.927","17.812","17.808","17.82","17.832","17.922","18.009","18.156","18.373","18.388","18.379","18.392","18.415","18.486","18.561","18.857","18.88","19.671" -"INTL.33-7-DEU-MK.A"," Germany","--","--","--","--","--","--","--","--","--","--","--","3.31","3.317","3.385","3.471","3.624","3.563","3.569","3.642","3.802","4.086","4.101","4.193","4.088","4.209","4.134","4.117","4.083","4.104","4.283","4.252","4.469","4.451","4.433","4.424","4.433","4.442","4.449","4.456","4.456","4.658" -"INTL.33-7-DDR-MK.A"," Germany, East","1.852","1.845","1.852","1.851","1.845","1.844","1.844","1.844","1.844","1.844","1.844","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" -"INTL.33-7-DEUW-MK.A"," Germany, West","6.45","6.509","6.531","6.631","6.668","6.71","6.71","6.71","6.85","6.86","6.86","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" -"INTL.33-7-GIB-MK.A"," Gibraltar","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" -"INTL.33-7-GRC-MK.A"," Greece","1.415","1.714","1.714","1.714","1.714","1.822","1.822","1.822","1.836","1.986","2.093","2.197","2.208","2.208","2.208","2.208","2.207","2.412","2.241","2.344","2.373","2.377","2.379","2.38","2.4","2.407","2.435","2.451","2.477","2.502","2.516","2.525","2.537","2.539","2.69","2.693","2.693","2.693","2.71","2.71","2.697" -"INTL.33-7-HUN-MK.A"," Hungary","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.054","0.049","0.049","0.049","0.049","0.051","0.053","0.053","0.055","0.056","0.057","0.057","0.057","0.057","0.057","0.057","0.057","0.056" -"INTL.33-7-ISL-MK.A"," Iceland","0.545","0.615","0.755","0.755","0.755","0.755","0.756","0.756","0.756","0.756","0.756","0.779","0.879","0.879","0.884","0.884","0.884","0.923","0.956","1.016","1.064","1.109","1.155","1.155","1.163","1.163","1.163","1.758","1.879","1.875","1.883","1.884","1.877","1.984","1.984","1.987","1.987","1.995","2.099","2.099","2.086" -"INTL.33-7-IRL-MK.A"," Ireland","0.224","0.224","0.225","0.225","0.226","0.226","0.221","0.222","0.222","0.222","0.223","0.226","0.226","0.226","0.227","0.227","0.232","0.233","0.233","0.236","0.236","0.238","0.24","0.24","0.24","0.234","0.234","0.234","0.234","0.234","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237" -"INTL.33-7-ITA-MK.A"," Italy","15.826","15.766","16.877","17.125","12.166","12.16","12.419","12.435","12.495","12.547","12.582","12.692","12.718","12.788","12.864","12.964","12.999","13.06","13.058","13.417","13.389","13.456","13.557","13.703","13.789","13.89","13.528","13.573","13.732","13.827","13.976","14.193","14.325","14.454","14.506","14.628","14.991","15.109","15.182","15.583","14.908" -"INTL.33-7-XKS-MK.A"," Kosovo","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","0.043","0.043","0.045","0.046","0.046","0.046","0.046","0.046","0.078","0.08","0.096","0.096","0.092" -"INTL.33-7-LVA-MK.A"," Latvia","--","--","--","--","--","--","--","--","--","--","--","--","1.499","1.504","1.506","1.521","1.521","1.487","1.517","1.523","1.523","1.565","1.565","1.537","1.536","1.536","1.536","1.536","1.536","1.536","1.576","1.576","1.576","1.587","1.588","1.588","1.564","1.564","1.565","1.565","1.576" -"INTL.33-7-LTU-MK.A"," Lithuania","--","--","--","--","--","--","--","--","--","--","--","--","0.106","0.106","0.108","0.108","0.108","0.108","0.108","0.112","0.112","0.113","0.103","0.109","0.11","0.117","0.117","0.115","0.115","0.116","0.116","0.116","0.116","0.116","0.117","0.117","0.117","0.117","0.117","0.117","0.116" -"INTL.33-7-LUX-MK.A"," Luxembourg","0.029","0.029","0.029","0.032","0.032","0.032","0.032","0.032","0.032","0.032","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.039","0.039","0.039","0.039","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.035","0.034","0.034","0.034" -"INTL.33-7-MLT-MK.A"," Malta","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" -"INTL.33-7-MNE-MK.A"," Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","0.658","0.658","0.658","0.658","0.658","0.658","0.658","0.651","0.651","0.651","0.651","0.652","0.652","0.652","0.658" -"INTL.33-7-NLD-MK.A"," Netherlands","0","0","0","0","0","0.002","0.002","0.002","0.002","0.025","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.038" -"INTL.33-7-MKD-MK.A"," North Macedonia","--","--","--","--","--","--","--","--","--","--","--","--","0.426","0.426","0.413","0.423","0.423","0.434","0.434","0.4338","0.434","0.436","0.436","0.448","0.516","0.54","0.545","0.546","0.552","0.553","0.555","0.556","0.595","0.603","0.617","0.632","0.66","0.674","0.674","0.674","0.674" -"INTL.33-7-NOR-MK.A"," Norway","19.443","20.963","21.789","22.37","22.628","23.076","23.555","24.358","24.453","25.728","25.817","25.823","25.963","25.983","26.215","27.379","27.494","27.327","26.982","27.54","26.766","26.319","26.604","26.947","26.721","27.222","27.398","27.647","28.062","28.188","28.367","28.618","29.158","29.682","29.889","29.939","30.281","30.382","31.12","31.182","31.556" -"INTL.33-7-POL-MK.A"," Poland","0.647","0.647","0.647","0.647","0.645","0.646","0.646","0.646","0.772","0.647","0.467","0.467","0.468","0.475","0.489","0.482","0.492","0.495","0.501","0.505","0.509","0.517","0.517","0.524","0.535","0.542","0.549","0.546","0.553","0.556","0.56","0.564","0.569","0.573","0.582","0.588","0.597","0.591","0.592","0.592","0.605" -"INTL.33-7-PRT-MK.A"," Portugal","2.516","2.615","2.854","2.944","3.016","2.721","2.818","2.82","2.722","2.799","2.783","2.772","3.146","3.613","3.697","3.848","3.867","3.877","3.94","3.93","3.918","3.943","3.966","3.966","3.974","3.968","4.004","4.012","4.009","4.042","4.057","4.49","4.414","4.363","4.368","4.446","4.458","4.462","4.484","4.484","4.373" -"INTL.33-7-ROU-MK.A"," Romania","3.455","3.533","3.734","3.885","4.062","4.42","4.706","5.057","5.421","5.583","5.666","5.723","5.687","5.872","5.938","6.011","6.038","6.074","6.081","6.082","6.12","6.122","6.242","6.248","6.279","6.289","6.282","6.331","6.362","6.358","6.382","6.391","6.456","6.249","6.256","6.359","6.377","6.328","6.328","6.328","6.221" -"INTL.33-7-SRB-MK.A"," Serbia","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","2.206","2.206","2.206","2.221","2.293","2.322","2.352","2.317","2.403","2.408","2.416","2.424","2.424","2.424","2.484" -"INTL.33-7-SVK-MK.A"," Slovakia","--","--","--","--","--","--","--","--","--","--","--","--","--","0.925","1.208","1.525","1.655","1.664","1.682","1.684","1.685","1.586","1.586","1.588","1.602","1.596","1.597","1.599","1.632","1.571","1.6","1.607","1.606","1.607","1.607","1.606","1.608","1.607","1.612","1.612","1.505" -"INTL.33-7-SVN-MK.A"," Slovenia","--","--","--","--","--","--","--","--","--","--","--","--","0.755","0.755","0.756","0.757","0.734","0.734","0.861","0.846","0.846","0.839","0.983","0.974","0.974","0.979","1.009","1.018","1.027","1.07","1.074","1.073","1.074","1.119","1.116","1.115","1.113","1.167","1.163","1.163","1.344" -"INTL.33-7-ESP-MK.A"," Spain","13.473","10.869","10.945","10.917","10.935","10.959","11.153","10.556","10.984","11.597","11.32","11.429","11.484","11.484","11.545","11.689","11.793","11.596","11.537","11.802","12.672","12.744","15.55","15.525","12.82","12.808","12.907","12.961","13.04","13.069","13.275","13.283","13.293","14.076","14.081","14.086","14.053","14.052","14.053","14.053","14.292" -"INTL.33-7-SWE-MK.A"," Sweden","14.859","14.919","15.215","15.29","15.445","15.69","15.813","15.996","16.112","15.759","15.904","15.891","16.021","15.867","16.072","15.725","15.776","16.371","16.169","16.432","16.506","16.523","16.187","16.098","16.302","16.302","16.234","16.592","16.352","16.544","16.624","16.478","16.315","16.395","15.897","16.23","16.367","16.403","16.332","16.332","16.379" -"INTL.33-7-CHE-MK.A"," Switzerland","11.45","11.46","11.47","11.47","11.48","11.48","11.51","11.51","11.52","11.58","3.474","3.484","3.504","3.509","3.526","3.541","3.55","3.553","3.584","3.614","3.636","3.642","3.653","3.669","3.65","3.682","3.694","3.7","3.709","3.749","3.81","3.852","3.882","3.896","3.948","3.996","4.06","4.112","4.193","4.193","4.193" -"INTL.33-7-TUR-MK.A"," Turkey","2.131","2.356","3.082","3.239","3.875","3.875","3.878","5.003","6.219","6.598","6.764","7.114","8.379","9.682","9.865","9.863","9.935","10.102","10.307","10.537","11.175","11.673","12.241","12.579","12.645","12.906","13.063","13.395","13.829","14.553","15.831","17.137","19.609","22.289","23.643","25.868","26.681","27.273","28.291","28.503","30.984" -"INTL.33-7-GBR-MK.A"," United Kingdom","2.451","2.451","2.451","2.721","4.188","4.19","4.192","4.197","4.196","1.424","1.11","1.415","1.423","1.425","1.425","1.432","1.455","1.488","1.475","1.477","1.485","1.629","1.59","1.486","1.499","1.501","1.515","1.522","1.626","1.638","1.637","1.673","1.693","1.709","1.73","1.777","1.836","1.873","1.878","1.878","1.879" +# https://www.eia.gov/international/data/world/electricity/electricity-generation?pd=2&p=00000000000000000000008&u=1&f=A&v=mapbubble&a=-&i=none&vo=value&t=R&g=000000000000002&l=73-1028i008017kg6368g80a4k000e0ag00gg0004g8g0ho00g000400008&l=72-00000000000000000000000000080000000000000000000g&s=315532800000&e=1609459200000&ev=false& +Report generated on: 03-14-2024 13:39:49 +"API","","1980","1981","1982","1983","1984","1985","1986","1987","1988","1989","1990","1991","1992","1993","1994","1995","1996","1997","1998","1999","2000","2001","2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012","2013","2014","2015","2016","2017","2018","2019","2020","2021" +"","hydroelectricity installed capacity (million kW)","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","" +"INTL.33-7-EURO-MK.A"," Europe","136.143","137.425","141.734","143.763","142.894","144.738","147.631","150.428","153.428","153.345","139.346","134.524","137.463","138.338","139.688","141.47","142.121","143.595","143.957","146.4204","147.3512","147.736","152.173","152.938","150.4894","151.424","152.276","154.198","155.405","156.988","159.495","162.112","165.452","170.146","171.588","174.906","176.998","178.221","180.212","181.039","184.728","185.46" +"INTL.33-7-ALB-MK.A"," Albania","0.5","0.525","0.55","0.6","0.625","0.65","0.675","0.68","0.69","0.69","1.668","1.668","1.668","1.668","1.668","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.445","1.432","1.432","1.432","1.45","1.45","1.461","1.508","1.628","1.781","1.725","1.798","1.913","2.047","2.105","2.193","2.39","2.39" +"INTL.33-7-AUT-MK.A"," Austria","8.206","9.157","9.51","9.582","10.034","10.171","10.423","10.691","10.762","10.858","7.028","7.129","7.204","7.202","7.245","7.323","7.385","7.54","7.685","7.669","7.676","7.703","7.567","7.607","7.613","7.667","7.684","7.845","7.848","7.827","7.913","7.947","7.97","8.272","8.321","8.457","8.493","8.506","8.591","8.63","9.001","9.151" +"INTL.33-7-BEL-MK.A"," Belgium","0.073","0.08","0.086","0.086","0.086","0.087","0.089","0.09","0.093","0.095","0.094","0.094","0.094","0.095","0.095","0.096","0.096","0.096","0.097","0.103","0.103","0.111","0.111","0.11","0.115","0.105","0.107","0.11","0.111","0.11","0.118","0.119","0.12","0.119","0.121","0.112","0.115","0.107","0.108","0.108","0.12","0.12" +"INTL.33-7-BIH-MK.A"," Bosnia and Herzegovina","--","--","--","--","--","--","--","--","--","--","--","--","1.2","1.2","1.139","1.219","1.219","1.219","1.624","1.983","1.983","1.993","2.38","2.38","2.38","2.38","2.411","2.411","2.117","2.117","2.117","2.117","2.12","2.12","2.049","2.055","2.084","2.084","2.09","2.09","2.093","1.747" +"INTL.33-7-BGR-MK.A"," Bulgaria","1.895","1.895","1.895","1.975","1.975","1.975","1.975","1.975","1.975","1.973","1.973","1.401","1.401","1.401","1.401","1.401","1.401","1.803","1.803","1.803","1.881","1.706","1.948","1.984","1.984","1.984","1.984","2.012","2.12","2.137","2.184","2.035","2.095","2.165","2.19","2.206","2.206","2.21","1.725","1.725","1.725","1.725" +"INTL.33-7-HRV-MK.A"," Croatia","--","--","--","--","--","--","--","--","--","--","--","--","1.769","1.77","1.77","1.781","1.785","1.785","1.785","1.785","1.785","1.785","1.775","1.783","1.79","1.804","1.804","1.782","1.782","1.799","1.848","1.848","1.848","1.897","1.9","1.915","1.912","1.912","1.913","1.913","1.848","1.874" +"INTL.33-7-CYP-MK.A"," Cyprus","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" +"INTL.33-7-CZE-MK.A"," Czechia","--","--","--","--","--","--","--","--","--","--","--","--","--","0.911","0.906","0.908","0.868","0.905","0.888","1.008","0.952","1","1","1.004","1.015","1.02","1.016","1.024","1.029","1.037","1.049","1.05","1.065","1.08","1.08","1.088","1.09","1.093","1.094","1.096","1.097","1.109" +"INTL.33-7-DNK-MK.A"," Denmark","0.008","0.008","0.01","0.009","0.009","0.009","0.009","0.009","0.009","0.011","0.01","0.01","0.01","0.01","0.008","0.01","0.01","0.01","0.011","0.011","0.01","0.011","0.011","0.011","0.011","0.011","0.009","0.009","0.009","0.009","0.009","0.009","0.009","0.009","0.009","0.007","0.009","0.009","0.009","0.009","0.009","0.007" +"INTL.33-7-EST-MK.A"," Estonia","--","--","--","--","--","--","--","--","--","--","--","--","0.001","0.001","0.001","0.001","0.001","0.001","0.001","0.0012","0.0012","0.003","0.003","0.004","0.004","0.005","0.005","0.005","0.005","0.007","0.006","0.005","0.008","0.008","0.005","0.006","0.006","0.007","0.007","0.007","0.008","0.004" +"INTL.33-7-FRO-MK.A"," Faroe Islands","0.018","0.018","0.018","0.018","0.018","0.018","0.018","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.0314","0.032","0.032","0.032","0.032","0.0314","0.031","0.031","0.031","0.031","0.031","0.031","0.031","0.039","0.039","0.04","0.04","0.04","0.04","0.04","0.04","0.039","0.039" +"INTL.33-7-FIN-MK.A"," Finland","2.42","2.467","2.474","2.503","2.497","2.505","2.555","2.586","2.597","2.586","2.621","2.648","2.679","2.731","2.736","2.777","2.785","2.861","2.881","2.881","2.882","2.926","2.964","2.966","2.999","3.035","3.062","3.102","3.122","3.145","3.155","3.196","3.196","3.224","3.248","3.249","3.249","3.272","3.287","3.287","3.263","3.263" +"INTL.33-7-CSK-MK.A"," Former Czechoslovakia","2.578","2.832","2.84","2.84","2.875","2.897","2.89","2.975","2.988","3.042","3.036","3.061","3.061","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-SCG-MK.A"," Former Serbia and Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","2.25","2.25","2.25","2.25","2.25","2.25","2.25","2.296","2.296","2.296","2.296","2.296","2.206","2.206","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-YUG-MK.A"," Former Yugoslavia","6.2","6.25","5.886","5.886","6.386","6.736","7.086","7.386","7.625","7.686","7.386","7.386","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-FRA-MK.A"," France","17.431","17.63","18.247","18.4","18.661","19.034","19.786","19.991","20.174","20.338","17.717","17.655","17.767","17.837","17.902","17.898","18","18.018","18.024","17.947","17.646","17.674","17.775","17.927","17.812","17.808","17.82","17.832","17.922","18.009","18.156","18.373","18.388","18.379","18.392","18.415","18.486","18.561","18.857","18.88","19.671","19.657" +"INTL.33-7-DEU-MK.A"," Germany","--","--","--","--","--","--","--","--","--","--","--","3.31","3.317","3.385","3.471","3.624","3.563","3.569","3.642","3.802","4.086","4.101","4.193","4.088","4.209","4.134","4.117","4.083","4.104","4.283","4.252","4.469","4.451","4.433","4.424","4.433","4.442","4.449","4.456","4.456","4.658","4.684" +"INTL.33-7-DDR-MK.A"," Germany, East","1.852","1.845","1.852","1.851","1.845","1.844","1.844","1.844","1.844","1.844","1.844","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-DEUW-MK.A"," Germany, West","6.45","6.509","6.531","6.631","6.668","6.71","6.71","6.71","6.85","6.86","6.86","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-7-GIB-MK.A"," Gibraltar","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" +"INTL.33-7-GRC-MK.A"," Greece","1.415","1.714","1.714","1.714","1.714","1.822","1.822","1.822","1.836","1.986","2.093","2.197","2.208","2.208","2.208","2.208","2.207","2.412","2.241","2.344","2.373","2.377","2.379","2.38","2.4","2.407","2.435","2.451","2.477","2.502","2.516","2.525","2.537","2.539","2.69","2.693","2.693","2.693","2.71","2.71","2.697","2.722" +"INTL.33-7-HUN-MK.A"," Hungary","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.048","0.054","0.049","0.049","0.049","0.049","0.051","0.053","0.053","0.055","0.056","0.057","0.057","0.057","0.057","0.057","0.057","0.057","0.056","0.058" +"INTL.33-7-ISL-MK.A"," Iceland","0.545","0.615","0.755","0.755","0.755","0.755","0.756","0.756","0.756","0.756","0.756","0.779","0.879","0.879","0.884","0.884","0.884","0.923","0.956","1.016","1.064","1.109","1.155","1.155","1.163","1.163","1.163","1.758","1.879","1.875","1.883","1.884","1.877","1.984","1.984","1.987","1.987","1.995","2.099","2.099","2.086","2.086" +"INTL.33-7-IRL-MK.A"," Ireland","0.224","0.224","0.225","0.225","0.226","0.226","0.221","0.222","0.222","0.222","0.223","0.226","0.226","0.226","0.227","0.227","0.232","0.233","0.233","0.236","0.236","0.238","0.24","0.24","0.24","0.234","0.234","0.234","0.234","0.234","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.237","0.216" +"INTL.33-7-ITA-MK.A"," Italy","15.826","15.766","16.877","17.125","12.166","12.16","12.419","12.435","12.495","12.547","12.582","12.692","12.718","12.788","12.864","12.964","12.999","13.06","13.058","13.417","13.389","13.456","13.557","13.703","13.789","13.89","13.528","13.573","13.732","13.827","13.976","14.193","14.325","14.454","14.506","14.628","14.991","15.109","15.182","15.583","14.908","14.908" +"INTL.33-7-XKS-MK.A"," Kosovo","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","0.043","0.043","0.045","0.046","0.046","0.046","0.046","0.046","0.078","0.08","0.096","0.096","0.092","0.092" +"INTL.33-7-LVA-MK.A"," Latvia","--","--","--","--","--","--","--","--","--","--","--","--","1.499","1.504","1.506","1.521","1.521","1.487","1.517","1.523","1.523","1.565","1.565","1.537","1.536","1.536","1.536","1.536","1.536","1.536","1.576","1.576","1.576","1.587","1.588","1.588","1.564","1.564","1.565","1.565","1.576","1.588" +"INTL.33-7-LTU-MK.A"," Lithuania","--","--","--","--","--","--","--","--","--","--","--","--","0.106","0.106","0.108","0.108","0.108","0.108","0.108","0.112","0.112","0.113","0.103","0.109","0.11","0.117","0.117","0.115","0.115","0.116","0.116","0.116","0.116","0.116","0.117","0.117","0.117","0.117","0.117","0.117","0.116","0.128" +"INTL.33-7-LUX-MK.A"," Luxembourg","0.029","0.029","0.029","0.032","0.032","0.032","0.032","0.032","0.032","0.032","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.039","0.039","0.039","0.039","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.034","0.035","0.034","0.034","0.034","0.037" +"INTL.33-7-MLT-MK.A"," Malta","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" +"INTL.33-7-MNE-MK.A"," Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","0.658","0.658","0.658","0.658","0.658","0.658","0.658","0.651","0.651","0.651","0.651","0.652","0.652","0.652","0.658","0.649" +"INTL.33-7-NLD-MK.A"," Netherlands","0","0","0","0","0","0.002","0.002","0.002","0.002","0.025","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.037","0.038","0.038" +"INTL.33-7-MKD-MK.A"," North Macedonia","--","--","--","--","--","--","--","--","--","--","--","--","0.426","0.426","0.413","0.423","0.423","0.434","0.434","0.4338","0.434","0.436","0.436","0.448","0.516","0.54","0.545","0.546","0.552","0.553","0.555","0.556","0.595","0.603","0.617","0.632","0.66","0.674","0.674","0.674","0.674","0.644" +"INTL.33-7-NOR-MK.A"," Norway","19.443","20.963","21.789","22.37","22.628","23.076","23.555","24.358","24.453","25.728","25.817","25.823","25.963","25.983","26.215","27.379","27.494","27.327","26.982","27.54","26.766","26.319","26.604","26.947","26.721","27.222","27.398","27.647","28.062","28.188","28.367","28.618","29.158","29.682","29.889","29.939","30.281","30.382","31.12","31.182","31.556","31.952" +"INTL.33-7-POL-MK.A"," Poland","0.647","0.647","0.647","0.647","0.645","0.646","0.646","0.646","0.772","0.647","0.467","0.467","0.468","0.475","0.489","0.482","0.492","0.495","0.501","0.505","0.509","0.517","0.517","0.524","0.535","0.542","0.549","0.546","0.553","0.556","0.56","0.564","0.569","0.573","0.582","0.588","0.597","0.591","0.592","0.592","0.605","0.605" +"INTL.33-7-PRT-MK.A"," Portugal","2.516","2.615","2.854","2.944","3.016","2.721","2.818","2.82","2.722","2.799","2.783","2.772","3.146","3.613","3.697","3.848","3.867","3.877","3.94","3.93","3.918","3.943","3.966","3.966","3.974","3.968","4.004","4.012","4.009","4.042","4.057","4.49","4.414","4.363","4.368","4.446","4.458","4.462","4.484","4.484","4.373","4.372" +"INTL.33-7-ROU-MK.A"," Romania","3.455","3.533","3.734","3.885","4.062","4.42","4.706","5.057","5.421","5.583","5.666","5.723","5.687","5.872","5.938","6.011","6.038","6.074","6.081","6.082","6.12","6.122","6.242","6.248","6.279","6.289","6.282","6.331","6.362","6.358","6.382","6.391","6.456","6.249","6.256","6.359","6.377","6.328","6.328","6.328","6.221","6.221" +"INTL.33-7-SRB-MK.A"," Serbia","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","2.206","2.206","2.206","2.221","2.293","2.322","2.352","2.317","2.403","2.408","2.416","2.424","2.424","2.424","2.484","2.491" +"INTL.33-7-SVK-MK.A"," Slovakia","--","--","--","--","--","--","--","--","--","--","--","--","--","0.925","1.208","1.525","1.655","1.664","1.682","1.684","1.685","1.586","1.586","1.588","1.602","1.596","1.597","1.599","1.632","1.571","1.6","1.607","1.606","1.607","1.607","1.606","1.608","1.607","1.612","1.612","1.505","1.505" +"INTL.33-7-SVN-MK.A"," Slovenia","--","--","--","--","--","--","--","--","--","--","--","--","0.755","0.755","0.756","0.757","0.734","0.734","0.861","0.846","0.846","0.839","0.983","0.974","0.974","0.979","1.009","1.018","1.027","1.07","1.074","1.073","1.074","1.119","1.116","1.115","1.113","1.167","1.163","1.163","1.163","1.121" +"INTL.33-7-ESP-MK.A"," Spain","13.473","10.869","10.945","10.917","10.935","10.959","11.153","10.556","10.984","11.597","11.32","11.429","11.484","11.484","11.545","11.689","11.793","11.596","11.537","11.802","12.672","12.744","15.55","15.525","12.82","12.808","12.907","12.961","13.04","13.069","13.275","13.283","13.293","14.076","14.081","14.086","14.053","14.052","14.053","14.053","14.292","14.308" +"INTL.33-7-SWE-MK.A"," Sweden","14.859","14.919","15.215","15.29","15.445","15.69","15.813","15.996","16.112","15.759","15.904","15.891","16.021","15.867","16.072","15.725","15.776","16.371","16.169","16.432","16.506","16.523","16.187","16.098","16.302","16.302","16.234","16.592","16.352","16.544","16.624","16.478","16.315","16.395","15.897","16.23","16.367","16.403","16.332","16.332","16.379","16.379" +"INTL.33-7-CHE-MK.A"," Switzerland","11.45","11.46","11.47","11.47","11.48","11.48","11.51","11.51","11.52","11.58","3.474","3.484","3.504","3.509","3.526","3.541","3.55","3.553","3.584","3.614","3.636","3.642","3.653","3.669","3.65","3.682","3.694","3.7","3.709","3.749","3.81","3.852","3.882","3.896","3.948","3.996","4.06","4.112","4.193","4.193","4.193","4.193" +"INTL.33-7-TUR-MK.A"," Turkiye","2.131","2.356","3.082","3.239","3.875","3.875","3.878","5.003","6.219","6.598","6.764","7.114","8.379","9.682","9.865","9.863","9.935","10.102","10.307","10.537","11.175","11.673","12.241","12.579","12.645","12.906","13.063","13.395","13.829","14.553","15.831","17.137","19.609","22.289","23.643","25.868","26.681","27.273","28.291","28.503","30.984","31.497" +"INTL.33-7-GBR-MK.A"," United Kingdom","2.451","2.451","2.451","2.721","4.188","4.19","4.192","4.197","4.196","1.424","1.11","1.415","1.423","1.425","1.425","1.432","1.455","1.488","1.475","1.477","1.485","1.629","1.59","1.486","1.499","1.501","1.515","1.522","1.626","1.638","1.637","1.673","1.693","1.709","1.73","1.777","1.836","1.873","1.878","1.878","1.879","1.88" +""," Eurasia","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","" +"INTL.33-7-MDA-MK.A"," Moldova","--","--","--","--","--","--","--","--","--","--","--","--","0.064","0.064","0.064","0.056","0.056","0.064","0.064","0.064","0.064","0.06","0.06","0.06","0.059","0.059","0.056","0.056","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.076","0.076" +"INTL.33-7-UKR-MK.A"," Ukraine","--","--","--","--","--","--","--","--","--","--","--","--","4.705","4.706","4.706","4.706","4.706","4.706","4.706","4.7","4.7","4.731","4.758","4.766","4.781","4.717","4.746","4.731","4.798","4.795","4.596","4.607","4.608","4.632","4.665","4.697","4.658","4.668","4.668","4.668","4.666","4.43" \ No newline at end of file diff --git a/data/eia_hydro_annual_generation.csv b/data/eia_hydro_annual_generation.csv index 859decf7..d4e64a31 100644 --- a/data/eia_hydro_annual_generation.csv +++ b/data/eia_hydro_annual_generation.csv @@ -1,53 +1,53 @@ -https://www.eia.gov/international/data/world/electricity/electricity-generation?pd=2&p=000000000000000000000000000000g&u=1&f=A&v=mapbubble&a=-&i=none&vo=value&t=R&g=000000000000002&l=73-1028i008017kg6368g80a4k000e0ag00gg0004g8g0ho00g000400008&l=72-00000000000000000000000000080000000000000000000g&s=315532800000&e=1609459200000&ev=false&,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -Report generated on: 01-06-2023 21:17:46,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -API,,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021 -,hydroelectricity net generation (billion kWh),,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -INTL.33-12-EURO-BKWH.A, Europe,"458,018","464,155","459,881","473,685","481,241","476,739","459,535","491,085","534,517","465,365","474,466","475,47","509,041","526,448","531,815","543,743","529,114164","543,845616","562,491501","566,861453","588,644662","584,806195","539,051405","503,7067","542,112443","542,974669","535,006084","538,449707","565,143111","561,761402","617,547148","540,926277","598,055253","629,44709","617,111295","613,079848","627,720566217","560,362524","616,5081462","606,5997419","644,1106599","628,1390143" -INTL.33-12-ALB-BKWH.A, Albania,"2,919","3,018","3,093","3,167","3,241","3,315","3,365","3,979","3,713","3,846","2,82","3,483","3,187","3,281","3,733","4,162","5,669","4,978","4,872","5,231","4,548","3,519","3,477","5,117","5,411","5,319","4,951","2,76","3,759","5,201","7,49133","4,09068","4,67775","6,88941","4,67676","5,83605","7,70418","4,47975","8,46648","5,15394","5,281","8,891943" -INTL.33-12-AUT-BKWH.A, Austria,"28,501","30,008","29,893","29,577","28,384","30,288","30,496","25,401","35,151","34,641","31,179","31,112","34,483","36,336","35,349","36,696","33,874","35,744","36,792","40,292","41,418","40,05","39,825","32,883","36,394","36,31","35,48","36,732","37,969","40,487","36,466","32,511","41,862","40,138","39,001","35,255","37,954","36,462","35,73","40,43655","41,9356096","38,75133" -INTL.33-12-BEL-BKWH.A, Belgium,"0,274","0,377","0,325","0,331","0,348","0,282","0,339","0,425","0,354","0,3","0,263","0,226","0,338","0,252","0,342","0,335","0,237","0,30195","0,38511","0,338","0,455","0,437","0,356","0,245","0,314","0,285","0,355","0,385","0,406","0,325","0,298","0,193","0,353","0,376","0,289","0,314","0,367","0,268","0,3135","0,302","0,2669","0,3933" -INTL.33-12-BIH-BKWH.A, Bosnia and Herzegovina,--,--,--,--,--,--,--,--,--,--,--,--,"3,374","2,343","3,424","3,607","5,104","4,608","4,511","5,477","5,043","5,129","5,215","4,456","5,919","5,938","5,798","3,961","4,818","6,177","7,946","4,343","4,173","7,164","5,876","5,495","5,585","3,7521","6,35382","6,02019","4,58","6,722" -INTL.33-12-BGR-BKWH.A, Bulgaria,"3,674","3,58","3,018","3,318","3,226","2,214","2,302","2,512","2,569","2,662","1,859","2,417","2,042","1,923","1,453","2,291","2,89","2,726","3,066","2,725","2,646","1,72","2,172","2,999","3,136","4,294","4,196","2,845","2,796","3,435","4,98168","2,84328","3,14622","3,99564","4,55598","5,59845","3,8412","2,79972","5,09553","2,929499","2,820398","4,819205" -INTL.33-12-HRV-BKWH.A, Croatia,--,--,--,--,--,--,--,--,--,--,--,--,"4,298","4,302","4,881","5,212","7,156","5,234","5,403","6,524","5,794","6,482","5,311","4,827","6,888","6,27","5,94","4,194","5,164","6,663","9,035","4,983","4,789","8,536","8,917","6,327","6,784","5,255","7,62399","5,87268","5,6624","7,1277" -INTL.33-12-CYP-BKWH.A, Cyprus,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -INTL.33-12-CZE-BKWH.A, Czechia,--,--,--,--,--,--,--,--,--,--,--,--,--,"1,355","1,445","1,982","1,949","1,68201","1,382","1,664","1,7404","2,033","2,467","1,369","1,999","2,356","2,525","2,068","2,004","2,405","2,775","1,95","2,107","2,704","1,909","1,779","1,983","1,852","1,615","1,98792","2,143884","2,40852" -INTL.33-12-DNK-BKWH.A, Denmark,"0,03","0,031","0,028","0,036","0,028","0,027","0,029","0,029","0,032","0,027","0,027","0,026","0,028","0,027","0,033","0,03","0,019","0,019","0,02673","0,031","0,03","0,028","0,032","0,021","0,027","0,023","0,023","0,028","0,026","0,019","0,021","0,017","0,017","0,013","0,015","0,01803","0,01927","0,017871","0,0148621","0,0172171","0,017064","0,016295" -INTL.33-12-EST-BKWH.A, Estonia,--,--,--,--,--,--,--,--,--,--,--,--,"0,001","0,001","0,003","0,002","0,002","0,003","0,004","0,004","0,005","0,007","0,006","0,013","0,022","0,022","0,014","0,021","0,028","0,032","0,027","0,029999","0,042","0,026","0,027","0,027","0,035","0,025999","0,0150003","0,0189999","0,03","0,0248" -INTL.33-12-FRO-BKWH.A, Faroe Islands,"0,049","0,049","0,049","0,049","0,049","0,049","0,049","0,049","0,062","0,071","0,074","0,074","0,083","0,073","0,075","0,075","0,069564","0,075066","0,076501","0,069453","0,075262","0,075195","0,095535","0,08483","0,093443","0,097986","0,099934","0,103407","0,094921","0,091482","0,06676","0,092","0,099","0,091","0,121","0,132","0,105","0,11","0,107","0,102","0,11","0,11" -INTL.33-12-FIN-BKWH.A, Finland,"10,115","13,518","12,958","13,445","13,115","12,211","12,266","13,658","13,229","12,9","10,75","13,065","14,956","13,341","11,669","12,796","11,742","12,11958","14,9","12,652","14,513","13,073","10,668","9,495","14,919","13,646","11,379","14,035","16,941","12,559","12,743","12,278001","16,666998","12,672","13,240001","16,583999","15,634127","14,609473","13,1369998","12,2454823","15,883","15,766" -INTL.33-12-CSK-BKWH.A, Former Czechoslovakia,"4,8","4,2","3,7","3,9","3,2","4,3",4,"4,853","4,355","4,229","3,919","3,119","3,602",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,-- -INTL.33-12-SCG-BKWH.A, Former Serbia and Montenegro,--,--,--,--,--,--,--,--,--,--,--,--,"11,23","10,395","11,016","12,071","14,266","12,636","12,763","13,243","11,88","12,326","11,633","9,752","11,01","11,912",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,-- -INTL.33-12-YUG-BKWH.A, Former Yugoslavia,"27,868","25,044","23,295","21,623","25,645","24,363","27,474","25,98","25,612","23,256","19,601","18,929",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,-- -INTL.33-12-FRA-BKWH.A, France,"68,253","70,358","68,6","67,515","64,01","60,248","60,953","68,623","73,952","45,744","52,796","56,277","68,313","64,3","78,057","72,196","64,43","63,151","61,479","71,832","66,466","73,888","59,992","58,567","59,276","50,965","55,741","57,029","63,017","56,428","61,945","45,184","59,099","71,042","62,993","54,876","60,094","49,389","64,485","56,913891","62,06191","58,856657" -INTL.33-12-DEU-BKWH.A, Germany,--,--,--,--,--,--,--,--,--,--,--,"14,742","17,223","17,699","19,731","21,562","21,737","17,18343","17,044","19,451","21,515","22,506","22,893","19,071","20,866","19,442","19,808","20,957","20,239","18,841","20,678","17,323","21,331","22,66","19,31","18,664","20,214","19,985","17,694","19,731","18,322","19,252" -INTL.33-12-DDR-BKWH.A," Germany, East","1,658","1,718","1,748","1,683","1,748","1,758","1,767","1,726","1,719","1,551","1,389",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,-- -INTL.33-12-DEUW-BKWH.A," Germany, West","17,125","17,889","17,694","16,713","16,434","15,354","16,526","18,36","18,128","16,482","15,769",--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,-- -INTL.33-12-GIB-BKWH.A, Gibraltar,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -INTL.33-12-GRC-BKWH.A, Greece,"3,396","3,398","3,551","2,331","2,852","2,792","3,222","2,768","2,354","1,888","1,751","3,068","2,181","2,26","2,573","3,494","4,305","3,84318","3,68","4,546","3,656","2,076","2,772","4,718","4,625","4,967","5,806","2,565","3,279","5,32","7,431","3,998","4,387","6,337","4,464","5,782","5,543","3,962","5,035","3,9798","3,343687","5,909225" -INTL.33-12-HUN-BKWH.A, Hungary,"0,111","0,166","0,158","0,153","0,179","0,153","0,152","0,167","0,167","0,156","0,176","0,192","0,156","0,164","0,159","0,161","0,205","0,21384","0,15345","0,179","0,176","0,184","0,192","0,169","0,203","0,2","0,184","0,208","0,211","0,226","0,184","0,215999","0,205999","0,207999","0,294001","0,226719","0,253308","0,213999","0,216","0,2129999","0,238","0,202379" -INTL.33-12-ISL-BKWH.A, Iceland,"3,053","3,085","3,407","3,588","3,738","3,667","3,846","3,918","4,169","4,217","4,162","4,162","4,267","4,421","4,47","4,635","4,724","5,15493","5,565","5,987","6,292","6,512","6,907","7,017","7,063","6,949","7,22","8,31","12,303","12,156","12,509999","12,381999","12,213999","12,747001","12,554","13,541","13,091609","13,891929","13,679377","13,32911","12,9196201","13,5746171" -INTL.33-12-IRL-BKWH.A, Ireland,"0,833","0,855","0,792","0,776","0,68","0,824","0,91","0,673","0,862","0,684","0,69","0,738","0,809","0,757","0,911","0,706","0,715","0,67122","0,907","0,838","0,838","0,59","0,903","0,592","0,624","0,625","0,717","0,66","0,959","0,893","0,593","0,699","0,795","0,593","0,701","0,798","0,674","0,685","0,687","0,87813","0,932656","0,750122" -INTL.33-12-ITA-BKWH.A, Italy,"44,997","42,782","41,216","40,96","41,923","40,616","40,626","39,05","40,205","33,647","31,31","41,817","41,778","41,011","44,212","37,404","41,617","41,18697","40,808","44,911","43,763","46,343","39,125","33,303","41,915","35,706","36,624","32,488","41,207","48,647","50,506","45,36477","41,45625","52,24626","57,95955","45,08163","42,00768","35,83701","48,29913","45,31824","47,551784","44,739" -INTL.33-12-XKS-BKWH.A, Kosovo,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,"0,075","0,119","0,154","0,104","0,095","0,142","0,149","0,139","0,243","0,177","0,27027","0,2079","0,262826","0,300635" -INTL.33-12-LVA-BKWH.A, Latvia,--,--,--,--,--,--,--,--,--,--,--,--,"2,498","2,846","3,272","2,908","1,841","2,922","2,99","2,729","2,791","2,805","2,438","2,243","3,078","3,293","2,671","2,706","3,078","3,422","3,487998","2,8568","3,677","2,838","1,953","1,841","2,522819","4,355513","2,4170639","2,0958919","2,5840101","2,6889293" -INTL.33-12-LTU-BKWH.A, Lithuania,--,--,--,--,--,--,--,--,--,--,--,--,"0,308","0,389","0,447","0,369","0,323","0,291","0,413","0,409","0,336","0,322","0,35","0,323","0,417","0,446193","0,393","0,417","0,398","0,42","0,535","0,475","0,419","0,516","0,395","0,346","0,45","0,597","0,427","0,34254","0,3006","0,3837" -INTL.33-12-LUX-BKWH.A, Luxembourg,"0,086","0,095","0,084","0,083","0,088","0,071","0,084","0,101","0,097","0,072","0,07","0,083","0,069","0,066","0,117","0,087","0,059","0,082","0,114","0,084","0,119","0,117","0,098","0,078","0,103","0,093","0,11","0,116","0,131","0,105","0,104","0,061","0,095","0,114","0,104","0,095","0,111","0,082","0,089","0,10593","0,091602","0,1068" -INTL.33-12-MLT-BKWH.A, Malta,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -INTL.33-12-MNE-BKWH.A, Montenegro,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,"1,733","1,271","1,524","2,05","2,723","1,192","1,462","2,479","1,734","1,476","1,825","1,014","1,693443","1,262781","0,867637","1,212652" -INTL.33-12-NLD-BKWH.A, Netherlands,0,0,0,0,0,"0,003","0,003","0,001","0,002","0,037","0,119","0,079","0,119","0,091","0,1","0,087","0,079","0,09108","0,111","0,089","0,141","0,116","0,109","0,071","0,094","0,087","0,105","0,106","0,101","0,097","0,105","0,057","0,104389","0,11431","0,112202","0,0927","0,100078","0,060759","0,0723481","0,074182","0,0462851","0,0838927" -INTL.33-12-MKD-BKWH.A, North Macedonia,--,--,--,--,--,--,--,--,--,--,--,--,"0,817","0,517","0,696","0,793","0,842","0,891","1,072","1,375","1,158","0,62","0,749","1,36","1,467","1,477","1,634",1,"0,832","1,257","2,407","1,419","1,031","1,568","1,195","1,846","1,878","1,099","1,773","1,15236","1,277144","1,451623" -INTL.33-12-NOR-BKWH.A, Norway,"82,717","91,876","91,507","104,704","104,895","101,464","95,321","102,341","107,919","117,369","119,933","109,032","115,505","118,024","110,398","120,315","102,823","108,677","114,546","120,237","140,4","119,258","128,078","104,425","107,693","134,331","118,175","132,319","137,654","124,03","116,257","119,78","141,189","127,551","134,844","136,662","142,244","141,651","138,202","123,66288","141,69",144 -INTL.33-12-POL-BKWH.A, Poland,"2,326","2,116","1,528","1,658","1,394","1,833","1,534","1,644","1,775","1,593","1,403","1,411","1,492","1,473","1,716","1,868","1,912","1,941","2,286","2,133","2,085","2,302","2,256","1,654","2,06","2,179","2,022","2,328","2,13","2,351","2,9","2,313","2,02","2,421","2,165","1,814","2,117","2,552","1,949","1,93842","2,118337","2,339192" -INTL.33-12-PRT-BKWH.A, Portugal,"7,873","4,934","6,82","7,897","9,609","10,512","8,364","9,005","12,037","5,72","9,065","8,952","4,599","8,453","10,551","8,26","14,613","12,97395","12,853","7,213","11,21","13,894","7,722","15,566","9,77","4,684","10,892","9,991","6,73","8,201","15,954","11,423","5,589","13,652","15,471","8,615","15,608","5,79","12,316","8,6526","12,082581","11,846464" -INTL.33-12-ROU-BKWH.A, Romania,"12,506","12,605","11,731","9,934","11,208","11,772","10,688","11,084","13,479","12,497","10,87","14,107","11,583","12,64","12,916","16,526","15,597","17,334","18,69","18,107","14,63","14,774","15,886","13,126","16,348","20,005","18,172","15,806","17,023","15,379","19,684","14,581","11,945","14,807","18,618","16,467","17,848","14,349","17,48736","15,580622","15,381243","17,376933" -INTL.33-12-SRB-BKWH.A, Serbia,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,"10,855","9,937","9,468","10,436","11,772","8,58","9,193","10,101","10,893","9,979","10,684","9,061","10,53261","9,457175","9,034496","11,284232" -INTL.33-12-SVK-BKWH.A, Slovakia,--,--,--,--,--,--,--,--,--,--,--,--,--,"3,432","4,311","4,831","4,185","4,023","4,224","4,429","4,569","4,878","5,215","3,4452","4,059","4,592","4,355","4,406",4,"4,324","5,184","3,211","3,687","4,329","3,762","3,701","4,302","4,321","3,506","4,27383","4,517","4,17" -INTL.33-12-SVN-BKWH.A, Slovenia,--,--,--,--,--,--,--,--,--,--,--,--,"3,379","2,974","3,348","3,187","3,616","3,046","3,4","3,684","3,771","3,741","3,265","2,916","4,033","3,426","3,555","3,233","3,978","4,666","4,452","3,506","3,841","4,562","6,011","3,75","4,443","3,814","4,643","4,43421","4,93406","4,711944" -INTL.33-12-ESP-BKWH.A, Spain,"29,16","21,64","25,99","26,696","31,088","30,895","26,105","27,016","34,76","19,046","25,16","27,01","18,731","24,133","27,898","22,881","39,404","34,43","33,665","22,634","29,274","40,617","22,691","40,643","31,359","18,209","25,699","27,036","23,13","26,147","41,576","30,07","20,192","36,45","38,815","27,656","35,77","18,007","33,743","24,23025","30,507","29,626" -INTL.33-12-SWE-BKWH.A, Sweden,"58,133","59,006","54,369","62,801","67,106","70,095","60,134","70,95","69,016","70,911","71,778","62,603","73,588","73,905","58,508","67,421","51,2226","68,365","74,25","70,974","77,798","78,269","65,696","53,005","59,522","72,075","61,106","65,497","68,378","65,193","66,279","66,047","78,333","60,81","63,227","74,734","61,645","64,651","61,79","64,46583","71,6","71,086" -INTL.33-12-CHE-BKWH.A, Switzerland,"32,481","35,13","35,974","35,069","29,871","31,731","32,576","34,328","35,437","29,477","29,497","31,756","32,373","35,416","38,678","34,817","28,458","33,70257","33,136","37,104","33,854","38,29","32,323","31,948","30,938","28,664","28,273","32,362","33,214","32,833","33,261","29,906","35,783","35,628","35,122","35,378","31,984","31,47968","32,095881","35,156989","37,867647","36,964485" -INTL.33-12-TUR-BKWH.A, Turkey,"11,159","12,308","13,81","11,13","13,19","11,822","11,637","18,314","28,447","17,61","22,917","22,456","26,302","33,611","30,28","35,186","40,07","39,41784","41,80671","34,33","30,57","23,77","33,346","34,977","45,623","39,165","43,802","35,492","32,937","35,598","51,423001","51,154999","56,668998","58,225","39,750001","65,856","66,685883","57,823851","59,490211","88,2094218","78,094369","55,1755392" -INTL.33-12-GBR-BKWH.A, United Kingdom,"3,921","4,369","4,543","4,548","3,992","4,08","4,767","4,13","4,915","4,732","5,119","4,534","5,329","4,237","5,043","4,79","3,359","4,127","5,117","5,336","5,085","4,055","4,78787","3,22767","4,844","4,92149","4,59315","5,0773","5,14119","5,22792","3,59138","5,69175","5,30965","4,70147","5,8878","6,29727","5,370412217","5,88187","5,44327","5,84628","6,75391","5,0149" -, Eurasia,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -INTL.33-12-MDA-BKWH.A, Moldova,--,--,--,--,--,--,--,--,--,--,--,--,"0,255","0,371","0,275","0,321","0,362","0,378","0,387","0,363","0,392","0,359","0,348","0,358","0,35","0,359","0,365","0,354","0,385","0,354","0,403","0,348","0,266","0,311","0,317","0,265","0,228","0,282","0,27324","0,29799","0,276","0,316" -INTL.33-12-UKR-BKWH.A, Ukraine,--,--,--,--,--,--,--,--,--,--,--,--,"7,725","10,929","11,997","9,853","8,546","9,757","15,756","14,177","11,161","11,912","9,531","9,146","11,635","12,239","12,757","10,042","11,397","11,817","13,02","10,837","10,374","13,663","8,393","5,343","7,594","8,856","10,32372","6,5083","7,5638","10,3326" +# https://www.eia.gov/international/data/world/electricity/electricity-generation?pd=2&p=000000000000000000000000000000g&u=1&f=A&v=mapbubble&a=-&i=none&vo=value&t=R&g=000000000000002&l=73-1028i008017kg6368g80a4k000e0ag00gg0004g8g0ho00g000400008&l=72-00000000000000000000000000080000000000000000000g&s=315532800000&e=1609459200000&ev=false& +Report generated on: 03-14-2024 13:40:38 +"API","","1980","1981","1982","1983","1984","1985","1986","1987","1988","1989","1990","1991","1992","1993","1994","1995","1996","1997","1998","1999","2000","2001","2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012","2013","2014","2015","2016","2017","2018","2019","2020","2021" +"","hydroelectricity net generation (billion kWh)","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","" +"INTL.33-12-EURO-BKWH.A"," Europe","458.018","464.155","459.881","473.685","481.241","476.739","459.535","491.085","534.517","465.365","474.466","475.47","509.041","526.448","531.815","543.743","529.114164","543.845616","562.491501","566.861453","588.644662","584.806195","539.051405","503.7067","542.112443","542.974669","535.006084","538.449707","565.143111","561.761402","617.547148","540.926277","598.055253","629.44709","617.111295","613.079848","627.720566217","560.362524","616.5081462","606.5997419","644.1106599","628.1390143" +"INTL.33-12-ALB-BKWH.A"," Albania","2.919","3.018","3.093","3.167","3.241","3.315","3.365","3.979","3.713","3.846","2.82","3.483","3.187","3.281","3.733","4.162","5.669","4.978","4.872","5.231","4.548","3.519","3.477","5.117","5.411","5.319","4.951","2.76","3.759","5.201","7.49133","4.09068","4.67775","6.88941","4.67676","5.83605","7.70418","4.47975","8.46648","5.15394","5.281","8.891943" +"INTL.33-12-AUT-BKWH.A"," Austria","28.501","30.008","29.893","29.577","28.384","30.288","30.496","25.401","35.151","34.641","31.179","31.112","34.483","36.336","35.349","36.696","33.874","35.744","36.792","40.292","41.418","40.05","39.825","32.883","36.394","36.31","35.48","36.732","37.969","40.487","36.466","32.511","41.862","40.138","39.001","35.255","37.954","36.462","35.73","40.43655","41.9356096","38.75133" +"INTL.33-12-BEL-BKWH.A"," Belgium","0.274","0.377","0.325","0.331","0.348","0.282","0.339","0.425","0.354","0.3","0.263","0.226","0.338","0.252","0.342","0.335","0.237","0.30195","0.38511","0.338","0.455","0.437","0.356","0.245","0.314","0.285","0.355","0.385","0.406","0.325","0.298","0.193","0.353","0.376","0.289","0.314","0.367","0.268","0.3135","0.302","0.2669","0.3933" +"INTL.33-12-BIH-BKWH.A"," Bosnia and Herzegovina","--","--","--","--","--","--","--","--","--","--","--","--","3.374","2.343","3.424","3.607","5.104","4.608","4.511","5.477","5.043","5.129","5.215","4.456","5.919","5.938","5.798","3.961","4.818","6.177","7.946","4.343","4.173","7.164","5.876","5.495","5.585","3.7521","6.35382","6.02019","4.58","6.722" +"INTL.33-12-BGR-BKWH.A"," Bulgaria","3.674","3.58","3.018","3.318","3.226","2.214","2.302","2.512","2.569","2.662","1.859","2.417","2.042","1.923","1.453","2.291","2.89","2.726","3.066","2.725","2.646","1.72","2.172","2.999","3.136","4.294","4.196","2.845","2.796","3.435","4.98168","2.84328","3.14622","3.99564","4.55598","5.59845","3.8412","2.79972","5.09553","2.929499","2.820398","4.819205" +"INTL.33-12-HRV-BKWH.A"," Croatia","--","--","--","--","--","--","--","--","--","--","--","--","4.298","4.302","4.881","5.212","7.156","5.234","5.403","6.524","5.794","6.482","5.311","4.827","6.888","6.27","5.94","4.194","5.164","6.663","9.035","4.983","4.789","8.536","8.917","6.327","6.784","5.255","7.62399","5.87268","5.6624","7.1277" +"INTL.33-12-CYP-BKWH.A"," Cyprus","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" +"INTL.33-12-CZE-BKWH.A"," Czechia","--","--","--","--","--","--","--","--","--","--","--","--","--","1.355","1.445","1.982","1.949","1.68201","1.382","1.664","1.7404","2.033","2.467","1.369","1.999","2.356","2.525","2.068","2.004","2.405","2.775","1.95","2.107","2.704","1.909","1.779","1.983","1.852","1.615","1.98792","2.143884","2.40852" +"INTL.33-12-DNK-BKWH.A"," Denmark","0.03","0.031","0.028","0.036","0.028","0.027","0.029","0.029","0.032","0.027","0.027","0.026","0.028","0.027","0.033","0.03","0.019","0.019","0.02673","0.031","0.03","0.028","0.032","0.021","0.027","0.023","0.023","0.028","0.026","0.019","0.021","0.017","0.017","0.013","0.015","0.01803","0.01927","0.017871","0.0148621","0.0172171","0.017064","0.016295" +"INTL.33-12-EST-BKWH.A"," Estonia","--","--","--","--","--","--","--","--","--","--","--","--","0.001","0.001","0.003","0.002","0.002","0.003","0.004","0.004","0.005","0.007","0.006","0.013","0.022","0.022","0.014","0.021","0.028","0.032","0.027","0.029999","0.042","0.026","0.027","0.027","0.035","0.025999","0.0150003","0.0189999","0.03","0.0248" +"INTL.33-12-FRO-BKWH.A"," Faroe Islands","0.049","0.049","0.049","0.049","0.049","0.049","0.049","0.049","0.062","0.071","0.074","0.074","0.083","0.073","0.075","0.075","0.069564","0.075066","0.076501","0.069453","0.075262","0.075195","0.095535","0.08483","0.093443","0.097986","0.099934","0.103407","0.094921","0.091482","0.06676","0.092","0.099","0.091","0.121","0.132","0.105","0.11","0.107","0.102","0.11","0.11" +"INTL.33-12-FIN-BKWH.A"," Finland","10.115","13.518","12.958","13.445","13.115","12.211","12.266","13.658","13.229","12.9","10.75","13.065","14.956","13.341","11.669","12.796","11.742","12.11958","14.9","12.652","14.513","13.073","10.668","9.495","14.919","13.646","11.379","14.035","16.941","12.559","12.743","12.278001","16.666998","12.672","13.240001","16.583999","15.634127","14.609473","13.1369998","12.2454823","15.883","15.766" +"INTL.33-12-CSK-BKWH.A"," Former Czechoslovakia","4.8","4.2","3.7","3.9","3.2","4.3","4","4.853","4.355","4.229","3.919","3.119","3.602","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-12-SCG-BKWH.A"," Former Serbia and Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","11.23","10.395","11.016","12.071","14.266","12.636","12.763","13.243","11.88","12.326","11.633","9.752","11.01","11.912","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-12-YUG-BKWH.A"," Former Yugoslavia","27.868","25.044","23.295","21.623","25.645","24.363","27.474","25.98","25.612","23.256","19.601","18.929","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-12-FRA-BKWH.A"," France","68.253","70.358","68.6","67.515","64.01","60.248","60.953","68.623","73.952","45.744","52.796","56.277","68.313","64.3","78.057","72.196","64.43","63.151","61.479","71.832","66.466","73.888","59.992","58.567","59.276","50.965","55.741","57.029","63.017","56.428","61.945","45.184","59.099","71.042","62.993","54.876","60.094","49.389","64.485","56.913891","62.06191","58.856657" +"INTL.33-12-DEU-BKWH.A"," Germany","--","--","--","--","--","--","--","--","--","--","--","14.742","17.223","17.699","19.731","21.562","21.737","17.18343","17.044","19.451","21.515","22.506","22.893","19.071","20.866","19.442","19.808","20.957","20.239","18.841","20.678","17.323","21.331","22.66","19.31","18.664","20.214","19.985","17.694","19.731","18.322","19.252" +"INTL.33-12-DDR-BKWH.A"," Germany, East","1.658","1.718","1.748","1.683","1.748","1.758","1.767","1.726","1.719","1.551","1.389","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-12-DEUW-BKWH.A"," Germany, West","17.125","17.889","17.694","16.713","16.434","15.354","16.526","18.36","18.128","16.482","15.769","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--" +"INTL.33-12-GIB-BKWH.A"," Gibraltar","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" +"INTL.33-12-GRC-BKWH.A"," Greece","3.396","3.398","3.551","2.331","2.852","2.792","3.222","2.768","2.354","1.888","1.751","3.068","2.181","2.26","2.573","3.494","4.305","3.84318","3.68","4.546","3.656","2.076","2.772","4.718","4.625","4.967","5.806","2.565","3.279","5.32","7.431","3.998","4.387","6.337","4.464","5.782","5.543","3.962","5.035","3.9798","3.343687","5.909225" +"INTL.33-12-HUN-BKWH.A"," Hungary","0.111","0.166","0.158","0.153","0.179","0.153","0.152","0.167","0.167","0.156","0.176","0.192","0.156","0.164","0.159","0.161","0.205","0.21384","0.15345","0.179","0.176","0.184","0.192","0.169","0.203","0.2","0.184","0.208","0.211","0.226","0.184","0.215999","0.205999","0.207999","0.294001","0.226719","0.253308","0.213999","0.216","0.2129999","0.238","0.202379" +"INTL.33-12-ISL-BKWH.A"," Iceland","3.053","3.085","3.407","3.588","3.738","3.667","3.846","3.918","4.169","4.217","4.162","4.162","4.267","4.421","4.47","4.635","4.724","5.15493","5.565","5.987","6.292","6.512","6.907","7.017","7.063","6.949","7.22","8.31","12.303","12.156","12.509999","12.381999","12.213999","12.747001","12.554","13.541","13.091609","13.891929","13.679377","13.32911","12.9196201","13.5746171" +"INTL.33-12-IRL-BKWH.A"," Ireland","0.833","0.855","0.792","0.776","0.68","0.824","0.91","0.673","0.862","0.684","0.69","0.738","0.809","0.757","0.911","0.706","0.715","0.67122","0.907","0.838","0.838","0.59","0.903","0.592","0.624","0.625","0.717","0.66","0.959","0.893","0.593","0.699","0.795","0.593","0.701","0.798","0.674","0.685","0.687","0.87813","0.932656","0.750122" +"INTL.33-12-ITA-BKWH.A"," Italy","44.997","42.782","41.216","40.96","41.923","40.616","40.626","39.05","40.205","33.647","31.31","41.817","41.778","41.011","44.212","37.404","41.617","41.18697","40.808","44.911","43.763","46.343","39.125","33.303","41.915","35.706","36.624","32.488","41.207","48.647","50.506","45.36477","41.45625","52.24626","57.95955","45.08163","42.00768","35.83701","48.29913","45.31824","47.551784","44.739" +"INTL.33-12-XKS-BKWH.A"," Kosovo","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","0.075","0.119","0.154","0.104","0.095","0.142","0.149","0.139","0.243","0.177","0.27027","0.2079","0.262826","0.300635" +"INTL.33-12-LVA-BKWH.A"," Latvia","--","--","--","--","--","--","--","--","--","--","--","--","2.498","2.846","3.272","2.908","1.841","2.922","2.99","2.729","2.791","2.805","2.438","2.243","3.078","3.293","2.671","2.706","3.078","3.422","3.487998","2.8568","3.677","2.838","1.953","1.841","2.522819","4.355513","2.4170639","2.0958919","2.5840101","2.6889293" +"INTL.33-12-LTU-BKWH.A"," Lithuania","--","--","--","--","--","--","--","--","--","--","--","--","0.308","0.389","0.447","0.369","0.323","0.291","0.413","0.409","0.336","0.322","0.35","0.323","0.417","0.446193","0.393","0.417","0.398","0.42","0.535","0.475","0.419","0.516","0.395","0.346","0.45","0.597","0.427","0.34254","0.3006","0.3837" +"INTL.33-12-LUX-BKWH.A"," Luxembourg","0.086","0.095","0.084","0.083","0.088","0.071","0.084","0.101","0.097","0.072","0.07","0.083","0.069","0.066","0.117","0.087","0.059","0.082","0.114","0.084","0.119","0.117","0.098","0.078","0.103","0.093","0.11","0.116","0.131","0.105","0.104","0.061","0.095","0.114","0.104","0.095","0.111","0.082","0.089","0.10593","0.091602","0.1068" +"INTL.33-12-MLT-BKWH.A"," Malta","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0" +"INTL.33-12-MNE-BKWH.A"," Montenegro","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","1.733","1.271","1.524","2.05","2.723","1.192","1.462","2.479","1.734","1.476","1.825","1.014","1.693443","1.262781","0.867637","1.212652" +"INTL.33-12-NLD-BKWH.A"," Netherlands","0","0","0","0","0","0.003","0.003","0.001","0.002","0.037","0.119","0.079","0.119","0.091","0.1","0.087","0.079","0.09108","0.111","0.089","0.141","0.116","0.109","0.071","0.094","0.087","0.105","0.106","0.101","0.097","0.105","0.057","0.104389","0.11431","0.112202","0.0927","0.100078","0.060759","0.0723481","0.074182","0.0462851","0.0838927" +"INTL.33-12-MKD-BKWH.A"," North Macedonia","--","--","--","--","--","--","--","--","--","--","--","--","0.817","0.517","0.696","0.793","0.842","0.891","1.072","1.375","1.158","0.62","0.749","1.36","1.467","1.477","1.634","1","0.832","1.257","2.407","1.419","1.031","1.568","1.195","1.846","1.878","1.099","1.773","1.15236","1.277144","1.451623" +"INTL.33-12-NOR-BKWH.A"," Norway","82.717","91.876","91.507","104.704","104.895","101.464","95.321","102.341","107.919","117.369","119.933","109.032","115.505","118.024","110.398","120.315","102.823","108.677","114.546","120.237","140.4","119.258","128.078","104.425","107.693","134.331","118.175","132.319","137.654","124.03","116.257","119.78","141.189","127.551","134.844","136.662","142.244","141.651","138.202","123.66288","141.69","144" +"INTL.33-12-POL-BKWH.A"," Poland","2.326","2.116","1.528","1.658","1.394","1.833","1.534","1.644","1.775","1.593","1.403","1.411","1.492","1.473","1.716","1.868","1.912","1.941","2.286","2.133","2.085","2.302","2.256","1.654","2.06","2.179","2.022","2.328","2.13","2.351","2.9","2.313","2.02","2.421","2.165","1.814","2.117","2.552","1.949","1.93842","2.118337","2.339192" +"INTL.33-12-PRT-BKWH.A"," Portugal","7.873","4.934","6.82","7.897","9.609","10.512","8.364","9.005","12.037","5.72","9.065","8.952","4.599","8.453","10.551","8.26","14.613","12.97395","12.853","7.213","11.21","13.894","7.722","15.566","9.77","4.684","10.892","9.991","6.73","8.201","15.954","11.423","5.589","13.652","15.471","8.615","15.608","5.79","12.316","8.6526","12.082581","11.846464" +"INTL.33-12-ROU-BKWH.A"," Romania","12.506","12.605","11.731","9.934","11.208","11.772","10.688","11.084","13.479","12.497","10.87","14.107","11.583","12.64","12.916","16.526","15.597","17.334","18.69","18.107","14.63","14.774","15.886","13.126","16.348","20.005","18.172","15.806","17.023","15.379","19.684","14.581","11.945","14.807","18.618","16.467","17.848","14.349","17.48736","15.580622","15.381243","17.376933" +"INTL.33-12-SRB-BKWH.A"," Serbia","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","10.855","9.937","9.468","10.436","11.772","8.58","9.193","10.101","10.893","9.979","10.684","9.061","10.53261","9.457175","9.034496","11.284232" +"INTL.33-12-SVK-BKWH.A"," Slovakia","--","--","--","--","--","--","--","--","--","--","--","--","--","3.432","4.311","4.831","4.185","4.023","4.224","4.429","4.569","4.878","5.215","3.4452","4.059","4.592","4.355","4.406","4","4.324","5.184","3.211","3.687","4.329","3.762","3.701","4.302","4.321","3.506","4.27383","4.517","4.17" +"INTL.33-12-SVN-BKWH.A"," Slovenia","--","--","--","--","--","--","--","--","--","--","--","--","3.379","2.974","3.348","3.187","3.616","3.046","3.4","3.684","3.771","3.741","3.265","2.916","4.033","3.426","3.555","3.233","3.978","4.666","4.452","3.506","3.841","4.562","6.011","3.75","4.443","3.814","4.643","4.43421","4.93406","4.711944" +"INTL.33-12-ESP-BKWH.A"," Spain","29.16","21.64","25.99","26.696","31.088","30.895","26.105","27.016","34.76","19.046","25.16","27.01","18.731","24.133","27.898","22.881","39.404","34.43","33.665","22.634","29.274","40.617","22.691","40.643","31.359","18.209","25.699","27.036","23.13","26.147","41.576","30.07","20.192","36.45","38.815","27.656","35.77","18.007","33.743","24.23025","30.507","29.626" +"INTL.33-12-SWE-BKWH.A"," Sweden","58.133","59.006","54.369","62.801","67.106","70.095","60.134","70.95","69.016","70.911","71.778","62.603","73.588","73.905","58.508","67.421","51.2226","68.365","74.25","70.974","77.798","78.269","65.696","53.005","59.522","72.075","61.106","65.497","68.378","65.193","66.279","66.047","78.333","60.81","63.227","74.734","61.645","64.651","61.79","64.46583","71.6","71.086" +"INTL.33-12-CHE-BKWH.A"," Switzerland","32.481","35.13","35.974","35.069","29.871","31.731","32.576","34.328","35.437","29.477","29.497","31.756","32.373","35.416","38.678","34.817","28.458","33.70257","33.136","37.104","33.854","38.29","32.323","31.948","30.938","28.664","28.273","32.362","33.214","32.833","33.261","29.906","35.783","35.628","35.122","35.378","31.984","31.47968","32.095881","35.156989","37.867647","36.964485" +"INTL.33-12-TUR-BKWH.A"," Turkiye","11.159","12.308","13.81","11.13","13.19","11.822","11.637","18.314","28.447","17.61","22.917","22.456","26.302","33.611","30.28","35.186","40.07","39.41784","41.80671","34.33","30.57","23.77","33.346","34.977","45.623","39.165","43.802","35.492","32.937","35.598","51.423001","51.154999","56.668998","58.225","39.750001","65.856","66.685883","57.823851","59.490211","88.2094218","78.094369","55.1755392" +"INTL.33-12-GBR-BKWH.A"," United Kingdom","3.921","4.369","4.543","4.548","3.992","4.08","4.767","4.13","4.915","4.732","5.119","4.534","5.329","4.237","5.043","4.79","3.359","4.127","5.117","5.336","5.085","4.055","4.78787","3.22767","4.844","4.92149","4.59315","5.0773","5.14119","5.22792","3.59138","5.69175","5.30965","4.70147","5.8878","6.29727","5.370412217","5.88187","5.44327","5.84628","6.75391","5.0149" +""," Eurasia","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","" +"INTL.33-12-MDA-BKWH.A"," Moldova","--","--","--","--","--","--","--","--","--","--","--","--","0.255","0.371","0.275","0.321","0.362","0.378","0.387","0.363","0.392","0.359","0.348","0.358","0.35","0.359","0.365","0.354","0.385","0.354","0.403","0.348","0.266","0.311","0.317","0.265","0.228","0.282","0.27324","0.29799","0.276","0.316" +"INTL.33-12-UKR-BKWH.A"," Ukraine","--","--","--","--","--","--","--","--","--","--","--","--","7.725","10.929","11.997","9.853","8.546","9.757","15.756","14.177","11.161","11.912","9.531","9.146","11.635","12.239","12.757","10.042","11.397","11.817","13.02","10.837","10.374","13.663","8.393","5.343","7.594","8.856","10.32372","6.5083","7.5638","10.3326" \ No newline at end of file diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index a9e111ea..d922a753 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -344,6 +344,7 @@ rule build_hydro_profile: params: hydro=config_provider("renewable", "hydro"), countries=config_provider("countries"), + snapshots=config_provider("snapshots"), input: country_shapes=resources("country_shapes.geojson"), eia_hydro_generation="data/eia_hydro_annual_generation.csv", diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index ce8f3a4c..99f15427 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -77,6 +77,8 @@ def get_eia_annual_hydro_generation(fn, countries, capacities=False): fn, skiprows=2, index_col=1, na_values=[" ", "--"], decimal="," ).iloc[1:, 1:] df.index = df.index.str.strip() + df.columns = df.columns.astype(int) + df = df.astype(float) former_countries = { "Former Czechoslovakia": dict( @@ -100,7 +102,7 @@ def get_eia_annual_hydro_generation(fn, countries, capacities=False): } for k, v in former_countries.items(): - period = [str(i) for i in range(v["start"], v["end"] + 1)] + period = [i for i in range(v["start"], v["end"] + 1)] ratio = df.loc[v["countries"]].T.dropna().sum() ratio /= ratio.sum() for country in v["countries"]: @@ -128,7 +130,7 @@ def get_eia_annual_hydro_generation(fn, countries, capacities=False): def correct_eia_stats_by_capacity(eia_stats, fn, countries, baseyear=2019): cap = get_eia_annual_hydro_generation(fn, countries, capacities=True) - ratio = cap / cap.loc[str(baseyear)] + ratio = cap / cap.loc[baseyear] eia_stats_corrected = eia_stats / ratio to_keep = ["AL", "AT", "CH", "DE", "GB", "NL", "RS", "RO", "SK"] to_correct = eia_stats_corrected.columns.difference(to_keep) @@ -137,9 +139,10 @@ def correct_eia_stats_by_capacity(eia_stats, fn, countries, baseyear=2019): def approximate_missing_eia_stats(eia_stats, runoff_fn, countries): runoff = pd.read_csv(runoff_fn, index_col=0).T[countries] + runoff.index = runoff.index.astype(int) - # fix ES, PT data points - runoff.loc["1978", ["ES", "PT"]] = runoff.loc["1979", ["ES", "PT"]] + # fix outliers; exceptional floods in 1977-1979 in ES & PT + runoff.loc[1978, ["ES", "PT"]] = runoff.loc[1979, ["ES", "PT"]] runoff_eia = runoff.loc[eia_stats.index] From 8aa4b5b558a2976781de2b307d450f0d68c45eaf Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 14:09:39 +0100 Subject: [PATCH 445/591] build_heat_totals: use more years for regression --- scripts/build_heat_totals.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/scripts/build_heat_totals.py b/scripts/build_heat_totals.py index e49ae635..d0dab987 100644 --- a/scripts/build_heat_totals.py +++ b/scripts/build_heat_totals.py @@ -15,17 +15,22 @@ idx = pd.IndexSlice def approximate_heat_demand(energy_totals, hdd): - if isinstance(hdd, str): - hdd = pd.read_csv(hdd, index_col=0).T - hdd.index = hdd.index.astype(int) + + countries = hdd.columns demands = {} for kind, sector in product(["total", "electricity"], ["services", "residential"]): - row = idx[:, 2007:2015] + # reduced number years (2007-2021) for regression because it implicitly + # assumes a constant building stock + row = idx[:, 2007:2021] col = f"{kind} {sector} space" demand = energy_totals.loc[row, col].unstack(0) + # ffill for GB in 2020- and bfill for CH 2007-2009 + # compromise to have more years available for the fit + demand = demand.ffill(axis=0).bfill(axis=0) + demand_approx = {} for c in countries: @@ -62,16 +67,15 @@ def approximate_heat_demand(energy_totals, hdd): if __name__ == "__main__": if "snakemake" not in globals(): - from helper import mock_snakemake + from _helpers import mock_snakemake - snakemake = mock_snakemake("build_energy_totals") + snakemake = mock_snakemake("build_heat_totals") hdd = pd.read_csv(snakemake.input.hdd, index_col=0).T + hdd.index = hdd.index.astype(int) energy_totals = pd.read_csv(snakemake.input.energy_totals, index_col=[0, 1]) - countries = hdd.columns - heat_demand = approximate_heat_demand(energy_totals, hdd) heat_demand.to_csv(snakemake.output.heat_totals) From 090792c9ec7583cf2f2f8ad7ee839da636f7a411 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:10:21 +0000 Subject: [PATCH 446/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data/eia_hydro_annual_capacity.csv | 2 +- data/eia_hydro_annual_generation.csv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/eia_hydro_annual_capacity.csv b/data/eia_hydro_annual_capacity.csv index 8092096d..42c0cc6f 100644 --- a/data/eia_hydro_annual_capacity.csv +++ b/data/eia_hydro_annual_capacity.csv @@ -50,4 +50,4 @@ Report generated on: 03-14-2024 13:39:49 "INTL.33-7-GBR-MK.A"," United Kingdom","2.451","2.451","2.451","2.721","4.188","4.19","4.192","4.197","4.196","1.424","1.11","1.415","1.423","1.425","1.425","1.432","1.455","1.488","1.475","1.477","1.485","1.629","1.59","1.486","1.499","1.501","1.515","1.522","1.626","1.638","1.637","1.673","1.693","1.709","1.73","1.777","1.836","1.873","1.878","1.878","1.879","1.88" ""," Eurasia","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","" "INTL.33-7-MDA-MK.A"," Moldova","--","--","--","--","--","--","--","--","--","--","--","--","0.064","0.064","0.064","0.056","0.056","0.064","0.064","0.064","0.064","0.06","0.06","0.06","0.059","0.059","0.056","0.056","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.064","0.076","0.076" -"INTL.33-7-UKR-MK.A"," Ukraine","--","--","--","--","--","--","--","--","--","--","--","--","4.705","4.706","4.706","4.706","4.706","4.706","4.706","4.7","4.7","4.731","4.758","4.766","4.781","4.717","4.746","4.731","4.798","4.795","4.596","4.607","4.608","4.632","4.665","4.697","4.658","4.668","4.668","4.668","4.666","4.43" \ No newline at end of file +"INTL.33-7-UKR-MK.A"," Ukraine","--","--","--","--","--","--","--","--","--","--","--","--","4.705","4.706","4.706","4.706","4.706","4.706","4.706","4.7","4.7","4.731","4.758","4.766","4.781","4.717","4.746","4.731","4.798","4.795","4.596","4.607","4.608","4.632","4.665","4.697","4.658","4.668","4.668","4.668","4.666","4.43" diff --git a/data/eia_hydro_annual_generation.csv b/data/eia_hydro_annual_generation.csv index d4e64a31..b228ddc6 100644 --- a/data/eia_hydro_annual_generation.csv +++ b/data/eia_hydro_annual_generation.csv @@ -50,4 +50,4 @@ Report generated on: 03-14-2024 13:40:38 "INTL.33-12-GBR-BKWH.A"," United Kingdom","3.921","4.369","4.543","4.548","3.992","4.08","4.767","4.13","4.915","4.732","5.119","4.534","5.329","4.237","5.043","4.79","3.359","4.127","5.117","5.336","5.085","4.055","4.78787","3.22767","4.844","4.92149","4.59315","5.0773","5.14119","5.22792","3.59138","5.69175","5.30965","4.70147","5.8878","6.29727","5.370412217","5.88187","5.44327","5.84628","6.75391","5.0149" ""," Eurasia","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","" "INTL.33-12-MDA-BKWH.A"," Moldova","--","--","--","--","--","--","--","--","--","--","--","--","0.255","0.371","0.275","0.321","0.362","0.378","0.387","0.363","0.392","0.359","0.348","0.358","0.35","0.359","0.365","0.354","0.385","0.354","0.403","0.348","0.266","0.311","0.317","0.265","0.228","0.282","0.27324","0.29799","0.276","0.316" -"INTL.33-12-UKR-BKWH.A"," Ukraine","--","--","--","--","--","--","--","--","--","--","--","--","7.725","10.929","11.997","9.853","8.546","9.757","15.756","14.177","11.161","11.912","9.531","9.146","11.635","12.239","12.757","10.042","11.397","11.817","13.02","10.837","10.374","13.663","8.393","5.343","7.594","8.856","10.32372","6.5083","7.5638","10.3326" \ No newline at end of file +"INTL.33-12-UKR-BKWH.A"," Ukraine","--","--","--","--","--","--","--","--","--","--","--","--","7.725","10.929","11.997","9.853","8.546","9.757","15.756","14.177","11.161","11.912","9.531","9.146","11.635","12.239","12.757","10.042","11.397","11.817","13.02","10.837","10.374","13.663","8.393","5.343","7.594","8.856","10.32372","6.5083","7.5638","10.3326" From 5b1575cb50e690e7130190bca22adba9ef568772 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 14:18:26 +0100 Subject: [PATCH 447/591] build_hydro: change decimal to '.' from ',' with updated data --- scripts/build_hydro_profile.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 99f15427..ebadd047 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -74,11 +74,10 @@ cc = coco.CountryConverter() def get_eia_annual_hydro_generation(fn, countries, capacities=False): # in billion kWh/a = TWh/a df = pd.read_csv( - fn, skiprows=2, index_col=1, na_values=[" ", "--"], decimal="," + fn, skiprows=2, index_col=1, na_values=[" ", "--"] ).iloc[1:, 1:] df.index = df.index.str.strip() df.columns = df.columns.astype(int) - df = df.astype(float) former_countries = { "Former Czechoslovakia": dict( From f84707ba38ee5fdfd9b95a278f00f7ec3035a883 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 14:30:50 +0100 Subject: [PATCH 448/591] drop_leap_days already in renewable profiles --- rules/build_electricity.smk | 4 ++++ scripts/build_hydro_profile.py | 7 ++++++- scripts/build_line_rating.py | 7 ++++--- scripts/build_renewable_profiles.py | 6 ++++-- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index d922a753..edf5fca3 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -267,6 +267,7 @@ def input_ua_md_availability_matrix(w): rule build_renewable_profiles: params: snapshots=config_provider("snapshots"), + drop_leap_day=config_provider("enable", "drop_leap_day"), renewable=config_provider("renewable"), input: unpack(input_ua_md_availability_matrix), @@ -345,6 +346,7 @@ rule build_hydro_profile: hydro=config_provider("renewable", "hydro"), countries=config_provider("countries"), snapshots=config_provider("snapshots"), + drop_leap_day=config_provider("enable", "drop_leap_day"), input: country_shapes=resources("country_shapes.geojson"), eia_hydro_generation="data/eia_hydro_annual_generation.csv", @@ -370,6 +372,7 @@ rule build_hydro_profile: rule build_line_rating: params: snapshots=config_provider("snapshots"), + drop_leap_day=config_provider("enable", "drop_leap_day"), input: base_network=resources("networks/base.nc"), cutout=lambda w: "cutouts/" @@ -413,6 +416,7 @@ rule add_electricity: length_factor=config_provider("lines", "length_factor"), scaling_factor=config_provider("load", "scaling_factor"), countries=config_provider("countries"), + snapshots=config_provider("snapshots"), renewable=config_provider("renewable"), electricity=config_provider("electricity"), conventional=config_provider("conventional"), diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index ebadd047..510bc6fa 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -174,7 +174,12 @@ if __name__ == "__main__": set_scenario_config(snakemake) params_hydro = snakemake.params.hydro - cutout = atlite.Cutout(snakemake.input.cutout) + + time = pd.date_range(freq="h", **snakemake.params.snapshots) + if snakemake.params.drop_leap_day: + time = time[~((time.month == 2) & (time.day == 29))] + + cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) countries = snakemake.params.countries country_shapes = ( diff --git a/scripts/build_line_rating.py b/scripts/build_line_rating.py index 5b4642d1..794638d2 100755 --- a/scripts/build_line_rating.py +++ b/scripts/build_line_rating.py @@ -146,10 +146,11 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - snapshots = snakemake.params.snapshots - n = pypsa.Network(snakemake.input.base_network) - time = pd.date_range(freq="h", **snapshots) + time = pd.date_range(freq="h", **snakemake.params.snapshots) + if snakemake.params.drop_leap_day: + time = time[~((time.month == 2) & (time.day == 29))] + cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) da = calculate_line_rating(n, cutout) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index e1576850..88057fb6 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -227,9 +227,11 @@ if __name__ == "__main__": else: client = None - sns = pd.date_range(freq="h", **snakemake.params.snapshots) + time = pd.date_range(freq="h", **snakemake.params.snapshots) + if snakemake.params.drop_leap_day: + time = time[~((time.month == 2) & (time.day == 29))] - cutout = atlite.Cutout(snakemake.input.cutout).sel(time=sns) + cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) regions = gpd.read_file(snakemake.input.regions) assert not regions.empty, ( f"List of regions in {snakemake.input.regions} is empty, please " From f695b63732d6e8a56716775c8b5c3a361ba36a53 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 14:31:18 +0100 Subject: [PATCH 449/591] add more documentation --- config/config.default.yaml | 2 +- doc/configtables/load.csv | 1 + rules/build_sector.smk | 1 - scripts/build_energy_totals.py | 2 +- ...build_population_weighted_energy_totals.py | 3 +- scripts/build_shipping_demand.py | 2 +- scripts/new-energy-totals.csv | 34 +++++++++++++++++++ 7 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 scripts/new-energy-totals.csv diff --git a/config/config.default.yaml b/config/config.default.yaml index ae45234c..da2e20f1 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -239,7 +239,7 @@ renewable: flatten_dispatch: false flatten_dispatch_buffer: 0.2 clip_min_inflow: 1.0 - eia_norm_year: 2013 + eia_norm_year: false eia_correct_by_capacity: false eia_approximate_missing: false diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index 0a62aeef..b245268f 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -4,3 +4,4 @@ time_shift_for_large_gaps,string,string,"Periods which are used for copying time manual_adjustments,bool,"{true, false}","Whether to adjust the load data manually according to the function in :func:`manual_adjustment`." scaling_factor,--,float,"Global correction factor for the load time series." fixed_year,--,Year or False,"To specify a fixed year for the load time series that deviates from the snapshots' year" +supplement_missing_data_artificially,bool,"{true, false}","Whether to supplement missing data for selected time period should be supplemented by artificial data from https://zenodo.org/record/7070438/files/demand_hourly.csv." \ No newline at end of file diff --git a/rules/build_sector.smk b/rules/build_sector.smk index e41d0224..14226ef8 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -908,7 +908,6 @@ rule prepare_sector_network: else [] ), network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), - energy_totals_name=resources("energy_totals.csv"), eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition", pop_weighted_energy_totals=resources( "pop_weighted_energy_totals_s{simpl}_{clusters}.csv" diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 48df4625..01532872 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -750,7 +750,7 @@ def build_transport_data(countries, population, idees): missing = transport_data.index[transport_data["average fuel efficiency"].isna()] if not missing.empty: logger.info( - f"Missing data on fuel efficiency from:\n{list(missing)}\nFilling gapswith averaged data." + f"Missing data on fuel efficiency from:\n{list(missing)}\nFilling gaps with averaged data." ) fill_values = transport_data["average fuel efficiency"].mean() diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index b26f289d..c2be19a9 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -15,8 +15,9 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_population_weighted_energy_totals", + kind='energy', simpl="", - clusters=48, + clusters=60, ) set_scenario_config(snakemake) diff --git a/scripts/build_shipping_demand.py b/scripts/build_shipping_demand.py index 58def027..b50cd316 100644 --- a/scripts/build_shipping_demand.py +++ b/scripts/build_shipping_demand.py @@ -18,7 +18,7 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "build_shipping_demand_per_node", + "build_shipping_demand", simpl="", clusters=48, ) diff --git a/scripts/new-energy-totals.csv b/scripts/new-energy-totals.csv new file mode 100644 index 00000000..78ba6736 --- /dev/null +++ b/scripts/new-energy-totals.csv @@ -0,0 +1,34 @@ +country,electricity residential space,total residential space,total residential water,electricity residential water,total residential cooking,electricity residential cooking,total residential,electricity residential,derived heat residential,thermal uses residential,total services space,electricity services space,total services water,electricity services water,total services cooking,electricity services cooking,total services,electricity services,derived heat services,thermal uses services,total agriculture electricity,total agriculture heat,total agriculture machinery,total agriculture,total road,electricity road,total two-wheel,total passenger cars,electricity passenger cars,total other road passenger,electricity other road passenger,total light duty road freight,electricity light duty road freight,total heavy duty road freight,total rail,electricity rail,total rail passenger,electricity rail passenger,total rail freight,electricity rail freight,total aviation passenger,total aviation freight,total domestic aviation passenger,total international aviation passenger,total domestic aviation freight,total international aviation freight,total domestic aviation,total international aviation,total domestic navigation,total international navigation +AL,0.5570465743624181,2.868681023831782,0.9246366122728509,0.4701405463928116,0.7560298250278052,0.606309006828873,6.745434890000001,3.8599970000000003,,,0.8492947400612103,0.24188377504306646,0.19063435423096936,0.1082113698760542,0.24955086644902696,0.190340216176473,2.2211439200000003,1.4779985500000001,,,,,,,8.933037890000001,0.0,0.11476078758153294,5.255099996394696,0.0,0.43826272462667554,0.0,1.0066258503715193,0.0,2.1182885310255757,0.03566921000000001,0.0,0.026867054339929548,0.0,0.008802155660070457,0.0,0.23558664812723476,0.015249191872765277,0.0,0.23558664812723476,0.0,0.015249191872765277,0.0,0.25083584000000003,0.38266189000000006,0.23777535000000002 +AT,3.8347980364339187,52.728795606720304,9.042762942245817,1.6580654856850694,3.332605848035772,2.2140159394525,74.4128059879979,17.31873449075142,8.985794565462129,65.16773835369318,17.423168106040677,1.362361756513761,3.4703813442929237,0.2967617406747894,3.4964403032216045,2.3458829314999434,33.49193062767192,13.244905252570849,9.882817057376736,24.839638062603143,0.6497150410629878,3.8719030223442585,1.7388785775882416,6.260496640995489,88.04632651098169,0.035087453918020005,0.6026064240302123,47.145477443307264,0.010621583280449667,3.067508471104808,0.02013826679946008,5.385434496257479,0.003947974868709491,31.84529967628193,3.384639661479662,2.8930267787407162,2.332832737694036,1.971964325107237,1.0518069237856262,0.9210624536334792,7.604475261435951,0.3130344308815537,0.26550445600104483,7.338970805434905,0.07206205482497326,0.24097237605658042,0.3375665108260181,7.579943181491485,0.058055683482739553,0.23600759000000002 +BA,0.9551423259051094,8.062615381913417,2.2035460750967655,0.8061285279384439,1.4999498844734496,1.039610369496632,15.49027994803239,6.61856060561295,,,2.075880307094079,0.37511972750507755,0.3986027383060623,0.16781704177400622,0.46097540282364163,0.2951846191943365,4.372938190104563,2.2921190692934506,,,,,,,10.403943245213432,0.0,0.1336571875633523,6.120399665114565,0.0,0.5104266398122862,0.0,1.172375886612297,0.0,2.4670838661109293,0.2691038049081697,0.22364645608190642,0.20269657078330564,0.1718117268416388,0.06640723412486403,0.051834729240267635,0.22862718311632196,0.01479871550610001,0.0,0.22862718311632196,0.0,0.01479871550610001,0.0,0.24342589862242198,0.05081711523682938,0.0511435984699603 +BE,2.815051564451901,72.00315684834005,14.758606504598777,1.9245397162358575,5.61762658049057,2.123765047409,104.53126486079485,19.81013300307489,0.048333322074790706,92.47214768445166,35.55025666623682,6.159088599308961,4.553234776118736,1.3005782934779981,4.296286602056132,1.7511206036264235,57.027872149578414,22.25434577090179,0.7699977716616743,45.32121766089195,1.2652057097802312,6.510654609861979,2.1504989713552063,9.926359290997418,93.22107248215386,0.01074409225014649,0.6477429921079886,54.179087820705185,0.006636212751625691,3.954966803176898,0.001991249371656604,10.47276574878302,0.0015859584461520306,23.966509117380756,2.2359228430787947,1.596953398545387,1.7366935264699335,1.306970119159899,0.4992293166088615,0.2899832793854877,11.903404936264774,2.9443700871166114,0.0,11.903404936264774,0.5794491728255937,2.3649209142910177,0.5794491728255937,14.268325850555792,1.822780948768488,71.59805975 +BG,1.0366899653005102,13.774445984268725,5.032599359348841,2.50096431277225,2.8263907739201346,2.446346362124563,26.126347522623533,10.536998125106878,3.70225381151711,21.738366989691684,3.6161635069149147,1.317290338927257,1.4876301353881975,0.8459255010716765,1.614166101394505,1.2802729496644545,11.214107236902933,7.954580847599141,1.1947324162166162,7.013424737247175,0.2157562658354375,1.238388279337861,0.8037223126895519,2.257866857862851,27.913508544418903,0.05240401618919764,0.2678003482560851,18.16930433603284,0.0,2.6753054767672606,0.05240401618919764,1.723251062925399,0.0,5.077847320437322,0.36999955326892575,0.19499962550233102,0.2595248907228583,0.1337123426290272,0.11047466254606741,0.06128728287330383,1.9735489165680373,0.0214510834319626,0.06685311111111157,1.9066958054569259,0.01455716249528969,0.0068939209366729115,0.08141027360640127,1.9135897263935986,0.0,1.0494446800000001 +CH,4.388888888888889,51.52777777777778,8.944444444444445,2.388888888888889,2.611111111111111,1.3611111111111112,72.58333333333333,18.777777777777775,,,21.5,1.1666666666666667,2.8055555555555554,0.19444444444444442,0.6388888888888888,0.6388888888888888,40.0,17.055555555555554,,,,,,,55.888888888888886,0.0,0.7179923543283743,32.87814329403942,0.0,2.7419582254567123,0.0,6.297879959411784,0.0,13.25291505565259,3.1666666666666665,3.1666666666666665,2.3852225886072858,2.432725641458858,0.7814440780593807,0.7339410252078085,17.617703597787695,1.1600741799900811,0.8685212443581152,16.749182353429582,0.07592320008632922,1.0841509799037519,0.9444444444444444,17.833333333333332,0.4444444444444445,0.0 +CZ,2.5725233632931075,62.57273499598758,10.288206369245467,2.9111285854172344,5.349291874222479,2.9169812116183698,83.99741666322201,14.715973413943496,13.888879856159699,78.24427707959727,20.246784369915833,4.388583048588386,3.0235451499346557,0.9434718391306539,3.505353453229548,1.7737748387302745,34.29840057384516,14.78664045488378,5.310847457419239,27.053057440415177,0.6941273932306512,4.054135056204236,2.4003802728676513,7.148642722302538,63.503988188281525,0.08911029892052649,0.6865202837197137,30.92628881993422,0.0007819669138069432,3.866800834894914,0.08831777854219773,5.7476679804286555,0.0,22.276710269304015,2.5098763617700213,1.491101348077621,1.957212181581117,1.1043425069361408,0.5526641801889038,0.38675884114148024,3.4758788630067836,0.048572629407252134,0.056765346606964515,3.419113516399819,0.019945792240296925,0.028626837166955205,0.07671113884726144,3.447740353566774,0.023888852908381327,0.0 +DE,23.552538648485736,482.88953556791756,88.86181482888813,9.341725122373857,41.094774831600795,14.516493828941883,694.2861367421355,136.00002715231648,51.24612134236524,614.0643012925772,200.1083899771467,8.177528100639465,38.567939444757855,8.148137272139993,48.02923585230634,20.88733594674748,388.35703665770825,141.5218730593723,16.87389225775031,291.39267527735336,7.53469558411125,5.474391021838289,1.4190403036639783,14.42812690961352,600.5438784206764,0.11224182554399796,5.370903791988889,380.78585774165197,0.0804737905883431,18.892615204428267,0.014714641214532026,28.660484589683342,0.015353321394055243,166.83401709292394,15.93416884756733,11.885002372832927,11.472824304223883,8.279888081535278,4.461344543343446,3.605114291297649,91.38069880171732,13.41045647623245,7.896669996323121,83.4840288053942,2.19924733222008,11.211209144012372,10.095917328543202,94.69523794940658,3.3722220527550077,26.697188350000005 +DK,0.7013376012077638,33.93012445800281,7.368540509780002,0.5229211600849933,3.1224115802390884,2.437647648641987,50.639691342206994,10.307073119763176,19.141944444444412,44.46958545008379,11.568860496650082,0.7165794765906534,1.9268567416141313,0.4139126319754398,2.107350856421504,1.6568129470533832,22.96597151274313,10.221030677425023,8.886388888888847,15.964433033531657,1.6065828331780032,4.6006732485303825,2.958335976083448,9.165592057791836,42.126010180586306,0.006041443591563428,0.26907068768936326,23.38606046077933,0.005426936489976022,3.9158027200781587,0.0,5.764536143667914,0.0006145071015874062,8.79054016837154,1.3112062796097734,0.3861092120959323,1.201322441895927,0.35393692637112534,0.10988383771384651,0.03217228572480684,10.062240435459456,0.3052602112787246,0.5934322985915401,9.468808136867919,0.10206631066816502,0.20319390061055956,0.6954986092597052,9.672002037478478,1.978361573681062,7.339855820000001 +EE,0.11231606763657928,7.615319503233344,1.5105449935831652,0.06137687617864419,0.7305183637351055,0.6392485833424982,10.871312066259437,1.8649831545295248,3.8389405197191633,9.856556620105813,2.8051300129906593,0.7294467788998327,0.3759461883671719,0.16897479263456983,0.43229161868604543,0.3654118725947719,4.8619944419222145,2.5288861940995093,1.1860593158990447,3.6224949714927197,0.17269894009588554,0.7062927576664825,0.4019989426098384,1.2809906403722064,8.143920002436563,0.02196621718242599,0.02187321389494755,5.041673827103431,0.0035133698706650515,0.9394047336082759,0.018423149598824944,0.6543028641167076,2.969771293599253e-05,1.4866653637132001,0.3473335032636153,0.04203126411907797,0.08800246779439479,0.04203126411907797,0.2593310354692205,0.0,0.32494722922299063,0.009489420040482168,0.0,0.32494722922299063,0.0036550739486526196,0.005834346091829548,0.0036550739486526196,0.33078157531482016,0.04694670715427129,4.740620600000001 +ES,10.794125129618664,71.26452543322868,39.68527650785515,7.710514219460869,19.26597649255715,8.828493562332296,177.196549581737,74.63098166927618,0.0,131.8776230960182,34.390226550633635,5.784912430114415,14.00729551399568,6.8886787516288885,17.98020571548081,13.01444004144452,115.94028841537886,75.5600175062191,0.0,75.67658371390513,3.798490176657542,20.504156811235546,10.361953239126692,34.664600227019776,295.6964784476745,0.008958749867787469,5.271025477457057,177.9796367179715,0.006198765274153721,10.784071123614806,0.0,20.279070030269107,0.0027599845936337485,81.38267509836203,8.270129202825443,4.551941091567911,7.174411141940354,4.18254627330064,1.095718060885089,0.36939481826726994,58.78529713592237,1.0458142160063002,18.097222294891036,40.68807484103132,0.33629527208914706,0.7095189439171532,18.433517566980182,41.39759378494848,5.86721442260112,84.04543941000001 +FI,7.848535711327018,41.84350237788999,9.048520920884483,3.443099269456141,2.9395617816882234,2.8792251386947934,60.826832141117144,21.50989869058375,18.587994476407626,53.92184520851802,21.23055041955415,6.199986054777693,2.553779457989475,0.9989674641957111,2.737139467312127,2.6900543568450637,34.04765319297288,17.50312586133877,12.247279309978593,26.808838116560455,1.2798819960077403,7.441003309894633,1.9312393542030517,10.652124660105425,45.56549617623142,0.0019365717691190252,0.5223209306867633,26.118742999170177,0.0007992579455364848,3.2601013702649593,0.00016885440537935242,5.613312604425437,0.0006476900733945322,10.051018271684086,1.1047159761512422,0.7330519889163917,0.6084665070352008,0.5419802858183081,0.4962494691160414,0.19107170309808352,7.731241694301903,0.3876090573520712,1.4438906650320935,6.287351029269809,0.11591836963879651,0.2716906877132747,1.55980903467089,6.559041716983084,1.725813385303544,1.5172963200000003 +FR,36.34821295388092,304.3090830974361,74.10444863335236,20.89120031251567,42.04728767502008,19.96798113754325,503.553879238341,167.90380216073933,14.323611111111111,421.0509096549809,149.2072481280514,29.02123818481345,25.328465674571646,12.10488257238001,28.51040521266642,17.00244127422052,285.9163571402345,142.24734181479553,8.505277777777804,216.87393093116245,7.478237257126606,32.74985084813704,20.230248718717654,60.4583368239813,477.2711666499798,0.17960126429470955,6.464992469847664,252.13117399671086,0.07795214668519337,21.88511370979885,0.039237383416606084,91.90030834156023,0.061631171267770395,104.88957813206223,12.134370941891715,10.168257793403882,10.262575388236112,8.653518950028449,1.8717955536556061,1.5147388433754336,71.22571967077627,3.5990187474665083,19.982431345628665,51.2432883251476,1.4447624710282905,2.154256276438218,21.427193816656956,53.397544601585814,5.826683163334846,26.200994400000006 +GB,32.35436698812953,318.9482399097387,79.0068899383846,11.692921151505214,20.777464730965892,3.4829778546191315,480.6012101626519,113.45010172801696,0.603890281538269,419.06137321331204,111.80304633929093,16.901263938070077,21.670713737923748,9.433929352734362,25.136145179539948,11.42081966062867,217.22824016750891,97.6278626859339,4.641112795545814,162.61403696376797,3.2166577319321257,5.143442067057801,2.6425900548485233,11.00268985383845,430.58518629173466,0.046201812762040446,1.9853577192078395,261.8768230625204,0.017483920193319114,13.879178870387758,0.01238603617527179,62.912474806224225,0.01625588985728355,89.93135183339443,11.756950007831975,4.3188908694754105,10.388956712485863,4.00601448166063,1.3679932953461098,0.3128763878147804,130.47903983498458,6.901249527740472,9.80331472977463,120.67572510520993,0.7901245563584364,6.1111249713820355,10.593439286133068,126.78685007659197,8.07111335225377,31.552050440000002 +GR,0.5656086758341576,21.217682502692107,8.293810066447499,3.7413645529326613,6.278738103001239,4.769683859069138,43.76514999884091,17.446059785604763,0.48277777777777753,37.40069475869229,5.125290380611692,2.6778373331934873,3.162988904204836,2.5497865662833865,3.05774002743643,1.940386753884961,21.204518154450987,17.03005713656159,0.0,12.844248401137325,2.309274089698663,3.4548066758354046,0.9812352669719969,6.745316032506065,57.6786974096937,7.609582935570777e-07,3.1869261083333336,29.7721921076304,0.0,5.078601781049937,0.0,7.226214055206279,0.0,12.414763357473749,0.4563904473396791,0.24500010394974975,0.413371507694714,0.23811802896220835,0.04301893964496518,0.006882074987541386,9.810799671681195,0.0797370737941638,1.3944121003233676,8.416387571357827,0.05929988423846293,0.02043718955570087,1.4537119845618307,8.436824760913527,5.0180753923393295, +HR,0.1580787880948285,18.34128786679964,4.389380056414181,1.0090057071271274,2.5476989978731437,1.318689059616855,28.847515888791193,6.237006781452905,1.6066742865068224,26.00131795404627,3.113211034470075,1.0345479474956152,0.9497163154353965,0.48100473034340274,1.0016020047136875,0.6411008353971066,8.272536625407751,5.38680865605112,0.4341687257624747,5.496189318262362,0.052814361197001926,1.8898328107958695,0.6988726986738213,2.6415198706666922,21.188430385465697,0.00018962982230924554,0.09159965703986905,13.436827525272498,0.00015599173040538647,1.8326831729199144,0.0,1.2565648624838692,3.363809190385904e-05,4.570755167749542,0.49776885579754093,0.21305012359963119,0.3313779723176993,0.15395303355572673,0.16639088347984168,0.05909709004390443,1.5213591752527897,0.005307491413879789,0.12226864940430518,1.3990905258484845,0.002843300346906715,0.002464191066973074,0.1251119497512119,1.4015547169154576,0.4627721052114323,0.04553145000000001 +HU,0.34544664961757376,51.71232046242127,9.058565274870105,2.140328474053002,5.714062255524212,2.0028906881072146,72.21082944708841,10.580042271441457,6.0852699910027175,66.5433537234814,14.356335066067029,0.16475011915334667,2.671442732381201,0.01669481559397995,3.150014039363932,0.1438143642750518,27.204656665349653,7.520276095678086,1.6199979270337255,20.586618985218344,0.5989606036781462,3.545410576534174,1.7932330983579277,5.937604278570248,38.02445666587427,0.004754012401710198,0.21252554633366075,20.378331083907437,0.0013669723377535844,3.8333953670014473,0.003313731799269432,4.637708110268266,7.330826468718214e-05,8.962496558363458,1.7569522475334471,1.1969520519059795,1.2917234069105592,0.9310232589824952,0.4652288406228879,0.2659287929234843,1.8353907709400215,0.054606555289952,0.0,1.8353907709400215,0.03396721087675474,0.020639344413197255,0.03396721087675474,1.8560301153532188,0.05833335371119447,0.0 +IE,1.1552139973989726,19.793109005806674,6.515397123991764,1.161434517801231,1.8421621718709775,0.8957692904350855,32.59953066332596,7.947985647128668,0.0,28.169618920079486,6.393256702138997,0.28535728735816485,1.6984446799638506,0.1477063007761994,1.856921735238021,0.6416420635559278,15.16447753566351,6.3577829109494655,0.0,10.2117126360729,0.47032508536436934,1.3904538819426195,0.862566607567254,2.723345574874243,40.68108342426441,0.008272205986726226,0.04426990840125408,24.407852018798376,0.007543433011813816,2.192367837492994,0.00016737978187553794,5.312891952707581,0.0005613931930368736,8.723701706864198,0.5233030297833083,0.04194485894551323,0.5099352244962404,0.04194485894551323,0.013367805287068027,0.0,7.3776188484574154,0.18094217829083742,0.018085728645439496,7.359533119811976,0.06395847585112205,0.11698370243971537,0.08204420449656154,7.476516822251692,0.2341743960240419,1.6970496000000002 +IT,1.0468206851697905,244.9130987767243,64.70816273756871,3.5257726860039496,33.711739880385224,5.298056156106979,398.1019762913365,66.98298367503608,10.821944449588157,350.87847290630515,79.03400365830159,10.16304834908569,19.572715587485437,6.461518895607246,23.010958076787716,7.348694836331663,185.82190964755122,88.9193830223242,2.2208333343889035,131.777336675836,4.840172338839531,14.844562085255594,12.704831814002475,32.38956623809759,382.16562754905397,0.12857527719351874,13.026200965629071,228.24478422974195,0.04308195860999806,25.177330023583888,0.06296249137904908,56.86449956932279,0.0016822306906727807,58.8528127607762,10.728613644333404,10.27889174413704,9.369662030497414,8.968468758742143,1.3589516138359898,1.3104229853948974,41.63152311753265,1.21375688128503,11.652418521864087,29.97910459566857,0.22427118935269547,0.9894856919323345,11.876689711216782,30.968590287600907,11.450287803031888,25.3443286 +LT,0.054268380164312624,11.715350602163216,2.5431037955938787,0.11347525483697869,1.2898906463385191,0.729637351593262,17.15320056639655,2.5910416440334036,5.404240349484153,15.549737784710798,3.6858966350176123,0.35403649213535254,0.646954859642566,0.2813772376756209,0.6491284395948164,0.5147296157717044,6.910102062603848,3.0984102546581362,1.9902252700580714,5.0040026932093715,0.14678373132394648,0.8607001311237008,0.3067145284231102,1.3141983908707575,16.47794344391527,0.07138098387942092,0.04742286954576074,11.759333998588998,2.367015705875897e-05,0.5515959910278992,0.06929945666578705,0.6262110477409603,0.0,3.49337953701165,0.6408426868412563,0.010000099960345853,0.11889710881126903,0.010000099960345853,0.5219455780299873,0.0,0.8025997207548139,0.012700327855460105,0.0,0.8025997207548139,0.007917059144158009,0.0047832687113020965,0.007917059144158009,0.807382989466116,0.05972313763724503,1.0061694500000002 +LU,0.09102207030796113,4.4582528460800175,0.5408506509033512,0.028752011719132938,0.1842589136749026,0.04414639513556391,5.784651145195065,0.9800439009093757,0.0,5.200337291213116,2.7416121696376643,0.42964741234496207,0.38754337834907376,0.13872110809105936,0.48879748143703383,0.21746057846312994,4.799602678258059,1.9924408503041833,0.7100000000000004,3.7584075376545165,0.03410552775164625,0.18906254463135402,0.05933199882242604,0.2825000712054263,25.012907547031013,0.006537582503034108,0.026090732142124796,9.61195035452163,0.0032742520029449287,0.34688378849703594,0.000672576010893665,0.4835316107788431,0.00048316442385610544,14.544451061091378,0.18787070506432504,0.12889466270463407,0.17086480068620152,0.11850807896971455,0.01700590437812352,0.010386583734919526,1.3692647775079168,2.9770867847386207,0.0,1.3692647775079168,0.14195883953447136,2.835127945204149,0.14195883953447136,4.204392722712066,0.0,0.0 +LV,0.04837569074377474,10.384613116949835,2.340644963567189,0.021113172384594966,0.6724545809684214,0.32652826749923863,14.743124497004171,1.7869997346257898,4.284217511442863,13.398134099393324,4.150995102858243,0.421817413562573,0.6219309895211804,0.18546538917869623,0.6530449380559203,0.4981204820144212,7.015731142346706,2.723629714011616,1.544950201464294,5.448903057406379,0.12993097414003488,1.024067185252895,0.6283022133780052,1.782300372770935,9.923692225555435,0.04430668304451984,0.026413105447034027,5.546359480279278,6.36983085949211e-05,0.853156946404734,0.04422967733254512,0.7124780217945105,1.0080120181086826e-05,2.785284671629878,0.8872377538316613,0.03889163480458043,0.12718689197385732,0.038891634804580424,0.7600508618578039,0.0,1.423451394923915,0.01682638285385829,0.0,1.423451394923915,0.011383099264030286,0.005443283589828004,0.011383099264030286,1.428894678513743,0.09444732504491289,2.7937818600000006 +ME,0.18428691762019353,1.6699110387853566,0.4476280894929783,0.1555359212866029,0.2968058048131801,0.20058433735409437,3.13138913,1.2769972600000001,,,0.08420605652273316,0.011619785550127245,0.01504797135378126,0.005198335075684077,0.01621943636276206,0.009143699254493983,0.15980783,0.07100115000000001,,,,,,,1.8195018700000003,0.0,0.023374743304404807,1.0703709519894518,0.0,0.08926636792867462,0.0,0.20503188721405052,0.0,0.43145791956341834,0.031866200000000004,0.020003600000000003,0.024002520016761314,0.015367348623627292,0.007863679983238687,0.004636251376372712,0.14909856022518334,0.009650939774816675,0.0,0.14909856022518334,0.0,0.009650939774816675,0.0,0.15874950000000002,0.07118723000000002,0.0 +MK,0.4423191483796166,2.8226495861922793,0.8413145426825128,0.37331199161795947,0.6356058031547073,0.48143565708557307,6.036190970000001,3.0650050900000005,,,0.9885463470402409,0.23288296163331187,0.20672486528543757,0.10418468247672413,0.2569197585883557,0.1832574063853998,2.3475271300000005,1.4230002800000001,,,,,,,5.933567850000001,0.0,0.07622725079860408,3.4905810062720652,0.0,0.29110607664715116,0.0,0.6686283945386197,0.0,1.4070251217435599,0.05284672,0.01700306,0.03980563903509613,0.013062246330083196,0.013041080964903865,0.003940813669916804,0.11322752199957879,0.00732905800042122,0.0,0.11322752199957879,0.0,0.00732905800042122,0.0,0.12055658000000001,0.0,0.0 +NL,1.6298586976689946,84.68942813303583,21.893183941383803,1.7773949260589401,9.357113200850907,1.3562324711811131,132.6887280464084,23.45301684196818,3.7844426867074854,116.07576375448231,41.256701585982235,3.4487947887252113,8.74386555749784,3.3685105382303595,9.870204039831533,4.025718619627854,84.81143946306823,36.32155823061464,1.7366658600480913,62.05804646052415,6.7784528108968365,31.684305638933232,6.298820126624233,44.7615785764543,121.86847257103743,0.048381893076100455,1.861204605302346,65.71183538795913,0.022202016959228868,3.939807489700578,0.009819762152609613,18.451060419932258,0.0038408434784715697,31.904564668143138,2.034727691797239,1.716116333742955,1.882559071473059,1.5955246718273612,0.1521686203241799,0.12059166191559394,34.92419971151198,5.748609775635073,0.0,34.92419971151198,0.3822845604365483,5.366325215198524,0.3822845604365483,40.2905249267105,4.103892187419366,152.76315521 +NO,28.804401730577776,39.45808456243531,7.757949880399734,5.663303412691806,2.5556362108232924,1.8656144339010035,52.202185400000005,38.90400146,,,26.130029515723944,19.07492154647848,3.545729560386932,2.5883825790824604,2.547165145793553,1.8594305564292937,35.12762416,26.495954460000007,,,,,,,39.489374250000004,0.028005040000000002,0.5073113699769504,23.230687369087583,0.00599875137002298,1.9373835604102068,0.018863239609742802,4.449888763994197,0.0031430490202342173,9.364103186531059,0.7961898000000001,0.6040040500000001,0.5997125986669634,0.4640135178884206,0.19647720133303667,0.13999053211157952,9.53481903369833,0.7042329663016708,3.837156822578874,5.697662211119456,0.335431317421127,0.3688016488805438,4.172588140000001,6.06646386,14.428050070000001,4.840906090000001 +PL,0.719707263764176,162.69384493310605,37.066477418290695,0.6321409759629364,19.48056221983485,7.554412836839432,237.44274247070248,28.441898996790353,48.88889712347745,219.28587265019746,51.955260494442626,8.819077017180906,8.441123332415255,3.5593519543311287,8.505633232810988,5.38704327166558,93.81952067315392,43.08232151710042,12.791391043403525,69.7380338434871,1.3424590215351815,34.01913900064919,6.315156248520575,41.67675427070494,174.29796279485242,0.06566503664190335,1.115185972116605,96.59925173251918,0.0006594983968755774,9.455957193306968,0.06495879022996191,24.85035470838785,4.674801506585862e-05,42.27721318852181,4.043880652573237,2.8530468343039725,2.283560723689119,1.8658111396792856,1.760319928884118,0.9872356946246871,6.230789077111895,0.07698608946551269,0.5481001624237407,5.682688914688154,0.03306317767518576,0.043922911790326924,0.5811633400989265,5.726611826478481,0.03611112581642298,1.6363293700000003 +PT,0.16853103420639537,6.167189443761765,6.844749403026448,0.6192555042551876,8.657967119181887,2.513361052425902,30.644647379477153,12.31396861546159,0.011388980962399788,21.88441540460838,5.314540992166446,1.8223271167970734,2.3288462896580606,1.389450501188967,2.7089567112102446,1.677792763857291,21.132756291752937,15.70110751612303,0.2966663759252526,11.94361641655254,0.8077702887437023,1.9424746346398076,2.1680579713654864,4.918302894748996,60.07163884638256,0.005796247464804267,0.6943809466998286,37.48714626049493,0.004144788310373135,1.8392478706029092,0.0014471892405585024,8.822663675857115,0.00015068153169906648,11.228200092727777,0.4119341087857363,0.29221113468922777,0.3542766997705545,0.261975695831413,0.0576574090151818,0.03023543885781476,12.04189939469445,0.24947267240484822,1.7711568990199187,10.270742495674531,0.1107532522332049,0.13871942017164332,1.8819101512531238,10.409461915846174,1.4175055568193127,7.483056010000001 +RO,0.8164119937824674,59.96132511343599,12.535594689161648,0.5966601803368272,8.287391484240173,0.6268225706774041,90.0416838937321,11.895960635306784,10.526118400572317,81.04442001456628,11.472370482472948,0.31126932980776745,2.499852646666194,0.43035561975633935,2.7719690913846016,1.1178608185175691,22.759444431153444,8.001025371554253,2.5952795750395103,16.898643459088195,0.7007809689311082,2.719627160661053,2.094159726588078,5.514567856180239,56.27724851083044,0.006095761615848004,0.21744941693675585,30.680317400032756,0.005639041540646845,11.646944255137056,0.00015561928868615372,7.116715973219791,4.505132889433588e-05,6.615821465504074,2.9624978308219267,1.0611074233348035,2.1230366871828705,0.7659474400326133,0.839461143639056,0.2951599833021901,2.424579253795485,0.029546566493058167,0.20490687455205012,2.2196723792434345,0.02497642466045021,0.004570141832607959,0.2298832992125003,2.2242425210760426,0.48333372495510224,0.48328465000000004 +RS,2.041447300754024,17.23241025134951,4.7096888757710875,1.7229567393124234,3.2058768205282546,2.221982761190753,33.10772576,14.145999310000002,,,4.436825941714843,0.8017518796993448,0.8519426499259911,0.3586791598052431,0.985253156817818,0.6309047643840355,9.346379720000002,4.898997940000001,,,,,,,22.236583260000003,0.0,0.285668530623453,13.081268662284423,0.0,1.0909464043385495,0.0,2.5057455043946524,0.0,5.272954158358922,0.5751616500000001,0.47800463000000004,0.43322796621493825,0.3672170905695961,0.14193368378506177,0.11078753943040395,0.4886500505665789,0.03162962943342115,0.0,0.4886500505665789,0.0,0.03162962943342115,0.0,0.52027968,0.10861257000000002,0.10931037 +SE,18.4203419908313,55.67334748926343,14.09700520336014,7.62928350560303,5.841710107199814,5.785689042843419,86.98471532467524,43.504196153945145,30.748061957160978,75.74261755247736,22.700405098892183,4.608878048490316,4.269153420938776,1.7706726927590173,4.374008646562861,4.286688107484913,46.05946171198871,25.491266437692087,15.6636143722038,32.15077398576433,1.0361667627692726,2.0898260280447953,1.010335904191686,4.136328695005755,83.04667870338166,0.01280258345751495,0.34320531162223467,51.05330259569601,0.0061524965671318635,6.1507365387542245,0.001514571605766908,7.009050732526921,0.002657098759479214,18.490383524782263,2.761947422261534,2.750002981435833,2.0247546969142176,2.0184609369237854,0.7371927253473161,0.7315420445120471,10.241309021150325,0.18676454919898827,1.9390076232799187,8.302301397870405,0.06947218543730693,0.11729236376168135,2.0084798087172255,8.419593761632086,0.7977769681471846,18.578494690000003 +SI,0.34227433442339894,8.376475064050604,2.9220707579747884,0.453818512537254,0.8699951748952809,0.5648060322082612,13.995062824999088,3.2289764898849858,0.9472293430810873,12.239285152226612,2.570621989760942,0.6007517589071416,0.5133561218151605,0.18953808270509473,0.647701991765941,0.48074261627130094,5.65765380957795,3.2179778886185555,0.5774928791411378,3.880746457492038,0.0,0.549946125291897,0.2641860340673345,0.8141321593592316,20.80700782789383,0.00010110043502486967,0.09327831893642177,11.880939237809546,8.371504104872192e-05,0.7193026858478071,0.0,0.9960279918658297,0.0,7.117459593434226,0.27222489410492606,0.15389153928786237,0.14979465172003809,0.07389407828151527,0.12243024238488796,0.0799974610063471,0.3099300394503224,0.004512821170390541,0.0,0.3099300394503224,0.0028361068079113625,0.0016767143624791794,0.0028361068079113625,0.3116067538128016,0.0,0.7076273500000001 +SK,0.7110244219256427,16.322019247760963,3.9420025260381517,0.4761557307462169,1.9667320357371187,0.7020969879798182,24.976139305348433,4.930015666329864,5.806117943917119,22.24202848390687,12.395946919792488,1.59350805554285,1.5814611823385478,0.7318096909411619,1.591685689729668,0.771687906762327,19.888551870977174,7.539329752327933,1.1225013209917258,15.78104264329495,0.21327589995852728,0.8694320240429981,0.44148890889017306,1.5241968328916984,23.792769864038295,0.03763800097049386,0.03401005608446167,9.914745300376103,6.220464867834378e-05,1.7151976456935867,0.0375611283634322,2.3748436290651527,1.0622037973027887e-05,9.753973232818993,0.5388822140190512,0.5388822140190512,0.37230773469849826,0.37230773469849826,0.166574479320553,0.166574479320553,0.46763946179091403,0.01347991726152616,0.0,0.46763946179091403,0.010194585747323313,0.003285331514202844,0.010194585747323313,0.4709247933051169,0.18577762000000003,0.0 From ad9da6118757ccfc44dc92cac00b7748fe7f383a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:34:15 +0000 Subject: [PATCH 450/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/configtables/load.csv | 2 +- scripts/build_hydro_profile.py | 4 +--- scripts/build_population_weighted_energy_totals.py | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index b245268f..02e7b97b 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -4,4 +4,4 @@ time_shift_for_large_gaps,string,string,"Periods which are used for copying time manual_adjustments,bool,"{true, false}","Whether to adjust the load data manually according to the function in :func:`manual_adjustment`." scaling_factor,--,float,"Global correction factor for the load time series." fixed_year,--,Year or False,"To specify a fixed year for the load time series that deviates from the snapshots' year" -supplement_missing_data_artificially,bool,"{true, false}","Whether to supplement missing data for selected time period should be supplemented by artificial data from https://zenodo.org/record/7070438/files/demand_hourly.csv." \ No newline at end of file +supplement_missing_data_artificially,bool,"{true, false}","Whether to supplement missing data for selected time period should be supplemented by artificial data from https://zenodo.org/record/7070438/files/demand_hourly.csv." diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 510bc6fa..76ffc496 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -73,9 +73,7 @@ cc = coco.CountryConverter() def get_eia_annual_hydro_generation(fn, countries, capacities=False): # in billion kWh/a = TWh/a - df = pd.read_csv( - fn, skiprows=2, index_col=1, na_values=[" ", "--"] - ).iloc[1:, 1:] + df = pd.read_csv(fn, skiprows=2, index_col=1, na_values=[" ", "--"]).iloc[1:, 1:] df.index = df.index.str.strip() df.columns = df.columns.astype(int) diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index c2be19a9..70105a06 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -15,7 +15,7 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_population_weighted_energy_totals", - kind='energy', + kind="energy", simpl="", clusters=60, ) From 0d6ba9fbd1d998e73b7a82f8941f516c9e18f49a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 15:15:56 +0100 Subject: [PATCH 451/591] move leap year handling into helper function --- doc/configtables/load.csv | 2 +- rules/build_electricity.smk | 2 ++ scripts/_helpers.py | 12 ++++++++++ scripts/add_electricity.py | 22 +++++++------------ scripts/base_network.py | 6 ++--- scripts/build_daily_heat_demand.py | 13 ++++++----- scripts/build_electricity_demand.py | 6 +++-- scripts/build_hourly_heat_demand.py | 8 +++---- scripts/build_hydro_profile.py | 10 +++------ scripts/build_line_rating.py | 6 ++--- ...build_population_weighted_energy_totals.py | 2 +- scripts/build_renewable_profiles.py | 9 +++----- scripts/build_solar_thermal_profiles.py | 7 ++---- scripts/build_temperature_profiles.py | 7 ++---- scripts/build_transport_demand.py | 14 +++++++----- scripts/make_summary.py | 5 +++-- scripts/prepare_sector_network.py | 4 ---- 17 files changed, 66 insertions(+), 69 deletions(-) diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index b245268f..02e7b97b 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -4,4 +4,4 @@ time_shift_for_large_gaps,string,string,"Periods which are used for copying time manual_adjustments,bool,"{true, false}","Whether to adjust the load data manually according to the function in :func:`manual_adjustment`." scaling_factor,--,float,"Global correction factor for the load time series." fixed_year,--,Year or False,"To specify a fixed year for the load time series that deviates from the snapshots' year" -supplement_missing_data_artificially,bool,"{true, false}","Whether to supplement missing data for selected time period should be supplemented by artificial data from https://zenodo.org/record/7070438/files/demand_hourly.csv." \ No newline at end of file +supplement_missing_data_artificially,bool,"{true, false}","Whether to supplement missing data for selected time period should be supplemented by artificial data from https://zenodo.org/record/7070438/files/demand_hourly.csv." diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index edf5fca3..6db8bcd7 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -21,6 +21,7 @@ if config["enable"].get("prepare_links_p_nom", False): rule build_electricity_demand: params: snapshots=config_provider("snapshots"), + drop_leap_day=config_provider("enable", "drop_leap_day"), countries=config_provider("countries"), load=config_provider("load"), input: @@ -68,6 +69,7 @@ rule base_network: params: countries=config_provider("countries"), snapshots=config_provider("snapshots"), + drop_leap_day=config_provider("enable", "drop_leap_day"), lines=config_provider("lines"), links=config_provider("links"), transformers=config_provider("transformers"), diff --git a/scripts/_helpers.py b/scripts/_helpers.py index a1504c3c..09687a11 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -724,3 +724,15 @@ def validate_checksum(file_path, zenodo_url=None, checksum=None): assert ( calculated_checksum == checksum ), "Checksum is invalid. This may be due to an incomplete download. Delete the file and re-execute the rule." + + +def get_snapshots(snapshots, drop_leap_day=False, freq="h", **kwargs): + """ + Returns pandas DateTimeIndex potentially without leap days. + """ + + time = pd.date_range(freq=freq, **snapshots, **kwargs) + if drop_leap_day and time.is_leap_year.any(): + time = time[~((time.month == 2) & (time.day == 29))] + + return time diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index a0d41e1d..ac73cb1f 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -93,7 +93,12 @@ import powerplantmatching as pm import pypsa import scipy.sparse as sparse import xarray as xr -from _helpers import configure_logging, set_scenario_config, update_p_nom_max +from _helpers import ( + configure_logging, + get_snapshots, + set_scenario_config, + update_p_nom_max, +) from powerplantmatching.export import map_country_bus from shapely.prepared import prep @@ -760,15 +765,6 @@ def estimate_renewable_capacities( ) -def drop_leap_day(n): - if not n.snapshots.is_leap_year.any(): - return - leap_days = (n.snapshots.day == 29) & (n.snapshots.month == 2) - n.set_snapshots(n.snapshots[~leap_days]) - n.snapshot_weightings[:] = 8760 / len(n.snapshots) - logger.info("Dropped February 29 from leap year.") - - def attach_line_rating( n, rating, s_max_pu, correction_factor, max_voltage_difference, max_line_rating ): @@ -805,7 +801,8 @@ if __name__ == "__main__": n = pypsa.Network(snakemake.input.base_network) - n.set_snapshots(pd.date_range(freq="h", **snakemake.params.snapshots)) + time = get_snapshots(snakemake.params.snapshots, snakemake.params.drop_leap_day) + n.set_snapshots(time) Nyears = n.snapshot_weightings.objective.sum() / 8760.0 @@ -916,8 +913,5 @@ if __name__ == "__main__": sanitize_carriers(n, snakemake.config) - if snakemake.params.drop_leap_day: - drop_leap_day(n) - n.meta = snakemake.config n.export_to_netcdf(snakemake.output[0]) diff --git a/scripts/base_network.py b/scripts/base_network.py index 66438994..346f99a5 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -75,7 +75,7 @@ import shapely import shapely.prepared import shapely.wkt import yaml -from _helpers import configure_logging, set_scenario_config +from _helpers import configure_logging, get_snapshots, set_scenario_config from packaging.version import Version, parse from scipy import spatial from scipy.sparse import csgraph @@ -730,12 +730,12 @@ def base_network( transformers = _set_electrical_parameters_transformers(transformers, config) links = _set_electrical_parameters_links(links, config, links_p_nom) converters = _set_electrical_parameters_converters(converters, config) - snapshots = snakemake.params.snapshots n = pypsa.Network() n.name = "PyPSA-Eur" - n.set_snapshots(pd.date_range(freq="h", **snapshots)) + time = get_snapshots(snakemake.params.snapshots, snakemake.params.drop_leap_day) + n.set_snapshots(time) n.madd("Carrier", ["AC", "DC"]) n.import_components_from_dataframe(buses, "Bus") diff --git a/scripts/build_daily_heat_demand.py b/scripts/build_daily_heat_demand.py index c08cfe33..54c5c386 100644 --- a/scripts/build_daily_heat_demand.py +++ b/scripts/build_daily_heat_demand.py @@ -11,7 +11,7 @@ import geopandas as gpd import numpy as np import pandas as pd import xarray as xr -from _helpers import set_scenario_config +from _helpers import get_snapshots, set_scenario_config from dask.distributed import Client, LocalCluster if __name__ == "__main__": @@ -32,11 +32,12 @@ if __name__ == "__main__": cutout_name = snakemake.input.cutout - time = pd.date_range(freq="h", **snakemake.params.snapshots) - daily = pd.date_range(freq="D", **snakemake.params.snapshots) - if snakemake.params.drop_leap_day: - time = time[~((time.month == 2) & (time.day == 29))] - daily = daily[~((daily.month == 2) & (daily.day == 29))] + time = get_snapshots(snakemake.params.snapshots, snakemake.params.drop_leap_day) + daily = get_snapshots( + snakemake.params.snapshots, + snakemake.params.drop_leap_day, + freq="D", + ) cutout = atlite.Cutout(cutout_name).sel(time=time) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 68df4bac..2d3da224 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -39,7 +39,7 @@ import logging import numpy as np import pandas as pd -from _helpers import configure_logging, set_scenario_config +from _helpers import configure_logging, get_snapshots, set_scenario_config from pandas import Timedelta as Delta logger = logging.getLogger(__name__) @@ -263,7 +263,9 @@ if __name__ == "__main__": configure_logging(snakemake) set_scenario_config(snakemake) - snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) + snapshots = get_snapshots( + snakemake.params.snapshots, snakemake.params.drop_leap_day + ) fixed_year = snakemake.config["load"].get("fixed_year", False) years = ( diff --git a/scripts/build_hourly_heat_demand.py b/scripts/build_hourly_heat_demand.py index c3916b54..1fb4f5a4 100644 --- a/scripts/build_hourly_heat_demand.py +++ b/scripts/build_hourly_heat_demand.py @@ -10,7 +10,7 @@ from itertools import product import pandas as pd import xarray as xr -from _helpers import generate_periodic_profiles, set_scenario_config +from _helpers import generate_periodic_profiles, get_snapshots, set_scenario_config if __name__ == "__main__": if "snakemake" not in globals(): @@ -24,9 +24,9 @@ if __name__ == "__main__": ) set_scenario_config(snakemake) - snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) - if snakemake.params.drop_leap_day: - snapshots = snapshots[~((snapshots.month == 2) & (snapshots.day == 29))] + snapshots = get_snapshots( + snakemake.params.snapshots, snakemake.params.drop_leap_day + ) daily_space_heat_demand = ( xr.open_dataarray(snakemake.input.heat_demand) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index 510bc6fa..b7f270b3 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -65,7 +65,7 @@ import atlite import country_converter as coco import geopandas as gpd import pandas as pd -from _helpers import configure_logging, set_scenario_config +from _helpers import configure_logging, get_snapshots, set_scenario_config from numpy.polynomial import Polynomial cc = coco.CountryConverter() @@ -73,9 +73,7 @@ cc = coco.CountryConverter() def get_eia_annual_hydro_generation(fn, countries, capacities=False): # in billion kWh/a = TWh/a - df = pd.read_csv( - fn, skiprows=2, index_col=1, na_values=[" ", "--"] - ).iloc[1:, 1:] + df = pd.read_csv(fn, skiprows=2, index_col=1, na_values=[" ", "--"]).iloc[1:, 1:] df.index = df.index.str.strip() df.columns = df.columns.astype(int) @@ -175,9 +173,7 @@ if __name__ == "__main__": params_hydro = snakemake.params.hydro - time = pd.date_range(freq="h", **snakemake.params.snapshots) - if snakemake.params.drop_leap_day: - time = time[~((time.month == 2) & (time.day == 29))] + time = get_snapshots(snakemake.params.snapshots, snakemake.params.drop_leap_day) cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) diff --git a/scripts/build_line_rating.py b/scripts/build_line_rating.py index 794638d2..f9c71ea3 100755 --- a/scripts/build_line_rating.py +++ b/scripts/build_line_rating.py @@ -58,7 +58,7 @@ import numpy as np import pandas as pd import pypsa import xarray as xr -from _helpers import configure_logging, set_scenario_config +from _helpers import configure_logging, get_snapshots, set_scenario_config from shapely.geometry import LineString as Line from shapely.geometry import Point @@ -147,9 +147,7 @@ if __name__ == "__main__": set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.base_network) - time = pd.date_range(freq="h", **snakemake.params.snapshots) - if snakemake.params.drop_leap_day: - time = time[~((time.month == 2) & (time.day == 29))] + time = get_snapshots(snakemake.params.snapshots, snakemake.params.drop_leap_day) cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index c2be19a9..70105a06 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -15,7 +15,7 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_population_weighted_energy_totals", - kind='energy', + kind="energy", simpl="", clusters=60, ) diff --git a/scripts/build_renewable_profiles.py b/scripts/build_renewable_profiles.py index 88057fb6..f1eb5e15 100644 --- a/scripts/build_renewable_profiles.py +++ b/scripts/build_renewable_profiles.py @@ -186,9 +186,8 @@ import time import atlite import geopandas as gpd import numpy as np -import pandas as pd import xarray as xr -from _helpers import configure_logging, set_scenario_config +from _helpers import configure_logging, get_snapshots, set_scenario_config from dask.distributed import Client from pypsa.geo import haversine from shapely.geometry import LineString @@ -227,11 +226,9 @@ if __name__ == "__main__": else: client = None - time = pd.date_range(freq="h", **snakemake.params.snapshots) - if snakemake.params.drop_leap_day: - time = time[~((time.month == 2) & (time.day == 29))] + sns = get_snapshots(snakemake.params.snapshots, snakemake.params.drop_leap_day) - cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) + cutout = atlite.Cutout(snakemake.input.cutout).sel(time=sns) regions = gpd.read_file(snakemake.input.regions) assert not regions.empty, ( f"List of regions in {snakemake.input.regions} is empty, please " diff --git a/scripts/build_solar_thermal_profiles.py b/scripts/build_solar_thermal_profiles.py index c9eaffcc..bb5180b9 100644 --- a/scripts/build_solar_thermal_profiles.py +++ b/scripts/build_solar_thermal_profiles.py @@ -9,9 +9,8 @@ Build solar thermal collector time series. import atlite import geopandas as gpd import numpy as np -import pandas as pd import xarray as xr -from _helpers import set_scenario_config +from _helpers import get_snapshots, set_scenario_config from dask.distributed import Client, LocalCluster if __name__ == "__main__": @@ -32,9 +31,7 @@ if __name__ == "__main__": config = snakemake.params.solar_thermal config.pop("cutout", None) - time = pd.date_range(freq="h", **snakemake.params.snapshots) - if snakemake.params.drop_leap_day: - time = time[~((time.month == 2) & (time.day == 29))] + time = get_snapshots(snakemake.params.snapshots, snakemake.params.drop_leap_day) cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) diff --git a/scripts/build_temperature_profiles.py b/scripts/build_temperature_profiles.py index e5fa0b38..00c88b5b 100644 --- a/scripts/build_temperature_profiles.py +++ b/scripts/build_temperature_profiles.py @@ -9,9 +9,8 @@ Build time series for air and soil temperatures per clustered model region. import atlite import geopandas as gpd import numpy as np -import pandas as pd import xarray as xr -from _helpers import set_scenario_config +from _helpers import get_snapshots, set_scenario_config from dask.distributed import Client, LocalCluster if __name__ == "__main__": @@ -29,9 +28,7 @@ if __name__ == "__main__": cluster = LocalCluster(n_workers=nprocesses, threads_per_worker=1) client = Client(cluster, asynchronous=True) - time = pd.date_range(freq="h", **snakemake.params.snapshots) - if snakemake.params.drop_leap_day: - time = time[~((time.month == 2) & (time.day == 29))] + time = get_snapshots(snakemake.params.snapshots, snakemake.params.drop_leap_day) cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time) diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index d3c740be..e39774fa 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -13,7 +13,12 @@ import logging import numpy as np import pandas as pd import xarray as xr -from _helpers import configure_logging, generate_periodic_profiles, set_scenario_config +from _helpers import ( + configure_logging, + generate_periodic_profiles, + get_snapshots, + set_scenario_config, +) logger = logging.getLogger(__name__) @@ -183,10 +188,9 @@ if __name__ == "__main__": options = snakemake.params.sector - snapshots = pd.date_range(freq="h", **snakemake.params.snapshots, tz="UTC") - if snakemake.params.drop_leap_day: - leap_day = (snapshots.month == 2) & (snapshots.day == 29) - snapshots = snapshots[~leap_day] + snapshots = get_snapshots( + snakemake.params.snapshots, snakemake.params.drop_leap_day, tz="UTC" + ) nyears = len(snapshots) / 8760 diff --git a/scripts/make_summary.py b/scripts/make_summary.py index b9e1a8af..8c2a1aea 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -13,7 +13,7 @@ import sys import numpy as np import pandas as pd import pypsa -from _helpers import configure_logging, set_scenario_config +from _helpers import configure_logging, get_snapshots, set_scenario_config from prepare_sector_network import prepare_costs idx = pd.IndexSlice @@ -690,7 +690,8 @@ if __name__ == "__main__": for planning_horizon in snakemake.params.scenario["planning_horizons"] } - Nyears = len(pd.date_range(freq="h", **snakemake.params.snapshots)) / 8760 + time = get_snapshots(snakemake.params.snapshots, snakemake.params.drop_leap_day) + Nyears = len(time) / 8760 costs_db = prepare_costs( snakemake.input.costs, diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 9c4404f2..5757a88b 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3507,10 +3507,6 @@ def set_temporal_aggregation(n, resolution, solver_name, drop_leap_day=False): logger.info("Aggregate to frequency %s", resolution) n = average_every_nhours(n, resolution) - if drop_leap_day: - sns = n.snapshots[~((n.snapshots.month == 2) & (n.snapshots.day == 29))] - n.set_snapshots(sns) - return n From 6a3cf1245970996ae42ee0153613cc67ce30cb8b Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 15:18:05 +0100 Subject: [PATCH 452/591] remove accidental file addition --- scripts/new-energy-totals.csv | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 scripts/new-energy-totals.csv diff --git a/scripts/new-energy-totals.csv b/scripts/new-energy-totals.csv deleted file mode 100644 index 78ba6736..00000000 --- a/scripts/new-energy-totals.csv +++ /dev/null @@ -1,34 +0,0 @@ -country,electricity residential space,total residential space,total residential water,electricity residential water,total residential cooking,electricity residential cooking,total residential,electricity residential,derived heat residential,thermal uses residential,total services space,electricity services space,total services water,electricity services water,total services cooking,electricity services cooking,total services,electricity services,derived heat services,thermal uses services,total agriculture electricity,total agriculture heat,total agriculture machinery,total agriculture,total road,electricity road,total two-wheel,total passenger cars,electricity passenger cars,total other road passenger,electricity other road passenger,total light duty road freight,electricity light duty road freight,total heavy duty road freight,total rail,electricity rail,total rail passenger,electricity rail passenger,total rail freight,electricity rail freight,total aviation passenger,total aviation freight,total domestic aviation passenger,total international aviation passenger,total domestic aviation freight,total international aviation freight,total domestic aviation,total international aviation,total domestic navigation,total international navigation -AL,0.5570465743624181,2.868681023831782,0.9246366122728509,0.4701405463928116,0.7560298250278052,0.606309006828873,6.745434890000001,3.8599970000000003,,,0.8492947400612103,0.24188377504306646,0.19063435423096936,0.1082113698760542,0.24955086644902696,0.190340216176473,2.2211439200000003,1.4779985500000001,,,,,,,8.933037890000001,0.0,0.11476078758153294,5.255099996394696,0.0,0.43826272462667554,0.0,1.0066258503715193,0.0,2.1182885310255757,0.03566921000000001,0.0,0.026867054339929548,0.0,0.008802155660070457,0.0,0.23558664812723476,0.015249191872765277,0.0,0.23558664812723476,0.0,0.015249191872765277,0.0,0.25083584000000003,0.38266189000000006,0.23777535000000002 -AT,3.8347980364339187,52.728795606720304,9.042762942245817,1.6580654856850694,3.332605848035772,2.2140159394525,74.4128059879979,17.31873449075142,8.985794565462129,65.16773835369318,17.423168106040677,1.362361756513761,3.4703813442929237,0.2967617406747894,3.4964403032216045,2.3458829314999434,33.49193062767192,13.244905252570849,9.882817057376736,24.839638062603143,0.6497150410629878,3.8719030223442585,1.7388785775882416,6.260496640995489,88.04632651098169,0.035087453918020005,0.6026064240302123,47.145477443307264,0.010621583280449667,3.067508471104808,0.02013826679946008,5.385434496257479,0.003947974868709491,31.84529967628193,3.384639661479662,2.8930267787407162,2.332832737694036,1.971964325107237,1.0518069237856262,0.9210624536334792,7.604475261435951,0.3130344308815537,0.26550445600104483,7.338970805434905,0.07206205482497326,0.24097237605658042,0.3375665108260181,7.579943181491485,0.058055683482739553,0.23600759000000002 -BA,0.9551423259051094,8.062615381913417,2.2035460750967655,0.8061285279384439,1.4999498844734496,1.039610369496632,15.49027994803239,6.61856060561295,,,2.075880307094079,0.37511972750507755,0.3986027383060623,0.16781704177400622,0.46097540282364163,0.2951846191943365,4.372938190104563,2.2921190692934506,,,,,,,10.403943245213432,0.0,0.1336571875633523,6.120399665114565,0.0,0.5104266398122862,0.0,1.172375886612297,0.0,2.4670838661109293,0.2691038049081697,0.22364645608190642,0.20269657078330564,0.1718117268416388,0.06640723412486403,0.051834729240267635,0.22862718311632196,0.01479871550610001,0.0,0.22862718311632196,0.0,0.01479871550610001,0.0,0.24342589862242198,0.05081711523682938,0.0511435984699603 -BE,2.815051564451901,72.00315684834005,14.758606504598777,1.9245397162358575,5.61762658049057,2.123765047409,104.53126486079485,19.81013300307489,0.048333322074790706,92.47214768445166,35.55025666623682,6.159088599308961,4.553234776118736,1.3005782934779981,4.296286602056132,1.7511206036264235,57.027872149578414,22.25434577090179,0.7699977716616743,45.32121766089195,1.2652057097802312,6.510654609861979,2.1504989713552063,9.926359290997418,93.22107248215386,0.01074409225014649,0.6477429921079886,54.179087820705185,0.006636212751625691,3.954966803176898,0.001991249371656604,10.47276574878302,0.0015859584461520306,23.966509117380756,2.2359228430787947,1.596953398545387,1.7366935264699335,1.306970119159899,0.4992293166088615,0.2899832793854877,11.903404936264774,2.9443700871166114,0.0,11.903404936264774,0.5794491728255937,2.3649209142910177,0.5794491728255937,14.268325850555792,1.822780948768488,71.59805975 -BG,1.0366899653005102,13.774445984268725,5.032599359348841,2.50096431277225,2.8263907739201346,2.446346362124563,26.126347522623533,10.536998125106878,3.70225381151711,21.738366989691684,3.6161635069149147,1.317290338927257,1.4876301353881975,0.8459255010716765,1.614166101394505,1.2802729496644545,11.214107236902933,7.954580847599141,1.1947324162166162,7.013424737247175,0.2157562658354375,1.238388279337861,0.8037223126895519,2.257866857862851,27.913508544418903,0.05240401618919764,0.2678003482560851,18.16930433603284,0.0,2.6753054767672606,0.05240401618919764,1.723251062925399,0.0,5.077847320437322,0.36999955326892575,0.19499962550233102,0.2595248907228583,0.1337123426290272,0.11047466254606741,0.06128728287330383,1.9735489165680373,0.0214510834319626,0.06685311111111157,1.9066958054569259,0.01455716249528969,0.0068939209366729115,0.08141027360640127,1.9135897263935986,0.0,1.0494446800000001 -CH,4.388888888888889,51.52777777777778,8.944444444444445,2.388888888888889,2.611111111111111,1.3611111111111112,72.58333333333333,18.777777777777775,,,21.5,1.1666666666666667,2.8055555555555554,0.19444444444444442,0.6388888888888888,0.6388888888888888,40.0,17.055555555555554,,,,,,,55.888888888888886,0.0,0.7179923543283743,32.87814329403942,0.0,2.7419582254567123,0.0,6.297879959411784,0.0,13.25291505565259,3.1666666666666665,3.1666666666666665,2.3852225886072858,2.432725641458858,0.7814440780593807,0.7339410252078085,17.617703597787695,1.1600741799900811,0.8685212443581152,16.749182353429582,0.07592320008632922,1.0841509799037519,0.9444444444444444,17.833333333333332,0.4444444444444445,0.0 -CZ,2.5725233632931075,62.57273499598758,10.288206369245467,2.9111285854172344,5.349291874222479,2.9169812116183698,83.99741666322201,14.715973413943496,13.888879856159699,78.24427707959727,20.246784369915833,4.388583048588386,3.0235451499346557,0.9434718391306539,3.505353453229548,1.7737748387302745,34.29840057384516,14.78664045488378,5.310847457419239,27.053057440415177,0.6941273932306512,4.054135056204236,2.4003802728676513,7.148642722302538,63.503988188281525,0.08911029892052649,0.6865202837197137,30.92628881993422,0.0007819669138069432,3.866800834894914,0.08831777854219773,5.7476679804286555,0.0,22.276710269304015,2.5098763617700213,1.491101348077621,1.957212181581117,1.1043425069361408,0.5526641801889038,0.38675884114148024,3.4758788630067836,0.048572629407252134,0.056765346606964515,3.419113516399819,0.019945792240296925,0.028626837166955205,0.07671113884726144,3.447740353566774,0.023888852908381327,0.0 -DE,23.552538648485736,482.88953556791756,88.86181482888813,9.341725122373857,41.094774831600795,14.516493828941883,694.2861367421355,136.00002715231648,51.24612134236524,614.0643012925772,200.1083899771467,8.177528100639465,38.567939444757855,8.148137272139993,48.02923585230634,20.88733594674748,388.35703665770825,141.5218730593723,16.87389225775031,291.39267527735336,7.53469558411125,5.474391021838289,1.4190403036639783,14.42812690961352,600.5438784206764,0.11224182554399796,5.370903791988889,380.78585774165197,0.0804737905883431,18.892615204428267,0.014714641214532026,28.660484589683342,0.015353321394055243,166.83401709292394,15.93416884756733,11.885002372832927,11.472824304223883,8.279888081535278,4.461344543343446,3.605114291297649,91.38069880171732,13.41045647623245,7.896669996323121,83.4840288053942,2.19924733222008,11.211209144012372,10.095917328543202,94.69523794940658,3.3722220527550077,26.697188350000005 -DK,0.7013376012077638,33.93012445800281,7.368540509780002,0.5229211600849933,3.1224115802390884,2.437647648641987,50.639691342206994,10.307073119763176,19.141944444444412,44.46958545008379,11.568860496650082,0.7165794765906534,1.9268567416141313,0.4139126319754398,2.107350856421504,1.6568129470533832,22.96597151274313,10.221030677425023,8.886388888888847,15.964433033531657,1.6065828331780032,4.6006732485303825,2.958335976083448,9.165592057791836,42.126010180586306,0.006041443591563428,0.26907068768936326,23.38606046077933,0.005426936489976022,3.9158027200781587,0.0,5.764536143667914,0.0006145071015874062,8.79054016837154,1.3112062796097734,0.3861092120959323,1.201322441895927,0.35393692637112534,0.10988383771384651,0.03217228572480684,10.062240435459456,0.3052602112787246,0.5934322985915401,9.468808136867919,0.10206631066816502,0.20319390061055956,0.6954986092597052,9.672002037478478,1.978361573681062,7.339855820000001 -EE,0.11231606763657928,7.615319503233344,1.5105449935831652,0.06137687617864419,0.7305183637351055,0.6392485833424982,10.871312066259437,1.8649831545295248,3.8389405197191633,9.856556620105813,2.8051300129906593,0.7294467788998327,0.3759461883671719,0.16897479263456983,0.43229161868604543,0.3654118725947719,4.8619944419222145,2.5288861940995093,1.1860593158990447,3.6224949714927197,0.17269894009588554,0.7062927576664825,0.4019989426098384,1.2809906403722064,8.143920002436563,0.02196621718242599,0.02187321389494755,5.041673827103431,0.0035133698706650515,0.9394047336082759,0.018423149598824944,0.6543028641167076,2.969771293599253e-05,1.4866653637132001,0.3473335032636153,0.04203126411907797,0.08800246779439479,0.04203126411907797,0.2593310354692205,0.0,0.32494722922299063,0.009489420040482168,0.0,0.32494722922299063,0.0036550739486526196,0.005834346091829548,0.0036550739486526196,0.33078157531482016,0.04694670715427129,4.740620600000001 -ES,10.794125129618664,71.26452543322868,39.68527650785515,7.710514219460869,19.26597649255715,8.828493562332296,177.196549581737,74.63098166927618,0.0,131.8776230960182,34.390226550633635,5.784912430114415,14.00729551399568,6.8886787516288885,17.98020571548081,13.01444004144452,115.94028841537886,75.5600175062191,0.0,75.67658371390513,3.798490176657542,20.504156811235546,10.361953239126692,34.664600227019776,295.6964784476745,0.008958749867787469,5.271025477457057,177.9796367179715,0.006198765274153721,10.784071123614806,0.0,20.279070030269107,0.0027599845936337485,81.38267509836203,8.270129202825443,4.551941091567911,7.174411141940354,4.18254627330064,1.095718060885089,0.36939481826726994,58.78529713592237,1.0458142160063002,18.097222294891036,40.68807484103132,0.33629527208914706,0.7095189439171532,18.433517566980182,41.39759378494848,5.86721442260112,84.04543941000001 -FI,7.848535711327018,41.84350237788999,9.048520920884483,3.443099269456141,2.9395617816882234,2.8792251386947934,60.826832141117144,21.50989869058375,18.587994476407626,53.92184520851802,21.23055041955415,6.199986054777693,2.553779457989475,0.9989674641957111,2.737139467312127,2.6900543568450637,34.04765319297288,17.50312586133877,12.247279309978593,26.808838116560455,1.2798819960077403,7.441003309894633,1.9312393542030517,10.652124660105425,45.56549617623142,0.0019365717691190252,0.5223209306867633,26.118742999170177,0.0007992579455364848,3.2601013702649593,0.00016885440537935242,5.613312604425437,0.0006476900733945322,10.051018271684086,1.1047159761512422,0.7330519889163917,0.6084665070352008,0.5419802858183081,0.4962494691160414,0.19107170309808352,7.731241694301903,0.3876090573520712,1.4438906650320935,6.287351029269809,0.11591836963879651,0.2716906877132747,1.55980903467089,6.559041716983084,1.725813385303544,1.5172963200000003 -FR,36.34821295388092,304.3090830974361,74.10444863335236,20.89120031251567,42.04728767502008,19.96798113754325,503.553879238341,167.90380216073933,14.323611111111111,421.0509096549809,149.2072481280514,29.02123818481345,25.328465674571646,12.10488257238001,28.51040521266642,17.00244127422052,285.9163571402345,142.24734181479553,8.505277777777804,216.87393093116245,7.478237257126606,32.74985084813704,20.230248718717654,60.4583368239813,477.2711666499798,0.17960126429470955,6.464992469847664,252.13117399671086,0.07795214668519337,21.88511370979885,0.039237383416606084,91.90030834156023,0.061631171267770395,104.88957813206223,12.134370941891715,10.168257793403882,10.262575388236112,8.653518950028449,1.8717955536556061,1.5147388433754336,71.22571967077627,3.5990187474665083,19.982431345628665,51.2432883251476,1.4447624710282905,2.154256276438218,21.427193816656956,53.397544601585814,5.826683163334846,26.200994400000006 -GB,32.35436698812953,318.9482399097387,79.0068899383846,11.692921151505214,20.777464730965892,3.4829778546191315,480.6012101626519,113.45010172801696,0.603890281538269,419.06137321331204,111.80304633929093,16.901263938070077,21.670713737923748,9.433929352734362,25.136145179539948,11.42081966062867,217.22824016750891,97.6278626859339,4.641112795545814,162.61403696376797,3.2166577319321257,5.143442067057801,2.6425900548485233,11.00268985383845,430.58518629173466,0.046201812762040446,1.9853577192078395,261.8768230625204,0.017483920193319114,13.879178870387758,0.01238603617527179,62.912474806224225,0.01625588985728355,89.93135183339443,11.756950007831975,4.3188908694754105,10.388956712485863,4.00601448166063,1.3679932953461098,0.3128763878147804,130.47903983498458,6.901249527740472,9.80331472977463,120.67572510520993,0.7901245563584364,6.1111249713820355,10.593439286133068,126.78685007659197,8.07111335225377,31.552050440000002 -GR,0.5656086758341576,21.217682502692107,8.293810066447499,3.7413645529326613,6.278738103001239,4.769683859069138,43.76514999884091,17.446059785604763,0.48277777777777753,37.40069475869229,5.125290380611692,2.6778373331934873,3.162988904204836,2.5497865662833865,3.05774002743643,1.940386753884961,21.204518154450987,17.03005713656159,0.0,12.844248401137325,2.309274089698663,3.4548066758354046,0.9812352669719969,6.745316032506065,57.6786974096937,7.609582935570777e-07,3.1869261083333336,29.7721921076304,0.0,5.078601781049937,0.0,7.226214055206279,0.0,12.414763357473749,0.4563904473396791,0.24500010394974975,0.413371507694714,0.23811802896220835,0.04301893964496518,0.006882074987541386,9.810799671681195,0.0797370737941638,1.3944121003233676,8.416387571357827,0.05929988423846293,0.02043718955570087,1.4537119845618307,8.436824760913527,5.0180753923393295, -HR,0.1580787880948285,18.34128786679964,4.389380056414181,1.0090057071271274,2.5476989978731437,1.318689059616855,28.847515888791193,6.237006781452905,1.6066742865068224,26.00131795404627,3.113211034470075,1.0345479474956152,0.9497163154353965,0.48100473034340274,1.0016020047136875,0.6411008353971066,8.272536625407751,5.38680865605112,0.4341687257624747,5.496189318262362,0.052814361197001926,1.8898328107958695,0.6988726986738213,2.6415198706666922,21.188430385465697,0.00018962982230924554,0.09159965703986905,13.436827525272498,0.00015599173040538647,1.8326831729199144,0.0,1.2565648624838692,3.363809190385904e-05,4.570755167749542,0.49776885579754093,0.21305012359963119,0.3313779723176993,0.15395303355572673,0.16639088347984168,0.05909709004390443,1.5213591752527897,0.005307491413879789,0.12226864940430518,1.3990905258484845,0.002843300346906715,0.002464191066973074,0.1251119497512119,1.4015547169154576,0.4627721052114323,0.04553145000000001 -HU,0.34544664961757376,51.71232046242127,9.058565274870105,2.140328474053002,5.714062255524212,2.0028906881072146,72.21082944708841,10.580042271441457,6.0852699910027175,66.5433537234814,14.356335066067029,0.16475011915334667,2.671442732381201,0.01669481559397995,3.150014039363932,0.1438143642750518,27.204656665349653,7.520276095678086,1.6199979270337255,20.586618985218344,0.5989606036781462,3.545410576534174,1.7932330983579277,5.937604278570248,38.02445666587427,0.004754012401710198,0.21252554633366075,20.378331083907437,0.0013669723377535844,3.8333953670014473,0.003313731799269432,4.637708110268266,7.330826468718214e-05,8.962496558363458,1.7569522475334471,1.1969520519059795,1.2917234069105592,0.9310232589824952,0.4652288406228879,0.2659287929234843,1.8353907709400215,0.054606555289952,0.0,1.8353907709400215,0.03396721087675474,0.020639344413197255,0.03396721087675474,1.8560301153532188,0.05833335371119447,0.0 -IE,1.1552139973989726,19.793109005806674,6.515397123991764,1.161434517801231,1.8421621718709775,0.8957692904350855,32.59953066332596,7.947985647128668,0.0,28.169618920079486,6.393256702138997,0.28535728735816485,1.6984446799638506,0.1477063007761994,1.856921735238021,0.6416420635559278,15.16447753566351,6.3577829109494655,0.0,10.2117126360729,0.47032508536436934,1.3904538819426195,0.862566607567254,2.723345574874243,40.68108342426441,0.008272205986726226,0.04426990840125408,24.407852018798376,0.007543433011813816,2.192367837492994,0.00016737978187553794,5.312891952707581,0.0005613931930368736,8.723701706864198,0.5233030297833083,0.04194485894551323,0.5099352244962404,0.04194485894551323,0.013367805287068027,0.0,7.3776188484574154,0.18094217829083742,0.018085728645439496,7.359533119811976,0.06395847585112205,0.11698370243971537,0.08204420449656154,7.476516822251692,0.2341743960240419,1.6970496000000002 -IT,1.0468206851697905,244.9130987767243,64.70816273756871,3.5257726860039496,33.711739880385224,5.298056156106979,398.1019762913365,66.98298367503608,10.821944449588157,350.87847290630515,79.03400365830159,10.16304834908569,19.572715587485437,6.461518895607246,23.010958076787716,7.348694836331663,185.82190964755122,88.9193830223242,2.2208333343889035,131.777336675836,4.840172338839531,14.844562085255594,12.704831814002475,32.38956623809759,382.16562754905397,0.12857527719351874,13.026200965629071,228.24478422974195,0.04308195860999806,25.177330023583888,0.06296249137904908,56.86449956932279,0.0016822306906727807,58.8528127607762,10.728613644333404,10.27889174413704,9.369662030497414,8.968468758742143,1.3589516138359898,1.3104229853948974,41.63152311753265,1.21375688128503,11.652418521864087,29.97910459566857,0.22427118935269547,0.9894856919323345,11.876689711216782,30.968590287600907,11.450287803031888,25.3443286 -LT,0.054268380164312624,11.715350602163216,2.5431037955938787,0.11347525483697869,1.2898906463385191,0.729637351593262,17.15320056639655,2.5910416440334036,5.404240349484153,15.549737784710798,3.6858966350176123,0.35403649213535254,0.646954859642566,0.2813772376756209,0.6491284395948164,0.5147296157717044,6.910102062603848,3.0984102546581362,1.9902252700580714,5.0040026932093715,0.14678373132394648,0.8607001311237008,0.3067145284231102,1.3141983908707575,16.47794344391527,0.07138098387942092,0.04742286954576074,11.759333998588998,2.367015705875897e-05,0.5515959910278992,0.06929945666578705,0.6262110477409603,0.0,3.49337953701165,0.6408426868412563,0.010000099960345853,0.11889710881126903,0.010000099960345853,0.5219455780299873,0.0,0.8025997207548139,0.012700327855460105,0.0,0.8025997207548139,0.007917059144158009,0.0047832687113020965,0.007917059144158009,0.807382989466116,0.05972313763724503,1.0061694500000002 -LU,0.09102207030796113,4.4582528460800175,0.5408506509033512,0.028752011719132938,0.1842589136749026,0.04414639513556391,5.784651145195065,0.9800439009093757,0.0,5.200337291213116,2.7416121696376643,0.42964741234496207,0.38754337834907376,0.13872110809105936,0.48879748143703383,0.21746057846312994,4.799602678258059,1.9924408503041833,0.7100000000000004,3.7584075376545165,0.03410552775164625,0.18906254463135402,0.05933199882242604,0.2825000712054263,25.012907547031013,0.006537582503034108,0.026090732142124796,9.61195035452163,0.0032742520029449287,0.34688378849703594,0.000672576010893665,0.4835316107788431,0.00048316442385610544,14.544451061091378,0.18787070506432504,0.12889466270463407,0.17086480068620152,0.11850807896971455,0.01700590437812352,0.010386583734919526,1.3692647775079168,2.9770867847386207,0.0,1.3692647775079168,0.14195883953447136,2.835127945204149,0.14195883953447136,4.204392722712066,0.0,0.0 -LV,0.04837569074377474,10.384613116949835,2.340644963567189,0.021113172384594966,0.6724545809684214,0.32652826749923863,14.743124497004171,1.7869997346257898,4.284217511442863,13.398134099393324,4.150995102858243,0.421817413562573,0.6219309895211804,0.18546538917869623,0.6530449380559203,0.4981204820144212,7.015731142346706,2.723629714011616,1.544950201464294,5.448903057406379,0.12993097414003488,1.024067185252895,0.6283022133780052,1.782300372770935,9.923692225555435,0.04430668304451984,0.026413105447034027,5.546359480279278,6.36983085949211e-05,0.853156946404734,0.04422967733254512,0.7124780217945105,1.0080120181086826e-05,2.785284671629878,0.8872377538316613,0.03889163480458043,0.12718689197385732,0.038891634804580424,0.7600508618578039,0.0,1.423451394923915,0.01682638285385829,0.0,1.423451394923915,0.011383099264030286,0.005443283589828004,0.011383099264030286,1.428894678513743,0.09444732504491289,2.7937818600000006 -ME,0.18428691762019353,1.6699110387853566,0.4476280894929783,0.1555359212866029,0.2968058048131801,0.20058433735409437,3.13138913,1.2769972600000001,,,0.08420605652273316,0.011619785550127245,0.01504797135378126,0.005198335075684077,0.01621943636276206,0.009143699254493983,0.15980783,0.07100115000000001,,,,,,,1.8195018700000003,0.0,0.023374743304404807,1.0703709519894518,0.0,0.08926636792867462,0.0,0.20503188721405052,0.0,0.43145791956341834,0.031866200000000004,0.020003600000000003,0.024002520016761314,0.015367348623627292,0.007863679983238687,0.004636251376372712,0.14909856022518334,0.009650939774816675,0.0,0.14909856022518334,0.0,0.009650939774816675,0.0,0.15874950000000002,0.07118723000000002,0.0 -MK,0.4423191483796166,2.8226495861922793,0.8413145426825128,0.37331199161795947,0.6356058031547073,0.48143565708557307,6.036190970000001,3.0650050900000005,,,0.9885463470402409,0.23288296163331187,0.20672486528543757,0.10418468247672413,0.2569197585883557,0.1832574063853998,2.3475271300000005,1.4230002800000001,,,,,,,5.933567850000001,0.0,0.07622725079860408,3.4905810062720652,0.0,0.29110607664715116,0.0,0.6686283945386197,0.0,1.4070251217435599,0.05284672,0.01700306,0.03980563903509613,0.013062246330083196,0.013041080964903865,0.003940813669916804,0.11322752199957879,0.00732905800042122,0.0,0.11322752199957879,0.0,0.00732905800042122,0.0,0.12055658000000001,0.0,0.0 -NL,1.6298586976689946,84.68942813303583,21.893183941383803,1.7773949260589401,9.357113200850907,1.3562324711811131,132.6887280464084,23.45301684196818,3.7844426867074854,116.07576375448231,41.256701585982235,3.4487947887252113,8.74386555749784,3.3685105382303595,9.870204039831533,4.025718619627854,84.81143946306823,36.32155823061464,1.7366658600480913,62.05804646052415,6.7784528108968365,31.684305638933232,6.298820126624233,44.7615785764543,121.86847257103743,0.048381893076100455,1.861204605302346,65.71183538795913,0.022202016959228868,3.939807489700578,0.009819762152609613,18.451060419932258,0.0038408434784715697,31.904564668143138,2.034727691797239,1.716116333742955,1.882559071473059,1.5955246718273612,0.1521686203241799,0.12059166191559394,34.92419971151198,5.748609775635073,0.0,34.92419971151198,0.3822845604365483,5.366325215198524,0.3822845604365483,40.2905249267105,4.103892187419366,152.76315521 -NO,28.804401730577776,39.45808456243531,7.757949880399734,5.663303412691806,2.5556362108232924,1.8656144339010035,52.202185400000005,38.90400146,,,26.130029515723944,19.07492154647848,3.545729560386932,2.5883825790824604,2.547165145793553,1.8594305564292937,35.12762416,26.495954460000007,,,,,,,39.489374250000004,0.028005040000000002,0.5073113699769504,23.230687369087583,0.00599875137002298,1.9373835604102068,0.018863239609742802,4.449888763994197,0.0031430490202342173,9.364103186531059,0.7961898000000001,0.6040040500000001,0.5997125986669634,0.4640135178884206,0.19647720133303667,0.13999053211157952,9.53481903369833,0.7042329663016708,3.837156822578874,5.697662211119456,0.335431317421127,0.3688016488805438,4.172588140000001,6.06646386,14.428050070000001,4.840906090000001 -PL,0.719707263764176,162.69384493310605,37.066477418290695,0.6321409759629364,19.48056221983485,7.554412836839432,237.44274247070248,28.441898996790353,48.88889712347745,219.28587265019746,51.955260494442626,8.819077017180906,8.441123332415255,3.5593519543311287,8.505633232810988,5.38704327166558,93.81952067315392,43.08232151710042,12.791391043403525,69.7380338434871,1.3424590215351815,34.01913900064919,6.315156248520575,41.67675427070494,174.29796279485242,0.06566503664190335,1.115185972116605,96.59925173251918,0.0006594983968755774,9.455957193306968,0.06495879022996191,24.85035470838785,4.674801506585862e-05,42.27721318852181,4.043880652573237,2.8530468343039725,2.283560723689119,1.8658111396792856,1.760319928884118,0.9872356946246871,6.230789077111895,0.07698608946551269,0.5481001624237407,5.682688914688154,0.03306317767518576,0.043922911790326924,0.5811633400989265,5.726611826478481,0.03611112581642298,1.6363293700000003 -PT,0.16853103420639537,6.167189443761765,6.844749403026448,0.6192555042551876,8.657967119181887,2.513361052425902,30.644647379477153,12.31396861546159,0.011388980962399788,21.88441540460838,5.314540992166446,1.8223271167970734,2.3288462896580606,1.389450501188967,2.7089567112102446,1.677792763857291,21.132756291752937,15.70110751612303,0.2966663759252526,11.94361641655254,0.8077702887437023,1.9424746346398076,2.1680579713654864,4.918302894748996,60.07163884638256,0.005796247464804267,0.6943809466998286,37.48714626049493,0.004144788310373135,1.8392478706029092,0.0014471892405585024,8.822663675857115,0.00015068153169906648,11.228200092727777,0.4119341087857363,0.29221113468922777,0.3542766997705545,0.261975695831413,0.0576574090151818,0.03023543885781476,12.04189939469445,0.24947267240484822,1.7711568990199187,10.270742495674531,0.1107532522332049,0.13871942017164332,1.8819101512531238,10.409461915846174,1.4175055568193127,7.483056010000001 -RO,0.8164119937824674,59.96132511343599,12.535594689161648,0.5966601803368272,8.287391484240173,0.6268225706774041,90.0416838937321,11.895960635306784,10.526118400572317,81.04442001456628,11.472370482472948,0.31126932980776745,2.499852646666194,0.43035561975633935,2.7719690913846016,1.1178608185175691,22.759444431153444,8.001025371554253,2.5952795750395103,16.898643459088195,0.7007809689311082,2.719627160661053,2.094159726588078,5.514567856180239,56.27724851083044,0.006095761615848004,0.21744941693675585,30.680317400032756,0.005639041540646845,11.646944255137056,0.00015561928868615372,7.116715973219791,4.505132889433588e-05,6.615821465504074,2.9624978308219267,1.0611074233348035,2.1230366871828705,0.7659474400326133,0.839461143639056,0.2951599833021901,2.424579253795485,0.029546566493058167,0.20490687455205012,2.2196723792434345,0.02497642466045021,0.004570141832607959,0.2298832992125003,2.2242425210760426,0.48333372495510224,0.48328465000000004 -RS,2.041447300754024,17.23241025134951,4.7096888757710875,1.7229567393124234,3.2058768205282546,2.221982761190753,33.10772576,14.145999310000002,,,4.436825941714843,0.8017518796993448,0.8519426499259911,0.3586791598052431,0.985253156817818,0.6309047643840355,9.346379720000002,4.898997940000001,,,,,,,22.236583260000003,0.0,0.285668530623453,13.081268662284423,0.0,1.0909464043385495,0.0,2.5057455043946524,0.0,5.272954158358922,0.5751616500000001,0.47800463000000004,0.43322796621493825,0.3672170905695961,0.14193368378506177,0.11078753943040395,0.4886500505665789,0.03162962943342115,0.0,0.4886500505665789,0.0,0.03162962943342115,0.0,0.52027968,0.10861257000000002,0.10931037 -SE,18.4203419908313,55.67334748926343,14.09700520336014,7.62928350560303,5.841710107199814,5.785689042843419,86.98471532467524,43.504196153945145,30.748061957160978,75.74261755247736,22.700405098892183,4.608878048490316,4.269153420938776,1.7706726927590173,4.374008646562861,4.286688107484913,46.05946171198871,25.491266437692087,15.6636143722038,32.15077398576433,1.0361667627692726,2.0898260280447953,1.010335904191686,4.136328695005755,83.04667870338166,0.01280258345751495,0.34320531162223467,51.05330259569601,0.0061524965671318635,6.1507365387542245,0.001514571605766908,7.009050732526921,0.002657098759479214,18.490383524782263,2.761947422261534,2.750002981435833,2.0247546969142176,2.0184609369237854,0.7371927253473161,0.7315420445120471,10.241309021150325,0.18676454919898827,1.9390076232799187,8.302301397870405,0.06947218543730693,0.11729236376168135,2.0084798087172255,8.419593761632086,0.7977769681471846,18.578494690000003 -SI,0.34227433442339894,8.376475064050604,2.9220707579747884,0.453818512537254,0.8699951748952809,0.5648060322082612,13.995062824999088,3.2289764898849858,0.9472293430810873,12.239285152226612,2.570621989760942,0.6007517589071416,0.5133561218151605,0.18953808270509473,0.647701991765941,0.48074261627130094,5.65765380957795,3.2179778886185555,0.5774928791411378,3.880746457492038,0.0,0.549946125291897,0.2641860340673345,0.8141321593592316,20.80700782789383,0.00010110043502486967,0.09327831893642177,11.880939237809546,8.371504104872192e-05,0.7193026858478071,0.0,0.9960279918658297,0.0,7.117459593434226,0.27222489410492606,0.15389153928786237,0.14979465172003809,0.07389407828151527,0.12243024238488796,0.0799974610063471,0.3099300394503224,0.004512821170390541,0.0,0.3099300394503224,0.0028361068079113625,0.0016767143624791794,0.0028361068079113625,0.3116067538128016,0.0,0.7076273500000001 -SK,0.7110244219256427,16.322019247760963,3.9420025260381517,0.4761557307462169,1.9667320357371187,0.7020969879798182,24.976139305348433,4.930015666329864,5.806117943917119,22.24202848390687,12.395946919792488,1.59350805554285,1.5814611823385478,0.7318096909411619,1.591685689729668,0.771687906762327,19.888551870977174,7.539329752327933,1.1225013209917258,15.78104264329495,0.21327589995852728,0.8694320240429981,0.44148890889017306,1.5241968328916984,23.792769864038295,0.03763800097049386,0.03401005608446167,9.914745300376103,6.220464867834378e-05,1.7151976456935867,0.0375611283634322,2.3748436290651527,1.0622037973027887e-05,9.753973232818993,0.5388822140190512,0.5388822140190512,0.37230773469849826,0.37230773469849826,0.166574479320553,0.166574479320553,0.46763946179091403,0.01347991726152616,0.0,0.46763946179091403,0.010194585747323313,0.003285331514202844,0.010194585747323313,0.4709247933051169,0.18577762000000003,0.0 From a5d0f07fe13f39cbc437c218324df90195646fb4 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 15:29:27 +0100 Subject: [PATCH 453/591] build_cutout: revert to master version --- scripts/build_cutout.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/build_cutout.py b/scripts/build_cutout.py index 80ddae34..1edb18ce 100644 --- a/scripts/build_cutout.py +++ b/scripts/build_cutout.py @@ -109,11 +109,9 @@ if __name__ == "__main__": cutout_params = snakemake.params.cutouts[snakemake.wildcards.cutout] - if "time" not in cutout_params: - snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) - cutout_params["time"] = [snapshots[0], snapshots[-1]] - - cutout_params["time"] = slice(*cutout_params["time"]) + snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) + time = [snapshots[0], snapshots[-1]] + cutout_params["time"] = slice(*cutout_params.get("time", time)) if {"x", "y", "bounds"}.isdisjoint(cutout_params): # Determine the bounds from bus regions with a buffer of two grid cells From 57b487f1638dbf998927d5fdb4a3afaf5b94db64 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 15:38:36 +0100 Subject: [PATCH 454/591] handle leap days in temporal clustering --- rules/build_electricity.smk | 1 + scripts/prepare_network.py | 3 +++ scripts/prepare_sector_network.py | 7 +++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 6db8bcd7..2b4d9af6 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -588,6 +588,7 @@ rule prepare_network: costs=config_provider("costs"), adjustments=config_provider("adjustments", "electricity"), autarky=config_provider("electricity", "autarky", default={}), + drop_leap_day=config_provider("enable", "drop_leap_day"), input: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), tech_costs=lambda w: resources( diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index f38a3619..f7a3f6b0 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -204,6 +204,9 @@ def average_every_nhours(n, offset): m = n.copy(with_time=False) snapshot_weightings = n.snapshot_weightings.resample(offset).sum() + sns = snapshot_weightings.index + if snakemake.params.drop_leap_days: + sns = sns[~((sns.month == 2) & (sns.day == 29))] m.set_snapshots(snapshot_weightings.index) m.snapshot_weightings = snapshot_weightings diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 5757a88b..e5f0dac8 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -812,6 +812,10 @@ def average_every_nhours(n, offset): m = n.copy(with_time=False) snapshot_weightings = n.snapshot_weightings.resample(offset).sum() + sns = snapshot_weightings.index + if snakemake.params.drop_leap_days: + sns = sns[~((sns.month == 2) & (sns.day == 29))] + snapshot_weightings = snapshot_weightings.loc[sns] m.set_snapshots(snapshot_weightings.index) m.snapshot_weightings = snapshot_weightings @@ -3660,8 +3664,7 @@ if __name__ == "__main__": solver_name = snakemake.config["solving"]["solver"]["name"] resolution = snakemake.params.time_resolution - drop_leap_day = snakemake.params.drop_leap_day - n = set_temporal_aggregation(n, resolution, solver_name, drop_leap_day) + n = set_temporal_aggregation(n, resolution, solver_name) co2_budget = snakemake.params.co2_budget if isinstance(co2_budget, str) and co2_budget.startswith("cb"): From 4fbb3c81c4ddb589614f67dc01c885c9b3806bbe Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 16:48:32 +0100 Subject: [PATCH 455/591] fix build_district_heat_share and build_transport_demand for multiyear --- rules/build_sector.smk | 4 ++++ scripts/build_district_heat_share.py | 7 +++---- scripts/build_energy_totals.py | 19 +++++++++++++++++-- ...build_population_weighted_energy_totals.py | 2 +- scripts/build_transport_demand.py | 10 ++++++---- scripts/prepare_network.py | 2 +- scripts/prepare_sector_network.py | 2 +- 7 files changed, 33 insertions(+), 13 deletions(-) diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 14226ef8..e1575a78 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -729,6 +729,8 @@ rule build_retro_cost: rule build_population_weighted_energy_totals: + params: + snapshots=config_provider("snapshots"), input: energy_totals=resources("{kind}_totals.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), @@ -771,6 +773,7 @@ rule build_transport_demand: snapshots=config_provider("snapshots"), drop_leap_day=config_provider("enable", "drop_leap_day"), sector=config_provider("sector"), + energy_totals_year=config_provider("energy", "energy_totals_year"), input: clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), pop_weighted_energy_totals=resources( @@ -799,6 +802,7 @@ rule build_transport_demand: rule build_district_heat_share: params: sector=config_provider("sector"), + energy_totals_year=config_provider("energy", "energy_totals_year"), input: district_heat_share=resources("district_heat_share.csv"), clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index 3cf88466..10a30915 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -22,7 +22,7 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_district_heat_share", simpl="", - clusters=48, + clusters=60, planning_horizons="2050", ) configure_logging(snakemake) @@ -32,9 +32,8 @@ if __name__ == "__main__": pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) - district_heat_share = pd.read_csv(snakemake.input.district_heat_share, index_col=0)[ - "district heat share" - ] + year = str(snakemake.params.energy_totals_year) + district_heat_share = pd.read_csv(snakemake.input.district_heat_share, index_col=0)[year] # make ct-based share nodal district_heat_share = district_heat_share.reindex(pop_layout.ct).fillna(0) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 01532872..a53c6208 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -721,10 +721,18 @@ def build_transport_data(countries, population, idees): transport_data = pd.DataFrame(idees["passenger cars"]) + countries_without_ch = set(countries) - {"CH"} + new_index = pd.MultiIndex.from_product( + [countries_without_ch, transport_data.index.levels[1]], + names=["country", "year"] + ) + + transport_data = transport_data.reindex(index=new_index) + # https://www.bfs.admin.ch/bfs/en/home/statistics/mobility-transport/transport-infrastructure-vehicles/vehicles/road-vehicles-stock-level-motorisation.html if "CH" in countries: fn = snakemake.input.swiss_transport - swiss_cars = pd.read_csv(fn, index_col=0).loc[1990:2021, ["passenger cars"]] + swiss_cars = pd.read_csv(fn, index_col=0).loc[2000:2015, ["passenger cars"]] swiss_cars.index = pd.MultiIndex.from_product( [["CH"], swiss_cars.index], names=["country", "year"] @@ -741,7 +749,14 @@ def build_transport_data(countries, population, idees): ) cars_pp = transport_data["number cars"] / population - transport_data.loc[missing, "number cars"] = cars_pp.mean() * population + + fill_values = {year: cars_pp.mean() * population for year in transport_data.index.levels[1]} + fill_values = pd.DataFrame(fill_values).stack() + fill_values = pd.DataFrame(fill_values, columns=["number cars"]) + fill_values.index.names = ["country", "year"] + fill_values = fill_values.reindex(transport_data.index) + + transport_data = transport_data.combine_first(fill_values) # collect average fuel efficiency in kWh/km diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 70105a06..69d4c681 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -15,7 +15,7 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_population_weighted_energy_totals", - kind="energy", + kind="heat", simpl="", clusters=60, ) diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index e39774fa..085a0954 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -23,8 +23,9 @@ from _helpers import ( logger = logging.getLogger(__name__) -def build_nodal_transport_data(fn, pop_layout): - transport_data = pd.read_csv(fn, index_col=0) +def build_nodal_transport_data(fn, pop_layout, year): + transport_data = pd.read_csv(fn, index_col=[0, 1]) + transport_data = transport_data.xs(min(2015, year), level='year') nodal_transport_data = transport_data.loc[pop_layout.ct].fillna(0.0) nodal_transport_data.index = pop_layout.index @@ -173,7 +174,7 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_transport_demand", simpl="", - clusters=48, + clusters=60, ) configure_logging(snakemake) set_scenario_config(snakemake) @@ -194,8 +195,9 @@ if __name__ == "__main__": nyears = len(snapshots) / 8760 + energy_totals_year = snakemake.params.energy_totals_year nodal_transport_data = build_nodal_transport_data( - snakemake.input.transport_data, pop_layout + snakemake.input.transport_data, pop_layout, energy_totals_year ) transport_demand = build_transport_demand( diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index f7a3f6b0..00cb00bf 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -205,7 +205,7 @@ def average_every_nhours(n, offset): snapshot_weightings = n.snapshot_weightings.resample(offset).sum() sns = snapshot_weightings.index - if snakemake.params.drop_leap_days: + if snakemake.params.drop_leap_day: sns = sns[~((sns.month == 2) & (sns.day == 29))] m.set_snapshots(snapshot_weightings.index) m.snapshot_weightings = snapshot_weightings diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index e5f0dac8..ceb7764e 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -813,7 +813,7 @@ def average_every_nhours(n, offset): snapshot_weightings = n.snapshot_weightings.resample(offset).sum() sns = snapshot_weightings.index - if snakemake.params.drop_leap_days: + if snakemake.params.drop_leap_day: sns = sns[~((sns.month == 2) & (sns.day == 29))] snapshot_weightings = snapshot_weightings.loc[sns] m.set_snapshots(snapshot_weightings.index) From 1496c585d03b60a1992a350a942872eb867a76a9 Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Thu, 14 Mar 2024 16:56:00 +0100 Subject: [PATCH 456/591] Fix duplicated years in add_land_use_constraint_m --- doc/release_notes.rst | 2 ++ scripts/solve_network.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index ad1bbf4f..5682d788 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -106,6 +106,8 @@ Upcoming Release * Adapt the disabling of transmission expansion in myopic foresight optimisations when limit is already reached to also handle cost limits. +* Fix duplicated years in `add_land_use_constraint_m`. + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 7e53e606..7adf492a 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -165,7 +165,7 @@ def _add_land_use_constraint_m(n, planning_horizons, config): previous_years = [ str(y) - for y in planning_horizons + grouping_years + for y in set(planning_horizons + grouping_years) if y < int(snakemake.wildcards.planning_horizons) ] From 115dd8d11643225a73f39616991f61f123de2e3e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 17:15:24 +0100 Subject: [PATCH 457/591] handle case when only artifical load must be loaded --- scripts/build_electricity_demand.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 2d3da224..8d61e770 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -183,7 +183,7 @@ def manual_adjustment(load, fn_load, countries): elif "MK" in load: load["AL"] = load["MK"] * (4.1 / 7.4) - if "MK" in countries: + if "MK" in countries and "MK" in countries: if "MK" not in load or load.MK.isnull().sum() > len(load) / 2: if "ME" in load: load["MK"] = load.ME * (6.7 / 2.9) @@ -192,7 +192,7 @@ def manual_adjustment(load, fn_load, countries): if "ME" in load: load["BA"] = load.HR * (11.0 / 16.2) - if "KV" not in load or load.KV.isnull().values.all(): + if ("KV" not in load or load.KV.isnull().values.all()) and "KV" in countries: if "RS" in load: load["KV"] = load["RS"] * (4.8 / 27.0) @@ -267,7 +267,7 @@ if __name__ == "__main__": snakemake.params.snapshots, snakemake.params.drop_leap_day ) - fixed_year = snakemake.config["load"].get("fixed_year", False) + fixed_year = snakemake.params["load"].get("fixed_year", False) years = ( slice(str(fixed_year), str(fixed_year)) if fixed_year @@ -281,6 +281,8 @@ if __name__ == "__main__": load = load_timeseries(snakemake.input.reported, years, countries) + load = load.reindex(index=snapshots) + if "UA" in countries: # attach load of UA (best data only for entsoe transparency) load_ua = load_timeseries(snakemake.input.reported, "2018", ["UA"]) @@ -297,9 +299,6 @@ if __name__ == "__main__": if snakemake.params.load["manual_adjustments"]: load = manual_adjustment(load, snakemake.input[0], countries) - if load.empty: - logger.warning("Build electricity demand time series is empty.") - logger.info(f"Linearly interpolate gaps of size {interpolate_limit} and less.") load = load.interpolate(method="linear", limit=interpolate_limit) From 88dba985121847067317a9e423f63043b2d32140 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 18:11:02 +0100 Subject: [PATCH 458/591] fix for CI --- scripts/build_energy_totals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index a53c6208..19fc5a8e 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -419,7 +419,7 @@ def build_energy_totals(countries, eurostat, swiss, idees): # add swiss energy data - df = pd.concat([df.drop("CH"), swiss]).sort_index() + df = pd.concat([df.drop("CH", errors='ignore'), swiss]).sort_index() # get values for missing countries based on Eurostat EnergyBalances # divide cooking/space/water according to averages in EU28 From a6ea15ea4a811a4874209c780c5ea42958092d4c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 17:11:26 +0000 Subject: [PATCH 459/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/build_district_heat_share.py | 4 +++- scripts/build_energy_totals.py | 8 +++++--- scripts/build_transport_demand.py | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/build_district_heat_share.py b/scripts/build_district_heat_share.py index 10a30915..178f2c0d 100644 --- a/scripts/build_district_heat_share.py +++ b/scripts/build_district_heat_share.py @@ -33,7 +33,9 @@ if __name__ == "__main__": pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) year = str(snakemake.params.energy_totals_year) - district_heat_share = pd.read_csv(snakemake.input.district_heat_share, index_col=0)[year] + district_heat_share = pd.read_csv(snakemake.input.district_heat_share, index_col=0)[ + year + ] # make ct-based share nodal district_heat_share = district_heat_share.reindex(pop_layout.ct).fillna(0) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index 19fc5a8e..dda84a53 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -419,7 +419,7 @@ def build_energy_totals(countries, eurostat, swiss, idees): # add swiss energy data - df = pd.concat([df.drop("CH", errors='ignore'), swiss]).sort_index() + df = pd.concat([df.drop("CH", errors="ignore"), swiss]).sort_index() # get values for missing countries based on Eurostat EnergyBalances # divide cooking/space/water according to averages in EU28 @@ -724,7 +724,7 @@ def build_transport_data(countries, population, idees): countries_without_ch = set(countries) - {"CH"} new_index = pd.MultiIndex.from_product( [countries_without_ch, transport_data.index.levels[1]], - names=["country", "year"] + names=["country", "year"], ) transport_data = transport_data.reindex(index=new_index) @@ -750,7 +750,9 @@ def build_transport_data(countries, population, idees): cars_pp = transport_data["number cars"] / population - fill_values = {year: cars_pp.mean() * population for year in transport_data.index.levels[1]} + fill_values = { + year: cars_pp.mean() * population for year in transport_data.index.levels[1] + } fill_values = pd.DataFrame(fill_values).stack() fill_values = pd.DataFrame(fill_values, columns=["number cars"]) fill_values.index.names = ["country", "year"] diff --git a/scripts/build_transport_demand.py b/scripts/build_transport_demand.py index 085a0954..35f22a80 100644 --- a/scripts/build_transport_demand.py +++ b/scripts/build_transport_demand.py @@ -25,7 +25,7 @@ logger = logging.getLogger(__name__) def build_nodal_transport_data(fn, pop_layout, year): transport_data = pd.read_csv(fn, index_col=[0, 1]) - transport_data = transport_data.xs(min(2015, year), level='year') + transport_data = transport_data.xs(min(2015, year), level="year") nodal_transport_data = transport_data.loc[pop_layout.ct].fillna(0.0) nodal_transport_data.index = pop_layout.index From 8d85acc61aa0252181c2d8da5f7702242dd1bbad Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 18:19:25 +0100 Subject: [PATCH 460/591] remove unused keyword argument in temporal aggregation [no ci] --- 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 ceb7764e..4e7e0374 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3486,7 +3486,7 @@ def apply_time_segmentation( return n -def set_temporal_aggregation(n, resolution, solver_name, drop_leap_day=False): +def set_temporal_aggregation(n, resolution, solver_name): """ Aggregate network temporally. """ From 02fc334a2e6bd0669babc1d817026c0d0102e702 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 18:46:45 +0100 Subject: [PATCH 461/591] handle leap days in add_brownfield --- rules/solve_myopic.smk | 1 + scripts/add_brownfield.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 57b8a9d3..eec1aca1 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -70,6 +70,7 @@ rule add_brownfield: ), threshold_capacity=config_provider("existing_capacities", " threshold_capacity"), snapshots=config_provider("snapshots"), + drop_leap_day=config_provider("enable", "drop_leap_day"), carriers=config_provider("electricity", "renewable_carriers"), input: unpack(input_profile_tech_brownfield), diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 1bccf563..c607132c 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -14,6 +14,7 @@ import pypsa import xarray as xr from _helpers import ( configure_logging, + get_snapshots set_scenario_config, update_config_from_wildcards, ) @@ -192,7 +193,7 @@ def adjust_renewable_profiles(n, input_profiles, params, year): clustermaps.index = clustermaps.index.astype(str) # temporal clustering - dr = pd.date_range(**params["snapshots"], freq="h") + dr = get_snapshots(params["snapshots"], params["drop_leap_day"]) snapshotmaps = ( pd.Series(dr, index=dr).where(lambda x: x.isin(n.snapshots), pd.NA).ffill() ) From f74e2f1bb7b7fee97a7d1c748a3ea3ef03baf5c7 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 18:47:09 +0100 Subject: [PATCH 462/591] build_heat_totals: allow subset of countries --- scripts/build_heat_totals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_heat_totals.py b/scripts/build_heat_totals.py index d0dab987..9bee63e5 100644 --- a/scripts/build_heat_totals.py +++ b/scripts/build_heat_totals.py @@ -16,7 +16,7 @@ idx = pd.IndexSlice def approximate_heat_demand(energy_totals, hdd): - countries = hdd.columns + countries = hdd.columns.intersection(energy_totals.index.levels[0]) demands = {} From f7e617befd090545ad5ecfb8169324d65fa67873 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 18:52:25 +0100 Subject: [PATCH 463/591] make_summary: add drop_leap_day param --- rules/postprocess.smk | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 1b188829..6d239a54 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -156,6 +156,7 @@ rule make_summary: foresight=config_provider("foresight"), costs=config_provider("costs"), snapshots=config_provider("snapshots"), + drop_leap_day=config_provider("enable", "drop_leap_day"), scenario=config_provider("scenario"), RDIR=RDIR, input: From 7587f2c6becb6d2bca565f3aacccdb1a16b27d3f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 18:52:59 +0100 Subject: [PATCH 464/591] pop_weighted_energy_totals: feasible for sub-annual temporal scope --- scripts/build_population_weighted_energy_totals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_population_weighted_energy_totals.py b/scripts/build_population_weighted_energy_totals.py index 69d4c681..60af66aa 100644 --- a/scripts/build_population_weighted_energy_totals.py +++ b/scripts/build_population_weighted_energy_totals.py @@ -24,7 +24,7 @@ if __name__ == "__main__": config = snakemake.config["energy"] if snakemake.wildcards.kind == "heat": - years = pd.date_range(freq="YE", **snakemake.params.snapshots).year + years = pd.date_range(freq="h", **snakemake.params.snapshots).year.unique() assert len(years) == 1, "Currently only works for single year." data_year = years[0] else: From 0bbda371d4a789a2e70a6d074a3d426842672450 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 17:54:14 +0000 Subject: [PATCH 465/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/add_brownfield.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index c607132c..82a40e57 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -14,7 +14,7 @@ import pypsa import xarray as xr from _helpers import ( configure_logging, - get_snapshots + get_snapshots, set_scenario_config, update_config_from_wildcards, ) From 63072f2224eb1424cd1cdb9739de6ac00ad41b9d Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 19:06:21 +0100 Subject: [PATCH 466/591] fix syntax mistake --- scripts/add_brownfield.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index c607132c..82a40e57 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -14,7 +14,7 @@ import pypsa import xarray as xr from _helpers import ( configure_logging, - get_snapshots + get_snapshots, set_scenario_config, update_config_from_wildcards, ) From a2f97ad1b38d6d3ddeccbc4d7ee665549a211cb1 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 14 Mar 2024 19:24:37 +0100 Subject: [PATCH 467/591] make build_eurostat independent of snakemake object to be imported --- scripts/build_energy_totals.py | 14 ++++++++------ scripts/prepare_sector_network.py | 15 +++++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index dda84a53..abab06e4 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -84,22 +84,19 @@ def eurostat_per_country(input_eurostat, country): return pd.concat(sheet) -def build_eurostat(input_eurostat, countries): +def build_eurostat(input_eurostat, countries, nprocesses=1, disable_progressbar=False): """ Return multi-index for all countries' energy data in TWh/a. """ countries = {idees_rename.get(country, country) for country in countries} - {"CH"} - nprocesses = snakemake.threads - disable_progress = snakemake.config["run"].get("disable_progressbar", False) - func = partial(eurostat_per_country, input_eurostat) tqdm_kwargs = dict( ascii=False, unit=" country", total=len(countries), desc="Build from eurostat database", - disable=disable_progress, + disable=disable_progressbar, ) with mute_print(): with mp.Pool(processes=nprocesses) as pool: @@ -953,7 +950,12 @@ if __name__ == "__main__": idees_countries = pd.Index(countries).intersection(eu28) input_eurostat = snakemake.input.eurostat - eurostat = build_eurostat(input_eurostat, countries) + eurostat = build_eurostat( + input_eurostat, + countries, + nprocesses=snakemake.threads, + disable_progressbar=snakemake.config["run"].get("disable_progressbar", False), + ) swiss = build_swiss() idees = build_idees(idees_countries) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 4e7e0374..b6ec98b2 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -23,7 +23,12 @@ from _helpers import ( update_config_from_wildcards, ) from add_electricity import calculate_annuity, sanitize_carriers, sanitize_locations -from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 +from build_energy_totals import ( + build_co2_totals, + build_eea_co2, + build_eurostat, + build_eurostat_co2, +) from networkx.algorithms import complement from networkx.algorithms.connectivity.edge_augmentation import k_edge_augmentation from prepare_network import maybe_adjust_costs_and_potentials @@ -255,12 +260,10 @@ def co2_emissions_year( """ eea_co2 = build_eea_co2(input_co2, year, emissions_scope) - # TODO: read Eurostat data from year > 2014 + eurostat = build_eurostat(input_eurostat, countries) + # this only affects the estimation of CO2 emissions for BA, RS, AL, ME, MK - if year > 2014: - eurostat_co2 = build_eurostat_co2(input_eurostat, countries, 2014) - else: - eurostat_co2 = build_eurostat_co2(input_eurostat, countries, year) + eurostat_co2 = build_eurostat_co2(eurostat, year) co2_totals = build_co2_totals(countries, eea_co2, eurostat_co2) From 97d876d4e5dce2c2b7eaad452e159a918a9fd8aa Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 15 Mar 2024 11:44:41 +0100 Subject: [PATCH 468/591] update synthetic load data to cover 1941-2023 --- rules/retrieve.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 76069c6f..e6f46aaa 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -199,7 +199,7 @@ if config["enable"]["retrieve"]: rule retrieve_artificial_load_data: input: storage( - "https://zenodo.org/record/7070438/files/demand_hourly.csv", + "https://zenodo.org/records/10820928/files/demand_hourly.csv", keep_local=True, ), output: From ee55bba56827fa03105d79beda9b87f785cb0f1e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 15 Mar 2024 12:04:25 +0100 Subject: [PATCH 469/591] omit synthetic load data md5 validation --- rules/retrieve.smk | 2 -- 1 file changed, 2 deletions(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index e6f46aaa..4724d8db 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -200,7 +200,6 @@ if config["enable"]["retrieve"]: input: storage( "https://zenodo.org/records/10820928/files/demand_hourly.csv", - keep_local=True, ), output: "data/load_artificial_raw.csv", @@ -211,7 +210,6 @@ if config["enable"]["retrieve"]: retries: 2 run: move(input[0], output[0]) - validate_checksum(output[0], input[0]) if config["enable"]["retrieve"]: From 3a5465371114627377a6ac03817dde05f16bd2a0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 15 Mar 2024 13:50:27 +0100 Subject: [PATCH 470/591] fix shared resources for scenario management with {kind} wildcard --- scripts/_helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 09687a11..d03a306b 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -60,7 +60,7 @@ def get_run_path(fn, dir, rdir, shared_resources): if shared_resources == "base": pattern = r"\{([^{}]+)\}" existing_wildcards = set(re.findall(pattern, fn)) - irrelevant_wildcards = {"technology", "year", "scope"} + irrelevant_wildcards = {"technology", "year", "scope", "kind"} no_relevant_wildcards = not existing_wildcards - irrelevant_wildcards no_elec_rule = not fn.startswith("networks/elec") and not fn.startswith( "add_electricity" @@ -68,7 +68,7 @@ def get_run_path(fn, dir, rdir, shared_resources): is_shared = no_relevant_wildcards and no_elec_rule elif isinstance(shared_resources, str): rdir = shared_resources + "/" - is_shared = True + is_shared = False elif isinstance(shared_resources, bool): is_shared = shared_resources else: From f50ee2f22551ba1dc73f32fa3b774853a1ebc960 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 15 Mar 2024 13:50:53 +0100 Subject: [PATCH 471/591] do not use log() for config independent retrieve rules --- rules/retrieve.smk | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 4724d8db..0a7cdf6a 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -168,7 +168,7 @@ if config["enable"]["retrieve"]: output: expand("data/gas_network/scigrid-gas/data/{files}", files=datafiles), log: - logs("retrieve_gas_infrastructure_data.log"), + "logs/retrieve_gas_infrastructure_data.log", retries: 2 conda: "../envs/retrieve.yaml" @@ -184,7 +184,7 @@ if config["enable"]["retrieve"]: output: "data/electricity_demand_raw.csv", log: - logs("retrieve_electricity_demand.log"), + "logs/retrieve_electricity_demand.log", resources: mem_mb=5000, retries: 2 @@ -204,7 +204,7 @@ if config["enable"]["retrieve"]: output: "data/load_artificial_raw.csv", log: - logs("retrieve_artificial_load_data.log"), + "logs/retrieve_artificial_load_data.log", resources: mem_mb=5000, retries: 2 @@ -223,7 +223,7 @@ if config["enable"]["retrieve"]: output: protected("data/shipdensity_global.zip"), log: - logs("retrieve_ship_raster.log"), + "logs/retrieve_ship_raster.log", resources: mem_mb=5000, retries: 2 @@ -351,7 +351,7 @@ if config["enable"]["retrieve"]: output: "data/validation/emission-spot-primary-market-auction-report-2019-data.xls", log: - logs("retrieve_monthly_co2_prices.log"), + "logs/retrieve_monthly_co2_prices.log", resources: mem_mb=5000, retries: 2 @@ -365,7 +365,7 @@ if config["enable"]["retrieve"]: output: "data/validation/energy-price-trends-xlsx-5619002.xlsx", log: - logs("retrieve_monthly_fuel_prices.log"), + "logs/retrieve_monthly_fuel_prices.log", resources: mem_mb=5000, retries: 2 From e459c3c89d11a7ff159de97718ce2807b689d27a Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 15 Mar 2024 14:28:01 +0100 Subject: [PATCH 472/591] add release notes; rename artificial to synthetic --- config/config.default.yaml | 2 +- doc/configtables/load.csv | 2 +- doc/release_notes.rst | 46 +++++++++++++++++++++++++++++ doc/sector.rst | 5 ++++ rules/build_electricity.smk | 6 ++-- rules/retrieve.smk | 6 ++-- scripts/build_electricity_demand.py | 12 ++++---- 7 files changed, 65 insertions(+), 14 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index da2e20f1..a8cd195c 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -292,7 +292,7 @@ load: manual_adjustments: true # false scaling_factor: 1.0 fixed_year: false # false or year (e.g. 2013) - supplement_missing_data_artificially: true + supplement_synthetic: true # docs # TODO: PyPSA-Eur merge issue in prepare_sector_network.py diff --git a/doc/configtables/load.csv b/doc/configtables/load.csv index 02e7b97b..34d73dc5 100644 --- a/doc/configtables/load.csv +++ b/doc/configtables/load.csv @@ -4,4 +4,4 @@ time_shift_for_large_gaps,string,string,"Periods which are used for copying time manual_adjustments,bool,"{true, false}","Whether to adjust the load data manually according to the function in :func:`manual_adjustment`." scaling_factor,--,float,"Global correction factor for the load time series." fixed_year,--,Year or False,"To specify a fixed year for the load time series that deviates from the snapshots' year" -supplement_missing_data_artificially,bool,"{true, false}","Whether to supplement missing data for selected time period should be supplemented by artificial data from https://zenodo.org/record/7070438/files/demand_hourly.csv." +supplement_synthetic,bool,"{true, false}","Whether to supplement missing data for selected time period should be supplemented by synthetic data from https://zenodo.org/record/10820928." diff --git a/doc/release_notes.rst b/doc/release_notes.rst index ad1bbf4f..a5cb9273 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,52 @@ Release Notes Upcoming Release ================ +* Enhanced support for choosing different weather years + (https://github.com/PyPSA/pypsa-eur/pull/204): + + - Processed energy statistics from eurostat (1990-2021) and IDEES (2000-2015) + are now initially stored for all available years and filtered by the year + given in ``energy: energy_totals_year:``. + + - Added option to supplement electricity load data with synthetic time series + for years not contained in OPSD (from https://zenodo.org/records/10820928, + ``load: supplement_synthetic:``). + + - The total annual heat demand for years not contained in the energy + statistics by eurostat (1990-2021) or IDEES (2000-2015) are scaled based on + a regression between the total number of heating degree days and the total + annual heat demand between the years 2007-2021, assuming a similar building + stock. + + - Added option to scale annual hydro-electricity generation data for years not + contained in the in EIA (1980-2021) based on a regression between annual + generation and total runoff per country for the years 1980-2021 + (``renewable: hydro: eia_approximate_missing:``) + + - Added option to normalize annual hydro generation data by the associated + installed capacity reported by EIA (1980-2021) in order to eliminate changes + in generation due to newly built capacity (``renewable: hydro: + eia_approximate_missing: eia_correct_by_capacity:``). + + - Added option to make hydro generation data independent of weather year + (``renewable: hydro: eia_approximate_missing: eia_norm_year:``). + + - Added option to drop leap days (``enable: drop_leap_day:``). + + - Added option to make electric load data independent of weather year + (``load: fixed_year:``). + + - Include time series of Swiss number of passenger vehicles from the `Swiss + Federal Statistical Office + `_. + + - Updated hydro-electricity generation and capacity data from EIA. + + - The easiest way to sweep over multiple weather years is to use the new + scenario management. An example for the necessary `create_scenarios.py` + script can be found in this `Github gist + `_. + * Upgrade to Snakemake v8.5+. This version is the new minimum version required. To upgrade an existing environment, run ``conda install -c bioconda snakemake-minimal">=8.5"`` and ``pip install snakemake-storage-plugin-http`` diff --git a/doc/sector.rst b/doc/sector.rst index 84a5fdc9..7a04a580 100644 --- a/doc/sector.rst +++ b/doc/sector.rst @@ -56,6 +56,11 @@ Rule ``build_energy_totals`` .. automodule:: build_energy_totals +Rule ``build_heat_totals`` +============================================================================== + +.. automodule:: build_heat_totals + Rule ``build_gas_input_locations`` ============================================================================== diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 2b4d9af6..f84a9969 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -26,9 +26,9 @@ rule build_electricity_demand: load=config_provider("load"), input: reported=ancient("data/electricity_demand_raw.csv"), - artificial=lambda w: ( - ancient("data/load_artificial_raw.csv") - if config_provider("load", "supplement_missing_data_artificially")(w) + synthetic=lambda w: ( + ancient("data/load_synthetic_raw.csv") + if config_provider("load", "supplement_synthetic")(w) else [] ), output: diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 0a7cdf6a..b2c1e8d6 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -196,15 +196,15 @@ if config["enable"]["retrieve"]: if config["enable"]["retrieve"]: - rule retrieve_artificial_load_data: + rule retrieve_synthetic_electricity_demand: input: storage( "https://zenodo.org/records/10820928/files/demand_hourly.csv", ), output: - "data/load_artificial_raw.csv", + "data/load_synthetic_raw.csv", log: - "logs/retrieve_artificial_load_data.log", + "logs/retrieve_synthetic_electricity_demand.log", resources: mem_mb=5000, retries: 2 diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 8d61e770..9174672d 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -307,12 +307,12 @@ if __name__ == "__main__": ) load = load.apply(fill_large_gaps, shift=time_shift) - if snakemake.params.load["supplement_missing_data_artificially"]: - logger.info("Supplement missing data with artificial data.") - fn = snakemake.input.artificial - artificial_load = pd.read_csv(fn, index_col=0, parse_dates=True) - artificial_load = artificial_load.loc[snapshots, countries] - load = load.combine_first(artificial_load) + if snakemake.params.load["supplement_synthetic"]: + logger.info("Supplement missing data with synthetic data.") + fn = snakemake.input.synthetic + synthetic_load = pd.read_csv(fn, index_col=0, parse_dates=True) + synthetic_load = synthetic_load.loc[snapshots, countries] + load = load.combine_first(synthetic_load) assert not load.isna().any().any(), ( "Load data contains nans. Adjust the parameters " From 941de04859e15a97a8db3dc464731bf1a5bd96af Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 18 Mar 2024 10:37:08 +0100 Subject: [PATCH 473/591] Don't use log path function in IRENA retrieval rule The `logs` function returns a path with a {run} wildcard which is not present in the output of the retrieval rule. Follows f50ee2f2. --- rules/retrieve.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index b2c1e8d6..ac296f79 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -50,7 +50,7 @@ if config["enable"].get("retrieve_irena"): onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", solar="data/existing_infrastructure/solar_capacity_IRENA.csv", log: - logs("retrieve_irena.log"), + "logs/retrieve_irena.log", resources: mem_mb=1000, retries: 2 From ce549cd9494228998ee6689d095ca06c171fff11 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 18 Mar 2024 10:00:42 +0100 Subject: [PATCH 474/591] Allow the retrieval of cost data from forks of technology-data --- scripts/retrieve_cost_data.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/retrieve_cost_data.py b/scripts/retrieve_cost_data.py index eb1ef041..39fcab7c 100644 --- a/scripts/retrieve_cost_data.py +++ b/scripts/retrieve_cost_data.py @@ -25,9 +25,10 @@ if __name__ == "__main__": set_scenario_config(snakemake) version = snakemake.params.version - baseurl = ( - f"https://raw.githubusercontent.com/PyPSA/technology-data/{version}/outputs/" - ) + if "/" in version: + baseurl = f"https://raw.githubusercontent.com/{version}/outputs" + else: + baseurl = f"https://raw.githubusercontent.com/PyPSA/technology-data/{version}/outputs/" filepath = Path(snakemake.output[0]) url = baseurl + filepath.name From 1f499eda6ffb20ed81c15a1b6a3a8557a53e18d4 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 18 Mar 2024 13:31:04 +0100 Subject: [PATCH 475/591] Document new handling of costs version config option --- doc/configtables/costs.csv | 2 +- doc/release_notes.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/configtables/costs.csv b/doc/configtables/costs.csv index b69c0bf9..03933c18 100644 --- a/doc/configtables/costs.csv +++ b/doc/configtables/costs.csv @@ -1,6 +1,6 @@ ,Unit,Values,Description year,--,YYYY; e.g. '2030',Year for which to retrieve cost assumptions of ``resources/costs.csv``. -version,--,vX.X.X; e.g. 'v0.5.0',Version of ``technology-data`` repository to use. +version,--,vX.X.X or //vX.X.X; e.g. 'v0.5.0',Version of ``technology-data`` repository to use. If this string is of the form // then costs are instead retrieved from ``github.com//`` at the tag. rooftop_share,--,float,Share of rooftop PV when calculating capital cost of solar (joint rooftop and utility-scale PV). social_discountrate,p.u.,float,Social discount rate to compare costs in different investment periods. 0.02 corresponds to a social discount rate of 2%. fill_values,--,float,Default values if not specified for a technology in ``resources/costs.csv``. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 11fd3df7..21094250 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -82,6 +82,8 @@ Upcoming Release * Upgrade default techno-economic assumptions to ``technology-data`` v0.8.1. +* Add possibility to download cost data from custom fork of ``technology-data``. + * Linearly interpolate missing investment periods in year-dependent configuration options. From e03fbf152c88ecff3aca56cc62ca4ac7794d6319 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 18 Mar 2024 13:37:58 +0000 Subject: [PATCH 476/591] Only sanitize locations when there are buses with a location Fixes an edge case when no buses with a location are added in add_extra_components. --- scripts/add_electricity.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index ac73cb1f..7e60203f 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -184,12 +184,13 @@ def sanitize_carriers(n, config): def sanitize_locations(n): - n.buses["x"] = n.buses.x.where(n.buses.x != 0, n.buses.location.map(n.buses.x)) - n.buses["y"] = n.buses.y.where(n.buses.y != 0, n.buses.location.map(n.buses.y)) - n.buses["country"] = n.buses.country.where( - n.buses.country.ne("") & n.buses.country.notnull(), - n.buses.location.map(n.buses.country), - ) + if "location" in n.buses.columns: + n.buses["x"] = n.buses.x.where(n.buses.x != 0, n.buses.location.map(n.buses.x)) + n.buses["y"] = n.buses.y.where(n.buses.y != 0, n.buses.location.map(n.buses.y)) + n.buses["country"] = n.buses.country.where( + n.buses.country.ne("") & n.buses.country.notnull(), + n.buses.location.map(n.buses.country), + ) def add_co2_emissions(n, costs, carriers): From c983aa7d2dcdee44d805d9c820f416870110e14d Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 7 Mar 2024 10:22:28 +0100 Subject: [PATCH 477/591] prepare_perfect: ensure network.meta assignment --- scripts/prepare_perfect_foresight.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index f7e8495e..fea0cef4 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -537,5 +537,8 @@ if __name__ == "__main__": # set carbon constraints n = set_carbon_constraints(n) + # update meta + n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) + # export network n.export_to_netcdf(snakemake.output[0]) From f3eae37a02ebf974228279777082d180f97c4a8a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 14 Mar 2024 12:52:25 +0100 Subject: [PATCH 478/591] scneario management: reenable shared resources in one folder --- scripts/_helpers.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index d03a306b..5884d908 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -66,20 +66,17 @@ def get_run_path(fn, dir, rdir, shared_resources): "add_electricity" ) is_shared = no_relevant_wildcards and no_elec_rule + rdir = "" if is_shared else rdir elif isinstance(shared_resources, str): rdir = shared_resources + "/" - is_shared = False elif isinstance(shared_resources, bool): - is_shared = shared_resources + rdir = "" else: raise ValueError( "shared_resources must be a boolean, str, or 'base' for special handling." ) - if is_shared: - return f"{dir}{fn}" - else: - return f"{dir}{rdir}{fn}" + return f"{dir}{rdir}{fn}" def path_provider(dir, rdir, shared_resources): From 1388104996d8794a6b345296386800eb43388a06 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 15 Mar 2024 13:02:27 +0100 Subject: [PATCH 479/591] test.sh: set continuous chain of && commands and print out commands --- test.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test.sh b/test.sh index d6007750..a3dfb65f 100755 --- a/test.sh +++ b/test.sh @@ -2,8 +2,12 @@ # # SPDX-License-Identifier: CC0-1.0 +set -x && \ + snakemake -call solve_elec_networks --configfile config/test/config.electricity.yaml --rerun-triggers=mtime && \ snakemake -call all --configfile config/test/config.overnight.yaml --rerun-triggers=mtime && \ snakemake -call all --configfile config/test/config.myopic.yaml --rerun-triggers=mtime && \ snakemake -call all --configfile config/test/config.perfect.yaml --rerun-triggers=mtime && \ -snakemake -call all --configfile config/test/config.scenarios.yaml --rerun-triggers=mtime -n +snakemake -call all --configfile config/test/config.scenarios.yaml --rerun-triggers=mtime -n && \ + +set +x From 04d4d9849d6ab91133250d091cce22d1e128d5c6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 19:45:01 +0000 Subject: [PATCH 480/591] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 24.2.0 → 24.3.0](https://github.com/psf/black-pre-commit-mirror/compare/24.2.0...24.3.0) --- .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 28d0278a..2fb51c54 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,7 +51,7 @@ repos: # Formatting with "black" coding style - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.2.0 + rev: 24.3.0 hooks: # Format Python files - id: black From 8d9afb0eb048f6d0d3c4370c84c29159862b4bec Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Tue, 19 Mar 2024 08:28:27 +0100 Subject: [PATCH 481/591] solve_electricity.smk:replace "minimal" by "shallow" --- rules/solve_electricity.smk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/solve_electricity.smk b/rules/solve_electricity.smk index f24119b9..389687a0 100644 --- a/rules/solve_electricity.smk +++ b/rules/solve_electricity.smk @@ -31,7 +31,7 @@ rule solve_network: mem_mb=memory, runtime=config_provider("solving", "runtime", default="6h"), shadow: - "minimal" + "shallow" conda: "../envs/environment.yaml" script: @@ -62,7 +62,7 @@ rule solve_operations_network: mem_mb=(lambda w: 10000 + 372 * int(w.clusters)), runtime=config_provider("solving", "runtime", default="6h"), shadow: - "minimal" + "shallow" conda: "../envs/environment.yaml" script: From 2565a7db4f283317a33e3a10c09b03463d2cb1fb Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Mar 2024 08:20:23 +0100 Subject: [PATCH 482/591] snakefile: move copy_default_files and process_run_config to helpers --- Snakefile | 30 ++++++------------------------ scripts/_helpers.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/Snakefile b/Snakefile index 58cb6677..4a41622e 100644 --- a/Snakefile +++ b/Snakefile @@ -2,26 +2,18 @@ # # SPDX-License-Identifier: MIT -from os.path import normpath, exists -from shutil import copyfile, move, rmtree from pathlib import Path import yaml - +from os.path import normpath +from shutil import move, rmtree from snakemake.utils import min_version min_version("8.5") -from scripts._helpers import path_provider +from scripts._helpers import path_provider, copy_default_files, process_run_config -default_files = { - "config/config.default.yaml": "config/config.yaml", - "config/scenarios.template.yaml": "config/scenarios.yaml", -} -for template, target in default_files.items(): - target = os.path.join(workflow.current_basedir, target) - template = os.path.join(workflow.current_basedir, template) - if not exists(target) and exists(template): - copyfile(template, target) + +copy_default_files(workflow) configfile: "config/config.default.yaml" @@ -29,17 +21,7 @@ configfile: "config/config.yaml" run = config["run"] -scenarios = run.get("scenarios", {}) -if run["name"] and scenarios.get("enable"): - fn = Path(scenarios["file"]) - scenarios = yaml.safe_load(fn.read_text()) - RDIR = "{run}/" - if run["name"] == "all": - config["run"]["name"] = list(scenarios.keys()) -elif run["name"]: - RDIR = run["name"] + "/" -else: - RDIR = "" +RDIR = process_run_config(run) logs = path_provider("logs/", RDIR, run["shared_resources"]) benchmarks = path_provider("benchmarks/", RDIR, run["shared_resources"]) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index d03a306b..2bacf5cd 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -11,7 +11,9 @@ import os import re import urllib from functools import partial +from os.path import exists from pathlib import Path +from shutil import copyfile import pandas as pd import pytz @@ -25,6 +27,33 @@ logger = logging.getLogger(__name__) REGION_COLS = ["geometry", "name", "x", "y", "country"] +def copy_default_files(workflow): + default_files = { + "config/config.default.yaml": "config/config.yaml", + "config/scenarios.template.yaml": "config/scenarios.yaml", + } + for template, target in default_files.items(): + target = os.path.join(workflow.current_basedir, target) + template = os.path.join(workflow.current_basedir, template) + if not exists(target) and exists(template): + copyfile(template, target) + + +def process_run_config(run): + scenarios = run.get("scenarios", {}) + if run["name"] and scenarios.get("enable"): + fn = Path(scenarios["file"]) + scenarios = yaml.safe_load(fn.read_text()) + RDIR = "{run}/" + if run["name"] == "all": + run["name"] = list(scenarios.keys()) + elif run["name"]: + RDIR = run["name"] + "/" + else: + RDIR = "" + return RDIR + + def get_run_path(fn, dir, rdir, shared_resources): """ Dynamically provide paths based on shared resources and filename. From a8454fd8305dff8b5360536903f3d581125b062d Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 18 Mar 2024 16:16:30 +0000 Subject: [PATCH 483/591] Fill in missing eurostat data on domestic aviation energy demand --- scripts/build_energy_totals.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/build_energy_totals.py b/scripts/build_energy_totals.py index abab06e4..b56d3294 100644 --- a/scripts/build_energy_totals.py +++ b/scripts/build_energy_totals.py @@ -124,6 +124,17 @@ def build_eurostat(input_eurostat, countries, nprocesses=1, disable_progressbar= ) df = pd.concat([temp, df.loc[~int_avia]]) + # Fill in missing data on "Domestic aviation" for each country. + domestic_avia = df.index.get_level_values(4) == "Domestic aviation" + for country in countries: + slicer = idx[country, :, :, :, "Domestic aviation"] + # For the Total and Fossil energy columns, fill in zeros with + # the closest non-zero value in the year index. + for col in ["Total", "Fossil energy"]: + df.loc[slicer, col] = ( + df.loc[slicer, col].replace(0.0, np.nan).ffill().bfill() + ) + # Renaming some indices index_rename = { "Households": "Residential", From 65af55c22b48e305a6baa30f265054429ba79a55 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 19 Mar 2024 08:54:58 +0100 Subject: [PATCH 484/591] Fix typos --- scripts/add_brownfield.py | 2 +- scripts/retrieve_cost_data.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 82a40e57..7e49031b 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -145,7 +145,7 @@ def disable_grid_expansion_if_limit_hit(n): for name, glc in glcs.iterrows(): total_expansion = ( ( - n.lines.query("p_nom_extendable") + n.lines.query("s_nom_extendable") .eval(f"s_nom_min * {cols[limit_type]}") .sum() ) diff --git a/scripts/retrieve_cost_data.py b/scripts/retrieve_cost_data.py index 39fcab7c..e236fbfd 100644 --- a/scripts/retrieve_cost_data.py +++ b/scripts/retrieve_cost_data.py @@ -26,7 +26,7 @@ if __name__ == "__main__": version = snakemake.params.version if "/" in version: - baseurl = f"https://raw.githubusercontent.com/{version}/outputs" + baseurl = f"https://raw.githubusercontent.com/{version}/outputs/" else: baseurl = f"https://raw.githubusercontent.com/PyPSA/technology-data/{version}/outputs/" filepath = Path(snakemake.output[0]) From 22d1bf5dd1a35554d476263c91d9bb390881dc2f Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 18 Mar 2024 11:58:39 +0100 Subject: [PATCH 485/591] Bugfix for missing eia years First, cannot cast pd index to boolean. Second, fix logic error of mistakenly swapped difference in calculating missing years. --- scripts/build_hydro_profile.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index b7f270b3..c4e9701e 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -202,9 +202,10 @@ if __name__ == "__main__": contained_years = pd.date_range(freq="YE", **snakemake.params.snapshots).year norm_year = config_hydro.get("eia_norm_year") + missing_years = contained_years.difference(eia_stats.index) if norm_year: eia_stats.loc[contained_years] = eia_stats.loc[norm_year] - elif missing_years := eia_stats.index.difference(contained_years): + elif missing_years.any(): eia_stats.loc[missing_years] = eia_stats.median() inflow = cutout.runoff( From fcf773c003254975740340bb8cb21827aef7fc8b Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 19 Mar 2024 08:28:14 +0000 Subject: [PATCH 486/591] Copy, don't move natura.tiff to resources Preventing problems when parallel processes attempt to move the same file to different resources directories. --- rules/retrieve.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/retrieve.smk b/rules/retrieve.smk index ac296f79..4b244483 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -115,7 +115,7 @@ if config["enable"]["retrieve"] and config["enable"].get( mem_mb=5000, retries: 2 run: - move(input[0], output[0]) + copyfile(input[0], output[0]) validate_checksum(output[0], input[0]) From 23e1139c212aa449059ae82f975555142e20e5ec Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Mar 2024 09:39:35 +0100 Subject: [PATCH 487/591] snakefile + helpers: separate scenario and rdir getter --- Snakefile | 5 +++-- scripts/_helpers.py | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Snakefile b/Snakefile index 4a41622e..3e8875d3 100644 --- a/Snakefile +++ b/Snakefile @@ -10,7 +10,7 @@ from snakemake.utils import min_version min_version("8.5") -from scripts._helpers import path_provider, copy_default_files, process_run_config +from scripts._helpers import path_provider, copy_default_files, get_scenarios, get_rdir copy_default_files(workflow) @@ -21,7 +21,8 @@ configfile: "config/config.yaml" run = config["run"] -RDIR = process_run_config(run) +scenarios = get_scenarios(run) +RDIR = get_rdir(run) logs = path_provider("logs/", RDIR, run["shared_resources"]) benchmarks = path_provider("benchmarks/", RDIR, run["shared_resources"]) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 2bacf5cd..9b390380 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -39,14 +39,21 @@ def copy_default_files(workflow): copyfile(template, target) -def process_run_config(run): - scenarios = run.get("scenarios", {}) - if run["name"] and scenarios.get("enable"): - fn = Path(scenarios["file"]) +def get_scenarios(run): + scenario_config = run.get("scenarios", {}) + if run["name"] and scenario_config.get("enable"): + fn = Path(scenario_config["file"]) scenarios = yaml.safe_load(fn.read_text()) - RDIR = "{run}/" if run["name"] == "all": run["name"] = list(scenarios.keys()) + return scenarios + return {} + + +def get_rdir(run): + scenario_config = run.get("scenarios", {}) + if run["name"] and scenario_config.get("enable"): + RDIR = "{run}/" elif run["name"]: RDIR = run["name"] + "/" else: From 8190fde9cee654a8dafd1fd2df09c18e116e4372 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Mar 2024 09:48:52 +0100 Subject: [PATCH 488/591] Snakefile: reinsert shutil and os functions --- Snakefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Snakefile b/Snakefile index 3e8875d3..4f55085f 100644 --- a/Snakefile +++ b/Snakefile @@ -4,8 +4,8 @@ from pathlib import Path import yaml -from os.path import normpath -from shutil import move, rmtree +from os.path import normpath, exists +from shutil import copyfile, move, rmtree from snakemake.utils import min_version min_version("8.5") From 86a6c3223def9ef304988eb9b0a53c973005bbf3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Mar 2024 11:26:36 +0100 Subject: [PATCH 489/591] perfect foresight: store configs in results dir --- rules/solve_perfect.smk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 215757fe..d4cbd6f3 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -110,7 +110,8 @@ rule solve_sector_network_perfect: output: network=RESULTS + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", - config="configs/config.elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.yaml", + config=RESULTS + + "configs/config.elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.yaml", threads: solver_threads resources: mem_mb=config_provider("solving", "mem"), From 651e28775ecbe50f9918ea18bbb06edc57d58ad9 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 19 Mar 2024 13:00:16 +0000 Subject: [PATCH 490/591] Use raw strings to avoid illegal backslash warnings python 12 --- Snakefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Snakefile b/Snakefile index 58cb6677..ca1b72cc 100644 --- a/Snakefile +++ b/Snakefile @@ -56,9 +56,9 @@ localrules: wildcard_constraints: simpl="[a-zA-Z0-9]*", clusters="[0-9]+(m|c)?|all", - ll="(v|c)([0-9\.]+|opt)", - opts="[-+a-zA-Z0-9\.]*", - sector_opts="[-+a-zA-Z0-9\.\s]*", + ll=r"(v|c)([0-9\.]+|opt)", + opts=r"[-+a-zA-Z0-9\.]*", + sector_opts=r"[-+a-zA-Z0-9\.\s]*", include: "rules/common.smk" @@ -127,7 +127,7 @@ rule dag: conda: "envs/environment.yaml" shell: - """ + r""" snakemake --rulegraph all | sed -n "/digraph/,\$p" > {output.dot} dot -Tpdf -o {output.pdf} {output.dot} dot -Tpng -o {output.png} {output.dot} From 9558f4405144048aebbf72ae25f4d4455411431d Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Wed, 6 Mar 2024 10:26:23 +0100 Subject: [PATCH 491/591] Drop assets including renewables in add_existing_baseyear --- doc/release_notes.rst | 2 ++ scripts/add_existing_baseyear.py | 14 ++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 21094250..0e319a3e 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -68,6 +68,8 @@ Upcoming Release (https://github.com/PyPSA/pypsa-eur/pull/958). Added additional grouping years before 1980. +* Add decommissioning of renewables assets in `add_existing_baseyear`. + * The Eurostat data was updated to the 2023 version in :mod:`build_energy_totals`. * The latest `Swiss energy totals diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 2c313927..9c35819f 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -55,7 +55,7 @@ def add_build_year_to_new_assets(n, baseyear): c.pnl[attr] = c.pnl[attr].rename(columns=rename) -def add_existing_renewables(df_agg): +def add_existing_renewables(df_agg, costs): """ Append existing renewables to the df_agg pd.DataFrame with the conventional power plants. @@ -103,6 +103,8 @@ def add_existing_renewables(df_agg): df_agg.at[name, "Fueltype"] = tech df_agg.at[name, "Capacity"] = capacity df_agg.at[name, "DateIn"] = year + df_agg.at[name, "lifetime"] = costs.at[tech, "lifetime"] + df_agg.at[name, "DateOut"] = year + costs.at[tech, "lifetime"] - 1 df_agg.at[name, "cluster_bus"] = node @@ -167,10 +169,6 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas ) df_agg.loc[biomass_i, "DateOut"] = df_agg.loc[biomass_i, "DateOut"].fillna(dateout) - # drop assets which are already phased out / decommissioned - phased_out = df_agg[df_agg["DateOut"] < baseyear].index - df_agg.drop(phased_out, inplace=True) - # assign clustered bus busmap_s = pd.read_csv(snakemake.input.busmap_s, index_col=0).squeeze() busmap = pd.read_csv(snakemake.input.busmap, index_col=0).squeeze() @@ -185,7 +183,11 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas df_agg["cluster_bus"] = df_agg.bus.map(clustermaps) # include renewables in df_agg - add_existing_renewables(df_agg) + add_existing_renewables(df_agg, costs) + + # drop assets which are already phased out / decommissioned + phased_out = df_agg[df_agg["DateOut"] < baseyear].index + df_agg.drop(phased_out, inplace=True) df_agg["grouping_year"] = np.take( grouping_years, np.digitize(df_agg.DateIn, grouping_years, right=True) From c5026aaf9b24a4ec17049e03cf2f6953b7059f02 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 20 Mar 2024 13:56:48 +0100 Subject: [PATCH 492/591] add draft HVDC projects from TYNDP 2024 --- data/links_tyndp.csv | 13 +++++++++++++ doc/release_notes.rst | 3 +++ 2 files changed, 16 insertions(+) diff --git a/data/links_tyndp.csv b/data/links_tyndp.csv index a0603120..43030be5 100644 --- a/data/links_tyndp.csv +++ b/data/links_tyndp.csv @@ -26,3 +26,16 @@ NordBalt,Klaipeda (LT),Nybro (SE),450,,700,built,,https://en.wikipedia.org/wiki/ Estlink 1,Harku (EE),Espoo (FI),105,,350,built,,https://en.wikipedia.org/wiki/Estlink,24.560278,59.384722,24.551667,60.203889 Greenlink,Waterford (IE),Pembroke (UK),,180,500,under construction,,https://tyndp2022-project-platform.azurewebsites.net/projectsheets/transmission/286,-6.987,52.260,-4.986,51.686 Celtic Interconnector,Aghada (IE),La Martyre (FR),,572,700,under consideration,,https://tyndp2022-project-platform.azurewebsites.net/projectsheets/transmission/107,-8.16642,51.91413,-4.184,48.459 +GiLA,Bordeaux (FR),Nantes (FR),,312,640,under consideration,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,-1.209,46.901,-0.576,44.960 +HG North Tyrrhenian Corridor,Milan (IT),Viterbo (IT),,500,2000,in permitting,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,9.409,45.553,12.015,42.244 +HG Adriatic Corridor,Ferrara (IT),Foggia (IT),,582,2000,in permitting,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,11.661,44.855,15.550,41.513 +SAPEI 2,Fioumesanto (IT),Montalto (IT),,390,1000,in permitting,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,8.283,40.790,11.602,42.331 +HG Ionian-Tyrrhenian Corridor,Rossano (IT),Latina (IT),,496,2000,in permitting,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,16.629,39.568,12.779,41.430 +HG Ionian-Tyrrhenian Corridor 2,Rossano (IT),Catania (IT),,330,2000,in permitting,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,16.629,39.568,15.049,37.408 +Germany-UK Hybrid Interconnector,Fetteresso (UK),Emden (DE),800,,2000,under consideration,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,-2.383,56.991,7.207,53.376 +NU-Link Interconnector,Hornsea (UK),Moerdijk (NL),,460,1200,under consideration,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,-0.261,53.655,4.586,51.661 +APOLLO-LINK,La Farga (ES),La Spezia (IT),,725,2091,under consideration,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,2.883,42.062,9.884,44.107 +Baltic WindConnector (BWC),Lubmin (DE),Lihula (EE),,960,2000,under consideration,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,13.686,54.139,23.818,58.675 +High-Voltage Direct Current Interconnector Project Romania-Hungary,Constanta (RO),Albertirsa (HU),,930,2500,under consideration,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,28.588,44.201,19.584,47.224 +Rhine-Main-Link,Ovelgönne (DE),Marxheim (DE),,433,4000,in permitting,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,8.379,53.315,8.435,50.078 +Green Aegean Interconnector,Arachthos (GR),Ottenhofen (DE),,600,3000,under consideration,,https://eepublicdownloads.blob.core.windows.net/public-cdn-container/tyndp-documents/TYNDP2024/240220_TYNDP2024_project_portfolio.xlsx,20.967,39.185,11.868,48.207 diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 21094250..e081ce35 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -59,6 +59,9 @@ Upcoming Release * Removed rule ``copy_config``. Instead, a config file is created for each network output of the ``solve_*`` rules, with the same content as ``n.meta``. +* Added new HVDC transmission projects from `TYNDP 2024 draft projects + `_. + * Upgrade to Snakemake v8.5+. This version is the new minimum version required. To upgrade an existing environment, run ``conda install -c bioconda snakemake-minimal">=8.5"`` and ``pip install snakemake-storage-plugin-http`` From bb898bf69519c1b3c6454ff3248f2d42df543c2d Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Wed, 20 Mar 2024 15:40:07 +0100 Subject: [PATCH 493/591] Fix typo in reading input to build_sequestration_potentials rule Presumably needed since the transition to snakemake 8 storage providers --- scripts/build_sequestration_potentials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_sequestration_potentials.py b/scripts/build_sequestration_potentials.py index 106c1271..2a362a77 100644 --- a/scripts/build_sequestration_potentials.py +++ b/scripts/build_sequestration_potentials.py @@ -44,7 +44,7 @@ if __name__ == "__main__": cf = snakemake.params.sequestration_potential - gdf = gpd.read_file(snakemake.input.sequestration_potential[0]) + gdf = gpd.read_file(snakemake.input.sequestration_potential) regions = gpd.read_file(snakemake.input.regions_offshore) if cf["include_onshore"]: From ab8336d6a891c89b2154a540ab10edcb61c73a06 Mon Sep 17 00:00:00 2001 From: Fabian Hofmann Date: Thu, 21 Mar 2024 09:55:48 +0100 Subject: [PATCH 494/591] disable windows machines in CI The CI on windows machines keeps failing due to some weird syntax problem in snakefiles, which we can't solve on our end it seems. --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c17c0425..7aabf0e6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,7 +31,7 @@ jobs: os: - ubuntu-latest - macos-latest - - windows-latest +# - windows-latest inhouse: - stable - master From d0951abdedd11c8ae4c044905673d270e56dc52e Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 21 Mar 2024 12:02:02 +0100 Subject: [PATCH 495/591] cluster_network: allow more solvers that can handle quadratic problems --- doc/release_notes.rst | 2 ++ scripts/cluster_network.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 21094250..2982f0a6 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,8 @@ Release Notes Upcoming Release ================ +* Allow the use of more solvers in clustering (Xpress, COPT, Gurobi, CPLEX, SCIP, MOSEK). + * Enhanced support for choosing different weather years (https://github.com/PyPSA/pypsa-eur/pull/204): diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 270774af..3f6c9ea2 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -267,7 +267,7 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="scip"): m.objective = (clusters * clusters - 2 * clusters * L * n_clusters).sum() if solver_name == "gurobi": logging.getLogger("gurobipy").propagate = False - elif solver_name not in ["scip", "cplex"]: + elif solver_name not in ["scip", "cplex", "xpress", "copt", "mosek"]: logger.info( f"The configured solver `{solver_name}` does not support quadratic objectives. Falling back to `scip`." ) From 7e99f3bba7deecb4cc73568d9fcee9b3ad58950a Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Fri, 22 Mar 2024 10:05:40 +0100 Subject: [PATCH 496/591] Fix error with symbol of buses in simplify_network --- doc/release_notes.rst | 2 ++ scripts/simplify_network.py | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b868e5e9..1aaaaebd 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -164,6 +164,8 @@ Upcoming Release * Fix duplicated years in `add_land_use_constraint_m`. +* Fix error with `symbol` of `buses` in `simplify_network`. + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index eac026a4..24df7312 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -594,18 +594,6 @@ if __name__ == "__main__": ) busmaps.append(busmap_hac) - if snakemake.wildcards.simpl: - n, cluster_map = cluster( - n, - int(snakemake.wildcards.simpl), - params.focus_weights, - solver_name, - params.simplify_network["algorithm"], - params.simplify_network["feature"], - params.aggregation_strategies, - ) - busmaps.append(cluster_map) - # some entries in n.buses are not updated in previous functions, therefore can be wrong. as they are not needed # and are lost when clustering (for example with the simpl wildcard), we remove them for consistency: remove = [ @@ -621,6 +609,18 @@ if __name__ == "__main__": n.buses.drop(remove, axis=1, inplace=True, errors="ignore") n.lines.drop(remove, axis=1, errors="ignore", inplace=True) + if snakemake.wildcards.simpl: + n, cluster_map = cluster( + n, + int(snakemake.wildcards.simpl), + params.focus_weights, + solver_name, + params.simplify_network["algorithm"], + params.simplify_network["feature"], + params.aggregation_strategies, + ) + busmaps.append(cluster_map) + update_p_nom_max(n) n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) From fd01cb0a756d769c1d638b38c372ae517814d097 Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Fri, 22 Mar 2024 15:57:37 +0100 Subject: [PATCH 497/591] Fix type error in cluster_network with "m" configuration --- doc/release_notes.rst | 2 ++ scripts/cluster_network.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b868e5e9..e561cbe0 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -164,6 +164,8 @@ Upcoming Release * Fix duplicated years in `add_land_use_constraint_m`. +* Fix type error with `m` option in `cluster_network`. + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 3f6c9ea2..22fb4176 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -471,7 +471,7 @@ if __name__ == "__main__": conventional_carriers = set(params.conventional_carriers) if snakemake.wildcards.clusters.endswith("m"): n_clusters = int(snakemake.wildcards.clusters[:-1]) - aggregate_carriers = params.conventional_carriers & aggregate_carriers + aggregate_carriers = conventional_carriers & aggregate_carriers elif snakemake.wildcards.clusters.endswith("c"): n_clusters = int(snakemake.wildcards.clusters[:-1]) aggregate_carriers = aggregate_carriers - conventional_carriers From 585f9a32a7a18d47d3b35c39169d10019f129f4d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 25 Mar 2024 14:07:02 +0100 Subject: [PATCH 498/591] cluster_network: ensure correct indexing of weights --- scripts/cluster_network.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 22fb4176..903cbe9b 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -231,7 +231,7 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="scip"): .pipe(normed) ) - N = n.buses.groupby(["country", "sub_network"]).size() + N = n.buses.groupby(["country", "sub_network"]).size()[L.index] assert ( n_clusters >= len(N) and n_clusters <= N.sum() @@ -454,7 +454,7 @@ if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake - snakemake = mock_snakemake("cluster_network", simpl="", clusters="5") + snakemake = mock_snakemake("cluster_network", simpl="", clusters="40") configure_logging(snakemake) set_scenario_config(snakemake) From 34f02942640504dbbfc2befead9d5820a783cca2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 25 Mar 2024 14:08:38 +0100 Subject: [PATCH 499/591] scenario management: fix shared resources --- scripts/_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 0fd5ab2b..8e8d67c8 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -106,7 +106,7 @@ def get_run_path(fn, dir, rdir, shared_resources): elif isinstance(shared_resources, str): rdir = shared_resources + "/" elif isinstance(shared_resources, bool): - rdir = "" + rdir = "" if shared_resources else rdir else: raise ValueError( "shared_resources must be a boolean, str, or 'base' for special handling." From 50466d959398b9d42e489cc7eac8daab9764f293 Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Mon, 25 Mar 2024 15:44:05 +0100 Subject: [PATCH 500/591] Fix grouping year reference in add_land_use_constraint_m --- doc/release_notes.rst | 2 +- scripts/solve_network.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b868e5e9..ca8dce2a 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -162,7 +162,7 @@ Upcoming Release * Adapt the disabling of transmission expansion in myopic foresight optimisations when limit is already reached to also handle cost limits. -* Fix duplicated years in `add_land_use_constraint_m`. +* Fix duplicated years and grouping years reference in `add_land_use_constraint_m`. PyPSA-Eur 0.10.0 (19th February 2024) ===================================== diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 10bc84e6..0f6725c7 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -155,7 +155,7 @@ def _add_land_use_constraint(n): def _add_land_use_constraint_m(n, planning_horizons, config): # if generators clustering is lower than network clustering, land_use accounting is at generators clusters - grouping_years = config["existing_capacities"]["grouping_years"] + grouping_years = config["existing_capacities"]["grouping_years_power"] current_horizon = snakemake.wildcards.planning_horizons for carrier in ["solar", "onwind", "offwind-ac", "offwind-dc"]: From 9dae86cd561995c20f27684034691f126e962ef1 Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Mon, 25 Mar 2024 20:11:02 +0100 Subject: [PATCH 501/591] Fix index for existing capacities in add_existing_baseyear --- doc/release_notes.rst | 2 ++ scripts/add_existing_baseyear.py | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b868e5e9..634af9a6 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -164,6 +164,8 @@ Upcoming Release * Fix duplicated years in `add_land_use_constraint_m`. +* Fix index of existing capacities in `add_power_capacities_installed_before_baseyear` with `m` option. + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 2c313927..8380edd0 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -257,13 +257,14 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas # for offshore the splitting only includes coastal regions inv_ind = [ - i for i in inv_ind if (i + name_suffix) in n.generators.index + i for i in inv_ind if (i + name_suffix) in n.generators.index.str + .replace(str(baseyear), str(grouping_year)) ] p_max_pu = n.generators_t.p_max_pu[ [i + name_suffix for i in inv_ind] ] - p_max_pu.columns = [i + name_suffix for i in inv_ind] + p_max_pu.columns = [i + name_suffix.replace(str(grouping_year), str(baseyear)) for i in inv_ind] n.madd( "Generator", From 8b2a068b3a4c4411c8fde1ff0e46a498cae7f1f8 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Tue, 26 Mar 2024 11:57:21 +0100 Subject: [PATCH 502/591] Check if scenario file exists before attempting to load Useful when running the `create_scenarios` rule the first time. --- scripts/_helpers.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 8e8d67c8..f063877e 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -43,10 +43,11 @@ def get_scenarios(run): scenario_config = run.get("scenarios", {}) if run["name"] and scenario_config.get("enable"): fn = Path(scenario_config["file"]) - scenarios = yaml.safe_load(fn.read_text()) - if run["name"] == "all": - run["name"] = list(scenarios.keys()) - return scenarios + if fn.exists(): + scenarios = yaml.safe_load(fn.read_text()) + if run["name"] == "all": + run["name"] = list(scenarios.keys()) + return scenarios return {} From be7dc0d0bbf7047002d87828f823d81022d6e474 Mon Sep 17 00:00:00 2001 From: Fabian Hofmann Date: Tue, 26 Mar 2024 13:28:06 +0100 Subject: [PATCH 503/591] postprocess: fix typo in benchmark folder --- rules/postprocess.smk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 2b298610..e7df2e66 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -44,7 +44,7 @@ if config["foresight"] != "perfect": benchmark: ( RESULTS - + "benchmarksplot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" + + "benchmarks/plot_power_network/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}" ) conda: "../envs/environment.yaml" From 89dbd53805680427231c96904655526548ee0021 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Tue, 26 Mar 2024 17:20:10 +0100 Subject: [PATCH 504/591] provide Path object as input to ConfigSettings --- doc/release_notes.rst | 2 ++ scripts/_helpers.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index e561cbe0..e08981d3 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,8 @@ Release Notes Upcoming Release ================ +* bugfix: convert Strings to pathlib.Path objects as input to ConfigSettings + * Allow the use of more solvers in clustering (Xpress, COPT, Gurobi, CPLEX, SCIP, MOSEK). * Enhanced support for choosing different weather years diff --git a/scripts/_helpers.py b/scripts/_helpers.py index f063877e..64ccab87 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -427,7 +427,7 @@ def mock_snakemake( configfiles = [configfiles] resource_settings = ResourceSettings() - config_settings = ConfigSettings(configfiles=configfiles) + config_settings = ConfigSettings(configfiles=map(Path, configfiles)) workflow_settings = WorkflowSettings() storage_settings = StorageSettings() dag_settings = DAGSettings(rerun_triggers=[]) From b34ce8d6f2221c1a9ec9cbe0dc1df74c14bdd7cb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 19:41:00 +0000 Subject: [PATCH 505/591] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/macisamuele/language-formatters-pre-commit-hooks: v2.12.0 → v2.13.0](https://github.com/macisamuele/language-formatters-pre-commit-hooks/compare/v2.12.0...v2.13.0) --- .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 2fb51c54..cb053d47 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -67,7 +67,7 @@ repos: # Do YAML formatting (before the linter checks it for misses) - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks - rev: v2.12.0 + rev: v2.13.0 hooks: - id: pretty-format-yaml args: [--autofix, --indent, "2", --preserve-quotes] From f7152856827705bd94cd7be9812495a82f22b834 Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Tue, 2 Apr 2024 16:48:37 +0200 Subject: [PATCH 506/591] adjust resources perfect foresight --- rules/solve_perfect.smk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index d4cbd6f3..70acc830 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -35,7 +35,8 @@ rule add_existing_baseyear: planning_horizons=config["scenario"]["planning_horizons"][0], #only applies to baseyear threads: 1 resources: - mem_mb=2000, + mem_mb=config_provider("solving", "mem_mb"), + runtime=config_provider("solving", "runtime", default="24h"), log: logs( "add_existing_baseyear_elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.log" From 3819e643774b028f5b16140d867222a2e41e8b12 Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Tue, 2 Apr 2024 16:50:09 +0200 Subject: [PATCH 507/591] remove solver name --- config/config.default.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index a8cd195c..235c238d 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -786,7 +786,6 @@ solving: PreDual: 0 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 @@ -798,7 +797,6 @@ solving: 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 From f0163d382381b9706ddb25a6ceecd9c09b1ec776 Mon Sep 17 00:00:00 2001 From: lisazeyen Date: Wed, 3 Apr 2024 16:28:20 +0200 Subject: [PATCH 508/591] update release notes --- doc/release_notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b7ad3e7f..3849cafd 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -75,7 +75,7 @@ Upcoming Release (https://github.com/PyPSA/pypsa-eur/pull/958). Added additional grouping years before 1980. -* Add decommissioning of renewables assets in `add_existing_baseyear`. +* Add decommissioning of existing renewables assets in `add_existing_baseyear`. * The Eurostat data was updated to the 2023 version in :mod:`build_energy_totals`. From 6ba598f426f5bb920f52c9f960be1a68cf1408d4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 14:51:09 +0000 Subject: [PATCH 509/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/add_existing_baseyear.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 8380edd0..075909d6 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -257,14 +257,21 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas # for offshore the splitting only includes coastal regions inv_ind = [ - i for i in inv_ind if (i + name_suffix) in n.generators.index.str - .replace(str(baseyear), str(grouping_year)) + i + for i in inv_ind + if (i + name_suffix) + in n.generators.index.str.replace( + str(baseyear), str(grouping_year) + ) ] p_max_pu = n.generators_t.p_max_pu[ [i + name_suffix for i in inv_ind] ] - p_max_pu.columns = [i + name_suffix.replace(str(grouping_year), str(baseyear)) for i in inv_ind] + p_max_pu.columns = [ + i + name_suffix.replace(str(grouping_year), str(baseyear)) + for i in inv_ind + ] n.madd( "Generator", From 6e20afbaee5f16d6c824572982688524c311a78f Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Thu, 4 Apr 2024 15:42:02 +0200 Subject: [PATCH 510/591] Fix typo --- scripts/build_industry_sector_ratios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_industry_sector_ratios.py b/scripts/build_industry_sector_ratios.py index b3ef9321..52e83f60 100644 --- a/scripts/build_industry_sector_ratios.py +++ b/scripts/build_industry_sector_ratios.py @@ -303,7 +303,7 @@ def chemicals_industry(): # There are Solids, Refinery gas, LPG, Diesel oil, Residual fuel oil, # Other liquids, Naphtha, Natural gas for feedstock. # Naphta represents 47%, methane 17%. LPG (18%) solids, refinery gas, - # diesel oil, residual fuel oils and other liquids are asimilated to Naphtha + # diesel oil, residual fuel oils and other liquids are assimilated to Naphtha s_fec = idees["fec"][13:22] assert s_fec.index[0] == subsector From f1c8b19cf08198153ec57959764fcd579271de78 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 19:56:47 +0000 Subject: [PATCH 511/591] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.5.0...v4.6.0) - [github.com/fsfe/reuse-tool: v3.0.1 → v3.0.2](https://github.com/fsfe/reuse-tool/compare/v3.0.1...v3.0.2) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb053d47..055b9080 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ exclude: "^LICENSES" repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-merge-conflict - id: end-of-file-fixer @@ -87,6 +87,6 @@ repos: # Check for FSFE REUSE compliance (licensing) - repo: https://github.com/fsfe/reuse-tool - rev: v3.0.1 + rev: v3.0.2 hooks: - id: reuse From b673b947ea807a93c1b1e7aade329a5667e3d11b Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Tue, 9 Apr 2024 17:30:38 +0200 Subject: [PATCH 512/591] Fix custom busmap read in cluster network --- doc/release_notes.rst | 2 ++ scripts/cluster_network.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 8326f615..b782a6df 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -174,6 +174,8 @@ Upcoming Release * Fix index of existing capacities in `add_power_capacities_installed_before_baseyear` with `m` option. +* Fix custom busmap read in `cluster_network`. + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 903cbe9b..b0b73ade 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -519,8 +519,8 @@ if __name__ == "__main__": custom_busmap = params.custom_busmap if custom_busmap: custom_busmap = pd.read_csv( - snakemake.input.custom_busmap, index_col=0, squeeze=True - ) + snakemake.input.custom_busmap, index_col=0 + ).squeeze() custom_busmap.index = custom_busmap.index.astype(str) logger.info(f"Imported custom busmap from {snakemake.input.custom_busmap}") From 74185560e0570cb15662fca8784adb8b3fa93aa2 Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Wed, 10 Apr 2024 12:04:45 +0200 Subject: [PATCH 513/591] initial implementation --- Snakefile | 8 +++++++- config/config.default.yaml | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Snakefile b/Snakefile index ba93a869..ed60c0f5 100644 --- a/Snakefile +++ b/Snakefile @@ -22,7 +22,13 @@ configfile: "config/config.yaml" run = config["run"] scenarios = get_scenarios(run) -RDIR = get_rdir(run) +prefix = run.get("prefix", "") +rdir = get_rdir(run) + +if prefix: + RDIR = f"{prefix}/{rdir}" +else: + RDIR = rdir logs = path_provider("logs/", RDIR, run["shared_resources"]) benchmarks = path_provider("benchmarks/", RDIR, run["shared_resources"]) diff --git a/config/config.default.yaml b/config/config.default.yaml index 235c238d..61ef8c1b 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -20,6 +20,7 @@ remote: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#run run: + prefix: "" name: "" scenarios: enable: false From 9d9ab98279dd7fbf7fd1ad064a09d97dd08d5b19 Mon Sep 17 00:00:00 2001 From: lisazeyen Date: Wed, 10 Apr 2024 12:06:53 +0200 Subject: [PATCH 514/591] add other co2 potentials --- config/config.default.yaml | 2 +- scripts/build_sequestration_potentials.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 235c238d..6a703b31 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -515,7 +515,7 @@ sector: regional_coal_demand: false regional_co2_sequestration_potential: enable: false - attribute: 'conservative estimate Mt' + attribute: ['conservative estimate Mt', 'conservative estimate GAS Mt', 'conservative estimate OIL Mt', 'conservative estimate aquifer Mt'] include_onshore: false min_size: 3 max_size: 25 diff --git a/scripts/build_sequestration_potentials.py b/scripts/build_sequestration_potentials.py index 2a362a77..3defe07a 100644 --- a/scripts/build_sequestration_potentials.py +++ b/scripts/build_sequestration_potentials.py @@ -23,13 +23,13 @@ def area(gdf): def allocate_sequestration_potential( gdf, regions, attr="conservative estimate Mt", threshold=3 ): - gdf = gdf.loc[gdf[attr] > threshold, [attr, "geometry"]] + gdf = gdf.loc[gdf[attr].sum(axis=1) > threshold, attr + ["geometry"]] gdf["area_sqkm"] = area(gdf) overlay = gpd.overlay(regions, gdf, keep_geom_type=True) overlay["share"] = area(overlay) / overlay["area_sqkm"] adjust_cols = overlay.columns.difference({"name", "area_sqkm", "geometry", "share"}) overlay[adjust_cols] = overlay[adjust_cols].multiply(overlay["share"], axis=0) - return overlay.dissolve("name", aggfunc="sum")[attr] + return overlay.dissolve("name", aggfunc="sum")[attr].sum(axis=1) if __name__ == "__main__": @@ -37,7 +37,7 @@ if __name__ == "__main__": from _helpers import mock_snakemake snakemake = mock_snakemake( - "build_sequestration_potentials", simpl="", clusters="181" + "build_sequestration_potentials", simpl="", clusters="128" ) set_scenario_config(snakemake) From 49db5bfb95368d58ff8ee76da2ce5ec33882ec2e Mon Sep 17 00:00:00 2001 From: lisazeyen Date: Wed, 10 Apr 2024 12:13:38 +0200 Subject: [PATCH 515/591] add release notes --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b782a6df..28bb03b7 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,8 @@ Release Notes Upcoming Release ================ +* correct estimation of CO2 sequestration potential to including hydrocarbon fields (gas + oil) or saline aquifers + * bugfix: convert Strings to pathlib.Path objects as input to ConfigSettings * Allow the use of more solvers in clustering (Xpress, COPT, Gurobi, CPLEX, SCIP, MOSEK). From fd239e268866af10fcefd017e148b071e80724c8 Mon Sep 17 00:00:00 2001 From: lisazeyen Date: Wed, 10 Apr 2024 12:15:33 +0200 Subject: [PATCH 516/591] adjust configtables --- doc/configtables/sector.csv | 294 ++++++++++++++++++------------------ 1 file changed, 147 insertions(+), 147 deletions(-) diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv index 1f8bb030..1692d299 100644 --- a/doc/configtables/sector.csv +++ b/doc/configtables/sector.csv @@ -1,147 +1,147 @@ -,Unit,Values,Description -transport,--,"{true, false}",Flag to include transport sector. -heating,--,"{true, false}",Flag to include heating sector. -biomass,--,"{true, false}",Flag to include biomass sector. -industry,--,"{true, false}",Flag to include industry sector. -agriculture,--,"{true, false}",Flag to include agriculture sector. -district_heating,--,,`prepare_sector_network.py `_ --- potential,--,float,maximum fraction of urban demand which can be supplied by district heating --- progress,--,Dictionary with planning horizons as keys., Increase of today's district heating demand to potential maximum district heating share. Progress = 0 means today's district heating share. Progress = 1 means maximum fraction of urban demand is supplied by district heating --- district_heating_loss,--,float,Share increase in district heat demand in urban central due to heat losses -cluster_heat_buses,--,"{true, false}",Cluster residential and service heat buses in `prepare_sector_network.py `_ to one to save memory. -,,, -bev_dsm_restriction _value,--,float,Adds a lower state of charge (SOC) limit for battery electric vehicles (BEV) to manage its own energy demand (DSM). Located in `build_transport_demand.py `_. Set to 0 for no restriction on BEV DSM -bev_dsm_restriction _time,--,float,Time at which SOC of BEV has to be dsm_restriction_value -transport_heating _deadband_upper,°C,float,"The maximum temperature in the vehicle. At higher temperatures, the energy required for cooling in the vehicle increases." -transport_heating _deadband_lower,°C,float,"The minimum temperature in the vehicle. At lower temperatures, the energy required for heating in the vehicle increases." -,,, -ICE_lower_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the cold environment and the minimum temperature. -ICE_upper_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the hot environment and the maximum temperature. -EV_lower_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the cold environment and the minimum temperature. -EV_upper_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the hot environment and the maximum temperature. -bev_dsm,--,"{true, false}",Add the option for battery electric vehicles (BEV) to participate in demand-side management (DSM) -,,, -bev_availability,--,float,The share for battery electric vehicles (BEV) that are able to do demand side management (DSM) -bev_energy,--,float,The average size of battery electric vehicles (BEV) in MWh -bev_charge_efficiency,--,float,Battery electric vehicles (BEV) charge and discharge efficiency -bev_plug_to_wheel _efficiency,km/kWh,float,The distance battery electric vehicles (BEV) can travel in km per kWh of energy charge in battery. Base value comes from `Tesla Model S `_ -bev_charge_rate,MWh,float,The power consumption for one electric vehicle (EV) in MWh. Value derived from 3-phase charger with 11 kW. -bev_avail_max,--,float,The maximum share plugged-in availability for passenger electric vehicles. -bev_avail_mean,--,float,The average share plugged-in availability for passenger electric vehicles. -v2g,--,"{true, false}",Allows feed-in to grid from EV battery -land_transport_fuel_cell _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses fuel cells in a given year -land_transport_electric _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses electric vehicles (EV) in a given year -land_transport_ice _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses internal combustion engines (ICE) in a given year. What is not EV or FCEV is oil-fuelled ICE. -transport_fuel_cell _efficiency,--,float,The H2 conversion efficiencies of fuel cells in transport -transport_internal _combustion_efficiency,--,float,The oil conversion efficiencies of internal combustion engine (ICE) in transport -agriculture_machinery _electric_share,--,float,The share for agricultural machinery that uses electricity -agriculture_machinery _oil_share,--,float,The share for agricultural machinery that uses oil -agriculture_machinery _fuel_efficiency,--,float,The efficiency of electric-powered machinery in the conversion of electricity to meet agricultural needs. -agriculture_machinery _electric_efficiency,--,float,The efficiency of oil-powered machinery in the conversion of oil to meet agricultural needs. -Mwh_MeOH_per_MWh_H2,LHV,float,"The energy amount of the produced methanol per energy amount of hydrogen. From `DECHEMA (2017) `_, page 64." -MWh_MeOH_per_tCO2,LHV,float,"The energy amount of the produced methanol per ton of CO2. From `DECHEMA (2017) `_, page 64." -MWh_MeOH_per_MWh_e,LHV,float,"The energy amount of the produced methanol per energy amount of electricity. From `DECHEMA (2017) `_, page 64." -shipping_hydrogen _liquefaction,--,"{true, false}",Whether to include liquefaction costs for hydrogen demand in shipping. -,,, -shipping_hydrogen_share,--,Dictionary with planning horizons as keys.,The share of ships powered by hydrogen in a given year -shipping_methanol_share,--,Dictionary with planning horizons as keys.,The share of ships powered by methanol in a given year -shipping_oil_share,--,Dictionary with planning horizons as keys.,The share of ships powered by oil in a given year -shipping_methanol _efficiency,--,float,The efficiency of methanol-powered ships in the conversion of methanol to meet shipping needs (propulsion). The efficiency increase from oil can be 10-15% higher according to the `IEA `_ -,,, -shipping_oil_efficiency,--,float,The efficiency of oil-powered ships in the conversion of oil to meet shipping needs (propulsion). Base value derived from 2011 -aviation_demand_factor,--,float,The proportion of demand for aviation compared to today's consumption -HVC_demand_factor,--,float,The proportion of demand for high-value chemicals compared to today's consumption -,,, -time_dep_hp_cop,--,"{true, false}",Consider the time dependent coefficient of performance (COP) of the heat pump -heat_pump_sink_T,°C,float,The temperature heat sink used in heat pumps based on DTU / large area radiators. The value is conservatively high to cover hot water and space heating in poorly-insulated buildings -reduce_space_heat _exogenously,--,"{true, false}",Influence on space heating demand by a certain factor (applied before losses in district heating). -reduce_space_heat _exogenously_factor,--,Dictionary with planning horizons as keys.,"A positive factor can mean renovation or demolition of a building. If the factor is negative, it can mean an increase in floor area, increased thermal comfort, population growth. The default factors are determined by the `Eurocalc Homes and buildings decarbonization scenario `_" -retrofitting,,, --- retro_endogen,--,"{true, false}",Add retrofitting as an endogenous system which co-optimise space heat savings. --- cost_factor,--,float,Weight costs for building renovation --- interest_rate,--,float,The interest rate for investment in building components --- annualise_cost,--,"{true, false}",Annualise the investment costs of retrofitting --- tax_weighting,--,"{true, false}",Weight the costs of retrofitting depending on taxes in countries --- construction_index,--,"{true, false}",Weight the costs of retrofitting depending on labour/material costs per country -tes,--,"{true, false}",Add option for storing thermal energy in large water pits associated with district heating systems and individual thermal energy storage (TES) -tes_tau,,,The time constant used to calculate the decay of thermal energy in thermal energy storage (TES): 1- :math:`e^{-1/24τ}`. --- decentral,days,float,The time constant in decentralized thermal energy storage (TES) --- central,days,float,The time constant in centralized thermal energy storage (TES) -boilers,--,"{true, false}",Add option for transforming gas into heat using gas boilers -resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers) -oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers -biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers -overdimension_individual_heating,--,"float",Add option for overdimensioning individual heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1. -chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) -micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas. -solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat. -solar_cf_correction,--,float,The correction factor for the value provided by the solar thermal profile calculations -marginal_cost_storage,currency/MWh ,float,The marginal cost of discharging batteries in distributed grids -methanation,--,"{true, false}",Add option for transforming hydrogen and CO2 into methane using methanation. -coal_cc,--,"{true, false}",Add option for coal CHPs with carbon capture -dac,--,"{true, false}",Add option for Direct Air Capture (DAC) -co2_vent,--,"{true, false}",Add option for vent out CO2 from storages to the atmosphere. -allam_cycle,--,"{true, false}",Add option to include `Allam cycle gas power plants `_ -hydrogen_fuel_cell,--,"{true, false}",Add option to include hydrogen fuel cell for re-electrification. Assuming OCGT technology costs -hydrogen_turbine,--,"{true, false}",Add option to include hydrogen turbine for re-electrification. Assuming OCGT technology costs -SMR,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) -SMR CC,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) and Carbon Capture (CC) -regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed. -regional_oil_demand,--,"{true, false}",Spatially resolve oil demand. Set to true if regional CO2 constraints needed. -regional_co2 _sequestration_potential,,, --- enable,--,"{true, false}",Add option for regionally-resolved geological carbon dioxide sequestration potentials based on `CO2StoP `_. --- attribute,--,string,Name of the attribute for the sequestration potential --- include_onshore,--,"{true, false}",Add options for including onshore sequestration potentials --- min_size,Gt ,float,Any sites with lower potential than this value will be excluded --- max_size,Gt ,float,The maximum sequestration potential for any one site. --- years_of_storage,years,float,The years until potential exhausted at optimised annual rate -co2_sequestration_potential,MtCO2/a,float,The potential of sequestering CO2 in Europe per year -co2_sequestration_cost,currency/tCO2,float,The cost of sequestering a ton of CO2 -co2_sequestration_lifetime,years,int,The lifetime of a CO2 sequestration site -co2_spatial,--,"{true, false}","Add option to spatially resolve carrier representing stored carbon dioxide. This allows for more detailed modelling of CCUTS, e.g. regarding the capturing of industrial process emissions, usage as feedstock for electrofuels, transport of carbon dioxide, and geological sequestration sites." -,,, -co2network,--,"{true, false}",Add option for planning a new carbon dioxide transmission network -co2_network_cost_factor,p.u.,float,The cost factor for the capital cost of the carbon dioxide transmission network -,,, -cc_fraction,--,float,The default fraction of CO2 captured with post-combustion capture -hydrogen_underground _storage,--,"{true, false}",Add options for storing hydrogen underground. Storage potential depends regionally. -hydrogen_underground _storage_locations,,"{onshore, nearshore, offshore}","The location where hydrogen underground storage can be located. Onshore, nearshore, offshore means it must be located more than 50 km away from the sea, within 50 km of the sea, or within the sea itself respectively." -,,, -ammonia,--,"{true, false, regional}","Add ammonia as a carrrier. It can be either true (copperplated NH3), false (no NH3 carrier) or ""regional"" (regionalised NH3 without network)" -min_part_load_fischer _tropsch,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the Fischer-Tropsch process -min_part_load _methanolisation,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the methanolisation process -,,, -use_fischer_tropsch _waste_heat,--,"{true, false}",Add option for using waste heat of Fischer Tropsch in district heating networks -use_fuel_cell_waste_heat,--,"{true, false}",Add option for using waste heat of fuel cells in district heating networks -use_electrolysis_waste _heat,--,"{true, false}",Add option for using waste heat of electrolysis in district heating networks -electricity_transmission _grid,--,"{true, false}",Switch for enabling/disabling the electricity transmission grid. -electricity_distribution _grid,--,"{true, false}",Add a simplified representation of the exchange capacity between transmission and distribution grid level through a link. -electricity_distribution _grid_cost_factor,,,Multiplies the investment cost of the electricity distribution grid -,,, -electricity_grid _connection,--,"{true, false}",Add the cost of electricity grid connection for onshore wind and solar -transmission_efficiency,,,Section to specify transmission losses or compression energy demands of bidirectional links. Splits them into two capacity-linked unidirectional links. --- {carrier},--,str,The carrier of the link. --- -- efficiency_static,p.u.,float,Length-independent transmission efficiency. --- -- efficiency_per_1000km,p.u. per 1000 km,float,Length-dependent transmission efficiency ($\eta^{\text{length}}$) --- -- compression_per_1000km,p.u. per 1000 km,float,Length-dependent electricity demand for compression ($\eta \cdot \text{length}$) implemented as multi-link to local electricity bus. -H2_network,--,"{true, false}",Add option for new hydrogen pipelines -gas_network,--,"{true, false}","Add existing natural gas infrastructure, incl. LNG terminals, production and entry-points. The existing gas network is added with a lossless transport model. A length-weighted `k-edge augmentation algorithm `_ can be run to add new candidate gas pipelines such that all regions of the model can be connected to the gas network. When activated, all the gas demands are regionally disaggregated as well." -H2_retrofit,--,"{true, false}",Add option for retrofiting existing pipelines to transport hydrogen. -H2_retrofit_capacity _per_CH4,--,float,"The ratio for H2 capacity per original CH4 capacity of retrofitted pipelines. The `European Hydrogen Backbone (April, 2020) p.15 `_ 60% of original natural gas capacity could be used in cost-optimal case as H2 capacity." -gas_network_connectivity _upgrade ,--,float,The number of desired edge connectivity (k) in the length-weighted `k-edge augmentation algorithm `_ used for the gas network -gas_distribution_grid,--,"{true, false}",Add a gas distribution grid -gas_distribution_grid _cost_factor,,,Multiplier for the investment cost of the gas distribution grid -,,, -biomass_spatial,--,"{true, false}",Add option for resolving biomass demand regionally -biomass_transport,--,"{true, false}",Add option for transporting solid biomass between nodes -biogas_upgrading_cc,--,"{true, false}",Add option to capture CO2 from biomass upgrading -conventional_generation,,,Add a more detailed description of conventional carriers. Any power generation requires the consumption of fuel from nodes representing that fuel. -biomass_to_liquid,--,"{true, false}",Add option for transforming solid biomass into liquid fuel with the same properties as oil -biosng,--,"{true, false}",Add option for transforming solid biomass into synthesis gas with the same properties as natural gas -limit_max_growth,,, --- enable,--,"{true, false}",Add option to limit the maximum growth of a carrier --- factor,p.u.,float,The maximum growth factor of a carrier (e.g. 1.3 allows 30% larger than max historic growth) --- max_growth,,, --- -- {carrier},GW,float,The historic maximum growth of a carrier --- max_relative_growth, --- -- {carrier},p.u.,float,The historic maximum relative growth of a carrier +,Unit,Values,Description +transport,--,"{true, false}",Flag to include transport sector. +heating,--,"{true, false}",Flag to include heating sector. +biomass,--,"{true, false}",Flag to include biomass sector. +industry,--,"{true, false}",Flag to include industry sector. +agriculture,--,"{true, false}",Flag to include agriculture sector. +district_heating,--,,`prepare_sector_network.py `_ +-- potential,--,float,maximum fraction of urban demand which can be supplied by district heating +-- progress,--,Dictionary with planning horizons as keys., Increase of today's district heating demand to potential maximum district heating share. Progress = 0 means today's district heating share. Progress = 1 means maximum fraction of urban demand is supplied by district heating +-- district_heating_loss,--,float,Share increase in district heat demand in urban central due to heat losses +cluster_heat_buses,--,"{true, false}",Cluster residential and service heat buses in `prepare_sector_network.py `_ to one to save memory. +,,, +bev_dsm_restriction _value,--,float,Adds a lower state of charge (SOC) limit for battery electric vehicles (BEV) to manage its own energy demand (DSM). Located in `build_transport_demand.py `_. Set to 0 for no restriction on BEV DSM +bev_dsm_restriction _time,--,float,Time at which SOC of BEV has to be dsm_restriction_value +transport_heating _deadband_upper,°C,float,"The maximum temperature in the vehicle. At higher temperatures, the energy required for cooling in the vehicle increases." +transport_heating _deadband_lower,°C,float,"The minimum temperature in the vehicle. At lower temperatures, the energy required for heating in the vehicle increases." +,,, +ICE_lower_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the cold environment and the minimum temperature. +ICE_upper_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the hot environment and the maximum temperature. +EV_lower_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the cold environment and the minimum temperature. +EV_upper_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the hot environment and the maximum temperature. +bev_dsm,--,"{true, false}",Add the option for battery electric vehicles (BEV) to participate in demand-side management (DSM) +,,, +bev_availability,--,float,The share for battery electric vehicles (BEV) that are able to do demand side management (DSM) +bev_energy,--,float,The average size of battery electric vehicles (BEV) in MWh +bev_charge_efficiency,--,float,Battery electric vehicles (BEV) charge and discharge efficiency +bev_plug_to_wheel _efficiency,km/kWh,float,The distance battery electric vehicles (BEV) can travel in km per kWh of energy charge in battery. Base value comes from `Tesla Model S `_ +bev_charge_rate,MWh,float,The power consumption for one electric vehicle (EV) in MWh. Value derived from 3-phase charger with 11 kW. +bev_avail_max,--,float,The maximum share plugged-in availability for passenger electric vehicles. +bev_avail_mean,--,float,The average share plugged-in availability for passenger electric vehicles. +v2g,--,"{true, false}",Allows feed-in to grid from EV battery +land_transport_fuel_cell _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses fuel cells in a given year +land_transport_electric _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses electric vehicles (EV) in a given year +land_transport_ice _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses internal combustion engines (ICE) in a given year. What is not EV or FCEV is oil-fuelled ICE. +transport_fuel_cell _efficiency,--,float,The H2 conversion efficiencies of fuel cells in transport +transport_internal _combustion_efficiency,--,float,The oil conversion efficiencies of internal combustion engine (ICE) in transport +agriculture_machinery _electric_share,--,float,The share for agricultural machinery that uses electricity +agriculture_machinery _oil_share,--,float,The share for agricultural machinery that uses oil +agriculture_machinery _fuel_efficiency,--,float,The efficiency of electric-powered machinery in the conversion of electricity to meet agricultural needs. +agriculture_machinery _electric_efficiency,--,float,The efficiency of oil-powered machinery in the conversion of oil to meet agricultural needs. +Mwh_MeOH_per_MWh_H2,LHV,float,"The energy amount of the produced methanol per energy amount of hydrogen. From `DECHEMA (2017) `_, page 64." +MWh_MeOH_per_tCO2,LHV,float,"The energy amount of the produced methanol per ton of CO2. From `DECHEMA (2017) `_, page 64." +MWh_MeOH_per_MWh_e,LHV,float,"The energy amount of the produced methanol per energy amount of electricity. From `DECHEMA (2017) `_, page 64." +shipping_hydrogen _liquefaction,--,"{true, false}",Whether to include liquefaction costs for hydrogen demand in shipping. +,,, +shipping_hydrogen_share,--,Dictionary with planning horizons as keys.,The share of ships powered by hydrogen in a given year +shipping_methanol_share,--,Dictionary with planning horizons as keys.,The share of ships powered by methanol in a given year +shipping_oil_share,--,Dictionary with planning horizons as keys.,The share of ships powered by oil in a given year +shipping_methanol _efficiency,--,float,The efficiency of methanol-powered ships in the conversion of methanol to meet shipping needs (propulsion). The efficiency increase from oil can be 10-15% higher according to the `IEA `_ +,,, +shipping_oil_efficiency,--,float,The efficiency of oil-powered ships in the conversion of oil to meet shipping needs (propulsion). Base value derived from 2011 +aviation_demand_factor,--,float,The proportion of demand for aviation compared to today's consumption +HVC_demand_factor,--,float,The proportion of demand for high-value chemicals compared to today's consumption +,,, +time_dep_hp_cop,--,"{true, false}",Consider the time dependent coefficient of performance (COP) of the heat pump +heat_pump_sink_T,°C,float,The temperature heat sink used in heat pumps based on DTU / large area radiators. The value is conservatively high to cover hot water and space heating in poorly-insulated buildings +reduce_space_heat _exogenously,--,"{true, false}",Influence on space heating demand by a certain factor (applied before losses in district heating). +reduce_space_heat _exogenously_factor,--,Dictionary with planning horizons as keys.,"A positive factor can mean renovation or demolition of a building. If the factor is negative, it can mean an increase in floor area, increased thermal comfort, population growth. The default factors are determined by the `Eurocalc Homes and buildings decarbonization scenario `_" +retrofitting,,, +-- retro_endogen,--,"{true, false}",Add retrofitting as an endogenous system which co-optimise space heat savings. +-- cost_factor,--,float,Weight costs for building renovation +-- interest_rate,--,float,The interest rate for investment in building components +-- annualise_cost,--,"{true, false}",Annualise the investment costs of retrofitting +-- tax_weighting,--,"{true, false}",Weight the costs of retrofitting depending on taxes in countries +-- construction_index,--,"{true, false}",Weight the costs of retrofitting depending on labour/material costs per country +tes,--,"{true, false}",Add option for storing thermal energy in large water pits associated with district heating systems and individual thermal energy storage (TES) +tes_tau,,,The time constant used to calculate the decay of thermal energy in thermal energy storage (TES): 1- :math:`e^{-1/24τ}`. +-- decentral,days,float,The time constant in decentralized thermal energy storage (TES) +-- central,days,float,The time constant in centralized thermal energy storage (TES) +boilers,--,"{true, false}",Add option for transforming gas into heat using gas boilers +resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers) +oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers +biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers +overdimension_individual_heating,--,float,Add option for overdimensioning individual heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1. +chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) +micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas. +solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat. +solar_cf_correction,--,float,The correction factor for the value provided by the solar thermal profile calculations +marginal_cost_storage,currency/MWh ,float,The marginal cost of discharging batteries in distributed grids +methanation,--,"{true, false}",Add option for transforming hydrogen and CO2 into methane using methanation. +coal_cc,--,"{true, false}",Add option for coal CHPs with carbon capture +dac,--,"{true, false}",Add option for Direct Air Capture (DAC) +co2_vent,--,"{true, false}",Add option for vent out CO2 from storages to the atmosphere. +allam_cycle,--,"{true, false}",Add option to include `Allam cycle gas power plants `_ +hydrogen_fuel_cell,--,"{true, false}",Add option to include hydrogen fuel cell for re-electrification. Assuming OCGT technology costs +hydrogen_turbine,--,"{true, false}",Add option to include hydrogen turbine for re-electrification. Assuming OCGT technology costs +SMR,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) +SMR CC,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) and Carbon Capture (CC) +regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed. +regional_oil_demand,--,"{true, false}",Spatially resolve oil demand. Set to true if regional CO2 constraints needed. +regional_co2 _sequestration_potential,,, +-- enable,--,"{true, false}",Add option for regionally-resolved geological carbon dioxide sequestration potentials based on `CO2StoP `_. +-- attribute,--,list,List of names of the attributes for the sequestration potential +-- include_onshore,--,"{true, false}",Add options for including onshore sequestration potentials +-- min_size,Gt ,float,Any sites with lower potential than this value will be excluded +-- max_size,Gt ,float,The maximum sequestration potential for any one site. +-- years_of_storage,years,float,The years until potential exhausted at optimised annual rate +co2_sequestration_potential,MtCO2/a,float,The potential of sequestering CO2 in Europe per year +co2_sequestration_cost,currency/tCO2,float,The cost of sequestering a ton of CO2 +co2_sequestration_lifetime,years,int,The lifetime of a CO2 sequestration site +co2_spatial,--,"{true, false}","Add option to spatially resolve carrier representing stored carbon dioxide. This allows for more detailed modelling of CCUTS, e.g. regarding the capturing of industrial process emissions, usage as feedstock for electrofuels, transport of carbon dioxide, and geological sequestration sites." +,,, +co2network,--,"{true, false}",Add option for planning a new carbon dioxide transmission network +co2_network_cost_factor,p.u.,float,The cost factor for the capital cost of the carbon dioxide transmission network +,,, +cc_fraction,--,float,The default fraction of CO2 captured with post-combustion capture +hydrogen_underground _storage,--,"{true, false}",Add options for storing hydrogen underground. Storage potential depends regionally. +hydrogen_underground _storage_locations,,"{onshore, nearshore, offshore}","The location where hydrogen underground storage can be located. Onshore, nearshore, offshore means it must be located more than 50 km away from the sea, within 50 km of the sea, or within the sea itself respectively." +,,, +ammonia,--,"{true, false, regional}","Add ammonia as a carrrier. It can be either true (copperplated NH3), false (no NH3 carrier) or ""regional"" (regionalised NH3 without network)" +min_part_load_fischer _tropsch,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the Fischer-Tropsch process +min_part_load _methanolisation,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the methanolisation process +,,, +use_fischer_tropsch _waste_heat,--,"{true, false}",Add option for using waste heat of Fischer Tropsch in district heating networks +use_fuel_cell_waste_heat,--,"{true, false}",Add option for using waste heat of fuel cells in district heating networks +use_electrolysis_waste _heat,--,"{true, false}",Add option for using waste heat of electrolysis in district heating networks +electricity_transmission _grid,--,"{true, false}",Switch for enabling/disabling the electricity transmission grid. +electricity_distribution _grid,--,"{true, false}",Add a simplified representation of the exchange capacity between transmission and distribution grid level through a link. +electricity_distribution _grid_cost_factor,,,Multiplies the investment cost of the electricity distribution grid +,,, +electricity_grid _connection,--,"{true, false}",Add the cost of electricity grid connection for onshore wind and solar +transmission_efficiency,,,Section to specify transmission losses or compression energy demands of bidirectional links. Splits them into two capacity-linked unidirectional links. +-- {carrier},--,str,The carrier of the link. +-- -- efficiency_static,p.u.,float,Length-independent transmission efficiency. +-- -- efficiency_per_1000km,p.u. per 1000 km,float,Length-dependent transmission efficiency ($\eta^{\text{length}}$) +-- -- compression_per_1000km,p.u. per 1000 km,float,Length-dependent electricity demand for compression ($\eta \cdot \text{length}$) implemented as multi-link to local electricity bus. +H2_network,--,"{true, false}",Add option for new hydrogen pipelines +gas_network,--,"{true, false}","Add existing natural gas infrastructure, incl. LNG terminals, production and entry-points. The existing gas network is added with a lossless transport model. A length-weighted `k-edge augmentation algorithm `_ can be run to add new candidate gas pipelines such that all regions of the model can be connected to the gas network. When activated, all the gas demands are regionally disaggregated as well." +H2_retrofit,--,"{true, false}",Add option for retrofiting existing pipelines to transport hydrogen. +H2_retrofit_capacity _per_CH4,--,float,"The ratio for H2 capacity per original CH4 capacity of retrofitted pipelines. The `European Hydrogen Backbone (April, 2020) p.15 `_ 60% of original natural gas capacity could be used in cost-optimal case as H2 capacity." +gas_network_connectivity _upgrade ,--,float,The number of desired edge connectivity (k) in the length-weighted `k-edge augmentation algorithm `_ used for the gas network +gas_distribution_grid,--,"{true, false}",Add a gas distribution grid +gas_distribution_grid _cost_factor,,,Multiplier for the investment cost of the gas distribution grid +,,, +biomass_spatial,--,"{true, false}",Add option for resolving biomass demand regionally +biomass_transport,--,"{true, false}",Add option for transporting solid biomass between nodes +biogas_upgrading_cc,--,"{true, false}",Add option to capture CO2 from biomass upgrading +conventional_generation,,,Add a more detailed description of conventional carriers. Any power generation requires the consumption of fuel from nodes representing that fuel. +biomass_to_liquid,--,"{true, false}",Add option for transforming solid biomass into liquid fuel with the same properties as oil +biosng,--,"{true, false}",Add option for transforming solid biomass into synthesis gas with the same properties as natural gas +limit_max_growth,,, +-- enable,--,"{true, false}",Add option to limit the maximum growth of a carrier +-- factor,p.u.,float,The maximum growth factor of a carrier (e.g. 1.3 allows 30% larger than max historic growth) +-- max_growth,,, +-- -- {carrier},GW,float,The historic maximum growth of a carrier +-- max_relative_growth,,, +-- -- {carrier},p.u.,float,The historic maximum relative growth of a carrier From 05a3c43c30bd82a20f2c50f5a901a26cad2da6a6 Mon Sep 17 00:00:00 2001 From: Philipp Glaum Date: Wed, 10 Apr 2024 12:23:28 +0200 Subject: [PATCH 517/591] move prefix from Snakefile to get_dir function --- Snakefile | 8 +------- scripts/_helpers.py | 5 +++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Snakefile b/Snakefile index ed60c0f5..ba93a869 100644 --- a/Snakefile +++ b/Snakefile @@ -22,13 +22,7 @@ configfile: "config/config.yaml" run = config["run"] scenarios = get_scenarios(run) -prefix = run.get("prefix", "") -rdir = get_rdir(run) - -if prefix: - RDIR = f"{prefix}/{rdir}" -else: - RDIR = rdir +RDIR = get_rdir(run) logs = path_provider("logs/", RDIR, run["shared_resources"]) benchmarks = path_provider("benchmarks/", RDIR, run["shared_resources"]) diff --git a/scripts/_helpers.py b/scripts/_helpers.py index 64ccab87..dfedcaea 100644 --- a/scripts/_helpers.py +++ b/scripts/_helpers.py @@ -59,6 +59,11 @@ def get_rdir(run): RDIR = run["name"] + "/" else: RDIR = "" + + prefix = run.get("prefix", "") + if prefix: + RDIR = f"{prefix}/{RDIR}" + return RDIR From 8a0c12b579976491885d642a5d2a1431d8c88d6f Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 10 Apr 2024 16:56:35 +0200 Subject: [PATCH 518/591] add doc and release notes --- doc/configtables/run.csv | 1 + doc/release_notes.rst | 3 +++ 2 files changed, 4 insertions(+) diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index 2835a324..44f06165 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -1,5 +1,6 @@ ,Unit,Values,Description name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenario: enable:`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenario: file:``. If the name is 'all', all defined scenarios will be run." +prefix,--,str,"Prefix for the run name which is used as a top-layer directory name in the results and resources folders." scenarios,,, -- enable,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``file``." -- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run: scenarios`` has to be set to ``true`` and ``run: name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combination of settings, alter and use the ``config/create_scenarios.py`` script in the ``config`` directory." diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b782a6df..79dfadcc 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -152,6 +152,9 @@ Upcoming Release - Collection rules get a new wildcard ``run=config["run"]["name"]`` so they can collect outputs across different scenarios. + - It is further possible to encapsulate your scenarios in a directory using + the setting ``run: prefix:``. + - **Warning:** One caveat remains for the scenario management with myopic or perfect foresight pathway optimisation. The first investment period must be shared across all scenarios. The reason is that the ``wildcard_constraints`` From 6bc136308017451852e6ed34dc1caba4b1b4fd5c Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 10 Apr 2024 17:13:58 +0200 Subject: [PATCH 519/591] allow sequestration potential attributes to be string --- config/config.default.yaml | 6 +- doc/configtables/sector.csv | 294 +++++++++++----------- doc/release_notes.rst | 2 +- scripts/build_sequestration_potentials.py | 2 + 4 files changed, 155 insertions(+), 149 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 6a703b31..0fc99a8d 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -515,7 +515,11 @@ sector: regional_coal_demand: false regional_co2_sequestration_potential: enable: false - attribute: ['conservative estimate Mt', 'conservative estimate GAS Mt', 'conservative estimate OIL Mt', 'conservative estimate aquifer Mt'] + attribute: + - conservative estimate Mt + - conservative estimate GAS Mt + - conservative estimate OIL Mt + - conservative estimate aquifer Mt include_onshore: false min_size: 3 max_size: 25 diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv index 1692d299..58ccd9bf 100644 --- a/doc/configtables/sector.csv +++ b/doc/configtables/sector.csv @@ -1,147 +1,147 @@ -,Unit,Values,Description -transport,--,"{true, false}",Flag to include transport sector. -heating,--,"{true, false}",Flag to include heating sector. -biomass,--,"{true, false}",Flag to include biomass sector. -industry,--,"{true, false}",Flag to include industry sector. -agriculture,--,"{true, false}",Flag to include agriculture sector. -district_heating,--,,`prepare_sector_network.py `_ --- potential,--,float,maximum fraction of urban demand which can be supplied by district heating --- progress,--,Dictionary with planning horizons as keys., Increase of today's district heating demand to potential maximum district heating share. Progress = 0 means today's district heating share. Progress = 1 means maximum fraction of urban demand is supplied by district heating --- district_heating_loss,--,float,Share increase in district heat demand in urban central due to heat losses -cluster_heat_buses,--,"{true, false}",Cluster residential and service heat buses in `prepare_sector_network.py `_ to one to save memory. -,,, -bev_dsm_restriction _value,--,float,Adds a lower state of charge (SOC) limit for battery electric vehicles (BEV) to manage its own energy demand (DSM). Located in `build_transport_demand.py `_. Set to 0 for no restriction on BEV DSM -bev_dsm_restriction _time,--,float,Time at which SOC of BEV has to be dsm_restriction_value -transport_heating _deadband_upper,°C,float,"The maximum temperature in the vehicle. At higher temperatures, the energy required for cooling in the vehicle increases." -transport_heating _deadband_lower,°C,float,"The minimum temperature in the vehicle. At lower temperatures, the energy required for heating in the vehicle increases." -,,, -ICE_lower_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the cold environment and the minimum temperature. -ICE_upper_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the hot environment and the maximum temperature. -EV_lower_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the cold environment and the minimum temperature. -EV_upper_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the hot environment and the maximum temperature. -bev_dsm,--,"{true, false}",Add the option for battery electric vehicles (BEV) to participate in demand-side management (DSM) -,,, -bev_availability,--,float,The share for battery electric vehicles (BEV) that are able to do demand side management (DSM) -bev_energy,--,float,The average size of battery electric vehicles (BEV) in MWh -bev_charge_efficiency,--,float,Battery electric vehicles (BEV) charge and discharge efficiency -bev_plug_to_wheel _efficiency,km/kWh,float,The distance battery electric vehicles (BEV) can travel in km per kWh of energy charge in battery. Base value comes from `Tesla Model S `_ -bev_charge_rate,MWh,float,The power consumption for one electric vehicle (EV) in MWh. Value derived from 3-phase charger with 11 kW. -bev_avail_max,--,float,The maximum share plugged-in availability for passenger electric vehicles. -bev_avail_mean,--,float,The average share plugged-in availability for passenger electric vehicles. -v2g,--,"{true, false}",Allows feed-in to grid from EV battery -land_transport_fuel_cell _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses fuel cells in a given year -land_transport_electric _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses electric vehicles (EV) in a given year -land_transport_ice _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses internal combustion engines (ICE) in a given year. What is not EV or FCEV is oil-fuelled ICE. -transport_fuel_cell _efficiency,--,float,The H2 conversion efficiencies of fuel cells in transport -transport_internal _combustion_efficiency,--,float,The oil conversion efficiencies of internal combustion engine (ICE) in transport -agriculture_machinery _electric_share,--,float,The share for agricultural machinery that uses electricity -agriculture_machinery _oil_share,--,float,The share for agricultural machinery that uses oil -agriculture_machinery _fuel_efficiency,--,float,The efficiency of electric-powered machinery in the conversion of electricity to meet agricultural needs. -agriculture_machinery _electric_efficiency,--,float,The efficiency of oil-powered machinery in the conversion of oil to meet agricultural needs. -Mwh_MeOH_per_MWh_H2,LHV,float,"The energy amount of the produced methanol per energy amount of hydrogen. From `DECHEMA (2017) `_, page 64." -MWh_MeOH_per_tCO2,LHV,float,"The energy amount of the produced methanol per ton of CO2. From `DECHEMA (2017) `_, page 64." -MWh_MeOH_per_MWh_e,LHV,float,"The energy amount of the produced methanol per energy amount of electricity. From `DECHEMA (2017) `_, page 64." -shipping_hydrogen _liquefaction,--,"{true, false}",Whether to include liquefaction costs for hydrogen demand in shipping. -,,, -shipping_hydrogen_share,--,Dictionary with planning horizons as keys.,The share of ships powered by hydrogen in a given year -shipping_methanol_share,--,Dictionary with planning horizons as keys.,The share of ships powered by methanol in a given year -shipping_oil_share,--,Dictionary with planning horizons as keys.,The share of ships powered by oil in a given year -shipping_methanol _efficiency,--,float,The efficiency of methanol-powered ships in the conversion of methanol to meet shipping needs (propulsion). The efficiency increase from oil can be 10-15% higher according to the `IEA `_ -,,, -shipping_oil_efficiency,--,float,The efficiency of oil-powered ships in the conversion of oil to meet shipping needs (propulsion). Base value derived from 2011 -aviation_demand_factor,--,float,The proportion of demand for aviation compared to today's consumption -HVC_demand_factor,--,float,The proportion of demand for high-value chemicals compared to today's consumption -,,, -time_dep_hp_cop,--,"{true, false}",Consider the time dependent coefficient of performance (COP) of the heat pump -heat_pump_sink_T,°C,float,The temperature heat sink used in heat pumps based on DTU / large area radiators. The value is conservatively high to cover hot water and space heating in poorly-insulated buildings -reduce_space_heat _exogenously,--,"{true, false}",Influence on space heating demand by a certain factor (applied before losses in district heating). -reduce_space_heat _exogenously_factor,--,Dictionary with planning horizons as keys.,"A positive factor can mean renovation or demolition of a building. If the factor is negative, it can mean an increase in floor area, increased thermal comfort, population growth. The default factors are determined by the `Eurocalc Homes and buildings decarbonization scenario `_" -retrofitting,,, --- retro_endogen,--,"{true, false}",Add retrofitting as an endogenous system which co-optimise space heat savings. --- cost_factor,--,float,Weight costs for building renovation --- interest_rate,--,float,The interest rate for investment in building components --- annualise_cost,--,"{true, false}",Annualise the investment costs of retrofitting --- tax_weighting,--,"{true, false}",Weight the costs of retrofitting depending on taxes in countries --- construction_index,--,"{true, false}",Weight the costs of retrofitting depending on labour/material costs per country -tes,--,"{true, false}",Add option for storing thermal energy in large water pits associated with district heating systems and individual thermal energy storage (TES) -tes_tau,,,The time constant used to calculate the decay of thermal energy in thermal energy storage (TES): 1- :math:`e^{-1/24τ}`. --- decentral,days,float,The time constant in decentralized thermal energy storage (TES) --- central,days,float,The time constant in centralized thermal energy storage (TES) -boilers,--,"{true, false}",Add option for transforming gas into heat using gas boilers -resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers) -oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers -biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers -overdimension_individual_heating,--,float,Add option for overdimensioning individual heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1. -chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) -micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas. -solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat. -solar_cf_correction,--,float,The correction factor for the value provided by the solar thermal profile calculations -marginal_cost_storage,currency/MWh ,float,The marginal cost of discharging batteries in distributed grids -methanation,--,"{true, false}",Add option for transforming hydrogen and CO2 into methane using methanation. -coal_cc,--,"{true, false}",Add option for coal CHPs with carbon capture -dac,--,"{true, false}",Add option for Direct Air Capture (DAC) -co2_vent,--,"{true, false}",Add option for vent out CO2 from storages to the atmosphere. -allam_cycle,--,"{true, false}",Add option to include `Allam cycle gas power plants `_ -hydrogen_fuel_cell,--,"{true, false}",Add option to include hydrogen fuel cell for re-electrification. Assuming OCGT technology costs -hydrogen_turbine,--,"{true, false}",Add option to include hydrogen turbine for re-electrification. Assuming OCGT technology costs -SMR,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) -SMR CC,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) and Carbon Capture (CC) -regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed. -regional_oil_demand,--,"{true, false}",Spatially resolve oil demand. Set to true if regional CO2 constraints needed. -regional_co2 _sequestration_potential,,, --- enable,--,"{true, false}",Add option for regionally-resolved geological carbon dioxide sequestration potentials based on `CO2StoP `_. --- attribute,--,list,List of names of the attributes for the sequestration potential --- include_onshore,--,"{true, false}",Add options for including onshore sequestration potentials --- min_size,Gt ,float,Any sites with lower potential than this value will be excluded --- max_size,Gt ,float,The maximum sequestration potential for any one site. --- years_of_storage,years,float,The years until potential exhausted at optimised annual rate -co2_sequestration_potential,MtCO2/a,float,The potential of sequestering CO2 in Europe per year -co2_sequestration_cost,currency/tCO2,float,The cost of sequestering a ton of CO2 -co2_sequestration_lifetime,years,int,The lifetime of a CO2 sequestration site -co2_spatial,--,"{true, false}","Add option to spatially resolve carrier representing stored carbon dioxide. This allows for more detailed modelling of CCUTS, e.g. regarding the capturing of industrial process emissions, usage as feedstock for electrofuels, transport of carbon dioxide, and geological sequestration sites." -,,, -co2network,--,"{true, false}",Add option for planning a new carbon dioxide transmission network -co2_network_cost_factor,p.u.,float,The cost factor for the capital cost of the carbon dioxide transmission network -,,, -cc_fraction,--,float,The default fraction of CO2 captured with post-combustion capture -hydrogen_underground _storage,--,"{true, false}",Add options for storing hydrogen underground. Storage potential depends regionally. -hydrogen_underground _storage_locations,,"{onshore, nearshore, offshore}","The location where hydrogen underground storage can be located. Onshore, nearshore, offshore means it must be located more than 50 km away from the sea, within 50 km of the sea, or within the sea itself respectively." -,,, -ammonia,--,"{true, false, regional}","Add ammonia as a carrrier. It can be either true (copperplated NH3), false (no NH3 carrier) or ""regional"" (regionalised NH3 without network)" -min_part_load_fischer _tropsch,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the Fischer-Tropsch process -min_part_load _methanolisation,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the methanolisation process -,,, -use_fischer_tropsch _waste_heat,--,"{true, false}",Add option for using waste heat of Fischer Tropsch in district heating networks -use_fuel_cell_waste_heat,--,"{true, false}",Add option for using waste heat of fuel cells in district heating networks -use_electrolysis_waste _heat,--,"{true, false}",Add option for using waste heat of electrolysis in district heating networks -electricity_transmission _grid,--,"{true, false}",Switch for enabling/disabling the electricity transmission grid. -electricity_distribution _grid,--,"{true, false}",Add a simplified representation of the exchange capacity between transmission and distribution grid level through a link. -electricity_distribution _grid_cost_factor,,,Multiplies the investment cost of the electricity distribution grid -,,, -electricity_grid _connection,--,"{true, false}",Add the cost of electricity grid connection for onshore wind and solar -transmission_efficiency,,,Section to specify transmission losses or compression energy demands of bidirectional links. Splits them into two capacity-linked unidirectional links. --- {carrier},--,str,The carrier of the link. --- -- efficiency_static,p.u.,float,Length-independent transmission efficiency. --- -- efficiency_per_1000km,p.u. per 1000 km,float,Length-dependent transmission efficiency ($\eta^{\text{length}}$) --- -- compression_per_1000km,p.u. per 1000 km,float,Length-dependent electricity demand for compression ($\eta \cdot \text{length}$) implemented as multi-link to local electricity bus. -H2_network,--,"{true, false}",Add option for new hydrogen pipelines -gas_network,--,"{true, false}","Add existing natural gas infrastructure, incl. LNG terminals, production and entry-points. The existing gas network is added with a lossless transport model. A length-weighted `k-edge augmentation algorithm `_ can be run to add new candidate gas pipelines such that all regions of the model can be connected to the gas network. When activated, all the gas demands are regionally disaggregated as well." -H2_retrofit,--,"{true, false}",Add option for retrofiting existing pipelines to transport hydrogen. -H2_retrofit_capacity _per_CH4,--,float,"The ratio for H2 capacity per original CH4 capacity of retrofitted pipelines. The `European Hydrogen Backbone (April, 2020) p.15 `_ 60% of original natural gas capacity could be used in cost-optimal case as H2 capacity." -gas_network_connectivity _upgrade ,--,float,The number of desired edge connectivity (k) in the length-weighted `k-edge augmentation algorithm `_ used for the gas network -gas_distribution_grid,--,"{true, false}",Add a gas distribution grid -gas_distribution_grid _cost_factor,,,Multiplier for the investment cost of the gas distribution grid -,,, -biomass_spatial,--,"{true, false}",Add option for resolving biomass demand regionally -biomass_transport,--,"{true, false}",Add option for transporting solid biomass between nodes -biogas_upgrading_cc,--,"{true, false}",Add option to capture CO2 from biomass upgrading -conventional_generation,,,Add a more detailed description of conventional carriers. Any power generation requires the consumption of fuel from nodes representing that fuel. -biomass_to_liquid,--,"{true, false}",Add option for transforming solid biomass into liquid fuel with the same properties as oil -biosng,--,"{true, false}",Add option for transforming solid biomass into synthesis gas with the same properties as natural gas -limit_max_growth,,, --- enable,--,"{true, false}",Add option to limit the maximum growth of a carrier --- factor,p.u.,float,The maximum growth factor of a carrier (e.g. 1.3 allows 30% larger than max historic growth) --- max_growth,,, --- -- {carrier},GW,float,The historic maximum growth of a carrier --- max_relative_growth,,, --- -- {carrier},p.u.,float,The historic maximum relative growth of a carrier +,Unit,Values,Description +transport,--,"{true, false}",Flag to include transport sector. +heating,--,"{true, false}",Flag to include heating sector. +biomass,--,"{true, false}",Flag to include biomass sector. +industry,--,"{true, false}",Flag to include industry sector. +agriculture,--,"{true, false}",Flag to include agriculture sector. +district_heating,--,,`prepare_sector_network.py `_ +-- potential,--,float,maximum fraction of urban demand which can be supplied by district heating +-- progress,--,Dictionary with planning horizons as keys., Increase of today's district heating demand to potential maximum district heating share. Progress = 0 means today's district heating share. Progress = 1 means maximum fraction of urban demand is supplied by district heating +-- district_heating_loss,--,float,Share increase in district heat demand in urban central due to heat losses +cluster_heat_buses,--,"{true, false}",Cluster residential and service heat buses in `prepare_sector_network.py `_ to one to save memory. +,,, +bev_dsm_restriction _value,--,float,Adds a lower state of charge (SOC) limit for battery electric vehicles (BEV) to manage its own energy demand (DSM). Located in `build_transport_demand.py `_. Set to 0 for no restriction on BEV DSM +bev_dsm_restriction _time,--,float,Time at which SOC of BEV has to be dsm_restriction_value +transport_heating _deadband_upper,°C,float,"The maximum temperature in the vehicle. At higher temperatures, the energy required for cooling in the vehicle increases." +transport_heating _deadband_lower,°C,float,"The minimum temperature in the vehicle. At lower temperatures, the energy required for heating in the vehicle increases." +,,, +ICE_lower_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the cold environment and the minimum temperature. +ICE_upper_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the hot environment and the maximum temperature. +EV_lower_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the cold environment and the minimum temperature. +EV_upper_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the hot environment and the maximum temperature. +bev_dsm,--,"{true, false}",Add the option for battery electric vehicles (BEV) to participate in demand-side management (DSM) +,,, +bev_availability,--,float,The share for battery electric vehicles (BEV) that are able to do demand side management (DSM) +bev_energy,--,float,The average size of battery electric vehicles (BEV) in MWh +bev_charge_efficiency,--,float,Battery electric vehicles (BEV) charge and discharge efficiency +bev_plug_to_wheel _efficiency,km/kWh,float,The distance battery electric vehicles (BEV) can travel in km per kWh of energy charge in battery. Base value comes from `Tesla Model S `_ +bev_charge_rate,MWh,float,The power consumption for one electric vehicle (EV) in MWh. Value derived from 3-phase charger with 11 kW. +bev_avail_max,--,float,The maximum share plugged-in availability for passenger electric vehicles. +bev_avail_mean,--,float,The average share plugged-in availability for passenger electric vehicles. +v2g,--,"{true, false}",Allows feed-in to grid from EV battery +land_transport_fuel_cell _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses fuel cells in a given year +land_transport_electric _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses electric vehicles (EV) in a given year +land_transport_ice _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses internal combustion engines (ICE) in a given year. What is not EV or FCEV is oil-fuelled ICE. +transport_fuel_cell _efficiency,--,float,The H2 conversion efficiencies of fuel cells in transport +transport_internal _combustion_efficiency,--,float,The oil conversion efficiencies of internal combustion engine (ICE) in transport +agriculture_machinery _electric_share,--,float,The share for agricultural machinery that uses electricity +agriculture_machinery _oil_share,--,float,The share for agricultural machinery that uses oil +agriculture_machinery _fuel_efficiency,--,float,The efficiency of electric-powered machinery in the conversion of electricity to meet agricultural needs. +agriculture_machinery _electric_efficiency,--,float,The efficiency of oil-powered machinery in the conversion of oil to meet agricultural needs. +Mwh_MeOH_per_MWh_H2,LHV,float,"The energy amount of the produced methanol per energy amount of hydrogen. From `DECHEMA (2017) `_, page 64." +MWh_MeOH_per_tCO2,LHV,float,"The energy amount of the produced methanol per ton of CO2. From `DECHEMA (2017) `_, page 64." +MWh_MeOH_per_MWh_e,LHV,float,"The energy amount of the produced methanol per energy amount of electricity. From `DECHEMA (2017) `_, page 64." +shipping_hydrogen _liquefaction,--,"{true, false}",Whether to include liquefaction costs for hydrogen demand in shipping. +,,, +shipping_hydrogen_share,--,Dictionary with planning horizons as keys.,The share of ships powered by hydrogen in a given year +shipping_methanol_share,--,Dictionary with planning horizons as keys.,The share of ships powered by methanol in a given year +shipping_oil_share,--,Dictionary with planning horizons as keys.,The share of ships powered by oil in a given year +shipping_methanol _efficiency,--,float,The efficiency of methanol-powered ships in the conversion of methanol to meet shipping needs (propulsion). The efficiency increase from oil can be 10-15% higher according to the `IEA `_ +,,, +shipping_oil_efficiency,--,float,The efficiency of oil-powered ships in the conversion of oil to meet shipping needs (propulsion). Base value derived from 2011 +aviation_demand_factor,--,float,The proportion of demand for aviation compared to today's consumption +HVC_demand_factor,--,float,The proportion of demand for high-value chemicals compared to today's consumption +,,, +time_dep_hp_cop,--,"{true, false}",Consider the time dependent coefficient of performance (COP) of the heat pump +heat_pump_sink_T,°C,float,The temperature heat sink used in heat pumps based on DTU / large area radiators. The value is conservatively high to cover hot water and space heating in poorly-insulated buildings +reduce_space_heat _exogenously,--,"{true, false}",Influence on space heating demand by a certain factor (applied before losses in district heating). +reduce_space_heat _exogenously_factor,--,Dictionary with planning horizons as keys.,"A positive factor can mean renovation or demolition of a building. If the factor is negative, it can mean an increase in floor area, increased thermal comfort, population growth. The default factors are determined by the `Eurocalc Homes and buildings decarbonization scenario `_" +retrofitting,,, +-- retro_endogen,--,"{true, false}",Add retrofitting as an endogenous system which co-optimise space heat savings. +-- cost_factor,--,float,Weight costs for building renovation +-- interest_rate,--,float,The interest rate for investment in building components +-- annualise_cost,--,"{true, false}",Annualise the investment costs of retrofitting +-- tax_weighting,--,"{true, false}",Weight the costs of retrofitting depending on taxes in countries +-- construction_index,--,"{true, false}",Weight the costs of retrofitting depending on labour/material costs per country +tes,--,"{true, false}",Add option for storing thermal energy in large water pits associated with district heating systems and individual thermal energy storage (TES) +tes_tau,,,The time constant used to calculate the decay of thermal energy in thermal energy storage (TES): 1- :math:`e^{-1/24τ}`. +-- decentral,days,float,The time constant in decentralized thermal energy storage (TES) +-- central,days,float,The time constant in centralized thermal energy storage (TES) +boilers,--,"{true, false}",Add option for transforming gas into heat using gas boilers +resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers) +oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers +biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers +overdimension_individual_heating,--,"float",Add option for overdimensioning individual heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1. +chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) +micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas. +solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat. +solar_cf_correction,--,float,The correction factor for the value provided by the solar thermal profile calculations +marginal_cost_storage,currency/MWh ,float,The marginal cost of discharging batteries in distributed grids +methanation,--,"{true, false}",Add option for transforming hydrogen and CO2 into methane using methanation. +coal_cc,--,"{true, false}",Add option for coal CHPs with carbon capture +dac,--,"{true, false}",Add option for Direct Air Capture (DAC) +co2_vent,--,"{true, false}",Add option for vent out CO2 from storages to the atmosphere. +allam_cycle,--,"{true, false}",Add option to include `Allam cycle gas power plants `_ +hydrogen_fuel_cell,--,"{true, false}",Add option to include hydrogen fuel cell for re-electrification. Assuming OCGT technology costs +hydrogen_turbine,--,"{true, false}",Add option to include hydrogen turbine for re-electrification. Assuming OCGT technology costs +SMR,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) +SMR CC,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) and Carbon Capture (CC) +regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed. +regional_oil_demand,--,"{true, false}",Spatially resolve oil demand. Set to true if regional CO2 constraints needed. +regional_co2 _sequestration_potential,,, +-- enable,--,"{true, false}",Add option for regionally-resolved geological carbon dioxide sequestration potentials based on `CO2StoP `_. +-- attribute,--,string or list,Name (or list of names) of the attribute(s) for the sequestration potential +-- include_onshore,--,"{true, false}",Add options for including onshore sequestration potentials +-- min_size,Gt ,float,Any sites with lower potential than this value will be excluded +-- max_size,Gt ,float,The maximum sequestration potential for any one site. +-- years_of_storage,years,float,The years until potential exhausted at optimised annual rate +co2_sequestration_potential,MtCO2/a,float,The potential of sequestering CO2 in Europe per year +co2_sequestration_cost,currency/tCO2,float,The cost of sequestering a ton of CO2 +co2_sequestration_lifetime,years,int,The lifetime of a CO2 sequestration site +co2_spatial,--,"{true, false}","Add option to spatially resolve carrier representing stored carbon dioxide. This allows for more detailed modelling of CCUTS, e.g. regarding the capturing of industrial process emissions, usage as feedstock for electrofuels, transport of carbon dioxide, and geological sequestration sites." +,,, +co2network,--,"{true, false}",Add option for planning a new carbon dioxide transmission network +co2_network_cost_factor,p.u.,float,The cost factor for the capital cost of the carbon dioxide transmission network +,,, +cc_fraction,--,float,The default fraction of CO2 captured with post-combustion capture +hydrogen_underground _storage,--,"{true, false}",Add options for storing hydrogen underground. Storage potential depends regionally. +hydrogen_underground _storage_locations,,"{onshore, nearshore, offshore}","The location where hydrogen underground storage can be located. Onshore, nearshore, offshore means it must be located more than 50 km away from the sea, within 50 km of the sea, or within the sea itself respectively." +,,, +ammonia,--,"{true, false, regional}","Add ammonia as a carrrier. It can be either true (copperplated NH3), false (no NH3 carrier) or ""regional"" (regionalised NH3 without network)" +min_part_load_fischer _tropsch,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the Fischer-Tropsch process +min_part_load _methanolisation,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the methanolisation process +,,, +use_fischer_tropsch _waste_heat,--,"{true, false}",Add option for using waste heat of Fischer Tropsch in district heating networks +use_fuel_cell_waste_heat,--,"{true, false}",Add option for using waste heat of fuel cells in district heating networks +use_electrolysis_waste _heat,--,"{true, false}",Add option for using waste heat of electrolysis in district heating networks +electricity_transmission _grid,--,"{true, false}",Switch for enabling/disabling the electricity transmission grid. +electricity_distribution _grid,--,"{true, false}",Add a simplified representation of the exchange capacity between transmission and distribution grid level through a link. +electricity_distribution _grid_cost_factor,,,Multiplies the investment cost of the electricity distribution grid +,,, +electricity_grid _connection,--,"{true, false}",Add the cost of electricity grid connection for onshore wind and solar +transmission_efficiency,,,Section to specify transmission losses or compression energy demands of bidirectional links. Splits them into two capacity-linked unidirectional links. +-- {carrier},--,str,The carrier of the link. +-- -- efficiency_static,p.u.,float,Length-independent transmission efficiency. +-- -- efficiency_per_1000km,p.u. per 1000 km,float,Length-dependent transmission efficiency ($\eta^{\text{length}}$) +-- -- compression_per_1000km,p.u. per 1000 km,float,Length-dependent electricity demand for compression ($\eta \cdot \text{length}$) implemented as multi-link to local electricity bus. +H2_network,--,"{true, false}",Add option for new hydrogen pipelines +gas_network,--,"{true, false}","Add existing natural gas infrastructure, incl. LNG terminals, production and entry-points. The existing gas network is added with a lossless transport model. A length-weighted `k-edge augmentation algorithm `_ can be run to add new candidate gas pipelines such that all regions of the model can be connected to the gas network. When activated, all the gas demands are regionally disaggregated as well." +H2_retrofit,--,"{true, false}",Add option for retrofiting existing pipelines to transport hydrogen. +H2_retrofit_capacity _per_CH4,--,float,"The ratio for H2 capacity per original CH4 capacity of retrofitted pipelines. The `European Hydrogen Backbone (April, 2020) p.15 `_ 60% of original natural gas capacity could be used in cost-optimal case as H2 capacity." +gas_network_connectivity _upgrade ,--,float,The number of desired edge connectivity (k) in the length-weighted `k-edge augmentation algorithm `_ used for the gas network +gas_distribution_grid,--,"{true, false}",Add a gas distribution grid +gas_distribution_grid _cost_factor,,,Multiplier for the investment cost of the gas distribution grid +,,, +biomass_spatial,--,"{true, false}",Add option for resolving biomass demand regionally +biomass_transport,--,"{true, false}",Add option for transporting solid biomass between nodes +biogas_upgrading_cc,--,"{true, false}",Add option to capture CO2 from biomass upgrading +conventional_generation,,,Add a more detailed description of conventional carriers. Any power generation requires the consumption of fuel from nodes representing that fuel. +biomass_to_liquid,--,"{true, false}",Add option for transforming solid biomass into liquid fuel with the same properties as oil +biosng,--,"{true, false}",Add option for transforming solid biomass into synthesis gas with the same properties as natural gas +limit_max_growth,,, +-- enable,--,"{true, false}",Add option to limit the maximum growth of a carrier +-- factor,p.u.,float,The maximum growth factor of a carrier (e.g. 1.3 allows 30% larger than max historic growth) +-- max_growth,,, +-- -- {carrier},GW,float,The historic maximum growth of a carrier +-- max_relative_growth,,, +-- -- {carrier},p.u.,float,The historic maximum relative growth of a carrier diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 28bb03b7..81c7ea14 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,7 +10,7 @@ Release Notes Upcoming Release ================ -* correct estimation of CO2 sequestration potential to including hydrocarbon fields (gas + oil) or saline aquifers +* Include gas and oil fields and saline aquifers in estimation of CO2 sequestration potential. * bugfix: convert Strings to pathlib.Path objects as input to ConfigSettings diff --git a/scripts/build_sequestration_potentials.py b/scripts/build_sequestration_potentials.py index 3defe07a..0d70448d 100644 --- a/scripts/build_sequestration_potentials.py +++ b/scripts/build_sequestration_potentials.py @@ -23,6 +23,8 @@ def area(gdf): def allocate_sequestration_potential( gdf, regions, attr="conservative estimate Mt", threshold=3 ): + if isinstance(attr, str): + attr = [attr] gdf = gdf.loc[gdf[attr].sum(axis=1) > threshold, attr + ["geometry"]] gdf["area_sqkm"] = area(gdf) overlay = gpd.overlay(regions, gdf, keep_geom_type=True) From f3ad1a36c7a12ca70b5974e11921e801cf17fdf9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:14:25 +0000 Subject: [PATCH 520/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- 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 0fc99a8d..a28dbd36 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -515,7 +515,7 @@ sector: regional_coal_demand: false regional_co2_sequestration_potential: enable: false - attribute: + attribute: - conservative estimate Mt - conservative estimate GAS Mt - conservative estimate OIL Mt From 0ae016a7d0a236e6c25ddd0044d4b02e623af7b7 Mon Sep 17 00:00:00 2001 From: cpschau Date: Wed, 10 Apr 2024 17:10:56 +0200 Subject: [PATCH 521/591] write shapes to base network --- scripts/base_network.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/base_network.py b/scripts/base_network.py index 346f99a5..f78f4b04 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -697,6 +697,14 @@ def _adjust_capacities_of_under_construction_branches(n, config): return n +def _set_shapes(n, country_shapes, offshore_shapes): + # Write the geodataframes country_shapes and offshore_shapes to the network.shapes component + country_shapes = gpd.read_file(country_shapes).rename(columns={"name": "idx"}) + country_shapes["type"] = "country" + offshore_shapes = gpd.read_file(offshore_shapes).rename(columns={"name": "idx"}) + offshore_shapes["type"] = "offshore" + all_shapes = pd.concat([country_shapes, offshore_shapes]) + n.shapes = pd.concat([n.shapes, all_shapes]) def base_network( eg_buses, @@ -758,12 +766,16 @@ def base_network( n = _adjust_capacities_of_under_construction_branches(n, config) + _set_shapes(n, country_shapes, offshore_shapes) + return n if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake + import os + os.chdir(os.path.dirname(os.path.abspath(__file__))) snakemake = mock_snakemake("base_network") configure_logging(snakemake) From c19b8d760ec19830e75dd2e3999acdbe17ca2866 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 10 Apr 2024 17:47:29 +0200 Subject: [PATCH 522/591] build_bus_regions: add shapes to network --- scripts/build_bus_regions.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/scripts/build_bus_regions.py b/scripts/build_bus_regions.py index 9d993c17..816c7fad 100644 --- a/scripts/build_bus_regions.py +++ b/scripts/build_bus_regions.py @@ -173,12 +173,31 @@ if __name__ == "__main__": offshore_regions_c = offshore_regions_c.loc[offshore_regions_c.area > 1e-2] offshore_regions.append(offshore_regions_c) - pd.concat(onshore_regions, ignore_index=True).to_file( - snakemake.output.regions_onshore + gdf = pd.concat(onshore_regions, ignore_index=True) + gdf.to_file(snakemake.output.regions_onshore) + + index = gdf.index.astype(int) + n.shapes.index.astype(int).max() + 1 + n.madd( + "Shape", + index, + geometry=gdf.geometry, + idx=index, + component="Bus", + type="onshore", ) if offshore_regions: - pd.concat(offshore_regions, ignore_index=True).to_file( - snakemake.output.regions_offshore + gdf = pd.concat(offshore_regions, ignore_index=True) + gdf.to_file(snakemake.output.regions_offshore) + + index = gdf.index.astype(int) + n.shapes.index.astype(int).max() + 1 + n.madd( + "Shape", + index, + geometry=gdf.geometry, + idx=index, + component="Bus", + type="offshore", ) + else: offshore_shapes.to_frame().to_file(snakemake.output.regions_offshore) From 7d0b775ca9c84ead87cafc547dca5b2d28f6c824 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:48:44 +0000 Subject: [PATCH 523/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/base_network.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index f78f4b04..77d3d250 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -697,6 +697,7 @@ def _adjust_capacities_of_under_construction_branches(n, config): return n + def _set_shapes(n, country_shapes, offshore_shapes): # Write the geodataframes country_shapes and offshore_shapes to the network.shapes component country_shapes = gpd.read_file(country_shapes).rename(columns={"name": "idx"}) @@ -704,7 +705,8 @@ def _set_shapes(n, country_shapes, offshore_shapes): offshore_shapes = gpd.read_file(offshore_shapes).rename(columns={"name": "idx"}) offshore_shapes["type"] = "offshore" all_shapes = pd.concat([country_shapes, offshore_shapes]) - n.shapes = pd.concat([n.shapes, all_shapes]) + n.shapes = pd.concat([n.shapes, all_shapes]) + def base_network( eg_buses, @@ -773,8 +775,10 @@ def base_network( if __name__ == "__main__": if "snakemake" not in globals(): - from _helpers import mock_snakemake import os + + from _helpers import mock_snakemake + os.chdir(os.path.dirname(os.path.abspath(__file__))) snakemake = mock_snakemake("base_network") From 9686407756684b064f27f77b75d06e4d3149142e Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 10 Apr 2024 17:58:08 +0200 Subject: [PATCH 524/591] cluster_network: add regions to n.shapes --- scripts/cluster_network.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index b0b73ade..a2473beb 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -428,16 +428,31 @@ def clustering_for_n_clusters( return clustering -def cluster_regions(busmaps, input=None, output=None): +def cluster_regions(busmaps, which, input=None, output=None): busmap = reduce(lambda x, y: x.map(y), busmaps[1:], busmaps[0]) - for which in ("regions_onshore", "regions_offshore"): - regions = gpd.read_file(getattr(input, which)) - regions = regions.reindex(columns=["name", "geometry"]).set_index("name") - regions_c = regions.dissolve(busmap) - regions_c.index.name = "name" - regions_c = regions_c.reset_index() - regions_c.to_file(getattr(output, which)) + regions = gpd.read_file(getattr(input, which)) + regions = regions.reindex(columns=["name", "geometry"]).set_index("name") + regions_c = regions.dissolve(busmap) + regions_c.index.name = "name" + regions_c = regions_c.reset_index() + regions_c.to_file(getattr(output, which)) + + # remove old regions + remove = n.shapes.query("component == 'Bus' and type == @which").index + n.mremove("Shape", remove) + + # add new clustered regions + index = regions_c.index.astype(int) + n.shapes.index.astype(int).max() + 1 + type = which.split("_")[1] + n.madd( + "Shape", + index, + geometry=regions_c.geometry, + idx=index, + component="Bus", + type="which", + ) def plot_busmap_for_n_clusters(n, n_clusters, fn=None): @@ -555,4 +570,5 @@ if __name__ == "__main__": ): # also available: linemap_positive, linemap_negative getattr(clustering, attr).to_csv(snakemake.output[attr]) - cluster_regions((clustering.busmap,), snakemake.input, snakemake.output) + for which in ["regions_onshore", "regions_offshore"]: + cluster_regions((clustering.busmap,), which, snakemake.input, snakemake.output) From 47134a88d833e2db1c1a6d95fd070ab208d5d5d6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 10 Apr 2024 18:13:14 +0200 Subject: [PATCH 525/591] regions to n.shapes: smooth out remaining issues --- scripts/base_network.py | 2 +- scripts/build_bus_regions.py | 7 +++++-- scripts/cluster_network.py | 3 ++- scripts/simplify_network.py | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index 77d3d250..528f04bf 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -705,7 +705,7 @@ def _set_shapes(n, country_shapes, offshore_shapes): offshore_shapes = gpd.read_file(offshore_shapes).rename(columns={"name": "idx"}) offshore_shapes["type"] = "offshore" all_shapes = pd.concat([country_shapes, offshore_shapes]) - n.shapes = pd.concat([n.shapes, all_shapes]) + n.shapes = pd.concat([n.shapes, all_shapes], ignore_index=True) def base_network( diff --git a/scripts/build_bus_regions.py b/scripts/build_bus_regions.py index 816c7fad..d26e6ba6 100644 --- a/scripts/build_bus_regions.py +++ b/scripts/build_bus_regions.py @@ -176,7 +176,8 @@ if __name__ == "__main__": gdf = pd.concat(onshore_regions, ignore_index=True) gdf.to_file(snakemake.output.regions_onshore) - index = gdf.index.astype(int) + n.shapes.index.astype(int).max() + 1 + offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 + index = gdf.index.astype(int) + offset n.madd( "Shape", index, @@ -185,11 +186,13 @@ if __name__ == "__main__": component="Bus", type="onshore", ) + if offshore_regions: gdf = pd.concat(offshore_regions, ignore_index=True) gdf.to_file(snakemake.output.regions_offshore) - index = gdf.index.astype(int) + n.shapes.index.astype(int).max() + 1 + offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 + index = gdf.index.astype(int) + offset n.madd( "Shape", index, diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index a2473beb..7a497626 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -443,7 +443,8 @@ def cluster_regions(busmaps, which, input=None, output=None): n.mremove("Shape", remove) # add new clustered regions - index = regions_c.index.astype(int) + n.shapes.index.astype(int).max() + 1 + offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 + index = regions_c.index.astype(int) + offset type = which.split("_")[1] n.madd( "Shape", diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 24df7312..6e404192 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -629,4 +629,5 @@ if __name__ == "__main__": busmap_s = reduce(lambda x, y: x.map(y), busmaps[1:], busmaps[0]) busmap_s.to_csv(snakemake.output.busmap) - cluster_regions(busmaps, snakemake.input, snakemake.output) + for which in ["regions_onshore", "regions_offshore"]: + cluster_regions(busmaps, which, snakemake.input, snakemake.output) From 84de226cb01a59945ab3505ad20fce62a492fa79 Mon Sep 17 00:00:00 2001 From: chrstphtrs Date: Thu, 11 Apr 2024 09:43:46 +0200 Subject: [PATCH 526/591] Add documentation section for how to contribute documentation --- doc/contributing.rst | 13 +++++++++++++ doc/release_notes.rst | 2 ++ 2 files changed, 15 insertions(+) diff --git a/doc/contributing.rst b/doc/contributing.rst index 0bf969b6..2d025382 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -35,3 +35,16 @@ including our own are reviewed by a second person before they are incorporated i If you are unfamiliar with pull requests, the GitHub help pages have a nice `guide `_. To ask and answer general usage questions, join the `PyPSA mailing list `_. + +Contributing to the documentation +==================================== + +We strive to keep documentation useful and up to date for all PyPSA users. If you encounter an area where documentation is not available or insufficient, we very much welcome your contribution. Here is How To: + +#. Install the conda environment for documentation from the `PyPSA repository `_. + (Here is `how to install a conda environment `_.) +#. Make your changes in the corresponding .rst file under ``pypsa-eur/doc``. +#. Compile your changes by running the following command in your terminal in the ``doc`` folder: ``make html`` + You may encounter some warnings, but end up with a message such as ``build succeeded, XX warnings.``. html files to review your changes can then be found under ``doc/_build/html``. +#. Contribute your documentation in a pull request (`here is a guide `_). + \ No newline at end of file diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b782a6df..c5099943 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -176,6 +176,8 @@ Upcoming Release * Fix custom busmap read in `cluster_network`. +* Add documentation section for how to contribute documentation + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== From 73971199d2f6416f219281b1823ecf39784ebffd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 07:46:20 +0000 Subject: [PATCH 527/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/contributing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/contributing.rst b/doc/contributing.rst index 2d025382..52dc8280 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -47,4 +47,4 @@ We strive to keep documentation useful and up to date for all PyPSA users. If yo #. Compile your changes by running the following command in your terminal in the ``doc`` folder: ``make html`` You may encounter some warnings, but end up with a message such as ``build succeeded, XX warnings.``. html files to review your changes can then be found under ``doc/_build/html``. #. Contribute your documentation in a pull request (`here is a guide `_). - \ No newline at end of file + From 590d3635790222ddddefc388a59547b4db64d02c Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 11 Apr 2024 12:13:07 +0200 Subject: [PATCH 528/591] clustering: add docstring to cluster_regions function, fix network reference --- scripts/cluster_network.py | 35 ++++++++++++++++++++++++----------- scripts/simplify_network.py | 2 +- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 7a497626..a18a2079 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -428,7 +428,20 @@ def clustering_for_n_clusters( return clustering -def cluster_regions(busmaps, which, input=None, output=None): +def cluster_regions(n, busmaps, which, input=None, output=None): + """ + Cluster regions based on busmaps and save the results to a file and to the + network. + + Parameters: + - busmaps (list): A list of busmaps used for clustering. + - which (str): The type of regions to cluster. + - input (str, optional): The input file path. Defaults to None. + - output (str, optional): The output file path. Defaults to None. + + Returns: + None + """ busmap = reduce(lambda x, y: x.map(y), busmaps[1:], busmaps[0]) regions = gpd.read_file(getattr(input, which)) @@ -438,7 +451,7 @@ def cluster_regions(busmaps, which, input=None, output=None): regions_c = regions_c.reset_index() regions_c.to_file(getattr(output, which)) - # remove old regions + # remove original regions remove = n.shapes.query("component == 'Bus' and type == @which").index n.mremove("Shape", remove) @@ -456,8 +469,8 @@ def cluster_regions(busmaps, which, input=None, output=None): ) -def plot_busmap_for_n_clusters(n, n_clusters, fn=None): - busmap = busmap_for_n_clusters(n, n_clusters) +def plot_busmap_for_n_clusters(n, n_clusters, solver_name="scip", fn=None): + busmap = busmap_for_n_clusters(n, n_clusters, solver_name) cs = busmap.unique() cr = sns.color_palette("hls", len(cs)) n.plot(bus_colors=busmap.map(dict(zip(cs, cr)))) @@ -554,17 +567,15 @@ if __name__ == "__main__": params.focus_weights, ) - update_p_nom_max(clustering.network) + nc = clustering.network + update_p_nom_max(nc) if params.cluster_network.get("consider_efficiency_classes"): labels = [f" {label} efficiency" for label in ["low", "medium", "high"]] - nc = clustering.network nc.generators["carrier"] = nc.generators.carrier.replace(labels, "", regex=True) - clustering.network.meta = dict( - snakemake.config, **dict(wildcards=dict(snakemake.wildcards)) - ) - clustering.network.export_to_netcdf(snakemake.output.network) + nc.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) + nc.export_to_netcdf(snakemake.output.network) for attr in ( "busmap", "linemap", @@ -572,4 +583,6 @@ if __name__ == "__main__": getattr(clustering, attr).to_csv(snakemake.output[attr]) for which in ["regions_onshore", "regions_offshore"]: - cluster_regions((clustering.busmap,), which, snakemake.input, snakemake.output) + cluster_regions( + nc, (clustering.busmap,), which, snakemake.input, snakemake.output + ) diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 6e404192..7b8710a0 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -630,4 +630,4 @@ if __name__ == "__main__": busmap_s.to_csv(snakemake.output.busmap) for which in ["regions_onshore", "regions_offshore"]: - cluster_regions(busmaps, which, snakemake.input, snakemake.output) + cluster_regions(n, busmaps, which, snakemake.input, snakemake.output) From 859212b21ff83e35a414d6874e7abba6e492b947 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 11 Apr 2024 06:41:59 +0000 Subject: [PATCH 529/591] Use powerplantmatching IRENASTAT for add_existing_baseyear --- config/config.default.yaml | 1 - .../offwind_capacity_IRENA.csv | 34 ------ .../onwind_capacity_IRENA.csv | 34 ------ .../solar_capacity_IRENA.csv | 34 ------ doc/configtables/enable.csv | 1 - doc/retrieve.rst | 5 - rules/retrieve.smk | 18 --- rules/solve_myopic.smk | 3 - rules/solve_perfect.smk | 3 - scripts/add_existing_baseyear.py | 29 +++-- scripts/retrieve_irena.py | 108 ------------------ 11 files changed, 20 insertions(+), 250 deletions(-) delete mode 100644 data/existing_infrastructure/offwind_capacity_IRENA.csv delete mode 100644 data/existing_infrastructure/onwind_capacity_IRENA.csv delete mode 100644 data/existing_infrastructure/solar_capacity_IRENA.csv delete mode 100644 scripts/retrieve_irena.py diff --git a/config/config.default.yaml b/config/config.default.yaml index d438c51f..94c91186 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -72,7 +72,6 @@ enable: 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 diff --git a/data/existing_infrastructure/offwind_capacity_IRENA.csv b/data/existing_infrastructure/offwind_capacity_IRENA.csv deleted file mode 100644 index d2a3f0f1..00000000 --- a/data/existing_infrastructure/offwind_capacity_IRENA.csv +++ /dev/null @@ -1,34 +0,0 @@ -Country/area,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022 -Albania,,,,,,,,,,,,,,,,,,,,,,, -Austria,,,,,,,,,,,,,,,,,,,,,,, -Belgium,,,,,,,,,,31.5,196.5,196.5,381.0,707.7,707.7,712.0,712.2,877.2,1185.9,1555.5,2261.8,2261.8,2261.8 -Bosnia Herzg,,,,,,,,,,,,,,,,,,,,,,, -Bulgaria,,,,,,,,,,,,,,,,,,,,,,, -Croatia,,,,,,,,,,,,,,,,,,,,,,, -Czechia,,,,,,,,,,,,,,,,,,,,,,, -Denmark,49.95,49.95,213.95,423.35,423.35,423.35,423.35,423.35,423.35,660.85,867.85,871.45,921.85,1271.05,1271.05,1271.05,1271.05,1263.8,1700.8,1700.8,1700.8,2305.6,2305.6 -Estonia,,,,,,,,,,,,,,,,,,,,,,, -Finland,,,,,,,,,24.0,24.0,26.3,26.3,26.3,26.3,26.3,32.0,32.0,72.7,72.7,73.0,73.0,73.0,73.0 -France,,,,,,,,,,,,,,,,,,2.0,2.0,2.0,2.0,2.0,482.0 -Germany,,,,,,,,,,35.0,80.0,188.0,268.0,508.0,994.0,3283.0,4132.0,5406.0,6393.0,7555.0,7787.0,7787.0,8129.0 -Greece,,,,,,,,,,,,,,,,,,,,,,, -Hungary,,,,,,,,,,,,,,,,,,,,,,, -Ireland,,,,,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2,25.2 -Italy,,,,,,,,,,,,,,,,,,,,,,,30.0 -Latvia,,,,,,,,,,,,,,,,,,,,,,, -Lithuania,,,,,,,,,,,,,,,,,,,,,,, -Luxembourg,,,,,,,,,,,,,,,,,,,,,,, -Montenegro,,,,,,,,,,,,,,,,,,,,,,, -Netherlands,,,,,,,108.0,108.0,228.0,228.0,228.0,228.0,228.0,228.0,228.0,357.0,957.0,957.0,957.0,957.0,2459.5,2459.5,2571.0 -North Macedonia,,,,,,,,,,,,,,,,,,,,,,, -Norway,,,,,,,,,,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,6.3,66.3 -Poland,,,,,,,,,,,,,,,,,,,,,,, -Portugal,,,,,,,,,,,,1.86,2.0,2.0,2.0,2.0,,,,,25.0,25.0,25.0 -Romania,,,,,,,,,,,,,,,,,,,,,,, -Serbia,,,,,,,,,,,,,,,,,,,,,,, -Slovakia,,,,,,,,,,,,,,,,,,,,,,, -Slovenia,,,,,,,,,,,,,,,,,,,,,,, -Spain,,,,,,,,,,,,,,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0 -Sweden,13.0,22.0,22.0,22.0,22.0,22.0,22.0,131.0,133.0,163.0,163.0,163.0,163.0,212.0,213.0,213.0,203.0,203.0,203.0,203.0,203.0,193.0,193.0 -Switzerland,,,,,,,,,,,,,,,,,,,,,,, -UK,4.0,4.0,4.0,64.0,124.0,214.0,304.0,394.0,596.2,951.0,1341.0,1838.0,2995.0,3696.0,4501.0,5093.0,5293.0,6988.0,8181.0,9888.0,10383.0,11255.0,13928.0 diff --git a/data/existing_infrastructure/onwind_capacity_IRENA.csv b/data/existing_infrastructure/onwind_capacity_IRENA.csv deleted file mode 100644 index cd5ac19c..00000000 --- a/data/existing_infrastructure/onwind_capacity_IRENA.csv +++ /dev/null @@ -1,34 +0,0 @@ -Country/area,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022 -Albania,,,,,,,,,,,,,,,,,,,,,,, -Austria,50.0,67.0,109.0,322.0,581.0,825.22,968.27,991.16,991.97,1000.99,1015.83,1105.97,1337.15,1674.54,2110.28,2488.73,2730.0,2886.7,3132.71,3224.12,3225.98,3407.81,3735.81 -Belgium,14.0,26.0,31.0,67.0,96.0,167.0,212.0,276.0,324.0,576.5,715.5,872.5,985.9,1061.3,1225.0,1469.3,1621.6,1902.2,2119.0,2308.0,2410.9,2686.6,2989.6 -Bosnia Herzg,,,,,,,,,,,,0.3,0.3,0.3,0.3,0.3,0.3,0.3,51.0,87.0,87.0,135.0,135.0 -Bulgaria,,,,,1.0,8.0,27.0,30.0,114.0,333.0,488.0,541.0,677.0,683.0,699.0,699.0,699.0,698.39,698.92,703.12,702.8,704.38,704.38 -Croatia,,,,,6.0,6.0,17.0,17.0,17.0,70.0,79.0,130.0,180.0,254.0,339.0,418.0,483.0,576.1,586.3,646.3,801.3,986.9,1042.9 -Czechia,2.0,,6.4,10.6,16.5,22.0,43.5,113.8,150.0,193.0,213.0,213.0,258.0,262.0,278.0,281.0,282.0,308.21,316.2,339.41,339.42,339.41,339.41 -Denmark,2340.07,2447.2,2680.58,2696.57,2700.36,2704.49,2712.35,2700.86,2739.52,2821.24,2933.98,3080.53,3240.09,3547.87,3615.35,3805.92,3974.09,4225.15,4421.86,4409.74,4566.23,4715.24,4782.24 -Estonia,,,1.0,3.0,7.0,31.0,31.0,50.0,77.0,104.0,108.0,180.0,266.0,248.0,275.0,300.0,310.0,311.8,310.0,316.0,317.0,315.0,315.0 -Finland,38.0,39.0,43.0,52.0,82.0,82.0,86.0,110.0,119.0,123.0,170.7,172.7,230.7,420.7,600.7,973.0,1533.0,1971.3,1968.3,2211.0,2513.0,3184.0,5541.0 -France,38.0,66.0,138.0,218.0,358.0,690.0,1412.0,2223.0,3403.0,4582.0,5912.0,6758.02,7607.5,8155.96,9201.42,10298.18,11566.56,13497.35,14898.14,16424.85,17512.0,18737.98,20637.98 -Germany,6095.0,8754.0,12001.0,14381.0,16419.0,18248.0,20474.0,22116.0,22794.0,25697.0,26823.0,28524.0,30711.0,32969.0,37620.0,41297.0,45303.0,50174.0,52328.0,53187.0,54414.0,56046.0,58165.0 -Greece,226.0,270.0,287.0,371.0,470.0,491.0,749.0,846.0,1022.0,1171.0,1298.0,1640.0,1753.0,1809.0,1978.0,2091.0,2370.0,2624.0,2877.5,3589.0,4119.25,4649.13,4879.13 -Hungary,,1.0,1.0,3.0,3.0,17.0,33.0,61.0,134.0,203.0,293.0,331.0,325.0,329.0,329.0,329.0,329.0,329.0,329.0,323.0,323.0,324.0,324.0 -Ireland,116.5,122.9,134.8,210.3,311.2,468.1,651.3,715.3,917.1,1226.1,1365.2,1559.4,1679.15,1898.1,2258.05,2425.95,2776.45,3293.95,3648.65,4101.25,4281.5,4313.84,4593.84 -Italy,363.0,664.0,780.0,874.0,1127.0,1635.0,1902.0,2702.0,3525.0,4879.0,5794.0,6918.0,8102.0,8542.0,8683.0,9137.0,9384.0,9736.58,10230.25,10679.46,10870.62,11253.73,11749.73 -Latvia,2.0,2.0,22.0,26.0,26.0,26.0,26.0,26.0,28.0,29.0,30.0,36.0,59.0,65.89,68.92,68.17,69.91,77.11,78.17,78.07,78.07,77.13,136.13 -Lithuania,,,,,1.0,1.0,31.0,47.0,54.0,98.0,133.0,202.0,275.0,279.0,288.0,436.0,509.0,518.0,533.0,534.0,540.0,671.0,814.0 -Luxembourg,14.0,13.9,13.9,20.5,34.9,34.9,34.9,34.9,42.92,42.93,43.73,44.53,58.33,58.33,58.34,63.79,119.69,119.69,122.89,135.79,152.74,136.44,165.44 -Montenegro,,,,,,,,,,,,,,,,,,72.0,72.0,118.0,118.0,118.0,118.0 -Netherlands,447.0,486.0,672.0,905.0,1075.0,1224.0,1453.0,1641.0,1921.0,1994.0,2009.0,2088.0,2205.0,2485.0,2637.0,3033.84,3300.12,3245.0,3436.11,3527.16,4188.38,5309.87,6176.0 -North Macedonia,,,,,,,,,,,,,,,37.0,37.0,37.0,37.0,37.0,37.0,37.0,37.0,37.0 -Norway,13.0,13.0,97.0,97.0,152.0,265.0,284.0,348.0,395.0,420.7,422.7,509.7,702.7,815.7,856.7,864.7,880.7,1204.7,1707.7,2911.7,4027.7,5042.7,5067.7 -Poland,4.0,19.0,32.0,35.0,40.0,121.0,172.0,306.0,526.0,709.0,1108.0,1800.0,2564.0,3429.0,3836.0,4886.0,5747.0,5759.36,5766.08,5837.76,6298.25,6967.34,7987.34 -Portugal,83.0,125.0,190.0,268.0,553.0,1064.0,1681.0,2201.0,2857.0,3326.0,3796.0,4254.35,4409.55,4607.95,4854.56,4934.84,5124.1,5124.1,5172.36,5222.75,5097.26,5402.33,5430.33 -Romania,,,,,,1.0,1.0,3.0,5.0,15.0,389.0,988.0,1822.0,2773.0,3244.0,3130.0,3025.0,3029.8,3032.26,3037.52,3012.53,3014.96,3014.96 -Serbia,,,,,,,,,,,,,0.5,0.5,0.5,10.4,17.0,25.0,227.0,398.0,398.0,398.0,398.0 -Slovakia,,,,3.0,3.0,5.0,5.0,5.0,5.0,3.0,3.0,3.0,3.0,5.0,3.0,3.0,3.0,4.0,3.0,4.0,4.0,4.0,4.0 -Slovenia,,,,,,,,,,,,,2.0,2.0,3.0,3.0,3.0,3.3,3.3,3.3,3.3,3.33,3.33 -Spain,2206.0,3397.0,4891.0,5945.0,8317.0,9918.0,11722.0,14820.0,16555.0,19176.0,20693.0,21529.0,22789.0,22953.0,22920.0,22938.0,22985.0,23119.48,23400.06,25585.08,26814.19,27902.65,29302.84 -Sweden,196.0,273.0,335.0,395.0,453.0,500.0,563.0,692.0,956.0,1312.0,1854.0,2601.0,3443.0,3982.0,4875.0,5606.0,6232.0,6408.0,7097.0,8478.0,9773.0,11923.0,14364.0 -Switzerland,3.0,5.0,5.0,5.0,9.0,12.0,12.0,12.0,14.0,18.0,42.0,46.0,49.0,60.0,60.0,60.0,75.0,75.0,75.0,75.0,87.0,87.0,87.0 -UK,431.0,490.0,531.0,678.0,809.0,1351.0,1651.0,2083.0,2849.8,3468.0,4080.0,4758.0,6035.0,7586.0,8573.0,9212.0,10833.0,12597.0,13425.0,13999.0,14075.0,14492.0,14832.0 diff --git a/data/existing_infrastructure/solar_capacity_IRENA.csv b/data/existing_infrastructure/solar_capacity_IRENA.csv deleted file mode 100644 index 01683f8d..00000000 --- a/data/existing_infrastructure/solar_capacity_IRENA.csv +++ /dev/null @@ -1,34 +0,0 @@ -Country/area,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022 -Albania,,0.1,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.3,0.4,0.56,0.68,0.76,0.87,1.05,1.0,1.0,1.0,14.0,21.0,23.0,28.6 -Austria,5.0,7.0,9.0,23.0,27.0,18.49,19.61,21.42,27.0,45.56,85.27,169.88,333.09,620.78,779.76,931.56,1089.53,1262.01,1447.94,1694.4,2034.74,2773.91,3538.91 -Belgium,,,1.0,1.0,1.0,2.0,2.0,20.0,62.0,386.0,1006.6,1978.6,2646.6,2901.6,3015.0,3131.6,3328.8,3620.6,4000.0,4636.6,5572.8,6012.4,6898.4 -Bosnia Herzg,,,,0.1,0.2,0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.35,1.34,7.17,8.17,14.12,16.0,18.15,22.35,34.89,56.51,107.47 -Bulgaria,,,,,,,,0.03,0.1,2.0,25.0,154.0,921.99,1038.54,1028.92,1027.89,1029.89,1030.7,1033.06,1044.39,1100.21,1274.71,1948.36 -Croatia,,,,,,,,,,0.3,0.3,0.3,4.0,19.0,33.0,47.8,55.8,60.0,67.7,84.8,108.5,138.3,182.3 -Czechia,0.1,0.1,0.2,0.3,0.4,0.59,0.84,3.96,39.5,464.6,1727.0,1913.0,2022.0,2063.5,2067.4,2074.9,2067.9,2075.44,2081.05,2110.67,2171.96,2246.09,2627.09 -Denmark,1.0,1.0,2.0,2.0,2.0,3.0,3.0,3.0,3.0,5.0,7.0,17.0,402.0,571.0,607.0,782.11,850.95,906.35,998.0,1080.0,1304.29,1704.04,3122.04 -Estonia,,,,,,,,,,0.1,0.1,0.2,0.38,1.5,3.34,6.5,10.0,15.0,31.9,120.6,207.67,394.77,534.77 -Finland,2.0,3.0,3.0,3.0,4.0,4.0,5.0,5.0,6.0,6.0,7.0,7.0,8.0,9.0,11.0,17.0,39.0,82.0,140.0,222.0,318.0,425.0,590.6 -France,7.0,7.0,8.0,9.0,11.0,13.0,15.0,26.0,80.0,277.0,1044.0,3003.57,4358.75,5277.29,6034.42,7137.52,7702.08,8610.44,9638.88,10738.39,11812.2,14436.97,17036.97 -Germany,114.0,195.0,260.0,435.0,1105.0,2056.0,2899.0,4170.0,6120.0,10564.0,18004.0,25914.0,34075.0,36708.0,37898.0,39222.0,40677.0,42291.0,45156.0,48912.0,53669.0,59371.0,66662.0 -Greece,,1.0,1.0,1.0,1.0,1.0,5.0,9.0,12.0,46.0,202.0,612.0,1536.0,2579.0,2596.0,2604.0,2604.0,2605.53,2651.57,2833.79,3287.72,4277.42,5557.42 -Hungary,,,,,,,,0.4,1.0,1.0,2.0,4.0,12.0,35.0,89.0,172.0,235.0,344.0,728.0,1400.0,2131.0,2968.0,2988.0 -Ireland,,,,,,,,,,,,,,,,,,,,,,, -Italy,19.0,20.0,22.0,26.0,31.0,34.0,45.0,110.0,483.0,1264.0,3592.0,13131.0,16785.0,18185.0,18594.0,18901.0,19283.0,19682.29,20107.59,20865.28,21650.04,22594.26,25076.56 -Latvia,,,,,,,,,,,,,,,,,0.69,0.69,1.96,3.3,5.1,7.16,56.16 -Lithuania,,,,,,,,,0.1,0.1,0.1,0.3,7.0,68.0,69.0,69.0,70.0,70.08,72.0,73.0,80.0,84.0,397.0 -Luxembourg,,0.16,1.59,14.17,23.56,23.58,23.7,23.93,24.56,26.36,29.45,40.67,74.65,95.02,109.93,116.27,121.9,128.1,130.62,159.74,186.64,277.16,319.16 -Montenegro,,,,,,,,,,,,,,,,,,,,,2.57,2.57,22.2 -Netherlands,13.0,21.0,26.0,46.0,50.0,51.0,53.0,54.0,59.0,69.0,90.0,149.0,287.0,650.0,1007.0,1526.26,2135.02,2910.89,4608.0,7226.0,11108.43,14910.69,18848.69 -North Macedonia,,,,,,,,,,,,2.0,4.0,7.0,15.0,17.0,16.7,16.7,16.7,16.71,84.93,84.93,84.93 -Norway,6.0,6.0,6.0,7.0,7.0,7.0,8.0,8.0,8.3,8.7,9.1,9.5,10.0,11.0,13.0,15.0,26.7,44.9,53.11,102.53,141.53,186.53,302.53 -Poland,,,,,,,,,,,,1.11,1.3,2.39,27.15,107.78,187.25,287.09,561.98,1539.26,3954.96,7415.52,11166.52 -Portugal,1.0,1.0,1.0,2.0,2.0,2.0,3.0,24.0,59.0,115.0,134.0,169.6,235.6,293.6,412.6,441.75,493.05,539.42,617.85,832.74,1010.07,1474.78,2364.78 -Romania,,,,,,,,,0.1,0.1,0.1,1.0,41.0,761.0,1293.0,1326.0,1372.0,1374.13,1385.82,1397.71,1382.54,1393.92,1413.92 -Serbia,,,,,,0.1,0.2,0.4,0.9,1.2,1.3,1.5,3.1,4.7,6.0,9.0,11.0,10.0,11.0,11.0,11.5,11.94,11.94 -Slovakia,,,,,,,,,,,19.0,496.0,513.0,533.0,533.0,533.0,533.0,528.0,472.0,590.0,535.0,537.0,537.0 -Slovenia,1.0,1.0,,,,0.05,0.19,0.59,1.0,4.0,12.0,57.0,142.0,187.0,223.0,238.0,233.0,246.8,246.8,277.88,369.78,461.16,632.16 -Spain,1.0,3.0,6.0,10.0,19.0,37.0,113.0,476.0,3365.0,3403.0,3851.0,4260.0,4545.0,4665.0,4672.0,4677.0,4687.0,4696.0,4730.7,8772.02,10100.42,13678.4,18176.73 -Sweden,3.0,3.0,3.0,4.0,4.0,4.0,5.0,6.0,8.0,9.0,11.0,12.0,24.0,43.0,60.0,104.0,153.0,231.0,411.0,698.0,1090.0,1587.0,2587.0 -Switzerland,16.0,18.0,20.0,22.0,24.0,28.0,30.0,37.0,49.0,79.0,125.0,223.0,437.0,756.0,1061.0,1394.0,1664.0,1906.0,2173.0,2498.0,2973.0,3655.0,4339.92 -UK,2.0,3.0,4.0,6.0,8.0,11.0,14.0,18.0,23.0,27.0,95.0,1000.0,1753.0,2937.0,5528.0,9601.0,11914.0,12760.0,13059.0,13345.0,13579.0,13965.0,14660.0 diff --git a/doc/configtables/enable.csv b/doc/configtables/enable.csv index 1e5571b3..06397fdf 100644 --- a/doc/configtables/enable.csv +++ b/doc/configtables/enable.csv @@ -5,7 +5,6 @@ retrieve_databundle,bool,"{true, false}","Switch to retrieve databundle from zen retrieve_sector_databundle,bool,"{true, false}","Switch to retrieve sector databundle from zenodo via the rule :mod:`retrieve_sector_databundle` or whether to keep a custom databundle located in the corresponding folder." retrieve_cost_data,bool,"{true, false}","Switch to retrieve technology cost data from `technology-data repository `_." build_cutout,bool,"{true, false}","Switch to enable the building of cutouts via the rule :mod:`build_cutout`." -retrieve_irena,bool,"{true, false}",Switch to enable the retrieval of ``existing_capacities`` from IRENASTAT with :mod:`retrieve_irena`. retrieve_cutout,bool,"{true, false}","Switch to enable the retrieval of cutouts from zenodo with :mod:`retrieve_cutout`." build_natura_raster,bool,"{true, false}","Switch to enable the creation of the raster ``natura.tiff`` via the rule :mod:`build_natura_raster`." retrieve_natura_raster,bool,"{true, false}","Switch to enable the retrieval of ``natura.tiff`` from zenodo with :mod:`retrieve_natura_raster`." diff --git a/doc/retrieve.rst b/doc/retrieve.rst index f9d6e2a7..36163eae 100644 --- a/doc/retrieve.rst +++ b/doc/retrieve.rst @@ -118,11 +118,6 @@ This rule downloads techno-economic assumptions from the `technology-data reposi - ``resources/costs.csv`` -Rule ``retrieve_irena`` -================================ - -.. automodule:: retrieve_irena - Rule ``retrieve_ship_raster`` ================================ diff --git a/rules/retrieve.smk b/rules/retrieve.smk index 4b244483..d0345f36 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -42,24 +42,6 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_databundle", "../scripts/retrieve_databundle.py" -if config["enable"].get("retrieve_irena"): - - rule retrieve_irena: - output: - offwind="data/existing_infrastructure/offwind_capacity_IRENA.csv", - onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", - solar="data/existing_infrastructure/solar_capacity_IRENA.csv", - log: - "logs/retrieve_irena.log", - resources: - mem_mb=1000, - retries: 2 - conda: - "../envs/retrieve.yaml" - script: - "../scripts/retrieve_irena.py" - - if config["enable"]["retrieve"] and config["enable"].get("retrieve_cutout", True): rule retrieve_cutout: diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index fe291c6d..6220af2a 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -26,9 +26,6 @@ rule add_existing_baseyear: existing_heating_distribution=resources( "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), - existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", - existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", - existing_offwind="data/existing_infrastructure/offwind_capacity_IRENA.csv", output: RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index 70acc830..51cb3920 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -25,9 +25,6 @@ rule add_existing_baseyear: "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), existing_heating="data/existing_infrastructure/existing_heating_raw.csv", - existing_solar="data/existing_infrastructure/solar_capacity_IRENA.csv", - existing_onwind="data/existing_infrastructure/onwind_capacity_IRENA.csv", - existing_offwind="data/existing_infrastructure/offwind_capacity_IRENA.csv", output: RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index f445efe3..19eea8a5 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -13,6 +13,7 @@ from types import SimpleNamespace import country_converter as coco import numpy as np import pandas as pd +import powerplantmatching as pm import pypsa import xarray as xr from _helpers import ( @@ -60,14 +61,22 @@ def add_existing_renewables(df_agg, costs): Append existing renewables to the df_agg pd.DataFrame with the conventional power plants. """ - carriers = {"solar": "solar", "onwind": "onwind", "offwind": "offwind-ac"} + tech_map = {"solar": "PV", "onwind": "Onshore", "offwind": "Offshore"} - for tech in ["solar", "onwind", "offwind"]: - carrier = carriers[tech] + countries = snakemake.config["countries"] + irena = pm.data.IRENASTAT().powerplant.convert_country_to_alpha2() + irena = irena.query("Country in @countries") + irena = irena.groupby(["Technology", "Country", "Year"]).Capacity.sum() - df = pd.read_csv(snakemake.input[f"existing_{tech}"], index_col=0).fillna(0.0) + irena = irena.unstack().reset_index() + + for carrier, tech in tech_map.items(): + df = ( + irena[irena.Technology.str.contains(tech)] + .drop(columns=["Technology"]) + .set_index("Country") + ) df.columns = df.columns.astype(int) - df.index = cc.convert(df.index, to="iso2") # calculate yearly differences df.insert(loc=0, value=0.0, column="1999") @@ -97,14 +106,16 @@ def add_existing_renewables(df_agg, costs): for year in nodal_df.columns: for node in nodal_df.index: - name = f"{node}-{tech}-{year}" + name = f"{node}-{carrier}-{year}" capacity = nodal_df.loc[node, year] if capacity > 0.0: - df_agg.at[name, "Fueltype"] = tech + df_agg.at[name, "Fueltype"] = carrier df_agg.at[name, "Capacity"] = capacity df_agg.at[name, "DateIn"] = year - df_agg.at[name, "lifetime"] = costs.at[tech, "lifetime"] - df_agg.at[name, "DateOut"] = year + costs.at[tech, "lifetime"] - 1 + df_agg.at[name, "lifetime"] = costs.at[carrier, "lifetime"] + df_agg.at[name, "DateOut"] = ( + year + costs.at[carrier, "lifetime"] - 1 + ) df_agg.at[name, "cluster_bus"] = node diff --git a/scripts/retrieve_irena.py b/scripts/retrieve_irena.py deleted file mode 100644 index 04e48db1..00000000 --- a/scripts/retrieve_irena.py +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2023 Thomas Gilon (Climact) -# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT -""" -This rule downloads the existing capacities from `IRENASTAT `_ and extracts it in the ``data/existing_capacities`` sub-directory. - -**Relevant Settings** - -.. code:: yaml - - enable: - retrieve_irena: - -.. seealso:: - Documentation of the configuration file ``config.yaml`` at - :ref:`enable_cf` - -**Outputs** - -- ``data/existing_capacities``: existing capacities for offwind, onwind and solar - -""" - -import logging - -import pandas as pd -from _helpers import configure_logging, set_scenario_config - -logger = logging.getLogger(__name__) - -REGIONS = [ - "Albania", - "Austria", - "Belgium", - "Bosnia and Herzegovina", - "Bulgaria", - "Croatia", - "Czechia", - "Denmark", - "Estonia", - "Finland", - "France", - "Germany", - "Greece", - "Hungary", - "Ireland", - "Italy", - "Latvia", - "Lithuania", - "Luxembourg", - "Montenegro", - # "Netherlands", - "Netherlands (Kingdom of the)", - "North Macedonia", - "Norway", - "Poland", - "Portugal", - "Romania", - "Serbia", - "Slovakia", - "Slovenia", - "Spain", - "Sweden", - "Switzerland", - # "United Kingdom", - "United Kingdom of Great Britain and Northern Ireland (the)", -] - -REGIONS_DICT = { - "Bosnia and Herzegovina": "Bosnia Herzg", - "Netherlands (Kingdom of the)": "Netherlands", - "United Kingdom of Great Britain and Northern Ireland (the)": "UK", -} - -if __name__ == "__main__": - if "snakemake" not in globals(): - from _helpers import mock_snakemake - - snakemake = mock_snakemake("retrieve_irena") - configure_logging(snakemake) - set_scenario_config(snakemake) - - irena_raw = pd.read_csv( - "https://pxweb.irena.org:443/sq/99e64b12-fe03-4a7b-92ea-a22cc3713b92", - skiprows=2, - index_col=[0, 1, 3], - encoding="latin-1", - ) - - var = "Installed electricity capacity (MW)" - irena = irena_raw[var].unstack(level=2).reset_index(level=1).replace(0, "") - - irena = irena[irena.index.isin(REGIONS)] - irena.rename(index=REGIONS_DICT, inplace=True) - - df_offwind = irena[irena.Technology.str.contains("Offshore")].drop( - columns=["Technology"] - ) - df_onwind = irena[irena.Technology.str.contains("Onshore")].drop( - columns=["Technology"] - ) - df_pv = irena[irena.Technology.str.contains("Solar")].drop(columns=["Technology"]) - - df_offwind.to_csv(snakemake.output["offwind"]) - df_onwind.to_csv(snakemake.output["onwind"]) - df_pv.to_csv(snakemake.output["solar"]) From 219847012d381c73c1479bf021cb36d05f797cc0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 11 Apr 2024 12:56:49 +0200 Subject: [PATCH 530/591] build_bus_regions: fix shapes index for correct alignment in madd cluster_regions: further modularize functions, fix index alignment --- scripts/build_bus_regions.py | 24 +++++++++--------- scripts/cluster_network.py | 48 +++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/scripts/build_bus_regions.py b/scripts/build_bus_regions.py index d26e6ba6..d0225797 100644 --- a/scripts/build_bus_regions.py +++ b/scripts/build_bus_regions.py @@ -173,31 +173,31 @@ if __name__ == "__main__": offshore_regions_c = offshore_regions_c.loc[offshore_regions_c.area > 1e-2] offshore_regions.append(offshore_regions_c) - gdf = pd.concat(onshore_regions, ignore_index=True) - gdf.to_file(snakemake.output.regions_onshore) + shapes = pd.concat(onshore_regions, ignore_index=True) + shapes.to_file(snakemake.output.regions_onshore) offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 - index = gdf.index.astype(int) + offset + shapes.index = shapes.index.astype(int) + offset n.madd( "Shape", - index, - geometry=gdf.geometry, - idx=index, + shapes.index, + geometry=shapes.geometry, + idx=shapes.name, component="Bus", type="onshore", ) if offshore_regions: - gdf = pd.concat(offshore_regions, ignore_index=True) - gdf.to_file(snakemake.output.regions_offshore) + shapes = pd.concat(offshore_regions, ignore_index=True) + shapes.to_file(snakemake.output.regions_offshore) offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 - index = gdf.index.astype(int) + offset + shapes.index = shapes.index.astype(int) + offset n.madd( "Shape", - index, - geometry=gdf.geometry, - idx=index, + shapes.index, + geometry=shapes.geometry, + idx=shapes.name, component="Bus", type="offshore", ) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index a18a2079..9dd0226d 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -428,7 +428,7 @@ def clustering_for_n_clusters( return clustering -def cluster_regions(n, busmaps, which, input=None, output=None): +def cluster_regions(busmaps, regions): """ Cluster regions based on busmaps and save the results to a file and to the network. @@ -436,36 +436,41 @@ def cluster_regions(n, busmaps, which, input=None, output=None): Parameters: - busmaps (list): A list of busmaps used for clustering. - which (str): The type of regions to cluster. - - input (str, optional): The input file path. Defaults to None. - - output (str, optional): The output file path. Defaults to None. Returns: None """ busmap = reduce(lambda x, y: x.map(y), busmaps[1:], busmaps[0]) - - regions = gpd.read_file(getattr(input, which)) regions = regions.reindex(columns=["name", "geometry"]).set_index("name") regions_c = regions.dissolve(busmap) regions_c.index.name = "name" - regions_c = regions_c.reset_index() - regions_c.to_file(getattr(output, which)) + return regions_c.reset_index() - # remove original regions + +def append_bus_shapes(n, shapes, type): + """ + Append shapes to the network. + + Parameters: + n (pypsa.Network): The network to which the shapes will be appended. + shapes (geopandas.GeoDataFrame): The shapes to be appended. + **kwargs: Additional keyword arguments used in `n.madd`. + + Returns: + None + """ remove = n.shapes.query("component == 'Bus' and type == @which").index n.mremove("Shape", remove) - # add new clustered regions offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 - index = regions_c.index.astype(int) + offset - type = which.split("_")[1] + shapes.index = shapes.index.astype(int) + offset n.madd( "Shape", - index, - geometry=regions_c.geometry, - idx=index, + shapes.index, + geometry=shapes.geometry, + idx=shapes.name, component="Bus", - type="which", + type=type, ) @@ -574,15 +579,18 @@ if __name__ == "__main__": labels = [f" {label} efficiency" for label in ["low", "medium", "high"]] nc.generators["carrier"] = nc.generators.carrier.replace(labels, "", regex=True) - nc.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) - nc.export_to_netcdf(snakemake.output.network) for attr in ( "busmap", "linemap", ): # also available: linemap_positive, linemap_negative getattr(clustering, attr).to_csv(snakemake.output[attr]) + nc.shapes = n.shapes.copy() for which in ["regions_onshore", "regions_offshore"]: - cluster_regions( - nc, (clustering.busmap,), which, snakemake.input, snakemake.output - ) + regions = gpd.read_file(snakemake.input[which]) + clustered_regions = cluster_regions((clustering.busmap,), regions) + append_bus_shapes(nc, clustered_regions, type=which.split("_")[1]) + clustered_regions.to_file(snakemake.output[which]) + + nc.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) + nc.export_to_netcdf(snakemake.output.network) From 6d9728aed6218950373a496bdf6dbdc524bfb3be Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 11 Apr 2024 13:02:28 +0200 Subject: [PATCH 531/591] Add release note --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d42b149f..d7e154b7 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -181,6 +181,8 @@ Upcoming Release * Fix custom busmap read in `cluster_network`. +* Data on existing renewable capacities is now consistently taken from powerplantmatching (instead of being retrieved separately); the dataset has also been updated to include 2023 values. + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== From 6965ce31ccca19b88ded25b0102973b87b333b9f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:05:35 +0000 Subject: [PATCH 532/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/release_notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d7e154b7..b37d3c4d 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -181,7 +181,7 @@ Upcoming Release * Fix custom busmap read in `cluster_network`. -* Data on existing renewable capacities is now consistently taken from powerplantmatching (instead of being retrieved separately); the dataset has also been updated to include 2023 values. +* Data on existing renewable capacities is now consistently taken from powerplantmatching (instead of being retrieved separately); the dataset has also been updated to include 2023 values. PyPSA-Eur 0.10.0 (19th February 2024) ===================================== From f1b33992f7adc8941e668d61eb30dbf4e46d233d Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 11 Apr 2024 13:27:52 +0200 Subject: [PATCH 533/591] move append_bus_shapes to build_bus_regions, apply it where possible --- scripts/build_bus_regions.py | 58 ++++++++++++++++++++++-------------- scripts/cluster_network.py | 30 ++----------------- scripts/simplify_network.py | 15 +++++++--- 3 files changed, 48 insertions(+), 55 deletions(-) diff --git a/scripts/build_bus_regions.py b/scripts/build_bus_regions.py index d0225797..05a7729e 100644 --- a/scripts/build_bus_regions.py +++ b/scripts/build_bus_regions.py @@ -109,6 +109,34 @@ def voronoi_partition_pts(points, outline): return polygons +def append_bus_shapes(n, shapes, type): + """ + Append shapes to the network. If shapes with the same component and type + already exist, they will be removed. + + Parameters: + n (pypsa.Network): The network to which the shapes will be appended. + shapes (geopandas.GeoDataFrame): The shapes to be appended. + **kwargs: Additional keyword arguments used in `n.madd`. + + Returns: + None + """ + remove = n.shapes.query("component == 'Bus' and type == @type").index + n.mremove("Shape", remove) + + offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 + shapes = shapes.rename(lambda x: int(x) + offset) + n.madd( + "Shape", + shapes.index, + geometry=shapes.geometry, + idx=shapes.name, + component="Bus", + type=type, + ) + + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -119,7 +147,8 @@ if __name__ == "__main__": countries = snakemake.params.countries - n = pypsa.Network(snakemake.input.base_network) + base_network = snakemake.input.base_network + n = pypsa.Network(base_network) country_shapes = gpd.read_file(snakemake.input.country_shapes).set_index("name")[ "geometry" @@ -175,32 +204,15 @@ if __name__ == "__main__": shapes = pd.concat(onshore_regions, ignore_index=True) shapes.to_file(snakemake.output.regions_onshore) - - offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 - shapes.index = shapes.index.astype(int) + offset - n.madd( - "Shape", - shapes.index, - geometry=shapes.geometry, - idx=shapes.name, - component="Bus", - type="onshore", - ) + append_bus_shapes(n, shapes, "onshore") if offshore_regions: shapes = pd.concat(offshore_regions, ignore_index=True) shapes.to_file(snakemake.output.regions_offshore) - - offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 - shapes.index = shapes.index.astype(int) + offset - n.madd( - "Shape", - shapes.index, - geometry=shapes.geometry, - idx=shapes.name, - component="Bus", - type="offshore", - ) + append_bus_shapes(n, shapes, "offshore") else: offshore_shapes.to_frame().to_file(snakemake.output.regions_offshore) + + # save network with shapes + n.export_to_netcdf(base_network) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 9dd0226d..f58e5f8b 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -135,6 +135,7 @@ import pypsa import seaborn as sns from _helpers import configure_logging, set_scenario_config, update_p_nom_max from add_electricity import load_costs +from build_bus_regions import append_bus_shapes from packaging.version import Version, parse from pypsa.clustering.spatial import ( busmap_by_greedy_modularity, @@ -447,33 +448,6 @@ def cluster_regions(busmaps, regions): return regions_c.reset_index() -def append_bus_shapes(n, shapes, type): - """ - Append shapes to the network. - - Parameters: - n (pypsa.Network): The network to which the shapes will be appended. - shapes (geopandas.GeoDataFrame): The shapes to be appended. - **kwargs: Additional keyword arguments used in `n.madd`. - - Returns: - None - """ - remove = n.shapes.query("component == 'Bus' and type == @which").index - n.mremove("Shape", remove) - - offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 - shapes.index = shapes.index.astype(int) + offset - n.madd( - "Shape", - shapes.index, - geometry=shapes.geometry, - idx=shapes.name, - component="Bus", - type=type, - ) - - def plot_busmap_for_n_clusters(n, n_clusters, solver_name="scip", fn=None): busmap = busmap_for_n_clusters(n, n_clusters, solver_name) cs = busmap.unique() @@ -589,8 +563,8 @@ if __name__ == "__main__": for which in ["regions_onshore", "regions_offshore"]: regions = gpd.read_file(snakemake.input[which]) clustered_regions = cluster_regions((clustering.busmap,), regions) - append_bus_shapes(nc, clustered_regions, type=which.split("_")[1]) clustered_regions.to_file(snakemake.output[which]) + append_bus_shapes(nc, clustered_regions, type=which.split("_")[1]) nc.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) nc.export_to_netcdf(snakemake.output.network) diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 7b8710a0..f129945c 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -88,12 +88,14 @@ The rule :mod:`simplify_network` does up to four things: import logging from functools import reduce +import geopandas as gpd import numpy as np import pandas as pd import pypsa import scipy as sp from _helpers import configure_logging, set_scenario_config, update_p_nom_max from add_electricity import load_costs +from build_bus_regions import append_bus_shapes from cluster_network import cluster_regions, clustering_for_n_clusters from pypsa.clustering.spatial import ( aggregateoneport, @@ -610,6 +612,7 @@ if __name__ == "__main__": n.lines.drop(remove, axis=1, errors="ignore", inplace=True) if snakemake.wildcards.simpl: + shapes = n.shapes n, cluster_map = cluster( n, int(snakemake.wildcards.simpl), @@ -619,15 +622,19 @@ if __name__ == "__main__": params.simplify_network["feature"], params.aggregation_strategies, ) + n.shapes = shapes busmaps.append(cluster_map) update_p_nom_max(n) - n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) - n.export_to_netcdf(snakemake.output.network) - busmap_s = reduce(lambda x, y: x.map(y), busmaps[1:], busmaps[0]) busmap_s.to_csv(snakemake.output.busmap) for which in ["regions_onshore", "regions_offshore"]: - cluster_regions(n, busmaps, which, snakemake.input, snakemake.output) + regions = gpd.read_file(snakemake.input[which]) + clustered_regions = cluster_regions(busmaps, regions) + clustered_regions.to_file(snakemake.output[which]) + append_bus_shapes(n, clustered_regions, type=which.split("_")[1]) + + n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) + n.export_to_netcdf(snakemake.output.network) From 7c30a2835fbe0f8435ca38b38c45a155bc3554c8 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Thu, 14 Mar 2024 13:44:15 +0100 Subject: [PATCH 534/591] group existing capacities to the earlier grouping_year for consistency with optimized capacities --- config/config.default.yaml | 2 +- doc/release_notes.rst | 1 + scripts/add_existing_baseyear.py | 20 ++++++++++++-------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index d438c51f..0d40bafc 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -361,7 +361,7 @@ solar_thermal: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#existing-capacities existing_capacities: grouping_years_power: [1960, 1965, 1970, 1975, 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 + grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020] # heat grouping years >= baseyear will be ignored threshold_capacity: 10 default_heating_lifetime: 20 conventional_carriers: diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d42b149f..cdad3fa0 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,6 +9,7 @@ Release Notes Upcoming Release ================ +* Group existing capacities to the earlier grouping_year for consistency with optimized capacities * Include gas and oil fields and saline aquifers in estimation of CO2 sequestration potential. diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index f445efe3..75d83e38 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -190,8 +190,8 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas df_agg.drop(phased_out, inplace=True) df_agg["grouping_year"] = np.take( - grouping_years, np.digitize(df_agg.DateIn, grouping_years, right=True) - ) + grouping_years[::-1], + np.digitize(df_agg.DateIn, grouping_years[::-1])) # calculate (adjusted) remaining lifetime before phase-out (+1 because assuming # phase out date at the end of the year) @@ -444,12 +444,16 @@ def add_heating_capacities_installed_before_baseyear( else: efficiency = costs.at[costs_name, "efficiency"] - for i, grouping_year in enumerate(grouping_years): - if int(grouping_year) + default_lifetime <= int(baseyear): - continue - - # installation is assumed to be linear for the past default_lifetime years - ratio = (int(grouping_year) - int(grouping_years[i - 1])) / default_lifetime + valid_grouping_years = pd.Series( + [int(gy) for gy in grouping_years if + int(baseyear) - default_lifetime <= int(gy) < int(baseyear)]) + # Installation is assumed to be linear for the past + _intervals = pd.concat( + [valid_grouping_years[1:], pd.Series(baseyear)], + ignore_index=True) - valid_grouping_years + ratios = _intervals / _intervals.sum() + + for ratio, grouping_year in zip(ratios, valid_grouping_years): n.madd( "Link", From 700b0e912a31c14e67db0ff4cc504590d7242448 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Thu, 14 Mar 2024 16:13:40 +0100 Subject: [PATCH 535/591] add more grouping years to avoid errors --- 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 0d40bafc..42132f22 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -360,7 +360,7 @@ solar_thermal: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#existing-capacities existing_capacities: - grouping_years_power: [1960, 1965, 1970, 1975, 1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030] + grouping_years_power: [1895, 1920, 1950, 1955, 1960, 1965, 1970, 1975, 1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030] grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020] # heat grouping years >= baseyear will be ignored threshold_capacity: 10 default_heating_lifetime: 20 From 3a0e3563821b4f3cded77c28ce57f23223751e4c Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Thu, 11 Apr 2024 08:54:15 +0200 Subject: [PATCH 536/591] add check if minimum grouping year< min build year --- scripts/add_existing_baseyear.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 75d83e38..01870a26 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -189,6 +189,15 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas phased_out = df_agg[df_agg["DateOut"] < baseyear].index df_agg.drop(phased_out, inplace=True) + older_assets = (df_agg.DateIn Date: Thu, 11 Apr 2024 09:26:30 +0200 Subject: [PATCH 537/591] adjust valid_grouping_years change sign, split up conditions for better readibility --- scripts/add_existing_baseyear.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 01870a26..75375565 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -454,14 +454,22 @@ def add_heating_capacities_installed_before_baseyear( efficiency = costs.at[costs_name, "efficiency"] valid_grouping_years = pd.Series( - [int(gy) for gy in grouping_years if - int(baseyear) - default_lifetime <= int(gy) < int(baseyear)]) + [ + int(grouping_year) + for grouping_year in grouping_years + if int(grouping_year) + default_lifetime > int(baseyear) + and int(grouping_year) < int(baseyear) + ] + ) # Installation is assumed to be linear for the past - _intervals = pd.concat( - [valid_grouping_years[1:], pd.Series(baseyear)], - ignore_index=True) - valid_grouping_years + _intervals = ( + pd.concat( + [valid_grouping_years[1:], pd.Series(baseyear)], ignore_index=True + ) + - valid_grouping_years + ) ratios = _intervals / _intervals.sum() - + for ratio, grouping_year in zip(ratios, valid_grouping_years): n.madd( From 7773f7c84ebbbbdd8dd9bd5e3b2f8e1ed6edbc7d Mon Sep 17 00:00:00 2001 From: Micha Date: Thu, 11 Apr 2024 09:37:36 +0200 Subject: [PATCH 538/591] Add release note for serendipitous bugfix --- doc/release_notes.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index cdad3fa0..079648d5 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,7 +9,9 @@ Release Notes Upcoming Release ================ -* Group existing capacities to the earlier grouping_year for consistency with optimized capacities +* Group existing capacities to the earlier grouping_year for consistency with optimized capacities. + +* bugfix: installed heating capacities were 5% lower than existing heating capacities * Include gas and oil fields and saline aquifers in estimation of CO2 sequestration potential. From e9c9d08107967119539b3fa7202b3f670868d092 Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Thu, 11 Apr 2024 09:52:17 +0200 Subject: [PATCH 539/591] rename _intervals to _years, shorten definition --- scripts/add_existing_baseyear.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 75375565..d70afb48 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -461,14 +461,12 @@ def add_heating_capacities_installed_before_baseyear( and int(grouping_year) < int(baseyear) ] ) + + # get number of years of each interval + _years = (valid_grouping_years.diff().shift(-1) + .fillna(baseyear-valid_grouping_years.iloc[-1])) # Installation is assumed to be linear for the past - _intervals = ( - pd.concat( - [valid_grouping_years[1:], pd.Series(baseyear)], ignore_index=True - ) - - valid_grouping_years - ) - ratios = _intervals / _intervals.sum() + ratios = _years / _years.sum() for ratio, grouping_year in zip(ratios, valid_grouping_years): From a72388b989d1d667ec7e44d66f6c3b494b46d000 Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:54:33 +0200 Subject: [PATCH 540/591] define active assets consitently --- scripts/add_brownfield.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 7e49031b..16b4e087 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -40,8 +40,8 @@ def add_brownfield(n, n_p, year): # CO2 or global EU values since these are already in n n_p.mremove(c.name, c.df.index[c.df.lifetime == np.inf]) - # remove assets whose build_year + lifetime < year - n_p.mremove(c.name, c.df.index[c.df.build_year + c.df.lifetime < year]) + # remove assets whose build_year + lifetime <= year + n_p.mremove(c.name, c.df.index[c.df.build_year + c.df.lifetime <= year]) # remove assets if their optimized nominal capacity is lower than a threshold # since CHP heat Link is proportional to CHP electric Link, make sure threshold is compatible From f8b33e8eb28982b424e3637c96fa53f44bb2b8cb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 12:21:43 +0000 Subject: [PATCH 541/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/add_existing_baseyear.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index d70afb48..8a8a78a4 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -189,18 +189,20 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas phased_out = df_agg[df_agg["DateOut"] < baseyear].index df_agg.drop(phased_out, inplace=True) - older_assets = (df_agg.DateIn Date: Thu, 11 Apr 2024 15:37:54 +0200 Subject: [PATCH 542/591] Activate Sphinx automodules, add mock imports for missing pypsa-eur modules in environment used to build documentation --- doc/conf.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index afa01d3a..c9f0b256 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -34,10 +34,10 @@ sys.path.insert(0, os.path.abspath("../scripts")) # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - #'sphinx.ext.autodoc', + 'sphinx.ext.autodoc', #'sphinx.ext.autosummary', "myst_parser", - "sphinx.ext.autosectionlabel", + # "sphinx.ext.autosectionlabel", "sphinx.ext.intersphinx", "sphinx.ext.todo", "sphinx.ext.mathjax", @@ -50,6 +50,8 @@ extensions = [ "sphinx.ext.imgconverter", # for SVG conversion ] +autodoc_mock_imports = ["atlite", "snakemake", "pycountry", "rioxarray", "country_converter", "tabula", "memory_profiler", "powerplantmatching", "rasterio", "dask.distributed"] + autodoc_default_flags = ["members"] autosummary_generate = True From 1c321b72cf57b0d24307cff96e3967d0bbcda2a1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 14:53:09 +0000 Subject: [PATCH 543/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/conf.py | 15 +++++++++++++-- doc/contributing.rst | 1 - 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index c9f0b256..739c7663 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -34,7 +34,7 @@ sys.path.insert(0, os.path.abspath("../scripts")) # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', + "sphinx.ext.autodoc", #'sphinx.ext.autosummary', "myst_parser", # "sphinx.ext.autosectionlabel", @@ -50,7 +50,18 @@ extensions = [ "sphinx.ext.imgconverter", # for SVG conversion ] -autodoc_mock_imports = ["atlite", "snakemake", "pycountry", "rioxarray", "country_converter", "tabula", "memory_profiler", "powerplantmatching", "rasterio", "dask.distributed"] +autodoc_mock_imports = [ + "atlite", + "snakemake", + "pycountry", + "rioxarray", + "country_converter", + "tabula", + "memory_profiler", + "powerplantmatching", + "rasterio", + "dask.distributed", +] autodoc_default_flags = ["members"] autosummary_generate = True diff --git a/doc/contributing.rst b/doc/contributing.rst index 52dc8280..22dfb447 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -47,4 +47,3 @@ We strive to keep documentation useful and up to date for all PyPSA users. If yo #. Compile your changes by running the following command in your terminal in the ``doc`` folder: ``make html`` You may encounter some warnings, but end up with a message such as ``build succeeded, XX warnings.``. html files to review your changes can then be found under ``doc/_build/html``. #. Contribute your documentation in a pull request (`here is a guide `_). - From cb7061d6030d73e3d01b7f0c192c65263977d7b5 Mon Sep 17 00:00:00 2001 From: chrstphtrs Date: Thu, 11 Apr 2024 15:55:11 +0200 Subject: [PATCH 544/591] Change all documentation links to be anonymous by adding double underscore suffix to avoid automatic target creation (which is triggered by single underscore suffix) --- doc/configuration.rst | 12 +- doc/costs.rst | 4 +- doc/foresight.rst | 4 +- doc/index.rst | 44 +++--- doc/installation.rst | 26 ++-- doc/introduction.rst | 14 +- doc/licenses.rst | 12 +- doc/limitations.rst | 2 +- doc/preparation.rst | 8 +- doc/release_notes.rst | 298 ++++++++++++++++++------------------- doc/retrieve.rst | 20 +-- doc/sector.rst | 11 +- doc/simplification.rst | 4 +- doc/spatial_resolution.rst | 14 +- doc/supply_demand.rst | 184 +++++++++++------------ doc/support.rst | 10 +- doc/tutorial.rst | 2 +- doc/validation.rst | 2 +- doc/wildcards.rst | 2 +- 19 files changed, 340 insertions(+), 333 deletions(-) diff --git a/doc/configuration.rst b/doc/configuration.rst index dae91380..d531ee66 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -90,9 +90,9 @@ For each wildcard, a **list of values** is provided. The rule ``results/networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc`` for **all combinations** of the provided wildcard values as defined by Python's `itertools.product(...) -`_ function +`__ function that snakemake's `expand(...) function -`_ +`__ uses. An exemplary dependency graph (starting from the simplification rules) then looks like this: @@ -129,7 +129,7 @@ An exemplary dependency graph (starting from the simplification rules) then look ``snapshots`` ============= -Specifies the temporal range to build an energy system model for as arguments to `pandas.date_range `_ +Specifies the temporal range to build an energy system model for as arguments to `pandas.date_range `__ .. literalinclude:: ../config/config.default.yaml :language: yaml @@ -197,7 +197,7 @@ Switches for some rules and optional features. ``atlite`` ========== -Define and specify the ``atlite.Cutout`` used for calculating renewable potentials and time-series. All options except for ``features`` are directly used as `cutout parameters `_. +Define and specify the ``atlite.Cutout`` used for calculating renewable potentials and time-series. All options except for ``features`` are directly used as `cutout parameters `__. .. literalinclude:: ../config/config.default.yaml :language: yaml @@ -427,7 +427,7 @@ overwrite the existing values. :widths: 22,7,22,33 :file: configtables/biomass.csv -The list of available biomass is given by the category in `ENSPRESO_BIOMASS `_, namely: +The list of available biomass is given by the category in `ENSPRESO_BIOMASS `__, namely: - Agricultural waste - Manure solid, liquid @@ -564,7 +564,7 @@ The list of available biomass is given by the category in `ENSPRESO_BIOMASS `_ and then +`PyPSA/technology-data `__ and then saved to a file ``resources/costs_{year}.csv``. The ``config/config.yaml`` provides options to choose a reference year and use a specific version of the repository. @@ -30,7 +30,7 @@ years compiled from various sources, namely for - carbon-dioxide intensity. Many values are taken from a database published by the Danish Energy Agency (`DEA -`_). +`__). The given overnight capital costs are annualised to net present costs diff --git a/doc/foresight.rst b/doc/foresight.rst index c749c84c..400f67ce 100644 --- a/doc/foresight.rst +++ b/doc/foresight.rst @@ -166,13 +166,13 @@ Options The total carbon budget for the entire transition path can be indicated in the `sector_opts -`_ +`__ in ``config/config.yaml``. The carbon budget can be split among the ``planning_horizons`` following an exponential or beta decay. E.g. ``'cb40ex0'`` splits a carbon budget equal to 40 Gt :math:`_{CO_2}` following an exponential decay whose initial linear growth rate r is zero. They can also follow some user-specified path, if defined `here -`_. +`__. The paper `Speed of technological transformations required in Europe to achieve different climate goals (2022) `__ defines CO_2 budgets corresponding to global temperature increases (1.5C – 2C) diff --git a/doc/index.rst b/doc/index.rst index acff820b..07ee28d1 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -81,16 +81,16 @@ them: .. note:: You can find showcases of the model's capabilities in the Supplementary Materials of the Joule paper `The potential role of a hydrogen network in Europe - `_, the Supplementary Materials of another `paper in Joule with a + `__, the Supplementary Materials of another `paper in Joule with a description of the industry sector - `_, or in `a 2021 presentation - at EMP-E `_. + `__, or in `a 2021 presentation + at EMP-E `__. The sector-coupled extension of PyPSA-Eur was initially described in the paper `Synergies of sector coupling and transmission reinforcement in a cost-optimised, highly renewable European energy system - `_ (2018) but it differs by being based on the + `__ (2018) but it differs by being based on the higher resolution electricity transmission model `PyPSA-Eur - `_ rather than a one-node-per-country model, + `__ rather than a one-node-per-country model, and by including biomass, industry, industrial feedstocks, aviation, shipping, better carbon management, carbon capture and usage/sequestration, and gas networks. @@ -99,8 +99,8 @@ About ===== PyPSA-Eur is designed to be imported into the open energy system modelling -framework `PyPSA `_ for which `documentation -`_ is available as well. However, since the +framework `PyPSA `__ for which `documentation +`__ is available as well. However, since the workflow is modular, it should be easy to adapt the data workflow to other modelling frameworks. @@ -114,22 +114,22 @@ of the individual parts. PyPSA-Eur is under active development and has several :doc:`limitations` which you should understand before using the model. The Github repository - `issues `_ collect known + `issues `__ collect known topics we are working on. Please feel free to help or make suggestions. This project is currently maintained by the `Department of Digital -Transformation in Energy Systems `_ at the -`Technische Universität Berlin `_. Previous versions were -developed within the `IAI `_ at the `Karlsruhe Institute -of Technology (KIT) `_ which was funded by -the `Helmholtz Association `_, and by the +Transformation in Energy Systems `__ at the +`Technische Universität Berlin `__. Previous versions were +developed within the `IAI `__ at the `Karlsruhe Institute +of Technology (KIT) `__ which was funded by +the `Helmholtz Association `__, and by the `Renewable Energy Group -`_ -at `FIAS `_ to carry out simulations for the -`CoNDyNet project `_, financed by the `German Federal -Ministry for Education and Research (BMBF) `_ +`__ +at `FIAS `__ to carry out simulations for the +`CoNDyNet project `__, financed by the `German Federal +Ministry for Education and Research (BMBF) `__ as part of the `Stromnetze Research Initiative -`_. +`__. Workflow @@ -153,10 +153,10 @@ to reading this documentation. - Documentation of `PyPSA `__, the package for modelling energy systems which PyPSA-Eur uses under the hood. -- Course on `Energy Systems `_ given at - Technical University of Berlin by `Prof. Dr. Tom Brown `_. -- Course on `Data Science for Energy System Modelling `_ - given at Technical University of Berlin by `Dr. Fabian Neumann `_. +- Course on `Energy Systems `__ given at + Technical University of Berlin by `Prof. Dr. Tom Brown `__. +- Course on `Data Science for Energy System Modelling `__ + given at Technical University of Berlin by `Dr. Fabian Neumann `__. Citing PyPSA-Eur diff --git a/doc/installation.rst b/doc/installation.rst index fbabfd15..dd5c912e 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -15,7 +15,7 @@ directory in which the commands following the ``%`` should be entered. Clone the Repository ==================== -First of all, clone the `PyPSA-Eur repository `_ using the version control system ``git`` in the command line. +First of all, clone the `PyPSA-Eur repository `__ using the version control system ``git`` in the command line. .. code:: bash @@ -30,11 +30,11 @@ Install Python Dependencies =============================== PyPSA-Eur relies on a set of other Python packages to function. -We recommend using the package manager `mamba `_ to install them and manage your environments. -For instructions for your operating system follow the ``mamba`` `installation guide `_. +We recommend using the package manager `mamba `__ to install them and manage your environments. +For instructions for your operating system follow the ``mamba`` `installation guide `__. You can also use ``conda`` equivalently. -The package requirements are curated in the `envs/environment.yaml `_ file. +The package requirements are curated in the `envs/environment.yaml `__ file. The environment can be installed and activated using .. code:: bash @@ -59,16 +59,16 @@ Install a Solver PyPSA passes the PyPSA-Eur network model to an external solver for performing the optimisation. PyPSA is known to work with the free software -- `HiGHS `_ -- `Cbc `_ -- `GLPK `_ (`WinGLKP `_) -- `Ipopt `_ +- `HiGHS `__ +- `Cbc `__ +- `GLPK `__ (`WinGLKP `__) +- `Ipopt `__ and the non-free, commercial software (for some of which free academic licenses are available) -- `Gurobi `_ -- `CPLEX `_ -- `FICO Xpress Solver `_ +- `Gurobi `__ +- `CPLEX `__ +- `FICO Xpress Solver `__ For installation instructions of these solvers for your operating system, follow the links above. Commercial solvers such as Gurobi and CPLEX currently significantly outperform open-source solvers for large-scale problems, and @@ -76,7 +76,7 @@ it might be the case that you can only retrieve solutions by using a commercial Nevertheless, you can still use open-source solvers for smaller problems. .. seealso:: - `Instructions how to install a solver in the documentation of PyPSA `_ + `Instructions how to install a solver in the documentation of PyPSA `__ .. note:: The rules :mod:`cluster_network` and :mod:`simplify_network` solve a mixed-integer quadratic optimisation problem for clustering. @@ -88,7 +88,7 @@ Nevertheless, you can still use open-source solvers for smaller problems. mamba activate pypsa-eur mamba install -c gurobi gurobi - Additionally, you need to setup your `Gurobi license `_. + Additionally, you need to setup your `Gurobi license `__. .. _defaultconfig: diff --git a/doc/introduction.rst b/doc/introduction.rst index d271391c..7cfa0e43 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -14,7 +14,7 @@ .. note:: - Find the introductory slides `here `_. + Find the introductory slides `here `__. .. warning:: The video only introduces the electricity-only part of PyPSA-Eur. @@ -23,7 +23,7 @@ Workflow ========= The generation of the model is controlled by the open workflow management system -`Snakemake `_. In a nutshell, the ``Snakefile`` +`Snakemake `__. In a nutshell, the ``Snakefile`` declares for each script in the ``scripts`` directory a rule which describes which files the scripts consume and produce (their corresponding input and output files). The ``snakemake`` tool then runs the scripts in the correct order @@ -54,9 +54,9 @@ preceding rules which another rule takes as input data. For the use of ``snakemake``, it makes sense to familiarize yourself quickly with the `basic tutorial -`_ and then +`__ and then read carefully through the documentation of the `command line interface -`_, noting the +`__, noting the arguments ``-j``, ``-c``, ``-f``, ``-F``, ``-n``, ``-r``, ``--dag`` and ``-t`` in particular. @@ -64,10 +64,10 @@ Scenarios, Configuration and Modification ========================================= It is easy to run PyPSA-Eur for multiple scenarios using the `wildcards feature -`_ +`__ of ``snakemake``. Wildcards allow to generalise a rule to produce all files that follow a `regular expression -`_ pattern, which defines +`__ pattern, which defines a particular scenario. One can think of a wildcard as a parameter that shows up in the input/output file names and thereby determines which rules to run, what data to retrieve and what files to produce. Details are explained in @@ -97,5 +97,5 @@ System Requirements Building the model with the scripts in this repository runs on a regular computer. But optimising for investment and operation decisions across many scenarios requires a strong interior-point solver -like `Gurobi `_ or `CPLEX `_ with more memory. +like `Gurobi `__ or `CPLEX `__ with more memory. Open-source solvers like `HiGHS ` can also be used for smaller problems. diff --git a/doc/licenses.rst b/doc/licenses.rst index 74640ea5..af531660 100644 --- a/doc/licenses.rst +++ b/doc/licenses.rst @@ -10,12 +10,12 @@ Licenses PyPSA-Eur is released under multiple licenses: -* All original source code is licensed as free software under `MIT `_. -* The documentation is licensed under `CC-BY-4.0 `_. -* Configuration files are mostly licensed under `CC0-1.0 `_. -* Data files are licensed under `CC-BY-4.0 `_. +* All original source code is licensed as free software under `MIT `__. +* The documentation is licensed under `CC-BY-4.0 `__. +* Configuration files are mostly licensed under `CC0-1.0 `__. +* Data files are licensed under `CC-BY-4.0 `__. -See the individual files and the `dep5 <.reuse/dep5>`_ file for license details. +See the individual files and the `dep5 <.reuse/dep5>`__ file for license details. Additionally, different licenses and terms of use also apply to the various input data for both electricity-only and sector-coupled modelling exercises, @@ -26,7 +26,7 @@ Electricity Systems Databundle .. note:: More details are included in `the description of the - data bundles on zenodo `_. + data bundles on zenodo `__. .. csv-table:: :header-rows: 1 diff --git a/doc/limitations.rst b/doc/limitations.rst index 2aa8ecfe..aeec5da6 100644 --- a/doc/limitations.rst +++ b/doc/limitations.rst @@ -19,7 +19,7 @@ improving the approximations. This list of limitations is incomplete and will be added to over time. .. seealso:: - See also the `GitHub repository issues `_. + See also the `GitHub repository issues `__. - **Electricity transmission network topology:** The grid data is based on a map of the ENTSO-E area that is known diff --git a/doc/preparation.rst b/doc/preparation.rst index bb55ba6b..f608e031 100644 --- a/doc/preparation.rst +++ b/doc/preparation.rst @@ -15,18 +15,18 @@ Instead we provide separate data bundles which can be obtained using the ``retrieve*`` rules (:ref:`data`). Having downloaded the necessary data, -- :mod:`build_shapes` generates GeoJSON files with shapes of the countries, exclusive economic zones and `NUTS3 `_ areas. -- :mod:`build_cutout` prepares smaller weather data portions from `ERA5 `_ for cutout ``europe-2013-era5`` and SARAH for cutout ``europe-2013-sarah``. +- :mod:`build_shapes` generates GeoJSON files with shapes of the countries, exclusive economic zones and `NUTS3 `__ areas. +- :mod:`build_cutout` prepares smaller weather data portions from `ERA5 `__ for cutout ``europe-2013-era5`` and SARAH for cutout ``europe-2013-sarah``. With these and the externally extracted ENTSO-E online map topology (``data/entsoegridkit``), it can build a base PyPSA network with the following rules: - :mod:`base_network` builds and stores the base network with all buses, HVAC lines and HVDC links, while -- :mod:`build_bus_regions` determines `Voronoi cells `_ for all substations. +- :mod:`build_bus_regions` determines `Voronoi cells `__ for all substations. Then the process continues by calculating conventional power plant capacities, potentials, and per-unit availability time series for variable renewable energy carriers and hydro power plants with the following rules: -- :mod:`build_powerplants` for today's thermal power plant capacities using `powerplantmatching `_ allocating these to the closest substation for each powerplant, +- :mod:`build_powerplants` for today's thermal power plant capacities using `powerplantmatching `__ allocating these to the closest substation for each powerplant, - :mod:`build_natura_raster` for rasterising NATURA2000 natural protection areas, - :mod:`build_ship_raster` for building shipping traffic density, - :mod:`build_renewable_profiles` for the hourly capacity factors and installation potentials constrained by land-use in each substation's Voronoi cell for PV, onshore and offshore wind, and diff --git a/doc/release_notes.rst b/doc/release_notes.rst index c5099943..74ca724b 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -51,20 +51,20 @@ Upcoming Release - Include time series of Swiss number of passenger vehicles from the `Swiss Federal Statistical Office - `_. + `__. - Updated hydro-electricity generation and capacity data from EIA. - The easiest way to sweep over multiple weather years is to use the new scenario management. An example for the necessary `create_scenarios.py` script can be found in this `Github gist - `_. + `__. * Removed rule ``copy_config``. Instead, a config file is created for each network output of the ``solve_*`` rules, with the same content as ``n.meta``. * Added new HVDC transmission projects from `TYNDP 2024 draft projects - `_. + `__. * Upgrade to Snakemake v8.5+. This version is the new minimum version required. To upgrade an existing environment, run ``conda install -c bioconda @@ -80,7 +80,7 @@ Upcoming Release * The Eurostat data was updated to the 2023 version in :mod:`build_energy_totals`. * The latest `Swiss energy totals - `_ + `__ have been updated to the 2023 version. * The JRC-IDEES data is only available until 2015. For energy totals years (``energy: energy_totals_year``) after @@ -269,10 +269,10 @@ PyPSA-Eur 0.10.0 (19th February 2024) * Default settings for recycling rates and primary product shares of high-value chemicals have been set in accordance with the values used in `Neumann et al. - (2023) `_ linearly interpolated + (2023) `__ linearly interpolated between 2020 and 2050. The recycling rates are based on data from `Agora Energiewende (2021) - `_. + `__. * Air-sourced heat pumps can now also be built in rural areas. Previously, only ground-sourced heat pumps were considered for this category @@ -390,7 +390,7 @@ PyPSA-Eur 0.10.0 (19th February 2024) (https://github.com/PyPSA/pypsa-eur/pull/861). Special thanks for this release to Koen van Greevenbroek (`@koen-vg -`_) for various new features, bugfixes and taking +`__) for various new features, bugfixes and taking care of deprecations. @@ -427,18 +427,18 @@ PyPSA-Eur 0.9.0 (5th January 2024) * Add locations, capacities and costs of existing gas storage using Global Energy Monitor's `Europe Gas Tracker - `_ + `__ (https://github.com/PyPSA/pypsa-eur/pull/835). * Add option to use `LUISA Base Map - `_ 50m land + `__ 50m land coverage dataset for land eligibility analysis in :mod:`build_renewable_profiles`. Settings are analogous to the CORINE dataset but with the key ``luisa:`` in the configuration file. To leverage the dataset's full advantages, set the excluder resolution to 50m (``excluder_resolution: 50``). For land category codes, see `Annex 1 of the technical documentation - `_ + `__ (https://github.com/PyPSA/pypsa-eur/pull/842). * Add option to capture CO2 contained in biogas when upgrading (``sector: @@ -681,7 +681,7 @@ PyPSA-Eur 0.8.1 (27th July 2023) * Add option to consider dynamic line rating based on wind speeds and temperature according to `Glaum and Hofmann (2022) - `_. See configuration section ``lines: + `__. See configuration section ``lines: dynamic_line_rating:`` for more details. (https://github.com/PyPSA/pypsa-eur/pull/675) * Add option to include a piecewise linear approximation of transmission losses, @@ -700,7 +700,7 @@ PyPSA-Eur 0.8.1 (27th July 2023) * A ``param:`` section in the snakemake rule definitions was added to track changed settings in ``config.yaml``. The goal is to automatically re-execute rules where parameters have changed. See `Non-file parameters for rules - `_ + `__ in the snakemake documentation. (https://github.com/PyPSA/pypsa-eur/pull/663) * A new function named ``sanitize_carrier`` ensures that all unique carrier @@ -809,7 +809,7 @@ PyPSA-Eur 0.8.0 (18th March 2023) * The :mod:`solve_network` script now uses the ``linopy`` backend of PyPSA and is applied for both electricity-only and sector-coupled models. This requires an adjustment of custom ``extra_functionality``. - See the `migration guide `_ in the PyPSA documentation. + See the `migration guide `__ in the PyPSA documentation. * The configuration file ``config.default.yaml`` now also includes settings for sector-coupled models, which will be ignored when the user runs @@ -914,7 +914,7 @@ PyPSA-Eur 0.7.0 (16th February 2023) inclusive:`` to address the upstream deprecation with ``pandas=1.4``. The previous setting ``None`` is no longer supported and replaced by ``both``, see the `pandas documentation - `_. + `__. Minimum version is now ``pandas>=1.4``. * The configuration setting ``summary_dir`` was removed. @@ -968,7 +968,7 @@ PyPSA-Eur 0.6.1 (20th September 2022) * Individual commits are now tested against pre-commit hooks. This includes black style formatting, sorting of package imports, Snakefile formatting and others. Installation instructions can for the pre-commit can be found `here - `_. + `__. * Pre-commit CI is now part of the repository's CI. @@ -991,7 +991,7 @@ PyPSA-Eur 0.6.0 (10th September 2022) * Functionality to consider shipping routes when calculating the available area for offshore technologies were added. Data for the shipping density comes from the `Global Shipping Traffic Density dataset - `_. + `__. * When transforming all transmission lines to a unified voltage level of 380kV, the workflow now preserves the transmission capacity rather than electrical @@ -1028,7 +1028,7 @@ PyPSA-Eur 0.5.0 (27th July 2022) ``from_opsd`` to ``True``. * Add operational reserve margin constraint analogous to `GenX implementation - `_. Can be activated + `__. Can be activated with config setting ``electricity: operational_reserve:``. * Implement country-specific Energy Availability Factors (EAFs) for nuclear @@ -1054,12 +1054,12 @@ PyPSA-Eur 0.5.0 (27th July 2022) * Techno-economic parameters of technologies (e.g. costs and efficiencies) will now be retrieved from a separate repository `PyPSA/technology-data - `_ that collects assumptions from a + `__ that collects assumptions from a variety of sources. It is activated by default with ``enable: retrieve_cost_data: true`` and controlled with ``costs: year:`` and ``costs: version:``. The location of this data changed from ``data/costs.csv`` to ``resources/costs.csv`` [`#184 - `_]. + `__]. * A new section ``conventional`` was added to the config file. This section contains configurations for conventional carriers. @@ -1074,18 +1074,18 @@ PyPSA-Eur 0.5.0 (27th July 2022) * Add an efficiency factor of 88.55% to offshore wind capacity factors as a proxy for wake losses. More rigorous modelling is `planned - `_ [`#277 - `_]. + `__ [`#277 + `__]. * Following discussion in `#285 - `_ we have disabled the + `__ we have disabled the correction factor for solar PV capacity factors by default while satellite data is used. A correction factor of 0.854337 is recommended if reanalysis data like ERA5 is used. * The default deployment density of AC- and DC-connected offshore wind capacity is reduced from 3 MW/sqkm to a more conservative estimate of 2 MW/sqkm [`#280 - `_]. + `__]. * The inclusion of renewable carriers is now specified in the config entry ``renewable_carriers``. Before this was done by commenting/uncommenting @@ -1114,12 +1114,12 @@ PyPSA-Eur 0.5.0 (27th July 2022) * Resource definitions for memory usage now follow `Snakemake standard resource definition - `_ + `__ ``mem_mb`` rather than ``mem``. * The powerplants that have been shut down by 2021 are filtered out. -* Updated historical `EIA hydro generation data `_. +* Updated historical `EIA hydro generation data `__. * Network building is made deterministic by supplying a fixed random state to network clustering routines. @@ -1168,24 +1168,24 @@ Synchronisation Release - Ukraine and Moldova (17th March 2022) --------------------------------------------------------------- On March 16, 2022, the transmission networks of Ukraine and Moldova have -successfully been `synchronised with the continental European grid `_. We have taken +successfully been `synchronised with the continental European grid `__. We have taken this as an opportunity to add the power systems of Ukraine and Moldova to PyPSA-Eur. This includes: .. image:: img/synchronisation.png :width: 500 -* the transmission network topology from the `ENTSO-E interactive map `_. +* the transmission network topology from the `ENTSO-E interactive map `__. -* existing power plants (incl. nuclear, coal, gas and hydro) from the `powerplantmatching `_ tool +* existing power plants (incl. nuclear, coal, gas and hydro) from the `powerplantmatching `__ tool -* country-level load time series from ENTSO-E through the `OPSD platform `_, which are then distributed heuristically to substations by GDP and population density. +* country-level load time series from ENTSO-E through the `OPSD platform `__, which are then distributed heuristically to substations by GDP and population density. * wind and solar profiles based on ERA5 and SARAH-2 weather data -* hydro profiles based on historical `EIA generation data `_ +* hydro profiles based on historical `EIA generation data `__ -* a simplified calculation of wind and solar potentials based on the `Copernicus Land Cover dataset `_. +* a simplified calculation of wind and solar potentials based on the `Copernicus Land Cover dataset `__. * electrical characteristics of 750 kV transmission lines @@ -1206,18 +1206,18 @@ PyPSA-Eur 0.4.0 (22th September 2021) * With this release, we change the license from copyleft GPLv3 to the more liberal MIT license with the consent of all contributors - [`#276 `_]. + [`#276 `__]. * Switch to the new major ``atlite`` release v0.2. The version upgrade comes along with significant speed up for the rule ``build_renewable_profiles.py`` (~factor 2). A lot of the code which calculated the land-use availability is now outsourced and does not rely on ``glaes``, ``geokit`` anymore. This facilitates the environment building and version compatibility of ``gdal``, ``libgdal`` with - other packages [`#224 `_]. + other packages [`#224 `__]. * Implemented changes to ``n.snapshot_weightings`` in new PyPSA version v0.18 - (cf. `PyPSA/PyPSA/#227 `_) - [`#259 `_]. + (cf. `PyPSA/PyPSA/#227 `__) + [`#259 `__]. * Add option to pre-aggregate nodes without power injections (positive or negative, i.e. generation or demand) to electrically closest nodes or neighbors @@ -1226,18 +1226,18 @@ PyPSA-Eur 0.4.0 (22th September 2021) * In :mod:`simplify_network`, bus columns with no longer correct entries are removed (symbol, tags, under_construction, substation_lv, substation_off) - [`#219 `_] + [`#219 `__] * Add option to include marginal costs of links representing fuel cells, electrolysis, and battery inverters - [`#232 `_]. + [`#232 `__]. * The rule and script ``build_country_flh`` are removed as they are no longer used or maintained. * The connection cost of generators in :mod:`simplify_network` are now reported in ``resources/connection_costs_s{simpl}.csv`` - [`#261 `_]. + [`#261 `__]. * The tutorial cutout was renamed from ``cutouts/europe-2013-era5.nc`` to ``cutouts/be-03-2013-era5.nc`` to accommodate tutorial and productive @@ -1247,72 +1247,72 @@ PyPSA-Eur 0.4.0 (22th September 2021) potentials was deprecated and now defaults to ``True``. * Update dependencies in ``envs/environment.yaml`` - [`#257 `_] + [`#257 `__] * Continuous integration testing switches to Github Actions from Travis CI - [`#252 `_]. + [`#252 `__]. * Documentation on readthedocs.io is now built with ``pip`` only and no longer - requires ``conda`` [`#267 `_]. + requires ``conda`` [`#267 `__]. -* Use ``Citation.cff`` [`#273 `_]. +* Use ``Citation.cff`` [`#273 `__]. **Bugs and Compatibility** -* Support for PyPSA v0.18 [`#268 `_]. +* Support for PyPSA v0.18 [`#268 `__]. * Minimum Python version set to ``3.8``. -* Removed ``six`` dependency [`#245 `_]. +* Removed ``six`` dependency [`#245 `__]. * Update :mod:`plot_network` and :mod:`make_summary` rules to latest PyPSA - versions [`#270 `_]. + versions [`#270 `__]. * Keep converter links to store components when using the ``ATK`` - wildcard and only remove DC links [`#214 `_]. + wildcard and only remove DC links [`#214 `__]. * Value for ``co2base`` in ``config.yaml`` adjusted to 1.487e9 t CO2-eq (from 3.1e9 t CO2-eq). The new value represents emissions related to the electricity sector for EU+UK+Balkan. The old value was too high and used when the emissions wildcard in ``{opts}`` was used - [`#233 `_]. + [`#233 `__]. * Add escape in :mod:`base_network` if all TYNDP links are already contained in the network - [`#246 `_]. + [`#246 `__]. * In :mod:`solve_operations_network` the optimised capacities are now fixed for all extendable links, not only HVDC links - [`#244 `_]. + [`#244 `__]. * The ``focus_weights`` are now also considered when pre-clustering in the :mod:`simplify_network` rule - [`#241 `_]. + [`#241 `__]. * in :mod:`build_renewable_profile` where offshore wind profiles could - no longer be created [`#249 `_]. + no longer be created [`#249 `__]. * Lower expansion limit of extendable carriers is now set to the existing capacity, i.e. ``p_nom_min = p_nom`` (0 before). Simultaneously, the upper limit (``p_nom_max``) is now the maximum of the installed capacity (``p_nom``) and the previous estimate based on land availability (``p_nom_max``) - [`#260 `_]. + [`#260 `__]. * Solving an operations network now includes optimized store capacities as well. Before only lines, links, generators and storage units were considered - [`#269 `_]. + [`#269 `__]. * With ``load_shedding: true`` in the solving options of ``config.yaml`` load shedding generators are only added at the AC buses, excluding buses for H2 - and battery stores [`#269 `_]. + and battery stores [`#269 `__]. * Delete duplicated capital costs at battery discharge link - [`#240 `_]. + [`#240 `__]. * Propagate the solver log file name to the solver. Previously, the PyPSA network solving functions were not told about the solver logfile specified - in the Snakemake file [`#247 `_] + in the Snakemake file [`#247 `__] PyPSA-Eur 0.3.0 (7th December 2020) ----------------------------------- @@ -1325,29 +1325,29 @@ Using the ``{opts}`` wildcard for scenario: For example ``EQ0.5c`` set in the ``{opts}`` wildcard requires each country to produce on average at least 50% of its consumption. Additionally, the option ``ATK`` requires autarky at each node and removes all means of power transmission through lines and links. ``ATKc`` only removes cross-border transfer capacities. - [`#166 `_]. + [`#166 `__]. * Added an option to alter the capital cost (``c``) or installable potentials (``p``) of carriers by a factor via ``carrier+{c,p}factor`` in the ``{opts}`` wildcard. This can be useful for exploring uncertain cost parameters. Example: ``solar+c0.5`` reduces the capital cost of solar to 50% of original values - [`#167 `_, `#207 `_]. + [`#167 `__, `#207 `__]. * Added an option to the ``{opts}`` wildcard that applies a time series segmentation algorithm based on renewables, hydro inflow and load time series to produce a given total number of adjacent snapshots of varying lengths. This feature is an alternative to downsampling the temporal resolution by simply averaging and - uses the `tsam `_ package - [`#186 `_]. + uses the `tsam `__ package + [`#186 `__]. More OPSD integration: -* Add renewable power plants from `OPSD `_ to the network for specified technologies. +* Add renewable power plants from `OPSD `__ to the network for specified technologies. This will overwrite the capacities calculated from the heuristic approach in :func:`estimate_renewable_capacities()` - [`#212 `_]. + [`#212 `__]. -* Electricity consumption data is now retrieved directly from the `OPSD website `_ using the rule :mod:`build_electricity_demand`. +* Electricity consumption data is now retrieved directly from the `OPSD website `__ using the rule :mod:`build_electricity_demand`. The user can decide whether to take the ENTSO-E power statistics data (default) or the ENTSO-E transparency data - [`#211 `_]. + [`#211 `__]. Other: @@ -1355,93 +1355,93 @@ Other: Then, the rule looks for custom busmaps at ``data/custom_busmap_elec_s{simpl}_{clusters}.csv``, which should have the same format as ``resources/busmap_elec_s{simpl}_{clusters}.csv``. i.e. the index should contain the buses of ``networks/elec_s{simpl}.nc`` - [`#193 `_]. + [`#193 `__]. * Line and link capacities can be capped in the ``config.yaml`` at ``lines: s_nom_max:`` and ``links: p_nom_max``: - [`#166 `_]. + [`#166 `__]. * Added Google Cloud Platform tutorial (for Windows users) - [`#177 `_]. + [`#177 `__]. **Changes** * Don't remove capital costs from lines and links, when imposing a line volume limit (``lv``) or a line cost limit (``lc``). Previously, these were removed to move the expansion in direction of the limit - [`#183 `_]. + [`#183 `__]. * The mappings for clustered lines and buses produced by the :mod:`simplify_network` and :mod:`cluster_network` rules changed from Hierarchical Data Format (``.h5``) to Comma-Separated Values format (``.csv``) for ease of use. - [`#198 `_] + [`#198 `__] * The N-1 security margin for transmission lines is now fixed to a provided value in ``config.yaml``, removing an undocumented linear interpolation between 0.5 and 0.7 in the range between 37 and 200 nodes. - [`#199 `_]. + [`#199 `__]. * Modelling hydrogen and battery storage with Store and Link components is now the default, rather than using StorageUnit components with fixed power-to-energy ratio - [`#205 `_]. + [`#205 `__]. * Use ``mamba`` (https://github.com/mamba-org/mamba) for faster Travis CI builds - [`#196 `_]. + [`#196 `__]. * Multiple smaller changes: Removed unused ``{network}`` wildcard, moved environment files to dedicated ``envs`` folder, removed sector-coupling components from configuration files, updated documentation colors, minor refactoring and code cleaning - [`#190 `_]. + [`#190 `__]. **Bugs and Compatibility** * Add compatibility for pyomo 5.7.0 in :mod:`cluster_network` and :mod:`simplify_network` - [`#172 `_]. + [`#172 `__]. * Fixed a bug for storage units such that individual store and dispatch efficiencies are correctly taken account of rather than only their round-trip efficiencies. In the cost database (``data/costs.csv``) the efficiency of battery inverters should be stated as per discharge/charge rather than per roundtrip - [`#202 `_]. + [`#202 `__]. * Corrected exogenous emission price setting (in ``config: cost: emission price:``), which now correctly accounts for the efficiency and effective emission of the generators - [`#171 `_]. + [`#171 `__]. * Corrected HVDC link connections (a) between Norway and Denmark and (b) mainland Italy, Corsica (FR) and Sardinia (IT) as well as for East-Western and Anglo-Scottish interconnectors - [`#181 `_, `#206 `_]. + [`#181 `__, `#206 `__]. * Fix bug of clustering ``offwind-{ac,dc}`` generators in the option of high-resolution generators for renewables. Now, there are more sites for ``offwind-{ac,dc}`` available than network nodes. Before, they were clustered to the resolution of the network (``elec_s1024_37m.nc``: 37 network nodes, 1024 generators) - [`#191 `_]. + [`#191 `__]. * Raise a warning if ``tech_colors`` in the config are not defined for all carriers - [`#178 `_]. + [`#178 `__]. PyPSA-Eur 0.2.0 (8th June 2020) ------------------------------- -* The optimization is now performed using the ``pyomo=False`` setting in the :func:`pypsa.lopf.network_lopf`. This speeds up the solving process significantly and consumes much less memory. The inclusion of additional constraints were adjusted to the new implementation. They are all passed to the :func:`network_lopf` function via the ``extra_functionality`` argument. The rule ``trace_solve_network`` was integrated into the rule :mod:`solve_network` and can be activated via configuration with ``solving: options: track_iterations: true``. The charging and discharging capacities of batteries modelled as store-link combination are now coupled [`#116 `_]. +* The optimization is now performed using the ``pyomo=False`` setting in the :func:`pypsa.lopf.network_lopf`. This speeds up the solving process significantly and consumes much less memory. The inclusion of additional constraints were adjusted to the new implementation. They are all passed to the :func:`network_lopf` function via the ``extra_functionality`` argument. The rule ``trace_solve_network`` was integrated into the rule :mod:`solve_network` and can be activated via configuration with ``solving: options: track_iterations: true``. The charging and discharging capacities of batteries modelled as store-link combination are now coupled [`#116 `__]. -* An updated extract of the `ENTSO-E Transmission System Map `_ (including Malta) was added to the repository using the `GridKit `_ tool. This tool has been updated to retrieve up-to-date map extracts using a single `script `_. The update extract features 5322 buses, 6574 lines, 46 links. [`#118 `_]. +* An updated extract of the `ENTSO-E Transmission System Map `__ (including Malta) was added to the repository using the `GridKit `__ tool. This tool has been updated to retrieve up-to-date map extracts using a single `script `__. The update extract features 5322 buses, 6574 lines, 46 links. [`#118 `__]. -* Added `FSFE REUSE `_ compliant license information. Documentation now licensed under CC-BY-4.0 [`#160 `_]. +* Added `FSFE REUSE `__ compliant license information. Documentation now licensed under CC-BY-4.0 [`#160 `__]. -* Added a 30 minute `video introduction `_ and a 20 minute `video tutorial `_ +* Added a 30 minute `video introduction `__ and a 20 minute `video tutorial `__ * Networks now store a color and a nicely formatted name for each carrier, accessible via ``n.carrier['color']`` and ``n.carrier['nice_name'] ``(networks after ``elec.nc``). * Added an option to skip iterative solving usually performed to update the line impedances of expanded lines at ``solving: options: skip_iterations:``. -* ``snakemake`` rules for retrieving cutouts and the natura raster can now be disabled independently from their respective rules to build them; via ``config.*yaml`` [`#136 `_]. +* ``snakemake`` rules for retrieving cutouts and the natura raster can now be disabled independently from their respective rules to build them; via ``config.*yaml`` [`#136 `__]. -* Removed the ``id`` column for custom power plants in ``data/custom_powerplants.csv`` to avoid custom power plants with conflicting ids getting attached to the wrong bus [`#131 `_]. +* Removed the ``id`` column for custom power plants in ``data/custom_powerplants.csv`` to avoid custom power plants with conflicting ids getting attached to the wrong bus [`#131 `__]. -* Add option ``renewables: {carrier}: keep_all_available_areas:`` to use all available weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed [`#150 `_]. +* Add option ``renewables: {carrier}: keep_all_available_areas:`` to use all available weather cells for renewable profile and potential generation. The default ignores weather cells where only less than 1 MW can be installed [`#150 `__]. -* Added a function ``_helpers.load_network()`` which loads a network with overridden components specified in ``snakemake.config['override_components']`` [`#128 `_]. +* Added a function ``_helpers.load_network()`` which loads a network with overridden components specified in ``snakemake.config['override_components']`` [`#128 `__]. -* Bugfix in :mod:`base_network` which now finds all closest links, not only the first entry [`#143 `_]. +* Bugfix in :mod:`base_network` which now finds all closest links, not only the first entry [`#143 `__]. -* Bugfix in :mod:`cluster_network` which now skips recalculation of link parameters if there are no links [`#149 `_]. +* Bugfix in :mod:`cluster_network` which now skips recalculation of link parameters if there are no links [`#149 `__]. -* Added information on pull requests to contribution guidelines [`#151 `_]. +* Added information on pull requests to contribution guidelines [`#151 `__]. * Improved documentation on open-source solver setup and added usage warnings. @@ -1452,31 +1452,31 @@ PyPSA-Eur 0.1.0 (9th January 2020) This is the first release of PyPSA-Eur, a model of the European power system at the transmission network level. Recent changes include: -* Documentation on installation, workflows and configuration settings is now available online at `pypsa-eur.readthedocs.io `_ [`#65 `_]. +* Documentation on installation, workflows and configuration settings is now available online at `pypsa-eur.readthedocs.io `__ [`#65 `__]. -* The ``conda`` environment files were updated and extended [`#81 `_]. +* The ``conda`` environment files were updated and extended [`#81 `__]. -* The power plant database was updated with extensive filtering options via ``pandas.query`` functionality [`#84 `_ and `#94 `_]. +* The power plant database was updated with extensive filtering options via ``pandas.query`` functionality [`#84 `__ and `#94 `__]. -* Continuous integration testing with `Travis CI `_ is now included for Linux, Mac and Windows [`#82 `_]. +* Continuous integration testing with `Travis CI `__ is now included for Linux, Mac and Windows [`#82 `__]. -* Data dependencies were moved to `zenodo `_ and are now versioned [`#60 `_]. +* Data dependencies were moved to `zenodo `__ and are now versioned [`#60 `__]. -* Data dependencies are now retrieved directly from within the snakemake workflow [`#86 `_]. +* Data dependencies are now retrieved directly from within the snakemake workflow [`#86 `__]. -* Emission prices can be added to marginal costs of generators through the keywords ``Ep`` in the ``{opts}`` wildcard [`#100 `_]. +* Emission prices can be added to marginal costs of generators through the keywords ``Ep`` in the ``{opts}`` wildcard [`#100 `__]. -* An option is introduced to add extendable nuclear power plants to the network [`#98 `_]. +* An option is introduced to add extendable nuclear power plants to the network [`#98 `__]. -* Focus weights can now be specified for particular countries for the network clustering, which allows to set a proportion of the total number of clusters for particular countries [`#87 `_]. +* Focus weights can now be specified for particular countries for the network clustering, which allows to set a proportion of the total number of clusters for particular countries [`#87 `__]. -* A new rule :mod:`add_extra_components` allows to add additional components to the network only after clustering. It is thereby possible to model storage units (e.g. battery and hydrogen) in more detail via a combination of ``Store``, ``Link`` and ``Bus`` elements [`#97 `_]. +* A new rule :mod:`add_extra_components` allows to add additional components to the network only after clustering. It is thereby possible to model storage units (e.g. battery and hydrogen) in more detail via a combination of ``Store``, ``Link`` and ``Bus`` elements [`#97 `__]. -* Hydrogen pipelines (including cost assumptions) can now be added alongside clustered network connections in the rule :mod:`add_extra_components` . Set ``electricity: extendable_carriers: Link: [H2 pipeline]`` and ensure hydrogen storage is modelled as a ``Store``. This is a first simplified stage [`#108 `_]. +* Hydrogen pipelines (including cost assumptions) can now be added alongside clustered network connections in the rule :mod:`add_extra_components` . Set ``electricity: extendable_carriers: Link: [H2 pipeline]`` and ensure hydrogen storage is modelled as a ``Store``. This is a first simplified stage [`#108 `__]. -* Logfiles for all rules of the ``snakemake`` workflow are now written in the folder ``log/`` [`#102 `_]. +* Logfiles for all rules of the ``snakemake`` workflow are now written in the folder ``log/`` [`#102 `__]. -* The new function ``_helpers.mock_snakemake`` creates a ``snakemake`` object which mimics the actual ``snakemake`` object produced by workflow by parsing the ``Snakefile`` and setting all paths for inputs, outputs, and logs. This allows running all scripts within a (I)python terminal (or just by calling ``python ``) and thereby facilitates developing and debugging scripts significantly [`#107 `_]. +* The new function ``_helpers.mock_snakemake`` creates a ``snakemake`` object which mimics the actual ``snakemake`` object produced by workflow by parsing the ``Snakefile`` and setting all paths for inputs, outputs, and logs. This allows running all scripts within a (I)python terminal (or just by calling ``python ``) and thereby facilitates developing and debugging scripts significantly [`#107 `__]. PyPSA-Eur-Sec Releases (pre-merge) @@ -1493,13 +1493,13 @@ biomass, and explicit modelling of methanol and ammonia as separate energy carriers. This release is known to work with `PyPSA-Eur -`_ Version 0.7.0 and `Technology Data -`_ Version 0.5.0. +`__ Version 0.7.0 and `Technology Data +`__ Version 0.5.0. **Gas Transmission Network** * New rule ``retrieve_gas_infrastructure_data`` that downloads and extracts the - SciGRID_gas `IGGIELGN `_ dataset from + SciGRID_gas `IGGIELGN `__ dataset from zenodo. It includes data on the transmission routes, pipe diameters, capacities, pressure, and whether the pipeline is bidirectional and carries H-Gas or L-Gas. @@ -1510,7 +1510,7 @@ This release is known to work with `PyPSA-Eur * New rule ``build_gas_input_locations`` compiles the LNG import capacities (from the Global Energy Monitor's `Europe Gas Tracker - `_, pipeline + `__, pipeline entry capacities and local production capacities for each region of the model. These are the regions where fossil gas can eventually enter the model. @@ -1523,7 +1523,7 @@ This release is known to work with `PyPSA-Eur * With the option ``sector: gas_network:``, the existing gas network is added with a lossless transport model. A length-weighted `k-edge augmentation algorithm - `_ + `__ can be run to add new candidate gas pipelines such that all regions of the model can be connected to the gas network. The number of candidates can be controlled via the setting ``sector: gas_network_connectivity_upgrade:``. When @@ -1554,7 +1554,7 @@ This release is known to work with `PyPSA-Eur * Add option for regionally-resolved geological carbon dioxide sequestration potentials through new rule ``build_sequestration_potentials`` based on - `CO2StoP `_. This + `CO2StoP `__. This can be controlled in the section ``regional_co2_sequestration_potential`` of the ``config.yaml``. It includes options to select the level of conservatism, whether onshore potentials should be included, the respective upper and lower @@ -1566,7 +1566,7 @@ This release is known to work with `PyPSA-Eur ``seq200`` in the ``{sector_opts}`` wildcard (for limit of 200 Mt CO2). * Add option to include `Allam cycle gas power plants - `_ (``allam_cycle``). + `__ (``allam_cycle``). * Add option for planning a new carbon dioxide network (``co2network``). @@ -1585,7 +1585,7 @@ This release is known to work with `PyPSA-Eur * Add regionalised hydrogen salt cavern storage potentials from `Technical Potential of Salt Caverns for Hydrogen Storage in Europe - `_. This data is compiled in + `__. This data is compiled in a new rule ``build_salt_cavern_potentials``. * Add option to resolve ammonia as separate energy carrier with Haber-Bosch @@ -1602,11 +1602,11 @@ This release is known to work with `PyPSA-Eur * Demand for liquid hydrogen in international shipping is now geographically distributed by port trade volumes in a new rule ``build_shipping_demand`` using data from the `World Bank Data Catalogue - `_. + `__. Domestic shipping remains distributed by population. * Add option to aggregate network temporally using representative snapshots or - segments (with `tsam `_). + segments (with `tsam `__). * Add option for minimum part load for Fischer-Tropsch plants (default: 90%) and methanolisation plants (default: 50%). @@ -1659,7 +1659,7 @@ This release is known to work with `PyPSA-Eur PyPSA network. * Updated `data bundle - `_ + `__ that includes the hydrogan salt cavern storage potentials. * Updated and extended documentation in @@ -1687,7 +1687,7 @@ This release is known to work with `PyPSA-Eur expansion of previous iteration as minimum capacity for next iteration. * Further rather minor bugfixes for myopic optimisation code (see `#256 - `_). + `__). Many thanks to all who contributed to this release! @@ -1706,9 +1706,9 @@ more options in setting exogenous transition paths, besides many performance improvements. This release is known to work with `PyPSA-Eur -`_ Version 0.4.0, `Technology Data -`_ Version 0.3.0 and -`PyPSA `_ Version 0.18.0. +`__ Version 0.4.0, `Technology Data +`__ Version 0.3.0 and +`PyPSA `__ Version 0.18.0. Please note that the data bundle has also been updated. @@ -1725,11 +1725,11 @@ Please note that the data bundle has also been updated. battery costs. * Separate basic chemicals into HVC (high-value chemicals), chlorine, methanol and ammonia - [`#166 `_]. + [`#166 `__]. * Add option to specify reuse, primary production, and mechanical and chemical recycling fraction of platics - [`#166 `_]. + [`#166 `__]. * Include energy demands and CO2 emissions for the agriculture, forestry and fishing sector. It is included by default through the option ``A`` in the ``sector_opts`` wildcard. @@ -1743,11 +1743,11 @@ Please note that the data bundle has also been updated. Heat demand is assigned at "services rural heat" buses. Electricity demands are added to low-voltage buses. Time series for demands are constant and distributed inside countries by population - [`#147 `_]. + [`#147 `__]. * Include today's district heating shares in myopic optimisation and add option to specify exogenous path for district heating share increase under ``sector: - district_heating:`` [`#149 `_]. + district_heating:`` [`#149 `__]. * Added option for hydrogen liquefaction costs for hydrogen demand in shipping. This introduces a new ``H2 liquid`` bus at each location. It is activated via @@ -1767,16 +1767,16 @@ Please note that the data bundle has also been updated. factor 2. In this example, ``e_nom_max`` represents the CO2 sequestration potential in Europe. -* Use `JRC ENSPRESO database `_ to +* Use `JRC ENSPRESO database `__ to spatially disaggregate biomass potentials to PyPSA-Eur regions based on overlaps with NUTS2 regions from ENSPRESO (proportional to area) (`#151 - `_). + `__). * Add option to regionally disaggregate biomass potential to individual nodes (previously given per country, then distributed by population density within) and allow the transport of solid biomass. The transport costs are determined based on the `JRC-EU-Times Bioenergy report - `_ in the new optional rule + `__ in the new optional rule ``build_biomass_transport_costs``. Biomass transport can be activated with the setting ``sector: biomass_transport: true``. @@ -1794,7 +1794,7 @@ Please note that the data bundle has also been updated. * The myopic option can now be used together with different clustering for the generators and the network. The existing renewable capacities are split evenly - among the regions in every country [`#144 `_]. + among the regions in every country [`#144 `__]. * Add optional function to use ``geopy`` to locate entries of the Hotmaps database of industrial sites with missing location based on city and country, @@ -1860,7 +1860,7 @@ Please note that the data bundle has also been updated. * Consistent use of ``__main__`` block and further unspecific code cleaning. -* Updated data bundle and moved data bundle to zenodo.org (`10.5281/zenodo.5546517 `_). +* Updated data bundle and moved data bundle to zenodo.org (`10.5281/zenodo.5546517 `__). **Bugfixes and Compatibility** @@ -1884,7 +1884,7 @@ PyPSA-Eur-Sec 0.5.0 (21st May 2021) This release includes improvements to the cost database for building retrofits, carbon budget management and wildcard settings, as well as an important bugfix for the emissions from land transport. -This release is known to work with `PyPSA-Eur `_ Version 0.3.0 and `Technology Data `_ Version 0.2.0. +This release is known to work with `PyPSA-Eur `__ Version 0.3.0 and `Technology Data `__ Version 0.2.0. Please note that the data bundle has also been updated. @@ -1905,15 +1905,15 @@ PyPSA-Eur-Sec 0.4.0 (11th December 2020) This release includes a more accurate nodal disaggregation of industry demand within each country, fixes to CHP and CCS representations, as well as changes to some configuration settings. -It has been released to coincide with `PyPSA-Eur `_ Version 0.3.0 and `Technology Data `_ Version 0.2.0, and is known to work with these releases. +It has been released to coincide with `PyPSA-Eur `__ Version 0.3.0 and `Technology Data `__ Version 0.2.0, and is known to work with these releases. New features: -* The `Hotmaps Industrial Database `_ is used to disaggregate the industrial demand spatially to the nodes inside each country (previously it was distributed by population density). +* The `Hotmaps Industrial Database `__ is used to disaggregate the industrial demand spatially to the nodes inside each country (previously it was distributed by population density). * Electricity demand from industry is now separated from the regular electricity demand and distributed according to the industry demand. Only the remaining regular electricity demand for households and services is distributed according to GDP and population. -* A cost database for the retrofitting of the thermal envelope of residential and services buildings has been integrated, as well as endogenous optimisation of the level of retrofitting. This is described in the paper `Mitigating heat demand peaks in buildings in a highly renewable European energy system `_. Retrofitting can be activated both exogenously and endogenously from the ``config.yaml``. -* The biomass and gas combined heat and power (CHP) parameters ``c_v`` and ``c_b`` were read in assuming they were extraction plants rather than back pressure plants. The data is now corrected in `Technology Data `_ Version 0.2.0 to the correct DEA back pressure assumptions and they are now implemented as single links with a fixed ratio of electricity to heat output (even as extraction plants, they were always sitting on the backpressure line in simulations, so there was no point in modelling the full heat-electricity feasibility polygon). The old assumptions underestimated the heat output. -* The Danish Energy Agency released `new assumptions for carbon capture `_ in October 2020, which have now been incorporated in PyPSA-Eur-Sec, including direct air capture (DAC) and post-combustion capture on CHPs, cement kilns and other industrial facilities. The electricity and heat demand for DAC is modelled for each node (with heat coming from district heating), but currently the electricity and heat demand for industrial capture is not modelled very cleanly (for process heat, 10% of the energy is assumed to go to carbon capture) - a new issue will be opened on this. +* A cost database for the retrofitting of the thermal envelope of residential and services buildings has been integrated, as well as endogenous optimisation of the level of retrofitting. This is described in the paper `Mitigating heat demand peaks in buildings in a highly renewable European energy system `__. Retrofitting can be activated both exogenously and endogenously from the ``config.yaml``. +* The biomass and gas combined heat and power (CHP) parameters ``c_v`` and ``c_b`` were read in assuming they were extraction plants rather than back pressure plants. The data is now corrected in `Technology Data `__ Version 0.2.0 to the correct DEA back pressure assumptions and they are now implemented as single links with a fixed ratio of electricity to heat output (even as extraction plants, they were always sitting on the backpressure line in simulations, so there was no point in modelling the full heat-electricity feasibility polygon). The old assumptions underestimated the heat output. +* The Danish Energy Agency released `new assumptions for carbon capture `__ in October 2020, which have now been incorporated in PyPSA-Eur-Sec, including direct air capture (DAC) and post-combustion capture on CHPs, cement kilns and other industrial facilities. The electricity and heat demand for DAC is modelled for each node (with heat coming from district heating), but currently the electricity and heat demand for industrial capture is not modelled very cleanly (for process heat, 10% of the energy is assumed to go to carbon capture) - a new issue will be opened on this. * Land transport is separated by energy carrier (fossil, hydrogen fuel cell electric vehicle, and electric vehicle), but still needs to be separated into heavy and light vehicles (the data is there, just not the code yet). * For assumptions that change with the investment year, there is a new time-dependent format in the ``config.yaml`` using a dictionary with keys for each year. Implemented examples include the CO2 budget, exogenous retrofitting share and land transport energy carrier; more parameters will be dynamised like this in future. * Some assumptions have been moved out of the code and into the ``config.yaml``, including the carbon sequestration potential and cost, the heat pump sink temperature, reductions in demand for high value chemicals, and some BEV DSM parameters and transport efficiencies. @@ -1936,7 +1936,7 @@ New features: * The script ``build_industrial_production_per_country_tomorrow.py`` determines the future industrial production of materials based on today's levels as well as assumed recycling and demand change measures. * The energy demand for each industry sector and each location in 2015 is also calculated, so that it can be later incorporated in the pathway optimization. * Ammonia production data is taken from the USGS and deducted from JRC-IDEES's "basic chemicals" so that it ammonia can be handled separately from the others (olefins, aromatics and chlorine). -* Solid biomass is no longer allowed to be used for process heat in cement and basic chemicals, since the wastes and residues cannot be guaranteed to reach the high temperatures required. Instead, solid biomass is used in the paper and pulp as well as food, beverages and tobacco industries, where required temperatures are lower (see `DOI:10.1002/er.3436 `_ and `DOI:10.1007/s12053-017-9571-y `_). +* Solid biomass is no longer allowed to be used for process heat in cement and basic chemicals, since the wastes and residues cannot be guaranteed to reach the high temperatures required. Instead, solid biomass is used in the paper and pulp as well as food, beverages and tobacco industries, where required temperatures are lower (see `DOI:10.1002/er.3436 `__ and `DOI:10.1007/s12053-017-9571-y `__). * National installable potentials for salt caverns are now applied. * When electricity distribution grids are activated, new industry electricity demand, resistive heaters and micro-CHPs are now connected to the lower voltage levels. * Gas distribution grid costs are included for gas boilers and micro-CHPs. @@ -1948,15 +1948,15 @@ New features: PyPSA-Eur-Sec 0.2.0 (21st August 2020) -------------------------------------- -This release introduces pathway optimization over many years (e.g. 2020, 2030, 2040, 2050) with myopic foresight, as well as outsourcing the technology assumptions to the `technology-data `_ repository. +This release introduces pathway optimization over many years (e.g. 2020, 2030, 2040, 2050) with myopic foresight, as well as outsourcing the technology assumptions to the `technology-data `__ repository. It is known to work with PyPSA-Eur v0.1.0 (commit bb3477cd69), PyPSA v0.17.1 and technology-data v0.1.0. New features: -* Option for pathway optimization with myopic foresight, based on the paper `Early decarbonisation of the European Energy system pays off (2020) `_. Investments are optimized sequentially for multiple years (e.g. 2020, 2030, 2040, 2050) taking account of existing assets built in previous years and their lifetimes. The script uses data on the existing assets for electricity and building heating technologies, but there are no assumptions yet for existing transport and industry (if you include these, the model will greenfield them). There are also some `outstanding issues `_ on e.g. the distribution of existing wind, solar and heating technologies within each country. To use myopic foresight, set ``foresight : 'myopic'`` in the ``config.yaml`` instead of the default ``foresight : 'overnight'``. An example configuration can be found in ``config.myopic.yaml``. More details on the implementation can be found in :doc:`myopic`. +* Option for pathway optimization with myopic foresight, based on the paper `Early decarbonisation of the European Energy system pays off (2020) `__. Investments are optimized sequentially for multiple years (e.g. 2020, 2030, 2040, 2050) taking account of existing assets built in previous years and their lifetimes. The script uses data on the existing assets for electricity and building heating technologies, but there are no assumptions yet for existing transport and industry (if you include these, the model will greenfield them). There are also some `outstanding issues `__ on e.g. the distribution of existing wind, solar and heating technologies within each country. To use myopic foresight, set ``foresight : 'myopic'`` in the ``config.yaml`` instead of the default ``foresight : 'overnight'``. An example configuration can be found in ``config.myopic.yaml``. More details on the implementation can be found in :doc:`myopic`. -* Technology assumptions (costs, efficiencies, etc.) are no longer stored in the repository. Instead, you have to install the `technology-data `_ database in a parallel directory. These assumptions are largely based on the `Danish Energy Agency Technology Data `_. More details on the installation can be found in :doc:`installation`. +* Technology assumptions (costs, efficiencies, etc.) are no longer stored in the repository. Instead, you have to install the `technology-data `__ database in a parallel directory. These assumptions are largely based on the `Danish Energy Agency Technology Data `__. More details on the installation can be found in :doc:`installation`. * Logs and benchmarks are now stored with the other model outputs in ``results/run-name/``. @@ -1979,7 +1979,7 @@ It is known to work with PyPSA-Eur v0.1.0 (commit bb3477cd69) and PyPSA v0.17.0. We are making this release since in version 0.2.0 we will introduce changes to allow myopic investment planning that will require minor changes for users of the overnight investment planning. PyPSA-Eur-Sec builds on the electricity generation and transmission -model `PyPSA-Eur `_ to add demand +model `PyPSA-Eur `__ to add demand and supply for the following sectors: transport, space and water heating, biomass, industry and industrial feedstocks. This completes the energy system and includes all greenhouse gas emitters except @@ -1988,17 +1988,17 @@ waste management, agriculture, forestry and land use. PyPSA-Eur-Sec was initially based on the model PyPSA-Eur-Sec-30 (Version 0.0.1 below) described in the paper `Synergies of sector coupling and transmission reinforcement in a cost-optimised, highly renewable European energy -system `_ (2018) but it differs by +system `__ (2018) but it differs by being based on the higher resolution electricity transmission model -`PyPSA-Eur `_ rather than a +`PyPSA-Eur `__ rather than a one-node-per-country model, and by including biomass, industry, industrial feedstocks, aviation, shipping, better carbon management, carbon capture and usage/sequestration, and gas networks. PyPSA-Eur-Sec includes PyPSA-Eur as a -`snakemake `_ -`subworkflow `_. PyPSA-Eur-Sec +`snakemake `__ +`subworkflow `__. PyPSA-Eur-Sec uses PyPSA-Eur to build the clustered transmission model along with wind, solar PV and hydroelectricity potentials and time series. Then PyPSA-Eur-Sec adds other conventional generators, storage units and @@ -2013,13 +2013,13 @@ PyPSA-Eur-Sec 0.0.2 (4th September 2020) This version, also called PyPSA-Eur-Sec-30-Path, built on PyPSA-Eur-Sec 0.0.1 (also called PyPSA-Eur-Sec-30) to include myopic pathway optimisation for the paper `Early decarbonisation of the -European energy system pays off `_ +European energy system pays off `__ (2020). The myopic pathway optimisation was then merged into the main PyPSA-Eur-Sec codebase in Version 0.2.0 above. This model has `its own github repository -`_ and is `archived -on Zenodo `_. +`__ and is `archived +on Zenodo `__. @@ -2030,12 +2030,12 @@ This is the first published version of PyPSA-Eur-Sec, also called PyPSA-Eur-Sec-30. It was first used in the research paper `Synergies of sector coupling and transmission reinforcement in a cost-optimised, highly renewable European energy system -`_ (2018). The model covers 30 +`__ (2018). The model covers 30 European countries with one node per country. It includes demand and supply for electricity, space and water heating in buildings, and land transport. -It is `archived on Zenodo `_. +It is `archived on Zenodo `__. Release Process @@ -2058,6 +2058,6 @@ Release Process * Tag a release on Github via ``git tag v0.x.x``, ``git push``, ``git push --tags``. Include release notes in the tag message. -* Make a `GitHub release `_, which automatically triggers archiving to the `zenodo code repository `_ with `MIT license `_. +* Make a `GitHub release `__, which automatically triggers archiving to the `zenodo code repository `__ with `MIT license `__. -* Send announcement on the `PyPSA mailing list `_. +* Send announcement on the `PyPSA mailing list `__. diff --git a/doc/retrieve.rst b/doc/retrieve.rst index f9d6e2a7..d21a74b4 100644 --- a/doc/retrieve.rst +++ b/doc/retrieve.rst @@ -25,12 +25,12 @@ Rule ``retrieve_cutout`` .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.6382570.svg :target: https://doi.org/10.5281/zenodo.6382570 -Cutouts are spatio-temporal subsets of the European weather data from the `ECMWF ERA5 `_ reanalysis dataset and the `CMSAF SARAH-2 `_ solar surface radiation dataset for the year 2013. -They have been prepared by and are for use with the `atlite `_ tool. You can either generate them yourself using the ``build_cutouts`` rule or retrieve them directly from `zenodo `__ through the rule ``retrieve_cutout``. +Cutouts are spatio-temporal subsets of the European weather data from the `ECMWF ERA5 `__ reanalysis dataset and the `CMSAF SARAH-2 `__ solar surface radiation dataset for the year 2013. +They have been prepared by and are for use with the `atlite `__ tool. You can either generate them yourself using the ``build_cutouts`` rule or retrieve them directly from `zenodo `__ through the rule ``retrieve_cutout``. The :ref:`tutorial` uses a smaller cutout than required for the full model (30 MB), which is also automatically downloaded. .. note:: - To download cutouts yourself from the `ECMWF ERA5 `_ you need to `set up the CDS API `_. + To download cutouts yourself from the `ECMWF ERA5 `__ you need to `set up the CDS API `__. **Relevant Settings** @@ -47,10 +47,10 @@ The :ref:`tutorial` uses a smaller cutout than required for the full model (30 M **Outputs** -- ``cutouts/{cutout}``: weather data from either the `ERA5 `_ reanalysis weather dataset or `SARAH-2 `_ satellite-based historic weather data. +- ``cutouts/{cutout}``: weather data from either the `ERA5 `__ reanalysis weather dataset or `SARAH-2 `__ satellite-based historic weather data. .. seealso:: - For details see :mod:`build_cutout` and read the `atlite documentation `_. + For details see :mod:`build_cutout` and read the `atlite documentation `__. Rule ``retrieve_natura_raster`` @@ -59,7 +59,7 @@ Rule ``retrieve_natura_raster`` .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.4706686.svg :target: https://doi.org/10.5281/zenodo.4706686 -This rule, as a substitute for :mod:`build_natura_raster`, downloads an already rasterized version (`natura.tiff `_) of `Natura 2000 `_ natural protection areas to reduce computation times. The file is placed into the ``resources`` sub-directory. +This rule, as a substitute for :mod:`build_natura_raster`, downloads an already rasterized version (`natura.tiff `__) of `Natura 2000 `__ natural protection areas to reduce computation times. The file is placed into the ``resources`` sub-directory. **Relevant Settings** @@ -74,7 +74,7 @@ This rule, as a substitute for :mod:`build_natura_raster`, downloads an already **Outputs** -- ``resources/natura.tiff``: Rasterized version of `Natura 2000 `_ natural protection areas to reduce computation times. +- ``resources/natura.tiff``: Rasterized version of `Natura 2000 `__ natural protection areas to reduce computation times. .. seealso:: For details see :mod:`build_natura_raster`. @@ -83,7 +83,7 @@ This rule, as a substitute for :mod:`build_natura_raster`, downloads an already Rule ``retrieve_electricity_demand`` ==================================== -This rule downloads hourly electric load data for each country from the `OPSD platform `_. +This rule downloads hourly electric load data for each country from the `OPSD platform `__. **Relevant Settings** @@ -97,7 +97,7 @@ None. Rule ``retrieve_cost_data`` ================================ -This rule downloads techno-economic assumptions from the `technology-data repository `_. +This rule downloads techno-economic assumptions from the `technology-data repository `__. **Relevant Settings** @@ -126,7 +126,7 @@ Rule ``retrieve_irena`` Rule ``retrieve_ship_raster`` ================================ -This rule downloads data on global shipping traffic density from the `World Bank Data Catalogue `_. +This rule downloads data on global shipping traffic density from the `World Bank Data Catalogue `__. **Relevant Settings** diff --git a/doc/sector.rst b/doc/sector.rst index ba3aa3e6..bdfc5386 100644 --- a/doc/sector.rst +++ b/doc/sector.rst @@ -7,8 +7,15 @@ Building Sector-Coupled Networks ########################################## -.. warning:: - This part of the documentation is under development. +The preparation process of the sector-coupled version of the PyPSA-Eur energy system model consists of a group of ``snakemake`` rules which are briefly outlined and explained in detail in the sections below. + +Not all data dependencies are shipped with the git repository. +Instead we provide separate data bundles which can be obtained +using the ``retrieve*`` rules (:ref:`data`). +Having downloaded the necessary data, + +- :mod:`add_brownfield` builds and stores the base network with all buses, HVAC lines and HVDC links, while + Rule ``add_brownfield`` ============================================================================== diff --git a/doc/simplification.rst b/doc/simplification.rst index 2272505d..cb048461 100644 --- a/doc/simplification.rst +++ b/doc/simplification.rst @@ -12,11 +12,11 @@ Simplifying Electricity Networks The simplification ``snakemake`` rules prepare **approximations** of the full model, for which it is computationally viable to co-optimize generation, storage and transmission capacities. - :mod:`simplify_network` transforms the transmission grid to a 380 kV only equivalent network, while -- :mod:`cluster_network` uses a `k-means `_ based clustering technique to partition the network into a given number of zones and then reduce the network to a representation with one bus per zone. +- :mod:`cluster_network` uses a `k-means `__ based clustering technique to partition the network into a given number of zones and then reduce the network to a representation with one bus per zone. The simplification and clustering steps are described in detail in the paper -- Jonas Hörsch and Tom Brown. `The role of spatial scale in joint optimisations of generation and transmission for European highly renewable scenarios `_), *14th International Conference on the European Energy Market*, 2017. `arXiv:1705.07617 `_, `doi:10.1109/EEM.2017.7982024 `_. +- Jonas Hörsch and Tom Brown. `The role of spatial scale in joint optimisations of generation and transmission for European highly renewable scenarios `__), *14th International Conference on the European Energy Market*, 2017. `arXiv:1705.07617 `__, `doi:10.1109/EEM.2017.7982024 `__. After simplification and clustering of the network, additional components may be appended in the rule :mod:`add_extra_components` and the network is prepared for solving in :mod:`prepare_network`. diff --git a/doc/spatial_resolution.rst b/doc/spatial_resolution.rst index a408f464..20158ab6 100644 --- a/doc/spatial_resolution.rst +++ b/doc/spatial_resolution.rst @@ -9,7 +9,7 @@ Spatial resolution ########################################## -The default nodal resolution of the model follows the electricity generation and transmission model `PyPSA-Eur `_, which clusters down the electricity transmission substations in each European country based on the k-means algorithm (See `cluster_network `_ for a complete explanation). This gives nodes which correspond to major load and generation centres (typically cities). +The default nodal resolution of the model follows the electricity generation and transmission model `PyPSA-Eur `__, which clusters down the electricity transmission substations in each European country based on the k-means algorithm (See `cluster_network `__ for a complete explanation). This gives nodes which correspond to major load and generation centres (typically cities). The total number of nodes for Europe is set in the ``config/config.yaml`` file under ``clusters``. The number of nodes can vary between 37, the number of independent countries / synchronous areas, and several hundred. With 200-300 nodes the model needs 100-150 GB RAM to solve with a commercial solver like Gurobi. @@ -21,7 +21,7 @@ Exemplary unsolved network clustered to 37 nodes: .. image:: ../graphics/elec_s_37.png -The total number of nodes for Europe is set in the ``config/config.yaml`` file under `clusters `_. The number of nodes can vary between 37, the number of independent countries/synchronous areas, and several hundred. With 200-300 nodes, the model needs 100-150 GB RAM to solve with a commercial solver like Gurobi. +The total number of nodes for Europe is set in the ``config/config.yaml`` file under `clusters `__. The number of nodes can vary between 37, the number of independent countries/synchronous areas, and several hundred. With 200-300 nodes, the model needs 100-150 GB RAM to solve with a commercial solver like Gurobi. Not all of the sectors are at the full nodal resolution, and some demand for some sectors is distributed to nodes using heuristics that need to be corrected. Some networks are copper-plated to reduce computational times. Here are some examples of how spatial resolution is set for different sectors in PyPSA-Eur-Sec: @@ -37,18 +37,18 @@ Here are some examples of how spatial resolution is set for different sectors in • Electricity demand in industry: Modeled as nodal, based on the location of industrial facilities from HotMaps database. • Industry demand (heat, chemicals, etc.) : Modeled as nodal, distributed in each country based on locations of industry from HotMaps database. -• Hydrogen network: Modeled as nodal (if activated in the `config `_ file). +• Hydrogen network: Modeled as nodal (if activated in the `config `__ file). -• Methane network: It can be modeled as a single node for Europe or it can be nodally resolved if activated in the `config `_. One node can be considered reasonable since future demand is expected to be low and no bottlenecks are expected. Also, the nodally resolved methane grid is based on SciGRID_gas data. +• Methane network: It can be modeled as a single node for Europe or it can be nodally resolved if activated in the `config `__. One node can be considered reasonable since future demand is expected to be low and no bottlenecks are expected. Also, the nodally resolved methane grid is based on SciGRID_gas data. -• Solid biomass: It can be modeled as a single node for Europe or it can be nodally resolved if activated in the `config `_. Nodal modeling includes modeling biomass potential per country (given per country, then distributed by population density within) and the transport of solid biomass between countries. +• Solid biomass: It can be modeled as a single node for Europe or it can be nodally resolved if activated in the `config `__. Nodal modeling includes modeling biomass potential per country (given per country, then distributed by population density within) and the transport of solid biomass between countries. -• CO2: It can be modeled as a single node for Europe or it can be nodally resolved with CO2 transport pipelines if activated in the `config `_. It should mentioned that in single node mode a transport and storage cost is added for sequestered CO2, the cost of which can be adjusted in the `config `_. +• CO2: It can be modeled as a single node for Europe or it can be nodally resolved with CO2 transport pipelines if activated in the `config `__. It should mentioned that in single node mode a transport and storage cost is added for sequestered CO2, the cost of which can be adjusted in the `config `__. • Carbonaceous fuels: Modeled as a single node for Europe by default, since transport costs for liquids are low and no bottlenecks are expected. Can be regionally resolved in configuration. **Electricity distribution network** -Contrary to the transmission grid, the grid topology at the distribution level (at and below 110 kV) is not included due to the very high computational burden. However, a link per node can be used (if activated in the `Config `_ file) to represent energy transferred between distribution and transmission levels at every node. In essence, the total energy capacity connecting the transmission grid and the low-voltage level is optimized. The cost assumptions for this link can be adjusted in Config file `options `_ , and is currently assumed to be 500 Eur/kW. +Contrary to the transmission grid, the grid topology at the distribution level (at and below 110 kV) is not included due to the very high computational burden. However, a link per node can be used (if activated in the `Config `__ file) to represent energy transferred between distribution and transmission levels at every node. In essence, the total energy capacity connecting the transmission grid and the low-voltage level is optimized. The cost assumptions for this link can be adjusted in Config file `options `__ , and is currently assumed to be 500 Eur/kW. Rooftop PV, heat pumps, resistive heater, home batteries chargers for passenger EVs, as well as individual heating technologies (heat pumps and resistive heaters) are connected to low-voltage level. All the remaining generation and storage technologies are connected to the transmission grid. In practice, this means that the distribution grid capacity is only extended if it is necessary to balance the mismatch between local generation and demand. diff --git a/doc/supply_demand.rst b/doc/supply_demand.rst index 8f6edcad..cc598aaf 100644 --- a/doc/supply_demand.rst +++ b/doc/supply_demand.rst @@ -11,7 +11,7 @@ An initial orientation to the supply and demand options in the model PyPSA-Eur-Sec can be found in the description of the model PyPSA-Eur-Sec-30 in the paper `Synergies of sector coupling and transmission reinforcement in a cost-optimised, highly renewable -European energy system `_ (2018). +European energy system `__ (2018). The latest version of PyPSA-Eur-Sec differs by including biomass, industry, industrial feedstocks, aviation, shipping, better carbon management, carbon capture and usage/sequestration, and gas networks. @@ -26,13 +26,13 @@ Electricity supply and demand ============================= Electricity supply and demand follows the electricity generation and -transmission model `PyPSA-Eur `_, +transmission model `PyPSA-Eur `__, except that hydrogen storage is integrated into the hydrogen supply, demand and network, and PyPSA-Eur-Sec includes CHPs. Unlike PyPSA-Eur, PyPSA-Eur-Sec does not distribution electricity demand for industry according to population and GDP, but uses the geographical data from the `Hotmaps Industrial Database -`_. +`__. Also unlike PyPSA-Eur, PyPSA-Eur-Sec subtracts existing electrified heating from the existing electricity demand, so that power-to-heat can be optimised separately. @@ -44,7 +44,7 @@ Heat demand =========== Building heating in residential and services sectors is resolved regionally, both for individual buildings and district heating systems, which include different supply options (see :ref:`heat-supply`.) -Annual heat demands per country are retrieved from `JRC-IDEES `_ and split into space and water heating. For space heating, the annual demands are converted to daily values based on the population-weighted Heating Degree Day (HDD) using the `atlite tool `_, where space heat demand is proportional to the difference between the daily average ambient temperature (read from `ERA5 `_) and a threshold temperature above which space heat demand is zero. A threshold temperature of 15 °C is assumed by default. The daily space heat demand is distributed to the hours of the day following heat demand profiles from `BDEW `_. These differ for weekdays and weekends/holidays and between residential and services demand. +Annual heat demands per country are retrieved from `JRC-IDEES `__ and split into space and water heating. For space heating, the annual demands are converted to daily values based on the population-weighted Heating Degree Day (HDD) using the `atlite tool `__, where space heat demand is proportional to the difference between the daily average ambient temperature (read from `ERA5 `__) and a threshold temperature above which space heat demand is zero. A threshold temperature of 15 °C is assumed by default. The daily space heat demand is distributed to the hours of the day following heat demand profiles from `BDEW `__. These differ for weekdays and weekends/holidays and between residential and services demand. *Space heating* @@ -54,11 +54,11 @@ The space heating demand can be exogenously reduced by retrofitting measures tha :language: yaml :lines: 205 -Co-optimsing of building renovation is also possible, if it is activated in the `config file `_. +Co-optimsing of building renovation is also possible, if it is activated in the `config file `__. Renovation of the thermal envelope reduces the space heating demand and is optimised at each node for every heat bus. Renovation measures through additional insulation material and replacement of energy inefficient windows are considered. -In a first step, costs per energy savings are estimated in `build_retro_cost.py `_. They depend on the insulation condition of the building stock and costs for renovation of the building elements. In a second step, for those cost per energy savings two possible renovation strengths are determined: a moderate renovation with lower costs, a lower maximum possible space heat savings, and an ambitious renovation with associated higher costs and higher efficiency gains. They are added by step-wise linearisation in form of two additional generations in `prepare_sector_network.py `_. +In a first step, costs per energy savings are estimated in `build_retro_cost.py `__. They depend on the insulation condition of the building stock and costs for renovation of the building elements. In a second step, for those cost per energy savings two possible renovation strengths are determined: a moderate renovation with lower costs, a lower maximum possible space heat savings, and an ambitious renovation with associated higher costs and higher efficiency gains. They are added by step-wise linearisation in form of two additional generations in `prepare_sector_network.py `__. Further information are given in the publication : - `Mitigating heat demand peaks in buildings in a highly renewable European energy system, (2021) `_. +`Mitigating heat demand peaks in buildings in a highly renewable European energy system, (2021) `__. *Water heating* @@ -66,7 +66,7 @@ Hot water demand is assumed to be constant throughout the year. *Urban and rural heating* -For every country, heat demand is split between low and high population density areas. These country-level totals are then distributed to each region in proportion to their rural and urban populations respectively. Urban areas with dense heat demand can be supplied with large-scale district heating systems. The percentage of urban heat demand that can be supplied by district heating networks as well as lump-sum losses in district heating systems is exogenously determined in the `config file `_. +For every country, heat demand is split between low and high population density areas. These country-level totals are then distributed to each region in proportion to their rural and urban populations respectively. Urban areas with dense heat demand can be supplied with large-scale district heating systems. The percentage of urban heat demand that can be supplied by district heating networks as well as lump-sum losses in district heating systems is exogenously determined in the `config file `__. *Cooling demand* @@ -96,41 +96,41 @@ Different supply options are available depending on whether demand is met centra **Urban central heat** -For large-scale district heating systems the following options are available: combined heat and power (CHP) plants consuming gas or biomass from waste and residues with and without carbon capture (CC), large-scale air-sourced heat pumps, gas and oil boilers, resistive heaters, and fuel cell CHPs. Additionally, waste heat from the `Fischer-Tropsch `_ and `Sabatier `_ processes for the production of synthetic hydrocarbons can supply district heating systems. For more detailed explanation of these processes, see :ref:`Oil-based products supply` and :ref:`Methane supply`. +For large-scale district heating systems the following options are available: combined heat and power (CHP) plants consuming gas or biomass from waste and residues with and without carbon capture (CC), large-scale air-sourced heat pumps, gas and oil boilers, resistive heaters, and fuel cell CHPs. Additionally, waste heat from the `Fischer-Tropsch `__ and `Sabatier `__ processes for the production of synthetic hydrocarbons can supply district heating systems. For more detailed explanation of these processes, see :ref:`Oil-based products supply` and :ref:`Methane supply`. **Residential and Urban decentral heat** Supply options in individual buildings include gas and oil boilers, air- and ground-sourced heat pumps, resistive heaters, and solar thermal collectors. -Ground-source heat pumps are only allowed in rural areas because of space constraints. Thus, only air- source heat pumps are allowed in urban areas. This is a conservative assumption, since there are many possible sources of low-temperature heat that could be tapped in cities (e.g. waste water, ground water, or natural bodies of water). Costs, lifetimes and efficiencies for these technologies are retrieved from the `technology-data repository `_. +Ground-source heat pumps are only allowed in rural areas because of space constraints. Thus, only air- source heat pumps are allowed in urban areas. This is a conservative assumption, since there are many possible sources of low-temperature heat that could be tapped in cities (e.g. waste water, ground water, or natural bodies of water). Costs, lifetimes and efficiencies for these technologies are retrieved from the `technology-data repository `__. -Below are more detailed explanations for each heating supply component, all of which are modelled as `links `_ in PyPSA-Eur-Sec. +Below are more detailed explanations for each heating supply component, all of which are modelled as `links `__ in PyPSA-Eur-Sec. .. _Large-scale CHP: **Large-scale CHP** -Large Combined Heat and Power plants are included in the model if it is specified in the `config file `_. +Large Combined Heat and Power plants are included in the model if it is specified in the `config file `__. -CHPs are based on back pressure plants operating with a fixed ratio of electricity to heat output. The efficiencies of each are given on the back pressure line, where the back pressure coefficient cb is the electricity output divided by the heat output. (For a more complete explanation of the operation of CHPs refer to the study by Dahl et al. : `Cost sensitivity of optimal sector-coupled district heating production systems `_. +CHPs are based on back pressure plants operating with a fixed ratio of electricity to heat output. The efficiencies of each are given on the back pressure line, where the back pressure coefficient cb is the electricity output divided by the heat output. (For a more complete explanation of the operation of CHPs refer to the study by Dahl et al. : `Cost sensitivity of optimal sector-coupled district heating production systems `__. PyPSA-Eur-Sec includes CHP plants fueled by methane and solid biomass from waste and residues. Hydrogen fuel cells also produce both electricity and heat. -The methane CHP is modeled on the Danish Energy Agency (DEA) “Gas turbine simple cycle (large)” while the solid biomass CHP is based on the DEA’s “09b Wood Pellets Medium”. For biomass CHP, cb = `0.46 `_ , whereas for gas CHP, cb = `1 `_. +The methane CHP is modeled on the Danish Energy Agency (DEA) “Gas turbine simple cycle (large)” while the solid biomass CHP is based on the DEA’s “09b Wood Pellets Medium”. For biomass CHP, cb = `0.46 `__ , whereas for gas CHP, cb = `1 `__. -NB: The old PyPSA-Eur-Sec-30 model assumed an extraction plant (like the DEA coal CHP) for gas which has flexible production of heat and electricity within the feasibility diagram of Figure 4 in the study by `Brown et al. `_ We have switched to the DEA back pressure plants since these are more common for smaller plants for biomass, and because the extraction plants were on the back pressure line for 99.5% of the time anyway. The plants were all changed to back pressure in PyPSA-Eur-Sec v0.4.0. +NB: The old PyPSA-Eur-Sec-30 model assumed an extraction plant (like the DEA coal CHP) for gas which has flexible production of heat and electricity within the feasibility diagram of Figure 4 in the study by `Brown et al. `__ We have switched to the DEA back pressure plants since these are more common for smaller plants for biomass, and because the extraction plants were on the back pressure line for 99.5% of the time anyway. The plants were all changed to back pressure in PyPSA-Eur-Sec v0.4.0. **Micro-CHP** -PyPSA-Eur-Sec allows individual buildings to make use of `micro gas CHPs `_ that are assumed to be installed at the distribution grid level. +PyPSA-Eur-Sec allows individual buildings to make use of `micro gas CHPs `__ that are assumed to be installed at the distribution grid level. **Heat pumps** -The coefficient of performance (COP) of air- and ground-sourced heat pumps depends on the ambient or soil temperature respectively. Hence, the COP is a time-varying parameter (refer to `Config `_ file). Generally, the COP will be lower during winter when temperatures are low. Because the ambient temperature is more volatile than the soil temperature, the COP of ground-sourced heat pumps is less variable. Moreover, the COP depends on the difference between the source and sink temperatures: +The coefficient of performance (COP) of air- and ground-sourced heat pumps depends on the ambient or soil temperature respectively. Hence, the COP is a time-varying parameter (refer to `Config `__ file). Generally, the COP will be lower during winter when temperatures are low. Because the ambient temperature is more volatile than the soil temperature, the COP of ground-sourced heat pumps is less variable. Moreover, the COP depends on the difference between the source and sink temperatures: .. math:: \Delta T = T_{sink} − T_{source} -For the sink water temperature Tsink we assume 55 °C [`Config `_ file]. For the time- and location-dependent source temperatures Tsource, we rely on the `ERA5 `_ reanalysis weather data. The temperature differences are converted into COP time series using results from a regression analysis performed in the study by `Stafell et al. `_. For air-sourced heat pumps (ASHP), we use the function: +For the sink water temperature Tsink we assume 55 °C [`Config `__ file]. For the time- and location-dependent source temperatures Tsource, we rely on the `ERA5 `__ reanalysis weather data. The temperature differences are converted into COP time series using results from a regression analysis performed in the study by `Stafell et al. `__. For air-sourced heat pumps (ASHP), we use the function: .. math:: COP (\Delta T) = 6.81 - 0.121\Delta T + 0.000630\Delta T^2 @@ -142,44 +142,44 @@ for ground-sourced heat pumps (GSHP), we use the function: **Resistive heaters** -Can be activated in Config from the `boilers `_ option. -Resistive heaters produce heat with a fixed conversion efficiency (refer to `Technology-data repository `_ ). +Can be activated in Config from the `boilers `__ option. +Resistive heaters produce heat with a fixed conversion efficiency (refer to `Technology-data repository `__ ). **Gas, oil, and biomass boilers** -Can be activated in Config from the `boilers `_ , `oil boilers `_ , and `biomass boiler `_ option. +Can be activated in Config from the `boilers `__ , `oil boilers `__ , and `biomass boiler `__ option. Similar to resistive heaters, boilers have a fixed efficiency and produce heat using gas, oil or biomass. **Solar thermal collectors** -Can be activated in the config file from the `solar_thermal `_ option. -Solar thermal profiles are built based on weather data and also have the `options `_ for setting the sky model and the orientation of the panel in the config file, which are then used by the atlite tool to calculate the solar resource time series. +Can be activated in the config file from the `solar_thermal `__ option. +Solar thermal profiles are built based on weather data and also have the `options `__ for setting the sky model and the orientation of the panel in the config file, which are then used by the atlite tool to calculate the solar resource time series. **Waste heat from Fuel Cells, Methanation and Fischer-Tropsch plants** -Waste heat from `fuel cells `_ in addition to processes like `Fischer-Tropsch `_, methanation, and Direct Air Capture (DAC) is dumped into district heating networks. +Waste heat from `fuel cells `__ in addition to processes like `Fischer-Tropsch `__, methanation, and Direct Air Capture (DAC) is dumped into district heating networks. **Existing heating capacities and decommissioning** -For the myopic transition paths, capacities already existing for technologies supplying heat are retrieved from `“Mapping and analyses of the current and future (2020 - 2030)” `_ . For the sake of simplicity, coal, oil and gas boiler capacities are assimilated to gas boilers. Besides that, existing capacities for heat resistors, air-sourced and ground-sourced heat pumps are included in the model. For heating capacities, 25% of existing capacities in 2015 are assumed to be decommissioned in every 5-year time step after 2020. +For the myopic transition paths, capacities already existing for technologies supplying heat are retrieved from `“Mapping and analyses of the current and future (2020 - 2030)” `__ . For the sake of simplicity, coal, oil and gas boiler capacities are assimilated to gas boilers. Besides that, existing capacities for heat resistors, air-sourced and ground-sourced heat pumps are included in the model. For heating capacities, 25% of existing capacities in 2015 are assumed to be decommissioned in every 5-year time step after 2020. **Thermal Energy Storage** -Activated in Config from the `tes `_ option. +Activated in Config from the `tes `__ option. -Thermal energy can be stored in large water pits associated with district heating systems and individual thermal energy storage (TES), i.e., small water tanks. Water tanks are modelled as `stores `_. -A thermal energy density of 46.8 kWh :math:`_{th}`/m3 is assumed, corresponding to a temperature difference of 40 K. The decay of thermal energy in the stores: 1- :math:`e^{-1/24τ}` is assumed to have a time constant of  τ=180 days for central TES and  τ=3 days for individual TES, both modifiable through `tes_tau `_ in config file. Charging and discharging efficiencies are 90% due to pipe losses. +Thermal energy can be stored in large water pits associated with district heating systems and individual thermal energy storage (TES), i.e., small water tanks. Water tanks are modelled as `stores `__. +A thermal energy density of 46.8 kWh :math:`_{th}`/m3 is assumed, corresponding to a temperature difference of 40 K. The decay of thermal energy in the stores: 1- :math:`e^{-1/24τ}` is assumed to have a time constant of  τ=180 days for central TES and  τ=3 days for individual TES, both modifiable through `tes_tau `__ in config file. Charging and discharging efficiencies are 90% due to pipe losses. **Retrofitting of the thermal envelope of buildings** -Co-optimising building renovation is only enabled if in the `config `_ file. To reduce the computational burden, +Co-optimising building renovation is only enabled if in the `config `__ file. To reduce the computational burden, default setting is set as false. Renovation of the thermal envelope reduces the space heating demand and is optimised at each node for every heat bus. Renovation measures through additional insulation material and replacement of energy inefficient windows are considered. -In a first step, costs per energy savings are estimated in the `build_retro_cost.py `_ script. +In a first step, costs per energy savings are estimated in the `build_retro_cost.py `__ script. They depend on the insulation condition of the building stock and costs for renovation of the building elements. In a second step, for those cost per energy savings two possible renovation @@ -187,12 +187,12 @@ strengths are determined: a moderate renovation with lower costs and lower maximum possible space heat savings, and an ambitious renovation with associated higher costs and higher efficiency gains. They are added by step-wise linearisation in form of two additional generations in -the `prepare_sector_network.py `_ script. +the `prepare_sector_network.py `__ script. Settings in the ``config/config.yaml`` concerning the endogenously optimisation of building -renovation include `cost factor `_, `interest rate `_, `annualised cost `_, `tax weighting `_, and `construction index `_. +renovation include `cost factor `__, `interest rate `__, `annualised cost `__, `tax weighting `__, and `construction index `__. -Further information are given in the study by Zeyen et al. : `Mitigating heat demand peaks in buildings in a highly renewable European energy system, (2021) `_. +Further information are given in the study by Zeyen et al. : `Mitigating heat demand peaks in buildings in a highly renewable European energy system, (2021) `__. .. _Hydrogen demand: @@ -200,7 +200,7 @@ Hydrogen demand ============================= Hydrogen is consumed in the industry sector (see :ref:`Industry demand`) to produce ammonia (see :ref:`Chemicals Industry`) and direct reduced iron (DRI) (see :ref:`Iron and Steel`). Hydrogen is also consumed to produce synthetic methane (see :ref:`Methane supply`) and liquid hydrocarbons (see :ref:`Oil-based products supply`) which have multiple uses in industry and other sectors. -Hydrogen is also used for transport applications (see :ref:`Transportation`), where it is exogenously fixed. It is used in `heavy-duty land transport `_ and as liquified hydrogen in the shipping sector (see :ref:`Shipping`). Furthermore, stationary fuel cells may re-electrify hydrogen (with waste heat as a byproduct) to balance renewable fluctuations (see :ref:`Electricity supply and demand`). The waste heat from the stationary fuel cells can be used in `district-heating systems `_. +Hydrogen is also used for transport applications (see :ref:`Transportation`), where it is exogenously fixed. It is used in `heavy-duty land transport `__ and as liquified hydrogen in the shipping sector (see :ref:`Shipping`). Furthermore, stationary fuel cells may re-electrify hydrogen (with waste heat as a byproduct) to balance renewable fluctuations (see :ref:`Electricity supply and demand`). The waste heat from the stationary fuel cells can be used in `district-heating systems `__. .. _Hydrogen supply: @@ -220,7 +220,7 @@ combined with a water-gas shift reaction CO + H_2O \xrightarrow{} CO_2 + H_2 -SMR is included `here `_. +SMR is included `here `__. PyPSA-Eur-Sec allows this route of :math:`H_2` production with and without [carbon capture (CC)] (see :ref:`Carbon dioxide capture, usage and sequestration (CCU/S)`). These routes are often referred to as blue and grey hydrogen. Here, methane input can be both of fossil or synthetic origin. Green hydrogen can be produced by electrolysis to split water into hydrogen and oxygen @@ -234,12 +234,12 @@ For the electrolysis, alkaline electrolysers are chosen since they have lower co **Transport** -Hydrogen is transported by pipelines. :math:`H_2` pipelines are endogenously generated, either via a greenfield :math:`H_2` network, or by `retrofitting natural gas pipelines `_). Retrofitting is implemented in such a way that for every unit of decommissioned gas pipeline, a share (60% is used in the study by `Neumann et al. `_) of its nominal capacity (exogenously determined in the `config file `_.) is available for hydrogen transport. When the gas network is not resolved, this input denotes the potential for gas pipelines repurposed into hydrogen pipelines. +Hydrogen is transported by pipelines. :math:`H_2` pipelines are endogenously generated, either via a greenfield :math:`H_2` network, or by `retrofitting natural gas pipelines `__). Retrofitting is implemented in such a way that for every unit of decommissioned gas pipeline, a share (60% is used in the study by `Neumann et al. `__) of its nominal capacity (exogenously determined in the `config file `__.) is available for hydrogen transport. When the gas network is not resolved, this input denotes the potential for gas pipelines repurposed into hydrogen pipelines. New pipelines can be built additionally on all routes where there currently is a gas or electricity network connection. These new pipelines will be built where no sufficient retrofitting options are available. The capacities of new and repurposed pipelines are a result of the optimisation. **Storage** -Hydrogen can be stored in overground steel tanks or `underground salt caverns `_. For the latter, energy storage capacities in every country are limited to the potential estimation for onshore salt caverns within `50 km `_ of shore to avoid environmental issues associated with brine solution disposal. Underground storage potentials for hydrogen in European salt caverns is acquired from `Caglayan et al. `_ +Hydrogen can be stored in overground steel tanks or `underground salt caverns `__. For the latter, energy storage capacities in every country are limited to the potential estimation for onshore salt caverns within `50 km `__ of shore to avoid environmental issues associated with brine solution disposal. Underground storage potentials for hydrogen in European salt caverns is acquired from `Caglayan et al. `__ .. _Methane demand: @@ -253,7 +253,7 @@ Methane is used in individual and large-scale gas boilers, in CHP plants with an Methane supply =================================== -In addition to methane from fossil origins, the model also considers biogenic and synthetic sources. `The gas network can either be modelled, or it can be assumed that gas transport is not limited `_. If gas infrastructure is regionally resolved, fossil gas can enter the system only at existing and planned LNG terminals, pipeline entry-points, and intra- European gas extraction sites, which are retrieved from the SciGRID Gas IGGIELGN dataset and the GEM Wiki. +In addition to methane from fossil origins, the model also considers biogenic and synthetic sources. `The gas network can either be modelled, or it can be assumed that gas transport is not limited `__. If gas infrastructure is regionally resolved, fossil gas can enter the system only at existing and planned LNG terminals, pipeline entry-points, and intra- European gas extraction sites, which are retrieved from the SciGRID Gas IGGIELGN dataset and the GEM Wiki. Biogas can be upgraded to methane. Synthetic methane can be produced by processing hydrogen and captures :math:`CO_2` in the Sabatier reaction @@ -275,7 +275,7 @@ The following figure shows the unclustered European gas transmission network bas Biomass Supply ===================== -Biomass supply potentials for each European country are taken from the `JRC ENSPRESO database `_ where data is available for various years (2010, 2020, 2030, 2040 and 2050) and scenarios (low, medium, high). No biomass import from outside Europe is assumed. More information on the data set can be found `here `_. +Biomass supply potentials for each European country are taken from the `JRC ENSPRESO database `__ where data is available for various years (2010, 2020, 2030, 2040 and 2050) and scenarios (low, medium, high). No biomass import from outside Europe is assumed. More information on the data set can be found `here `__. .. _Biomass demand: @@ -283,19 +283,19 @@ Biomass demand ===================== -Biomass supply potentials for every NUTS2 region are taken from the `JRC ENSPRESO database `_ where data is available for various years (2010, 2020, 2030, 2040 and 2050) and different availability scenarios (low, medium, high). No biomass import from outside Europe is assumed. More information on the data set can be found `here `_. The data for NUTS2 regions is mapped to PyPSA-Eur-Sec model regions in proportion to the area overlap. +Biomass supply potentials for every NUTS2 region are taken from the `JRC ENSPRESO database `__ where data is available for various years (2010, 2020, 2030, 2040 and 2050) and different availability scenarios (low, medium, high). No biomass import from outside Europe is assumed. More information on the data set can be found `here `__. The data for NUTS2 regions is mapped to PyPSA-Eur-Sec model regions in proportion to the area overlap. -The desired scenario can be selected in the PyPSA-Eur-Sec `configuration `_. The script for building the biomass potentials from the JRC ENSPRESO data base is located `here `_. Consult the script to see the keywords that specify the scenario options. +The desired scenario can be selected in the PyPSA-Eur-Sec `configuration `__. The script for building the biomass potentials from the JRC ENSPRESO data base is located `here `__. Consult the script to see the keywords that specify the scenario options. -The `configuration `_ also allows the user to define how the various types of biomass are used in the model by using the following categories: biogas, solid biomass, and not included. Feedstocks categorized as biogas, typically manure and sludge waste, are available to the model as biogas, which can be upgraded to biomethane. Feedstocks categorized as solid biomass, e.g. secondary forest residues or municipal waste, are available for combustion in combined-heat-and power (CHP) plants and for medium temperature heat (below 500 °C) applications in industry. It can also converted to gas or liquid fuels. +The `configuration `__ also allows the user to define how the various types of biomass are used in the model by using the following categories: biogas, solid biomass, and not included. Feedstocks categorized as biogas, typically manure and sludge waste, are available to the model as biogas, which can be upgraded to biomethane. Feedstocks categorized as solid biomass, e.g. secondary forest residues or municipal waste, are available for combustion in combined-heat-and power (CHP) plants and for medium temperature heat (below 500 °C) applications in industry. It can also converted to gas or liquid fuels. Feedstocks labeled as not included are ignored by the model. -A `typical use case for biomass `_ would be the medium availability scenario for 2030 where only residues from agriculture and forestry as well as biodegradable municipal waste are considered as energy feedstocks. Fuel crops are avoided because they compete with scarce land for food production, while primary wood, as well as wood chips and pellets, are avoided because of concerns about sustainability. See the supporting materials of the `paper `_ for more details. +A `typical use case for biomass `__ would be the medium availability scenario for 2030 where only residues from agriculture and forestry as well as biodegradable municipal waste are considered as energy feedstocks. Fuel crops are avoided because they compete with scarce land for food production, while primary wood, as well as wood chips and pellets, are avoided because of concerns about sustainability. See the supporting materials of the `paper `__ for more details. *Solid biomass conversion and use* @@ -303,19 +303,19 @@ A `typical use case for biomass `_ would be th Solid biomass can be used directly to provide process heat up to 500˚C in the industry. It can also be burned in CHP plants and boilers associated with heating systems. These technologies are described elsewhere (see :ref:`Large-scale CHP` and :ref:`Industry demand`). -Solid biomass can be converted to syngas if the option is enabled in the `config file `_. In this case the model will enable the technology BioSNG both with and without the option for carbon capture (see `Technology-data repository `_). +Solid biomass can be converted to syngas if the option is enabled in the `config file `__. In this case the model will enable the technology BioSNG both with and without the option for carbon capture (see `Technology-data repository `__). -Liquefaction of solid biomass `can be enabled `_ allowing the model to convert it into liquid hydrocarbons that can replace conventional oil products. This technology also comes with and without carbon capture (see `Technology-data repository `_). +Liquefaction of solid biomass `can be enabled `__ allowing the model to convert it into liquid hydrocarbons that can replace conventional oil products. This technology also comes with and without carbon capture (see `Technology-data repository `__). *Transport of solid biomass* -The transport of solid biomass can either be assumed unlimited between countries or it can be associated with a country specific cost per MWh/km. In the config file these options are toggled `here `_. If the option is off, use of solid biomass is transport. If it is turned on, a biomass transport network will be `created `_ between all nodes. This network resembles road transport of biomass and the cost of transportation is a variable cost which is proportional to distance and a country specific cost per MWh/km. The latter is `estimated `_ from the country specific costs per ton/km used in the publication `“The JRC-EU-TIMES model. Bioenergy potentials for EU and neighbouring countries” `_. +The transport of solid biomass can either be assumed unlimited between countries or it can be associated with a country specific cost per MWh/km. In the config file these options are toggled `here `__. If the option is off, use of solid biomass is transport. If it is turned on, a biomass transport network will be `created `__ between all nodes. This network resembles road transport of biomass and the cost of transportation is a variable cost which is proportional to distance and a country specific cost per MWh/km. The latter is `estimated `__ from the country specific costs per ton/km used in the publication `“The JRC-EU-TIMES model. Bioenergy potentials for EU and neighbouring countries” `__. *Biogas transport and use* -Biogas will be aggregated into a common European resources if a gas network is not modelled explicitly, i.e., the `gas_network `_ option is set to false. If, on the other hand, a gas network is included, the biogas potential will be associated with each node of origin. +Biogas will be aggregated into a common European resources if a gas network is not modelled explicitly, i.e., the `gas_network `__ option is set to false. If, on the other hand, a gas network is included, the biogas potential will be associated with each node of origin. The model can only use biogas by first upgrading it to natural gas quality [see :ref:`Methane supply`] (bio methane) which is fed into the general gas network. .. _Oil-based products demand: @@ -338,7 +338,7 @@ Oil-based products can be either of fossil origin or synthetically produced by c 𝑛CO+(2𝑛+1)H_2 → C_{n}H_{2n + 2} +𝑛H_2O -with costs as included from the `technology-data repository `_. The waste heat from the Fischer-Tropsch process is supplied to `district heating networks `_. The share of fossil and synthetic oil is an optimisation result depending on the techno-economic assumptions. +with costs as included from the `technology-data repository `__. The waste heat from the Fischer-Tropsch process is supplied to `district heating networks `__. The share of fossil and synthetic oil is an optimisation result depending on the techno-economic assumptions. *Oil-based transport* @@ -361,24 +361,24 @@ The Subsection overview below provides a general description of the modelling ap Greenhouse gas emissions associated with industry can be classified into energy-related and process-related emissions. Today, fossil fuels are used for process heat energy in the chemicals industry, but also as a non-energy feedstock for chemicals like ammonia ( :math:`NH_3`), ethylene ( :math:`C_2H_4`) and methanol ( :math:`CH_3OH`). Energy-related emissions can be curbed by using low-emission energy sources. The only option to reduce process-related emissions is by using an alternative manufacturing process or by assuming a certain rate of recycling so that a lower amount of virgin material is needed. -The overarching modelling procedure can be described as follows. First, the energy demands and process emissions for every unit of material output are estimated based on data from the `JRC-IDEES database `_ and the fuel and process switching described in the subsequent sections. Second, the 2050 energy demands and process emissions are calculated using the per-unit-of-material ratios based on the industry transformations and the `country-level material production in 2015 `_, assuming constant material demand. +The overarching modelling procedure can be described as follows. First, the energy demands and process emissions for every unit of material output are estimated based on data from the `JRC-IDEES database `__ and the fuel and process switching described in the subsequent sections. Second, the 2050 energy demands and process emissions are calculated using the per-unit-of-material ratios based on the industry transformations and the `country-level material production in 2015 `__, assuming constant material demand. -Missing or too coarsely aggregated data in the JRC-IDEES database is supplemented with additional datasets: `Eurostat energy balances `_, `United States `_, `Geological Survey `_ for ammonia production, `DECHEMA `_ for methanol and chlorine, and `national statistics from Switzerland `_. +Missing or too coarsely aggregated data in the JRC-IDEES database is supplemented with additional datasets: `Eurostat energy balances `__, `United States `__, `Geological Survey `__ for ammonia production, `DECHEMA `__ for methanol and chlorine, and `national statistics from Switzerland `__. Where there are fossil and electrified alternatives for the same process (e.g. in glass manufacture or drying), we assume that the process is completely electrified. Current electricity demands (lighting, air compressors, motor drives, fans, pumps) will remain electric. Processes that require temperatures below 500 °C are supplied with solid biomass, since we assume that residues and wastes are not suitable for high-temperature applications. We see solid biomass use primarily in the pulp and paper industry, where it is already widespread, and in food, beverages and tobacco, where it replaces natural gas. Industries which require high temperatures (above 500 °C), such as metals, chemicals and non-metallic minerals are either electrified where suitable processes already exist, or the heat is provided with synthetic methane. Hydrogen for high-temperature process heat is not part of the model currently. -Where process heat is required, our approach depends on the necessary temperature. For example, due to the high share of high-temperature process heat demand (see `Naegler et al. `_ and `Rehfeldt el al. `_), we disregard geothermal and solar thermal energy as sources for process heat since they cannot attain high-temperature heat. +Where process heat is required, our approach depends on the necessary temperature. For example, due to the high share of high-temperature process heat demand (see `Naegler et al. `__ and `Rehfeldt el al. `__), we disregard geothermal and solar thermal energy as sources for process heat since they cannot attain high-temperature heat. -The following figure shows the final consumption of energy and non-energy feedstocks in industry today in comparison to the scenario in 2050 assumed in `Neumann et al `_. +The following figure shows the final consumption of energy and non-energy feedstocks in industry today in comparison to the scenario in 2050 assumed in `Neumann et al `__. .. image:: ../graphics/fec_industry_today_tomorrow.png The following figure shows the process emissions in industry today (top bar) and in 2050 without -carbon capture (bottom bar) assumed in `Neumann et al `_. +carbon capture (bottom bar) assumed in `Neumann et al `__. @@ -386,7 +386,7 @@ carbon capture (bottom bar) assumed in `Neumann et al `_, which is illustrated in the figure below. This open database includes georeferenced industrial sites of energy-intensive industry sectors in EU28, including cement, basic chemicals, glass, iron and steel, non-ferrous metals, non-metallic minerals, paper, and refineries subsectors. The use of this spatial dataset enables the calculation of regional and process-specific energy demands. This approach assumes that there will be no significant migration of energy-intensive industries. +Inside each country the industrial demand is then distributed using the `Hotmaps Industrial Database `__, which is illustrated in the figure below. This open database includes georeferenced industrial sites of energy-intensive industry sectors in EU28, including cement, basic chemicals, glass, iron and steel, non-ferrous metals, non-metallic minerals, paper, and refineries subsectors. The use of this spatial dataset enables the calculation of regional and process-specific energy demands. This approach assumes that there will be no significant migration of energy-intensive industries. .. image:: ../graphics/hotmaps.png @@ -395,7 +395,7 @@ Inside each country the industrial demand is then distributed using the `Hotmaps **Iron and Steel** -Two alternative routes are used today to manufacture steel in Europe. The primary route (integrated steelworks) represents 60% of steel production, while the secondary route (electric arc furnaces, EAF), represents the other 40% `(Lechtenböhmer et. al) `_. +Two alternative routes are used today to manufacture steel in Europe. The primary route (integrated steelworks) represents 60% of steel production, while the secondary route (electric arc furnaces, EAF), represents the other 40% `(Lechtenböhmer et. al) `__. The primary route uses blast furnaces in which coke is used to reduce iron ore into molten iron, which is then converted into steel: @@ -415,9 +415,9 @@ The primary route uses blast furnaces in which coke is used to reduce iron ore i FeO + CO \xrightarrow{} Fe + CO_2 -The primary route of steelmaking implies large process emissions of 0.22 t :math:`_{CO_2}` /t of steel, amounting to 7% of global greenhouse gas emissions `(Vogl et. al) `_. +The primary route of steelmaking implies large process emissions of 0.22 t :math:`_{CO_2}` /t of steel, amounting to 7% of global greenhouse gas emissions `(Vogl et. al) `__. -In the secondary route, electric arc furnaces are used to melt scrap metal. This limits the :math:`CO_2` emissions to the burning of graphite electrodes `(Friedrichsen et. al) `_, and reduces process emissions to 0.03 t :math:`_{CO_2}` /t of steel. +In the secondary route, electric arc furnaces are used to melt scrap metal. This limits the :math:`CO_2` emissions to the burning of graphite electrodes `(Friedrichsen et. al) `__, and reduces process emissions to 0.03 t :math:`_{CO_2}` /t of steel. We assume that the primary route can be replaced by a third route in 2050, using direct reduced iron (DRI) and subsequent processing in an EAF. @@ -433,10 +433,10 @@ We assume that the primary route can be replaced by a third route in 2050, using FeO + H_2 \xrightarrow{} Fe + H_2O -This circumvents the process emissions associated with the use of coke. For hydrogen- based DRI, we assume energy requirements of 1.7 MWh :math:`_{H_2}` /t steel `(Vogl et. al) `_ and 0.322 MWh :math:`_{el}`/t steel `(HYBRIT 2016) `_. +This circumvents the process emissions associated with the use of coke. For hydrogen- based DRI, we assume energy requirements of 1.7 MWh :math:`_{H_2}` /t steel `(Vogl et. al) `__ and 0.322 MWh :math:`_{el}`/t steel `(HYBRIT 2016) `__. -The share of steel produced via the primary route is exogenously set in the `config file `_. The share of steel obtained via hydrogen-based DRI plus EAF is also set exogenously in the `config file `_. The remaining share is manufactured through the secondary route using scrap metal in EAF. Bioenergy as alternative to coke in blast furnaces is not considered in the model (`Mandova et.al `_, `Suopajärvi et.al `_). +The share of steel produced via the primary route is exogenously set in the `config file `__. The share of steel obtained via hydrogen-based DRI plus EAF is also set exogenously in the `config file `__. The remaining share is manufactured through the secondary route using scrap metal in EAF. Bioenergy as alternative to coke in blast furnaces is not considered in the model (`Mandova et.al `__, `Suopajärvi et.al `__). For the remaining subprocesses in this sector, the following transformations are assumed. Methane is used as energy source for the smelting process. Activities associated with furnaces, refining and rolling, and product finishing are electrified assuming the current efficiency values for these cases. These transformations result in changes in process emissions as outlined in the process emissions figure presented in the industry overview section (see :ref:`Overview`). @@ -446,28 +446,28 @@ For the remaining subprocesses in this sector, the following transformations are The chemicals industry includes a wide range of diverse industries, including the production of basic organic compounds (olefins, alcohols, aromatics), basic inorganic compounds (ammonia, chlorine), polymers (plastics), and end-user products (cosmetics, pharmaceutics). -The chemicals industry consumes large amounts of fossil-fuel based feedstocks (see `Levi et. al `_), which can also be produced from renewables as outlined for hydrogen (see :ref:`Hydrogen supply`), for methane (see :ref:`Methane supply`), and for oil-based products (see :ref:`Oil-based products supply`). The ratio between synthetic and fossil-based fuels used in the industry is an endogenous result of the optimisation. +The chemicals industry consumes large amounts of fossil-fuel based feedstocks (see `Levi et. al `__), which can also be produced from renewables as outlined for hydrogen (see :ref:`Hydrogen supply`), for methane (see :ref:`Methane supply`), and for oil-based products (see :ref:`Oil-based products supply`). The ratio between synthetic and fossil-based fuels used in the industry is an endogenous result of the optimisation. -The basic chemicals consumption data from the `JRC IDEES `_ database comprises high- value chemicals (ethylene, propylene and BTX), chlorine, methanol and ammonia. However, it is necessary to separate out these chemicals because their current and future production routes are different. +The basic chemicals consumption data from the `JRC IDEES `__ database comprises high- value chemicals (ethylene, propylene and BTX), chlorine, methanol and ammonia. However, it is necessary to separate out these chemicals because their current and future production routes are different. -Statistics for the production of ammonia, which is commonly used as a fertilizer, are taken from the `USGS `_ for every country. Ammonia can be made from hydrogen and nitrogen using the Haber-Bosch process. +Statistics for the production of ammonia, which is commonly used as a fertilizer, are taken from the `USGS `__ for every country. Ammonia can be made from hydrogen and nitrogen using the Haber-Bosch process. .. math:: N_2 + 3H_2 \xrightarrow{} 2NH_3 -The Haber-Bosch process is not explicitly represented in the model, such that demand for ammonia enters the model as a demand for hydrogen ( 6.5 MWh :math:`_{H_2}` / t :math:`_{NH_3}` ) and electricity ( 1.17 MWh :math:`_{el}` /t :math:`_{NH_3}` ) (see `Wang et. al `_). Today, natural gas dominates in Europe as the source for the hydrogen used in the Haber-Bosch process, but the model can choose among the various hydrogen supply options described in the hydrogen section (see :ref:`Hydrogen supply`) +The Haber-Bosch process is not explicitly represented in the model, such that demand for ammonia enters the model as a demand for hydrogen ( 6.5 MWh :math:`_{H_2}` / t :math:`_{NH_3}` ) and electricity ( 1.17 MWh :math:`_{el}` /t :math:`_{NH_3}` ) (see `Wang et. al `__). Today, natural gas dominates in Europe as the source for the hydrogen used in the Haber-Bosch process, but the model can choose among the various hydrogen supply options described in the hydrogen section (see :ref:`Hydrogen supply`) -The total production and specific energy consumption of chlorine and methanol is taken from a `DECHEMA report `_. According to this source, the production of chlorine amounts to 9.58 MtCl/a, which is assumed to require electricity at 3.6 MWh :math:`_{el}`/t of chlorine and yield hydrogen at 0.937 MWh :math:`_{H_2}`/t of chlorine in the chloralkali process. The production of methanol adds up to 1.5 MtMeOH/a, requiring electricity at 0.167 MWh :math:`_{el}`/t of methanol and methane at 10.25 MWh :math:`_{CH_4}`/t of methanol. +The total production and specific energy consumption of chlorine and methanol is taken from a `DECHEMA report `__. According to this source, the production of chlorine amounts to 9.58 MtCl/a, which is assumed to require electricity at 3.6 MWh :math:`_{el}`/t of chlorine and yield hydrogen at 0.937 MWh :math:`_{H_2}`/t of chlorine in the chloralkali process. The production of methanol adds up to 1.5 MtMeOH/a, requiring electricity at 0.167 MWh :math:`_{el}`/t of methanol and methane at 10.25 MWh :math:`_{CH_4}`/t of methanol. -The production of ammonia, methanol, and chlorine production is deducted from the JRC IDEES basic chemicals, leaving the production totals of high-value chemicals. For this, we assume that the liquid hydrocarbon feedstock comes from synthetic or fossil- origin naphtha (14 MWh :math:`_{naphtha}`/t of HVC, similar to `Lechtenböhmer et al `_), ignoring the methanol-to-olefin route. Furthermore, we assume the following transformations of the energy-consuming processes in the production of plastics: the final energy consumption in steam processing is converted to methane since requires temperature above 500 °C (4.1 MWh :math:`_{CH_4}` /t of HVC, see `Rehfeldt et al. `_); and the remaining processes are electrified using the current efficiency of microwave for high-enthalpy heat processing, electric furnaces, electric process cooling and electric generic processes (2.85 MWh :math:`_{el}`/t of HVC). +The production of ammonia, methanol, and chlorine production is deducted from the JRC IDEES basic chemicals, leaving the production totals of high-value chemicals. For this, we assume that the liquid hydrocarbon feedstock comes from synthetic or fossil- origin naphtha (14 MWh :math:`_{naphtha}`/t of HVC, similar to `Lechtenböhmer et al `__), ignoring the methanol-to-olefin route. Furthermore, we assume the following transformations of the energy-consuming processes in the production of plastics: the final energy consumption in steam processing is converted to methane since requires temperature above 500 °C (4.1 MWh :math:`_{CH_4}` /t of HVC, see `Rehfeldt et al. `__); and the remaining processes are electrified using the current efficiency of microwave for high-enthalpy heat processing, electric furnaces, electric process cooling and electric generic processes (2.85 MWh :math:`_{el}`/t of HVC). The process emissions from feedstock in the chemical industry are as high as 0.369 t :math:`_{CO_2}`/t of ethylene equivalent. We consider process emissions for all the material output, which is a conservative approach since it assumes that all plastic-embedded :math:`CO_2` will eventually be released into the atmosphere. However, plastic disposal in landfilling will avoid, or at least delay, associated :math:`CO_2` emissions. -Circular economy practices drastically reduce the amount of primary feedstock needed for the production of plastics in the model (see `Kullmann et al. `_, `Meys et al. (2021) `_, `Meys et al. (2020) `_, `Gu et al. `_) and consequently, also the energy demands and level of process emission. The percentage of plastics that are assumed to be mechanically recycled can be selected in the `config file `_, as well as -the percentage that is chemically recycled, see `config file `_ The energy consumption for those recycling processes are respectively 0.547 MWh :math:`_{el}`/t of HVC (as indicated in the `config file `_) (`Meys et al. (2020) `_), and 6.9 MWh :math:`_{el}`/t of HVC (as indicated in the `config file `_) based on pyrolysis and electric steam cracking (see `Materials Economics `_ report). +Circular economy practices drastically reduce the amount of primary feedstock needed for the production of plastics in the model (see `Kullmann et al. `__, `Meys et al. (2021) `__, `Meys et al. (2020) `__, `Gu et al. `__) and consequently, also the energy demands and level of process emission. The percentage of plastics that are assumed to be mechanically recycled can be selected in the `config file `__, as well as +the percentage that is chemically recycled, see `config file `__ The energy consumption for those recycling processes are respectively 0.547 MWh :math:`_{el}`/t of HVC (as indicated in the `config file `__) (`Meys et al. (2020) `__), and 6.9 MWh :math:`_{el}`/t of HVC (as indicated in the `config file `__) based on pyrolysis and electric steam cracking (see `Materials Economics `__ report). **Non-metallic Mineral Products** @@ -476,7 +476,7 @@ This subsector includes the manufacturing of cement, ceramics, and glass. *Cement* -Cement is used in construction to make concrete. The production of cement involves high energy consumption and large process emissions. The calcination of limestone to chemically reactive calcium oxide, also known as lime, involves process emissions of 0.54 t :math:`_{CO_2}` /t cement (see `Akhtar et al. `_. +Cement is used in construction to make concrete. The production of cement involves high energy consumption and large process emissions. The calcination of limestone to chemically reactive calcium oxide, also known as lime, involves process emissions of 0.54 t :math:`_{CO_2}` /t cement (see `Akhtar et al. `__. .. math:: @@ -487,16 +487,16 @@ Additionally, :math:`CO_2` is emitted from the combustion of fossil fuels to pro Cement process emissions can be captured assuming a capture rate of 90%. Whether emissions are captured is decided by the model taking into account the capital costs of carbon capture modules. The electricity and heat demand of process emission carbon capture is currently ignored. For net-zero emission scenarios, the remaining process emissions need to be compensated by negative emissions. -With the exception of electricity demand and biomass demand for low-temperature heat (0.06 MWh/t and 0.2 MWh/t), the final energy consumption of this subsector is assumed to be supplied by methane (0.52 MWh/t), which is capable of delivering the required high-temperature heat. This implies a switch from burning solid fuels to burning gas which will require adjustments of the `kilns <10.1109/CITCON.2013.6525276>`_. The share of fossil vs. synthetic methane consumed is a result of the optimisation +With the exception of electricity demand and biomass demand for low-temperature heat (0.06 MWh/t and 0.2 MWh/t), the final energy consumption of this subsector is assumed to be supplied by methane (0.52 MWh/t), which is capable of delivering the required high-temperature heat. This implies a switch from burning solid fuels to burning gas which will require adjustments of the `kilns <10.1109/CITCON.2013.6525276>`__. The share of fossil vs. synthetic methane consumed is a result of the optimisation *Ceramics* -The ceramics sector is assumed to be fully electrified based on the current efficiency of already electrified processes which include microwave drying and sintering of raw materials, electric kilns for primary production processes, electric furnaces for the `product finishing `_. In total, the final electricity consumption is 0.44 MWh/t of ceramic. The manufacturing of ceramics includes process emissions of 0.03 t :math:`_{CO_2}`/t of ceramic. For a detailed overview of the ceramics industry sector see `Furszyfer Del Rio et al `_. +The ceramics sector is assumed to be fully electrified based on the current efficiency of already electrified processes which include microwave drying and sintering of raw materials, electric kilns for primary production processes, electric furnaces for the `product finishing `__. In total, the final electricity consumption is 0.44 MWh/t of ceramic. The manufacturing of ceramics includes process emissions of 0.03 t :math:`_{CO_2}`/t of ceramic. For a detailed overview of the ceramics industry sector see `Furszyfer Del Rio et al `__. *Glass* -The production of glass is assumed to be fully electrified based on the current efficiency of electric melting tanks and electric annealing which adds up to an electricity demand of 2.07 MWh :math:`_{el}`/t of `glass `_. The manufacturing of glass incurs process emissions of 0.1 t :math:`_{CO_2}`/t of glass. Potential efficiency improvements, which according to `Lechtenböhmer et al `_ could reduce energy demands to 0.85 MW :math:`_{el}`/t of glass, have not been considered. For a detailed overview of the glass industry sector see `Furszyfer Del Rio et al `_. +The production of glass is assumed to be fully electrified based on the current efficiency of electric melting tanks and electric annealing which adds up to an electricity demand of 2.07 MWh :math:`_{el}`/t of `glass `__. The manufacturing of glass incurs process emissions of 0.1 t :math:`_{CO_2}`/t of glass. Potential efficiency improvements, which according to `Lechtenböhmer et al `__ could reduce energy demands to 0.85 MW :math:`_{el}`/t of glass, have not been considered. For a detailed overview of the glass industry sector see `Furszyfer Del Rio et al `__. **Non-ferrous Metals** @@ -511,75 +511,75 @@ The primary route involves two energy-intensive processes: the production of alu 2Al_2O_3 +3C \xrightarrow{} 4Al+3CO_2 -The primary route requires high-enthalpy heat (2.3 MWh/t) to produce alumina which is supplied by methane and causes process emissions of 1.5 t :math:`_{CO_2}`/t aluminium. According to `Friedrichsen et al. `_, inert anodes might become commercially available by 2030 that would eliminate the process emissions, but they are not included in the model. Assuming all subprocesses are electrified, the primary route requires 15.4 MWh :math:`_{el}`/t of aluminium. +The primary route requires high-enthalpy heat (2.3 MWh/t) to produce alumina which is supplied by methane and causes process emissions of 1.5 t :math:`_{CO_2}`/t aluminium. According to `Friedrichsen et al. `__, inert anodes might become commercially available by 2030 that would eliminate the process emissions, but they are not included in the model. Assuming all subprocesses are electrified, the primary route requires 15.4 MWh :math:`_{el}`/t of aluminium. -In the secondary route, scrap aluminium is remelted. The energy demand for this process is only 10% of the primary route and there are no associated process emissions. Assuming all subprocesses are electrified, the secondary route requires 1.7 MWh/t of aluminium. The share of aliminum manufactured by the primary and secondary route can be selected in the `config file `_] +In the secondary route, scrap aluminium is remelted. The energy demand for this process is only 10% of the primary route and there are no associated process emissions. Assuming all subprocesses are electrified, the secondary route requires 1.7 MWh/t of aluminium. The share of aliminum manufactured by the primary and secondary route can be selected in the `config file `__] For the other non-ferrous metals, we assume the electrification of the entire manufacturing process with an average electricity demand of 3.2 MWh :math:`_{el}`/t lead equivalent. **Other Industry Subsectors** -The remaining industry subsectors include (a) pulp, paper, printing, (b) food, beverages, tobacco, (c) textiles and leather, (d) machinery equipment, (e) transport equipment, (f) wood and wood products, (g) others. Low- and mid-temperature process heat in these industries is assumed to be `supplied by biomass `_ while the remaining processes are electrified. None of the subsectors involve process emissions. +The remaining industry subsectors include (a) pulp, paper, printing, (b) food, beverages, tobacco, (c) textiles and leather, (d) machinery equipment, (e) transport equipment, (f) wood and wood products, (g) others. Low- and mid-temperature process heat in these industries is assumed to be `supplied by biomass `__ while the remaining processes are electrified. None of the subsectors involve process emissions. Agriculture demand ========================= -Energy demands for the agriculture, forestry and fishing sector per country are taken from the `JRC-IDEES database `_. Missing countries are filled with `Eurostat data `_. Agricultural energy demands are split into electricity (lighting, ventilation, specific electricity uses, electric pumping devices), heat (specific heat uses, low enthalpy heat), and machinery oil (motor drives, farming machine drives, diesel-fueled pumping devices). Heat demand is assigned at “services rural heat” buses. Time series for demands are assumed to be constant and distributed inside countries by population. +Energy demands for the agriculture, forestry and fishing sector per country are taken from the `JRC-IDEES database `__. Missing countries are filled with `Eurostat data `__. Agricultural energy demands are split into electricity (lighting, ventilation, specific electricity uses, electric pumping devices), heat (specific heat uses, low enthalpy heat), and machinery oil (motor drives, farming machine drives, diesel-fueled pumping devices). Heat demand is assigned at “services rural heat” buses. Time series for demands are assumed to be constant and distributed inside countries by population. .. _Transportation: Transportation ========================= -Annual energy demands for land transport, aviation and shipping for every country are retrieved from `JRC-IDEES data set `_. Below, the details of how each of these categories are treated is explained. +Annual energy demands for land transport, aviation and shipping for every country are retrieved from `JRC-IDEES data set `__. Below, the details of how each of these categories are treated is explained. .. _Land transport: **Land transport** -Both road and rail transport is combined as `land transport demand `_ although electrified rail transport is excluded because that demand is included in the current electricity demand. +Both road and rail transport is combined as `land transport demand `__ although electrified rail transport is excluded because that demand is included in the current electricity demand. -The most important settings for land transport are the exogenously fixed fuel mix (an option enabling the endogeous optimization of transport electrification is planned but not yet implemented). In the `config file `_, the share of battery electric vehicles (BEV) and hydrogen fuel cell vehicles (FCEV) can be set. The remaining percentage will be treated as internal combustion engines (ICE) that consume oil products. +The most important settings for land transport are the exogenously fixed fuel mix (an option enabling the endogeous optimization of transport electrification is planned but not yet implemented). In the `config file `__, the share of battery electric vehicles (BEV) and hydrogen fuel cell vehicles (FCEV) can be set. The remaining percentage will be treated as internal combustion engines (ICE) that consume oil products. *Battery Electric vehicles (BEV)* -For the electrified land transport, country-specific factors are computed by comparing the `current car final energy consumption per km in `_ (average for Europe 0.7 kWh/km) to the 0.18 kWh/km value assumed for battery-to-wheels efficiency in EVs. The characteristic `weekly profile `_ provided by the German Federal Highway Research Institute (BASt) is used to obtain hourly time series for European countries taking into account the corresponding local times. Furthermore, a temperature dependence is included in the time series to account for heating/cooling demand in transport. For temperatures `below `_/`above `_ certain threshold values, e.g. 15 °C/20 °C, `temperature coefficients `_ of typically 0.98%/°C and 0.63%/°C are assumed, based on the `paper `_. +For the electrified land transport, country-specific factors are computed by comparing the `current car final energy consumption per km in `__ (average for Europe 0.7 kWh/km) to the 0.18 kWh/km value assumed for battery-to-wheels efficiency in EVs. The characteristic `weekly profile `__ provided by the German Federal Highway Research Institute (BASt) is used to obtain hourly time series for European countries taking into account the corresponding local times. Furthermore, a temperature dependence is included in the time series to account for heating/cooling demand in transport. For temperatures `below `__/`above `__ certain threshold values, e.g. 15 °C/20 °C, `temperature coefficients `__ of typically 0.98%/°C and 0.63%/°C are assumed, based on the `paper `__. -For BEVs the user can define the `storage energy capacity `_, `charging power capacity `_, and `charging efficiency `_. +For BEVs the user can define the `storage energy capacity `__, `charging power capacity `__, and `charging efficiency `__. -For BEV, smart charging is an option. A `certain share `_ of the BEV fleet can shift their charging time. The BEV state of charge is forced to be higher than a `set percentage `_, e.g. 75%, every day at a `specified hour `_, e.g., 7 am, to ensure that the batteries are sufficiently charged for peak usage in the morning and they not behave as seasonal storage. They also have the option to participate in vehicle-to-grid (V2G) services to facilitate system operation if that `is enabled `_. +For BEV, smart charging is an option. A `certain share `__ of the BEV fleet can shift their charging time. The BEV state of charge is forced to be higher than a `set percentage `__, e.g. 75%, every day at a `specified hour `__, e.g., 7 am, to ensure that the batteries are sufficiently charged for peak usage in the morning and they not behave as seasonal storage. They also have the option to participate in vehicle-to-grid (V2G) services to facilitate system operation if that `is enabled `__. The battery cost of BEV is not included in the model since it is assumed that BEV owners buy them to primarily satisfy their mobility needs. *Hydrogen fuel cell vehicles (FCEV)* The share of all land transport that is specified to be be FCEV will be converted to a demand for hydrogen (see :ref:`Hydrogen supply`) using the `FCEV efficiency -`_. +`__. FCEVs are typically used to simulate demand for transport that is hard to electrify directly, e.g. heavy construction machinery. But it may also be used to investigate a more widespread adoption of the technology. *Internal combustion engine vehicles (ICE)* All land transport that is not specified to be either BEV or FCEV will be treated as conventional ICEs. The transport demand is converted to a demand for oil products (see :ref:`Oil-based products supply`) using the `ICE efficiency -`_. +`__. .. _Aviation: **Aviation** -The `demand for aviation `_ includes international and domestic use. It is modelled as an oil demand since aviation consumes kerosene. This can be produced synthetically or have fossil-origin (see :ref:`Oil-based products supply`). +The `demand for aviation `__ includes international and domestic use. It is modelled as an oil demand since aviation consumes kerosene. This can be produced synthetically or have fossil-origin (see :ref:`Oil-based products supply`). .. _Shipping: **Shipping** -Shipping energy demand is covered by a combination of oil and hydrogen. Other fuel options, like methanol or ammonia, are currently not included in PyPSA-Eur-Sec. The share of shipping that is assumed to be supplied by hydrogen can be selected in the `config file `_. +Shipping energy demand is covered by a combination of oil and hydrogen. Other fuel options, like methanol or ammonia, are currently not included in PyPSA-Eur-Sec. The share of shipping that is assumed to be supplied by hydrogen can be selected in the `config file `__. -To estimate the `hydrogen demand `_, the average fuel efficiency of the fleet is used in combination with the efficiency of the fuel cell defined in the technology-data repository. The average fuel efficiency is set in the `config file `_. +To estimate the `hydrogen demand `__, the average fuel efficiency of the fleet is used in combination with the efficiency of the fuel cell defined in the technology-data repository. The average fuel efficiency is set in the `config file `__. The consumed hydrogen comes from the general hydrogen bus where it can be produced by SMR, SMR+CC or electrolysers (see :ref:`Hydrogen supply`). The fraction that is not converted into hydrogen use oil products, i.e. is connected to the general oil bus. -The energy demand for liquefaction of the hydrogen used for shipping can be `included `_. If this option is selected, liquifaction will happen at the `node where the shipping demand occurs `_. +The energy demand for liquefaction of the hydrogen used for shipping can be `included `__. If this option is selected, liquifaction will happen at the `node where the shipping demand occurs `__. .. _Carbon dioxide capture, usage and sequestration (CCU/S): @@ -600,12 +600,12 @@ For the following point source emissions, carbon capture is applicable: • CHP plants using biomass or methane -• `Coal power plants `_. +• `Coal power plants `__. -Point source emissions are captured assuming a capture rate, e.g. 90%, which can be specified in the `config file `_. The electricity and heat demand of process emission carbon capture +Point source emissions are captured assuming a capture rate, e.g. 90%, which can be specified in the `config file `__. The electricity and heat demand of process emission carbon capture is currently ignored. -DAC (if `included `_) includes the adsorption phase where electricity and heat consumptionsare required to assist the adsorption process and regenerate the adsorbent. It also includes the drying and compression of :math:`CO_2` prior to storage which consumes electricity and rejects heat. +DAC (if `included `__) includes the adsorption phase where electricity and heat consumptionsare required to assist the adsorption process and regenerate the adsorbent. It also includes the drying and compression of :math:`CO_2` prior to storage which consumes electricity and rejects heat. *Carbon dioxide usage* @@ -614,8 +614,8 @@ naphtha). If captured carbon is used, the :math:`CO_2` emissions of the syntheti *Carbon dioxide sequestration* -Captured :math:`CO_2` can also be sequestered underground up to an annual sequestration limit of 200 Mt :math:`_{CO_2}`/a. This limit can be chosen in the `config file `_. As stored carbon dioxide is modelled as a single node for Europe, :math:`CO_2` transport constraints are neglected. Since :math:`CO_2` sequestration is an immature technology, the cost assumption is defined in the `config file `_. +Captured :math:`CO_2` can also be sequestered underground up to an annual sequestration limit of 200 Mt :math:`_{CO_2}`/a. This limit can be chosen in the `config file `__. As stored carbon dioxide is modelled as a single node for Europe, :math:`CO_2` transport constraints are neglected. Since :math:`CO_2` sequestration is an immature technology, the cost assumption is defined in the `config file `__. *Carbon dioxide transport* -Carbon dioxide can be modelled as a single node for Europe (in this case, :math:`CO_2` transport constraints are neglected). A network for modelling the transport of :math:`CO_2` among the different nodes can also be created if selected in the `config file `_. +Carbon dioxide can be modelled as a single node for Europe (in this case, :math:`CO_2` transport constraints are neglected). A network for modelling the transport of :math:`CO_2` among the different nodes can also be created if selected in the `config file `__. diff --git a/doc/support.rst b/doc/support.rst index 1a3e6d08..fc86a998 100644 --- a/doc/support.rst +++ b/doc/support.rst @@ -7,8 +7,8 @@ Support ####################### -* In case of code-related **questions**, please post on `stack overflow `_. -* For non-programming related and more general questions please refer to the `mailing list `_. -* To **discuss** with other PyPSA users, organise projects, share news, and get in touch with the community you can use the `discord server `_. -* For **bugs and feature requests**, please use the `issue tracker `_. -* We strongly welcome anyone interested in providing **contributions** to this project. If you have any ideas, suggestions or encounter problems, feel invited to file issues or make pull requests on `Github `_. For further information on how to contribute, please refer to :ref:`contributing`. +* In case of code-related **questions**, please post on `stack overflow `__. +* For non-programming related and more general questions please refer to the `mailing list `__. +* To **discuss** with other PyPSA users, organise projects, share news, and get in touch with the community you can use the `discord server `__. +* For **bugs and feature requests**, please use the `issue tracker `__. +* We strongly welcome anyone interested in providing **contributions** to this project. If you have any ideas, suggestions or encounter problems, feel invited to file issues or make pull requests on `Github `__. For further information on how to contribute, please refer to :ref:`contributing`. diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 4f272292..93bb8e54 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -323,4 +323,4 @@ Jupyter Notebooks). n = pypsa.Network("results/networks/elec_s_6_ec_lcopt_Co2L-24H.nc") -For inspiration, read the `examples section in the PyPSA documentation `_. +For inspiration, read the `examples section in the PyPSA documentation `__. diff --git a/doc/validation.rst b/doc/validation.rst index e538717c..afe7a7f3 100644 --- a/doc/validation.rst +++ b/doc/validation.rst @@ -9,7 +9,7 @@ Validation The PyPSA-Eur model workflow provides a built-in mechanism for validation. This allows users to contrast the outcomes of network optimization against the historical behaviour of the European power system. The snakemake rule ``validate_elec_networks`` enables this by generating comparative figures that encapsulate key data points such as dispatch carrier, cross-border flows, and market prices per price zone. -These comparisons utilize data from the 2019 ENTSO-E Transparency Platform. To enable this, an ENTSO-E API key must be inserted into the ``config.yaml`` file. Detailed steps for this process can be found in the user guide `here `_. +These comparisons utilize data from the 2019 ENTSO-E Transparency Platform. To enable this, an ENTSO-E API key must be inserted into the ``config.yaml`` file. Detailed steps for this process can be found in the user guide `here `__. Once the API key is set, the validation workflow can be triggered by running the following command: diff --git a/doc/wildcards.rst b/doc/wildcards.rst index f86ff311..1fd1646f 100644 --- a/doc/wildcards.rst +++ b/doc/wildcards.rst @@ -17,7 +17,7 @@ what data to retrieve and what files to produce. .. note:: Detailed explanations of how wildcards work in ``snakemake`` can be found in the - `relevant section of the documentation `_. + `relevant section of the documentation `__. .. _cutout_wc: From 8273b7854027bfba8c961856820dbdfc783689ec Mon Sep 17 00:00:00 2001 From: toniseibold Date: Thu, 11 Apr 2024 16:32:08 +0200 Subject: [PATCH 545/591] file is not used --- data/hydrogen_salt_cavern_potentials.csv | 31 ------------------------ 1 file changed, 31 deletions(-) delete mode 100644 data/hydrogen_salt_cavern_potentials.csv diff --git a/data/hydrogen_salt_cavern_potentials.csv b/data/hydrogen_salt_cavern_potentials.csv deleted file mode 100644 index c1168266..00000000 --- a/data/hydrogen_salt_cavern_potentials.csv +++ /dev/null @@ -1,31 +0,0 @@ -ct,TWh -AT, -BA, -BE, -BG, -CH, -CZ, -DE,4500 -DK,700 -EE, -ES,350 -FI, -FR, -GB,1050 -GR,120 -HR, -HU, -IE, -IT, -LT, -LU, -LV, -NL,150 -NO, -PL,120 -PT,400 -RO, -RS, -SE, -SI, -SK, From 4d4b8ea2666e141977f7b168452561e37a79f16a Mon Sep 17 00:00:00 2001 From: cpschau Date: Thu, 11 Apr 2024 13:45:02 +0200 Subject: [PATCH 546/591] n.madd instead of pd.concat --- scripts/base_network.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index 528f04bf..706c112e 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -704,8 +704,14 @@ def _set_shapes(n, country_shapes, offshore_shapes): country_shapes["type"] = "country" offshore_shapes = gpd.read_file(offshore_shapes).rename(columns={"name": "idx"}) offshore_shapes["type"] = "offshore" - all_shapes = pd.concat([country_shapes, offshore_shapes]) - n.shapes = pd.concat([n.shapes, all_shapes], ignore_index=True) + all_shapes = pd.concat([country_shapes, offshore_shapes], ignore_index=True) + n.madd( + "Shape", + all_shapes.index, + geometry=all_shapes.geometry, + idx=all_shapes.idx, + type=all_shapes.type, + ) def base_network( From f2db3c63270b94aabd1cf2d65f16ede0e446b5a2 Mon Sep 17 00:00:00 2001 From: cpschau Date: Thu, 11 Apr 2024 16:26:16 +0200 Subject: [PATCH 547/591] add AC & DC lines --- scripts/base_network.py | 67 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/scripts/base_network.py b/scripts/base_network.py index 706c112e..00750502 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -705,6 +705,10 @@ def _set_shapes(n, country_shapes, offshore_shapes): offshore_shapes = gpd.read_file(offshore_shapes).rename(columns={"name": "idx"}) offshore_shapes["type"] = "offshore" all_shapes = pd.concat([country_shapes, offshore_shapes], ignore_index=True) +<<<<<<< HEAD +======= + +>>>>>>> dce7d57a (add AC & DC lines) n.madd( "Shape", all_shapes.index, @@ -712,6 +716,69 @@ def _set_shapes(n, country_shapes, offshore_shapes): idx=all_shapes.idx, type=all_shapes.type, ) +<<<<<<< HEAD +======= + + # Write the AC and DC line shapes to the network.shapes component + start_index = n.shapes.index.astype(int).max() + 1 + index_AC = pd.RangeIndex(start=start_index, stop=start_index + len(n.lines)) + geo_AC = gpd.GeoSeries( + n.lines.geometry.apply(shapely.wkt.loads).fillna( + n.lines[["bus0", "bus1"]].apply( + lambda x: LineString( + [n.buses.loc[x[0], ["x", "y"]], n.buses.loc[x[1], ["x", "y"]]] + ), + axis=1, + ) + ) + ) + geo_AC.index = index_AC + + n.madd( + "Shape", + index_AC, + geometry=geo_AC.values, + idx=n.lines.index, + component="Line", + type=n.lines.carrier.values, + ) + + if n.links.empty: + return + start_index = n.shapes.index.astype(int).max() + 1 + index_DC = pd.RangeIndex(start=start_index, stop=start_index + len(n.links)) + if "geometry" in n.links.columns: + geo_DC = gpd.GeoSeries( + n.links.geometry.apply(shapely.wkt.loads).fillna( + n.links[["bus0", "bus1"]].apply( + lambda x: LineString( + [n.buses.loc[x[0], ["x", "y"]], n.buses.loc[x[1], ["x", "y"]]] + ), + axis=1, + ) + ) + ) + else: + geo_DC = gpd.GeoSeries( + n.links[["bus0", "bus1"]].apply( + lambda x: LineString( + [n.buses.loc[x[0], ["x", "y"]], n.buses.loc[x[1], ["x", "y"]]] + ), + axis=1, + ) + ) + + geo_DC = gpd.GeoSeries(geo_DC) + + n.madd( + "Shape", + index_DC, + geometry=geo_DC.values, + idx=n.links.index, + component="Link", + type=n.links.carrier.values, + ) +>>>>>>> dce7d57a (add AC & DC lines) def base_network( From c68e3420c0e400398e1cb1fe5cc5295148d157e1 Mon Sep 17 00:00:00 2001 From: cpschau Date: Thu, 11 Apr 2024 16:42:19 +0200 Subject: [PATCH 548/591] clean-up after rebase --- scripts/base_network.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index 00750502..916241a9 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -705,19 +705,13 @@ def _set_shapes(n, country_shapes, offshore_shapes): offshore_shapes = gpd.read_file(offshore_shapes).rename(columns={"name": "idx"}) offshore_shapes["type"] = "offshore" all_shapes = pd.concat([country_shapes, offshore_shapes], ignore_index=True) -<<<<<<< HEAD -======= - ->>>>>>> dce7d57a (add AC & DC lines) n.madd( "Shape", all_shapes.index, geometry=all_shapes.geometry, idx=all_shapes.idx, - type=all_shapes.type, + type=all_shapes["type"], ) -<<<<<<< HEAD -======= # Write the AC and DC line shapes to the network.shapes component start_index = n.shapes.index.astype(int).max() + 1 @@ -778,7 +772,6 @@ def _set_shapes(n, country_shapes, offshore_shapes): component="Link", type=n.links.carrier.values, ) ->>>>>>> dce7d57a (add AC & DC lines) def base_network( From 35713e82b4b25604bc5c5afd7a99bcbd656f5660 Mon Sep 17 00:00:00 2001 From: toniseibold Date: Thu, 11 Apr 2024 16:44:18 +0200 Subject: [PATCH 549/591] Remove heat_load_profile_DK_AdamJensen.csv and license comment --- data/heat_load_profile_DK_AdamJensen.csv | 25 ------------------------ doc/configtables/licenses-sector.csv | 1 - 2 files changed, 26 deletions(-) delete mode 100644 data/heat_load_profile_DK_AdamJensen.csv diff --git a/data/heat_load_profile_DK_AdamJensen.csv b/data/heat_load_profile_DK_AdamJensen.csv deleted file mode 100644 index cb417bde..00000000 --- a/data/heat_load_profile_DK_AdamJensen.csv +++ /dev/null @@ -1,25 +0,0 @@ -hour,weekday,weekend -0,0.9181438689,0.9421512708 -1,0.9172359071,0.9400891069 -2,0.9269464481,0.9461062015 -3,0.9415047932,0.9535084941 -4,0.9656299507,0.9651094993 -5,1.0221166443,0.9834676747 -6,1.1553090493,1.0124171051 -7,1.2093411031,1.0446615927 -8,1.1470295942,1.088203419 -9,1.0877191341,1.1110334576 -10,1.0418327372,1.0926752822 -11,1.0062977133,1.055488209 -12,0.9837030359,1.0251266112 -13,0.9667570278,0.9990015154 -14,0.9548320932,0.9782897278 -15,0.9509232061,0.9698167237 -16,0.9636973319,0.974288587 -17,0.9799372563,0.9886456216 -18,1.0046501848,1.0084159643 -19,1.0079452419,1.0171243296 -20,0.9860566481,0.9994722379 -21,0.9705228074,0.982761591 -22,0.9586485819,0.9698167237 -23,0.9335023778,0.9515079292 diff --git a/doc/configtables/licenses-sector.csv b/doc/configtables/licenses-sector.csv index 7f20b5a6..d1660596 100644 --- a/doc/configtables/licenses-sector.csv +++ b/doc/configtables/licenses-sector.csv @@ -8,7 +8,6 @@ Eurostat Energy Balances,eurostat-energy_balances-*/,Eurostat,https://ec.europa. Swiss energy statistics from Swiss Federal Office of Energy,switzerland-sfoe/,unknown,http://www.bfe.admin.ch/themen/00526/00541/00542/02167/index.html?dossier_id=02169 BASt emobility statistics,emobility/,unknown,http://www.bast.de/DE/Verkehrstechnik/Fachthemen/v2-verkehrszaehlung/Stundenwerte.html?nn=626916 BDEW heating profile,heat_load_profile_BDEW.csv,unknown,https://github.com/oemof/demandlib -heating profiles for Aarhus,heat_load_profile_DK_AdamJensen.csv,unknown,Adam Jensen MA thesis at Aarhus University co2 budgets,co2_budget.csv,CC BY 4.0,https://arxiv.org/abs/2004.11009 existing heating potentials,existing_infrastructure/existing_heating_raw.csv,unknown,https://energy.ec.europa.eu/publications/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment-fossilrenewables-1_en IRENA existing VRE capacities,existing_infrastructure/{solar|onwind|offwind}_capcity_IRENA.csv,unknown,https://www.irena.org/Statistics/Download-Data From 1867e510e26d22790d1efd1c50078c213082a71a Mon Sep 17 00:00:00 2001 From: cpschau Date: Thu, 11 Apr 2024 17:14:17 +0200 Subject: [PATCH 550/591] remove redundant line --- scripts/base_network.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index 916241a9..663e995f 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -762,8 +762,6 @@ def _set_shapes(n, country_shapes, offshore_shapes): ) ) - geo_DC = gpd.GeoSeries(geo_DC) - n.madd( "Shape", index_DC, From 7dd1d8fb59065f4b6782caf46f5261f5530f625a Mon Sep 17 00:00:00 2001 From: toniseibold Date: Thu, 11 Apr 2024 17:46:44 +0200 Subject: [PATCH 551/591] delete biomass JRC from license file --- doc/configtables/licenses-sector.csv | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/configtables/licenses-sector.csv b/doc/configtables/licenses-sector.csv index d1660596..a44e0a5d 100644 --- a/doc/configtables/licenses-sector.csv +++ b/doc/configtables/licenses-sector.csv @@ -1,7 +1,6 @@ description,file/folder,licence,source JRC IDEES database,jrc-idees-2015/,CC BY 4.0,https://ec.europa.eu/jrc/en/potencia/jrc-idees urban/rural fraction,urban_percent.csv,unknown,unknown -JRC biomass potentials,biomass/,unknown,https://doi.org/10.2790/39014 JRC ENSPRESO biomass potentials,remote,CC BY 4.0,https://data.jrc.ec.europa.eu/dataset/74ed5a04-7d74-4807-9eab-b94774309d9f EEA emission statistics,eea/UNFCCC_v23.csv,EEA standard re-use policy,https://www.eea.europa.eu/data-and-maps/data/national-emissions-reported-to-the-unfccc-and-to-the-eu-greenhouse-gas-monitoring-mechanism-16 Eurostat Energy Balances,eurostat-energy_balances-*/,Eurostat,https://ec.europa.eu/eurostat/web/energy/data/energy-balances From 038575dfc0c3dd9139c2253aa6cfa2c3ff596d40 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 11 Apr 2024 19:14:45 +0200 Subject: [PATCH 552/591] skip heat bus for CHPs in places where no central heating --- scripts/add_existing_baseyear.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index f445efe3..f1028099 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -362,13 +362,20 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas ) else: key = "central solid biomass CHP" + central_heat = n.buses.query( + "carrier == 'urban central heat'" + ).location.unique() + heat_buses = new_capacity.index.map( + lambda i: i + " urban central heat" if i in central_heat else "" + ) + n.madd( "Link", new_capacity.index, suffix=name_suffix, bus0=spatial.biomass.df.loc[new_capacity.index]["nodes"].values, bus1=new_capacity.index, - bus2=new_capacity.index + " urban central heat", + bus2=heat_buses, carrier=generator, p_nom=new_capacity / costs.at[key, "efficiency"], capital_cost=costs.at[key, "fixed"] From 3b31b99dd2d2f48c30eda741b6b21c07b0895cef Mon Sep 17 00:00:00 2001 From: toniseibold Date: Fri, 12 Apr 2024 10:01:09 +0200 Subject: [PATCH 553/591] removing the output file eia_hydro_stats.csv --- rules/build_electricity.smk | 1 - scripts/build_hydro_profile.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index f84a9969..65e24189 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -360,7 +360,6 @@ rule build_hydro_profile: + ".nc", output: profile=resources("profile_hydro.nc"), - eia_hydro=resources("eia_hydro_stats.csv"), log: logs("build_hydro_profile.log"), resources: diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index c4e9701e..cd51ce90 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -198,8 +198,6 @@ if __name__ == "__main__": fn = snakemake.input.era5_runoff eia_stats = approximate_missing_eia_stats(eia_stats, fn, countries) - eia_stats.to_csv(snakemake.output.eia_hydro) - contained_years = pd.date_range(freq="YE", **snakemake.params.snapshots).year norm_year = config_hydro.get("eia_norm_year") missing_years = contained_years.difference(eia_stats.index) From 98d2c4dd911b6d0157ea11691b057f32837a1760 Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Thu, 11 Apr 2024 10:54:25 +0200 Subject: [PATCH 554/591] Fix p_nom_min of renewables generators for myopic approach and add check of existing capacities in add_land_use_constraint_m --- doc/release_notes.rst | 2 ++ scripts/solve_network.py | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d42b149f..d9c69244 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -181,6 +181,8 @@ Upcoming Release * Fix custom busmap read in `cluster_network`. +* Fix p_nom_min of renewables generators for myopic approach and add check of existing capacities in `add_land_use_constraint_m`. + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 0f6725c7..b8819a19 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -159,6 +159,9 @@ def _add_land_use_constraint_m(n, planning_horizons, config): current_horizon = snakemake.wildcards.planning_horizons for carrier in ["solar", "onwind", "offwind-ac", "offwind-dc"]: + extendable_i = (n.generators.carrier == carrier) & n.generators.p_nom_extendable + n.generators.loc[extendable_i, "p_nom_min"] = 0 + existing = n.generators.loc[n.generators.carrier == carrier, "p_nom"] ind = list( {i.split(sep=" ")[0] + " " + i.split(sep=" ")[1] for i in existing.index} @@ -180,6 +183,19 @@ def _add_land_use_constraint_m(n, planning_horizons, config): sel_p_year ].rename(lambda x: x[:-4] + current_horizon) + # check if existing capacities are larger than technical potential + existing_large = n.generators[ + n.generators["p_nom_min"] > n.generators["p_nom_max"] + ].index + if len(existing_large): + logger.warning( + f"Existing capacities larger than technical potential for {existing_large},\ + adjust technical potential to existing capacities" + ) + n.generators.loc[existing_large, "p_nom_max"] = n.generators.loc[ + existing_large, "p_nom_min" + ] + n.generators.p_nom_max.clip(lower=0, inplace=True) From 7a0ca73f3a1f7e2feae8446fb9815fd6b2a13b93 Mon Sep 17 00:00:00 2001 From: Sermisha Date: Sun, 14 Apr 2024 14:24:01 +0530 Subject: [PATCH 555/591] Update to BAU constraint formulation in function add_BAU_constraints Constraint formulation was not taking into account the ordering of the carriers --- scripts/solve_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 0f6725c7..b1463b35 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -543,7 +543,7 @@ def add_BAU_constraints(n, config): ext_carrier_i = xr.DataArray(ext_i.carrier.rename_axis("Generator-ext")) lhs = p_nom.groupby(ext_carrier_i).sum() index = mincaps.index.intersection(lhs.indexes["carrier"]) - rhs = mincaps[index].rename_axis("carrier") + rhs = mincaps[lhs.indexes["carrier"]].rename_axis("carrier") n.model.add_constraints(lhs >= rhs, name="bau_mincaps") From 4429711b15bbacdd3ef0cad49d09b189b65fa67a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 19:51:09 +0000 Subject: [PATCH 556/591] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 24.3.0 → 24.4.0](https://github.com/psf/black-pre-commit-mirror/compare/24.3.0...24.4.0) - [github.com/snakemake/snakefmt: v0.10.0 → v0.10.1](https://github.com/snakemake/snakefmt/compare/v0.10.0...v0.10.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 055b9080..a3aab9ed 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,7 +51,7 @@ repos: # Formatting with "black" coding style - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.3.0 + rev: 24.4.0 hooks: # Format Python files - id: black @@ -74,7 +74,7 @@ repos: # Format Snakemake rule / workflow files - repo: https://github.com/snakemake/snakefmt - rev: v0.10.0 + rev: v0.10.1 hooks: - id: snakefmt From 15345ff1cfae4026a69c070d02f5893642f6b0f2 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 11 Apr 2024 19:14:45 +0200 Subject: [PATCH 557/591] skip heat bus for CHPs in places where no central heating --- scripts/add_existing_baseyear.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index f445efe3..f1028099 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -362,13 +362,20 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas ) else: key = "central solid biomass CHP" + central_heat = n.buses.query( + "carrier == 'urban central heat'" + ).location.unique() + heat_buses = new_capacity.index.map( + lambda i: i + " urban central heat" if i in central_heat else "" + ) + n.madd( "Link", new_capacity.index, suffix=name_suffix, bus0=spatial.biomass.df.loc[new_capacity.index]["nodes"].values, bus1=new_capacity.index, - bus2=new_capacity.index + " urban central heat", + bus2=heat_buses, carrier=generator, p_nom=new_capacity / costs.at[key, "efficiency"], capital_cost=costs.at[key, "fixed"] From 380884e9ab16337c6f1fbc9d2bc489376066f2c9 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Thu, 14 Mar 2024 13:44:15 +0100 Subject: [PATCH 558/591] group existing capacities to the earlier grouping_year for consistency with optimized capacities --- config/config.default.yaml | 2 +- doc/release_notes.rst | 1 + scripts/add_existing_baseyear.py | 20 ++++++++++++-------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index d438c51f..0d40bafc 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -361,7 +361,7 @@ solar_thermal: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#existing-capacities existing_capacities: grouping_years_power: [1960, 1965, 1970, 1975, 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 + grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020] # heat grouping years >= baseyear will be ignored threshold_capacity: 10 default_heating_lifetime: 20 conventional_carriers: diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d9c69244..d9075ac7 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,6 +9,7 @@ Release Notes Upcoming Release ================ +* Group existing capacities to the earlier grouping_year for consistency with optimized capacities * Include gas and oil fields and saline aquifers in estimation of CO2 sequestration potential. diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index f1028099..c10e9deb 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -190,8 +190,8 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas df_agg.drop(phased_out, inplace=True) df_agg["grouping_year"] = np.take( - grouping_years, np.digitize(df_agg.DateIn, grouping_years, right=True) - ) + grouping_years[::-1], + np.digitize(df_agg.DateIn, grouping_years[::-1])) # calculate (adjusted) remaining lifetime before phase-out (+1 because assuming # phase out date at the end of the year) @@ -451,12 +451,16 @@ def add_heating_capacities_installed_before_baseyear( else: efficiency = costs.at[costs_name, "efficiency"] - for i, grouping_year in enumerate(grouping_years): - if int(grouping_year) + default_lifetime <= int(baseyear): - continue - - # installation is assumed to be linear for the past default_lifetime years - ratio = (int(grouping_year) - int(grouping_years[i - 1])) / default_lifetime + valid_grouping_years = pd.Series( + [int(gy) for gy in grouping_years if + int(baseyear) - default_lifetime <= int(gy) < int(baseyear)]) + # Installation is assumed to be linear for the past + _intervals = pd.concat( + [valid_grouping_years[1:], pd.Series(baseyear)], + ignore_index=True) - valid_grouping_years + ratios = _intervals / _intervals.sum() + + for ratio, grouping_year in zip(ratios, valid_grouping_years): n.madd( "Link", From 27f2bd77fb6f8cea85e149bd3a918f9c0af2688a Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Thu, 14 Mar 2024 16:13:40 +0100 Subject: [PATCH 559/591] add more grouping years to avoid errors --- 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 0d40bafc..42132f22 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -360,7 +360,7 @@ solar_thermal: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#existing-capacities existing_capacities: - grouping_years_power: [1960, 1965, 1970, 1975, 1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030] + grouping_years_power: [1895, 1920, 1950, 1955, 1960, 1965, 1970, 1975, 1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030] grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020] # heat grouping years >= baseyear will be ignored threshold_capacity: 10 default_heating_lifetime: 20 From 17d44d7f64d76878cadcabf09064ac53a2306dd5 Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Thu, 11 Apr 2024 08:54:15 +0200 Subject: [PATCH 560/591] add check if minimum grouping year< min build year --- scripts/add_existing_baseyear.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index c10e9deb..ddd409c1 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -189,6 +189,15 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas phased_out = df_agg[df_agg["DateOut"] < baseyear].index df_agg.drop(phased_out, inplace=True) + older_assets = (df_agg.DateIn Date: Thu, 11 Apr 2024 09:26:30 +0200 Subject: [PATCH 561/591] adjust valid_grouping_years change sign, split up conditions for better readibility --- scripts/add_existing_baseyear.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index ddd409c1..285776cc 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -461,14 +461,22 @@ def add_heating_capacities_installed_before_baseyear( efficiency = costs.at[costs_name, "efficiency"] valid_grouping_years = pd.Series( - [int(gy) for gy in grouping_years if - int(baseyear) - default_lifetime <= int(gy) < int(baseyear)]) + [ + int(grouping_year) + for grouping_year in grouping_years + if int(grouping_year) + default_lifetime > int(baseyear) + and int(grouping_year) < int(baseyear) + ] + ) # Installation is assumed to be linear for the past - _intervals = pd.concat( - [valid_grouping_years[1:], pd.Series(baseyear)], - ignore_index=True) - valid_grouping_years + _intervals = ( + pd.concat( + [valid_grouping_years[1:], pd.Series(baseyear)], ignore_index=True + ) + - valid_grouping_years + ) ratios = _intervals / _intervals.sum() - + for ratio, grouping_year in zip(ratios, valid_grouping_years): n.madd( From 6f09a16b3a8f1f10c1808f3f42d7cdb5f0ff394c Mon Sep 17 00:00:00 2001 From: Micha Date: Thu, 11 Apr 2024 09:37:36 +0200 Subject: [PATCH 562/591] Add release note for serendipitous bugfix --- doc/release_notes.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d9075ac7..660fa357 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,7 +9,9 @@ Release Notes Upcoming Release ================ -* Group existing capacities to the earlier grouping_year for consistency with optimized capacities +* Group existing capacities to the earlier grouping_year for consistency with optimized capacities. + +* bugfix: installed heating capacities were 5% lower than existing heating capacities * Include gas and oil fields and saline aquifers in estimation of CO2 sequestration potential. From dd874e0ed8ae9ef2a99e1bdf51d093f7adeef958 Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Thu, 11 Apr 2024 09:52:17 +0200 Subject: [PATCH 563/591] rename _intervals to _years, shorten definition --- scripts/add_existing_baseyear.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 285776cc..db2c27e4 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -468,14 +468,12 @@ def add_heating_capacities_installed_before_baseyear( and int(grouping_year) < int(baseyear) ] ) + + # get number of years of each interval + _years = (valid_grouping_years.diff().shift(-1) + .fillna(baseyear-valid_grouping_years.iloc[-1])) # Installation is assumed to be linear for the past - _intervals = ( - pd.concat( - [valid_grouping_years[1:], pd.Series(baseyear)], ignore_index=True - ) - - valid_grouping_years - ) - ratios = _intervals / _intervals.sum() + ratios = _years / _years.sum() for ratio, grouping_year in zip(ratios, valid_grouping_years): From ec96a73baf745ecff3c10e418ae5dcde8ac19958 Mon Sep 17 00:00:00 2001 From: lisazeyen <35347358+lisazeyen@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:54:33 +0200 Subject: [PATCH 564/591] define active assets consitently --- scripts/add_brownfield.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 7e49031b..16b4e087 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -40,8 +40,8 @@ def add_brownfield(n, n_p, year): # CO2 or global EU values since these are already in n n_p.mremove(c.name, c.df.index[c.df.lifetime == np.inf]) - # remove assets whose build_year + lifetime < year - n_p.mremove(c.name, c.df.index[c.df.build_year + c.df.lifetime < year]) + # remove assets whose build_year + lifetime <= year + n_p.mremove(c.name, c.df.index[c.df.build_year + c.df.lifetime <= year]) # remove assets if their optimized nominal capacity is lower than a threshold # since CHP heat Link is proportional to CHP electric Link, make sure threshold is compatible From da15ab3ac25ea6c85dc60d100e239cd666c81bbd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 12:21:43 +0000 Subject: [PATCH 565/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/add_existing_baseyear.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index db2c27e4..e75fe5a2 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -189,18 +189,20 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas phased_out = df_agg[df_agg["DateOut"] < baseyear].index df_agg.drop(phased_out, inplace=True) - older_assets = (df_agg.DateIn Date: Tue, 16 Apr 2024 10:24:16 +0200 Subject: [PATCH 566/591] no addition of straight lines --- scripts/base_network.py | 58 ----------------------------------------- 1 file changed, 58 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index 663e995f..6727a724 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -713,64 +713,6 @@ def _set_shapes(n, country_shapes, offshore_shapes): type=all_shapes["type"], ) - # Write the AC and DC line shapes to the network.shapes component - start_index = n.shapes.index.astype(int).max() + 1 - index_AC = pd.RangeIndex(start=start_index, stop=start_index + len(n.lines)) - geo_AC = gpd.GeoSeries( - n.lines.geometry.apply(shapely.wkt.loads).fillna( - n.lines[["bus0", "bus1"]].apply( - lambda x: LineString( - [n.buses.loc[x[0], ["x", "y"]], n.buses.loc[x[1], ["x", "y"]]] - ), - axis=1, - ) - ) - ) - geo_AC.index = index_AC - - n.madd( - "Shape", - index_AC, - geometry=geo_AC.values, - idx=n.lines.index, - component="Line", - type=n.lines.carrier.values, - ) - - if n.links.empty: - return - start_index = n.shapes.index.astype(int).max() + 1 - index_DC = pd.RangeIndex(start=start_index, stop=start_index + len(n.links)) - if "geometry" in n.links.columns: - geo_DC = gpd.GeoSeries( - n.links.geometry.apply(shapely.wkt.loads).fillna( - n.links[["bus0", "bus1"]].apply( - lambda x: LineString( - [n.buses.loc[x[0], ["x", "y"]], n.buses.loc[x[1], ["x", "y"]]] - ), - axis=1, - ) - ) - ) - else: - geo_DC = gpd.GeoSeries( - n.links[["bus0", "bus1"]].apply( - lambda x: LineString( - [n.buses.loc[x[0], ["x", "y"]], n.buses.loc[x[1], ["x", "y"]]] - ), - axis=1, - ) - ) - - n.madd( - "Shape", - index_DC, - geometry=geo_DC.values, - idx=n.links.index, - component="Link", - type=n.links.carrier.values, - ) - def base_network( eg_buses, From 6aac8c90b4c221e11a9d44df7ddcf91d7765a3f6 Mon Sep 17 00:00:00 2001 From: cpschau Date: Tue, 16 Apr 2024 10:30:39 +0200 Subject: [PATCH 567/591] added release note --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d42b149f..4441f439 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -181,6 +181,8 @@ Upcoming Release * Fix custom busmap read in `cluster_network`. +* Added shapes to .nc file for different stages of the network object in `base_network`, `build_bus_regions`, and `cluster_network`. + PyPSA-Eur 0.10.0 (19th February 2024) ===================================== From 6ea8d52a81085d3396d831289bd5c3b0f50c602c Mon Sep 17 00:00:00 2001 From: cpschau Date: Tue, 16 Apr 2024 10:43:07 +0200 Subject: [PATCH 568/591] no directory change before mock_snakemake --- scripts/base_network.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index 6727a724..d96a7e54 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -781,12 +781,9 @@ def base_network( if __name__ == "__main__": if "snakemake" not in globals(): - import os from _helpers import mock_snakemake - os.chdir(os.path.dirname(os.path.abspath(__file__))) - snakemake = mock_snakemake("base_network") configure_logging(snakemake) set_scenario_config(snakemake) From feb564506a1c11ee7bb0b1c20be29a0e8027656f Mon Sep 17 00:00:00 2001 From: martacki Date: Tue, 16 Apr 2024 15:41:01 +0200 Subject: [PATCH 569/591] remove connection_costs as snakemake output from simplify_network --- rules/build_electricity.smk | 1 - scripts/simplify_network.py | 12 ++---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 65e24189..ed341d2f 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -487,7 +487,6 @@ rule simplify_network: regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), regions_offshore=resources("regions_offshore_elec_s{simpl}.geojson"), busmap=resources("busmap_elec_s{simpl}.csv"), - connection_costs=resources("connection_costs_s{simpl}.csv"), log: logs("simplify_network/elec_s{simpl}.log"), benchmark: diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 24df7312..d74fcdb5 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -207,7 +207,7 @@ def _compute_connection_costs_to_bus( return connection_costs_to_bus -def _adjust_capital_costs_using_connection_costs(n, connection_costs_to_bus, output): +def _adjust_capital_costs_using_connection_costs(n, connection_costs_to_bus): connection_costs = {} for tech in connection_costs_to_bus: tech_b = n.generators.carrier == tech @@ -228,14 +228,12 @@ def _adjust_capital_costs_using_connection_costs(n, connection_costs_to_bus, out ) ) connection_costs[tech] = costs - pd.DataFrame(connection_costs).to_csv(output.connection_costs) def _aggregate_and_move_components( n, busmap, connection_costs_to_bus, - output, aggregate_one_ports={"Load", "StorageUnit"}, aggregation_strategies=dict(), exclude_carriers=None, @@ -248,7 +246,7 @@ def _aggregate_and_move_components( if not df.empty: import_series_from_dataframe(n, df, c, attr) - _adjust_capital_costs_using_connection_costs(n, connection_costs_to_bus, output) + _adjust_capital_costs_using_connection_costs(n, connection_costs_to_bus) generator_strategies = aggregation_strategies["generators"] @@ -281,7 +279,6 @@ def simplify_links( length_factor, p_max_pu, exclude_carriers, - output, aggregation_strategies=dict(), ): ## Complex multi-node links are folded into end-points @@ -406,7 +403,6 @@ def simplify_links( n, busmap, connection_costs_to_bus, - output, aggregation_strategies=aggregation_strategies, exclude_carriers=exclude_carriers, ) @@ -419,7 +415,6 @@ def remove_stubs( renewable_carriers, length_factor, simplify_network, - output, aggregation_strategies=dict(), ): logger.info("Removing stubs") @@ -436,7 +431,6 @@ def remove_stubs( n, busmap, connection_costs_to_bus, - output, aggregation_strategies=aggregation_strategies, exclude_carriers=simplify_network["exclude_carriers"], ) @@ -556,7 +550,6 @@ if __name__ == "__main__": params.length_factor, params.p_max_pu, params.simplify_network["exclude_carriers"], - snakemake.output, params.aggregation_strategies, ) @@ -569,7 +562,6 @@ if __name__ == "__main__": params.renewable_carriers, params.length_factor, params.simplify_network, - snakemake.output, aggregation_strategies=params.aggregation_strategies, ) busmaps.append(stub_map) From 48f199f93671338c0f8a5e159804e4e8c752cbbd Mon Sep 17 00:00:00 2001 From: martacki Date: Tue, 16 Apr 2024 15:46:36 +0200 Subject: [PATCH 570/591] remove UA from countries list for synthetic load data --- scripts/build_electricity_demand.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 9174672d..7615bbc6 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -311,6 +311,8 @@ if __name__ == "__main__": logger.info("Supplement missing data with synthetic data.") fn = snakemake.input.synthetic synthetic_load = pd.read_csv(fn, index_col=0, parse_dates=True) + # "UA" does not appear in synthetic load data + countries = list(set(countries) - set(["UA"])) synthetic_load = synthetic_load.loc[snapshots, countries] load = load.combine_first(synthetic_load) From c505ea174e7b2272db98fdeefae2540062ea7ad5 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 24 Apr 2024 16:23:43 +0200 Subject: [PATCH 571/591] doc: update solver requirements [skip ci] --- config/config.default.yaml | 2 +- doc/configtables/solving.csv | 2 +- doc/installation.rst | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 42132f22..0db6dc03 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -770,7 +770,7 @@ solving: solver_options: highs-default: - # refer to https://ergo-code.github.io/HiGHS/options/definitions.html#solver + # refer to https://ergo-code.github.io/HiGHS/dev/options/definitions/ threads: 4 solver: "ipm" run_crossover: "off" diff --git a/doc/configtables/solving.csv b/doc/configtables/solving.csv index 7189399b..4d245195 100644 --- a/doc/configtables/solving.csv +++ b/doc/configtables/solving.csv @@ -20,7 +20,7 @@ constraints ,,, -- BAU,bool,"{'true','false'}",Add a per-``carrier`` minimal overall capacity; i.e. at least ``40GW`` of ``OCGT`` in Europe; configured in ``electricity: BAU_mincapacities`` -- SAFE,bool,"{'true','false'}",Add a capacity reserve margin of a certain fraction above the peak demand to which renewable generators and storage do *not* contribute. Ignores network. solver,,, --- name,--,"One of {'gurobi', 'cplex', 'cbc', 'glpk', 'ipopt'}; potentially more possible",Solver to use for optimisation problems in the workflow; e.g. clustering and linear optimal power flow. +-- name,--,"One of {'gurobi', 'cplex', 'highs', 'cbc', 'glpk'}; potentially more possible",Solver to use for optimisation problems in the workflow; e.g. clustering and linear optimal power flow. -- options,--,Key listed under ``solver_options``.,Link to specific parameter settings. solver_options,,dict,Dictionaries with solver-specific parameter settings. mem,MB,int,Estimated maximum memory requirement for solving networks. diff --git a/doc/installation.rst b/doc/installation.rst index dd5c912e..45404e1f 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -62,7 +62,7 @@ PyPSA is known to work with the free software - `HiGHS `__ - `Cbc `__ - `GLPK `__ (`WinGLKP `__) -- `Ipopt `__ +- `SCIP `__ and the non-free, commercial software (for some of which free academic licenses are available) @@ -80,7 +80,7 @@ Nevertheless, you can still use open-source solvers for smaller problems. .. note:: The rules :mod:`cluster_network` and :mod:`simplify_network` solve a mixed-integer quadratic optimisation problem for clustering. - The open-source solvers HiGHS, Cbc and GlPK cannot handle this. A fallback to SCIP is implemented in this case. + The open-source solvers HiGHS, Cbc and GlPK cannot handle this. A fallback to SCIP is implemented in this case, which is included in the standard environment specifications. For an open-source solver setup install in your ``conda`` environment on OSX/Linux. To install the default solver Gurobi, run .. code:: bash From 29f6c9507f01c5a9cca7f8435c6260143f60dd6f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:36:31 +0000 Subject: [PATCH 572/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index ed341d2f..c074bdbd 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -433,7 +433,7 @@ rule add_electricity: else resources("networks/base.nc") ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), @@ -478,7 +478,7 @@ rule simplify_network: input: network=resources("networks/elec.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), @@ -526,7 +526,7 @@ rule cluster_network: else [] ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), output: network=resources("networks/elec_s{simpl}_{clusters}.nc"), @@ -555,7 +555,7 @@ rule add_extra_components: input: network=resources("networks/elec_s{simpl}_{clusters}.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), output: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), @@ -590,7 +590,7 @@ rule prepare_network: input: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: From 884d308d8b1de46988db184c94443299d1935293 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 25 Apr 2024 17:45:51 +0200 Subject: [PATCH 573/591] Bump powerplantmatching version Needed in order to get renewable capacities from pm.IRENA newer than 2020; updated to 2023 in version 0.5.13 --- envs/environment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/envs/environment.yaml b/envs/environment.yaml index ee1d1605..8f425805 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -25,7 +25,7 @@ dependencies: - yaml - pytables - lxml -- powerplantmatching>=0.5.5,!=0.5.9 +- powerplantmatching>=0.5.13 - numpy - pandas>=2.1 - geopandas>=0.11.0 From a4a2af5404abf0a5452d68a22986b7cb7d0943ee Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Thu, 25 Apr 2024 18:05:41 +0200 Subject: [PATCH 574/591] Fix double space in existing capacities The `name_suffix` variable already includes a space after the bus name. --- scripts/add_existing_baseyear.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index e75fe5a2..0ae23125 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -310,7 +310,7 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas n.madd( "Generator", new_capacity.index, - suffix=" " + name_suffix, + suffix=name_suffix, bus=new_capacity.index, carrier=generator, p_nom=new_capacity, From 105cadaf7b83a1a549482c3f39f33e2285a0894c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:08:45 +0000 Subject: [PATCH 575/591] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- rules/build_electricity.smk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index ed341d2f..c074bdbd 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -433,7 +433,7 @@ rule add_electricity: else resources("networks/base.nc") ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), regions=resources("regions_onshore.geojson"), powerplants=resources("powerplants.csv"), @@ -478,7 +478,7 @@ rule simplify_network: input: network=resources("networks/elec.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), regions_onshore=resources("regions_onshore.geojson"), regions_offshore=resources("regions_offshore.geojson"), @@ -526,7 +526,7 @@ rule cluster_network: else [] ), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), output: network=resources("networks/elec_s{simpl}_{clusters}.nc"), @@ -555,7 +555,7 @@ rule add_extra_components: input: network=resources("networks/elec_s{simpl}_{clusters}.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), output: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), @@ -590,7 +590,7 @@ rule prepare_network: input: resources("networks/elec_s{simpl}_{clusters}_ec.nc"), tech_costs=lambda w: resources( - f"costs_{config_provider('costs', 'year')(w)}.csv" + f"costs_{config_provider('costs', 'year') (w)}.csv" ), co2_price=lambda w: resources("co2_price.csv") if "Ept" in w.opts else [], output: From edc1d4991a0c84330a6390d043880447a6db7a40 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 26 Apr 2024 09:35:54 +0200 Subject: [PATCH 576/591] reenable windows ci with snakemake 8.11 --- .github/workflows/ci.yaml | 2 +- Snakefile | 2 +- envs/environment.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7aabf0e6..c17c0425 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,7 +31,7 @@ jobs: os: - ubuntu-latest - macos-latest -# - windows-latest + - windows-latest inhouse: - stable - master diff --git a/Snakefile b/Snakefile index ba93a869..e6980708 100644 --- a/Snakefile +++ b/Snakefile @@ -8,7 +8,7 @@ from os.path import normpath, exists from shutil import copyfile, move, rmtree from snakemake.utils import min_version -min_version("8.5") +min_version("8.11") from scripts._helpers import path_provider, copy_default_files, get_scenarios, get_rdir diff --git a/envs/environment.yaml b/envs/environment.yaml index ee1d1605..0a378fdc 100644 --- a/envs/environment.yaml +++ b/envs/environment.yaml @@ -20,7 +20,7 @@ dependencies: - openpyxl!=3.1.1 - pycountry - seaborn -- snakemake-minimal>=8.5 +- snakemake-minimal>=8.11 - memory_profiler - yaml - pytables From 162d376ce96753fb09c24d3968b7115ecf29cad9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 19:55:49 +0000 Subject: [PATCH 577/591] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 24.4.0 → 24.4.2](https://github.com/psf/black-pre-commit-mirror/compare/24.4.0...24.4.2) --- .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 a3aab9ed..3ffe8d9e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,7 +51,7 @@ repos: # Formatting with "black" coding style - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.4.0 + rev: 24.4.2 hooks: # Format Python files - id: black From 54e3d2bb1bad28370170b6b90919cebc5cb27a98 Mon Sep 17 00:00:00 2001 From: Thomas Gilon Date: Tue, 23 Apr 2024 23:04:26 +0200 Subject: [PATCH 578/591] Fix typo --- 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 b6ec98b2..9f53e317 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -97,7 +97,7 @@ def define_spatial(nodes, options): spatial.gas.industry = nodes + " gas for industry" spatial.gas.industry_cc = nodes + " gas for industry CC" spatial.gas.biogas_to_gas = nodes + " biogas to gas" - spatial.gas.biogas_to_gas_cc = nodes + "biogas to gas CC" + spatial.gas.biogas_to_gas_cc = nodes + " biogas to gas CC" else: spatial.gas.nodes = ["EU gas"] spatial.gas.locations = ["EU"] From 91e990c0b04e077dc5f026031f296ef3548a5a1b Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 3 May 2024 09:36:40 +0200 Subject: [PATCH 579/591] update env fixed --- envs/environment.fixed.yaml | 893 +++++++++++++++++++----------------- 1 file changed, 460 insertions(+), 433 deletions(-) diff --git a/envs/environment.fixed.yaml b/envs/environment.fixed.yaml index 8bbd70bf..61c25375 100644 --- a/envs/environment.fixed.yaml +++ b/envs/environment.fixed.yaml @@ -7,440 +7,467 @@ channels: - bioconda - http://conda.anaconda.org/gurobi - conda-forge -- defaults dependencies: -- _libgcc_mutex=0.1 -- _openmp_mutex=4.5 -- affine=2.4.0 -- alsa-lib=1.2.10 -- ampl-mp=3.1.0 -- amply=0.1.6 -- appdirs=1.4.4 -- asttokens=2.4.1 -- atk-1.0=2.38.0 -- atlite=0.2.12 -- attr=2.5.1 -- attrs=23.2.0 -- aws-c-auth=0.7.15 -- aws-c-cal=0.6.9 -- aws-c-common=0.9.12 -- aws-c-compression=0.2.17 -- aws-c-event-stream=0.4.1 -- aws-c-http=0.8.0 -- aws-c-io=0.14.3 -- aws-c-mqtt=0.10.1 -- aws-c-s3=0.5.0 -- aws-c-sdkutils=0.1.14 -- aws-checksums=0.1.17 -- aws-crt-cpp=0.26.1 -- aws-sdk-cpp=1.11.242 -- azure-core-cpp=1.10.3 -- azure-storage-blobs-cpp=12.10.0 -- azure-storage-common-cpp=12.5.0 -- beautifulsoup4=4.12.3 -- blosc=1.21.5 -- bokeh=3.3.4 -- bottleneck=1.3.7 -- branca=0.7.1 -- brotli=1.1.0 -- brotli-bin=1.1.0 -- brotli-python=1.1.0 -- bzip2=1.0.8 -- c-ares=1.26.0 -- c-blosc2=2.13.2 -- ca-certificates=2024.2.2 -- cairo=1.18.0 -- cartopy=0.22.0 -- cdsapi=0.6.1 -- certifi=2024.2.2 -- cffi=1.16.0 -- cfgv=3.3.1 -- cfitsio=4.3.1 -- cftime=1.6.3 -- charset-normalizer=3.3.2 -- click=8.1.7 -- click-plugins=1.1.1 -- cligj=0.7.2 -- cloudpickle=3.0.0 -- coin-or-cbc=2.10.10 -- coin-or-cgl=0.60.7 -- coin-or-clp=1.17.8 -- coin-or-osi=0.108.8 -- coin-or-utils=2.11.9 -- coincbc=2.10.10 -- colorama=0.4.6 -- configargparse=1.7 -- connection_pool=0.0.3 -- contourpy=1.2.0 -- country_converter=1.2 -- cppad=20240000.2 -- cycler=0.12.1 -- cytoolz=0.12.3 -- dask=2024.2.0 -- dask-core=2024.2.0 -- datrie=0.8.2 -- dbus=1.13.6 -- decorator=5.1.1 -- deprecation=2.1.0 -- descartes=1.1.0 -- distlib=0.3.8 -- distributed=2024.2.0 -- distro=1.9.0 -- docutils=0.20.1 -- dpath=2.1.6 -- entsoe-py=0.6.6 -- et_xmlfile=1.1.0 -- exceptiongroup=1.2.0 -- executing=2.0.1 -- expat=2.5.0 -- filelock=3.13.1 -- fiona=1.9.5 -- folium=0.15.1 -- font-ttf-dejavu-sans-mono=2.37 -- font-ttf-inconsolata=3.000 -- font-ttf-source-code-pro=2.038 -- font-ttf-ubuntu=0.83 -- fontconfig=2.14.2 -- fonts-conda-ecosystem=1 -- fonts-conda-forge=1 -- fonttools=4.49.0 -- freetype=2.12.1 -- freexl=2.0.0 -- fribidi=1.0.10 -- fsspec=2024.2.0 -- gdal=3.8.4 -- gdk-pixbuf=2.42.10 -- geographiclib=1.52 -- geojson-rewind=1.1.0 -- geopandas=0.14.3 -- geopandas-base=0.14.3 -- geopy=2.4.1 -- geos=3.12.1 -- geotiff=1.7.1 -- gettext=0.21.1 -- gflags=2.2.2 -- giflib=5.2.1 -- gitdb=4.0.11 -- gitpython=3.1.42 -- glib=2.78.4 -- glib-tools=2.78.4 -- glog=0.6.0 -- glpk=5.0 -- gmp=6.3.0 -- graphite2=1.3.13 -- graphviz=9.0.0 -- gst-plugins-base=1.22.9 -- gstreamer=1.22.9 -- gtk2=2.24.33 -- gts=0.7.6 -- harfbuzz=8.3.0 -- hdf4=4.2.15 -- hdf5=1.14.3 -- humanfriendly=10.0 -- icu=73.2 -- identify=2.5.35 -- idna=3.6 -- importlib-metadata=7.0.1 -- importlib_metadata=7.0.1 -- importlib_resources=6.1.1 -- iniconfig=2.0.0 -- ipopt=3.14.14 -- ipython=8.21.0 -- jedi=0.19.1 -- jinja2=3.1.3 -- joblib=1.3.2 -- json-c=0.17 -- jsonschema=4.21.1 -- jsonschema-specifications=2023.12.1 -- jupyter_core=5.7.1 -- kealib=1.5.3 -- keyutils=1.6.1 -- kiwisolver=1.4.5 -- krb5=1.21.2 -- lame=3.100 -- lcms2=2.16 -- ld_impl_linux-64=2.40 -- lerc=4.0.0 -- libabseil=20230802.1 -- libaec=1.1.2 -- libarchive=3.7.2 -- libarrow=15.0.0 -- libarrow-acero=15.0.0 -- libarrow-dataset=15.0.0 -- libarrow-flight=15.0.0 -- libarrow-flight-sql=15.0.0 -- libarrow-gandiva=15.0.0 -- libarrow-substrait=15.0.0 -- libblas=3.9.0 -- libboost-headers=1.84.0 -- libbrotlicommon=1.1.0 -- libbrotlidec=1.1.0 -- libbrotlienc=1.1.0 -- libcap=2.69 -- libcblas=3.9.0 -- libclang=15.0.7 -- libclang13=15.0.7 -- libcrc32c=1.1.2 -- libcups=2.3.3 -- libcurl=8.5.0 -- libdeflate=1.19 -- libedit=3.1.20191231 -- libev=4.33 -- libevent=2.1.12 -- libexpat=2.5.0 -- libffi=3.4.2 -- libflac=1.4.3 -- libgcc-ng=13.2.0 -- libgcrypt=1.10.3 -- libgd=2.3.3 -- libgdal=3.8.4 -- libgfortran-ng=13.2.0 -- libgfortran5=13.2.0 -- libglib=2.78.4 -- libgomp=13.2.0 -- libgoogle-cloud=2.12.0 -- libgpg-error=1.47 -- libgrpc=1.60.1 -- libhwloc=2.9.3 -- libiconv=1.17 -- libjpeg-turbo=3.0.0 -- libkml=1.3.0 -- liblapack=3.9.0 -- liblapacke=3.9.0 -- libllvm15=15.0.7 -- libnetcdf=4.9.2 -- libnghttp2=1.58.0 -- libnl=3.9.0 -- libnsl=2.0.1 -- libnuma=2.0.16 -- libogg=1.3.4 -- libopenblas=0.3.26 -- libopus=1.3.1 -- libparquet=15.0.0 -- libpng=1.6.42 -- libpq=16.2 -- libprotobuf=4.25.1 -- libre2-11=2023.06.02 -- librsvg=2.56.3 -- librttopo=1.1.0 -- libscotch=7.0.4 -- libsndfile=1.2.2 -- libspatialindex=1.9.3 -- libspatialite=5.1.0 -- libspral=2023.09.07 -- libsqlite=3.45.1 -- libssh2=1.11.0 -- libstdcxx-ng=13.2.0 -- libsystemd0=255 -- libthrift=0.19.0 -- libtiff=4.6.0 -- libutf8proc=2.8.0 -- libuuid=2.38.1 -- libvorbis=1.3.7 -- libwebp=1.3.2 -- libwebp-base=1.3.2 -- libxcb=1.15 -- libxcrypt=4.4.36 -- libxkbcommon=1.6.0 -- libxml2=2.12.5 -- libxslt=1.1.39 -- libzip=1.10.1 -- libzlib=1.2.13 -- linopy=0.3.4 -- locket=1.0.0 -- lxml=5.1.0 -- lz4=4.3.3 -- lz4-c=1.9.4 -- lzo=2.10 -- mapclassify=2.6.1 -- markupsafe=2.1.5 -- matplotlib=3.8.3 -- matplotlib-base=3.8.3 -- matplotlib-inline=0.1.6 -- memory_profiler=0.61.0 -- metis=5.1.0 -- minizip=4.0.4 -- mpg123=1.32.4 -- msgpack-python=1.0.7 -- mumps-include=5.6.2 -- mumps-seq=5.6.2 -- munkres=1.1.4 -- mysql-common=8.0.33 -- mysql-libs=8.0.33 -- nbformat=5.9.2 -- ncurses=6.4 -- netcdf4=1.6.5 -- networkx=3.2.1 -- nodeenv=1.8.0 -- nomkl=1.0 -- nspr=4.35 -- nss=3.98 -- numexpr=2.9.0 -- numpy=1.26.4 -- openjdk=21.0.2 -- openjpeg=2.5.0 -- openpyxl=3.1.2 -- openssl=3.2.1 -- orc=1.9.2 -- packaging=23.2 -- pandas=2.2.0 -- pango=1.50.14 -- parso=0.8.3 -- partd=1.4.1 -- patsy=0.5.6 -- pcre2=10.42 -- pexpect=4.9.0 -- pickleshare=0.7.5 -- pillow=10.2.0 -- pip=24.0 -- pixman=0.43.2 -- pkgutil-resolve-name=1.3.10 -- plac=1.4.2 -- platformdirs=4.2.0 -- pluggy=1.4.0 -- ply=3.11 -- poppler=24.02.0 -- poppler-data=0.4.12 -- postgresql=16.2 -- powerplantmatching=0.5.11 -- pre-commit=3.6.2 -- progressbar2=4.3.2 -- proj=9.3.1 -- prompt-toolkit=3.0.42 -- psutil=5.9.8 -- pthread-stubs=0.4 -- ptyprocess=0.7.0 -- pulp=2.7.0 -- pulseaudio-client=16.1 -- pure_eval=0.2.2 -- py-cpuinfo=9.0.0 -- pyarrow=15.0.0 -- pyarrow-hotfix=0.6 -- pycountry=22.3.5 -- pycparser=2.21 -- pygments=2.17.2 -- pyomo=6.6.1 -- pyparsing=3.1.1 -- pyproj=3.6.1 -- pypsa=0.27.0 -- pyqt=5.15.9 -- pyqt5-sip=12.12.2 -- pyscipopt=4.4.0 -- pyshp=2.3.1 -- pysocks=1.7.1 -- pytables=3.9.2 -- pytest=8.0.0 -- python=3.11.8 -- python-dateutil=2.8.2 -- python-fastjsonschema=2.19.1 -- python-tzdata=2024.1 -- python-utils=3.8.2 -- python_abi=3.11 -- pytz=2024.1 -- pyxlsb=1.0.10 -- pyyaml=6.0.1 -- qt-main=5.15.8 -- rasterio=1.3.9 -- rdma-core=50.0 -- re2=2023.06.02 -- readline=8.2 -- referencing=0.33.0 -- requests=2.31.0 -- reretry=0.11.8 -- rioxarray=0.15.1 -- rpds-py=0.18.0 -- rtree=1.2.0 -- s2n=1.4.3 -- scikit-learn=1.4.1.post1 -- scip=8.1.0 -- scipy=1.12.0 -- scotch=7.0.4 -- seaborn=0.13.2 -- seaborn-base=0.13.2 -- setuptools=69.1.0 -- setuptools-scm=8.0.4 -- setuptools_scm=8.0.4 -- shapely=2.0.2 -- sip=6.7.12 -- six=1.16.0 -- smart_open=6.4.0 -- smmap=5.0.0 -- snakemake-minimal=7.32.4 -- snappy=1.1.10 -- snuggs=1.4.7 -- sortedcontainers=2.4.0 -- soupsieve=2.5 -- sqlite=3.45.1 -- stack_data=0.6.2 -- statsmodels=0.14.1 -- stopit=1.1.2 -- tabula-py=2.7.0 -- tabulate=0.9.0 -- tbb=2021.11.0 -- tblib=3.0.0 -- threadpoolctl=3.3.0 -- throttler=1.2.2 -- tiledb=2.20.0 -- tk=8.6.13 -- toml=0.10.2 -- tomli=2.0.1 -- toolz=0.12.1 -- toposort=1.10 -- tornado=6.3.3 -- tqdm=4.66.2 -- traitlets=5.14.1 -- typing-extensions=4.9.0 -- typing_extensions=4.9.0 -- tzcode=2024a -- tzdata=2024a -- ucx=1.15.0 -- ukkonen=1.0.1 -- unidecode=1.3.8 -- unixodbc=2.3.12 -- uriparser=0.9.7 -- urllib3=2.2.1 -- validators=0.22.0 -- virtualenv=20.25.0 -- wcwidth=0.2.13 -- wheel=0.42.0 -- wrapt=1.16.0 -- xarray=2024.2.0 -- xcb-util=0.4.0 -- xcb-util-image=0.4.0 -- xcb-util-keysyms=0.4.0 -- xcb-util-renderutil=0.3.9 -- xcb-util-wm=0.4.1 -- xerces-c=3.2.5 -- xkeyboard-config=2.41 -- xlrd=2.0.1 -- xorg-fixesproto=5.0 -- xorg-inputproto=2.3.2 -- xorg-kbproto=1.0.7 -- xorg-libice=1.1.1 -- xorg-libsm=1.2.4 -- xorg-libx11=1.8.7 -- xorg-libxau=1.0.11 -- xorg-libxdmcp=1.1.3 -- xorg-libxext=1.3.4 -- xorg-libxfixes=5.0.3 -- xorg-libxi=1.7.10 -- xorg-libxrender=0.9.11 -- xorg-libxt=1.3.0 -- xorg-libxtst=1.2.3 -- xorg-recordproto=1.14.2 -- xorg-renderproto=0.11.1 -- xorg-xextproto=7.3.0 -- xorg-xf86vidmodeproto=2.3.1 -- xorg-xproto=7.0.31 -- xyzservices=2023.10.1 -- xz=5.2.6 -- yaml=0.2.5 -- yte=1.5.4 -- zict=3.0.0 -- zipp=3.17.0 -- zlib=1.2.13 -- zlib-ng=2.0.7 -- zstd=1.5.5 +- _libgcc_mutex=0.1=conda_forge +- _openmp_mutex=4.5=2_gnu +- affine=2.4.0=pyhd8ed1ab_0 +- alsa-lib=1.2.11=hd590300_1 +- ampl-mp=3.1.0=h2cc385e_1006 +- amply=0.1.6=pyhd8ed1ab_0 +- appdirs=1.4.4=pyh9f0ad1d_0 +- argparse-dataclass=2.0.0=pyhd8ed1ab_0 +- asttokens=2.4.1=pyhd8ed1ab_0 +- atk-1.0=2.38.0=h04ea711_2 +- atlite=0.2.12=pyhd8ed1ab_0 +- attr=2.5.1=h166bdaf_1 +- attrs=23.2.0=pyh71513ae_0 +- aws-c-auth=0.7.18=he0b1f16_0 +- aws-c-cal=0.6.11=heb1d5e4_0 +- aws-c-common=0.9.15=hd590300_0 +- aws-c-compression=0.2.18=hce8ee76_3 +- aws-c-event-stream=0.4.2=h01f5eca_8 +- aws-c-http=0.8.1=hdb68c23_10 +- aws-c-io=0.14.7=hbfbeace_6 +- aws-c-mqtt=0.10.4=h50844eb_0 +- aws-c-s3=0.5.7=h6be9164_2 +- aws-c-sdkutils=0.1.15=hce8ee76_3 +- aws-checksums=0.1.18=hce8ee76_3 +- aws-crt-cpp=0.26.8=h2150271_2 +- aws-sdk-cpp=1.11.267=hddb5a97_7 +- azure-core-cpp=1.11.1=h91d86a7_1 +- azure-identity-cpp=1.6.0=hf1915f5_1 +- azure-storage-blobs-cpp=12.10.0=h00ab1b0_1 +- azure-storage-common-cpp=12.5.0=h94269e2_4 +- beautifulsoup4=4.12.3=pyha770c72_0 +- blosc=1.21.5=hc2324a3_1 +- bokeh=3.4.1=pyhd8ed1ab_0 +- bottleneck=1.3.8=py311h1f0f07a_0 +- branca=0.7.2=pyhd8ed1ab_0 +- brotli=1.1.0=hd590300_1 +- brotli-bin=1.1.0=hd590300_1 +- brotli-python=1.1.0=py311hb755f60_1 +- bzip2=1.0.8=hd590300_5 +- c-ares=1.28.1=hd590300_0 +- c-blosc2=2.14.4=hb4ffafa_1 +- ca-certificates=2024.2.2=hbcca054_0 +- cads-api-client=1.0.0=pyhd8ed1ab_0 +- cairo=1.18.0=h3faef2a_0 +- cartopy=0.23.0=py311h320fe9a_0 +- cdsapi=0.7.0=pyhd8ed1ab_0 +- certifi=2024.2.2=pyhd8ed1ab_0 +- cffi=1.16.0=py311hb3a22ac_0 +- cfgv=3.3.1=pyhd8ed1ab_0 +- cfitsio=4.4.0=hbdc6101_1 +- cftime=1.6.3=py311h1f0f07a_0 +- charset-normalizer=3.3.2=pyhd8ed1ab_0 +- click=8.1.7=unix_pyh707e725_0 +- click-plugins=1.1.1=py_0 +- cligj=0.7.2=pyhd8ed1ab_1 +- cloudpickle=3.0.0=pyhd8ed1ab_0 +- coin-or-cbc=2.10.10=h9002f0b_0 +- coin-or-cgl=0.60.7=h516709c_0 +- coin-or-clp=1.17.8=h1ee7a9c_0 +- coin-or-osi=0.108.10=haf5fa05_0 +- coin-or-utils=2.11.11=hee58242_0 +- coincbc=2.10.10=0_metapackage +- colorama=0.4.6=pyhd8ed1ab_0 +- conda-inject=1.3.1=pyhd8ed1ab_0 +- configargparse=1.7=pyhd8ed1ab_0 +- connection_pool=0.0.3=pyhd3deb0d_0 +- contourpy=1.2.1=py311h9547e67_0 +- country_converter=1.2=pyhd8ed1ab_0 +- cppad=20240000.4=h59595ed_0 +- cycler=0.12.1=pyhd8ed1ab_0 +- cytoolz=0.12.3=py311h459d7ec_0 +- dask=2024.4.2=pyhd8ed1ab_0 +- dask-core=2024.4.2=pyhd8ed1ab_0 +- dask-expr=1.0.14=pyhd8ed1ab_0 +- datrie=0.8.2=py311h459d7ec_7 +- dbus=1.13.6=h5008d03_3 +- decorator=5.1.1=pyhd8ed1ab_0 +- deprecation=2.1.0=pyh9f0ad1d_0 +- descartes=1.1.0=py_4 +- distlib=0.3.8=pyhd8ed1ab_0 +- distributed=2024.4.2=pyhd8ed1ab_0 +- distro=1.9.0=pyhd8ed1ab_0 +- docutils=0.21.2=pyhd8ed1ab_0 +- dpath=2.1.6=pyha770c72_0 +- entsoe-py=0.6.7=pyhd8ed1ab_0 +- et_xmlfile=1.1.0=pyhd8ed1ab_0 +- exceptiongroup=1.2.0=pyhd8ed1ab_2 +- executing=2.0.1=pyhd8ed1ab_0 +- expat=2.6.2=h59595ed_0 +- filelock=3.14.0=pyhd8ed1ab_0 +- fiona=1.9.6=py311hf8e0aa6_0 +- fmt=10.2.1=h00ab1b0_0 +- folium=0.16.0=pyhd8ed1ab_0 +- font-ttf-dejavu-sans-mono=2.37=hab24e00_0 +- font-ttf-inconsolata=3.000=h77eed37_0 +- font-ttf-source-code-pro=2.038=h77eed37_0 +- font-ttf-ubuntu=0.83=h77eed37_2 +- fontconfig=2.14.2=h14ed4e7_0 +- fonts-conda-ecosystem=1=0 +- fonts-conda-forge=1=0 +- fonttools=4.51.0=py311h459d7ec_0 +- freetype=2.12.1=h267a509_2 +- freexl=2.0.0=h743c826_0 +- fribidi=1.0.10=h36c2ea0_0 +- fsspec=2024.3.1=pyhca7485f_0 +- gdal=3.8.5=py311hd032c08_2 +- gdk-pixbuf=2.42.11=hb9ae30d_0 +- geographiclib=2.0=pyhd8ed1ab_0 +- geojson-rewind=1.1.0=pyhd8ed1ab_0 +- geopandas=0.14.4=pyhd8ed1ab_0 +- geopandas-base=0.14.4=pyha770c72_0 +- geopy=2.4.1=pyhd8ed1ab_1 +- geos=3.12.1=h59595ed_0 +- geotiff=1.7.1=h6cf1f90_16 +- gettext=0.22.5=h59595ed_2 +- gettext-tools=0.22.5=h59595ed_2 +- gflags=2.2.2=he1b5a44_1004 +- giflib=5.2.2=hd590300_0 +- gitdb=4.0.11=pyhd8ed1ab_0 +- gitpython=3.1.43=pyhd8ed1ab_0 +- glib=2.80.0=hf2295e7_6 +- glib-tools=2.80.0=hde27a5a_6 +- glog=0.7.0=hed5481d_0 +- glpk=5.0=h445213a_0 +- gmp=6.3.0=h59595ed_1 +- graphite2=1.3.13=h59595ed_1003 +- graphviz=9.0.0=h78e8752_1 +- gst-plugins-base=1.24.1=hfa15dee_2 +- gstreamer=1.24.1=h98fc4e7_2 +- gtk2=2.24.33=h280cfa0_4 +- gts=0.7.6=h977cf35_4 +- harfbuzz=8.4.0=h3d44ed6_0 +- hdf4=4.2.15=h2a13503_7 +- hdf5=1.14.3=nompi_h4f84152_101 +- humanfriendly=10.0=pyhd8ed1ab_6 +- icu=73.2=h59595ed_0 +- identify=2.5.36=pyhd8ed1ab_0 +- idna=3.7=pyhd8ed1ab_0 +- immutables=0.20=py311h459d7ec_1 +- importlib-metadata=7.1.0=pyha770c72_0 +- importlib_metadata=7.1.0=hd8ed1ab_0 +- importlib_resources=6.4.0=pyhd8ed1ab_0 +- iniconfig=2.0.0=pyhd8ed1ab_0 +- ipopt=3.14.16=hf967516_0 +- ipython=8.22.2=pyh707e725_0 +- jedi=0.19.1=pyhd8ed1ab_0 +- jinja2=3.1.3=pyhd8ed1ab_0 +- joblib=1.4.2=pyhd8ed1ab_0 +- json-c=0.17=h7ab15ed_0 +- jsonschema=4.22.0=pyhd8ed1ab_0 +- jsonschema-specifications=2023.12.1=pyhd8ed1ab_0 +- jupyter_core=5.7.2=py311h38be061_0 +- kealib=1.5.3=h2f55d51_0 +- keyutils=1.6.1=h166bdaf_0 +- kiwisolver=1.4.5=py311h9547e67_1 +- krb5=1.21.2=h659d440_0 +- lame=3.100=h166bdaf_1003 +- lcms2=2.16=hb7c19ff_0 +- ld_impl_linux-64=2.40=h55db66e_0 +- lerc=4.0.0=h27087fc_0 +- libabseil=20240116.2=cxx17_h59595ed_0 +- libaec=1.1.3=h59595ed_0 +- libarchive=3.7.2=h2aa1ff5_1 +- libarrow=15.0.2=hefa796f_6_cpu +- libarrow-acero=15.0.2=hbabe93e_6_cpu +- libarrow-dataset=15.0.2=hbabe93e_6_cpu +- libarrow-flight=15.0.2=hc4f8a93_6_cpu +- libarrow-flight-sql=15.0.2=he4f5ca8_6_cpu +- libarrow-gandiva=15.0.2=hc1954e9_6_cpu +- libarrow-substrait=15.0.2=he4f5ca8_6_cpu +- libasprintf=0.22.5=h661eb56_2 +- libasprintf-devel=0.22.5=h661eb56_2 +- libblas=3.9.0=22_linux64_openblas +- libboost-headers=1.84.0=ha770c72_2 +- libbrotlicommon=1.1.0=hd590300_1 +- libbrotlidec=1.1.0=hd590300_1 +- libbrotlienc=1.1.0=hd590300_1 +- libcap=2.69=h0f662aa_0 +- libcblas=3.9.0=22_linux64_openblas +- libclang-cpp15=15.0.7=default_h127d8a8_5 +- libclang13=18.1.4=default_h5d6823c_0 +- libcrc32c=1.1.2=h9c3ff4c_0 +- libcups=2.3.3=h4637d8d_4 +- libcurl=8.7.1=hca28451_0 +- libdeflate=1.20=hd590300_0 +- libedit=3.1.20191231=he28a2e2_2 +- libev=4.33=hd590300_2 +- libevent=2.1.12=hf998b51_1 +- libexpat=2.6.2=h59595ed_0 +- libffi=3.4.2=h7f98852_5 +- libflac=1.4.3=h59595ed_0 +- libgcc-ng=13.2.0=h77fa898_6 +- libgcrypt=1.10.3=hd590300_0 +- libgd=2.3.3=h119a65a_9 +- libgdal=3.8.5=hf9625ee_2 +- libgettextpo=0.22.5=h59595ed_2 +- libgettextpo-devel=0.22.5=h59595ed_2 +- libgfortran-ng=13.2.0=h69a702a_6 +- libgfortran5=13.2.0=h43f5ff8_6 +- libglib=2.80.0=hf2295e7_6 +- libgomp=13.2.0=h77fa898_6 +- libgoogle-cloud=2.23.0=h9be4e54_1 +- libgoogle-cloud-storage=2.23.0=hc7a4891_1 +- libgpg-error=1.49=h4f305b6_0 +- libgrpc=1.62.2=h15f2491_0 +- libhwloc=2.9.3=default_h554bfaf_1009 +- libiconv=1.17=hd590300_2 +- libjpeg-turbo=3.0.0=hd590300_1 +- libkml=1.3.0=h01aab08_1018 +- liblapack=3.9.0=22_linux64_openblas +- liblapacke=3.9.0=22_linux64_openblas +- libllvm15=15.0.7=hb3ce162_4 +- libllvm16=16.0.6=hb3ce162_3 +- libllvm18=18.1.4=h2448989_0 +- libnetcdf=4.9.2=nompi_h9612171_113 +- libnghttp2=1.58.0=h47da74e_1 +- libnl=3.9.0=hd590300_0 +- libnsl=2.0.1=hd590300_0 +- libogg=1.3.4=h7f98852_1 +- libopenblas=0.3.27=pthreads_h413a1c8_0 +- libopus=1.3.1=h7f98852_1 +- libparquet=15.0.2=hacf5a1f_6_cpu +- libpng=1.6.43=h2797004_0 +- libpq=16.2=h33b98f1_1 +- libprotobuf=4.25.3=h08a7969_0 +- libre2-11=2023.09.01=h5a48ba9_2 +- librsvg=2.58.0=hadf69e7_1 +- librttopo=1.1.0=h8917695_15 +- libscotch=7.0.4=h91e35bf_1 +- libsndfile=1.2.2=hc60ed4a_1 +- libspatialindex=1.9.3=h9c3ff4c_4 +- libspatialite=5.1.0=h6f065fc_5 +- libspral=2024.01.18=h6aa6db2_0 +- libsqlite=3.45.3=h2797004_0 +- libssh2=1.11.0=h0841786_0 +- libstdcxx-ng=13.2.0=hc0a3c3a_6 +- libsystemd0=255=h3516f8a_1 +- libthrift=0.19.0=hb90f79a_1 +- libtiff=4.6.0=h1dd3fc0_3 +- libutf8proc=2.8.0=h166bdaf_0 +- libuuid=2.38.1=h0b41bf4_0 +- libvorbis=1.3.7=h9c3ff4c_0 +- libwebp=1.4.0=h2c329e2_0 +- libwebp-base=1.4.0=hd590300_0 +- libxcb=1.15=h0b41bf4_0 +- libxcrypt=4.4.36=hd590300_1 +- libxkbcommon=1.7.0=h662e7e4_0 +- libxml2=2.12.6=h232c23b_2 +- libxslt=1.1.39=h76b75d6_0 +- libzip=1.10.1=h2629f0a_3 +- libzlib=1.2.13=hd590300_5 +- linopy=0.3.8=pyhd8ed1ab_0 +- locket=1.0.0=pyhd8ed1ab_0 +- lxml=5.2.1=py311hc0a218f_0 +- lz4=4.3.3=py311h38e4bf4_0 +- lz4-c=1.9.4=hcb278e6_0 +- lzo=2.10=hd590300_1001 +- mapclassify=2.6.1=pyhd8ed1ab_0 +- markupsafe=2.1.5=py311h459d7ec_0 +- matplotlib=3.8.4=py311h38be061_0 +- matplotlib-base=3.8.4=py311h54ef318_0 +- matplotlib-inline=0.1.7=pyhd8ed1ab_0 +- memory_profiler=0.61.0=pyhd8ed1ab_0 +- metis=5.1.0=h59595ed_1007 +- minizip=4.0.5=h0ab5242_0 +- mpfr=4.2.1=h9458935_1 +- mpg123=1.32.6=h59595ed_0 +- msgpack-python=1.0.7=py311h9547e67_0 +- multiurl=0.3.1=pyhd8ed1ab_0 +- mumps-include=5.6.2=ha770c72_4 +- mumps-seq=5.6.2=hfef103a_4 +- munkres=1.1.4=pyh9f0ad1d_0 +- mysql-common=8.3.0=hf1915f5_4 +- mysql-libs=8.3.0=hca2cd23_4 +- nbformat=5.10.4=pyhd8ed1ab_0 +- ncurses=6.4.20240210=h59595ed_0 +- netcdf4=1.6.5=nompi_py311he8ad708_100 +- networkx=3.3=pyhd8ed1ab_1 +- nodeenv=1.8.0=pyhd8ed1ab_0 +- nomkl=1.0=h5ca1d4c_0 +- nspr=4.35=h27087fc_0 +- nss=3.98=h1d7d5a4_0 +- numexpr=2.9.0=py311h039bad6_100 +- numpy=1.26.4=py311h64a7726_0 +- openjdk=22.0.1=hb622114_0 +- openjpeg=2.5.2=h488ebb8_0 +- openpyxl=3.1.2=py311h459d7ec_1 +- openssl=3.3.0=hd590300_0 +- orc=2.0.0=h17fec99_1 +- packaging=24.0=pyhd8ed1ab_0 +- pandas=2.2.2=py311h320fe9a_0 +- pango=1.52.2=ha41ecd1_0 +- parso=0.8.4=pyhd8ed1ab_0 +- partd=1.4.1=pyhd8ed1ab_0 +- patsy=0.5.6=pyhd8ed1ab_0 +- pcre2=10.43=hcad00b1_0 +- pexpect=4.9.0=pyhd8ed1ab_0 +- pickleshare=0.7.5=py_1003 +- pillow=10.3.0=py311h18e6fac_0 +- pip=24.0=pyhd8ed1ab_0 +- pixman=0.43.2=h59595ed_0 +- pkgutil-resolve-name=1.3.10=pyhd8ed1ab_1 +- plac=1.4.3=pyhd8ed1ab_0 +- platformdirs=4.2.1=pyhd8ed1ab_0 +- pluggy=1.5.0=pyhd8ed1ab_0 +- ply=3.11=pyhd8ed1ab_2 +- poppler=24.04.0=hb6cd0d7_0 +- poppler-data=0.4.12=hd8ed1ab_0 +- postgresql=16.2=h82ecc9d_1 +- powerplantmatching=0.5.14=pyhd8ed1ab_0 +- pre-commit=3.7.0=pyha770c72_0 +- progressbar2=4.4.2=pyhd8ed1ab_0 +- proj=9.4.0=h1d62c97_1 +- prompt-toolkit=3.0.42=pyha770c72_0 +- psutil=5.9.8=py311h459d7ec_0 +- pthread-stubs=0.4=h36c2ea0_1001 +- ptyprocess=0.7.0=pyhd3deb0d_0 +- pulp=2.8.0=py311h38be061_0 +- pulseaudio-client=17.0=hb77b528_0 +- pure_eval=0.2.2=pyhd8ed1ab_0 +- py-cpuinfo=9.0.0=pyhd8ed1ab_0 +- pyarrow=15.0.2=py311hd5e4297_6_cpu +- pyarrow-hotfix=0.6=pyhd8ed1ab_0 +- pycountry=22.3.5=pyhd8ed1ab_0 +- pycparser=2.22=pyhd8ed1ab_0 +- pygments=2.17.2=pyhd8ed1ab_0 +- pyomo=6.6.1=py311hb755f60_0 +- pyparsing=3.1.2=pyhd8ed1ab_0 +- pyproj=3.6.1=py311hb3a3e68_6 +- pypsa=0.27.1=pyhd8ed1ab_0 +- pyqt=5.15.9=py311hf0fb5b6_5 +- pyqt5-sip=12.12.2=py311hb755f60_5 +- pyscipopt=5.0.1=py311hb755f60_0 +- pyshp=2.3.1=pyhd8ed1ab_0 +- pysocks=1.7.1=pyha2e5f31_6 +- pytables=3.9.2=py311h3e8b7c9_2 +- pytest=8.2.0=pyhd8ed1ab_0 +- python=3.11.9=hb806964_0_cpython +- python-dateutil=2.9.0=pyhd8ed1ab_0 +- python-fastjsonschema=2.19.1=pyhd8ed1ab_0 +- python-tzdata=2024.1=pyhd8ed1ab_0 +- python-utils=3.8.2=pyhd8ed1ab_0 +- python_abi=3.11=4_cp311 +- pytz=2024.1=pyhd8ed1ab_0 +- pyxlsb=1.0.10=pyhd8ed1ab_0 +- pyyaml=6.0.1=py311h459d7ec_1 +- qt-main=5.15.8=hc9dc06e_21 +- rasterio=1.3.10=py311h375a7ea_0 +- rdma-core=51.0=hd3aeb46_0 +- re2=2023.09.01=h7f4b329_2 +- readline=8.2=h8228510_1 +- referencing=0.35.1=pyhd8ed1ab_0 +- requests=2.31.0=pyhd8ed1ab_0 +- reretry=0.11.8=pyhd8ed1ab_0 +- rioxarray=0.15.5=pyhd8ed1ab_0 +- rpds-py=0.18.0=py311h46250e7_0 +- rtree=1.2.0=py311h3bb2b0f_0 +- s2n=1.4.12=h06160fa_0 +- scikit-learn=1.4.2=py311hc009520_0 +- scip=9.0.0=hded5f35_4 +- scipy=1.13.0=py311h64a7726_0 +- scotch=7.0.4=h23d43cc_1 +- seaborn=0.13.2=hd8ed1ab_2 +- seaborn-base=0.13.2=pyhd8ed1ab_2 +- setuptools=69.5.1=pyhd8ed1ab_0 +- setuptools-scm=8.0.4=pyhd8ed1ab_1 +- setuptools_scm=8.0.4=hd8ed1ab_1 +- shapely=2.0.4=py311h2032efe_0 +- sip=6.7.12=py311hb755f60_0 +- six=1.16.0=pyh6c4a22f_0 +- smart_open=7.0.4=pyhd8ed1ab_0 +- smmap=5.0.0=pyhd8ed1ab_0 +- snakemake-interface-common=1.17.2=pyhdfd78af_0 +- snakemake-interface-executor-plugins=9.1.1=pyhdfd78af_0 +- snakemake-interface-report-plugins=1.0.0=pyhdfd78af_0 +- snakemake-interface-storage-plugins=3.2.2=pyhdfd78af_0 +- snakemake-minimal=8.11.1=pyhdfd78af_0 +- snappy=1.2.0=hdb0a2a9_1 +- snuggs=1.4.7=py_0 +- sortedcontainers=2.4.0=pyhd8ed1ab_0 +- soupsieve=2.5=pyhd8ed1ab_1 +- spdlog=1.13.0=hd2e6256_0 +- sqlite=3.45.3=h2c6b66d_0 +- stack_data=0.6.2=pyhd8ed1ab_0 +- statsmodels=0.14.1=py311h1f0f07a_0 +- stopit=1.1.2=py_0 +- tabula-py=2.7.0=py311h38be061_1 +- tabulate=0.9.0=pyhd8ed1ab_1 +- tbb=2021.11.0=h00ab1b0_1 +- tblib=3.0.0=pyhd8ed1ab_0 +- threadpoolctl=3.5.0=pyhc1e730c_0 +- throttler=1.2.2=pyhd8ed1ab_0 +- tiledb=2.22.0=h27f064a_3 +- tk=8.6.13=noxft_h4845f30_101 +- toml=0.10.2=pyhd8ed1ab_0 +- tomli=2.0.1=pyhd8ed1ab_0 +- toolz=0.12.1=pyhd8ed1ab_0 +- toposort=1.10=pyhd8ed1ab_0 +- tornado=6.4=py311h459d7ec_0 +- tqdm=4.66.2=pyhd8ed1ab_0 +- traitlets=5.14.3=pyhd8ed1ab_0 +- typing-extensions=4.11.0=hd8ed1ab_0 +- typing_extensions=4.11.0=pyha770c72_0 +- tzcode=2024a=h3f72095_0 +- tzdata=2024a=h0c530f3_0 +- ucx=1.15.0=ha691c75_8 +- ukkonen=1.0.1=py311h9547e67_4 +- unidecode=1.3.8=pyhd8ed1ab_0 +- unixodbc=2.3.12=h661eb56_0 +- uriparser=0.9.7=h59595ed_1 +- urllib3=2.2.1=pyhd8ed1ab_0 +- validators=0.28.1=pyhd8ed1ab_0 +- virtualenv=20.26.1=pyhd8ed1ab_0 +- wcwidth=0.2.13=pyhd8ed1ab_0 +- wheel=0.43.0=pyhd8ed1ab_1 +- wrapt=1.16.0=py311h459d7ec_0 +- xarray=2024.3.0=pyhd8ed1ab_0 +- xcb-util=0.4.0=hd590300_1 +- xcb-util-image=0.4.0=h8ee46fc_1 +- xcb-util-keysyms=0.4.0=h8ee46fc_1 +- xcb-util-renderutil=0.3.9=hd590300_1 +- xcb-util-wm=0.4.1=h8ee46fc_1 +- xerces-c=3.2.5=hac6953d_0 +- xkeyboard-config=2.41=hd590300_0 +- xlrd=2.0.1=pyhd8ed1ab_3 +- xorg-fixesproto=5.0=h7f98852_1002 +- xorg-inputproto=2.3.2=h7f98852_1002 +- xorg-kbproto=1.0.7=h7f98852_1002 +- xorg-libice=1.1.1=hd590300_0 +- xorg-libsm=1.2.4=h7391055_0 +- xorg-libx11=1.8.9=h8ee46fc_0 +- xorg-libxau=1.0.11=hd590300_0 +- xorg-libxdmcp=1.1.3=h7f98852_0 +- xorg-libxext=1.3.4=h0b41bf4_2 +- xorg-libxfixes=5.0.3=h7f98852_1004 +- xorg-libxi=1.7.10=h7f98852_0 +- xorg-libxrender=0.9.11=hd590300_0 +- xorg-libxt=1.3.0=hd590300_1 +- xorg-libxtst=1.2.3=h7f98852_1002 +- xorg-recordproto=1.14.2=h7f98852_1002 +- xorg-renderproto=0.11.1=h7f98852_1002 +- xorg-xextproto=7.3.0=h0b41bf4_1003 +- xorg-xf86vidmodeproto=2.3.1=h7f98852_1002 +- xorg-xproto=7.0.31=h7f98852_1007 +- xyzservices=2024.4.0=pyhd8ed1ab_0 +- xz=5.2.6=h166bdaf_0 +- yaml=0.2.5=h7f98852_2 +- yte=1.5.4=pyha770c72_0 +- zict=3.0.0=pyhd8ed1ab_0 +- zipp=3.17.0=pyhd8ed1ab_0 +- zlib=1.2.13=hd590300_5 +- zlib-ng=2.0.7=h0b41bf4_0 +- zstd=1.5.5=hfc55251_0 - pip: - highspy==1.5.3 + - oauthlib==3.2.2 + - requests-oauthlib==1.3.1 + - snakemake-executor-plugin-cluster-generic==1.0.9 + - snakemake-executor-plugin-slurm==0.4.5 + - snakemake-executor-plugin-slurm-jobstep==0.2.1 + - snakemake-storage-plugin-http==0.2.3 - tsam==2.3.1 +prefix: /home/fabian/.miniconda3/envs/pypsa-eur From 2db729f8725e83aa0c3c98f9cad92fd9364a474e Mon Sep 17 00:00:00 2001 From: Fabian Hofmann Date: Fri, 3 May 2024 10:27:05 +0200 Subject: [PATCH 580/591] Update environment.fixed.yaml --- envs/environment.fixed.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/envs/environment.fixed.yaml b/envs/environment.fixed.yaml index 61c25375..260c17fd 100644 --- a/envs/environment.fixed.yaml +++ b/envs/environment.fixed.yaml @@ -470,4 +470,3 @@ dependencies: - snakemake-executor-plugin-slurm-jobstep==0.2.1 - snakemake-storage-plugin-http==0.2.3 - tsam==2.3.1 -prefix: /home/fabian/.miniconda3/envs/pypsa-eur From 76c201ef7d40f2a55aeb049f44b7795eea3adc51 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 3 May 2024 14:50:14 +0200 Subject: [PATCH 581/591] Integrate `build_bus_regions` into `base_network` Fixes a problem with the `build_bus_regions` writing to base.nc without declaring base.nc as an output. --- rules/build_electricity.smk | 25 +--- scripts/base_network.py | 163 +++++++++++++++++++++++++- scripts/build_bus_regions.py | 218 ----------------------------------- scripts/cluster_network.py | 2 +- scripts/simplify_network.py | 2 +- 5 files changed, 164 insertions(+), 246 deletions(-) delete mode 100644 scripts/build_bus_regions.py diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index c074bdbd..c8d19d50 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -86,7 +86,9 @@ rule base_network: offshore_shapes=resources("offshore_shapes.geojson"), europe_shape=resources("europe_shape.geojson"), output: - resources("networks/base.nc"), + base_network=resources("networks/base.nc"), + regions_onshore=resources("regions_onshore.geojson"), + regions_offshore=resources("regions_offshore.geojson"), log: logs("base_network.log"), benchmark: @@ -127,27 +129,6 @@ rule build_shapes: "../scripts/build_shapes.py" -rule build_bus_regions: - params: - countries=config_provider("countries"), - input: - country_shapes=resources("country_shapes.geojson"), - offshore_shapes=resources("offshore_shapes.geojson"), - base_network=resources("networks/base.nc"), - output: - regions_onshore=resources("regions_onshore.geojson"), - regions_offshore=resources("regions_offshore.geojson"), - log: - logs("build_bus_regions.log"), - threads: 1 - resources: - mem_mb=1000, - conda: - "../envs/environment.yaml" - script: - "../scripts/build_bus_regions.py" - - if config["enable"].get("build_cutout", False): rule build_cutout: diff --git a/scripts/base_network.py b/scripts/base_network.py index d96a7e54..1598568e 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -75,11 +75,11 @@ import shapely import shapely.prepared import shapely.wkt import yaml -from _helpers import configure_logging, get_snapshots, set_scenario_config +from _helpers import REGION_COLS, configure_logging, get_snapshots, set_scenario_config from packaging.version import Version, parse from scipy import spatial from scipy.sparse import csgraph -from shapely.geometry import LineString, Point +from shapely.geometry import LineString, Point, Polygon PD_GE_2_2 = parse(pd.__version__) >= Version("2.2") @@ -779,9 +779,147 @@ def base_network( return n +def voronoi_partition_pts(points, outline): + """ + Compute the polygons of a voronoi partition of `points` within the polygon + `outline`. Taken from + https://github.com/FRESNA/vresutils/blob/master/vresutils/graph.py. + + Attributes + ---------- + points : Nx2 - ndarray[dtype=float] + outline : Polygon + Returns + ------- + polygons : N - ndarray[dtype=Polygon|MultiPolygon] + """ + points = np.asarray(points) + + if len(points) == 1: + polygons = [outline] + else: + xmin, ymin = np.amin(points, axis=0) + xmax, ymax = np.amax(points, axis=0) + xspan = xmax - xmin + yspan = ymax - ymin + + # to avoid any network positions outside all Voronoi cells, append + # the corners of a rectangle framing these points + vor = spatial.Voronoi( + np.vstack( + ( + points, + [ + [xmin - 3.0 * xspan, ymin - 3.0 * yspan], + [xmin - 3.0 * xspan, ymax + 3.0 * yspan], + [xmax + 3.0 * xspan, ymin - 3.0 * yspan], + [xmax + 3.0 * xspan, ymax + 3.0 * yspan], + ], + ) + ) + ) + + polygons = [] + for i in range(len(points)): + poly = Polygon(vor.vertices[vor.regions[vor.point_region[i]]]) + + if not poly.is_valid: + poly = poly.buffer(0) + + with np.errstate(invalid="ignore"): + poly = poly.intersection(outline) + + polygons.append(poly) + + return polygons + + +def build_bus_shapes(n, country_shapes, offshore_shapes, countries): + country_shapes = gpd.read_file(country_shapes).set_index("name")["geometry"] + offshore_shapes = gpd.read_file(offshore_shapes) + offshore_shapes = offshore_shapes.reindex(columns=REGION_COLS).set_index("name")[ + "geometry" + ] + + onshore_regions = [] + offshore_regions = [] + + for country in countries: + c_b = n.buses.country == country + + onshore_shape = country_shapes[country] + onshore_locs = ( + n.buses.loc[c_b & n.buses.onshore_bus] + .sort_values( + by="substation_lv", ascending=False + ) # preference for substations + .drop_duplicates(subset=["x", "y"], keep="first")[["x", "y"]] + ) + onshore_regions.append( + gpd.GeoDataFrame( + { + "name": onshore_locs.index, + "x": onshore_locs["x"], + "y": onshore_locs["y"], + "geometry": voronoi_partition_pts( + onshore_locs.values, onshore_shape + ), + "country": country, + } + ) + ) + + if country not in offshore_shapes.index: + continue + offshore_shape = offshore_shapes[country] + offshore_locs = n.buses.loc[c_b & n.buses.substation_off, ["x", "y"]] + offshore_regions_c = gpd.GeoDataFrame( + { + "name": offshore_locs.index, + "x": offshore_locs["x"], + "y": offshore_locs["y"], + "geometry": voronoi_partition_pts(offshore_locs.values, offshore_shape), + "country": country, + } + ) + offshore_regions_c = offshore_regions_c.loc[offshore_regions_c.area > 1e-2] + offshore_regions.append(offshore_regions_c) + + shapes = pd.concat(onshore_regions, ignore_index=True) + + return onshore_regions, offshore_regions, shapes + + +def append_bus_shapes(n, shapes, type): + """ + Append shapes to the network. If shapes with the same component and type + already exist, they will be removed. + + Parameters: + n (pypsa.Network): The network to which the shapes will be appended. + shapes (geopandas.GeoDataFrame): The shapes to be appended. + **kwargs: Additional keyword arguments used in `n.madd`. + + Returns: + None + """ + remove = n.shapes.query("component == 'Bus' and type == @type").index + n.mremove("Shape", remove) + + offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 + shapes = shapes.rename(lambda x: int(x) + offset) + n.madd( + "Shape", + shapes.index, + geometry=shapes.geometry, + idx=shapes.name, + component="Bus", + type=type, + ) + + if __name__ == "__main__": if "snakemake" not in globals(): - from _helpers import mock_snakemake snakemake = mock_snakemake("base_network") @@ -803,5 +941,22 @@ if __name__ == "__main__": snakemake.config, ) + onshore_regions, offshore_regions, shapes = build_bus_shapes( + n, + snakemake.input.country_shapes, + snakemake.input.offshore_shapes, + snakemake.params.countries, + ) + + shapes.to_file(snakemake.output.regions_onshore) + append_bus_shapes(n, shapes, "onshore") + + if offshore_regions: + shapes = pd.concat(offshore_regions, ignore_index=True) + shapes.to_file(snakemake.output.regions_offshore) + append_bus_shapes(n, shapes, "offshore") + else: + offshore_shapes.to_frame().to_file(snakemake.output.regions_offshore) + n.meta = snakemake.config - n.export_to_netcdf(snakemake.output[0]) + n.export_to_netcdf(snakemake.output.base_network) diff --git a/scripts/build_bus_regions.py b/scripts/build_bus_regions.py deleted file mode 100644 index 05a7729e..00000000 --- a/scripts/build_bus_regions.py +++ /dev/null @@ -1,218 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT -""" -Creates Voronoi shapes for each bus representing both onshore and offshore -regions. - -Relevant Settings ------------------ - -.. code:: yaml - - countries: - -.. seealso:: - Documentation of the configuration file ``config/config.yaml`` at - :ref:`toplevel_cf` - -Inputs ------- - -- ``resources/country_shapes.geojson``: confer :ref:`shapes` -- ``resources/offshore_shapes.geojson``: confer :ref:`shapes` -- ``networks/base.nc``: confer :ref:`base` - -Outputs -------- - -- ``resources/regions_onshore.geojson``: - - .. image:: img/regions_onshore.png - :scale: 33 % - -- ``resources/regions_offshore.geojson``: - - .. image:: img/regions_offshore.png - :scale: 33 % - -Description ------------ -""" - -import logging - -import geopandas as gpd -import numpy as np -import pandas as pd -import pypsa -from _helpers import REGION_COLS, configure_logging, set_scenario_config -from scipy.spatial import Voronoi -from shapely.geometry import Polygon - -logger = logging.getLogger(__name__) - - -def voronoi_partition_pts(points, outline): - """ - Compute the polygons of a voronoi partition of `points` within the polygon - `outline`. Taken from - https://github.com/FRESNA/vresutils/blob/master/vresutils/graph.py. - - Attributes - ---------- - points : Nx2 - ndarray[dtype=float] - outline : Polygon - Returns - ------- - polygons : N - ndarray[dtype=Polygon|MultiPolygon] - """ - points = np.asarray(points) - - if len(points) == 1: - polygons = [outline] - else: - xmin, ymin = np.amin(points, axis=0) - xmax, ymax = np.amax(points, axis=0) - xspan = xmax - xmin - yspan = ymax - ymin - - # to avoid any network positions outside all Voronoi cells, append - # the corners of a rectangle framing these points - vor = Voronoi( - np.vstack( - ( - points, - [ - [xmin - 3.0 * xspan, ymin - 3.0 * yspan], - [xmin - 3.0 * xspan, ymax + 3.0 * yspan], - [xmax + 3.0 * xspan, ymin - 3.0 * yspan], - [xmax + 3.0 * xspan, ymax + 3.0 * yspan], - ], - ) - ) - ) - - polygons = [] - for i in range(len(points)): - poly = Polygon(vor.vertices[vor.regions[vor.point_region[i]]]) - - if not poly.is_valid: - poly = poly.buffer(0) - - with np.errstate(invalid="ignore"): - poly = poly.intersection(outline) - - polygons.append(poly) - - return polygons - - -def append_bus_shapes(n, shapes, type): - """ - Append shapes to the network. If shapes with the same component and type - already exist, they will be removed. - - Parameters: - n (pypsa.Network): The network to which the shapes will be appended. - shapes (geopandas.GeoDataFrame): The shapes to be appended. - **kwargs: Additional keyword arguments used in `n.madd`. - - Returns: - None - """ - remove = n.shapes.query("component == 'Bus' and type == @type").index - n.mremove("Shape", remove) - - offset = n.shapes.index.astype(int).max() + 1 if not n.shapes.empty else 0 - shapes = shapes.rename(lambda x: int(x) + offset) - n.madd( - "Shape", - shapes.index, - geometry=shapes.geometry, - idx=shapes.name, - component="Bus", - type=type, - ) - - -if __name__ == "__main__": - if "snakemake" not in globals(): - from _helpers import mock_snakemake - - snakemake = mock_snakemake("build_bus_regions") - configure_logging(snakemake) - set_scenario_config(snakemake) - - countries = snakemake.params.countries - - base_network = snakemake.input.base_network - n = pypsa.Network(base_network) - - country_shapes = gpd.read_file(snakemake.input.country_shapes).set_index("name")[ - "geometry" - ] - offshore_shapes = gpd.read_file(snakemake.input.offshore_shapes) - offshore_shapes = offshore_shapes.reindex(columns=REGION_COLS).set_index("name")[ - "geometry" - ] - - onshore_regions = [] - offshore_regions = [] - - for country in countries: - c_b = n.buses.country == country - - onshore_shape = country_shapes[country] - onshore_locs = ( - n.buses.loc[c_b & n.buses.onshore_bus] - .sort_values( - by="substation_lv", ascending=False - ) # preference for substations - .drop_duplicates(subset=["x", "y"], keep="first")[["x", "y"]] - ) - onshore_regions.append( - gpd.GeoDataFrame( - { - "name": onshore_locs.index, - "x": onshore_locs["x"], - "y": onshore_locs["y"], - "geometry": voronoi_partition_pts( - onshore_locs.values, onshore_shape - ), - "country": country, - } - ) - ) - - if country not in offshore_shapes.index: - continue - offshore_shape = offshore_shapes[country] - offshore_locs = n.buses.loc[c_b & n.buses.substation_off, ["x", "y"]] - offshore_regions_c = gpd.GeoDataFrame( - { - "name": offshore_locs.index, - "x": offshore_locs["x"], - "y": offshore_locs["y"], - "geometry": voronoi_partition_pts(offshore_locs.values, offshore_shape), - "country": country, - } - ) - offshore_regions_c = offshore_regions_c.loc[offshore_regions_c.area > 1e-2] - offshore_regions.append(offshore_regions_c) - - shapes = pd.concat(onshore_regions, ignore_index=True) - shapes.to_file(snakemake.output.regions_onshore) - append_bus_shapes(n, shapes, "onshore") - - if offshore_regions: - shapes = pd.concat(offshore_regions, ignore_index=True) - shapes.to_file(snakemake.output.regions_offshore) - append_bus_shapes(n, shapes, "offshore") - - else: - offshore_shapes.to_frame().to_file(snakemake.output.regions_offshore) - - # save network with shapes - n.export_to_netcdf(base_network) diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index f58e5f8b..87762b36 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -135,7 +135,7 @@ import pypsa import seaborn as sns from _helpers import configure_logging, set_scenario_config, update_p_nom_max from add_electricity import load_costs -from build_bus_regions import append_bus_shapes +from base_network import append_bus_shapes from packaging.version import Version, parse from pypsa.clustering.spatial import ( busmap_by_greedy_modularity, diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index 8f2a84cd..558e4cf2 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -95,7 +95,7 @@ import pypsa import scipy as sp from _helpers import configure_logging, set_scenario_config, update_p_nom_max from add_electricity import load_costs -from build_bus_regions import append_bus_shapes +from base_network import append_bus_shapes from cluster_network import cluster_regions, clustering_for_n_clusters from pypsa.clustering.spatial import ( aggregateoneport, From f90f48ceb69fd61b5a75dd3f75c88cc15c929d14 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Fri, 3 May 2024 14:54:47 +0200 Subject: [PATCH 582/591] Adapt release note to reflect bus regions fix --- doc/release_notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 5e530963..dbc857bc 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -186,7 +186,7 @@ Upcoming Release * Data on existing renewable capacities is now consistently taken from powerplantmatching (instead of being retrieved separately); the dataset has also been updated to include 2023 values. -* Added shapes to .nc file for different stages of the network object in `base_network`, `build_bus_regions`, and `cluster_network`. +* Added shapes to .nc file for different stages of the network object in `base_network`, `simplify_network`, and `cluster_network`; the `build_bus_regions` rule is now integrated into the `base_network` rule. * Fix p_nom_min of renewables generators for myopic approach and add check of existing capacities in `add_land_use_constraint_m`. From ca6f803e28214d7ca635d9ca1dbb7ea0d231221d Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 6 May 2024 08:52:42 +0200 Subject: [PATCH 583/591] Update documentation to reflect removal of `build_bus_regions` rule --- doc/img/intro-workflow.png | Bin 232347 -> 213303 bytes doc/preparation.rst | 10 +- doc/tutorial.rst | 124 ++-- doc/tutorial_sector.rst | 1158 +++++++++++++++++++----------------- scripts/base_network.py | 11 + 5 files changed, 670 insertions(+), 633 deletions(-) diff --git a/doc/img/intro-workflow.png b/doc/img/intro-workflow.png index 27b5a389d97416a5c61710cba4beb41ce90efaa3..a273ab3969709c34bb316433ae734f773f9ec411 100644 GIT binary patch literal 213303 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%0Ap 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
-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 z z97sS+x>{_N-3QR5L{GD|Mn*IMqnf;%taz4d(Bt6nJ@xcA7gC?irp6-My~E7O>I{D&kLZe%Nyi*h`B*&{2brilj{NjdE3d}nkMX9lBmFr zOX}W%i8To5m6a!O*lS-tun_gP77s*c?;rP4e;R52yF&ncO5Atx{5hH#JA}VR&e)*( zeXH};TKuxue-=3t}M zoc9Hmr6MbGF4|L_){iDtmv$WoD6z^5B`@*)R_nl_8a4W*qXWq?ZPQVb^>R z>-oa5kj|L{eJCGaX)U+Lg!S3+_Ji&#e*m`jpdco2LxS9GEpr9NdO!O@BVM;?Y#l0} z@1?gY3L8DpW_MSd`AIjWvfa}&nHgUu?*EVpag_ ztFA`qQq>+fx>uFWB6=CHngC80ZfOzdviu@FDuP9K&J2AjY|eLX=Fg!`0BQj~WOp2M zy49%r!6rYqtW0}Nhzw>`Q0p3wZbvZ1Y`@S8U=s}V#F}#6{chMx%zp7Aly43X z4m5%*?n2Y7ZbL_9#-X$0_WULeV>Sh?m+3?IIPt~qdFB_U$hLz$Xe*8l!jYtm46l$5 z*iHNr+<}U1Gsroj1CRrM2r~;yXpAg5Cbi0OO#Qvpc*=0fYwTxo)l==EtSNs9gI}rjIparTLU8s})y9#Y@3O&x5p4 z0Y#SU9?CzS$&{@Z{A6EH|BN&SG#o1O;`#IL#n)C_hL2f_$8H-*C-C*Z&(CCT9*_dj zE6D7BD_0|xTT!*BXYI)rG|D(e$Ho#yAHbKNi!xYjiM;BdV6ZHVfFkTwD=_@M7oNo< zOn%X4B7z%%x=_O6IO&iOWy1TS2GaBdA`uEHz02h}EU&mMkEx`z_TfrAz&w>gBNY@B zh_Wc%FUtohvhBlx8l0uK*GbaBj5Ush9MXyJ&PAZT;pXJ2dA7_u{6;NI>21zOtsfFK z!w&m6aWCM@&Pjdd0`?#k_tp6hBuUUMKKO#nfuABBlzz=9U)i^O`Jp8n>O97;wAbGK z`m*B%zPiuP{eXuM{GO_@NhT()dddOy#>XCD+&`K+)c?%D(g7z(l%Dbf$9qPMe6k3aH|MGTP|GF;q<|&M7gN5X}=E&4q7_8x%Z87tM@IO*mE1xvgz~_3@L}C2cC%shQ@4vGhdD=` zh2z+CdYRv2s>@c}*t=77R07+^?!i)oDVt*KKBNHP64&*$fDsKbGTmjZ=r9Dy0E-W;(_q` zQy$x*!1~8!c+`nRt~tEQ&#gI}&RtsUIw(nt5ZYKtmQzrm7C4p#9%De~Il|4q?E*M} z_!Apb{a^oNwJt7AbE&554Vl+=P3{xof z9N;e>E$W^#gI>YF^=tf0S)FX>che2j$=I_I`$|jgscYoWH zs;-3s8!-B-rvISi$ASRq2q512KVVfPrKH&G-fwQ+Q(W197#f7+YBgR{l(f<*E-$W& zwzjtKQb9wQJ2^3J^)`I~)X9YTdv=l!bV&D*94$oEA9J8aMhQIl>ldR;3ue7^KP#Ml zr3=JbRwnnbE!RNMz|b(Mcj5qw3bb~x*XE5nNQIS6vFM{j!R7WKd3-As%nkJvd3WyH zk(b#nfFzI$m*TXku2q~Vc|D7;vCh8VyAFh^J)CE5nR}&s#7EQ|L-bJdJ}gde7_Jx} zAOAE$BN@!2SdW6hKyWLzbz+OebW#vSwU}~xTkC2slhIp;q#mP7d&iOJA8dUDAMIAm zu|g77G}=z>L#~nfQU3@v@0VpJF*LApO79naV7g1iGbyaKgAuPF2u2}tlx z4ya%5e+8KXdHc4|1f=8Dp^5<4;mwD@!Gq~TD0q>GAd(T=E=C@zNQ^|d zFErvCeJpy(MS9QEwkudUg4BW4{mU*0*cwJqRBqT_xE> z{BO>MhtrM!WJMtT0yT??+n>BV{c{>Q3-mWpPt7eRom#^~;D7wOYwA@f1A4+AghI8v zET+M}Ti}O`cC4BfgT9hfCpI`BVYsA(Q)1kqrPzRut4Hzn!6koWHDCxqG(xum$Ykx+ zwdWv8*@M89hRMjS8tdIDmsvinkSf>!luZC_l@wsZ%{wB~SG%MCF?dv+cc}$e!pgx= zj~|9>nPM2obolV)e*kfQ9BQ-{9|WhMFTYqdhRR1Jh0OCtNtzBR@2+424vm5!Gfxf3 zDnu_<)uZgVu>lF>$Lyf$Kw4(U#5NlBw9s=eR5V4NQ4hCwt0}1$bu`hgZekEfeu_{C zN)Y%2p&LOKVFslq=pA61ivGi{340d~XDelQ@Nm#VY-ZTNEde(!02ZQBz(OkZ?wY~{ z4v(deP3xxkS>2tZ-Q9sA-~KzIY|sF?+w5nXeE)*6B#Pny$EW9B@HL07PKQb;*uS8V z-)WFc3QNpqFceVykclE5a0P3t_ucM}iTPcJ+;8K~KA-lhSOjN@GCZJ~8xAr2x%iwy zfvaO1h*^{h&P97)`JF)C{9C(rT60G=>`QFfl{BiXkP1o^R7zz(t6Lb6(iy41jP2m% z0|WBr&6_?uNs!bs;nfU+4PlNW0v3jRW*Q3g!1>!K9Y&HjHq_gMk1EsRJ?aKje)Y9R^U?jS|4Kf_M#4r6bGz%D70-#o171P>Kp}Q9_Ad}* zpdcxN0V6Q|ywy;JVzhp=s**aS5NT=diSr-@*tV?N(B0T^;~3tDaiI)u*-oUJ6 zMxg#Zb4ZPt8%;?;u9x2dr~niXV6fSV1eyg^sosJoiSA_Clb7vRL%VO|L|-d(E($^| zf~t#Mq-)9<9RAl@(+b!RFhTtt;0yy9I-K5?r9U7-Xm;sRz~?i%1b_Tn8uwUc9V11s zC3Q^^h5o0bpt6RCEn&nF39-Hb``q*A&k^|PK#|?LwHu=Oynd`Ezfc6(vx7g58XZj5 z&uo9CS4E?s9Kl#$X^uIoBTc(;fH?N-!B0%?u`$1NX&WeD6cc}OYUE*>6I4UKg?a*a zhfu=d0?vY->1_;YnwvGY83Yg7eDVQ9%%IEa<8U6k!RGplGl47m)4gZoGS6ggt5RMi zPg#rQelW?RCCdkL1Pjs?{)DPuHEfP+Y7l4r^0IbX@+&rY`qFPf1jo$%@H(ZP;4J#p zS#H~LY=fqa1+2UK0zh1cFQ`_qb=WC^)ru4gbZnAGS!pPJ6tSYD^+)F15S%voY9x%R z-s~BWq=l&)A{kx~@1ijr3_?-hu@kJL&fYimJNPy$5Fo`8|VKaAzIZAFO^m)+VcP$;ZE1GFOQ!u6^6ac;m0}hX-~{ zY^kw_{R-$2NDq1m?gdDxJ4`j4fN_U_OalW&1qFY27e0o|!!ftEwsz-B6G~@GOCM%F zz3HHzC17&2OE-01$GAm2{ih;;;0gW}cp`phvyFFDJ&0}MBTk`nQSPf(N@WKn&6y&hMRN%PnTP^rriJVng-!RmKJ{PdPk^h|;=3#Qf9T&3opeb@CI=-AxcZQHJBX!)eRv8={J6hYy-@yv}>10C35!bZgqqyjw-z$fjS<@K+4qJ(LuX3*j`=Bq&}QcU^~USOlg`N%k1;zMYx z!!6uS1msQzvXhIED#%SKr4n*7xU(NW9*SLRz-wU+gqIG}aLqaUEm9^su-)RbmvMrs zuD>jkx`T1B7^w=k75LSxQGUjH@1(}2S21%FDl=R`a~hi+P=Yg$GnDQreMeP;j@R4h0o3@c9FZJbWA8 zZB%iiA4W$K#5vE-)dJtFQd{vODk80q(H9X?g?{rjz1=hp46 zUw1uViN6-v{2B%CN)vDrem9oA|39A}zdABLM2HXwxc!yBbfB8C?Y?~dT7eob!+eL2 z0}6IwD9fm^;e2G$mF3nr60|nG^1n>a5SygAZFS3oSF8&*Aj`l;LY$A;rAt0q{R?am zDXIZn1lNuPaAptHcF3-j910ykF`mM_P8Fa4f5!5?xGGHiMIrn(lr1$7O% z|1W(OAU01xVZhLuK|ASq6zk?LCTx5O7OYz_Hv$P?Y(b5U4U?C#0Q+%Rh8@^IxeYtG z^*shCRX;?Aa~Gre)cKvYcw5PLo}KX7k4{N>5h#M!A6m3PxvfSLeaC)P=2$}^TAv6-V?#j1J ztEW=nN?=tL-9z)DaneO9xtb?W`8L@@K4DTsP32`VLNg>vU|Cr{a@y+G4e0E_Rhw76 zRIx#j@v(qK7~dVd`x0RbY_Nssc4QUMh7fJ@I%SUd!$wh?42KqO%bQkd(ewJ;A!Vj( zwXJ$8r}Z)o9%v zjuWo0tuTJc=U-G0(|K{m{|Ser@O_*oq;b4Qy6I9$^nda(^t|5mk6W!0Y7ebH|y2D*#gl8nY+`A{}#j z_cKefOm_mt83~=^IKBy#F+qC~WEwJXQO|pL%Lzd)aG5{iSTZJLWDWVR6Cp#Td zJ#(PPz65F(p54o^% zDn<*NLDv0`{8bLHW2h>h-3cQn6f2?zZN6rY+W)-_sxpVYfBQtXDY@dXfq;9Ea?|L4 zWi7lt$+wA0v1Sl($>zb&#azLYK2s7GzuT0`&8qBrm8ZPU{b=JH)S%9V;sl0|ptWG~ z*)WVDhM@fn-%9VFZs-z-{daID*IjN}Weac`eow*%B~L5a=5?lxdl>Vg@@x3n#b_j8 zw$JbpTmx4Qykko?5$s&oTTC$8R(TkKzDfjdA18(0MZKP@{VEgcn|E$~9`^S3L+kh( zPbu0_YJ&S> zn?SrkFV?LLibLj7W_4#Ygab{?p}K&BS5RIP=W!rvp3%@HWAKy)8Ia zlMgQTHmh4laQz0#6IfI9l@@D_Mq~>itaY4>xF&*92wez1ir4~(GZxvs*5dZ=?ho49 z^pK9^xqe){bz40QztIj?{pIW>Z@yp(pp?+~%}>-2p#Zo6i)=LaaCOGZb1#eykCoeZ z-+6+0l)>+1RQ!yyYwGK%oSmJ?$OsVxBji3sOY87?L$SwWdgvIl;Z1I{5@xJG7V2DR zQ@O)fe*KowB}u9Zt3XDTd0PFc;7}3TL)2UEXm! zEhg!9lBX}tIW^JqIt=@LMA=Z<5|IP|0KvqI3#}DZW+JFuDZCY+@MTcZ9{h+)N#@kt=MH<7UXS;&*uI6{mh9|C2 z{6)x59k0WDh}{%UBi~3BK$=Y>X+;G*J8hqjR8ckja-(?=6xWTSo@+fqn;wq7KKJ5$ zkcs_k{dM#8>(ie}FJ!|<=K;=UV27Z?MTkv+hxyfpd8=uS#2=|9g;VgOhBb8t*B z1V9G{Y~fX}n4T6ws>Zv2e_V#javXgzFf|}dVc$R=ORnbTfdF>#_U+s6j(!6cwY1z~ zmFETqxlvjpIdrffBhcm4P6&&Q;ZWB?)hyCR)xkjq1?~7t>m+wtD~9pn1>pk;3JJ+B zjxcE}D|JrHW4mLoZ)IPcPpNu@0EufOg7{C9BK+?LkhbZ@!LHl9mHj%|=oa|;DbHj& zX{Mye5L|2kX>TYFBOEw5a}JG2+L)R6Hc{6mh>)ssu>ti3d^GtstA~M(t2>D6`~LEZ zAy40@gI9#JB}S9>lO4IfjCzb_MBFVddNR8N^Rwf8;EvxN#ka@7q?6o(><08n%&xEy zEeFc+m_Cj&1CC)>IzU_yn;wd9fv<85F-s05k=g(bCiS&z*M7x4rN@&6ki9c^&J+ap z2m{bg(P=?u!bGby2cj-EHdgy)cGCB~;0^aRh~gOiSel>kZ&~=A{o=~%Skn{k`U6{; zbWfAQk(H3Co@Ooq)AB#XePI>AeCT&0zxz&~%6e%_B<_nYpy5|u4ddP67l8XDP{E*D zJ0Q#TdCIxY>H~(CpjYHiA&YWEL|tmH;ZGqmbyRiexjM{RtL*#I5#hFAu13h9UC$Bnt5i@4 zWN=uhYG8;Nq4wq<{dMfZw_n9GEXKx+(6xn^t79sSH0~$K%m~d4@|pdkXz=qtFF-?J zjb!k$*$Y@DP)cHfwnnR$Y@#YGsOH!5yP!c~AwvEw5~&3CGJq(DzZRGon4E01V;H+h zjaPJ}RhQJ}3vbKptO$MxUwD%Ldj^=B2=Az~v&v(7Tugy6CORas*4eG~zkv1_bWgL? zFV8WKs>e3nm$3atQx(`XCGPCvV(;vHzq(pkk|Wrj&Qb7JAZg}n_vO=LwgP%E;EA^; zow9^zBPOpLF$x0XhIEjt%$ko~GgwDLWp{Q{Bo)%?GG6iS*_LJ?2y0)+kP{g?K0zdF zUzodEKa?an;!|mg84Gu%O3!3Mc>;=NMU{G2zE8`o8Pq$-#CwmaK+JY{)Ng5u7$YqI z>20B3LHTdJdLZIUjMqnN`72i0r!(NQs&%_08uQ&{{Sn@We&#;_->|{q%~E)m+tUS# z_T!)2mwx$ws&*?e2BY}EO+P|Cxoxa(Xo%w7;*tgWt2b0~m;L`k^KZJQ2%bjcMa8q( z7+SK^JBthS#6k-o575IQL!d{4W-ZUVRF}vcjyaSvMzxM-I!0 z`p*3uA^IR`K#({z$VHB|X&fHvy zkq~TLJ8qnhAf#R~eDHRgq%^M>7 z54-jVz<*?ww|Sbb{^-Q_@089(@qTW$;r9|DpigvU+dDXT!MQ+&XM;izRBv>_wY`=r zzo><614sc%`kl9TkKF8B|C8op1D57MQ&%!x^y!SP6p!l7!3g05=NjOcw~pOV3)41~ z+wOG-W(@qm|Ft2kXtu>xe9f2*SA$tF5C#w7ua=^vh>|;$n_FF~dk1TUbOM~-mdlea#3G@ytWTC;%;SnTJ%qBYUw!^J1Qa~TNuq|${0B9x)}&Kz z$3$pLn_2FMg0>w%hT1fQc&RCb;uQRG`NfA6XCl3R1N{zYO3BH|wfAu1=WZ8(&WBF` zg$;R>TPqZ*cu>SBiYS8@pU)qYlcmsD$Sb;W9hqXbbp{Z9PPRErB_%W~k~0QQR&F!6 zz4XEl4@la`>w|P8`gG8(BNSEl_IZ!ZuBiHSE-H9iQ5nOV*lEoSAO*htr69aqyV65Z zA>XAb{8!AM1dkHjk-#4Wd&5mHl8 zQBhf@UayHR^(R>ES8eBIU}{y0JiA>;_*)r&y(5J}!Bp3h7fNx^oJiELZFfu%;}<0) z7JTIO3bSR>y7%BL+H<_g&nL*lmQlhx2KVE~c?KVc6OzH+Xq|v*9**(U(@E7HE>GL9 z_9Gm@gv+5fAZVQJ0(2sCbm`bwTk_N8N_(RGf+(kcMs|PyCa}oH#@JPar#)s6N%~u< z2Q_+l2|8YBV1wM<^iH2;6z_0A+%U7f^p6YdnV70HCj$=R#exH2n6_CmKU88oQ|Cv5 z8n)BFN`BXwKAE+KIT_r*mcF#4T)21DZ3USL5w7|_U~91; z3&8v(wwpqJ`~rR*lGlpo`n#plwlUD5G%~7)*>Ix28=UinYk>5#hff04SgObFYAy!-ytT`|_Nf2`|r!ohIW=*sSrBO7;e?`56 zg}wj?h~-0T++k3=knnCu@8~N&83Ug2+>4NNq)%60*M31``HSpu6fr+YW_5vH>H?4A zJRzzD<{K<3(R3ZhDB^c61C;M2TqxIj6`=( z5}LJ@q0x+w3&h_hh0r#<1eS0S_)?;2Ej5|zpvQ4UHCHtfCLT;f7mG@w6j;7+I9pmA z|1ay$BO|f6m~Zyy@JYgG=f(Bp+=~Gm6W6ts#c=b20S*EvJWYkP4MgWc1dCJ zU=Ze#RA{b1;RkCwdsnLazT~G5w(2s%{VCQbiwYddCly+G-iPWYaR0|C_EDd$!*2P1 zym$as=vX$(mEk-}c0Y5=663N^1Y&)Gf%^2g z?4R%qA!!affD?x>Uyj5~z-unF0iXug%u-t1 zLnE;$m59+qDs}xh@pJ-m9Z*OOYWDwGpx7P5bgrHPJzl)yM5Y>Jk>w-HE2E)o-o!>8 zgXHu-%Noi9&Ja2#J>y9Oi5Cz&yZKn)AVLELx}G=M9k;%n+3qEOPx;-Vneukem?o0k7u^#gZ~Z7%@a5CfuvkxFSNXmXj-vH75Y{po?&^r*VYMkiwMnP+J)--C4nd>$6) zB=Bi)inNTX+h2fL!0e~z*#^Ut6bpg;dKrwU_VK&b<<_hBp9)NF?6~O`np`bY$^#AN+XP$r89X<4{`cciG zn@dSYO4Guv-9!0_+j%A3V*3=IiHodO&jwQ+H2rf)3z4^rTut1v9Na&mCxz&qBD5d8 zT^MLV)UK>g#$R&e?tJw6>_Ewa%Ff!%r*GTakFU#_S=m$-yV$rGx^3ScWB<1@-p)L`ubI3R`whihkYH>%Wv!a@bvM3bwkY=PBYPyzvwz!E~7L&=HS z0?7qqtnkcz{Fr)`jcqsQ2`5LGA9F}a?SKDT6afIJOiD{=!uBzjU$wa;pIC-#!}EPL zo^AV_+Hfzg}5XDu#D747j?f(=5nnt>s&zPfr#rX#p3{mt_9j!I>{HJzQE zwdblP=Fu1sC}!3|SQp^G#-4=*4L;L9X!W|3mT-ceLVV_Rr!{rVUiX9V&xqG=x<3A? z#Py+H7}p3LDoCia_Z0VmbH-&glwR+uBH*1uoIu+m^*_9lf;-7=w&)|0;G=`m& ztZp65?ytlw?q6lkfhz>C{`QU`df|l}o5lr_KV;|@q5#5jv68j!cU6k z$rw$bG{8Ie^|d`<$iM;~3GD_phc~Spgw!rM&{9A zN`Tma4fM~_{6Q$C_zmCYQW&a=cmio|4|5y};67*|6xCopO2bhDZ=XDPA0SW0Y6jhr zi-!w3HZ4i1g;goVhY#&b8or=AB6*ju#vTVvvyWen&sL6q+bNjw2|*fwABu?=S09cX zTmY$AofNY)Fd0!7U&=$>+kb`bO4=3i*n)xr*0IA`r!#UOLH;x9;6=9PoGivl6X70* zYvAb4o;{16DR7j?cx{{?^|9ywtSlY@ltErZOASsn8nA?-%$p+uhc1(-Bkp!G>INj& z#_a)>@#W}Upl9?n!efNCMst|zsq5@K>Yfhrw1Lmbah&RrCWdoeJgg={ZzkwK<8YYu zf!KX6W7Wj;T3OmBg`y0iFX7%#?)KcGCA zIB38xF_CW|_}p+knQ9ht2)qeD=0>&2@?T4=&+c8%%}I=Mc7X>#DuV14*2;Q zrWy$yi8=zh2xpW(#E;8w6zz%juCBG?X#l?MdrQ4gapR*PK?5%4MG9K7aGGuIAcu*u@(!&Y17g$nRSHSCOUAzyl9vO0m=$ zksV_W?}fQ!mnppiumytx;HoZIco7E&RUuh^e4KZAUxex}Pgr&!yI!9 z7rpMI_Z6N1&?F#h!Dr`;HgxTzn3bp;;7S-(S6U=n_1xRh(b4CY@PbJy7_$LS@a{}{ zy;sC(X;t=oW|LxNlyb%BT>sM2<3b^!BEOw~mj8^--$Y}8y@yATR{CaL#!#(v0Bbw~ zd`)IWO@3kzcb4Hl2d9P{5Kukv#jOm8e#X4yRGu1xU)FE9hecH7?q^u3-|X&6UT(2 z)FKovOg_R+!{!A1frXKX+dC`CHG&6oUcXlMVmA{+#7EGZ{0&&$q(^C{g^C{EVk1uPg%{ux2C>yP5myJJ;a?%5)CDMrs-{L_EGL*>+(rDIWwxX_v-Vne0v!U z@%mPIk>w#tZ(|1-9dKaS4B(=rj%j&$mdSB9GAf7q zAKI^O)-k*c%VSE1uZivH!OeU#5kl%av$C@6z+TOW7~a{wa=}7MuvVYMNN0n3ahJn4 zj~Aw)BROp&Ki+5`58?W@yYP>Acpc{JJ~0w%>F&1riZp}o70i(iNej{*sq;i5O=Xto zucA0Xd=L~PFce5pMQf&Ap}WQh*CWbokef=HQj?lvuwVd2ml(@U^_Q}{t>Ml$G``&4 zf$C}4A?D~+whl6_^tN1;LxDS^_ECDd3I%c}!`uKWWzl^tLG9bc!?-j64@zr3PN|Uv z5iCr0z-G9Ep`aP4Yj^mbl#_PVZb$8Dh_$2M&(>uq7rtatO* z7pQ*hN+)49f3pNgXGlw(KKmX(&0Y@XGqiyM!`!ZJ7lhS!7Rf=yDtIv!=C}s@IlcQ5 zL^^PS;3$x%(YCAAe6n_Uct5)M?{s-sy0}Csu~d13KRnaLMo9sVDqV)#iz^|ycV-aH z*H2ZxVf@RjTd@NMWth-Wg?TS%<`+h2H4uFN*jAIeGiXo2^=O6OnFcO~;hpHd;X7xo zPG5E7A+-gH89SavJ{eCSY52~cV(tKL9G+b&-{!vScnqH z0d*o`7i?o+dV3R>m3Al;OKkPt1S|%OV@eyj=$_C-haVsv4|CUj#73BOkq|nq*M=87 z8!on+lb>3&UtHlL5D6;{m-@%NH!)&Am+Q^r_P_TRwzSyRY~K}J+cLCwaFS*u?0@XNV5J#5t49cNRn9cedNaF9f1>805yxY6{9sA1< zYufZxqDLk@1t}{SRew4Ry>~$qccg~pkVx>L!Jwi5`+nofA1g?+p%?pO;247O@WIdm zW{zP`linz6#sl3T5Gp1ee!~aBJ@4q(p6*mA4u@GWRRg?`!p6)u3lT>tZ5S6+tD-0r ziaGJ4+pe+|8bifHen>LT4jIaX>Bli}i_Pd;(8pNLMIO`RQQ+JF4`&B!=*Zqda9R5^ zNO$${TV8aB1B4*mljRpy5-m1D0j>|x`JOPkX(c|2htlj##zrTG>A)qNe~2Cz4@(Y* z9@>gS3d;|g3cPvMq0U##l&#CYKG$xlN9ueK;3~_TY@`TlIenn7AZNs}lo1ChKD)r0 zL8!KH=iq4SO}YPo^u`VsW~fjE>T7?2^Dmgu#rYMH+ailsU6az41%CI$^~FSDvv0Un zCt=xuHqeQ|A3d?WpmWJ?2hv|s{=pNHjq(ckD5y!5rvk0q}fC&eH1@jpYEk>-4cj7{4_n#$75e{vU4u$U7 zi=1}Lx8E2D5`m!5Xfo~;Jw@&$&1lgGv`}ktH2z^c!*n$n3?$$H)!L4Ex$dZRivfiQ zC6H@D-HbVO&jAo#aC?23i^F38s&5&+w*F?Gx91*N2{EAwZbUw;UbAA4k(y(eP{}P?gUg5Szd{I(FzgekSyu_NxE| zsIbsFN4#PE_uMV&ksAA}HH^!@vS$XYK|M$b6Z-JL-l6m)Ra5&qbEsb-d%kN${iyJ}|iw z`W|p09tnN`!am#!O*i^qVrzjb@$bC}~S81bGs;4dTLam9<5p0W>O zPGh-IdK+O#6!wfaO-dE4h?v=(KusqR#GWunYrFh-bVrD}>o<27&JxN~nVh?VOW$8f zaFq({#b8iqqX>L9O;663)T7v=seRhkzc z8yWR8+&*v?skm!!ZV_n72M-N1b3V$e3Q2;7(BtTzVCY2k#D)Pp$3G`_riA^{{M1pA$-^$3e*Zeh@ZV-B`8sL7B+&Xz@~q$o&o zKzvg~L%zKVGsPyWfSQ8xM%Mj)=+bddP5K5+ z_>Z6(HzaPp1N|6C|0uTy5Ap{*WJDtvd_5bz)Zd(FelBmm(=eRO?swKsxPq5uihM|^ z@L6r|L4VSAGs1FaaQ^%Wd=b9zO)YcJf1uEQf?9igJfP52_wX^u+*VUmdm&+D6N(2`{gl?6376_Hbn%DPSLGF!ma2dsTv}SH z?LNXBC=%+xMgJ%DX`3kbF-BW!Yr=sYUYA357D5>o+$x7zp&%wsROPi_twzFXj*Hr_ z4jW8$;_Ws6`T6-6r__jk$>2gh98jc70OCiiQ}Z`@Y+PU39gJ-PO#?%esk!;)@{4x$ ziTAjeH!uFdX9z}3iM$Q$_qoMokNI&%QwMkJ*I*Y|pH`5EGY=5==pLWV_(0G(Yw{Ig^pT``tf;X^-_HQ8aX zMRA9t1vG~lTR=9jOdt}4*WDuqT(xnI=!fcPETZ9F_5*!{!)+gve)$ONME8*TFZz}CwaWNB>FWOYG z@Nl3Rn&s9?zvJ7v9c1PBvn7g3T2_aJvZC7U{V2md%UYDeU4)ZKiWs+A*jBqGwvr`M zqdMS3jX&>jS03Xh9_DR^AI=Iy8gRcd&PFF1S-wIs+#kcb&8RLO7wVz=<%dj*bfZ(z z1r#wrwNOG(VH7g8xU_NTB;2#@ z?Mx_QaRJ6b-jafXJEQ=8K~4Hy76yHS0o-6Wz~aT8q&xOLAu$ny!BF%{0A&M-I8YyPRlk=NQAkjKHL<%ZTuXux2QVw5yQa zQKmt^_;tPaT2;>6_&aH>Dw&Deng~;ov^drXpGSjl*qD>$F2(j=AN{9FcE?baP@zug z9@MKq?4Ta7*VmWJ){hO4k#%#1fA2oV>E?O<#hFkwUV}MYfw$Yp$f$2=iRe1ND}OPq zis$9|@Y5M9!v#Jv`NE7;bj$!&SAirDl(GAljxzvp!wh~zkGmfG8kN4a_^s^D48^1; z(X_K^*j?D`bZ)j*JVR;Bp{mCCyS*2M%PJR+ zc3=d2S@_jfW^4A&I1rqK#{!rd@z|-RUPlHu(3c7W)k;FHG5Os4ytq6uHW`o(qctjx z>V__H=jcgOG**B3D6nXm_$qj`+!-})?JVJ8c= zQ4J9-lDe{7l^`-0^%wX2PftZK|^#T8ggaWSA zW$M8Z^#>|E7`7~de{Xc*0@4l8%gW+tBEBD-0g1oq6NAv-1PYVjD21W`Vq;uSf-FBk z+xNNTHTp@|gS4(xQREiXZgHv%&P7F3$czGUXOhFuPos0XGgpL_9g8JMBR=910j%87xZ zi6Q&!^)J7(3y*Wi?eTO!C-iS+qG9kDjmxpy*DP97IZRkfg?dX57Dw39$(>c9r#Pc2 z)7^K4GhPA}$FdD`iNZTE#D1Q#pdxaOKIh&iyt9LUuO9$Kh_4QOhqsOBhb~RfZUJ^p zR&%d>8wQlJ<4utI2=s(T=)mgS8e3Q>{xJvV>Zx0-D?a zu^`Y155Em}z4g~6h-QJj$Fzqs{m@tbs3r7TJ1`Mqe4UiHt0UgDV{CD(BO$h+ZotyJ zu$wH{WqZ$^j2(BG&5>yxZq*#_u^lR1nFljt&W| zg5qMZ4i^int~75VI-O^3ukVKLJU$Lvec;G@Y8VWj=N_`VCA&;)eNF!ZxOCUlEf)$= zegCeRU>Jvx`vc#Yh$BVA$_$YQ&vkctCGr1GE3<~d@t)`;sAQ20Ho0JMBpCS_V~it#-uqnrf=28|6B(Ye*UDb z-%gYF2|>MK4oCocnWsPUy{9xY`dOeu%9#M)ClobN;`{msd_l-UTs!@_;H}0s0pA_Q z%SR6HGHlSOquV&AGf_*!;7N3S=XF{rnBn8%`p3eP9Jm%9f$P_@2h1IzT6vXVDlsC3 z5F0XDdMIWe(HwhE<@GLL*AQ<6rs<$>BfSle8pcdC5}fQ@wSnJ>ikPMalO{y039q+c zcJoI$yrRWGFaZxkI0I8FAtB+|#r7vjMHX}&vaU=^h}bX8E+cf>*30fKrfZ^=6)J@y zI}eYK^B)ksUmYdvmatN=64&1mS{>n%??%lx^$nJkAF%mv+q>6>GWASm485a41V8l= z-~2r;9EfXkU|^hQ)yIk5AcI9%CTnIoONb(oB4EzSdj{Jj^r&MY>Fm<4uV!&5uK;5UR}?1Be3T$QqLYx>b82o(z^DKt z?dUl7ZE&#r07`spv+Aw>{%BRe833aNa8>hO5Ks;V^}pkBivpvK1ONY2V=hNwC(lvs z1Ab#7lcyJTD(MP^1_uVnapx0)6sFMiP}ri)O)x)3BlTJ7#bzkye`W`_T`LAzMvPd| zbE7sB2Tj+ws-2{B5e@w#JE}h6l(g*B#e^>(sY~&3akyburhpGNY+~BWmG4k2bJ3v1 z{)8WHJ7SI^8mr04P@Q7NVz2cDDQharyiR7Tz0q3?zI+Vd(i|D?-+Ph9ny}*p4 zsROoEInPQrrl{srpULa2YHe-p4&Y~^+H$Z~4zrWEDDma~{2ZpnL-i`}d*%D*>X23* z!J;!#HTvu{R~x~FvSdH=!VIT8GQ-UErW1E6Dgl5~A`Y7Sw4<#M3_~c4j=(yD4Ccr zYcUh<&(vFv6!7)tb;4uc=TLarMp-k6FyG+*AZ+?!|Ry)D7qj;QRL< z$pv-a%DY5$!jQ#~cM1@?sUov|+#p}Q@68$Lzwc0UTz%c_(cNT|kM>y@L;xdz{=g-W z-Imbqz-2Q~g|>RX65{sb2cc-tI4tF*5!>`zi2O1F6x!6m1_IV1%cEB_$<=ay1OLAscPzRuhlV5OP&kRg)>Crt+#)|d7B#qiI==m715tfjUP}%^yB7MWw8v99uwkd)pTFlUV~KICk;n}QhC zz4Sa z1=Hc2cR#1+`@1SbgzMKZ!yE#1O;x_O0(X7gk1+1;{2TlaeL^{EL=M!$a{;a#OrP^@ zs8?uR1%Luw8L^oMg5;(9fhByye2`Ev+!fIkD!pG`$%FQ*mQCbiU$h&^0ebNA{FMgk zuCpkAU<|2I?Urb1ZYCZdL}g5tB`g6%m)>6_m9 zzZgBhLer+UEeaP4iH2QdQf>#&2dMS212K$M*OA;SnoN7U0A$`=)cUyiB1oR=-2iv^ z`_Va&xXiXdLM^hg^mz&(2N}xUWH=pm@+LH)KF zxKdcYfQ}(H_texT*4}%yQ_fK79k0+l93l2T>PiG6l$Iz0`D)r=9__wQhacrJP_#7VTO-ZfDxs z)U?B&(e12L_dGsGNTkt}9&JU`S< zKpjz0QOMvZ=1of7%i(@x9*~@zTLg;;J5I~3>gvj@eK=ZxI!(vU?yP!=yn(hIP*^CL ziAex0qcLCb^|3H19;FJ5SAv@5pH9O219%`lHpc5==K3yHWam71;C6`Bo>;mza_^!ADTe`CT!Cywwk(tEScDq$CKwyS*cs zgwfxJYwGMrU7t3k{lY!M9kQXI4> zY7SWnM*KMnrUsAQ@iB)GsWfm>d<6tQ%A&z z)iu?@gEB36?0ul)5!Ie}L~-%e<~$+#`wRpLXyRIH7u<_F5!+*MR#S$Lh#SHtrDSAT z+1ct!QmTm4BfL~(@O(g0)Z=6l5k?7$I+ZN{=sy^UuE)us&<%}_lS%ih^_#-PaFo`B zcG`WQrR`XJv)?lB(S46m=WGGCo$W9oSY)WyXnHs$W^4!^$-QoHRHzW$+H)0zffrRY`9#N*Bj zOFw#}07P&^ZkBw@yzqpPs@m_FgTVu+!ZlRFzQW;EgR@W2VaObK{OulpQt#H_K{)B4 zhyZ9|3J02TQF@Vezda$2@it~6;2Kfoqm6XKA8{Y9d3e&S8B)8ev^`fh$eXdy>&Tiw z@*vTHPpgBl%dIF3>G{+@299#Q+@%fFRA|I`Y(3N`9B0KezRIr}*0779<>fqAT!{Hl?cPAr|dDp}W) zSU(+dnEM4@07I5S&+RST{&jx-C_V;8yp;S&;Z+xG?jYF9u;y|K5jXso4LuFy-;IQ7 z99Cev!$PEL)cuToH&lYoa3JdjRq#vyn#XQNd4bgVWeRSm%VN^-z0MI%SM+NX0afe( zqlka?e~5Yyc&`8Udt9Y5A|a%bBrDk?G7H&-NM=T|_a;iEkc6ykLRMCGD3QIgG9qMz zs3ZybpLd_%{r%sM?$t+md%d2|Yn*egb2W^kXhIg2IJ36qDY1;cM1WzRu3ft!FbM@I zQJnE(Xm|lkfv5&x2!lX^K3Fa9SIDfFd*UQl9c2(l%;Slag9m9rLs8?0BmV%r2ls+N zWDsL`G`iy{#A>`Ee4Z@lPzq9e zwC@F(h;c(49K?HM72ulp8%-!#xY`qBZOz*a+jKT2Vers16bYDC;mRhK^yFIG^J#SoBWXu7bcqz;s`_kGV{J- zA2I}pg6-FUjgOP;MD0;~b0d(jMXm zsYvfyM~=$AIvv1VIKEZEnu*DgbE&b->x;*WroVl4+Sxv_v0ODE4G|p`u}R*_xJ$*U z9N!=kmjq^>Ba|gm9cJ4nChdSw0m!%jA`^frTq=un3ANT5At_08!3dflcpJZ1X@I|F zfAGSM^N0#7xh!v#;;w=ch2OOoj zbq2yWO}m5NSs?1aYG=z#<>|fxntwmuBknJ1s2WVN-f5eDTK}94y6^Qn!c)$*;ZLbL z*fAvrH8C(G+!|y)D1quWtMIP22&2iSMVmitc+R$I1YLN@w>T-I{sgc)9i&O(?6|Z# z+$ZR{N=NM2+JQ^|r#*1#E&7K-U`%SV03)EN4VX#lOCp+yi!3EhrePN6!^lWF>Gng| zp+dxX4_HKQ?kPGr87}<(_4P15Yg*5o0c|l}3IH+?tr22zXyE`dpjPUrxz>ce8Y5o` zfFfYUZ{Mh3-c=7rAc!qt&G(M1oFLwoI)-j=bbCLE=|DJ53eIKw*BYaOT@`M_m9Jhk zpfUq#jyPg)MBo1)at2oZ5g39dR7VK-1Y$7kn6&2YgGEn(+TpYSM}b4I+0C0bXGX6c zqrQl~7$LjzqUnJKm&fE3x5_=j?y6o>K=!l|VT*`L(gVIla>9+aNc>_O!X#9e5d77g6S#BZqA{$B>Z27peLFzb?g2tOL{fhsDpOjYA6;qLT6J$<+ zd2Q1mmp_QV_(v6E_yJ|*Bgu;ZrU?pppgOc0Cmx6fPMw)499dqwDy8B6qz2-6)JGCb zH`W^lI};%@w%P2)NDeoh)v;t*7y>}>)oP#2Fa{@x~xGb0-Z%z6R&-P~NK0r6&$7Fb#;jDP@OUFS34 z1pF`{z|eQYbq7MStW6~n(;}3K1n}3p2GznpsE-LUU+8Dcm7y1LJoD^1xvG>CDX|GEzd zEFc5dZ(H5Ci2{Fb@+ncrP=$1S`ekAB09|W@NSDOC!38{ObPZ`7rhE+l$rXTNU^@I& ztCBN(St=O}&VBx$7T|`lv2m}L&pR|jkTR)WW)-E(@}`_T2_Xr%tQ{2{2Qj$|9rBd` zA|lLTWoUYJakr!1wvww;M}4WV{~|Q%6mZt9%oPKkK|psfnumx6cjUUQUn9B37b944 zMu^H+-gu4ewFvTIQ63(mOP(Oz4=qPPEGyZ)0Jmeuz|X^7aCU{@cOs*_WI!L*bfYX} zu`qo`zv5CWjx~NXBoFm0!ICsh&;`Y9182~N0K@v_cjvetDV!6LaS+Jyp^KJv+}Yu= z3=%`|n4^n$B4HSWU_1++80!^Q7p`E@di%|$S`^#3EkKV^NrQHTzcP%nQSlOBrjJWL z^{3%A10yF6S`d^6NQfb5y79Lfuv^oAVl2!8LpvbRCAc>kN(9Id5P>m08P-%%C=aB5 z4Ie`vv|^Ia5=IUh`(tgJ_P}Wq#$w`|AhS!riTu7t|x+(@3;PV%6r#e_k(yk$aXG0 zPr{guRGvux6cDV2QsB{@cD>&Leqblrje=CjKq0%ri5d4aZ_r1G zLS#atuDcR4IN*ix@#vMG8(UA}6R5&E9~o0Gvdr9{kngE5$6QPUD?U`a20&g&IMI3v z^e}%bPx*ngjVbbjEvi0F(Ot7ctL1bWt;pEa8q_N1OZ93zk|ErI)skCrycU%21a=s) z5)I@e#F2=B|E58hkkAE}6`o-!8(}&nIr+r@y^gndvsJcuJ$v>$JSR`6!3_QxWTlO`I4@`PDd!QD;zUtWDKPpXI zV@QOr6MDS#3~uhDbk|zfPFGD4b_0I-@+J4MM=MV%3RXmAOocT*&SrRslPZP20DUW* z^yK*bukc|KEA|rL*lzIvT`mG03u-T1FVD;HJfd}7g;NkVSxHMbEiEk_4h{BHL8#~9 z<;6@q(`Y78n(<}9p3i4yO%8c|wSXT)sUC2DrE6z*p^|}_2U^F?uIdH7V#lsA|m3JNc;b7fa}spyPyoDuR;syIMtbt@=uW4AeC-EL|>68h`tWh z3HNBxeP$yvAO&G2dsR`?Pu>TvXEF|9OFis26q49Oc%fn-mStG*_FAi*rM(-H_S&!jT9brWVMcxBLm^+dBKUw;b7BO!6uEMQQ29Dc^l<%Q ziQ4t2(<{lpJ3}+Q=OGE38XL_PrA6$y)Nd?if&Y#05j698kC`)xFj4s55c9tRs?xxo zwJ90iS^q|3#5D`t>G7CABOr+ZiuSHir+ATxhWris+pB)>uJL`sZg1NAY)0+C9OApM zBF8zLZDuEgGo^YR4fj!`qR}Nx!LB`hD2at$sNg`4t?Wr>8DoSH2o)aC74W-2>nA>a z`Xpa)Ty$s;5!M&1_S4+e$yXr})1W5iCqQ@qF@6tHiZ62&ea?Y4!cqZ~)TqP3pG-T~ zcu~plDDNHfdv7NY_n$riYL56?df9fekM=PKn|GAk7hq4RxnP})$jcQug#2>@F)2uc6h4?&3gW^8P1l|HmqL5iO8nU45S_79jLBe|$yytJD4yaEnzg6TvP-R2C923~XI%4!43anZ$q^`wqDoV!P1Va8FLF*J=oDo=wb-&QIgIeLKohQJ}z=OD-` z7X=8ic}2W9lyQg_7=_>KqW|N&Hy;B*pHEmC-DN`Eph^QfQY?Za*@<-xqa6-FY0+0D zkHP|1pa;$|cUsK7H{Kkek>~lKhI)G`yGtHYS$Nr-9zU>^@cl8vFaG}@K?y!g-9Srt zjKjlNY=Nl~D08_xHUHI5=n4Sg9HYI^+8IrRHVk~qn*9{}Uqp2R&X{)_`#j&^U+1Q8 z2d$yl1?ovuk(jj%(t_tsEcs`)9Y9790HJX4QRHR&r@)o4(f{Yqbzwk*^=YyLSXShI z)H~=qv7|M`l@zjO!>m8gTh5hapTulOQG+y+`AY`&=a5DqJaXSUF%IM!75Wb7=o31} zSh{&e>e^_&l|!3=!+|G9NalA&58VSKVQbs{+3z;03S2YvAp|OnmW=2YxF1j)QBemm zs~ktsUTMJd4_!jlhh=5}Pf+y{DC^#x-A#zj(C^?6qSD5AHDTa9d6N=&AM^$)(Flk- ztRtA|g<>9A8Z8Z`bICqYH5>+;f%X*}q5`0Ca24-Jh(z}WMhrhNoViC2nn)^OzYG*4 z74 zkgj3l9s8{rR2?aTbiX+yY#=m&sS#bHh=h^`uLd8n*#-X-Z8r`VgaDu<8>PmfO$dNe z&?3SN=7gBG)Vp$kH*@6cqxOmN^71c7)Y=JJ1{f|+J9m6!EWt6yhk4V4`3~q@x#`Gh z)FUqW6+wmk|G)q!o`K}XzMa=XR?WPDTEc~sCF%OoSF08GTgQ!HPi4~LO;AW*)4fDG zy64LD&N!3XCjWL6zeZ#yU`p<1VGL8kP8S9*fwyA|HDpfs$Y2an&j3Q{60u&&P&BC&Vs_vCsT;q;364?=zRXY21}V)r_hS1^gB zBEC&}`ueQOdacQ9Tb9v9zcH64-z(R$feiIq53QP%tNdHVg(;!rtwT+KdzSNaug9c; z&h-Dgl1%j1o`lO^M9gU4sNXESACN;??nz_1Ryo7jWTq1kR{=(N@tpsU3eb7!LoarL z-FPW!8?VHr0J10AQ>+h;g9E_n8tphsfa2xcEK0l@?3{JtEvUP)U>i3%8PHK_eCO38 z=9!qmic6He@NO{E%h}8P;0q>iG2@9}K*7<~*u)zAv)a8T5Qi8D@xzBrR)&3(FnWq$ zML7m(xs~6;3{Yn1%pV4g;m@JKowZ+5R6X`DnYFh^14E3D52k8(R-~7Y!^i8q98Z{+ zCb%vJvs7P1l~SP!7clWM-W?dx1I`L38N6Lk6UdrgKfENmO2#j8(58*I-u1ftV)OD| z15>|na*}_g>s8Dy0f05ZtHmF|E?5)C{ripLN~>U#_Zlp8gOIu z^f^bAE*ZhgrlsU$gLUcT+PMD(*mOgSg%5=bhzAA=sIaJrKk{QIvOb}`f`u3quaLF< zZ)m8}pqFVZm*CQj^N5hd7J0kF!sojeVY?Fu2z2lNHmuB~{gws z(lQbl@+8edsgFJabQ3bgZHVeEg{t@rTksH(S3ylc<>i@l0kjL6y`we{?!f~YbR54@YJB-d(`~Of7n+MFMDs9eStl`$L;#kXhVc+TVQd=0br2fe z%WD_@w$fMb=r&usiJ>hZqAu|lPd<>Bdyx&XI|ejWg$TB~V3!saY|w+E=K{)t;&Rjf z*OEj<_=d#q&2lFiQAHwF&;2cN6YY-b9dl)qrQBx=O8g>4hg!v7bWB|4if?6VvFFt8 z++aK0Rv_wdQoG>mpngl|IdEqr>d2+?(R<5Bl%(I^iUdd7u$&QM4*Z9lK z9iRQ=sQ8$uc|6M+;`@}1`+K@S)=haOVK{zqk^AGvk7;C+Y#7OG%ZYY#b>-vZyY!Zh zG?Xx}ar7b(?XQpzC=@w*^eDzl^+e73Y2_#C?~z-x+)?g+)@YjT)_a!`{j3JL z5$Z~~cI#}aUKuziE2a@XXLcp|`FfR__8!5IMwZ~T2loO4nEQl*+j!Z@RU%)fUn(s z@NOt%0$=9m;c&q(EPM|ph0)hhznnO6LP%7!#Afit=>wm7-oLN^yR{+av2^6$)lJieEK@aw8Kvdrxoa08Dp?>)yG#q3ITM>4jNX$ZJTI)HLH6wZ z30AEe%@$29^fTepLdv_sR_>-#7g97av34`I`l}vGtUoA!KaC+=MThojk1~_cun6n0 zjFTpJ^c{{l3LDOFQxx(7!d=qF>^%+9=R*oiVf$rX zj(o=pR%vr_m+))$5vrWBMxCSULG>SdeSgl<@%K|xFQ1;{JUu36g|*lo7TrQU&q^nR z-Ft_Gn$_Dh3<66}KQFlaMwyjb_2R``GnS~}hTh&@S9kaK0|W2+`e++X;g`5uPhUTG zJ>u?3T%P& z0`7U{$DbfMN5OFN=>B1k?}tw}IWFjQ3f02p%+!|=G- zb(s{apA!tCpOCcfXazpl#`TV*Ug3lCR19o9A3l6YG_6b#>KYm~EkqvD6!h*dM#q1J z7~Jc~>K}F#|9e)?pe|U)MpolVe2(52VN+#>w(j6K5z^n%Ss(2rH|x6}V}toZ@aau^Ofq08>!jH~UE1 zGv>1_i3vlCk~p)bNBK7T@z=R#XZKD_C8#E*J`?)Ia$c6|?&`dV`;V)GSry~HPYgsZ zh{V@SCua=ODMfhBrQWv|P&gYW)fCi7AE#`5O`mPx0I|u)7wh4+U8n2bQLfx}vtv(G z7nGD#W2VxLzNV7Zn>}?J#y5-LXAL(F*sDcfSGaJY|C&yy!rM=u@IkZQou*;b7Kr=Y z9w#_2IgDsH7!|8+xlfB+%+Hafy(O1ZxwwMfp7yhs zmm2ZC>p$*GeCOrg)&T5AG^lo0J9-PMm&LJ~YWuzS0Ekukt`~cUepy&ZM^E}Lzsd)R zX1Ks`~ntJBuoGE1|pIg;u5Q&bya-rxeb!>*Z4@JzTNn4AxA$ ztQ^tSHA*X#+durRO8S29chV&`OK2!R(ppvueJIxaC=k>3QG5F72m+9`Oh%6-AwaO9 z!5gyG$J|`{T+n49AT<k|beF%Z zdSB5#P^)KpkGbGp(v0(ut?PAzih2frM2>ii?osQtOFB&w(9Q6}Ioi|Yc4PgK9~7i< zd-B%4J)iY(oFBZxiHC$kcC&ZW@1E`rgPX__F0-A`so!$`G~e9~*eLzq#gIy#?aS7h zAN9f;la!PcwvQ?dj~JpJ_dnZSml%4QJn0Eh*!hdOT49Z>Gd|X*uRIRQ3~uNC%=sj` z!0OnyxZgDwJr8~Bzww4N)f?o%G2d@HP&w!8wAHMQ`Dl$puIREfDn^8|?L&=^$LXh4 zCm%2?Pq6vbB_jy$j6cTBYMYn;l0=DWAXk^0Cs)&}x>4{_61NWRZn!G+q+bwqlU+xS zLt#a9KdHqdazW3g+a{oY{sXx1x@d4A*)8*0!%l$=f?}&%k%IW*0yzt{O;-1&Lnz_f!zXQT(SLkBZlJFn4$(PJW}Hj{N0a6 zvto0&%EgOej4~`F@z+m<8pF}s8I@oP|GS}(j5B|S3L-im=G66C9X)e2`L#v$u}BT> z%ny{#m7J3;9zpMn(sf^r?R60NnpU#4Eti%1cNS}e0j5+Ms8f^~{8@SLUvM8Hs8w&= z4vgWO7Ab;=w4=&uF$aDuAT3=t=`PGjf%op};Zaa&_x-0APuI=F$p~ibSU*-UMN^S? zp~t3i@{Ea3MAXjjKX=njI#8?E-cQ?Or}$FTKiYoH;dqYb*wZu)&>Voza4~eb6%fzA zPKlnd{Gov7gqTF}+;3;OwRkeq^n%Mci-vMe-Gb=q57MR+M@pF*QcDL5-7xbPpPNEk z`M9#h3cmNx;+!G64~EmG~55FoHIx15UaZ`rQ_?rPWUg= zz6Z}taGg$ziM^Gxj-B|u@Gzqj>_BeRPv7?&K1ZA-s+I_1(|@(UvD#gV!P$dV)z$Kv z@3;VxAkRKuiH9U$Yhx|M>{MPHcUyv_PqgQ&1PP~8?QcjWvoZ#Fo#z2qSH zJ!lu@BT8MTSov?}HJndqc~rB!R(uoIc-T4pXfJUpeH$|C*c@mY&Es2Lth7G-KP>>S z?GBZx-S!7ry?!lTb=z8$TpK+>b~*3u(>ok!QNJuNk2hqJ#b@vfnv>@iMbRB6Jy(iA zBYfD4n@(%*ar;In`$~oY-C?j|(S0MBTx;+IU5L|6`=ONDoq^OD+}m!yw#|gJUUYNr z*gxX2BJIUgpL%eYNI>CHPL53$zo4x14m7+`yL#0aCAZ_3wMNY<-F^*K57(ygAq%+a*pq+x_0yyzwkSQLk1w;cgC0Gigm?-n zkMqBHNp|9`BiY7iXN+j}RX4VQnMhn^RT4LNbaB#YJIqo} z{*j%M#t&`?zJLZ;`FGR4GKAnDlt!+d* zbkx$jCh7L=9T+e(l;mabN&Nmv`guP)MU_R>X!2V#fAbShIY}r^>67r)d^C7q44quaMHEbi~CxQ?S-O3!iE(|%(2m|DVRe~)H?hUDLWA7?%_jz2g?wtcJo zZC7rcmGIK1$g%N^605?%uhhh{A0$?W`2Pz3Jh~aT5cGY&7}GRA^!DKc{>#Q(QL%}M z*KKVVGq-K5tWvYG;GkBvv}FqvA~-z!fbe=oqp8XE-z^r|yh0w8JMu6zCCKg<9Lfp@ zFPLt=&6O?vV_u@xG|S|^(kunZpayZ;?xc;zoy$g5wSKeRl;r+Dt{zj{^Znz;95fFo zcP@pTJ1Xv~m@iY~%H2Qh?DXmN?Wd(Kr*t_VXl`Wi-u$AXa?F4$s!#q5tg2Klvr^gX zaL@v~Cjybw6E}1Yb@XlLCS~F#vU+E5&)AHrqC$?o^<{ZEKwTwP>NbHJvg_WlSo$Z& zf*nE#5^u4Y2-|e7Mg#KDUNFasgv_ig4O*zJENyIZTiplEQe!{yW+mU?qTlm6zx?~L zv;I-W?o6+r^$b=Zc=QF|l|w(yeq@8>;8go(dQL8ZWwsZS{b%R+$6npqeo@A&gi;?5 z1^}D920#-uo)SzKKknAl>C)qtq6eidB`l`GFE@`W&safArD$;#cTB^NO*ZN_pF@*lAuI{B% z4$y;&i;I6KcQ}@xpFg*nX3XB#sl!;e@BZ6);nJ+E8*g*P^0nD~?zMd3)#7R-vJ{}` z?p^gaDVM&>8np7p{iKp!yIQr=2PU@2YULsZg=oPB8V56bM!5p09sEzfYidG|0Jk|b zD1?#ZM0LQX_(ph3z5V_29v-5AgHgx<)xi8PWI!$En#)!WS8h5>nqRdrF}V#{W{bI= z_VrtF-&RxuYgIA??sl!7T3qrxlAHZ^XAp7ffUDlA(`6e)v40+9bTOaWU3|~W^vi+K zvb{aF>F`h1WeryZtQwn?G&5XkqpGHcWw>C(p?24jN@Zmn9yySZLktWlrKJbK z#hi`rWKLLl^=(vdR+nub zx?fw=bO?C!QlR#%Y2DP6?n`yH_a``-+h^ZhZSLZ;takVqbq8sa^8Ot;mekILE0AF! zT7tm>X&?UbI}d=1!29?6SxwZlB6sbje6X%+Vwjnk*;jcU!ya$$>}@poME7emh;Mw$ z>p^RGcfk?2@4pM&x(6+C?B3q3HWjw2^e+#s)uFk;_MSGFY^7)C2^uS=QM2;}`2}tf z=iC4}qSBqJzyufGky1p3^K`Ix7a};1lYgl?4zqP?SW;3_)E$oNSLtM*jL4i+*>|hM z0xll|74qjw|1~CsJvfy}eCT^=CV&vXj zK=*U#M=?)Zsuv{3(p;=65`U7G49ads@weI7MY6Dp$c}Fb%@CHss%Mp?8pkk?Lgoo9 z2)~UV4LC}F@ECeLb0;Sa!)JN@)>aM?Y|B4hxY0B<_wo^Ax$1Lzz5GM>w@k z!}?s8+xhFTFwxWa_$zt8IFzWt89_k;wicBpERErEFuP*snF1{jD2L*T3f#4-uM9FA ze_?sZE^S>BeRPbsyXVJ(qW1GW$4T_BM!vaF@>R<8i%D<>@jcVKuJ!?RBX<-vw+w9t zQCL%lH37{AHvI10JBDM&ZlJIQqr(GWj+k*#>^VZ z)ST~Po7GlQz8VP$>kfW5s9}ON({d2g3Vo{s5zMxMKu;-uqKNJt8+$bJH8VZ^PG_e&{0W|> ziY9mQwk^iPU!Rp4%PRQJo`vy}DqAFqQY@^^*(J@j<6Lms^9_Sg*fnyuX}29=P5)Lp zl+5>(bMNr7pvRA7asPuQnNn<{yJeprqb{s&xoxKMGX2vZgeKNB%M>Q3omCon}=E>F|E2$tf%1Lm}T1sUCK%T>7EHa6;|Z z$;mWtI~xawCVOM!h|GRsJ$E;^Y|=9Wm`S7|Ax1eNs%@xfu23nk=0S*4R@l8UUW#~U>RY>&$*sZYH;k~1vDHFYgsZ01SVEZ{6cQa^jP4LG}* znb~|LYoa=@$~V%%l1Mmbz<+LTX~|-?GZD`Wg#h4<7t3o{d(mSlW(8s~FXXdJdfX}B zn@jP{&6X!A!pgS`By8&n20BpRJ-5-xzqi+J?T5)ccaUa;%yC7%PRC|}m)Tz#g0>Tq z?KdyNiZw7brcwPKwuGOuMnevj6Pwu*5p$ z$V{hzTd1dfw=#9!J3l%#MC6sxtSi#obkrv|VnG|mh2K4Ob#+s8xg$C(@W!$7w(77V z_D&&Jz_4F~7SaS%L2fm-tT?ejz`E30SXo{}M7Spy>W(k2?{U423IIUn9{MF1_t0Ci z#z_OBtcCQ!1uGjH$V?-YGcM7}tMLJTvKg%^jbtT-LorVb!8VA444Dnlqw{!uG=v)j z6=`rW_e2;SEOesybxd~BS0#}hP6x#oQgXKck@j|8o? zaC*J4Xgb8V+GA01^WeI5Fg?Ae-;Bd!&eZUin+i=+FXP?qTWcX7X1smXCOzGXo}Stv zomnuP$)fugk(%B}RatJ2<$pyA&>nn%*bWQfB9+ujm*}_XA?&25$K(U#DBztkSsh;7 z035nHukB`F5W%`<&z^Y!&g5=gR5v%elC+!X2rS&(+;gYgyP*-hT${7YU60$N2Q_a_ z&=@g|o!ZG!PMvP_c0!8WA&jm0Anl9J>xaI@S-J$Rj_Bijo{zqc9-x>zcTH0#HwsRq zjOF$=6}imHSEJ*SlJ>OH_@$kj7+_VR2AR-Y44eCue7l>GYUj2-D2F^IHc6j$7AxH> zh0VShJA9cSZ-FKPSkaX$^e|OGxegIf1S`%_w016pSLno%A#cmv0$@d`MH@}=JEb%> z*#5Jzg|nS~IjyGVrgnjeg+-vPhzevR*rN)S6&wn*L<;0M+XiR+&KYr<_RV>vEeu-q zh}s`yk);yp@>3Cw5nLfAcdBn>we#L9`EH(DDu-B8hf5Qd%h{T8E>>5GL_aY%v8)rC?Ue?Z_Ey0 z&I@BzLfHXtA3Y6G)EtVemR43)AGnL6WLjI-E2tHr?SLevOe)n0n+JJ}YujPbR$Q9} zBPqaj`zR@K-wyw(K4rUK-)hs@+xsan{~GWjFvO97I+~()wY;W zXSE$T!5Xow!F3Y>&(~t2oUU$9 zlFLOL+xf{&LOEtbGqY&p?pwM}c%cu|6d>g~M)FV6`_ zA%oYS^BML93U~P1J)x)bZ@=FnNF*`ud3W4(+gfb|ehA%`+vp}?wU4+c z?nm0e_@cvOfqiA1C6+ggQ(}J0@YgWY@VA>}D7qM{$J8PR-j()Q(V9=*+x=^J(7%?O z7T$v4Kcp7jOT{CA4lb;M{6a+lsb(67wRXnP&{c5D(5R&MR4lm*J%tLNP=k>r0#!ul zdaycNU)56F-rP)rKAs338=Z+Pl?^(->d%Jwdgdp*T<+OL>9;Zwszk=t7v1U_an|nmO9JuWSta za>&h5qYu7>idsfRCFH5Aj0P<_p&+?)TUwPQS8%uMCkpkxlI!ZEVrw8O-=dM_1kTL& z2Lcy@sBksr=I7JW)2CkKJOVb))1q0)HCrG&em*|cDR)0o$>QdQ-VX^>>Q#X#>8APfGapLHq9zW$Z2WOAT?ooDJ)*COYK8izr#w#xe~b%RXAuwHZ42q zvvAY0+(C_ZYHU; ztPxoPVSBLBd$?qTqMA%z?-$2v`CC6NDy%I0&yFULUH87}rQwr72CwXTca*ocoTIa> zKYA)gJW~(2f(BMN1?M|LmCZr#xA#=#@1I|Kp{x*&Tz@aU=X|AvPm%7c>&(7Iy5_#V zM=&IM@#21|S3q>JBo~!PEeFi6lYy4!X%6OCCwA8sUeV%USWND;zXyE-} zHG4b9ZroDH`P1tioe5&+rIOjHNUrfQ%=5@-K&$L94&$tE=b;RS6ahm_f!T$RXKrDkpcViLPKEEf0AeZuUqUd62^rjtl>YLiW0&NbBPb#_ z{<&8mBHOMUy%*7wh2d=cJ$9X*znV@^A~F}m3(#fr%WWd zMt3)7?w4;;-R_)Wy6THfdFvzG%-o~COnGrA95&N&X+o!7wnTJ&@HA6Y--mEpVnOKi>mb=rZe zA5q^7%&#Pkf4cM8>b-N|RQQ$OFIQ+RmmTel!aV4Vf6uW8UG(;+x7ro?3VsVhQbA3x z>bkVFwn=y2^Pu;ySYjrOfvRT#ZOpl?U!FF&0GUu)Nl7GhA{G`FeN9&)PQnob^KwYa z&#RsKt)Vd@a3L;d{~s69s(DVEz$WM0Tk|mhf=pJFsBPT({g!0iv{JWyR%+&*Dedx_ z&f59~317#PO5*G;n_DEwQj2oA2X3b1TYeFL3~Yugs^0X#it=H*#)Fwr^9J<;mr3gp z%2D;^v)iLa_v4BS*fDCq7HF~2Z(R!U*LCt+T%u>Aa-yPsao7B6Eza9x%#$&=(Elbo z3Ss?)L1q2VpF&WSVK8Py>Q~2a4*84(x2-Gj%d&O1X^wyeGTg3RCy@?K%1C+QdD=ZS zNA?L38v1<{6iy&sAnL?nMJBBx55O`x6b%9b0y|%0;0fYPAz|VEit8Q_&SR*yy|a_h z9Vn#7SKV?uiR$gm8(GwXadB}b_V$!lqwzzis;dJVJFl;Q7(f_>q3}g2>wM57=kHTG zA?2eK!dgARmlh1 zNBm{;uPa%VFg-NVQo!S9T;{C~aNw4l&u5fbod+m;b< zW90D96cKpf48Us3OK>9vK=g?Vk1n6CP|^tIZt&l6OJnxk)bHO_<(wqv;*1tj`oD9O zgvW5wrpsw&SsEQzlHs5=_4W1DjskMe4sTEE!q52;SH@ZssZGcRagm{Y2u=fGY(p(~ z^>Xkg%U>QMdqcrv9uhCV*dY{uP(Gq}HcXspV!HX1TnN8V&yswxMvg%Y?xHraezI7iIvT!e$f_h|17<=6FD5Nco*0MciX8wc1jU<|D{L> zAW^ykF(H~3d)(5ZgllhQXP1$lZlKr_ly&G_oi2W6_=7?%^9-aOIZ?qVgDJ=^*bazm&3KpI3H0wFmKgY zV~f-Xk(Cv5ckuO1NKH*;EVK5Zx-MQ;lp#9ZXsR*#j69$)|8ntnnacSA3t030qvERn zoR!!34J8v{2O=z|-Opk-W+qn@jAj*Ci|21bbBIzkPbc%0w(v`>Y$u|h5z+T;O?&d0 zNo>q|pPsS)I+fUPkj;gho0hs_wLjm$qGSjW(A3Z))Q5u zy5(Ga3<>0)+~z`VKU!e*3m2NyXi~v%;MxEmL=F3MZEety4~UUAIv(l4E73QuQuqoo z3|m=KPf64d3&s86XRL0S&Q#3kOyS5lt8-I7w^cW*$8xk!9v-uqIob(RaUrzRVbp6w z$7IuzIw=CWe@i?H6Fls7=$7J-xB7cD;AjE#668(p*wW9RKZCci8VKkVN@k#@kRF%n zK|V;qKX7F~xNi6AMDQ&_j5XPRW-TgWE6*vb@A~#&YlqO}5vV2#?QwV;+QP38{pRy> ze;dG2z$Q)HYIc1?K8+gHg7(Pr?=yo^jO?!>{yg3oI3#CPK7x7=6p=ujLD`Jm$*B5W zSZIo?i*gcF5UM*QA-n~+2!b3Xzy~4&-X8de1Y};kY3jQtL?^a$gRFgFz%GA#dWB}O zDlLwb7r<=h+|8;pk;kJ>bzP7w9(=^1P;t}O_xTYy(r**}&!8v@U}IzJ^9gKy8s>P$ z;EFtNSx$TaM-1i95alQOBkxmMe5H5;ICjf^(BYDO0u6UeoA%Ve6YXM0guUZ!0*ICH zTQ91vhPh^faaufSwe?tLFKMU1%v&>vbxnL zqK(Fsp5*!(wzvP_-&)F927N#%k$8+=k-VOp;{eC_qIwZCk2Ul4DcBX!-mZF{_!w4+ zUwWW^~8&B`Pqo=%&2qAj14Lb7w z%8DR$j|~G)spK#y*b(k;%cQVr8xotG%^75FHLwrV57 z%Mz};@(TnITci@j6JTxgbqing#-9Vs4{9_;v&~99^z)e~y}P|a1?p!V*LDXK7W4pXBlLD zc(eBNr;caZGgM;w{FjGHvg`+5ksV%`R8`nocdR2x8&Mb6+vj=IJD{k(xa)SIFe-H6 zNAPrkPW$yx$&DR&8&l2UCrWL{qS?7L?9EgJ2WOot0~cITcjRfaQvbsp<@;7&>Q+(9 zk%G^ILo`T5IB7r*IAn$mpvyTd*X4y6r%|5*402!mAgdUk`Rob(-_^sSbzE8ac~z2I za{o#s?sxd$hZKly2Z;7~dq7$V-`XvP!5nWqLBcBn0jr^b7-5IPY5e1V`DF&YJZnMeMoCEGcp6KNJISBQ`en z(ylx5R2j^+k1~`v7QXxmZ!<2)>^Gk;Fj2XipJJudZO$WIb6oZbM4j_pp-ggdEm3v; z5ziWJ7xV4Rh)qI@pZ;k%7+_8=Yc6&{BFV(mG(eXdAqL~i1O<0|PAz$V|NHl8I_+qQ z;+f>c5?6MmL<#+5T#)WbWF|S6J}0_L#eJ8Aj;^^y?BUaS==YsrJLAD z0xt3Hd&;J_@9SOX-n&1v7RJWjyHR4pU&jdMDgo3%mxcb)99WQJ#jCPss2BS=VN?cM zv3$hv%2a_UWb}~3VkYhq(PbUK>KBV!<4@G9ERJHeVEv$OG z5lJSh7uf8m1loC}Ac`ZTabcFI#z^%ADX?QhvX-2U83+S#bKgKK!Y- zmod9GLV~nj$E44&u1rlW%;o!Jqucm4mP8zosU+p53#pp(1{trJ{W5za?BEp9nU|D5 z|K+$#!uEzH1)bLmUi()~g7_SsV@3#4gz*k_J# z3@L!;r`vny78djeL_>gZR5;%D7{3{VB?9r(nge&vrM~|5t&mX$UeGAHfZd+!N4!u_ zQ0S9#MU;oegCHLSy39gE8A4a1-tgO2)ZVAkC~0RyZ~WP4HroW{$E;wYwFbQ}55(?l z%h4zAFE>5es-Qc1D(_=x6cQO#*{-Y6{qbR$nQXRYf5;hKt3N{Zj;9Sw7ZbSgOz9l0 zhWjZ&z(Tiyg}RXL@3Bo%4Sj37&aV*4p?R95{tqPI)YN2TSFcaqv2kA>Q$u9`2Lx4m zuX0rbs`<7x77Aqnl$v0SfHR;anw!sAww;A&8Q&LO^;=>M9kA@c-xlDG(Fl!#&MtQ7 z&k>T|nidhHfF1|4cc&%|eRZciD&7Fp3-th!AR^{aoxlHE9ue$1CV)i~6DB~D(Vyaf zKr#!gJZ8tLFyM{8K(?LtwE|v?PLpv)DUdj`P%D zQ;1MRcHrp)WjjM>{@hU1$&n7j?y0^{>`*1C4}LI|ltC$!kwvYeR^FBk;5RUv+*JT6GxMR{G&WcU`D6>`qV(EAl@ow3+Y z(e)Q*9cx%SC-9pdZ7H1WKX^IBXlYpoq#ki9Q6u@diW{!3zT0!>HaZ&dvuDvHfmU{V zB#rfGl9C-*cxtGfrJA9caMnZJuj0qiB=7ZAYEDPS%WZsHs8b>rOM_t8N?1#B;?k-iu|l(zo+Qw@~x!f zr_~EgvN83ad;3-4rfy$#wbg?4qn6Mn)6=%J~?8W4?`r%V^R-WE*m{K9MZ^G+nRYv+WacU zg&co;RwBSP9JHDRVt7gD8kXv|{V?S)cukUD(86G=;uqV zmDg>3<$7tc@L_T4`_JBsEhM@=n%n>P)BfMR(p$a4 z%ipJCjA#0<7#sGNfjId+vERR9{%d}t^)Dy(@16k~&C>D#A~|79 zLG>>z!9{DhCf!S2jb20$Ta<829;un`?9rDO9*gOCuW0wt(qqN&`SdT*DM@{AyRqkS z(XF1tAM>v3F57H7Y=5nDTAlAdYj0EPlB-hgQJy30e^x@G9V1#-RzLKYl^b=EANG1U zurfy4_OateAyfJIbNl}LdSR`;!wTB>Fdh`s)(F8g^vt~Aljc?jPqkdh(W=G&hX%Nh zn^T>YdV(-p-~=1PwwX)2O=`Hb)lb=kKu@)6*DgfFOXQ})T5fi(#!ET_f`NJ;b1N?G z2SO08NDPMwFRk#5j5j|Zfs7w|X?MLb?q<NZK&PJb1Sr6+hZ=@-J@4-e<~=>W}zqWabL-wim+j<9jSLP`8TjZ;6D z2OtoD<w!j7TA?hz80oWQOdWkR(N@jLc*uJ7jO(<9eR||NXr0^SSTmdG2!O z=eoY%^E}SuIL`C@H(53%bn;{=Ph-cm0-_xb9sDR7rt)hy=VzAP(M-%`mP)!evLNFV?Y`8TfJ z)hWo)D_YlH&GKK&kHFvtUS3{Qj{+hhpYUxO6lrBXB`Eq6bu%1h1)Z6)o=Nnio%QIT zL8jL*y7jJgugnvtTN7O;sF(-s-tU}$>(T#xA zm=)A?TZW#w-%i#CUzd=XZ*)4sqUd3z3h+x}MMd1|R7G6*-9^5g#I7WSftiifDJOJe zpi&g$mHdtGgvp8z8np|ZGAoqD~cseO;N?e+b2`dSCD z&k>lKRK%35;qjAjW*V1HM}~%mewYu5|JbHADh(*^oDkmF@o7&{Ji;Wpau-~?+J#yTUIHBnLD={8*$=6n~*ZTY>dK}_mC z6>E{3ABh)x^5u|?@hX$?+V2DS(@{F_&Ka8L@z{mB0nvFjiEaHM>W88& z-Jus`Ym48{^TO1MZ>&Svb)rTg^+$K!%ifi?VhP7TRGTyWn;$QD&g=zW%WI!<0-4%) zxlV_mJM~@+y|9e!2Y>{T#O95vU8iD2i`8=p6G?X2m(SDpuJ$ZK{=N#pXI&QY-X8uf zWlfjq&j(yblOr+00#rb(+t{%nR+)6xP>daqVcYoU|8A!4MEy^<40Ci7x3+s_tdrZU zxbt{y+Ao%BI~h#Pt)XRVdTqAhKR*N|n>$@!M2#gb_1Z-52CwQ?dt9?yjOp@Fv0vi>r#t;sxZ&Ru<29mz2erMnmgyj6KdpxMc|~E`j@v!c z)2*1fhLs9%y1T@27E;#y9}BFwIAvJx2|*GsRWaBcaHsG>A}FBWjG6+&UB$bL#dcs3cl)^3 zfty$+0L%qpH_iH4bZ*h-ft#rE30VLgJiBs34nIOPBk&raq;`h0Vm2^2F>51{`>N23 z(#hE!U0vFY6<@CvSbuPY@b^pL|sDYrg)p#;siFr`rReR{NaZB}kmIQ9HX91*;o zd@(ILNEOs_@5Vy0D|(4qhKY&KqL`%w&_yCT>^v6=;%;I)5U3sgcmKBV zm(T5istmg1(!^rVz3A(@CxRhsn_ z{~nm~OXM~vaolz#0zvBHURu$7`M+8_k{R5x0>y??b>?GmsW5$Mdf8oizU30Ic!AUK zdFNlFotAN2dmiyHr>+c%S73D@;%7L%R9IH_J6wbqY=L>i|LQB&>g6TXrhypbh<*hE zDb#qasS-;Pfk||3G&E1Z=YV9`yZrr*gx7}j`uci(wUGADnwLL~c<3cP*CdFa4LJrZ zCccaa8xUCk>r5q#el2hCGB&2!Hg_v)LToi^GvfB5HFBR;?r|IE&D72~8F6zUujFO8 zQA4wbR@ub(@QtdiJaE+IYpr33U2*-mw#%nxBxx6r4vFJjO1O-mQ#f z5Eu5K)NN{R%hrv_I~DZ}UK>te696mO*7_)+!lDzE&si#x-*`yBcZHs9wWCJ+7n?kX zQ}B{%dx`e2`G}6|OCLw$Hi)RjT{khB?7!{JK~20Y{`6u&iQHqq*`TOjU)0E{?m49W z*!+jyGL)VSw;&1C_IAk??cuQGnxXSG=AsQ1)1pWj={31XBy5{YH6WaOTm}L~E1tAC^Kps<4E_=>&~FyrIFOcB3lmBED!g!_l`n!@{?u@M4Zee*=_uovA(g zA}Xr%dbU09)aSFrD?mtd84TCK{1C9YaAxSdTgVz(y<0W_;;v|H>LVhOLwj6!mo1z2 z``DZznX=Yl)AIJACok$_8Vt7d2@coX97*>w@{(F3m#?%Px!Sn!Aw70B(B9pr!F@;= zPiy-36aJnSTH=x0fWd0HdJkn&j{D#VYq?S8-X#h+T#CECiNBxTB|D#XA+2T_y;J>& z!-Q!CcFOlyI-22>aiYj_bYbCdXVs&h$V7)YHrU?fGFdXb1UOLr z^(!?9N`gA#_gb!p&jNIO0CcgkGJV^606^D;PRrH_KHD6gdLqBPn`>4>>n>EHq-?3T z(;dGii?DKaW+>X8xVXROjDBVB(#bIzOiPXZO|*5Dlw2`9Z4hX_RX|Lv`o{&iZDEbI5+f594W~(+_lyIL>$| zEYHMjD)Ls`)Y0;==VC?wvX+NzZ_3w%Ga;|C`)6FFPlsUTh32rye`;3-kpCE7lhbbB zaWVjYaaajcHp<{|g({Z!M*cP71^M#jVU$FVS)K!WMN0Kn58uevX{dgftkw}#=)RKc zq}5Pzsp9YL^=zs6*2$LkvP+w@b_>PLHu^T3o7x^(5OvSLJo)*($6yI9EN4WjMVXH6 zDdc^`M)BaanE3z4kH6y>wbt=H1{jx-E1=! z<)0;o>KCUUG817M=lD0Y(|BnMf5n>6)Vo<4qVYE>*#gEo;uO`hN&(sshcsUL^}?sU z7k&wq%}%X-pZbT$RzsLV_&ukexG$FVmYYkVC(dhQ*z3Ff=7Rlfvl{U7r(mled_6R^JcMH^{5aL88+6~VX<1t zMVWe;MV_gdwOQT#tJ@zxe*6#X6FH9^+m5MLG0oA(FL z$n20VF*XV?aWBkfn0iS*_AxA`L3)J8sQemuU`q9$oJ{J+3t--B?XIkn~jc z;|00(t@6SZUAd;@VmCVEi89%Xr zvb-MdOy%W;LZbleSXY#AEc(X%>qC06k>CW8Z`eRgg)^#AwI!OaD;=rpced4#>eN$Kg<9p#on44jP6A3l9j z@_q1ttWn}5_wnP2)n7PwW0l?sHA5ZgJ?~qN1cZNFu$%Ov$$sZ@M(Jwf)$<)^=k+m#V9)q_wrR zJk_bYccrv)VKVyi{X1%^nFGYznfO`cg5+@hJp>oxsrz6=10ztV@Ti3r7UBFXyx#G~ zmKkTsVfLH&0K#)6Dkzdw^%$e@wZ3}(3MITr?QDZbS^C9HVO<@rwfJPY*MA)O8Y{zm z^nA<*eD$-42$k`A-A-#88_E`cERrDJJg7I4ys0U>kxTzJlyA&)u^{U{LZQUqIsyA0 zX`%|?=I5^&`W7vCci~3qg{tHp@YlI6(`IkW%4k>b*6zEQ7B-nRr{l+B3;v15rY-Z- z&6|R@I=0>J2!u<3hI5`3fGBu%~hJjA0j-=gE4t1yt>{RY`pYQRD&K7+U3NKU}~ga%cz1W@vy zotEM~E}Uo8)S6mbMdf>7 zCoS!iqoa`Q$_VGa{rgP^>%v{Iv~|AjT4q*>1BmKhH)~j0I^LI-GNDzCXbqd0oejou z@mO6T#(s3Xy_sb66H}eMV1H?p9M%n`N zR{BETdokioK8uPvJMPeyd8MQ9`d<9RysY)-igq556u;5oEo##ipP5OGt1UvjRY|9z zJ{*Wj1jqYlLXWV^$@N|>r!Aso{Qcn`Iq_^f>h~X<)7gb5QUYnk;UcKrAyZEuhY53n$ zueB;Gmh0mm!wgb>wl$x`ScpSMF2n}Bdnb*icM@Lp>MJ^yNk%r%3$n!ysm%brdv zeYhIa3tjf(wQImt7l$i+Ou4=IY~LWr5@3cXtPsub?_w4^bmGKLS65e;&Gkh=*O{v; zo_|8(5-jUtJY#Vdaa!VrR`C(YiAn+hiCW&gZ~AXR!_TYssyeBIddi+HpR20KiMUsI z{l~MA5QV_wMKdB|VjOaEY{U>)3yZ;cx9bt{+8H;|H#~Oe8J5@mdV7=SB5zeX1}qaQ zLQn=K2tOAv-Qu+JNr3s%cz$IYpFx{-^^8c-hRC94b=|em6|dYPZTJC+(-XCcwvp+X zdVX^>w$2q`vJ4G@y9#Tpt!28rXu}2Fu&PO92N$T}bLRpod&g9gFnatGrqJX(3P{=^ zM1^9Ri})L(DVYA+_>tcnZRYyfgKY+FzXdWsU>3z*Bg|7bza0R^j zZ=Ut_nGnBssV!e9!KUzq32}zqR~u;`P1DBRJat>XU?2qhfVIVoLn58!j~z} zMX8y8RkWe``9i-(N6(CnjZv}tf{oh4$aqF}V`+da9~Sw&_vGaf6{y(ByUwn5RRDJT z)Sc8dd|q0SyzXODLfv|zeU9K8)$P+gH=gTu^1$+;8lwZX6@e zE_T1w*LKXCqZhn52>NvWrKHnmEiU_z{ajLC#^)&|Q}eKJCL~7E$?yA3%qPhyp-$oE z;dwP9Dk9RMcQ9$+fdiMWSO~qy`phT>YvvbBB>9qOUSs9@lvU;|V3bN-U7g>&%vTeM zEux~LZVlh@1vhw`pP_U2ReZd6#4sil!iDxzkH_z2Q+K!e@#Dw8fNGjw*~DatT8K4| zba{?ob7@q4YiH+~!N%{=jMR6lG#B_WF?Yhzi2r)0;^VX0&k{rSD;*hl!}=2~4UZl_ z=75;&7UzYye2Zlj#e9hC?9iykCKl_2I*+&EvA>Y@IJu06JbLG+=pW34RlD!wGv5qU zvdOXcXy`4clmF`lIDZ&FJ>Ci|Xxrl&j^bySdr$g;z*Ko=1Hj7vQ+0I+7<`3?DYo!u zeF0&9-Ycn$W&?lr85I>j&5~US;Sn)O|ly?+p#1DI$5~~^Tg~TLVW1{6WY|z>VNzQ zy{xUx6c$OhZn+LxgzJLz^r!d=X6j3WO+$hQ^J$CN7)o=*Hi0R}!YAs&Pkh2+bWDnF z?q#yEQOwjY4!Y5id#|OnH8?j{;5aS2?=P^GZqDxk5%wH7pbCNbkp}mx)f8X4kgzZ% zlq42&MtWm<3(qcbo%oU#vj0`|z}+BIFN62)FW!@98J(8dJ$8+XW_^@QE zsd?dgK$BnfzV5q>8MJ((tC6Oy=~`Ej*5{_!JeTgZB_x}_NW0z7Vd>%`@p6$>#_iSz z*9pXc+PICmqbtREZfs}Sgp|A(G0yaigM)x85SL`+&D@Qv4{_8(aBgUqezlZ6t)I2Y z^n5G3Gh!jUazdXF?FAKS^3CDWcf_#NublC!qisv6>V*v?0_g}Ax4Sh2|k*RRUBVm;aP?V0wF{eN<} zPCSgFUjLf-{(bECLG?h7_8l0;0HkFK?1}b{1tBP*YPM9~~d_h{1?>rqd%XK%tCJ#>hK8K>2IUZ^nNkEXkiZ^Eo5ECINi(thXHP0IB2biaKb zBk=y5R##UBvL&e>_Q%+^aHo}MyV6HSy{M$n4X9vY!R5KJYut9 zBe@s#Yc+rkElC0lVt#(U1GrLz!M-Q_??2$({R3>Os;Qww{%5<~*3xqM@R1{18Vg&| zszJGChl3bnA?oawgA)KP^|P zlAm6)u;};NTxHt;A%(K}$BoV#59ANYU%a?y-dk5o%i@maKI~$)^3c}O8dc8C6Teli z^HX0&Z!gNikr6AHoE%kvQAFF$s7I9o@=8iue-8|dc4!+K1_G}# zt650GKL<=m_ehB(vO5{|hkTNypb9^x5W^bvrJv3QH)eAK z=%+45!-59$3?+`^5v)TWW$HLsQsnFBXExT7HfP^0vz5{u+$B?7&SH!Ro zlubm1M>MypMerm{{K3p#Kn(I;&sE-U^%~{qWhcrrf|p2??AT%Z>KsIE&U;U_hrYku zdFRd@5)*Bec=xT)D@`R7M4hDzDq(#Uxy1kJ)2E%wU*qKB-Vh_a@m#NavDL|73csM! z(7DVj1r#MEB_z;ZWyo3qZk80@h$MYr_CBM}9F5JA6Sda;da?Z>9uh0}B4DyMfwDX| zg*W&$N>t5$O#rY@_stDP0)v%vOZ9pzvOo{Pf%CKNdXoT(W&i&D#PU5jhw>~NSV>V- zW?Wocpk^M4KCWY6_x1PxVUxZ7RXbPkr);&AqWNRH!y@MMm0TX1LI-8s_7P#ts{yYE zWgSUmR$Z-H=+eYT(+U!ttzHDF+5EaD~79QS|cM0IUQA?mTNDsl?2D3HJEU(tT zH>unL!zifUJ*0oIC9rdGeg6B<%b@<&K%jW@IG)K?N=ozJpB~}4CF18o`QrG!K|}xf zkA{N$d<|V)ta>Kw73_x(Z>^8uWsV;(-}zV59)N*y_wL=#g)DY7|M;peXh)O-E+%E`&OWxdR06k7UYcDMyo zCs2x%H+;R$kJVLfS-UJTU>RpVZO=Qq_h`~@;QpeqQYmmbwzTwQ0Gk{um^JR8gOUp2 zf2i1x3=SVpowUaS98Ggc`J@0H4Gr(fNjrDMjpyR_tOx}J6PQ$9&H|}K1!WL?NvO6# zUW^jlw;7Nj`3%+*vNnqO6opIXNBwW5QClbKar!h>xtNyRrId5TWL+YvV_}33C9R`2 zP3r@jxTXg-Y~}ra%>U-wjRydCPhGuw*vMmEt6;ETKZ?#dx(9Uk!FffypU>vX&dzSp zFyf2snqZ(EVb;X-fKH7N8=q`Ji(9uuoJ-?HQ@+;LnpTHV`;jRqC_Dq`8_vOA9{A-$ z44EG@;~29G3I@OLE%FPyVeWVf+mto6v>t%{8$jl8qx_4g`0(LF`D@pX?Ag1Q_o91| z7)*;eafb{)pTV4c0VNxoaql9o1Gjo-30aFMb%{59`t)gm^cbGt(~XE9#oyl#1WC=c zt(Dr`xb$4l#|sbf;p4|20kUtxD?nTU(OgMKn^9w(^+mdK;aPHeoOP%Yh@+4GwB%JW zkZkg1W*m6a)RSZ*-!D+N>VuLa7Nv`B$w%T{ucE#2nZL{>AaW5%wO zHdxm>*=1JfJJK30sjYoYBrEM^e{!Ueg0=N=*`+>m%u1sNx`zP^V*)u6=2EBSz8z#peL zX*5vA34UbaK>+*ZfxH1*n}8&rDR@vomTxYSSYX7xZ)~Dq$JQ-?jssxg6fu3Ft&MEi zsWQw!kGd%97-f{i)nn8VPy-7nL*WeU?8FmJN zwo#}_#^fN~Ots47bL+iX>s<<~c7suI32y{a<5ZQEK@)F5d~NJ3;1h^+@dg4Gz%-FxYDV%y0x#pG(X zANw9Dwd^dXcarulDlBYVz`icZ_(wGO9PyT?card>|Ni~+&dK5L-X|PpRQ7t{Vl2vU zW>hRhXocMwZdHO>JwM|V{=?vNKJqqL`u>roBnhxS`2__{Xu1aDH-KMx`1Gl&h6Wux zImC}iE4%dJYAik{1bw$Sw93#fz5IW}l=b;?tNx2}KgrKvB{S3z^XdS`nAvu-^akn_ zceC?sFJX5@Iqzz=O3?rrh`D5V8#_EOWMFmUhOb_h zin{tYlKsPl`*w$!vhI&teL!BtZ!!p9qh?}e*3{SEi6Ie1dVwn|ZjeAw+aMo24%N}2 zFfXKIV0eh+O!(Y!c=5Rj$>!q4i+>#hgb7b2_<)$07!4gAO8omDKPrq}f7ZWLSX6}O zCo+6BIgK{)vokS0{_sJ*On8lI#|~ucZRje3VnMfmzr`IPEIeNQh=prc_idMrlarUs zh8}w1`Unc~&zR^%NaH+L^0#VfY55Ed4iEc>h3&h6IZ9vh$^F{<^tS!}7A-yi;fDxp zWL9BQtZpOhNscxwz0`hrf~_I>C`1WVK^S%LspdO0m`8&qnc83-CpWR&NLuYun_b!>cDGXz>8T97s-7PZb zYA5^q??oE9ZD$s@`vhwaC68h0KJ=_ytEaMB;4yL=$MeL`EeF3{UfFnl zayaiQk8mrWB5x|6!I%fP#}|h6@hqaI%=w=H_uOsqrmJUGQKVVcVr-faqmA&T^-9g& zZ$kn71~v9socdXNFRE4Be{k6R?MQnmzvk1YzA9R|PoQD~AXBpte14DntooBbAhOs9 zkO3;Cx%7w1h%lx3fP&YSEnBcp3JFOiFb*#rT*z)#RvOsy*js~f!;rlpGJh3%CBhX+ zuU12&===v`o^g^OOTAQ4V%_0a*O2UP5X)>6_!6-7)5`pK9*9Z;eRkwqJn3}RE&KL% z$TI64QJk&JT_>v%46_sx~XLi$omt_Al=O#Wuy^XL%%3ateo zB?O~%Mc9fp@f>jhToA<&FixF1HTSpT%^Ujg@Nf}1G!{ZiD|0ws?Qjry4AlJ#GA?sn z0n3eT4*D64bw5I!H#OS)+Ke_WQNcmO-14+0X$CFdMC%C=HK1dXyt`O4*ikkM9gIVw zWiqJ(8Jp>vl$v@JR|Jm;+WKvPU_nb7?fc(GR3uAP!WRDa2UnU1_+hzFvL9P%6N~DW zb(!E!W=L}J?eH9_0C0dZ+f7eTfrplu$U%xy7s-m0Fh?nv7#~j>92}f0z{b|70_oMo zsnmAx%gQ%y@Bo!KRP7S)Yfe@Z`OQiqq&@;*rOpk7sU8pK0G+Z>kn?`!vF9+Bh2E1F zFgca>AR{K?S$Oz^mr{3rmyT!qJbg+_eB%QL{4tzU(_V6R_&+(x0VklmP>-Lx6cjEw zgfZ@8#}eW^Ksdz=GG_9f>+WsdFg;(A86K;)o~fI+#h-@dBYFe;khTkEo_JG&M~xtK2n*7;x)-S4+#)h>O(@1AqUXJMbAq%5BMN@~En9 z6BH9x2K<;Th3dz=F6 zXM4N2yeS5*2&}-KdXO;qVKM`S*Is&hzu&+AvwwBF^UN_+gacLj-v{!4)6=Ka z)pz~s?q&}^J3q9gv$M0K{BCjV9iwcUxyt8)<`l5^UuY-xT}ZgiajzR44>yBp0X433 zE_(^@=gXZG8Bd=-XFxgLPpGwt%1=mE3mmA4gQKI>7H#Qy^?bo)p-FqM_qD(`XtYC> z+WX1?x$9v-z$b9<{5N{uxqhiOQdG_u$qvjH__>Vw;Pq@F5DGdC=zgTAlgGO*5Cw~74okX@hq zK^7P7ws>V_&028yO75#1>WGT}ClHp}RDfC|ylp5Q$OLj}N7`Pp7utw-_cEQdEZWDn zC~%}~@`@44g~`%!KDYNawG60u`UeISU+&Ppd|Bh=cBjVHsz#L~bzi?8oGZqtL;{8r zRG{1{R!i|? zf&;z;XsHPei^Y(};%RFm>+!1TwAZiWSB_x5+qH(HfH;adsC_e!cUk!VG16ZW! zqs8s330ehi01)~K@$vEv+~0NGoazcdSn%i-QlT>!xPIjCUnRU5(l-jT+qcE=hszpx ztDiBxIXX>28Dr64m`_wme_BP!jo#(E@g~wP0z?^>guZJxFp0t z0emd)=5~_sET9&|yh2WBxZn~UoSX`ZTa&c#UV2Is1R@C!Hx-cR`negC7Qu^$Mil^z@jBhmDlG z2F>SnMutyl=yHuV>R~ptk=}!zPXqWR;XD==d$ir6KBE7E*UDb3D0qS>uB4(871nj} zT(~VbAM!CDw1q+hCxRj29w%#5vOI`96T~KWK76q~^NJ7NY|NWW=g-p^7#PeYT1S~p z{wfifxpw}1kn+6DWw@==?#r8)#2aS&Mz)teDPTIQ?{od?>_YQvh{jx z%D{`Yll7@T4jth{B&-j?c=s^b_q^gkGyZc?8~O-7!^fa^@k8x}pzy}pwNO|8Hm~9+ zWy<7g-H99%SPY*_IvqjC@VBp6r>B+v=dG;iOHKUHro<3a*xGYFR&TFO*n3ssS`l`D zb1#Ipp^Ask=<+>lNK-J8a2`>QdNq75M9>Xe&xm8BrM3UR$p5cn;J0e4RfZ(>z++Xx z8xIZ`eE_+C6PVcL5{Nf|Ah&Vz5BcgkS3Iki z38?jim_S&6F@Xt7#jD7W6{H z0l$l?sCA`o|NVgZ?>=#!E8AIFS*@(B2t!mr+wKD;e)scEqHsE3S2iI=6pC=E0fe1G zOd$%Af+_RNwUj!`TBoEZk{*pH1W`!V;I2!{4KZ$(j~s1hT#2H-#cW@Z!&3=aP6>S}6f@rC+ieSvU zm;cLOe&GNcu-_b(jlO(s;jmNIJz8vjGZ&5~ zZ zo*CukVa$Bq*_vb3!YxqQcc*xgGH^fPTR3X;dOJX4O;_kPZ!HZ} zfvA_ny3NqQKma%pFKg709|bF3DcmKx$=gv`+2vq`l+h9l;bFE4J1Mie1szT|5)!(A=VVa6SlHxIVExqjazAAy zr2y+~I(TZ}sX@3@qJbY!QzZQyP|Mi(IA#d+V{GAGi>nk>v5-d;pmd|SJQP_^kXFH` z`=+Mk%xJw4Rr^poh)cru0P3r)0&{e@ucwn0GUxu_#1v@ zd&{wJ2kb9om^%yOC1Q_ELmjmr@6E9FdZLtTRRpc>$m+~HGFl!G+oMJz$@SilkX(L# zZs5-!U-$+%czCFN=}?rJq4CQLKguY#6@8-sx@~Vr9 z^YjM~2Eflp*2vutNWm^4(eX$4^+o5ztaT}pciCMI>0jT3T^OkIbkFVgH8V3Ci4Egy zY`Mv>LyOXP3%~CYUti25AWUVTcn{Di%`dm{td3IW6EB5Tm6S}DX9f@X9y)oFiD-$b z4q|x%ImRvJ02|wd#qy$dlsH7H!^B8BRA8_~5nl;a{m9D`)DdxfSp7$}bEmK?t$99( zPg9^yxQS7YRbo@YL-hLvL`X_WF{7SDK1`|G^r=l;U4Fd(MBnJ>cEmq|UVjTQuWx*u z_^wH#MGk2NOG_?5?z)Bx2@B+x7Uxl_lsb?1jg9TVTa{iJNpgXMkGih8A}eq=8yi8< zSijPM`U+%@2i%WDXAAL0Mr3Y{{w=2-&6z4O z>AgWE`EHnD;fcRLC3+C3*fD}oL07jUcS44Ba*2`U__23eV|DxP$_(H7FAoGxZRELG zx-8Ebwmp09<0YO-&;YTw1C{-80`gw9w1f?V%zK$gw0TPBAtK{wj7$_G8gsC-S0=g* z|MaKE-UhM&W^tNmFIm#5u)UWCB$nc!4u!@K}7Y zy0(zR<`lQhX|>K|Iod5Q+M1x2n(xdG_FOa=<0T_qUHyLVX{h*cp@C#mDJAJt{4B#^ z7xjTKKcqi&oFtu1C;Fvg$)n&1J|rxR{<=K?LRAsG`h5cfKA_5)M72@BOicY8$9Lt? z%_YIlj3TWPLJ=atBm8U6r4KOi$Qc68kmD_eqE@>LNdpHDix~t!5Ul}`SI@WG^xP#F zZUqHw+TM?WT)UZ=tTpH-hQW~%XDUsx60OblI2qtu3Tx-|-q`mBMH+kJ8+`Rf+X8Wf zj>futH0dTq-MoRQ2@nLh^BGAyJ@tuD*h$RPI(7E!4)As~82{((O(Ha6pyVUtU;f9d z$pjcV`F_<7We8lzoH&ZGDL?J;^iI3o_*r9FJ-p%9aEjORw+SCaaB%08_z2%?-`>q# z>0#k5=Aq2FLk1}{9fuy7wO zovp3TpCVqEvSFUD!8?~=roW{nCGZA#e2R?|_KU09#xgRZSy`{{y^ZmGO!ITSNHX$v zzLYlWlo^pb>$MiPRu2<0H+N+X;-d<9ZMeGy{T>>kfK*7_^_KpiE4+k?Tw&tdmO*${R}zpx%w0c|-H-m{{?rm(#e@D4hsqxxj(6Pd8yeLk%XdoM`e z!;>W}%_J2S$+r%cqxu>?hkgjtT=3=1FOnd6-@m^FZgBEOp2vSb>&Ihm20&wic1Hi$ z*xCJ76OT|T#;2rEkOTm~%QR_P&!o3+pR>NgYKf<(EqRmnD^LNw?NWJ(Bam8mzs=xI=N4?SBDlm4Af)IH9I!Nh z#6Z0(DBr8Ixf$+c5tW0;IP|WxEHrw06~3>W#Yu<6tWOviyp^oVyF*}e@L|+T(m;?X zamZzj-@8jf^`1uW6ZLBO!58mk1&^n1P?4ypbtyExM^AI5NWfqU@rZchxYd$jNwGUy znVUFs?nOH>98s#Uv$;t<0}>%AA;I*+FwD8EP1O?y4Bsq@!}`+;fH?sM2v-CyRLqao zV$VlEjeDK0YwGt;9-1m?3YhFM2b!@|^&HC2a}&1y<4om5Q#szmPg^gOS!uhO4odv&ge-Y%Y`B;5%7 z>3cfTVehf8mNug=4{31r2=7(<7%TAd0|orbM6c0@VU+hvs21(XA7!(o)XCodt4o-w z39H7gR|T}$&McB=y?#}A$$=mCo^cGk!lrK)qAwc6FXvCc};h7Ga7U( znTlE;cJy7A8kk>AluRx`r+wCYKIS0lU8eRnT>3MEY1)5f69i+s+%D|nAb&yg^Yp1Z z4Z;8|1JzfuBjtXHZ4Ih}O|a?LFKYR{zGv?ARDTU-BybG$CUin(DPy=Rb;f@T0u#zF zz8L^fV=Rw`mew|O0aaJ4$TX}aZG$xeFqdx2;f#?)P6}=q>Fxq$Ebc3 zIfCUe*cx;>-~wlxlpX{-H0!{+415SxfELs`{Jvd!B7VDZO#eqS07)|HfoZ0Mq}15h zxZAd`D-IeLRJ){{99n$0hmRha&Yq?45j4ZPJfG~y(2$Tu_=A%`SFe8{I-0&kiE39I zFt-Bd-}I${jEwAW`BkFV15r${Zx&2Mr+k!6y%k?sGPTZ2wA1VaA1+jX+Nb}yl9G}< z#A1AC6q(>sj&Qn43MIM5_|=7UK$Xjk;<8n zlY3{j5w(d=HfNwR+pT>nPMsx=S>sN87G9;Ik5e3~Vw-wZhs3QOp z3iGZ~`>hj4j-tu{O%j@r4dn;COubF}>uAfGW9X7=0=o7?6>7 znZj!znaF90(4UZ!;&=SI|APmCrQaeUOuGN8r1bGjed!Q%Eugi*Avh%DKEdeV84_YF z)Xix$uo_-sEbK^JOA)v%2c6VqV|jQQSlb-sNsGClNgPfW_!THf0o=~x*m?X@W6!E``}6#~yxlNaBgr4~jmHmID!HkQ(M7h2)C~xw&+Rmv}aX1T_W~7@v9{Jw5ST&?bPwQE4RE#o9HzZnZ`mePTkw zJr%{)&-L{?@%t?TZB73}p1@cM@&uL__`q#>>3u3qbU)#J1wn@MXq+MlD_8-D9u1r% zVw4A9CDB@?zit$e&`(7(b&yPrqwwU8q>{gA&N@kSlKz8)(2qR%>8ad?RqH!O&b^r2 z8Nev)cbu%Xy`2-Dpf}z6|nx|FP#=+bQmSK|h6inhb7d8;qZ18nvB)XZ$xjbYLPX(Y`V|%vlZ~q>vDQ zK2o)GcQUf>nKRo1&u=9WDO`mH1rfncL)`*rhT3h88lu}aNXEEnA2==x1#pC))zsBJ z9mfXb01z(mr}MCn>8`&PS)WXF&q81hbYNj-w%Om631%BC0P(Q1v+XYbq|@EoWkW4| zBgjr^--~nA0o;t#epQEpPmd^FeRTrV^YQVC3G6RnoVLh6g2g<aa>AowFcM{5fLG(P!ydg z`Q8-0rLGoz0N)Vmw)5xD6C@@cnWpA$cn?)GH6wB5j=*UL!>mGr25~uYtRM;Sq=y7z z?D4Bu@70PjaKI2fL6^!VvP?K|foH=ZKIDr)^0Z?Zo3aD~1aJOU!aPY@@NYQWgxQat z-{@;k&20+ytvKY~*K$H9*wH^2iURmmN{SgcG~DZ=A_;0Kc4_H@&d$!LL-E-ZU0mK8 zN>rE!*b!o9}~7pHj!ckA%s!wk-AWBvVPC~=ikRf!%`d_?>u z^n%*k)0Y^x&6EJj*`HA&z!9>u=H<&u&bsJ%4u1ap%R)9|Rh>g-eTUxD%03nFO1m~* zIgi=y!XqNWxt|{e$U5A`Al=mY1yYymHEMyxxtW>#1QBWqA5)ow-wIsuz7bqbQJn&( ziIMkOVtQMbY&ElwjIj?}?tE8Xo`+V&=w!Ame9+u)?wkziZ1|uAT`2Z!K8Su)NLNPNsv`Ws^7>cd7^Dx6(5HL)v_|1##i_7+1aMRb7?l`&QP6FR3yh>TDpS= zzXl-8grJ@za!r2z9$z{L1xN-Q($c@$60i8e|3n-H7>(kQi2!g3%f>9LHF;q${bw^l z3@)T_pMsMDt9x-CgVM=u;5Y6M$b@f%R`cCEvF|^+YkAeD9KgP)3;CG&A zWD)`H5Ksvn4RstQ7+1c%Igsf_yOCo)cUp$h+~6)m(VO+W#nda^8Z|c|Ice(rs)1-TvDtla$3#c%>U^&T z?pA#J!m9=o8vHCoC(zx?z+oug#MCT*BCaAILGWb}QLw-cJCxG+3)INk`Z}UB33b!$ z+Y)tzog5(vHhv9cohu$$^$zY!6*S$}qWv+~B-$))WLYxbiZ<-?wmcr>cQ%ExscG6-i0 z>dF&TVlWy|%NTFiS2K58FF%_#7hp(=whKS_bG}Tfcca=U>pCNh zyAXID_BP*$J@oV{vdfJd znY*~m0xthD6sd0Sb{yJgEz-=j`Ykvhdgl`po2koMT1}GjaKyI`s}UsL{Jb)Hq0vqZ z9yi01vbvAvZWM!CFn3Xp2DWIKzakKF`I1D)#q&sQOYYys%h2!b9g@qnb%$5<>qo0U z{bSgCDjB*TuKpY;np`rw;Nt44smSs`;a+p|MP{{Er)(HXP40;K(xAs9lJ!w$S9emkNg-_R7m*p+a1^qqt{4QVf6<^kLN!L9a_GW zelkJhj4jVDpxC*MlYG;z3RK%Tg=e;#I{du*uCvgV=Wu0F>UPr<<{#( z?wHhQUdTE5BgS&OtHKi1JO4q}o{DTI{nar)E-#!2hpT$4V`L;*#g29|5jTXfYdPr5 z@QdB|ctL^$&8tU7uVwrfeF6Rv<9kd^ z*>NQkG`KU5kXOmRe*L;pIG&LDgyXO3o{KN8?kg?O*>;^)YJkP|Va@^>$@jeU(%S;7 z>VQ628lf1%|(vcR+j~%loPQuE$Dt*fn;2Rs=T~+ zU~(QS;#12PZ1&W**mHP~Th&0j)lIJQb0tBQCe(p@u8@}p-QF%Tqt>-&|Nd>rBP6UW z*?D-+qd=}^22JZ-gD8T|twjm$5xjQpioX66xG8Zk1qbM>UxR^V01&wKHzO-c`O1|S zfywy?5$&&Dy{eH!NTRS?3HxhlD`2N6jtu%xE78vgL*NtS+Ldx-5`t$%QO=HG51yW$ zVqt9?V79i!yAF@2Y(Z=a@_(WxQa%|T-f^DJPqFdGsy>^e^P_wTHbZ~Ppg;ez^X5sSxkV|b+1&?n(dezQVKB(eZi_ReG z?AH%>?9V?z@}`P(pmM27@?%&Vmo8J~Qr2g?v%%n2P`omQzfOURJh3a!WJQ<%qDb zzCX30XnIivO)homU_a4t49lalGgA#MYDoZiHwu1gzY-z=oq<3WZ1F)DWSrYAckqvwrA|I;YSK~QicCeE`qCli>}iCo~_o2Z$82BFGf zE08U^Nq5N$n=)kAKFosLlgKOyOPFHNj%xB}V+oJGX!F{i3QaVB%^}1Ppn1+N^~mGr z&yLC`>c0(47Nmv;7=5W}{-4l;E2BuQPbAp*_(LS7s^}mZF;=PLQ14Md5IqNG=H{aY z$^eFt$0Q{sUuR`m1j{id-N)xcMEtRgL6Fs`?p6P)#A$GU^4-3-Zz5~DlrOXvIe<7M z%xYpnXtR5E`Y@8I66i5vM3qh?PBT0MHLuQu3II5QW0d-}(x5kT(x%Z(o;cx;aD(~2 zo0CX}-L8jxU4<-lDcH~6avmll#XMlA+u_6WU2U8j>js;gb2xvG2dm_Cm45Hg*h5hz zI6897_hOdh>a_C(;c1)d(-yFPwUEuBgCz5fW%N+6QclCI!7E%uDqxt{x3DisKdUoC z&FO;Bv`zh^+ZU4CxeQCHZnF__LF87=*XQin35Y`@^QX68gJc*8Wks{|B`gsr7J(IP zjzi?3BqnAc7@)_H@PXj0yERE;L<=#O1NRBi90e?>@O`{XaTN0NJ9k9U$SBsxOHEzf zd8AyUx`>^(&c`V3*m!=z;Q$+TQ+3+XL8kJ&Lhd`vYE=R%hK4Mqr6LWfkS&!G6O>8f z6z~V$dk!!#H)KUUNt_JQ2k2Se)ftmc(?ZlVj{I=(e%ZHsyUu&`&oS0OMK!Os3VVWbsjl93>YhQ_mu(*s zl>)aQyy8a`a2{(Rs}B3A7y_%~wR5!&E`UAom#BmvhNT{kq2%3Ni^QYBFLAQh4LTw~ z{7}E-cO6QahMwMI6hVovU!QKM5=73#@=vhZgnoEA_7!(bYFu zFH;kiiV!gToUO(r&gHE83-Ag4Wk%FeQn5}{NxytNW1=(YCXM1-CvH;Tt>G)Dwa&4> zAY77l{Xt1{Zt3l>Ov^3=sGf{jj_ML=I!K4o)_PH0*-*pa_Kk|3Nj1K|q9- z1J@%llmR;B-*YwJ(O3Tg(-f{Z(gGGC#5NX~QJ8ZFY`>-A;w_AidgkaWnHzl4dJ-|4 zT^(|wJ@tMe0s-uywXbO^h=Kmo1ODr=xUzG4UJg>{4N~)?-6yCrBQ6%>0I&9HVO!}mDIApht{3ik0EWtq{!SCLEit_;$;}G*; zAjN-u9nt>}f{qE%bsYrB^f6ImCNsV8Cqbt@cI;S-l{x|o+T>jWMHR3e2(6mLXc7>X zz?>sR6^OZnfDPgr^MbB_ND!(L0bw;4Wt$?*5EPixApOsUX?SZ$M7PG?l0YCW5h~62 zlEGQy&EHiG!){MzF*kWmZ_%V(bNj+K3exK{Y-4)wbMr)~{RSF4^#k5yJCR5i+W!w% z?*WeW|GtfD(~zQML?SC8I~gT}jBLq>Y_iFwQnFgejtC)SWfMXYl5{88$=*BbIqyEd z-~WF+&vD$}MK=Sch{ zlHOCFS<8CHh7%B?73A4upPflU!rLNvw2k{|tt$_8CEc@fv+X25k0^a?cX;z2$tR?m zV`Sw}mUoPJG|M!NeZOavoY66GmdEuU`B%jM{HaT9L-|vIxe}kU;DZVXL=S=a3=gLw z%3krckdl+9Dw}T$HInuA7DsjEfQ>pRL&wiCnErTy{t`9yg_l=JzQmdTyy<&0#3qkz zWjo2=@STQnH&lmZchtF5h-ha!d==;ZcBJj%()9Zq1!}sw3d8i+p-uSE>5pAEg5T_{ zt&^3RkNq-|4c||a81$3m$Gs1kZ<=ZUR|{~1S5^RU*OMl}AS1|`$ul*^kt2Tm&>^AS zvGUSmz-55U-qVj&;Uc5z7>yMCz;;tRmU3SGp}vPi&VHXvOvB9a=em?wLj>@%eHqmQ zP4};YBR|kDy1Uo72UzGJn4s2_+WW~woY zVo0?xhIWf9+7u8X2xeks;%BDE!_IyI8>>T4s~C=JiQPuCiZm^N64!pjsIqk{|8`pL)5%fq-m0{vh&tWIf$w^;NszhU z?v>SVvo>BV@yz!cr@dS5F;pjI%4R+u?;Ex5+g7#Jv(Epr%A>z`-nzQVN-=poY{5<~ zBCtk^bXHfe@N-dRFMU(ej}_g%?wt0F3|b|ne_r-0df(j+X=o1NicU;;l~NOTFMj=c z_-JrS@aZ)#?2W#``w>f+R(=vH>+$Pt7F4m#X6w;r`SRFMiNE9p<-eHcQi$})wxR=; zYw_9RSfcVaH`jsH#H-ZuEyeH^yUy|Q+NU?On$QldJ*7w?k%*Tj`^cieByBjZ_|hLbPwkGG8D3yG7tV|Q zt$Z2e+f?+iAbG=X$voxO=Bt_Y3Ie--F#}%~UzNk$84^YI_2!R;i3uks@HenFaNA_) zFfi-v>@>=E+dPc__KnV{4U?#1T|C5Iq&YA*)IS4+k0sTk5Zw8K001vt8sWvBy53oVa@OM^8_x1}Du{6`U(+ zLmii=^oesq@Lu6gx!&v2)~QGk2u0ZC&XFZ`cq&z$P-AR6O_#!7b*1oo_b`2%q*dW@ zwP@e%ew`Cc^y{~KSFMqWkF|!UCEUv9lgYJbUdZp=if>UKAY2tZcbjs+n?BXIiIine zg`v^=!XHCN0-NCdifxSBf41^iTU%SiEEyQKC+VzoUS0E6x;#ucy!9l8m9p$U#X#`i ztcB@3^{zdAr+avEM`EgGrbi2Rt|;`e-EkEeSw384<}Y%eLMkqGevNJGJ!!1(xf$)5 zYrWzt$AarZ_)DKYg@L1d4%|A$+-CfoMGq8Q3M{hg71~X;KpEC3&3o)OD0nPnG&C|b zy^lo7Z*H2U6>P%S`1h|UmWQ3ik`{VK#^p(Ot14B^2<*WpCnxt?a-YG$iQYXW6~`8Q zt>1jh>%3gr_>A?|$%|R5KAtQ|w>Q35$>)bzByf0{_B0I?E54hQ0W||bSlL#W%suh!tC^6XH&{7VsDY40Ql1*60)Z-w9m`9FZ(9{Hisq#XsAEJ6QZ|`_#(OWjZ zV-#6o{(0rf6|YHa!$Ewru!G>v`D;bXz#!Dq`uNeK(sEj+4>EkQzx->rwvm+f{N`Pf zY_~B;SZ0{Djmg@-=dv%gz8wh#`NmpQbIYGCy|UYgf)4sa#0maTu&WFu4DSL{_BN=K49}p*qMQcEiq2WsH;?+dcX>H`Zit z5a7p{msbNtQ=~R)b}3J@NAdZg-8ZIRwdAbN-(=x;S@iO(_-N<-tFlt$7Av#ZX^&P^ zbfGbyu=*K}aw$H(GO8gLkB7<*>IyshQvWerufwa=$KJQ9`^=|F*X4y37Y83W1i%G* zq!fO&=lC~d7pUDgg2rK{OG80GT_)O|c6mseVoB}3##s|?NrCG{ffA`vwd4*HLi`L;gOY_0C{l$3% zO{I1~;pJ|#cSA!DJZt(*fW+~Z*{mN- zi#gXKBNXZ^DzPNC%%gQvlzffF>h$HT%6q8<4sC|PMK7{2d4uHv1cpcVer!qSclvNM z(68+Cza+WQVwj`Dl~+`>r{Mg6Ybui=^}VU{CZBp!Ql7sSd}Q%%ZokJ=(urkJsq!qn zRi^8+hO(Dssy{S8t-9ZEwtdnx@XDX%HMF@v=CRkaI)Qo$-Zx&G{` z)}68!r%Gh^F?|?z)A9Ml)39|=LqjoY@P`#FYs@^3(8|T7X>iJv{9@Se z1QLgTE0jf=!*6LHTeRX=8=*Fr3iGo1hplWmh7R%gV6-wN!gf6qT?1o0pN8jQs(e*5 z0$P;5z7ymPWxZmpq7T?#YreB)`?h#=tF*W}>dgDs&AyK^k4i0+*<^m+I<|J4`2tNY z`ONKlpY3Ul--jY9&X;v7XLevoRH7yAqDO`GvO2yQ9j@I4(;a2*hT5DFA(obKMl~;` z4QevY@5Cx$bgz&+6zU$Zpq^noeq1$&FzZplcUD7>28))72cF}4mR9c`4qQZ7!OKz? z!*RIVwuM9euqu&-gp+(84Shl*P`&9OdIh(3Ezrj#X z$ev7@XW<(Y2N{P~J$uDcQ{LsAm0YH-^%`8d5UG92AVn*4cA}HtS--)AFSoorr1^Wi z$2B};&WNN=8@0?1m<>iOFRSAS_b3R(V(s}Ct3q7FC)v#23In!mhD0gMZuEq?Lu5+EK$a{<5=>ma8waF%)(JEhk&)>(?2)dVRReT zNCNZ89Q}T4p1iI}FnfbwTOyle(`peZxsE0qo3_I= zKA}oB`C_52sf7h;aNSqLLF?bdBYfqdnyR9k*z#*FVas=F7P_HQ{asOtP!*DKl*C?in1*pRr`Oupvcf=k$*S8{n4h2EBoNiM0RYgBG)I# zr?rD4UG{i18`b^Gv1PVm?h>uXJ!$^Njjzo0lga*B)lPa9s11tBb^8b^n~Xl^=Ud?y zc6BAa@9})t9mdh0F<#$!eY$wB5A7MTpeNiu_a=*fAga!Es#jc#$={7Sy8ciVwD$7^)LoUPyRb#a(P|ZC%#j|KeEk8LPA4I&h(E_S3+?Nvwp| zH@LR!9MkGwYlLha;#4e~d?zF0!g*4ibPW^|^b8CzafNR@?1?LH8FzZyP=_hXxxIQKI5?_`Eg!GBwm>|ba#pxnWiQ-mrc7I;N{rM z=x+9wo%Mw#dE1>(-8f0^H-m!bX^M97%KtEUXl-8f;x{Tczurc%#8km;I`)r7liRXwe1vEZV1ai`s>_+rWRrV7wK&y$_~37oxJ&`xM_5+D zdEj5>pCZxcj1UnOP3o{Z%gcKrb~$O9BM9qeUg~jU9TidrR3qy?zP%`#JSvdj1`)X% zZ{+Iy<&?X|PSvuL4elQf6#FLoej}>D1ruB9`9wt6rVwaUwRF*YfcAMs3zqhm8kk!y#>dKj~YWrCB`6?D3s-29gF|MrK z5<(MX>GH^_s-eD(M>YG_jvH!kKJVWWtKFQsFCaY)EaRJ%;HM$Jj0~dJuk^|3!s#Og zyI1m-8B{o1*)vYHBO` zsWN(H%_MfxGDJB)vP$T0FW-2{vVozeon7mX<^9m~D=Aehd$eBRi~fy1T_ASS;|NTM zFu{#?jZ;5;m1()nJNypaSp^iYpIS~=w)Eiii&nGNQ7&=lI+j^XV zVf*9*G9-U}1J&s#6e(_}LuK!2aPBHF{86E|z+|98jOZX(lMHf_+4o}GAi*)Cv9B-j zY)qM2I=nA>#&xs5kYDb88=#ZPpxPeut$?-n^yJLt`h5-!RC9&x^DkC& zb`G)%t?&qX92~pe+bG#D+}_L7X`_x?z8P1GVsjy`|Z3n-h_cfPXjiTctwH z8V~0Y4&mVjZVLLgb^&A$_zid;f8|`FC;Q|K>Uc|C?H;EdEs2ETk&%bZ%}VHsG1h2) zH!NPh1Y9LtGp^X@1)vXm^ytwSfl#YLIHgCGt315oq`Abi#vx5M85nNRdO1qTHly%> zbH#mP!LsEqHQQC7d+tKRs~@UV!HTcTjh*#nH1}y(U;jP76*L&O6{ffp``YUKhy`C~ zpuf)pxfOh|(=e5_q#Yk0MG!h6JfJjd1%b_r)=@LxuRK5iHSJ{86L8o z+hN2#wkXS6nsZoJ0n+OSWwy`ML>RmH4S6&w0UkFQNPGru$1T>9u+AMhfAJ7+10)?C>%uNM@nsX?$|cCI<~SBm7L6sIDziTUL<>{@6{rjJhRF09>{c@i=7mX~f)qKe{{=|xld2mA=I^v=NpOF6AfPXD;KXxt; ze`U(Z7F_L~U|Vnh>>X43cQxUJfAQC&`pN5|Gs01CZ?k>7O%v11+Pg7z8>yB3-#q+} zh(;RUziGY-6$TCc_A^6pN%&eN`5pjDqgj5GA}i6iX3J!j`jR1!MAnu$DC4vi*8Gc=Z z(6l(mVDlJ3dw5_yFpsR5cDQZS8G3Iyw-~IlIf) z<#c>{s<_2kvd*}T=lG#O>-xdXC;cCLKUj$;EZo=Fi_e^gT zB2i?#jh$F8-r||3yu()wZq^(MZaB&$v7=4;$dEQ-X&s>HGk8$thst-!t%JcYjEiDcW*@Jw ze~8?n(@fwg=-~l^49rC%QhC$$dE{GxVk=vkdZs*weXv)EC)x& z?eB@k7l7srnvHX32I}@Dc6&?jP5T>0JYH16bsvYj^xM-?Q?p$f5|nRe>2U|7T4GfU zj759OPKV2!%^#s1+Oy}++0(4bx-wR}^J34r{Hv37Eu#u-d1~!5p)2oaHBV3GRMW81 z{QPTPaaQ=G;c(hL!)kK}7f*TWPyc+rLq~56IhLG0ScR4_>ft#7fo~DyvgjWLVwLF0 z1H??0w}mzOW8j-M6aWj#D}4fvD$K=jer$`bi#i5Xrm*jQdG%w|u{YzQI8k@*Y>QJi zFN$1NhGiclIU1a%icfC|#p<7rntIbeGxG!p3IaE3PjkHOEG=Mq>gwvBo0|c=w5GTR z7wf^E4NdTkU)H1!G})gvO{q zqr1u-lzzuJJFbi1q7x9f+b5*6-|+qPW?x0xKu~6r2_N2(e2NdYE?aY6#hmBxC$ttBJslMp&oKyH*0b?>pg;UQ-{}IXB@1&APSB!j& zRwM^@Eblc-DM};kv|;{5v(8lh{Di5XN_xb`x{BzYy{vl8C+;me)I?lok9vJ=E^@Bo zJ_VuciFXhq>87TS$;fb^sF_=@d5>0R9m@8QQGd8oi>uNBMsr_Z$vtGjAKT2u&Ap^y z|I#p8krm%NX4qzD9pG3G-aes>RU7<`kR zO`EeLwwXw4U~j0tK{SQkQHHm3mu~N-+1JV5A@KFSS?i>kn+>N@R#5^6cl%6Y1ml{T zpW#ZIkwld1O`*mf7oM(PzgQxhwn6^xk;>t5Ic@3^!37puzu3HcV_8*~Y=hYyMu89l z;6Qtp;^-4#fJ@sZ8o&LsnUjk1`>}WM!f`C2$6T0k?#J)nj{<5Di_AF=yd=M$u`egU z*RT60Syv&Yap?XdSr;$)mM}+9*jbC*VtQ8iR{VS7#7OA9jk@q1p6dO3f|#kqI5`Z1 zlQMV7FddC!{-LC8N4cPcv;=63DYjV+Ubqc|k(*CwNOz)4*^MCz z=b^-;{EJ*K%Qo>HVI_i*jZMhLhWDe#kK0`0^|%|bEb%|L@P%6=iVx9w;$!9N>{n`c z`@6t_L+9N^!FgK9n!37dcyf(=ifQ;oE5JWMSm$vDurd< z>$E?*chSGtPOiPJ@&dDHm~n&gQeQ!6ze~$tL8x9|Mx7>H4YA_mY*0CW^nS1z!+cM_ z`UmECRDIB{Fid*&{92~%TSG~fu1~7pJ<=Z3Wa!#=&=;Rp789gyi8&s&IojJzRdCf+ ztE^axNxCZcw2+vY@XdFJ{>0~p{P@embwhK)i+81#_&=)aG~^l9EaN<{U+<#*xn@Xt zq&cKy>isW!!`TqIUsQ7qdzu9Oam)2f?W1pXw zgo;E0V5~inO{R*k7tk{3ZLC=f(AwD898>!Kazhk3@yUi#o3P?uFPEMs?cs`WD^BY@ znoD6Wc_~MSJZ_I4SF+%8TT(qcpG5mI$)M`bXV=WT4Mt{M7B_vqHOgJcKC=NoUfRM~ z*RqXYR^8ZS41}V-^PQQaw29?4mT}7`DV4c>QMwhxtiX4n0aVonF(Py=a15U0rd~BTMDSme*9NcIgvPfkZMSp|B{>ogA=q zFP>6~KM)6m0ySW0=$5mn5*%&Z+@e4mbgol-Te`Y}%&6Jil!!?sB3H00{Og+03BVLU zu$cQCmf1msVG&c08L9g_j|wU=$2LDxPD98Qh~-f^k>525IdVs|KH zpa0bY=*e%rjS}A}#&~GP>)T|Cp1XC4;9N6hh7uhk*Ve~~xF~xX1~$eWla0z&O|qvL zlb#(kD%3?eK-5M1RK;~X+&Anjiroh-(IUT@3Yepb(-h90seL_FTFSRr$a5KVy9T4cp z7E2wTM>P$FT(ySiRW04#-u^}$+wOZ8ckkJ=X0^2ly#xBFK^o*VB4Gs3q_mumsVBa{ z=uh&wgN)5CMVomyt*wJ~-jE5b20NYk^XJv*!;yoF9`X2@gUdy>-D90j_w7X#IU~0J zq&(J8Ute0D)Wgc8;P9Yn2zy%r+AVtMr#6EZ=ovi_27Ll|_NyYecEbL`ePxEJG&{ef zB(Q6;etgl@(^9IOg`S);R2JtIxs^fE=W}=2ZHE#){p(@4j+urVL%hp-Hz9YHDdA|5v-322C#6`?19l5X&XPiq~5G%cC_41M=v6~vAS~JUU zoSi+3zllEt;BwHKOtJ4_mGM zP-M-ziD8ny+<*s*5oias(9==p#a+_fxpJf~r>deYUfCI|@1I;dvo z8U0+dI`PkGC-j3E1Mkmo<%|Lf&V7+RHo9J)Y>W8$_-f!v*On+4t%xfc+GkW@zy?uz za2@R7RyKT++thM)8{*r6dd}QR1&Arm%rjA5rWRGWh>nbqT2!^-D{*m`kt(kM12I@J zg{3LjRFa{I#?o{LEIrSD@Q&-~zBY?+3jv7V@is9<`33#C zCLTV>znh{%uo9<=GgO65G?8mc*TA+C;-u34-8_?Pdoc1?cQPYGjq51S;>MKookvvf z4G#EJC17dbQ$<#6^1|pb4m^l0koVw?4xpGwDb`zvXbDeNeliE;+eoQTcGwS|Fv7TC z&;`2C-Dodxl-?E;EGX{@jSr-cCo702&rLf=PqfQZj4OXYB?FyAUR9M!W(QKi(k;?! zq)Y}W{I{q_Mr)fhFQi@#GDywHXk%BPy-xJs3gac};fpfX7ubl0$ia=q-mf%%`C3UTP$XxW()Y6aLi3e!;@~YdA zlP3^QoHAxEh)+)3ISw@WN>1t2bA=Rbp_nx;NL_ZGsxaU&$f1sHb|nL;^)MKvq{YN= zRI}Oh$jCB}gYj}KKYslZ$Zm2ii?6GbfjMdEJ64D1jV33L?LWMKcbiMMMP9f<3OEvy z`fKWZ(I3!i&98>=e>8BP{%pc0hMv_T2G9^nTbva6cz=pvIf4r@3VJ{4?7U|Aj`eSS zPtOa7`jPon%*>z>x-qC_}h-c$%srM&xl;`D)riWox5g7I>dLz9tbN9I76`Pr6yV zy+q?3&CLVsMLq*&Qk*C=h6OTCotW1Og$k<>bgqUc#lS5N;va6+lJFjZ*b4gIyG?J;80Lvb4Lav zq_Z4;Dz4#R3t0v(6%#}kQ2Sra(sG~a+XgMmRJ!cNG`4uiX#auV6|+vr{tgmtWK(kd zmzn%my#6siHal6*_csdf>gc!8si2Hma1#?hFLQ;IsYg?c!Q9i6&cbjF$-i`|{Ea2; z`Sa&de+}NOzVYOGk*)lX)Bx{yjcO%&tcWa)CL!KYEx*y2HsSrj7?#KbiEq=?1SY}C z@R*L#sYLHrsmqlm{`+`emU#FLm!r-0YJxg**BB6EoCJLXy!J9Z) zfMjl1S%E(ogtnXFnfMKVSvIjmWklltMg;*+z>P*%G}!P!%G8nwgog=$-mo z4<;cf397Me1(&8vv-yRDh&(YJ;A*7EP)k}oI|Mnff9qeJSCxwh%Jy^4q?O71+gNeQ zkcCRQ_v89u(U53-Djp+e1dARJCqB_?iOdepvemfao?cJw0eI5@JbJLFG)j(P*6e78;VVF;0Nu$W*|iO5Eqo zv|A_;_3MnEdP&$RM&WGOt;e-0pQAf=%x!elkd)~|lXAc}h{=fH!jlbFcu*I0h5k!G zgN`LEZ@B%7kD{>(%@>eSEp{0{T7Bc~X=}U_AT^&!yE%fuu@H~1{JJQ8RX$`?6EIhJsYM-3emh(qUC+mfvO}&|`H;o|LH+OW82==a-v)#-JHjv!LL^#@aGe zSrrxH$@yUv6;QmPn7O8}e+u&exE>25hfq$BMxQVZ=$&quURKW`5Iah!3}SD^D_fz@ zefg3JcJqJ#7%7zZEG!5hI^%1ruHN=k?zdWxFY+sn*oboW_}`TKPUmGFD5t3lJ<8!l z!HhqQL<@4?;-vp4%zkk1?x)oRnE)~rFo1C2FaZyOOUT6F)Qj!KxbLbUU zWD^|jiRIL%PkYh#1L>ldLOBvC(fhxs*3Ns?FUk@QSKI_;3c1?*wzjAACS*+6{_Vr` ze5M-%8k`aQYXx(5XFQ%NCY5`U2i!w(51j^zn0o(Dimdm*2$n^0{!9EJ^$fVe@Hh$` z{cs*{3BeQrO2^;&W5R=P_!0Rc;63|~LN=nfc5YxfR#`?P0Q@K~CtwEgP6SrFx`ngWd)zsXb zIHSKUZFwhc=!3SMLMT5iX=mnMTu39E=!8n$9rSJL)X`Boou)&w5*JICZd>D0h9RGgiA3l2h`XGSc!()fVVF>21wsZ^6 zLs24um}@CH&OGla^DgX~B*qgVAz9Wi9G9ofW_Mhx|KMC8p7F)c?R~481#T2XXLnFjGy27gsim(yfv~1GHLW96d#-S*az1`K(K4p3WHH~j5@CC7 zV=m^1-6;yvK4;N%txRH}%+JqEHzxJ4lHe}1=hcZn+mF-JAFFy16*V%T;O|zU{P1hP zz1+P-ZoKLJ2M(MS5b#g6M0tvXJL>$C{W%gE3a)`!5%hr;yNP9TrG^(%P?G)pA0-s2 zC>BRbTkz2_*oW!TW$vHnkN2UbsSj_|7Eeep2x}kxFuq7j$!f}(O(9i&ZCLCL|Ft}) z?#XWt%aw;?JU#MWDJ~t6diYNIh2(F{SXJ5{F$8e37wm?mQexiQkUJ^TKD_%jtQ=SK;^b(~{8pXAu zF~%J(EkDWBqnxHiegicq_Iq;Yj0EqyF9j%8K#4i5kpj}LidQebd1{U%jpLYf+8kAC zN1ZMb-(t&y*kXVk%1AZ{JZw~Z&!Y9fPej^;rip0#z>#s3cvcY8|A&%Cu0{!9tf)UG z19{?|`&NYtVhqD8D?dgQ+oP2&i@HFshCF(t5Sb!@*@6#f8339AH{y#f4-ZgEXf>xw z{WHIMg(GiN@#W6wulC*e5NIB*h{l_t#lzCSj0}W!Coiwh*ubDo{tZ$pV6e~+LEnO# zgky+;8nZq{kxTcF1j~FKU5LI^qfDqr<6`tHAnta6mV-BB9QkEs!5JB-rOtghEVWR9 z#6kRs)L>P@hz*7MbDyz~r?VfoD<5F2S_b@&6@0pn| zQRRXX5Ee+E#i-eS(VuyRVxo11es0I$(+`2{M$pL&R zkMZ`jN|3+C&Dw(fm^Q*K<0gZPpNHtHv>_ zvsWFHQPt7Y`whZKfc5~wBqVtHqui_?y3kdF2%VYfzl2&0(UI6b!ewOsqJqV3)qMfA zQ0d?|khTzB@f=ID>5g~AE3=_&=&_U|T@UE_!Sz z&i2YYqe$^vs;Gs^1RHJeN0|M!xQ@c~QUx+YQ0yrEN-H#&3^*uA(YSs<-ItMZ_;JHF z4{o_@nH?cDeYo&q({W}(vBUeWiw!B_oe=8u|E#a zL$7ViL+lFVVTP`ixlL{`Y2R0?!Vu5XvCXXQV=}Fx6;(`O?4GfN@w)LvzH{d+#h6cp z$={R;%pONTKm!6N(PBMr9FXc8S2w$Y2oRM0s_=|N226e;#PAp*A?VI7Yjza9@W2}b z7;?DpkkrE>$WWodB~?Jm!^}=bhR@Wnk5J;&q6cdG$hTHZ{>2`s7tV=^?UaZo{T@o2 z3+#{xY0mTH5Sj)ClH$(pyEH8B>){cjmTt0>^L(pi+Kz~S6CrXU^g`Ps@Em}n#98`N zk_SY`$49J@GI7g`#{c>Kd#A;o65C(JZ2&B1S2Z*R#{!8o^4g{z#*EasBP|Pckwns0 z-FD$_M&hFl64Dx?_c2N5jQp~QRb(aes3P(*$n)@Ml|nZxEF5~t5Zlc9R@*3~l_1iT9`GiOsr zOLr!qPlZ?w`41vPq)q&wWKSXN-!$^|O~5HeC9HaZWBKiXW>OnFavE|y~aihFj z*ARQ4hn4C}(4ih4zTz+~mLRRa-FV{A51ir*iY%IDUkSwRRUG`ibu3j%#Q) zAnFuCr(moS@)Le+eFOe^Bm_shGX|MXDkvIc{=W`ZoIz6)tw2AXetu_25<8H}!TICl zd+^8khBO{t`DRr}1WJ5h7{+71JBbHeFpYcqg%kFtYN`M;VOJE%;$<4 zKGdp^lL-Srt)n)@JAg%l_dD%L4e{xJfLNPAD6yDWpScw6$L67xcHNmxF1p#w9sBEh zcX7P*&N%|GRW=#j0b&ex8=0i~OG1a4w2zkjo| zSrl|NQ4OFkehfG8nU&d_2vYdLsP>3or_HlL1HMHu7F%UP~&pFoEpQnU6VrODduKozt5?Xwnf6pcGj9q^@XHTdx)jM z(O{Vu+oV;-seS-jE6EvECu*5hZWZd{lpv>*IT5S`5fYKAGdmPcQ1G&<$r(*8wp$2< zj6MUu>m}ivnz*D1>`)@%Am+*;l{LsInr>kLjKmjLS+B);{w-;k8NFewsv$O`W z)BtHk?&6)1YuX%goo%CUM8(CGP>|uCDRCjA0GvT>_#fc@)OJHK%pkG=0Eapki3tGZsgI{T9svfu z8xDBZgpbVL=%RwACY0!C5>QxL2M3Dos*JY`vn$&J85_t`z==dW;KUGo4o#B^-FT4F z&dLohJcb;Nin_|mV=~zo9=F>F-C3f#X}QVbfp(K9zKH(mBcsE0 z6jF&}w6s#~0)y_SF^NJ*`8TeIMORQ<&a7?x8w`08=WcircrVBps=dfFKz}jm5}I%` zR|kqeFmTLzomPbw0<@_9KKi_-koxlC#&=8mZZZYTHVtkpDcK0o0T+#Ia$yzWz)=}M za3&V;aq^uuLcm6O3cpJeToC&@ySoKb50~k2+xAw5HVu^)xID~+#D`ZvK)S*Jo50H* z$6PS71C62xJvrR5z{gEp@-MzoqSx|z+*O4Be*ko^N}{B~S|GOh7nZGmigN)>0!|J1 z0EUgw7+nOk526Rm3-eVhSwUf-ze)FyM}gqN%r5XC+sIzsX1#)H10OvmwPJQ2-14aNi|BvY zdR?>>Y1=6Pc?j9eGXOnwbaiV+oeh4{q6GmcZ9YaM6ry8e!)U2z4gNvA#A-d6hPm+PdKi@GVT7)G zWdo5nqH7PDe8e4ReYVJ^MwXdY;v-9GJ!)~Kzkni%8tC)jMd8DNA3uC>y1^G+?7b$m zJl&htY2)bS6+##{H8FYBb%k=E(BQ}`J$?NlvC??@7&+)TLM561# zzXae6(jbDI@4W({64Jogjo&Wq+!)D# zhETS8%AI-~dpVNW_u?A^dxs(k!6okyXAj6eR!}{U8$#D^McZ=vkFdpagr8vg6#PVy zHMG$O`j^8}hs7rsHUoix{rta00d)P1${&^61pvyAI@8Li9y@l7msP{SOf}c-d>UKg zk>I+by$jAYV)5dxa6)+h{=Ic8WwRM1tNc(x;v?aVlhn69^5?iup^Zf%qLkrYu@^)O za-#ohT5Cr0rg{7+D*6%XP-UOdaH)SF zs92>X>Yo?F?%_Yf))3Ky4}sMA_wNrY*MJF5OiksXRR=(gST4tM@*)pYOLa@jquHM! zvdMhME-#crRrIgC-;Qm?+}Ws^@jMp)e4q1&pRn#xvXY$H?OjTKP!^}kDAH=%azuxhg^M2oDI zc|UvnU*%@L{awO=eL7j_*P5cY$Q+J)E&bHxI%?Rpb4mbIc-JJzWJ4w#r2o{pM0L4@ z5FekhKyUf}nAF_-{7YO%`6d1=dR&8Y<$>Tp1s)Bg9xdPA#y0;E7IK&pqigy6`AO3d z&=4Ra%v|lA`vA2QdAv~Bp=&A+Z)-r)Eh@VGr>6k=jelT!>bNM8H>SP+K#J*K!=tIc zKdn8mwx2h~EI8l9{A&4EQ{@t3GX{tWhrpt$O^a zrJ{H5bgo@1c``jT>jwP}bi5^cl~0ng!A>~84!?VImK((S@>KWW{{w-b<{&n1clWhX z>TyS&eVPXptI>og=t6I0K6MHw5wr(DHtuC?KQO;?%ceJGq)MZApUdlA(!I1@);T|p zsNP=O>7uIQWRS_t$>}Ps9~Vn`B$tq<)Jyh+WKm&JN#WBUy_wb$7DZ;83*9R+6wj+4 zSTd_c^EU{~Mt7TdPRv8m4k`xd#{MBM=>vSPFMeuoSO1t7a)WoJ-C7`M=jwB3 zxO?KuIaVeUo7YSVvCX?H3?zSdC>||LKS%;n*yGj-W|ae~n3Wb~P&^CeCKwzrm)RTN z>P5yFbn-h9IE=SmZ&>a&cWt*D%<>`1%e*K<&1)cCvul z**}s5%(mfmUuxT|TU^B-K!Ru_aQbktL0s+auQ(*5`eoGl1nG9sc=DfH$)czWNl7DZ$|k2Gf&+7KJ~JctW2*)y#@WyL6wCRZxy>oj;!MaA2YyH*>V&-C=i<-pYoFHA_k1tlP65K`3Zi-8VS9Axw9%NY6q;JUO zD8ZIzo0w}QdiAh13WX*Fx(1myCL{Qa`_wXy|5#dDg6tA92IxVr4c-kvGZHH_I_oCO zD$Oe_ya(_d%ri)q>8hWxK;^LC-PGh4ddTlAC&L;~(1wzG%KKByC3#dlvMt)@7gJNd z$7Sy+k{Bs@*%vJGZ;}O+j`v<#T!?pQss}TRX0!a&iC%;+4Dnrx^+UwzU-YP+7qhjq>)hFn0W%%02Ux#% zv;f0i&Ww}0;+64c_uV~lfx^GCL1nVUYo}n`>RVpA;woyuQ8$XZI&&7hS(BxxWRU!i zMrqWBS>5zYv!~ya-}(9OvoVL~FS`6G_+Fro!F|5Qe>h$_0IQ4+R#YW4L(K0`ot?6O z_YO4hc)yZ12TbyCjuBWiGCL}l*SsWTqrnRx z4Ng6vtiU(tnSW>DSKd|epFh9GE$HZ9o`Qum!2C#-hq=&6QTmEcIF|e<_<_2d=@SE0 z5{t^;haAFqi?2a&GpucFGG&|OWxaWm*lClb#|=^Lz`_C*y6IYjqfD)QvCTFohXi(V z+}V6&iLV6}2m0kBK`1N1r(sJC-UeX6vFA(Mz&y=Pb_ufw-EC^RQrtZy>`T7%fW1R` z#7-&xXHxs<-%19iDyba8&0Dt)yu3;ZErOD$Qi>WVE|ls}Eou16Jy6K(Ft)WN$DXGr zEMy&4i)pb=?>EMCkQv)qkCQiil(^lIkU2l^MDl)U=oE`QipiQM+OqYH6BAtAJUmQ6 zCs7oE#}}2oo;K$k-g)Q#sSdwZC(50S`xZk!Ex!9HfclpyTJdB; z>!s&Im4RS&b|W~U|6+J-&Y8yjF>l>OF0aFCV{Rw1^1gf3Bozh+ajq&1S{WeP9B~%K zalvnd%C;9#^T;3G7tRs1U6rcydQq2Y)jQp+%V~+OqQ?Qs;YG6Cst!7~l0Y5+g|L!; zxmH^H#VoCxMvbz`v&Iz1SIj+fXr+*n-gZq=diI7>NTs5e{($f2d@mXZq|CdWHk(g! z@MBt9Tc0)!{a6D+hdRz8=IrXJ2!&mUryUuuQPL*0jl@ok1FPlY;<|x}WAtbG^O?2c z-#jv*ga_&YoyJQ_DTdctnXtv!VQ)xTfOU7jj~tpS_mX%FS0j?;>c42no?1TJeBlw> z45Y%Uyyxa$SNq2I62_knF!}GtrO_f8vKNuCX*Z{Jpbr3M>b16X0AB?HJ0|RdvKl|C z-wT)YS-+6h9vyTdg*Y8xX-S4XH)5@*Zt~^tjyZoSD?5)T1jR+|;Ou_)x-iu7xq;z# zPr&n%97AY!e+5HinMEFfN~74>uOumKzZI7b!Os-WtIIES0u^`1Hb3Aotn?dpN9#m- zmqe8cya9GBqaECy)_!in^cly?-KQ{o4V)#Ja*qZ8JV9;`hTthHB6I;%5Xyyt=xsk1To| zjdLl{W8R`?O;(BjiA;IzYMyRZ-qkIqZ-W_i#-sa`4@;3oi#=oMhbt}m$conKW!&t^ z+Lp@@pAaKo)?MhA1ZeB9aW}xro9`MxZ#bDqu!yZ5D~xW1%HQn;Ql(6;j!CEvt}R|D z=+VFeut~>GKk;kN9ejLRvLg`;5ZwdHIi+4;uG`+jE(;`kMOs$G)c!Ik19H#&KQ*j-O^W5cdcn@1wlD?N5{Je z%;`TqfChZypw2kb%MtX-~PoB_IHFn)yQkox!sO>3 z8=*a8LhHH}>esQLB-YnQ>RU|`g72@M9;xT1cy!nRyW_tKLH)X$T+d^!Cfpr}ZEfy8 z^YEU1QhmdZMIM3fz4!2kl$4a*y(&vF@$vW32?543xmG_pc?K~KYq;J<%GN`4WgIW9 zo=$b2os5ZD=~g%i366rX)V^f&;JFW!(BG*$-HQ$pj**u4(X^wmH8tH8D!T)~9;iL> zoNtX0W6pa8uZ}Kyu)RC<`d_7GQ)-f;=APRaD@xYfZ~yjczsR)wxU(qYIbPo%7F=b2 zJAY6{^+(SR`z<{+Hfzy%WuRG6&3~Tm{}q_@(6y|YRW9RkhyBY^6+ZSygXq=q($UFV zo@JlRM+Kvk^*uq#{22>Ts)(~Q>@^*(TbQVe#U$g4sN>Zr5Asngx@9Oor#G?UnQ7g4 z+0*!J&`0kSa#Jxgs2<_|J ztS5#YN!_TC0a@6g%02=2DsZ zvEYND{hQjH!M8`Rs&7!B5}VND!HnuvcFe&cR2y+_pZV>L%!~TTu_Qz--CrSP&g9TD zbZfQ!eoaF)sOE9Ga3df}fZ7O)P2Lt21;DT^_l(?}n;2GQ)dMy``N|n_H;G*b)>2Df zKOO_f3$)BgQYA~v+Bmp|jA>A1@-X>TWK>yo_C^u4T3gmIOPkiAMvJSpnh4Q%PavlL zo?oq;>PB9{3s)E4qfN$8@$QUoffgNBNAQb!?~7!Uj2ch;XokSC{S!(#gsRSp{nwu34oa&^7j?;$b(>WoOD^e9 z_-hBS+}X5zW|m*V!-YPr!N(37R%0`>-MADaQ&kE0sba0kIL;*hhpRV%rm~N|fKeow zGKCPjW|f45GGxv?r4l716bczLWR`GglrfQ+R4QXhNJ0q7%qwFhLnVCsssI1~ed}B6 zF6&)y<=*=|zvrBN_TJ~5t0Wz`?C`>OLs^WcyR+>o#WN<+Wg4MP2U4k)Ta_2(Gx$tr zy;jWnr%9pA7Y&Ws0M8J_N&@ykNkM*NQXHJ~P>?@((4OIG(24*pT24IPAEps*mIh5k zWB{ipzYqO)@i|OVTAA+2?T+d)+`x(&xn^q8cQ&^EpqLB9WGrGlJ`yobL8bNA9-9^5 zF>GF0+K23-h;48h}n>Vw~W@d?W~m6$mRNfogLB3U&o>%^;Lu8#qBvLt`WImtstLZBT1H#4*IU!8TcR_8jQ4Mm)+WEc;17=Y zE{*m;O1tB0_)AgjK-oYqDIzW^yhCXXFoA_tHmO*%-tBaharqqvFAY++p&u{JRmzHr z3Q6r_#oeVC#QITH7nVG*s60G8Dr6F97j1GVo~}>R0(&4myO4FoZxDXe_@nBy0&&y3 z#xj}5`(V*17{1!KxrVxx}W|!drpofUM;nnCx=AAeW3M`dL*~ z7)rq4w+%(gT4DUOl9C4+)nz=n@8TD@G0iPM>zoLaY<6+V;8tVTNLW3Fz~`a$gn1b* z86ddYrKv6(S#JHo^-{^^nH7=_3z}XsbO72e&0k(WA4e_J;_#!h|HzR1^)T^Uw{GDn zLo$ahwWXdw?U-vn>W*3!l=P>wX@aN;sD--DW1D`&X^EAEJSe!`OjA{TQO_fu&`zZ0fYi*5F_nzO2D2Nw6 zDOe2v^pk@({sQ!;hOm>1ndu4NCF#g3DxRsa!K2;xX|wb%q!(D8`ijx#WsU8KbFIV2QPA)0VHVbmkA^Lqq{FmdHoM7z9ym| za%YPJD_o-Ayp_PX1UK1nFG)AiCfMK6C#Ji!a$I(jxm#VERX5D}#p>fJsgi7Zr}%j+ z!~Ti2(mfnC2T}|$u#5}8fLS9!)&f{L^M~KOWN|lcc#uKPRd@|yBKLjItfpyFYPr$P zX2vkZY|sD}x43h3LR{ObsIwn8Xbi-FTp0XHyhNkn>~>MZvOq)TjrgW`0ZM^S0V(p# zswgAHRGI#l68*1(Z%#=qgrO61qLcay%>y~tsa-}U%j}&&=Yc}rW+W#g{M!!5$YjQ{`Uzvp&x$;6}|T#0W=aUKdS+`l)61fj;miIy9G=P1MIQy*Gc zh5zyNDBLO-i55{QsK%EgN=FdG--PqKq5-oK&R4ZH>AA$E|c^#+9;1vu=lhql$Gs6#%J_97Fr1^w=_M-ckBOTuH4<<5NHX6 zMsw9g!5*Z`$^5cjNj!1Lbcm{ekvVeSzZH>b;f5ocDZ0cV>?HTMd2?p^OH`$_o-2#- zm$^O);~aPc?9U4Oo7;VkiQfQW5rLLU@y~Zn$fVLq22i{xMw`?Q%gP+sx35mvU~TG$ zW^wl@_Eq%^4r+mo0ZD`nHI|#i0L&GYr@Sh_kioh{%%Du$Gf%?1(9>X87k{)MXd&4H zf}z*$0cm?xFa%{ARSSW|z+{=v`wKFiHKcb#f$`H@mTS^NDe=EG>K$rvpVYI7axeOK z_xW`>%Agz}{>WSD>rJ_XmUK}($-OfYC8R4_OC@xi*(L>Ze z>xHtnZPu%I)F7vhF19P)`RkZYdZ09hI#D;c<8tC1m8$>|G4Hv0|EJ|ZMaGB?c!A;q zErl13PrUsd_Ujnnvy&yNZLRtCR*eMejIPy}zEx`@S=|w=e!Dof%piFVrXhJs-^N3P zimcji8PN$n(K|TaL5U{T@>V=eMb^im?4)6C974%}vwZQn)!>0di+tXd_zd(5cdsq_ z@?uX}*9jeRsGW3_nRpmlFd&$#QMQ}oH3R)4qi9Wu=)>{P(L8fV8jIW!GveN96 zSG56ki@-m)#H!4W@sy(KI@WE9!d2zY5(1(Ap>U+UIS0DsMXn49=P~V2z$<78Z5PT> zAfJ*;-WsbJQ6-~hokb(IytIT1Lu?O@C%;%*gUkfL2vm&~mNU=ty>`}AR=x)PfWqbc zx2g{y2=T!n*Z}4!@wFO;i6LDYCmpSNvuI%EBdIRdJYSYp+<)P)aZ>dbTcnsyj`gvmLY$#E|%#DH!m*A z0{8^2T)J(TcF6dWJO%E<%sPBLMv*Mw(e~gCF&_{dLr&reHCi9nDK=dSSGlT~Kio(k zDJi@}`3JT$LA%yb2K5f3-#J7v1avVIr}7^7DX%TE<(6l6O!j!_KJhclFbc{PMMeWA zgNm-71C7+<$7KpMD}XI)vSR@chz}jGUmgbxWLN2RpF`mODd6M4wO=BzNEH;$r36^M30?Y{uO%^Tp>ve@^&#SgkR zpEH!@H|hSM$ll^mX51JNe;LOGQ5=GLg6;z}5+cfi{s#vEiWSA9u7>mB58D-vUL{v8 zYo}sQMvq<7zz_-A)V$(G)mj94n?xyODNLee@=JlW8Axd**SHse_TBefdfDK*aZ@N%l!qhVkEw zFnBF}Bxe}y0DvY0mPcTzucro!gUS)4Kw}ItD(0*ZlL0!X7o%CS^dhh-KxfXA*fq)r&;nw30z7K!=ZW9H;;6I5>X zMmhRk3MnG%P;~97bHG?JMw}7de+y^eP{8lkAxS7EXRan;uA)uN6?@hS6g7&IKDRdFnj~s5&HFE@wpRIx zg8Az!ca@ZMDDOj~^yDwS@Hb9RUO7Dx!8`^?cZibpwp#;N7q@``+R7LaQS~lLScj!z z&qKN60b(AEe^`~irbte@$v?D?W>#xV_LKjWFe(p_4|~X!o+s0Fn{R^}MrjP&-H!Ri zrk`*}!TDHlpdxxy9X5+i-8VjlRp`o%*X5OKvP3KcD84kvCgv$9L`@m!AjL_< z>F3X%r)8T)XGS9b!a4PS!coJN7E%tf1wTg&ibt4}SJ`}BWVlVR=TRGmHEi!o(H_Db5l!VME8k69UgfWG3++DEAO|KK$2Bi}D6NqSQ!o;uTx} zaNcikBuLLoS#h&C|4g4lpq&Tv&GNtC@`)0#? zT{QE%FkPt*i6vzZ;JX@}?cE1F)<+O1Bhhp;wB~>B#Rsx647zEn&$zWs(>l;cbXPS# z0TdPyOBf@7mW(AidXsdY&@P^q`Y8sOfUJs)CMzJ#N&j`#kUx}O8*&EnGfpm!rAr_h zI)W#B&?FRhKC#GHFxu9}=#fP}gFpQf81f`_5`8xl*aOG*{T4I8DkPd6q;jp@|LX;? zxGJPWg!bM=>2KdzrJ8;s&w;AIIaE$L^DmP@GJC;MuiP>{y{G`H0rEIvK7t*}ZamOp zdODicPz7;!S5^_e`nL)1%rz1nT3AS0y#g!a9Qz@39o_H0fa%97BU z;oFnG^SF1A=Q&=O=5Xa{+{iF;bh%3UTK{z!=q0^xc8x84qcx*3yacaDzi+E(&bQv4 zIfGF>Aj~kFR7z1X26|pa|Dm>Sp|Pr#ckhN;mDkk)2#|WG1>s1)41Eb^!8Y}3fuiETD%OfFwK4=nIuo)MH5H{7 z{d`;Yj9rMm|Yq9}Ki`F$luVC+Wc<~*mN zoQ_E)KZgEh7rDAwFPH#2)_4WZAgqi4_TwRbR$Uz~*^GMc=gQZb(&}o1iATlwjFv`^ zmN|bz^}}T6w;@14=f{?J;=b!~fY82l=_+84*Ico|6^!WL@zL_}@j^mw1ASAqhllYD zmOa|tO(wU)Fc;tA0LD2mPqwsg79|cs(&NCNw2&^qia;a;&J##6IDFHdBO6rN?XTj*JKMB?RYt$)&sp4}>tk7J)*hch-xLl~k&%(|)I&%iB%b z^QhNlNS-k|vyJvB0!2J2id`8c*$el*AutXK&{84(AWtIwAk`=>_KP)o8|7&8^73Yw ziK{YiluP(vTT1Wev$F*#hdb65$`QmIpcoKTwW|!%kP|?NfADzA2iOHhu$6}2hR)bY zh8t%YYqPf1U>djI-f#0(ktR6)|C9hE8Q8L||0ss~Z~RxGefM^AcMrz6f}ypug=XSF zaZ%iE{`|6y$BVm>gp79IN;^2<&a(+d^=v&DN3Pjxg99AFcnlzvKa*CrR>{%}G-6#} zbAP*LI*4T*1vv}{f@Cx9B(PlQwT+AS+U%s;4~=XG1_RuxUFFl2;`|$L2b}NT!Smbp zYZq5uL~Ml9lTR^zo*=LQt#O+(MISAfAK!&iACCed%=#a~^aCd;jmF4PdBz0ojZg-2 za&pj$g~yqIOGB@A@`bl_1xP#@Zn#7UF?Ko_!8}13%B&VHp4JL53#^x1D<jXw+bkr+x zZK*QN0#L;zO4in)zO@IJ0)A$^z)|6B+|m0lXEI6i{?=d>ieWcz$-~k$S0{YHNM!W7 zRR26Hq@z~RAKvchKTnK;#qp`OG+X?@rn@-J@Yc4pEtEzYK44bhiH*<-R`xdHt^#>+*elvKfHM%Vt+{=(_WUZfU#$CaI#uaE!rs z?R=>v(#0TZraz;@NsmGOx{L}8P1MG9OwMf4fCLKo0s3C}P2(f_)Ct%Qpi9;bpYkhb z;}Ep-I3~&Azxtc~yEhL34}*|o9m=8zQHowYCKH(KB~_x6_xyv+RXhzZ(eRX>1re+N zLfYH)!(esp!@Z5(%~H)%wX4=ED5WFhiu1asK}^p&&-2i3ggU6UqP#IW6BdxNZ=H3Q z(AFEG!XKo{{kptfr%?!eEmc zKosT&BVHlO?3mBfJmDHio<@~DAOQ>-@oTt6;P z1aRC34$kA&)_hRjxFUb^9Kw97)*k_?a1F`LjK?wn$00T$qJ2{u+@JCY3eN6u2%TL7ThCBD?T)vjTxn*Ojhrrj?Yxv zApHRd4}aiGP5L~EHc!!wKL6wQ274+q+goF?RU+#Z-sPVc#)$E9IRNU$O2Ai6D- z8EP7U7(nlxGYvOg*h7Z^3jAY0dpzV%j-T&o=2FND7uo>l6rwD}oT8P%yu&U5yJz@I ze~UkUT74z1^M9W}4dd5fE^ryyEfY#n29{J+#Uh%3Vn$5_czGHbKKi8%c!(0l3E;`U zJU0!L3uCsw%EhnXiVpL9bNn~DKoEoCx|R>;bPOX^!y{-L{NWZDO_);7uIpjKshoO~ z`{(2^(XLa>)DDgEkOgOiUja1X&I1*LSVhMBn}2@Y^}-;8_j68e^AGg*VI=e`a-4p{ zZ4RbnX+4wp`ETEtK@EoRm++52TT5>2!|g>6GOAlNA6Z&kXBX9l#%CBGPC8!bRZz5D z%Ut}1ZR|e5ghsQ}!G!OK-Kh-LxU5HImjuTS#GO1`BO_LLS@&+oB+7yyxJL>-VQ|9> z!JNpmu~>jp_T(Yu19d@6L)?gMCuyzACyMXjQe+r?DgS6dJ2~;)`&+|~Ko~}8(Q+sI zguC2tXWZmLhdk9LRpB30>v|JFq5&^;5IyX8aIFw<@tc9N*sW_Y-jMOR2@c>;<3`@RsYsNuIU^Hk{9t?5Fs64a< zgb08>+c;?Q6S!(@w5Wz z{BvQF6~m}|v$7{-xMR1iU+Z!T>zmaqwe(*Y^{NO+XP8k{OCqRD-yh-e<(Mx_U}M;Z zFw`}(Zx#c$hwy;0QQ$*~L4~wp9mIMG3B|v8wK(XTjyS|6zPN z(O)y@M@50h6!SRZ?YSWEpkA!AW)ZNX^HkvVDxAFd-0}B2SF$}9SVsy+NDmmP_^XNe z0W!pg4<9xaNBXlJyE(Y}v)JHBzL|KzWZRJyXW_)nD84a>L;tRSt7l%zF4$mE_k#=s z1&!2vBA=fYk0oAG+_7#I{UDR^bAuslUinzgg^g&nC?VKSvd)Ktv?pX8Jdem`a7Ypt z8E)B@P*G3uVufQD;{&vY(yAID-y@jj#r&d$ld>3a0IMw3L~8?nyhU3uD1vX#mrtOW zc~)6z$6AlP0CbtVbXgZx0{DmEV}WSh(GaV-^RH*Jwr60F=P14eFc2XSqawiProh^= z;jcC8n*7YQXh=MHHSw}}u9+J=jYDgmM+zU1?95OLB3_i{HX(@NK0(;`281rS{=_0* z-}Agom}rv}JNSX$S5afoVHN%1*qNmtR6Tzi46WRH`I$7(~sZZ*vWXh{vDsu*Jd z#h5}a3KBmicG%^~`6;F_O3a%LsvG++eMP;GUUiES8AoluySW{O*gj+#Z;~?LSZWzw zRcSNt_SPY%-X;~SV@(lP;Sm&UYR!EL>4 z5#^^PCEsQmn!H&wwgQ-tNmb`cuZc!WNhnLu zlseISMWv!&6W0MY8UV6}(bK_iCyLg$gi!^psJ(X`tUitI>bVVD=fiRP(ThM}H&o-O zjF9GIV`Gob_D)=Uez~T5_y5$+2Nl_m!+ef8-|@u0ehx! zZH5mQZ$*Uyb-*U27!ou32g63Quc12Qh=IRw$Y(9*KMv${oQNwmfkVEm^TeK@r%#_E zH$(WTzY>ngkvLt@yCJ4ce!f$Az?cm#ueafYV2q8gUX(WBqY*vG#{|z+cHYwTE?oAd zXBeFqNsd<~tZ0c%=_soEFLZ1n35>N64VniBz?J9Rzm@AQjUpGg3O$Kbj^N}osGOxO zaPq-~;H{~VPQAQnU_pyg53hP$niK90M;W+3cv_FS8CAW!;^Wg4lEk#%m0jZ{G8Dcg zfS%Oa<{C+mTgBZwIbsg}It%Q|rs4B_WMKT_OHlUR&DK{hI4O589$=5o|3N%A18vmM)Z#ClR~R<&V||NGzyW`BHWpKx@q1uYRCq|L=hi$>xIQ z#}@ey0+^+}QpKrclUo-2Q&j-|q1>Vrs_`s*V4&xxPoe!6AeFWOGV@Hv7eV=<)H!w& zMI8im+?2jO0GKEp@xsT3js&rxeZ|8mlI0nb?cD4vhL(M}A}HXBY6~|Dt4GmT2bBV4 zugcBwZOK>imZ9j;5%vWn{DTbx0S&j7c!E~~w1EDu-vOU9w;h1#j(n!*$bbLQG}%4+ zdZ-e!fe=?C26y<%2bkP%he6q7=W8)E@&F;=BSA+rj188*UI$+df)xxGvLAR=kr~sJ z12qvhaba=V{?7yf5^6Rgalfa#JEbZ!#pmwWU;foZbsnh1k^UK)v&yeM@FxE)!Qtg% z@H=o=W0Fl;3aL|1c*D>Ymwoy<0-=>p{?D!(`X>(pJa7?e&VMNnMTBQo3@xpXBg9g| zS~vh230fbT=4Hli=+mSaG-R8?vx~|PwZCXIl@2-HASZ2g1!V`J7@|EhKL$vX9)w#o zFCP+32tR%2uf05su&Wn*4M2DtD*9>|CW@Zd60oyv6a02o;IRMn)vRuZfRKFK0!x7Y z(KTq3jhhWku@SQ#kteX=U(aG9-K~L_BpR^;*Xz)!gZxSuQSn$BrU^@5)1%o&7uNIq z1X{A0g+M~(CO)A6C2qtTIhbUS)BD^`l#RRZlAUx_>LICMHDDkQt z$~NnettEe(v4zRbn-$*&c{p9N&bi2aoZ*N9&-K#kaElFO92{VClq-@(x#3#&$54bo zqeWdc?Do&=3vVjenCjMCQ99@$1hHLOs#?4wv@*j{h7N)b-i-nwhKo%@Rf_Y^WGlQ! zRyHo2#3hNrb_v?oCuF{$tyJ0`Vye%gBLmMF(a0!RR-?)N*8rZK0NWB^Te@Z zsz?PX*Or%;zmGR>`xGQ_Mu>+IMZhT7CsYMXOB`g7N#*6zlWg&?%v*T;RpWqzTeLIg$CM;Bre&?D-)#uA%>6!wIrxku#oRD zctx_~fzKBwtGGJ`8R+A)oyjd|MnHS=!Q=iix`gM;5`8XAY_}f+nVJei?_0eWNFl48 zYv6h>iGLjFSpNE9q*c*qG;*f%k0+UK+1WMXtjhc_m{DM?4lZ=B^M_X=YjQ5r0S;v} zZM2g-_%v<69K06vy#K=4mAFxl zVl;Np{^E7=mgb9F?$3v4hctJpcyNbUa*H4;d+v>%zwN*^tc0)@p^YQ0wT%021OyBS zFi@HrmiWdW|D%|I8z5K|JU^FVgt9U#&2#<)&`qpgr!U1_gCm;tbrcUU&H_&!@7F7d zT}~Qhy`lWH8)QZ9nLUotpaBVvZ1j&`4X@%+YYfHI5J`D76dVyzICJ6BC02MiEhT|% zOZkQRRd$ZrVWutu9CStCAwX+TU=)--ihxMKt0%XOKqU z+DQkG%5(gIuj_7xek4#Tfc@F+o6W`9Iewao=v900uDaRYtsA~QHJbJ!uB4=dLY28k z<}G#`T`A(5vp>{1>48DGLEvOx?B*Y1puVaKpC)1negaS9!{a~jE7OEu=fP~1-xWfb zt8ea4#<)NR^phWe%s6`hGgCNjXC2f+-PR#~t62cYrD_eNy~Xsmc8xF4zyAEGbp4&x zf1v?wNj(EGf~}^-0YF{bFMNZs{S}^192pn6K4uG@0c>8b#U2W{)pzgSje*Sq&C-wn z0XZPMX%4#1J3$055NLh%ib~c{cqf#CQ-Ogsu2kdLxzROKO$nhCP;Y2$-RF4VT(0iT z%IJ)c1dEw8UJL zfW!@#p7Q{R;9wrSH5e=!jT^aP{TJ9qK*eEjw`ZPk0nC0wg#}+Amb;ZKFCV(1^Ow3k z72IgUK+wo2_m~dKYc^`Z$O@SoR2EUe<65Fs$tG|$3`3Vd-ugGbNzN24sH;#oiEy*t zDZ7>t(La!LTH(zzUvceUn442t?E^OgBdB-?T`=N$dq+aUr!z6g1+GMOhy0M$G0CJD z&Z3r$UxnmR8(`cff0F4sns8B*-JwM?fk#R0Bi`}TH0LF-6s490#hgFIzI*@ajl=2( zjwG|<2MxJmeOmkO=n?kQh&lkFe;^e<_pF_S?u(Uv$UV=WZ@&8S8>NJ>-F%pu0L}0QFHDAZG`F*(f16W(^XVa1=JDZ%%T}UrrT=Pn|2CJ9Fb) zg)gJDSOl}0wP3Tf;#1hia|4W1QCrgx_WbXon~>+g1`*{}Rh7QTW4i(X3;$p9VV>o~ zK743!@4>L!a28j|6oYjcq3=RY{Puo+E9R=NPVeK6{W(9r1ueWi*`3a6pmO;@CnFvm zFI+M&PN`aNK>hbP${?Hkw-W(hkHEeFgE$lru|F+41=OC`dtIDIU$9 zpcELZLU@on{chq1gOBX!F6cDO8!47sd_`x}-rV`CO@_2PW@V=Bg=ZKfrQ4-T`;1h+ zWI$W!93uUa#rHthK&B`oTc%lVOCA{Z++jum*Vho$VEQHmMJxdPl;wMGCPnhVY=<}0 zrT82qLKyP?w~Y+>mEpl~5I-&9`jn-q4S47j5Wve3GhWwycp&1hYz2-Ag;9GpC&D&H zq=Y1zYBT7=5(Td+FycqaxCtM`-ZpFWOB7llqcKpRC+9R~HB9+5X@j;zIzFW@h&(j; z>(?9K=_G5@e1&s_&FaCjT{2-TD*xbDs*HO)))il#)jf@3ItHc}7#%<&5WYSa7ka`G z6AkMG%${%o$DvGujsTzmFOx~|@OIstj+%vKb>r7KSg-^(OnIu~BV4|`4SEWY5Q2Za zz0Z)F8Hq&|#`TU#|1O8%7ws@4$Xl%2pxFko3XMLPyoY3}%BCSVF2_laE@v+AaYL;z zDB=wInQlmo^V}E!UZS)%>$gLxrQ<#~Dm|xolht2FB0G2N*g=dWUy8;cQ?^&Q!4&*A zblWclG0)Ha%@qyzY_#Bo&oYiVYU9VNrKttaGg_}c%`WAy&w-%8MAcJey$`>)DSio< z!uh_Tq&?QZ_}Xl9?ojJI2(7A12s2Ou2NQiA6IhuCO*) z9fSc5Hh-pfPZOHB_>F%U0XJY~Z`c9hIC#J3=5|*HuA_G|1|CZEX@apQ`caR3e9XS(}VMVqN+5H92}uu8&NIUVP4jIftpE9M6{5!^|H5kx8cyWuFZu@b9O2?d32`*}&K*?@ z4(gEk;;>0z>@rXnp}StW8nOG6a3VHgqH2Q)cN22trAr&Ctm8oN&OF#UFOEP$m=1Bm zQ6____{VK3ex!^vMvMHnuj^}HQOc7^i&Y2x(?p}=?SHk$+5BaoLDXI|7s*7Sg&7S@p`PpJRDf*+VQ+y?k)poVf}9Tmw{ju@3k*HQH( zT3^@|c+WTJ?YutPqrRj=XOh>lrIUaBU;W0<%sKzIQ45U)@RLx?JpNXpJXq=}RLCJuGIHdma8}jap!f=_~8`IBHe9D_K(~0#{bBLE+o- zVBi@5W!weV$I@!TSp4(~alkuuy|A?dw%ZHkxyNV-$5{v%6yk0R{3@wSoLWPnz_5iK zj~NU@f;@~&_WEPXvfK>lT==H6Zdb=0Q%{xFx(QT&MgQ7M3DPKGIB|B)cNMpXE=M$C zgKSrDV5V4JcI(O>L36uPL!&l4BL#0ZQh>@jr_!oudN?Ul)ZjeFwY;Uq{9FND3Vi3z zFhsBuAbIPpDT(5Ni&kz z$=Au7o;m$d$@Ysi*?;xv=g#h{XZM@!=2Yf3*mD03)vW=hnsb|vd~A(8?v*jRP-o4}W&AH~z=$6v(`_tv4zr+}(|Y*qhaJS^jcx1Czd{+K3+0yHjd!a8CpPI`P|c*dc8`Fq~q z1W7DZA&e!RdHgFbPXIBLrz82wm1C13u6+E1KZEn!VjcEhE&3dqY2D2_zgwPSw0xUP z7aOlk<`%b483{8(q)qZol(AzJBE6Ivir;dg&#o)q^IT7}v8HP{m(gu`s(ocxYS&BW zRr+H4ZFl$fX_=%CW!DP^vqo zZC#>9Z0Yx(*9>;AbrU}(G+atkJ#LD@*lKIEsw2NX;%TM44Z z-OKCawiyoykv29Fy)Jy8UNlaNMTbBr1xt2${rR>Acg&oE9)Qiv3kQX3^inK+y}ZH^ z1diQAt1P@0gx#ejHOCT=9>;}3<$n7qXXh=)XNUY;Ln|X7Vn{3DRovvG7@S`l9X>Z=^zh`~ZyW@(76xX+}#Z1@KW$_M{u>3lhDGFf* z9q^B^KH_7ohBl!5U;FdR3*}`EzN_Bs7UW?cNstmx`6ezrf+ozt=_K zMGj~G+0o`ad;8Mbe#sYWiVHid<4EGtYxn)b*H0eOC^`}NYft5?{U_K5jRHDabsDow z)6)e!+v1}m%VT~9=HHUKsPN~g7TbDV*_PtDUuUAxjr#J`m;4sWIgy`v!Eb@Z(1U4P z`g3LirUD#>npIaplo!HbXrZ%{MmN=}*t`F}dxI~Dkn>@AW-|zd1}1*LG+=3T_lCS2 zYWt{Rt;ME+eELlZ;($Q3^8Unj$F;zvIVGh>kKS!xU+%0XoqggHWH;os)FUt0$R3++) z=LQVszyBJS$w!_endjB9ISv<{mc3>xFPKHB!_6CFk%{Ifnl`heFn6W#P3!{cmxO5r@kBYXa97>+GSiQmck zUxua0<}j%pRM#zP1)E}oj9;8)oH}Mwv}eS3zwt6VkK~%@3-fKk8_YL<&i!*`{jPe` z&%kL0lR{!p2>753qmtm=f2}9r0HR}Jj(y-1IKgh1H73spLexby+{!TP8q-h%s~DF2 zfpYKPK10)e`q90oukgGy{RFJS zH&40|Py6GgaYZUKnd584dLacfKR3%xZZbbNS&*Bo^1xqNUe$?xo6n&Tqt^^ajpEuW zR<$!Cr~6-jJKARX$Jor_oU%#U*{yN62Z9B>b!+leLUnZn%mle!d#nnL6^u|m+eyh8 zVqjTUy3$RtL*g>Ywc6K4~8adu~ZS6{DSJ(OJSH7ebeFK9>Ptm@T zp)N}{R%$(CYfAJe0}sKDMfu&S9n z!g>R~4u-Zl6KiWm2x?hVn8NtDyu3sAA!)*mCjuW30|GIGkCFo8bio+6_w;D9DkKiY z%71_NA)syLP46Y$47!tfF>U0U9YP=O(rapY(V3p&8=c!P^~IZOu7tNba?75=KO*70 zfiDMduDgnAn7tG}3J|KoUy_}PLXD8SN#xJ3b?~tuMZ?AyruK5J*huuFRYSm`9oXB1 zAt+!p-RH-20EA^^W!s%%NkTjg8PA_{QFvJiJ^-(Vaa-Q04VV-SP0h*ai()`dqV5C8 zZNO4+z#wNmjusQJJAnbAOSd^jb-{MkW6pk1PXI(Q&rf~yn)kk(c)|44eAYM0C``Od zL$rA?&flqMZW>iiC^F%_&uwf$tZE$GSu?XHm0skWAlNy688O1#xEAGaN|1W>F1f{mGKDl&LS-O`uXj} z<|p{|P|KkBfNv026I6nog8Id9IDVH_1yOE(_&^?xY`nmMr3(rQbby5XUdkUoetaq+ zA>e?CcfqIy(Pu!?RePHG@L{BVP~WVVE-Z~%uN`HmBKv9EU+47aWM+ow=l$oyw{z#t zByF9G78)AV_@vmlfg6bu2d$roNV>cR$x@pZe|C*jxrGj_9vV{rVtg{>YW;pS!St0Q zj{+WlaB_Um<(>BXc;y+tty+aOno?5@nSoU62iMuHY}^%fA9&tjOmqRiZ=r+LBxPAT zaSde-wU^*|p}qLrUq3U;BvV0IoAmL3 z7u;2akM>jI#(vd<*LMwU8LXJ~r4&)SF~uUoF-W`h$@FG{1L8IqTYOG-s;he>YgR+= zL}09TCsRcrmDWT}NELheeg3*t?ILZ8^%o1`ZvslE_iP&4K)v|$*%Hsg(8;5m!l5o{ zEbe@VtUAM)*q@BZPDt|YNV$yeztYE# zH-cMy^=d}@r!exUbp5a!VNL;()z?6fj>PIKGjnrQNshBpuWsW=VElD)?sY8BjSdf| ziBy-VQtX2b%i=uTw)~v*sY~3~M~y5k8(BmWd1Hjf^tRH4Ii5Qgj2`mNPBv8exVo5y zgiWuiY3;o4Fzhmu8Bb_oVQlpY?Kd!0Vt9Vtup33B(7dOI$Jj#UZ7bnh&BGW3dE--m zcu^=xC|}X)yxevVg_AV*ar860Y^t$IlYGr97pt4l;Q&)oVXn50L`=L@7JP^|boVML zT{99TrVS$;dU$y`XiWG$JvMJRqO-cL!Owl7MN`DNR`x|;h_2p^sHQtRM@T)z)!gTQ zeQmhZ%yg=KKjqP$XdB7TSL4h+2kRave0Edkdmj0(VxMMyW5HVqz532H^83+uXpk=s zfug+dN6q8MY#JIG&K9Avob-q+j|C-lnhf-_u9g45z7U*j;7Jvq;zT_87 z(6;!zBTfHR#neasDtc0x1M+;_>mwF%qa-fHbgnm=}k>0MvU=j_XGy<;x#-_+zrZ z>t|+ZaLj*y0-hC(G#k;LlM1@WYmz}VOT8m#r%Sk)R2=P&H%Swmcjwh1eoN_3 zpK{pS+ru0vDk>UewR>}TY zqT=GZ6>4U}VwmPTF;R9S6@&3{W6aYAhjGx*qKrm8Gx3&5yHgh(W|G#9pywQ4m;a`G zk(u~Dp7!@oG45XYMptKN+joOt>*BLrA^CZEMppNHAI0vmd(-#ZRbb&lMYUw$jwK6! zE*2s&dhwSU1+#nZhxNebm|f zR)&>Y;t*{UJ4-P0%DglGxH{(&ckKrGxnt@vl^cadI*Y}=Q^&$biw~V2grN(eGlWhD ziU*@?VI((;>#_WHLwl{2?;$cEYtu6u6yK20$hFHTR8=i(JL*wYZs6Rn(Z)T zH4OR$oJ-bxEjM~~06=uz^Pd6l%7N%Ayj6Tf^0duBJ zBGYRs7GhlfYoS#A~nsk-8u)td}SA8DtJ zPhM+2;!0V2ek~@{WuJh^8*}?|HSze-XRA!#G_1URCs%%|FYXs$ZwsCA_@>kSq>NjmICoJ)N4JB$fq@hQg> zOt8iPr3{A6KzN;TeSi_99T^GxK$H)UH6^090Rf_pe3*S$Fm#6Ed$oG7ib~T@F%Sm@ zbPu#iy3VKHxphXIIWlNd;oeew1}m^ObyzaZXDB6ld>v-9>slJ;nGJmzXce6YNfyY@Rzg-$V5&6ydv+K{m zpSPwYjD-!Vm>yo#&CV#$k&3ar?n!Q3`7|MBC;FTVKj*6U}?-6UO-w=$Wp z8KOTXHGY8Rh}+gZ$$WJ;9;7vUoH~Gl@D;Lls7}pbO?I^PBlHbm;&v1n&P_BWUwp14 zV!?-9Mvjh-K^Pc?4P|g4y&9G}apQ4rZj?o=kPe&yKp$`wq5PQP%LJ8@PxHGx50N(| zC54zrPGSjuc?tvCPp{~DaUl1MjM(B4#hxC-x8r)aFB}L;<%$;Hjo=O!&9X}<{4l*( z@X8NC@%V;L5xttAm42_P;{)Lqf5Q(0W1-OcmbG|l&DOoouExlp_NC{=S(#*7VwInZ zify?S{o}h(zp8FJiPUh?qUYLp{Fa*X*q7{^hm`4yM^mRHOsdORV(JkL>M^`O|Dr~W zB}_EE=MX4+UBbamv^bpju@68AWwM!tg+mwT8E9^hwvRYc+QwM5hZNjFzB)FNg}-;% z{{%mC`oo8`&;__-9keXY30AN+xI4PIsKY;m%0*7QnC^U@atC zCnqOqUKRn8R>2&bxR_YeDH5r#v%9-&N(R17EwcfEidz7wetwE4o=c!f%EN;Vq4S)% zf1~}ITAc;OHF^r8s3UFx^~#4EjT1xdI5trheF&gjKNu+D^3tCEfVD>Plu1&PV^|d+ z7CyNOe=Q5?sEFQ$2boza{HNH33|C!q3c`!9b$9Oh1dM^0X3L0p3{TqE${&nQ&dzwE zbW(yz=fF6Fg&Od zTz<9P>P_aTxmoV+uqpcGozDd+|Gbr^rHH3fe^xePJGSMrW+0tFMSsJSiBkfn8sfWy zHrH$p^n5=Q5`yFd1_JC1;2%ye5LqVm0Fi=dp^G8~;e|%SmR1ml;^N{)78WAJ0~Sy(Ymt+ninB6m!&U;!|3) z^XJ@AT)k=1!ZhmW2_&pz2YMBG7Thwya~ZxXVC8X!)S9eXfaM zi$Nh=*RS2fZdWXB#qBV`vvcAB95hdk!%*fTcf!JeUO3cl8z#jH&nDftVK2{3F1(wZ zj6X!V2E1%pcTa&urzr2?Lx@B#0i+OIh|Y7`ji}CFI9n8Uth^~5+P;CJQ&get_GN2i zFuTHoZ>?vHmux?EL};vUH1O3jzVB#w?gX+dT6Bo#T$D`>RG8)`T{PP1Q#YBe_c@VC z%+o_ybUJO3l+iP(u|Xvl=38W0&~WQ+}Wo9Wq$K%4pWsaLnvx{j}xt)M-k zC*Y8!;DaVRHHmo*c4_mAM`4u4hqrTyR*MW@1pzLezcJS z#&%?$g=F@%iheG4uwd>Hi*`Jn3Esw3`SQ_5*{+yL{&%OC2U0q%D5^n)0!;mRZ zajK-u$m$5%mhWkk)%YJ z>yF&@kmqqGyN&|mAGr%pg-5Zv*FnrpPfg{+y69J!4Lg1@qqvv}wlZu0y~7wsg73KG zD<4Lf!oE$frS7#Ip9Nd6o(6@2ozc?TWPZ5C7MvuS%wy~3ggqv-K0Na6IvZ23rUR!$ zDDHmGnHLW6Ew5R{&;Wrvj@?7;y}dg7yGUm-s11D~m@`gHJjFcJQ>Q4vsM(+^xbXSjpnRNMFYn~9>USCk2#0R}f=cT%d2t48xISP0C>z+w8R zPo|HkJ260TrhjK!oLE+lQol&EWH<3)(xX7!-aqU!9L8up0v$E(A;@#U4^{Q&&CB(8 zR=!M5z69Jxhd7=g>?Ld)7%*tstEheK7#GYSI65#Ls}tWU>2m{P-Eo~H6&LqbV%boMvAzAcoQ5t^!o34Pl*k7VjUT@*M{x!g3E<3OT%M|x z=)oeqsVHImtnas{mzE}wJk!K zz&0Spf@eW5*U2XjU(fZLUev^|26+pFWsyMU-WD1ki`g`2C7@6NlJI0s(0Au)$XnR8 zXAd}z3!G0w{?`j|3Yi&q93|yj5AV>dEI_z}2M-bu4%T6~?`&*#C@3hPC0CkvfU9oj zTb2$P@5ir)6^TNkJU(Zroaw(Yge05||0%>kg#N+`vc0%Y64E}nUOW+3 zYSte&1gr2r&?WOUfQl;CNxF74fv8G!A9QB-IbdcXJ_yR&+xPBaAStG|tK!W;CoIkM zZperiRw1_(8f0Bl7bHF$PCc&aKAvM!sGJByEH594mpy3jAPyBSC%#l^a|LB)<5?#m!G;zR4V_)Z>qPof7=(c$At}) zrwq4P6d6h6Bi8%jm;hg@@H1QfDD&QN$;amaCJjonowmiTMO-VGXJJlG8fa@%Sv__Z zK@6?XXV^uKiWI$pvl;c7g*%z$0Id!h3p4Wbx1bOM9|N)qdpT54j0%}JF+{g#sM?FDoNy@Ok``&Nwj zIc7CEI~nfYSd(+-&V}C>c%F%*jbsLl1eAxfN@!Q;rpZ3MlZ5qhJVE~^XLR|-Br z?-GotD4bD*i2+H90!eOG0wD7!+!^W;1xBWIVgm)+wrw2&GaP`UrBSQ^R_DymxoujY zt?n!8HbDWZ###7iTT!i&nlY0VK3flXeRhFEAv!f&6m8j}VR|YZinP5=OX3o4owA!K zIDZrlQMpfbC;b#8fn0#sKUgJ*LmoUUSr#c2feI1Ua`<`|LGpA=f}Jn(Ex@cT!W9#{ zLW!1W6?1d;y!`yKN45^TF^n2HyviLDZJitv_z3q|~E0^n;;31L5b*kBhIT#=P(#Q%m~z0e`7_|WnY%XH4eV4hi1 zvjY!0E|0#QL6|nl)|`ZeDt?u}*E_jxRH1Z5xr)m}$P#!0k;GoURE74AZ%5Qc3VP)F z5#ILz7K*|NCc=rO>KNg;DWWczKuMmS?L$k9@waY8APj@=L4AJrF|GG}3PApYK04laso1GI{~?hHt~r_4BuG3fnbk=;qADWzr{c!OEX7NdhtwMVrtH72 zrtH}`d(O4^*)vXuOOjjrY)jKCE0t!?WB#K&u_U_ufg2A~)*l@_WXypQNc&$~;$C&Wevl0F!o;hX$Q zva-}rOhzrnzK0G@zuV1hiVe;e#M}Kg|ISygz=ICKmgo@ZawFIO_!E9rA%F8mDnukC z8}MA7J30<_z6XbCY5vwb3{y}y;>JKbI4&CEk_YOA!pltX0a!G^JfI77ngHWj3JM8v zOjJXAxF_#U1&ZmE6!;~%4uP#|7uA)bOe8rb7M87qU$3-MfHprgdnmj%?`gulPm7_< zuNo~DcT(3ytz3EfcB@Y@Q=a9$e%7YV0+SLPHRU5UJMXQH$v!#0IzeLHvfE=puBHpNFa6TmnRj63*Bh`|1Z@9*sQT`3 zF8}uZw^6jrLS3Hhl?Y>{HYn<14o#*z=`rSgjYLWUdOGYJ?lAcb<$jFGA0;|3_ae(8G>+3V} zFsMJNMu=}u^? z?%Q)IJcE2xlFKSH%8|?dSGiwc5-tDw9ZCRaXsJ;ELsU>gSq4BU>+m-e)cdyj;Pdnnx>}CQ8@3o>DW=q(SGFp^RsLP-{E zYT0?a{jJgS>_S7^RtC-xF#jVg^f;Oa4k+PKnq*;>suy&&>xROguX^;wJ_n(gf3Sdc z_wI^t?^R1uxn;QA+mW}nMT1NpBbw$KgHE>18k$qQqN{_qk+e83kw@wfCa6Ey}iizb&o(5dseQf|w6t zLhta`G~Bk^uu z?3dIH2L53DLIm^iV*E54W3`C;U;dk|BVXp1c>?|D?l#j%{(J$RHY?A%41*#g1?t|S z`G0=+;pblzoK`Ma7XP#DZF;)DOt@P6r~3M@EiF~+sJBC54!>PRS#24H4D%CR^@ag| z|1}5j?W(u8D#|J;VcVFZ-FRWsaRbW}?X9J6Z93{VA9YB2`&h~s$Cp*go`i4nG&|c5 ztMMlVI{!WqAiGOMH$+x;{LLSCG)byP~G3ZejQzb8(Kt6(6snS`E{_46s)8l48!OcFM^am&}=I2+|iZWGl3IvV0_B@ zZtQ)n6#4AW_?;>xOQ(0JWqf_=kbuX@Q*p_!Nuj$+Q`T5&b-y8+K<^yK7B=B!enwZ45`P7DCc@%I>)$hwUSOb@r z-7u3$7xNCYigji9W2*_u0kf3}`e#h(&}!ieDf(HuBK3v7(*n1DYMA<4Q-NrT)HFTq z@b;TJI8%81L>YY%@R|F<1c5psjv=4{yTfEC@Y%CxT7fP<5YmB`%T8A@V#7-6<}h8h z#m#|Qdg1~+iMO@L^Pa9I5`e?pcOwE>#d$V%`H+H96{D^!8GfJZxkY>z0*kR}+*-Eo zgkG`JbD;|)hr+SkVi9yocvPmYy?0#ykZ;hMA=-vL$cEcS!s2`rL3~HmKxBRecQ#@{2uioDcd<#el9v{eEOf1R*6Fp z@p_mbnR!p<~u`#ksjcugEyv+vi9>tcAOrFQ)$N&ok~SwX?PD z*6aC@wNiF!ue5R9>o&=w>~*W_St}@*rttpCZ43IFQk1|L1aA^tb|-G*j<=3DOf zW`A`KY(wsFSzr>uA;P8boOn#KsOe1!WdA^%jrn#Q&DCC7?{bB;W(9b7_F?8;$>!4O z&@PeoRUq-!@7-EDIu;x2YwDi4Ms~t1+xvP0IX(_4Y}}Gvn{7tHSdQH-`>9_Q>D}C? z{v3PGH8bhG;f~P-uF9`SO`!^8y8w_jR)Xux-kPv2v$@EY z0Jy!^#>}Ue$MP_#>wh!*^|_STZJsx;Hgd(8<1b5rNGi>_;Pt*vq@+2NafcJv2N z)?XTuh_T$cfTyqv7w9;6ce!QjZa*Ynv>omoUW*Jm^1VMvpj+$AT6c@8Hg+kB@k=2Z zqFi~Q9QGX-0KnkMvu8gs(SG4Y!-i%aAN-Frl#k=$;>5>~yp+bdyeV@5&L#M)=MG{G z1;6;Q?C+_Cg%3aaP}fnpdsRQ~OdLZg z=RYivZC$4V7>QdM7 z?vo{d=3II_C281Y@3xwIvk8|jase7f=%OYSf)!$q?~P;GHyCUFajw-I>_Q*3k{&A^ zJs-atnTNV`-=YeaUlu^XIMWFno!Q*uaOv{*Jc1rT6eRezwK5_%HX7#lfA4?zNxEAwtp9#eQaHvGhFO0TZZsT6(0hG${9Sg~H_Ba+2mj4T?%ZgQ zrb53#vRG)rLI+;H`H}OQY7k3e14KYpB`*w+N80?$+5Zq9)CDAq?+kr@jy#g5#5EMv zUJ`I_e`I9jc9lpIq|3GiE8wPvJlU5ui`QGmGdgm$cCNUMuViIqrLQpQgu1+va1@QS zd1ZG~HgaiAf1v_~lb)0A91~?5UU)ryc*%wRVMnL>LWEOM37D_;F}L}1kX#32jO=?n z7xMEz&ix4}4N~?zmX#2qJXz4@#WQ+CV0}@I@8#X z0*xrgyymja$?kTAc+bT5n9dMEMs}*4f@Gn72``}WolRc6?Yk`n-EIeT5~OY)ohYQh z`?~T$%FwP6At>zVL^)2;h1I{YWmUj>gvwSO@%M%Vea%MQr22{=No*rRG?jn}s%vZnp`n^t15sw+E92}YBM zynN}Q8fwzS`xzZmr|+jxAb#8?{N4xpSRT!mI~ADXt7ASFX%DiHmA978i+jwbaS&tl ziIN2~BJo;RgocLoUYd**Xt){Xo$7kzg3~wQxl@n|QC9`>2|5u#@NU=s9RyELJ$YwH zHE=FfqKd&0#6?KZOh)ep5U?D!*n7h=zuom6(@PL3$s3;Y%(}4B5nfyF5VN!;hu7dx)|J==-jS zy4`PJ1%?LwhcF7|z!LWbJ@P>sMsukhZ4IG~sfr{-x$?_H7@^plH13+%zO2@st$bTwf>)&rI^#)3Y|=V$6%;p)L3VambceR=#$1L7RFyh1Qe0XYr%tRExfD z?^jh0f?*6-Ysi*j24YXdLE@kxtCe0z*gLK-STi1>%6=OqT8CZPmuHlayy*`yU**b9 zfI30oe+XAa|8z1)hmfVpD_s^OC8woPlr2^ZPlazRhGTxWpQFa0VcNNta3p|E$w@F* zjANj5_%>T+PwhN3a!^4Lc%V+AY!DtO%0SDSFjPBCF)=Z(pY1c|HnR~li*R&xl^Qyr zhxIhW2q;!UdiK?1rM232P7{4o)9rx&KsNqw&XsZQP#oRMng38H(lNZMXpM^j+@E#; zHb#9;vgk>guHGej$fSL4Ogd`(Q)v5w$%x6BL#S&atUCVeWed0R+Gz1y9MSdO3RVFI zR)CV6x1-c*`uX!NP)6CA&qo$lhZJZ@uILl&hnrHg`L!klS_R*7O4zhmB5wx7} zwm%`^TAEiOV$C0qCw~!Zn9W={ZHvbxNaeKNi%OkdE8~Uh%VYZ8-M9>1(;?>PuUw&q zl@jhj;c#lm+xKkv=^;Yz?w)=J?XGGiS~-8>kX$XRfrx$hSY8>s!p2e~*?X6@aZI1W zy=J*PZw);L-<6C6ZVnJP9JbZzaPLn0_;7`Fsg+Ln;-o!!vKi9Rnk(+V%E=5j{VncU z6CyrRr)z&G$^Pti6a$3|-R=%R$WaH8Nb)OfjeSWQOG(qjzZ|y|la~)emSgtx^c)@? zwP=J>rc?MS)6~Mgm3Lo@wC7j|x#IPe$r_Al(ZXZ61}gqt{zO-D)aW&>asffsOqbu) zcwf6Fc;Wr!j#1|YTa%|z7&$DXmq1p90@-uJv8&tSwo#Jr+_ftO#|lwE`l#)$?VDjq z5I8tED87P{KN#Gl^aBx-hSQBf|40n53zZ%h$0!E>93xg02w*jM8B%llV1$c-EZP(> zra_z97h8YBO-rT&BYI?!my=I{1-{)U$=PuTpfTD^m9z*sBRxG|a8CDh^xQUVRGME| zlP;jvcqZ`5$9gY{Bs6e{G(T9{5AmKOCX90`!S|1({D0%8E?ZS^Zv`OzH@s3Q+PYA{ zU=AfBDoPHF8;(v806}*cdir8}9oo(|Wlhpzt*X4Qok#!Pt2Q%8M1{+v*~Wfw80+`r zSUvx#168`5jUMzg%CqxI3E3T_CBul_B=jor(VI!<&YeRgN=7pEn66%2ZY`t1P!>7f z`Af-76o(ixkyS-nE6nGI=c}`$3QclAPIy^Y4W6N7r#*$4YwxB9%0*@gCK1DhC9~f& zF;e^BM=M{Oh~)&#`7ERQ@Fss&vEsXqj$SjpH5l_}4sxv54cBz%q-+OVaV_W#Yr3mBG8d!eD^BlnS1Xg|m7zEx0=CICMTp1WLz#bqwcQ-Yq zh=|CsplE4GR$*M3AbX1e_mwXyh{=S@Kj9-BBI>$shN^XguX_E4fsxVWF9W64wyjBZ z&V!f6SLS${FZDbRO;8iHng0@|Dq7|}D*ql&k$94AYjJ0DK2|fEfA;d~50&g2$xOPW ze!XmM+>TM`?`xA~K8Z03jX_hMm;XwH_OKg~&u?0iNysNwGg z*iv|a-TymJBsgTARDc`Dp657!5pPY8X7TQFYR#{~t5~d{^?Gq=avJ|dhv=;WdJ}Pr z_{3ADwwW(}c%l%llIDs&nAj9SpGJb=bNjcS%|zWWzu3>QAw}e7kWgNzYh+t4qMq{w zn)9HXs!EW@Kz|*gCq!BkC7w~MZ6*gR_d=Js>6>hyEhVBk(9J}vE(m6gME@@WQ7Ji)sQsWFTrfTV- zgjd&t$rH4v`}dj`mSBfjkUQ$g$Np)IWc=rD1DnS_0~PKuK?>QQUBd|JmCfAJ#lW7e zvyqK)w@?isdcnR~D^QubE?M6wtmn{yo%cT@RUC`}m4~1JDr+qNi7-_ z7HqRNJ96HBbPeh^RurN{?|%xY#?i_5jOZw-*j;~-NkmMxq_-`4N|GQWk@Duv+-uKZ zZ>l`zAwymnSpIE+bUo%?e~R|n7GC(0ei=)3zZW)V1?C=`B|9O zH_q640j+Rka)!w+BbMIXK5ZD=&|##^LC*e>Vf59vTwp{1N0dC-!%(jfeif zCA57fsHMLU)Xks%vU|+c!g?kzs~^U-M&jHZHZ0fH37pG$aP+6-^`1QbQ}J^DGFVv$&E&$CFCS{kT~VZn{q@c(asJv%?Im+{U<0t1`k zE}DH3flx?0TuC4C_!_)Mv4`+H9Mb)%kY)m`LmYYaZ06uJtR?9gn3{ezxV6Um!2g;u5)kkUm3 z-RObYI$bXY$sUg*>oW=)jOZ*5VX=r*HIZXvVrpu2AOzl#5?`fkv5^OY^~eNG)NmpG zkb)wQ7Ohc0$4?DkBbl0Mtt3lD(X7-|a!eO7&mpw?Zm~o83cLuA;h$8feZT;atUOFJ z9U>exKm>5cK$k%$L~#FF7g@2?1y58Q_FwSog<-k4og#Jr%+i_E`)6|+mbTowTo0Jx zI!Eh|AD2#Z9G55A3O}mpzxBfXZ(7YNiDn-CjreKlf47r?!r^l8_OZn3w>m-35%Oj?};Vjc#47-t)1 zJ9W87xhk3(8@GjJ30)F>1oBtC;6bwd$y%gskj$D=Gcqx%2Rw&&0y@SRpAJZ_pd6$X z7P{7WK&G+|(FYQ%;BsKa?_&@nzm5rINIJ$(TR>Dm-FzC+()jy^u5$piYr(01dxoEG zj05D06koF9^3nXCuGJk~=bI0V7#cNkD+|TGs(2b|$P0=+`}A??v(kwP+GysGBCTJD z1Jt*-pL%^?b2Bp)G&ZYV-T`Sxk088H&v)3p@>W&>82u~ zpCoEa!~>t7%6AmjMs&9n6xsF2%WkaBJpVf6Ts%FRoyWH-2e*aH=12C`Y!Hk@i8ntv zl;kbn`?kN2LL9JL($eS4fMCJFqTT0wu-k3y(0n@)^rh^7kx0Kj9muOX(kNSLxQg13 z!0a6Acw?>W<;jA=J2GO;g87p?9JS}_?WGc`%<_aE_dgt!=HoHK92C=jVwp_a1FBo7 zoGM#d489#$jd~2TAsR5fNaYOsZ6r(r(lluCE8E#!X1v`W6wMya4{lTrK?n&qqWuUh z*U>FwulJca_U(!z9m_Jf)a6kB#Cgq-$1Pkr->#*!N8_l+o15*m$Chp84ZJqWZ&MJ> zzj0DbO~3TGY!@Oq0YXjz2=ATht=!W8^N=TF{2ZChf;?a3)5a04$5C_ZhTlSYzb;G$wEU7ffxZs%Q`bC{p_ zGYSa`^wjiJk00)QVSZj}^{13+Dr{<&8Rj832K1@xneBANGO=>e>0UA%b5Q^!zvVo#=CR@49HIGLGL z$frm9Zh&`>^+E!Q6nq59oCmY2-}>R7&;fiDBloXP53G-3nuFs0)nRwoc7kY)7V0GV zpb*T?e#%Yd=0RYc)#P#5{Tx9dp@5qHK1tcys z%U5xSdJ$D&Hc@>b?>#vTS@beBWNHq7zoDg;3n_9`o)6>VeCwA?X-$FT&_8f17xgM6^Pve!I3JLwwG)Z1XiiV%&)Rco1XzV~oryTuNuyKnyW; z8_8H~$&|kXP=Oj4=5;;K5$}}(?+`p_21G@CTG&f`NfoKXI@sfFu*@Z(q;R?Up8-8> zU=SfA!6%>@=LrxVpgHI>5RaRMO+Ll62yi`@&Q1tW(wb{fe@ z992QX_z#X;8jS6ayPkX7K(N}xuH+8K`c&W+W_qm??`k%zYvS*H53&EqF9AHU?HpEj zkTLOP5R_H@7|bR${jCprwT)s7TO!hg86fLhW0q!Bzn2Jn)bY%jM9a zh|!4Yt*ve2V+z4tb2-hBF*QN#b++)&xygZkVI^w(Bj>E<%OtSHc8?HD4yt{ZYwDu- z$*K(R5W6n+VpftUp!~aRsYr-DeBva{TIW8gupOo!k1nG2kqS#w;jO!cc`8XtoY35ITCXVzBtr1P2~J(v#@gfs5F$G}?{TaRtNuBIL%7=2v&M$v z8dF_+jDh>jF&%5wx_f5QQ?flXbl&?_Ki|%+)A`|^+i_&DkVkZ%=!hG{8F^YmdhrL7 z8;#Elv-7<-)?bHNJ{yv1V0P#&T!Y?DOzJN2;CcTtCAB9gb5OElenvp*X{P`MV)}*M zgVYx<>?;SZymUv~3R5yv*$`nt+u-Z#n~+EiBR`-PVESM|0*vmCrYalmYPA?& zDNVd6A3gfe=|s-KzXp%pyaLFALlzB2I-kvyPQEI)me6ElDB_WA3~BxWu_on7Hi)7g zUb;5rrDbN0b1%zI)l}A#G;qEDC1kDhvkNMF>00kHr?j*mpRRl7)iA&N3cvlijpt>P zuVc>{l?u#X&Y3iKw(IqqE^XMe^t$!jE84{H)}>o-&W4&V#h7C?5OlK-ldBDrzXk>< zq3=ade#l4&u02Z)E@*Xb6BR<^S^>oqOS`@k?#J?0SdxZrh4-Iu*GXHHl&&}4$VrfV zz`W*OIyxuS)PL=+T$`#ROK!PzpJ%#qfiK7R<;!Ip5{=wXJ&RuLfR3HQqMyRCf)4B? zeIV!<9?Q*1Ol9jac^;cUW`nw*`AU21)ZVh`y@WU4RG`B4=LH(#wb zCxq^?eMpQiR@?K|_S{qH-uzh03&@}PM-K#|h}z!}uhKRiC_GPMFkA6K^U)(jsA zLPxy4lHpiJpxx7m5xy5#u)Pf|uZKnO$$cDsG;E_OWJk6f3Fr~{T=`Vel7r_#h*3uD(dmE z!|pvR?5>H-%&Y!tgA-lFXy1vy#V}uEuYj^11otDkuy?KbZ_le^YgNmJP~8#F@W+1gr#2NeMERW+<eQ?pi-hQ8i zIQeqW2sZXoGif5fO3TXb+!niYYju@wI_2_$BDRvQIJQBn5blXp5fRLoQM;~;7ho0* zl01PwW+`#S`u9sY1c$Va?b?>XcMA0lN>4HpWVpe>U{DonvQp5aH(ztnX|XR zYph_ZzHGIg#MkeT&^p83pQakFQc5M3+c+Ziajs%)`l8r7b&tt9`EM_0lFmC-t*A}@ zuw3jPP#}@kReRzWe^PIKCiDSEZhbj#V>zo)SXh{tAEi>#pGzE)n@1grDMhqKMwacw zt+vLm>E_|)p&r|0DLsCQ1@_E(|LyedA%-QOP~lQ_zH_=xNe_ zbX1V-rcM!%M$)l^Okjw@dOdMbQ6u0&75Q`6C_K10J=Loun4UmFWXH3E2q5(GaC;3z z#Cdi22esTR)0&6)Z~A!3`vrX`j->JOiVAI3m+Ifo&EjDh8+Kz z*W^Xn$^80^#g+F$E7Ebl$ELvrWWo{$>F#75Le~IH@X(T=@qx5_ih2|ULj6;Fy@n+d z1OZ6UXZ5LLBtpQcpFgXyJbt~o^;2@~gZ{$I(wcu7Ls&~Y#lDMk;0+3jUW5XuOM^_> z=T3J^8v7X*WEs$Ai#cF4yc%>50`O3Yh9BY1M#&wUDRNDV6jwGWzh7XaBr7qq6LhR^ zIGD<6&F=N0o|;p*zJL1H;vx$Prj%KC|1x~t!MK~sZ~wky8*@JQ9U!Uihr>-AE0~}l zJ#?427rM;}e!ldorI+4O2rJAjy-lx0Vib1^YHyWln%cIs!9<^^`19o!h0`AxPDTaHd{Ee zvSu+<25LL{Bj2sGb;gLKXC7=i<{l)Rh9dBh7WpuTb;Fm?Ap^DjS~KsQJK5bq(jJmu zkoG`a^GD$CS?lV#00~2aTQQ9u`j_tdfbLYR_fo9uSWdxtq>`k)1vL)zi3==cm~)>S zos9ZcST*;4EaLt9FJH7*N0QdFS}v&d-3pgu4>z|Ju^fGwly&R7h@+Vu{McHh zf{tC=_(Q7u9#z}p5CTQVo(fH%(!9IqB;@8krH{doPk>fCyPTWgut1>-X!3$kvCVjCUn0_m{k`spp%jD`$$XLb*l6p z)S{=CO<=aBWGni>w(H#;JMWba*Nrv8W?=e`um>3iQOrcx#HInJstPNw6eWh9N#@sfzEz#D~Dhz5A(-y=QP7?l=tv*19uvk(%%$2+B~)&u&JoQ#cipY z_Vw4t(7mYY(W*cTBAi|B1BM=$NT$<--@kE6U?+aMAL?Fs_)#8*dNBSE<%keG@$a6U z_i~fs^!dS(H@ZAGR_L{cH>kB^y+!<4`7GOW`dj&Db8t;*puP^Fu zP>qMHRq+!X z+rY}>TV{n(7*!3`UwdQLeq2&%%L7zAM;oh&i_E=WD>9G`0V!M*L2Q3%wiMxdbY|&k(A_d>bjde{_h3jIIov6Fp zGZHB4(?9;1Jj3UikhR`Qse1%MkTQ=kVty2?JcJJprYzE{=xis7DkxrQU!1o3&l&|D zSFhSUM#m7(aEk#0Z1y|uOTC4&`4S*xc!vLHb81@<-*7z%n#~sO?k2JdIHm#3BhgZV zq9cg;sb8N;(QO${+K+40EX{iB(}+szW%1to-2Z#C{Vv$c{I2% zf9CemdfZ=EsE1bv`BvOW=q;0o=nRo>=-ulVq-YHA(@~ehs2GS8N=1AT_W^uG0d-6y| zorCF7)u{+|Bf%K3qN>M&FR2njHRq6Wt}6`uj5<;*CL1DdnU<0DCKZbezUnmGBI)@d2GJR8ARs zSNrl5{(5BYmDF*g;1;BoQ#ejn6=02sivme_F=)gY3hB5oCr8n(NPjdl+P|IVD$H92eLbDa9pPhsGFx z{jbS^k|H$i0TF5fjCaZ8Kc(YDKlm#MCKXHh3oZ6vw=y9?0;R%El?Hr$;vq zRfjzgyA!E}HStXtfsT*c0Fs7bMrW}Ltx=v?Mm5DFS3FLmT+`c?y^zr%!zbUlwa|S* z2(=Wb+;00F3g2w&tC@CYFjf^o}e77#mB$i&fTbbCvf1k zhrBS~7B^Y;cYKL3WP>#f1qmA}zlVffaxCQEa>-_G?%Z`fsIqy3~#QQQwwPj(Nm>=Y0t;n6F}D_I?O2uR~J}MT$j3K17&(}V~GAd zp=XjgUYGH&tby`U)kvKtlBZkA`Zsc}zkQBHP$5Rch|9ChVr{12<7K$~lYmh5O za?3F(cmY3Itlc1c6Es*t7GodXeHmHBhA;mlI(vywDG^WHN$(ALq({)Xgk?{Cf9`l* zYD7kK*ZyuHoe|HdplfJRKX_geUg|KkGq=?wa)9|>`j3^VQboKmFS zdKNNpPgsRt)B<@DeOl6FUM|l-alU!Dvg3^s(J=j5 z=2h8uQ|3_jQ7B$TRH?uY^Se{=Ik+G=^dZwp&#a&w#d;y$9mr}elSg(0^D_ojHLb_v zVfIWW#r4&}^Z}$O$VeDw&$YCol>nM8%ieghR1z+rj4>L7A1v?>_?NM==U{ z;*}PsB@d1k#(YG2#o>c_5^Q`iLq+an_G;u1^`>4@WVOk?{kWYr|LW4foppI!+`@I5 zIMZFE7nj!WR(+*&M0z`pXpVc2yPIQ(f(C9VsGe$Itd!G}c`sqx{um8jw1icPpI|X@ zZS}~df17e5sIicuww(`JO%O^=n6=`Mdv;6yvCicy!Vwck6KzB?$cH5>?+em*TdvcM z-jQ-MrO0ZhrBBBFwfb~%bTWCxilff`_KF&Z#FyUj_QRB9)^TpJh-=s%( z(%UR#s&fbfK)rgDM-sjvbe#B`iwo%<0m$2>;ALHT-9GnLU)2#X_gn8yH~Nc3TYMgv3>4V z@<~af0R_0LuzTrC0$mo&6P|l_wVvUWfIFg+#_82C=m^7!xo>+NBI_~@v*9F?b=MJ4 zpxIdw_sjO!6n8* z+sPwA`-!p^!jvQn&Oun7P##ZK{&2X@xftFxv=1&uXk=i@u6yFDXf;}x>2&5(-*`UF zsAuT)nQ>{Sct}7bK2)VzA@BKfH73ob<#79xt9z-*1Fx(%_KJH`YW%yrJB4TIq~C<^ zd|&RFE~$0nMb@mqt3#`?jx0%Uaw>A349F-B{5C0Cs0vrG+)*;$1Luh*YYDR1D1Ls= zt`o?$T6C0nD*0Dl>Sf8^7`}~g2P3sG4z=y8D)|cs;b7FD-jm2z0ugo35k_P@U8$R@av>O7U!k6je;gpFFLoXnG8S? zVDks1aYd=nQNn+Ss0bHyP`hB$HhSZj+1_2Je1iq*u1G)D!F@$6!E1xng&sr8rc|zf z;|hzl~&1!I~AK(@VN0^&pfDZXrMuN52J!R ztj|mgbUI&p(zs}PhX|UKcT|^E#5d&KTV0_0`>y+t7gdZI6Y0gp72`ACTXy>19zKrz21^*!jVW8C`Fd5>Kph!=32ul`uQwK+(-gLqTHWxd&w+LOsw`maw)_ zOcD8h?#kdjKDaEx^EBC;t;wwZ6&sAnnny^(y5q3cj;v1Amp*K_!WyRG9U@^;etg>Q zg$9b>+Gv@BUQ{{!D{99(8Wp{9fdy4=3m>)nrEsxZ#pu^mPN(~#kyqSit-A^D^}{a| zx0NZFwH7;c4SSE5jSUPauS(HTCmfYPQCx{!41JHq4O*u6JBTj(AQLcrY`e)=N-JgP zRn*mO*?Q+g(-0KTs< z(Nv0{N{gm+Qs2DgXyd5$iP{s0&VAaCnnw~Ad88D5)&mBJGz=3c_(-55T%5MVvKGV} z^nH0AxuWitwC!XW)q>W{$s9xYOVGrBk@(xQ`G<>;#cXyCjPaR75J0zgQ1)~J1R-w`7K zQ0o(96dtOnGd6wngTg3gNhFx5wkt&Mm)>8L-Q zC|8LY?VzLa!8q%Jj>}#gl_CU<3I6H5JmbuA+H{m?_Y)El2(wtvFEG6QCly({Ty!8t z1Az+$8M=cm7;yjt0P7ZyA&85||9%Luum*c3grSh?Uo%U5>j}dbA)2Qe&Ysd{O+K90 zs+e-0=z2cP$YL-LSEHucI)r086%x=T76;`Sz0La8&F(pViom*HHbu{D}wpRis zBazVCLRq3`V_BcQ_6nX1F3#co0M$;V-rZgYX!B+y<1Vt&IKb(s(f(ZSzh#yXx19uk zM$74*duK0H#f@dVK3os~b%%X|cb%H!@rvj0RY;gTVz7C8*S$`Ga>0sYzu1g!N~ymm z&*tsxkH&Vqclx{Vi}ROv<0`e#8~W>RGEv-Ckxs5m-VYbOPg$6dd>Y$-h-7-MZH~=9 zqqXYl>^$E&O|Muh)_02?wxj4u1|65O6w8{?d_XlAUns@IQ#{}e01I7vG-!s|;7wEJf zj|I_{RF32abpEAhBX^onmI3D0Ra~aY3Z9}nw}NJ%!LmCds(H@uU_H&6aac6)l^-U$ zo|q{j=1?B@L8`CmkJu;1#gA-)&;1`f4_^Zb8X+~9$^IMBJ$&adq$~sQ{$M@E0>JXW z?vRgQgBBNL!x0xCHaKz8yT9Ic<;BJH zqg2CN*jU9m&VRp2b#@bPZB)I{<@&{tsO-X!q`;!Mui12-K>Nm7Q^qT!2g!15B@cynO#k?JU&xMY_O#Px6MFtb&5DgL3}} z@R=nKc8pHCq~vs&#>r)@cYkjnlS=VZoFVIca`fa^G}T-;*xue-VAx>#fXdYzq(H;EXvbVU(bzz z{j+P5jo2QDT#LRuvxQT+0b2@~m&-iHjOH+g{or9d`#!2)ZHu6b4h|O)9D;}O@dU03 zTf&*h%Rq%uCR8BR5+#A3IEK~8lbGb9I?|by?={Awg1aVWh`_L1e@KWtd|!l!9bR)} zdPoQjqbQy-9v09xaGHY8`mU{c=I5vXSCm8L>DGQUnP8}3_KG-ntc;x>Go7nfgBp12 z)V`y7`Pnfx_bK(RXi{Uytt|kW`1 z!+fgY%NKPvnn&a@8YdFO#^&6vemfX(2m)fDsiESvEkM{qFN)c$HC&P;Zr082=E(w$ z7>y2UVza!!n=*2L$2{s>De9be4w^A(=LVzxr)x34ZG1xg@4(*ynZv8*LEe6P1!cz4 z+2%FE%ia`QRl4`S_J0rmU=q|0A6$fOFe3aaTRjLCekn(*+8*rs(q zbVRVvBb()aYgX)R^Cwq0c6#%tae=cX2j7|QLWl6H$^3TM4~X(Sdgf%Y=+M`bJdH*n z*Sto1!_KE@z%zYU*Y;L$aF!5XOV%DAX~)W{7&gN>o}*Tmv4H z@VCT4fbE@Oc1$j>Vy(e$F*f8xI!ZF%eYNjWt_j9`z>)J=_pA=xD|sbH#Y_Xsh4b@o z&$Miw-Fp(rMo*rCKmsU$zaA?q%4QANR$@qh5obT`E2+i-T3i{n(gU5SLa{uBBV63| zq_1;ZB&P7!-jL2ef2Ys51icLl(Ye2WUmon1+H#8t5g3PBEGO@5PO5<*$VhdmE1Nm} ze0vSEdAs!i1|dX1gF517r3K3-L+yfyD<@7}oEiRWBb&QUx^{=gtc!sq;0OCa-xPV^ z!hxP@mv0+n+7opH`_}f94s5hGH4W@kY)C&T03J9(9txj|mj`iM0bZ7v0q9CoGJ6zt zofBf4*f(VnOg9kN*|MmqxV`djkk&t~CP?_HvoY;Xf#a4=Cftqu&Wi{*NewBUh|beN zzdbSG+b@L)6zr0}wl(j@+=hqG7DS1B4|9Cp&LSH*1tOS#S7!1{zIe z70TO{>Vw6FN$a%3@@=Xw$6D>{H}ZJn%iX(vsfOin|JZ+<(e?egqbh-y^PeT%j*Ii7 z7oG3Us+m&Y-%v<@x7NBdul?S}{;5~?&&IL7+D7NLhhsF`JBeitsA7AzqU(+vE=Moop3MMclBE{DlmAmOAnV z+D)M9Pg}>3MJ3`xgL8z4(aAqoZN{E2kM99UMe@Y%0wMuh?foo~hd(Zh?ZJ!z{}ZAv zE^SRIfl(V z`~RIH5S*a=CW+aVC??qG2&G<*h+nDNJWC5H7kERc$W%wx z)%eVr3vA%i z$6Ms){kG<;9L_PU%F{>(&`Z z3}Fxn5LwZ>!-upw4?uCgtNo=*D$YS0z!&SR7>bLD3A&O#Kb3Yna1BV2(7tNZYTe1{ zpPb~LbyDEuK_=uRgn>WK#Vr>?4G_i&wjYIgHh`9K`F#2|$u-MI;_My>zgSWGNlSkgv(D2_w1H}%jC;Dj5x4PzETBiQJ z!{~6@7R5ZV<8@8mMgxP>i9A@ZoBu@_WRp({zI_uH7bkU=BJ^Xl3iT`_9 zfHZ^%_vg>(pwrr{eJ>hg#)59;d2X&=CC_fKL@9|iDCAt=>88kKeY9^;m66VaS^^|) zc$oT_H+PJwJgy&>qv4eaKVY{KoiEp{tnNSO3$z{cqj}*+;r-XbkNj$~xw3iyM%&YJ zYT$$J+^W8}N%N$Lptaiu@4@y>%GMa@F_b0qv8- z3`6t@~op2dv^}EsalX$BP|(U?K!X>{-+o)OmrL5 zdciF1wD<3x8da^CpJK}*dHI#kzJ2xAP!xJZA`{Q`GbjkQKM?3LcKFYmnZDMT?S3fk zr`|m3IQjU7uM3#jDJOve5BJ$iHOwub$WI?}E=HS#2#s`aK~ekazlI(?Jxoj^#Ap&P z!IBz>@R63vL5AJ`$%?+TNfv)-D^r^y^#u;OP$KT1Zb}47Ba5jB!FPiJEzY!WMY6Ty zp^kBhw*>{&N76x&m!ais{C-6YVF|IVx)J8Sm^ECp(h>SH(t7^EMc#V@jXe6X7-@?4ywB_TKO$rfIge6P;jW{ZR;Xno*th`(Xad zYjEQ>i7dl*j~#PaXhBF1`&Vwxfy@V?1yjZgc^^^}BV=|e@;$)33&g~L2|rA_yg*#E zM8QyT{^TfK-KK~eoEeHK>|#6s*$)0u>9~Ro*7v`|E%K(A?-_>=vOizJ`a&Ab8s2{2MpA4mn7(*w)xPR!U)4@T4OPv^0un`z zgq?6xE1DO87;yJf9>4njIl2qr?fBBkJTm*Hq6Hoi3eheQz!|W{YzFfekbN-h&oa

zG8XG`LliOjn2sO7XphlKy^)4ZngFkrlOzPHAkrsZt4SC8?J^a2^2E}22ar9*Dnop3 z#JlmXtK2g>>1fWzbpfdje^ixSZ?qfFwIJ|sIAoA>!$))4dU`(n#;Jo_6&5)^q_pvI9?OE#qpvXG18^N)BM6j4H6Cgi=2OCc0CgD!H5A+v&j)^Y zJ-oAG%020^$i^?mzoO(tm3TjfG@Le~iz3~EB(c$kknLw~x!=5p_vz=Lw485I>wBo~ z<4|?`)F$C)14o9E6Pj1!gipjhT`^aSPM1%Q4bX5{JDu2O4jFiEE7xUY?m|S@*4Clh z&5{N!(amJK1z<0$mX~&fvt;{|1&0W`6)0Go zpO*3U{eD*9Xw&jmwdBz4KkJ*y^AGdt+Yeba_b*ShbsR4)Tkak0mspkyYD73D=PR8?0=urvo_~5AO}&tMHMz|DfRf-_xPq6q#F=ejgKN<}{!1)R%E| zP@Iu3e)toenYt`N91gYPxS&ufv1c`~CaY^UOrM5u@vGjYh|N7IQqpT|WFQQVj0FDu>l)1W*w)sT5MGn(`pMAUN@}k_$!C%bLEjN;A3thAIvTAg z($AbmBP|3SP8G6L*f=#z_UP5^oZ?$CO4hEnqoVAa{UdDd@q7su=lUm85WX#M5shVj0ih18F_<8*)i_~!iKSsd-`O^seb zej2LJV&R`!NYbjdQBx&+njZHv(<+$gHOyqvZQ-P$r4>H2-{52I@WWsQ0->RJ{)d!P z$<;sP)L1wBF_3m2dC49cPnj%xTDG7d5(1Xf$?91zRf>H1uv6}$hK8?Rp>@;q!%p4f zSbf%MRrU!Z$M*gjnwkoI_;6?LEuJ$yoL|?-y?ORK&c1p6@}AzlDpB*(`Wr(8Lh}ft zP(9OSdjmO|t22V4n;E^4Nw&zpOB{MIPQ1%uv zgvG~?h&=I;rCz?>GMI0BfFRS<8?t&(>D#lhpFjPRler10qsv&O;&|zW@WnInZCCXd zFso#6W+oiduCM?6^2pI%XDX!JZIK6#q)R!hlR=oih<@(IyPkJDlC9 zs^wRHwaNG3qV(@x?Ifm>+}tOM%-{tMh>3N+Q*?T;uW|OH9f432O+S!W_wBJM{h`B$ z_vFVuf6k)#;;N|)C;!qax$axx>vm$Zsw(6q346yi$`j~F+;Qef$HvAmr=9H5nbX@y zPhod=soI{l#zq;#Lw6+D6JGOa(#4ezR$TmYxkh!h~p zn42@HyJ_^BcHmasV53&)`?=O*UrIETUt!x*T!RIs#A9`malv_mWR`CXav{#_xjMYt z$;hsMeR}NPg9i!U&0v}$ZelOCC&TQ7k=KQ+3y_B%Mn}`eUsNun<&a{-lBKaL4qYO* zdBjL>dv=KJ6d}v__`=RxHo&G=K&;4lY^qoDq42BB!o{Y`4&)l=v<(+tZqv4Tdy-DX zL;iVHRd$-XRN)Bpq$jflUXFHxA>goou~+!SpW4n9B9hT*p0~ zCo)WGCooNMN4gK(E@ncT;H9Jvvh`BHES`U=d%0%3~>QH@@0B;XZVc~?P=9Mdfxuy*X zMHcq@p{E6`_KYT9vW=D4P2l7!^(*L&BC&q7A|xz)fR8V<+}2KvEreZi@1;v1n3yi1 z;~c)7yBv~kLY^za6anvdhq~M)BZ!IJ`IvTmL(p%k(rM1miGf3%5+ki_XgL z%V*L(@jNoRzo5K4<}Nd(V>`#5i=S>}U)hz{#iZjO_oK-CI!ADgU*&gZ+f$t^yh=*l zHTUFv0-28Ta=CoE$IvS4G5URfaN_7p*oc^o`F6qJYB?h#PAA2*Ternu*M0r^Zf|Y9 z(SD4Ce)Q~_qTp=+T;kkS$bO_f{I3s~6}1V|*}CpLZ}OQWur!N}?RG5U`Cb9O*M;su zaq;idPUhU%=`ZMM$N%BR8M&S9#3)YtYh>{lU64Gf0gx5eIeoK!E!-GYk#o704fEF9>2eB4{ducEhS}`=sGyG>>_1G-t6vTR#sMW zW+mousbQ*w%KL$aZhh)WOuANP++k8Tp{}8+IX9Wxz;)^r z19AD?(O8dda+JhHcY6d)2C-D}tfQll)Y_yVfrn!L?S;t3)>i+YKX1O%D^yEjTU?S} z|3OcP)3nyr-HSnsuWw~t!wouh>J-djZauH*7wwE|!m5vFzW4R_-@g8LIGjkvWMd&- zx+nI3-N&B3vG-DVyG+AyL`}O zSYc}YeNN?qH0-@eYGj#dGX?8Q`<_mfSZuITW4y@Cn}-Myv@c_0)de$k80+ojJTJUX z9}5Y)cP~x=jlK|WG7L%su@5^q?|Ic~GK*d+ixhIw!4oIw%FD}1dj*DXr+xE%Uu?m~ zdYW2a)P&8b@w21{k86y9o8I4jPwnRyoo(`jO=SC<+E_MBd?vmuR98JHow+<4Rl550 zwWJR;twp?<#F-;7bW>l)$)$)gKkN2a(YJ{!GB;G@1^AJP9{ zsKNKl^CmqSc|Yall-Z$_1=mY;HV-FK2F&TMTCF5MOWXF{WG+djaxwes9ULD^zm#b^ z%8``ynu`2h8MI8-NR{bIz>O+Y(%#U}Fsa*^^T7VgS)O0RBG(0UoOP6zIn{_h7t!-RWwMNS2%qBy-+Eh`HgS(9o46yTw>je!2K4KcI;UTqTG?EidGz9ivX?1y zaGUAyDz3Utf#sfvUjWitX;*&yZhGzc*wm&dER=-6{puBGVKxi5JgxwiA~n?-ibRG2 zz=g1#ZoY9+kM#b3^KJ=R92~;tPk&w6&vdxEI(658+O;Mlhbaq2hvXmQE`{xy?()-w zf}3W;BO{8jvQFJw<=6|7NY2mS4OpeDsw%Ik`Q+^PYNI`r z2fozRwLB=Ir=j_T`SSV9Je|~2Z3e^MxfD?zFYUbJU3%q&7Mw$!Ci|C0GRnU!dOz9M z!a{Mz`r2O4)UI`@#Fs2N$!##%Tzk>LG>l@q8nMXJ zrEw`ut7&WSO{}%juCH*j?Pd6}%RIt?A1IJ{&f0j)G@q{VO~+2tMJjkbsp;wIbN3xc zE7@l?B4%0C^@kiYDtGdk>SI@=0v7{u<4cJZcH@#C%r2=L3zI5FPi<$u1q=QeDjym! zXy0Nad)_S}?|-s5&oeF`eMOH2Y#)w5NB79^u>8TwRj!tpLE6$YSzptRSLHu>dKZpE z;0{dNuKRVPx5$q9etYh2+;lU;eNrApS9ZNE{?eT)yNmdJ#eAaRuGgSK^1aX%XyFH?H@Wx00YVT1UWHh8z@mX;sCeg%B_qFfrBv)>X9A0qexE_-ao`?4ij>2v(UiSb}-z<#P(ec!4PG1-*g-g#~7Qon|V zwjs{s<>kedm$PH?jfv@vyzSWiBh;f|WE5A;d_1L2hG1mrN8&59Bl~<};bl5AA|l|E zxKlNl6V0jZ94Bjjr$=VTVV;|*j>`;c@kXZ_SV=!V>Rpd0~06e9z-Eo~w=?SZiJ6IL7$+ z$&;}=H2agNy}Z0iK4@YfO^b0tMqb|K<2Opq{P^($4Ys;H$bT3uvdY^MW83(<=apyw zGxSw{`SK;s={|;sFfcI*CSUo57K7#hVQXt^O4|HM9*KYj>o-gtFH;WRoUo1djCX4~ zbn(k7yHA~w6dD^a&>oZ#Rspo7GFkDCE6d}oMZU-y4?`ptiO9^%yk(i%e&u0C_R|!y z`o_#G9oyNZz;`)}RDuGm3yNlD+^K14=;*q1_3Hh~N}1pb-_6z7^mrIc&cLb0ip?;X zFpWvXG%&Bq2*U#l3s?SabDGe`re$lJRsB;y?YECos#!pes?DkVxIKYfyjg?egQ1F74|nf= zR!FP6+v@kBR8G#f%tE9e8-2)_-|v^WbSzCaH^H>4ntjDg*g{a3hw(A@v^aa0eoy3~ zY3k!w-pQz_P-R>zQz`5#aSDFxf(5;DcMs}_Q!Y$Jpf~bkv>oLM_)oxvgA}`NJ1XMomqUF6WPPLb?o!OrC zc%q9FUEQOm(=;2@rFDuIopr8w<#bspI3_+j>K~V!{H2oNvvH_nZ;7poi;|@!?+s() z`~?lfFFb|^pk~qveSVz4baO=G*K}q;gXdrHS7q#PB*aa&vQn@St2t>)>*xIizI|zz z%@@v!w6FwGS*jtG>b_OKZ9=7Sa%itI;@u$wSu$A36R5wi9$lzB*wLs*$4k707m6$+ z*q`euhg)!Ief@2!#N06SXAj^Mi)q1ElkrAYi?#(@IaMJpF)JsH4rW(4K8U;GCEzik zq@nRoN;=B!wQe`Q5G`iMg{k+Uzki$g2LIG8kCw1|c{t6scoA0y+9 z!_jY7LiWrI!oc!&Ikrj&A{3&*?FT}d#cRjMI>Kq%&pO0Mnpl|{H${E2v$M-qj^qtB z;jva%SFfXNW9^ud^rQ6KpD^t}K3P{jI6A7d=&Qq9(5a9o++sKJp{|a4Zf=fv84Y@s z{;_Ep`o-JgFN!6rG9 zyuA@Qqfziq{aaht+Z*4?euuB!nw#r<@S?lD)VSc66=}j^$W?uh*z8}X-!ycFujY?< z8aoD0Ei1J+1wZH)Ql&rY7^Ha9FI{bXNffIol-1Q|vOTe9FBu!6^DR0MjzW40ZT#x5 z^l1RlXeOz}W7#Np6%4%)|K&K4p`H;OOpOuma~K2hqLtnA{bIXba$4HQh~wJWsm<@T z>48b0gQYX&@@LPI-QC)7(XY6>AGV-@*_F}QiT6?jor=4Xn8820Hd7&w^<5F#*WyP{ zX&v!%f__uvG{LOJiNK3OZb6id7ad=FwPx@zT0Znp8G0`64jsyKvA4I+WAkl)3w%TT zBc=-`qY!#t`Ics9Hw`AFOeg1x5ejZ+A~&w;ySlsY6K3z(+t${`Ets=pqoA-IWoLRX zSDo=!;cgzkAA4IB6cw8rkYJggq=f}e&)CWT$FCB}8R`v`#Zc63e|_EkG$P{VyS4u# zXF{8sHA<}h&i-JPbjvdszpiTk^9uvt=!0YUvFoTuF}$jkuH{w@^X}b0fVA9x?Rk8i z=W|rcv(9qQGuSlrK-i+)XuLJ$@9)>)$xMCC%b%G~C7s-s8n7b0vG7Fp>PWw;{8X!D zjg0Y3fwx;WT6d@B<&0JFgw33lePoQ9%x=k1dWsq)#08PRm3Ut8M!m#1<2yO8*GZw} z>}Q*~Npqbs-R9@W>jc|b+)AAtV%z#}>du#+Dyd$I)mAOYS3;ZDMUhCWCyTqSh@*u3 z{r!KhS0JHj{d{HLE4{U%PIN6xE_q@bdG?KJDuVax*T$J?5@ls&i!qsnSfQgsNlDpw z=e*%f0UdJS7L>=Ue=uf%Vc)(pzu6l7cfJbTN5K4lOZ%awXIJ`P$=lltY%XScU2jdk zMB2BD{LDvOJhXfPXrM*<$gSgzQE@rd;%TpreV!6toFERPhpwzszz>-y`A3uzK zt*^}M6k6|R=F{CyKNGKN3J40)7Rd548@If@fW4yCuY@gZw>FlI>z?uHjy-a!)xu<%5~t%tl?1!u zxsDy%QD`&pnMqy32PoBT9b4_P97fev%aW5R)3h@K0WhGc6j=2H;%alKKI5&zHm1Dq zrFZ5{E^BKWqvXVL`mlCM4NWbr0EC($@Z5_1cgXc*=evZ2H)2LqB=qvGBD9Q|*0&Cm zRzKs@L(zDDs;AHxAD9>#pyzMSg?kynYNeBB_UOv4E^R~4fQ_}~;YuG;WfheV_*FAC z=?L%Frb~q)9-k;~klvCwVNmj>EdxJfJkww17A`o_4R?0dtvY5bqoc5Bf7jGZfd*RF zvBc+DMpfH*4N9IWT27RFmc~0_vw2cYVSfIBW5@0^=*B$Nj z!3QIL+0Kt#NUuIl^A;UlcKHA1qvBv`q@-f(WL#dCmF?drYW<1$W#Ut&XKTk!YxV?} zCEiF&NvRTSkdU`h){JTe>42h@Z{&Nl>XbU>CZIlT3Q;sC*1zkZy2u++>h89hI*iNl zG7lGz#>ktP9C`fsF)=>B2h-Jh-EzDb!L8qG%k!qG>2PDbJf5E%fFY5U%k(M+(ffoab z=TCocEJuHY`_g2UFBvtzO~1rsZ*j|{dy_%Th*Vi^f6gsxtYS@S%g8KWrP}&iBfZd1 zA#Z%|l(;Z9P2qVd$jNPs@m#tpBqD;WO-3)duyb=ZNO}@$tBc#kU>%L9Xi0?q_b_Utgd8|EPKk zsH*m^Yy2PxNTUcyhXN|y-7PI50@5lWUDDm9qI4snh=7!Ult@cANC^_s-SDk_-~T)Q z-!}%2<38SV59jRt+biarYt1&=hk?(R`^Lw^;fq=dWr7bi*0W0VkJ`#H1@m+xGwBOMO z>VN1a`nbxgJTq6R@-CQa78d^go!f4sZQJ?VwY^chX$tunsb-3s`s#-EMJBEQ&r`0B zm`Q#4((^Lu-&MCtBFkkMZ-lD=ev!BQ{r&gS3gMtb71Z9@IdD&)(Kzwbr+enlpAXE8 zPEJxn{mB31lS!uge6#>KI%~h2ti%W6RuA`VZ>4@@LekHV1sNRB)@-@REr=DAFGIg&2YNBOJM(gKf5 zKA-)`R}2J*udvQjON#&iXFfN<@CQVfZGi9}KF!%Y??)cwRuTOdCE{i^t+q1f+D5c} zF6(|iwYkNIgMGUNxbjs6#?D<+lzA;sH*|oMwF7F?n#;moZSTs^g(9`v?u9qPwI)os zs`2nDgKnQQtuLuA^%6KcvET#;0Cye-oY7n4e{gY$stv^Zy1!CDG~3fdC>S4crFGS} zZrpDc(o}A%K5M<)K(zzRxO^B%#sMoV9_Z=od#+86jL4&21FQEHnk;TWF$M+(vMYLF z&_T)Go)f%oKTHClAwTW8DOR@*^$8=Y9Ws?lRc>D1TR?os?^M;*rJ?9x>T>V0xbA@B z34oCFL9YSfc@3#G1I(?0Qw1FYz@ZZEV7t-94%yq}WM!c86cyU09OfVy-WC-#D73*M zq*<%zhACUb&w2rjjYmDBr|urjSRr5FozZEbQX7{pR)vqS+eWHV&0QXzxKuIE_*BqI zM-;76!ZKHbZ}$GkU%^$;*RK3r8NYCc>FxKQvRVmmP4^t2(_8qMpPoGfc7w3vaslD3 zCm}So%MgmmHmJj=T$`$WTujxy4*k#I{lmrXl%M0{NkF*~OJg6y#|eiD4iFmo3Wb@9 zx`PSpJx?eg&?F(|c~1F)ahi59fRXTYF8m0_-K*7Q%@fw05$kgy@LuQF>49;ZaClmv zvJ*R4@xgEX{lKheiZZvjPJZY5jqt7U7pmeTByc-As-2eFky8MuZ+CqD2pQzDGD(>H zgB>UF>)Ez1q@qydR;9$c z*hy&U+k}TOsCVfhr3R9j4NXgRS9jsT2?yK2csB5O?R^7=-m5l|dLfHENpNETlLF^K z$O;+2*TrAhL6kKIQaFgnbSt%PJT~N|8r1sbx*aqk)MDz8vF@p=9NQp|e4rn8ti@H&s4H%7nlg0MCMy1mIL+ty6f5DnmN@d_ zjiM|FIICUPDa1Aaw%#-RCp~jSaqE`SwEGhE$x|DnckkZqO%QZjTiMz&0T{NBpW(y( zies&ZRM9tj;i<~)AJ*}!58;9M=g@uFc>y+%D%Mn`n9#*DLbkcnaDI^TXn}`Zq3m%GIfZ|61+ye+8y-a_=0 z4pZ*kJw7vBniwLdkcp~O2czf@Gl%Pw3NXP0NN(1od@PM>{rSP9;bi9VMZxBIW$}C( zlfnZd#*BqKZ%MNL+63w)h235hlexZ|PJh>>ElS+>e`CT>A64iV>(OUbiB1yuVzG5i z%cM7DRI9%0ocP}6+Pt;%d8>Ql^4w-@fTu=N;w@!v80dh6Rq%Um}%X3OYq<-^;c1<+J{c&zsz(T_^8B)$pMR0WUi{ z`_}HR44BG+DdDd#_(d^Rj6pEqdeHuf>oqub8N(Yu^9*nW}l3mWGBL;7WMdsL5!C1EsmQ z3+|Cf-3Q%{o^A8nrGcLYr_=GJ&PJ^F?p*0QTfP3rIht2BUa1`wqH{y%M

7!V)Zk` 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

=8mlEE4*ivWMr>O=hXECIST-zTz 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

wBzLoPZxx_1U^murxY7P@Rq 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%0DFAgQJCVaX&(DqGzqv~nZ%;og?fXGhw7bn(T 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 CRnV#c literal 0 HcmV?d00001 diff --git a/doc/index.rst b/doc/index.rst index 07ee28d1..8a523ea0 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -135,7 +135,7 @@ as part of the `Stromnetze Research Initiative Workflow ======== -.. image:: ../graphics/workflow.png +.. image:: img/workflow.png :class: full-width :align: center diff --git a/graphics/workflow.png b/graphics/workflow.png deleted file mode 100644 index a7fbc5add57498182dab3094d70fb0edd1b3fb75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 680340 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 z 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

=m&%-X( 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

~eS~@=~cU9TDl;Qm-j}{abrC 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

T*!(Uf9VZ<@xBqKx?v@1v)?oi7u&?c1*k}y4VAs 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%0DQ6MgBl4)-R6pyB63%@DZ>;CY8uuQ;IxAX;r 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

4;?8|R644r_RUGzE8ywfgpNuIuPvbc+N{X#;8 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 From 303b526bf1be4f71ed8c70b30c0671e2d5f5a762 Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 6 May 2024 09:09:23 +0200 Subject: [PATCH 585/591] Fix formatting of link in `base_network` documentation --- scripts/base_network.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index d8e1fb4a..432813cf 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -5,10 +5,7 @@ # coding: utf-8 """ -Creates the network topology from a `ENTSO-E map extract. - -`_ (March 2022) as a PyPSA -network. +Creates the network topology from an `ENTSO-E map extract `_ (March 2022) as a PyPSA network. Relevant Settings ----------------- From 97035092acc13c87b5cd56b7e9e8d96bf0887439 Mon Sep 17 00:00:00 2001 From: Johannes Schmidt Date: Mon, 6 May 2024 13:20:53 +0200 Subject: [PATCH 586/591] Fix approximate_missing_eia_stats Function crasehd when 'ET' or 'PT' not present in list of countries. --- scripts/build_hydro_profile.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index cd51ce90..f1e56532 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -139,7 +139,8 @@ def approximate_missing_eia_stats(eia_stats, runoff_fn, countries): runoff.index = runoff.index.astype(int) # fix outliers; exceptional floods in 1977-1979 in ES & PT - runoff.loc[1978, ["ES", "PT"]] = runoff.loc[1979, ["ES", "PT"]] + if ("ES" and "PT") in runoff: + runoff.loc[1978, ["ES", "PT"]] = runoff.loc[1979, ["ES", "PT"]] runoff_eia = runoff.loc[eia_stats.index] From 315f5ef64ffd701083b10b4c4f11b49473bb9826 Mon Sep 17 00:00:00 2001 From: Johannes Schmidt Date: Mon, 6 May 2024 13:25:13 +0200 Subject: [PATCH 587/591] Update release_notes.rst with hydro bugfix --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index dbc857bc..f65f4cf2 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -172,6 +172,8 @@ Upcoming Release * Bugfix: allow modelling sector-coupled landlocked regions. (Fixed handling of offshore wind.) +* Bugfix: approximation of hydro power generation if Portugal or Spain are not included works now. + * Adapt the disabling of transmission expansion in myopic foresight optimisations when limit is already reached to also handle cost limits. * Fix duplicated years and grouping years reference in `add_land_use_constraint_m`. From 9d36d2bc9b76bf25fa927d63173f6cb4b1226f62 Mon Sep 17 00:00:00 2001 From: Johannes Schmidt Date: Mon, 6 May 2024 13:37:32 +0200 Subject: [PATCH 588/591] Fix copy_timeslice copy timeslice would add data although country not present in load --- scripts/build_electricity_demand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_electricity_demand.py b/scripts/build_electricity_demand.py index 7615bbc6..fc8af372 100755 --- a/scripts/build_electricity_demand.py +++ b/scripts/build_electricity_demand.py @@ -129,7 +129,7 @@ def copy_timeslice(load, cntry, start, stop, delta, fn_load=None): load.loc[start:stop, cntry] = load.loc[ start - delta : stop - delta, cntry ].values - elif fn_load is not None: + elif fn_load is not None and cntry in load: duration = pd.date_range(freq="h", start=start - delta, end=stop - delta) load_raw = load_timeseries(fn_load, duration, [cntry]) load.loc[start:stop, cntry] = load_raw.loc[ From a184f159c0653eaae71d6d64b634af0c60b4f9d1 Mon Sep 17 00:00:00 2001 From: Johannes Schmidt Date: Mon, 6 May 2024 13:38:36 +0200 Subject: [PATCH 589/591] Update release_notes.rst --- doc/release_notes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index f65f4cf2..b73b56f8 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -174,6 +174,8 @@ Upcoming Release * Bugfix: approximation of hydro power generation if Portugal or Spain are not included works now. +* Bugfix: copy_timeslice does not copy anymore, if country not present in load data. + * Adapt the disabling of transmission expansion in myopic foresight optimisations when limit is already reached to also handle cost limits. * Fix duplicated years and grouping years reference in `add_land_use_constraint_m`. From 3b77b4a370c869d927bf9710c0aeee34a48d7663 Mon Sep 17 00:00:00 2001 From: Johannes Schmidt Date: Mon, 6 May 2024 18:46:04 +0200 Subject: [PATCH 590/591] Fix that code works if either ES or PT is present --- scripts/build_hydro_profile.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index f1e56532..ed3bbd1d 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -139,8 +139,10 @@ def approximate_missing_eia_stats(eia_stats, runoff_fn, countries): runoff.index = runoff.index.astype(int) # fix outliers; exceptional floods in 1977-1979 in ES & PT - if ("ES" and "PT") in runoff: - runoff.loc[1978, ["ES", "PT"]] = runoff.loc[1979, ["ES", "PT"]] + if "ES" in runoff: + runoff.loc[1978, ["ES"]] = runoff.loc[1979, ["ES"]] + if "PT" in runoff: + runoff.loc[1978, ["PT"]] = runoff.loc[1979, ["PT"]] runoff_eia = runoff.loc[eia_stats.index] From ff99db5cb5bf3a703d546a50961b23b5231421ed Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Tue, 7 May 2024 10:53:07 +0200 Subject: [PATCH 591/591] Update scripts/build_hydro_profile.py --- scripts/build_hydro_profile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build_hydro_profile.py b/scripts/build_hydro_profile.py index ed3bbd1d..6a0315c7 100644 --- a/scripts/build_hydro_profile.py +++ b/scripts/build_hydro_profile.py @@ -140,9 +140,9 @@ def approximate_missing_eia_stats(eia_stats, runoff_fn, countries): # fix outliers; exceptional floods in 1977-1979 in ES & PT if "ES" in runoff: - runoff.loc[1978, ["ES"]] = runoff.loc[1979, ["ES"]] + runoff.loc[1978, "ES"] = runoff.loc[1979, "ES"] if "PT" in runoff: - runoff.loc[1978, ["PT"]] = runoff.loc[1979, ["PT"]] + runoff.loc[1978, "PT"] = runoff.loc[1979, "PT"] runoff_eia = runoff.loc[eia_stats.index]

na(>N8qd`b0~VwMSG>E;JpD|ccrZsWm{(P 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�(2I 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°)h)dFt$!j)chl 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

7kMn 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 za62?(�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 p(dJ4>;-m#!qh$61`__ for all substations. +- :mod:`base_network` builds and stores the base network with all buses, HVAC lines and HVDC links, and determines `Voronoi cells `__ for all substations. Then the process continues by calculating conventional power plant capacities, potentials, and per-unit availability time series for variable renewable energy carriers and hydro power plants with the following rules: @@ -35,13 +34,6 @@ Then the process continues by calculating conventional power plant capacities, p The central rule :mod:`add_electricity` then ties all the different data inputs together into a detailed PyPSA network stored in ``networks/elec.nc``. -.. _busregions: - -Rule ``build_bus_regions`` -============================= - -.. automodule:: build_bus_regions - .. _cutout: Rule ``build_cutout`` diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 93bb8e54..4c10b573 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -133,32 +133,31 @@ This triggers a workflow of multiple preceding jobs that depend on each rule's i graph[bgcolor=white, margin=0]; node[shape=box, style=rounded, fontname=sans, fontsize=10, penwidth=2]; edge[penwidth=2, color=grey]; - 0[label = "solve_network", color = "0.39 0.6 0.85", style="rounded"]; - 1[label = "prepare_network\nll: copt\nopts: Co2L-24H", color = "0.29 0.6 0.85", style="rounded"]; - 2[label = "add_extra_components", color = "0.28 0.6 0.85", style="rounded"]; - 3[label = "cluster_network\nclusters: 6", color = "0.19 0.6 0.85", style="rounded"]; - 4[label = "simplify_network\nsimpl: ", color = "0.01 0.6 0.85", style="rounded"]; - 5[label = "add_electricity", color = "0.49 0.6 0.85", style="rounded"]; - 6[label = "build_renewable_profiles\ntechnology: solar", color = "0.21 0.6 0.85", style="rounded"]; - 7[label = "base_network", color = "0.27 0.6 0.85", style="rounded"]; - 8[label = "build_shapes", color = "0.26 0.6 0.85", style="rounded"]; - 9[label = "retrieve_databundle", color = "0.59 0.6 0.85", style="rounded"]; - 10[label = "retrieve_natura_raster", color = "0.47 0.6 0.85", style="rounded"]; - 11[label = "build_bus_regions", color = "0.13 0.6 0.85", style="rounded"]; - 12[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.36 0.6 0.85", style="rounded,dashed"]; - 13[label = "build_renewable_profiles\ntechnology: onwind", color = "0.21 0.6 0.85", style="rounded"]; - 14[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.21 0.6 0.85", style="rounded"]; - 15[label = "build_ship_raster", color = "0.00 0.6 0.85", style="rounded"]; - 16[label = "retrieve_ship_raster", color = "0.51 0.6 0.85", style="rounded,dashed"]; - 17[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.21 0.6 0.85", style="rounded"]; - 18[label = "build_line_rating", color = "0.05 0.6 0.85", style="rounded"]; - 19[label = "retrieve_cost_data\nyear: 2030", color = "0.15 0.6 0.85", style="rounded"]; - 20[label = "build_powerplants", color = "0.54 0.6 0.85", style="rounded"]; - 21[label = "build_electricity_demand", color = "0.52 0.6 0.85", style="rounded"]; - 22[label = "retrieve_electricity_demand", color = "0.22 0.6 0.85", style="rounded"]; - 23[label = "copy_config", color = "0.44 0.6 0.85", style="rounded"]; + 0[label = "solve_network", color = "0.24 0.6 0.85", style="rounded"]; + 1[label = "prepare_network\nll: vopt\nopts: Co2L-3H", color = "0.10 0.6 0.85", style="rounded"]; + 2[label = "add_extra_components", color = "0.33 0.6 0.85", style="rounded"]; + 3[label = "cluster_network\nclusters: 128", color = "0.59 0.6 0.85", style="rounded"]; + 4[label = "simplify_network\nsimpl: ", color = "0.18 0.6 0.85", style="rounded"]; + 5[label = "add_electricity", color = "0.48 0.6 0.85", style="rounded"]; + 6[label = "build_renewable_profiles\ntechnology: solar", color = "0.29 0.6 0.85", style="rounded"]; + 7[label = "base_network", color = "0.30 0.6 0.85", style="rounded"]; + 8[label = "build_shapes", color = "0.61 0.6 0.85", style="rounded"]; + 9[label = "retrieve_databundle", color = "0.06 0.6 0.85", style="rounded"]; + 10[label = "retrieve_natura_raster", color = "0.03 0.6 0.85", style="rounded"]; + 11[label = "retrieve_cutout\ncutout: europe-2013-sarah", color = "0.50 0.6 0.85", style="rounded"]; + 12[label = "build_renewable_profiles\ntechnology: onwind", color = "0.29 0.6 0.85", style="rounded"]; + 13[label = "retrieve_cutout\ncutout: europe-2013-era5", color = "0.50 0.6 0.85", style="rounded"]; + 14[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.29 0.6 0.85", style="rounded"]; + 15[label = "build_ship_raster", color = "0.16 0.6 0.85", style="rounded"]; + 16[label = "retrieve_ship_raster", color = "0.53 0.6 0.85", style="rounded"]; + 17[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.29 0.6 0.85", style="rounded"]; + 18[label = "build_hydro_profile", color = "0.47 0.6 0.85", style="rounded"]; + 19[label = "retrieve_cost_data\nyear: 2030", color = "0.21 0.6 0.85", style="rounded"]; + 20[label = "build_powerplants", color = "0.56 0.6 0.85", style="rounded"]; + 21[label = "build_electricity_demand", color = "0.54 0.6 0.85", style="rounded"]; + 22[label = "retrieve_electricity_demand", color = "0.34 0.6 0.85", style="rounded"]; + 23[label = "retrieve_synthetic_electricity_demand", color = "0.65 0.6 0.85", style="rounded"]; 1 -> 0 - 23 -> 0 2 -> 1 19 -> 1 3 -> 2 @@ -167,15 +166,14 @@ This triggers a workflow of multiple preceding jobs that depend on each rule's i 19 -> 3 5 -> 4 19 -> 4 - 11 -> 4 + 7 -> 4 6 -> 5 - 13 -> 5 + 12 -> 5 14 -> 5 17 -> 5 - 7 -> 5 18 -> 5 + 7 -> 5 19 -> 5 - 11 -> 5 20 -> 5 9 -> 5 21 -> 5 @@ -185,37 +183,32 @@ This triggers a workflow of multiple preceding jobs that depend on each rule's i 10 -> 6 8 -> 6 11 -> 6 - 12 -> 6 8 -> 7 9 -> 8 - 8 -> 11 - 7 -> 11 - 7 -> 13 - 9 -> 13 - 10 -> 13 - 8 -> 13 - 11 -> 13 - 12 -> 13 + 7 -> 12 + 9 -> 12 + 10 -> 12 + 8 -> 12 + 13 -> 12 7 -> 14 9 -> 14 10 -> 14 15 -> 14 8 -> 14 - 11 -> 14 - 12 -> 14 + 13 -> 14 16 -> 15 - 12 -> 15 + 13 -> 15 7 -> 17 9 -> 17 10 -> 17 15 -> 17 8 -> 17 - 11 -> 17 - 12 -> 17 - 7 -> 18 - 12 -> 18 + 13 -> 17 + 8 -> 18 + 13 -> 18 7 -> 20 22 -> 21 + 23 -> 21 } | @@ -226,28 +219,25 @@ In the terminal, this will show up as a list of jobs to be run: Building DAG of jobs... Job stats: - job count - --------------------------- ------- - add_electricity 1 - add_extra_components 1 - base_network 1 - build_bus_regions 1 - build_electricity_demand 1 - build_line_rating 1 - build_powerplants 1 - build_renewable_profiles 4 - build_shapes 1 - build_ship_raster 1 - cluster_network 1 - copy_config 1 - prepare_network 1 - retrieve_cost_data 1 - retrieve_databundle 1 - retrieve_electricity_demand 1 - retrieve_natura_raster 1 - simplify_network 1 - solve_network 1 - total 22 + job count + ------------------------------------- ------- + add_electricity 1 + add_extra_components 1 + build_line_rating 1 + build_renewable_profiles 4 + build_ship_raster 1 + cluster_network 1 + prepare_network 1 + retrieve_cost_data 1 + retrieve_cutout 1 + retrieve_databundle 1 + retrieve_electricity_demand 1 + retrieve_natura_raster 1 + retrieve_ship_raster 1 + retrieve_synthetic_electricity_demand 1 + simplify_network 1 + solve_network 1 + total 19 ``snakemake`` then runs these jobs in the correct order. diff --git a/doc/tutorial_sector.rst b/doc/tutorial_sector.rst index a1556150..d6fafa69 100644 --- a/doc/tutorial_sector.rst +++ b/doc/tutorial_sector.rst @@ -71,18 +71,16 @@ which were already included in the electricity-only tutorial: add_electricity 1 add_extra_components 1 all 1 - base_network 1 build_ammonia_production 1 build_biomass_potentials 1 - build_bus_regions 1 build_clustered_population_layouts 1 build_cop_profiles 1 build_daily_heat_demand 1 build_district_heat_share 1 - build_electricity_demand 1 build_energy_totals 1 build_gas_input_locations 1 build_gas_network 1 + build_heat_totals 1 build_hourly_heat_demand 1 build_industrial_distribution_key 1 build_industrial_energy_demand_per_country_today 1 @@ -94,19 +92,17 @@ which were already included in the electricity-only tutorial: build_industry_sector_ratios 1 build_industry_sector_ratios_intermediate 1 build_population_layouts 1 - build_population_weighted_energy_totals 1 - build_powerplants 1 + build_population_weighted_energy_totals 2 build_renewable_profiles 4 build_salt_cavern_potentials 1 - build_shapes 1 build_ship_raster 1 build_shipping_demand 1 build_simplified_population_layouts 1 + build_solar_thermal_profiles 3 build_temperature_profiles 3 build_transport_demand 1 cluster_gas_network 1 cluster_network 1 - copy_config 1 make_summary 1 plot_gas_network 1 plot_hydrogen_network 1 @@ -116,14 +112,18 @@ which were already included in the electricity-only tutorial: prepare_network 1 prepare_sector_network 1 retrieve_cost_data 1 + retrieve_cutout 1 retrieve_databundle 1 retrieve_electricity_demand 1 + retrieve_eurostat_data 1 retrieve_gas_infrastructure_data 1 retrieve_natura_raster 1 retrieve_sector_databundle 1 + retrieve_ship_raster 1 + retrieve_synthetic_electricity_demand 1 simplify_network 1 solve_sector_network 1 - total 60 + total 63 This covers the retrieval of additional raw data from online resources and preprocessing data about the transport, industry, and heating sectors as well as @@ -142,234 +142,252 @@ successfully. graph[bgcolor=white, margin=0]; node[shape=box, style=rounded, fontname=sans, fontsize=10, penwidth=2]; edge[penwidth=2, color=grey]; - 0[label = "all", color = "0.55 0.6 0.85", style="rounded"]; - 1[label = "plot_summary", color = "0.31 0.6 0.85", style="rounded"]; - 2[label = "make_summary", color = "0.37 0.6 0.85", style="rounded"]; - 3[label = "plot_power_network_clustered", color = "0.50 0.6 0.85", style="rounded"]; - 4[label = "cluster_network\nclusters: 5", color = "0.62 0.6 0.85", style="rounded"]; - 5[label = "simplify_network\nsimpl: ", color = "0.18 0.6 0.85", style="rounded"]; - 6[label = "add_electricity", color = "0.33 0.6 0.85", style="rounded"]; - 7[label = "build_renewable_profiles\ntechnology: solar", color = "0.20 0.6 0.85", style="rounded"]; - 8[label = "base_network", color = "0.31 0.6 0.85", style="rounded"]; - 9[label = "build_shapes", color = "0.36 0.6 0.85", style="rounded"]; - 10[label = "retrieve_databundle", color = "0.29 0.6 0.85", style="rounded"]; - 11[label = "retrieve_natura_raster", color = "0.01 0.6 0.85", style="rounded"]; - 12[label = "build_bus_regions", color = "0.10 0.6 0.85", style="rounded"]; - 13[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.37 0.6 0.85", style="rounded,dashed"]; - 14[label = "build_renewable_profiles\ntechnology: onwind", color = "0.20 0.6 0.85", style="rounded"]; - 15[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.20 0.6 0.85", style="rounded"]; - 16[label = "build_ship_raster", color = "0.64 0.6 0.85", style="rounded"]; - 17[label = "retrieve_ship_raster", color = "0.64 0.6 0.85", style="rounded,dashed"]; - 18[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.20 0.6 0.85", style="rounded"]; - 19[label = "retrieve_cost_data\nyear: 2030", color = "0.12 0.6 0.85", style="rounded"]; - 20[label = "build_powerplants", color = "0.23 0.6 0.85", style="rounded"]; - 21[label = "build_electricity_demand", color = "0.54 0.6 0.85", style="rounded"]; - 22[label = "retrieve_electricity_demand", color = "0.07 0.6 0.85", style="rounded"]; - 23[label = "solve_sector_network", color = "0.41 0.6 0.85", style="rounded"]; - 24[label = "prepare_sector_network\nsector_opts: CO2L0-24h-T-H-B-I-A-dist1", color = "0.22 0.6 0.85", style="rounded"]; - 25[label = "cluster_gas_network", color = "0.24 0.6 0.85", style="rounded"]; - 26[label = "build_gas_network", color = "0.10 0.6 0.85", style="rounded"]; - 27[label = "retrieve_gas_infrastructure_data", color = "0.17 0.6 0.85", style="rounded"]; - 28[label = "build_gas_input_locations", color = "0.16 0.6 0.85", style="rounded"]; - 29[label = "prepare_network\nll: v1.5\nopts: ", color = "0.49 0.6 0.85", style="rounded"]; - 30[label = "add_extra_components", color = "0.14 0.6 0.85", style="rounded"]; - 31[label = "build_energy_totals", color = "0.39 0.6 0.85", style="rounded"]; - 32[label = "retrieve_sector_databundle", color = "0.58 0.6 0.85", style="rounded"]; - 33[label = "build_population_weighted_energy_totals", color = "0.56 0.6 0.85", style="rounded"]; - 34[label = "build_clustered_population_layouts", color = "0.49 0.6 0.85", style="rounded"]; - 35[label = "build_population_layouts", color = "0.06 0.6 0.85", style="rounded"]; - 36[label = "build_shipping_demand", color = "0.47 0.6 0.85", style="rounded"]; - 37[label = "build_transport_demand", color = "0.45 0.6 0.85", style="rounded"]; - 38[label = "build_temperature_profiles\nscope: total", color = "0.04 0.6 0.85", style="rounded"]; - 39[label = "build_biomass_potentials\nplanning_horizons: 2030", color = "0.11 0.6 0.85", style="rounded"]; - 40[label = "build_salt_cavern_potentials", color = "0.15 0.6 0.85", style="rounded"]; - 41[label = "build_simplified_population_layouts", color = "0.46 0.6 0.85", style="rounded"]; - 42[label = "build_industrial_energy_demand_per_node", color = "0.63 0.6 0.85", style="rounded"]; - 43[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2030", color = "0.07 0.6 0.85", style="rounded"]; - 44[label = "build_industry_sector_ratios", color = "0.59 0.6 0.85", style="rounded"]; - 45[label = "build_ammonia_production", color = "0.04 0.6 0.85", style="rounded"]; - 46[label = "build_industrial_energy_demand_per_country_today", color = "0.44 0.6 0.85", style="rounded"]; - 47[label = "build_industrial_production_per_country", color = "0.34 0.6 0.85", style="rounded"]; - 48[label = "build_industrial_production_per_node", color = "0.26 0.6 0.85", style="rounded"]; - 49[label = "build_industrial_distribution_key", color = "0.13 0.6 0.85", style="rounded"]; - 50[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2030", color = "0.32 0.6 0.85", style="rounded"]; - 51[label = "build_industrial_energy_demand_per_node_today", color = "0.48 0.6 0.85", style="rounded"]; - 52[label = "build_hourly_heat_demand", color = "0.28 0.6 0.85", style="rounded"]; - 53[label = "build_daily_heat_demand\nscope: total", color = "0.28 0.6 0.85", style="rounded"]; - 54[label = "build_district_heat_share\nplanning_horizons: 2030", color = "0.52 0.6 0.85", style="rounded"]; - 55[label = "build_temperature_profiles\nscope: rural", color = "0.04 0.6 0.85", style="rounded"]; - 56[label = "build_temperature_profiles\nscope: urban", color = "0.04 0.6 0.85", style="rounded"]; - 57[label = "build_cop_profiles", color = "0.38 0.6 0.85", style="rounded"]; - 58[label = "copy_config", color = "0.19 0.6 0.85", style="rounded"]; - 59[label = "plot_power_network", color = "0.60 0.6 0.85", style="rounded"]; - 60[label = "plot_hydrogen_network", color = "0.27 0.6 0.85", style="rounded"]; - 61[label = "plot_gas_network", color = "0.08 0.6 0.85", style="rounded"]; + 0[label = "all", color = "0.66 0.6 0.85", style="rounded"]; + 1[label = "plot_summary", color = "0.20 0.6 0.85", style="rounded"]; + 2[label = "make_summary", color = "0.02 0.6 0.85", style="rounded"]; + 3[label = "solve_sector_network", color = "0.11 0.6 0.85", style="rounded"]; + 4[label = "prepare_sector_network\nsector_opts: CO2L0-24h-T-H-B-I-A-dist1", color = "0.22 0.6 0.85", style="rounded"]; + 5[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.26 0.6 0.85", style="rounded"]; + 6[label = "base_network", color = "0.53 0.6 0.85", style="rounded"]; + 7[label = "build_shapes", color = "0.04 0.6 0.85", style="rounded"]; + 8[label = "retrieve_databundle", color = "0.49 0.6 0.85", style="rounded"]; + 9[label = "retrieve_natura_raster", color = "0.46 0.6 0.85", style="rounded"]; + 10[label = "build_ship_raster", color = "0.29 0.6 0.85", style="rounded"]; + 11[label = "retrieve_ship_raster", color = "0.42 0.6 0.85", style="rounded"]; + 12[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.27 0.6 0.85", style="rounded"]; + 13[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.26 0.6 0.85", style="rounded"]; + 14[label = "cluster_gas_network", color = "0.48 0.6 0.85", style="rounded"]; + 15[label = "build_gas_network", color = "0.27 0.6 0.85", style="rounded"]; + 16[label = "retrieve_gas_infrastructure_data", color = "0.38 0.6 0.85", style="rounded"]; + 17[label = "cluster_network\nclusters: 5", color = "0.58 0.6 0.85", style="rounded"]; + 18[label = "simplify_network\nsimpl: ", color = "0.55 0.6 0.85", style="rounded"]; + 19[label = "add_electricity", color = "0.37 0.6 0.85", style="rounded"]; + 20[label = "build_renewable_profiles\ntechnology: solar", color = "0.26 0.6 0.85", style="rounded"]; + 21[label = "build_renewable_profiles\ntechnology: onwind", color = "0.26 0.6 0.85", style="rounded"]; + 22[label = "retrieve_cost_data\nyear: 2030", color = "0.14 0.6 0.85", style="rounded"]; + 23[label = "build_powerplants", color = "0.64 0.6 0.85", style="rounded"]; + 24[label = "build_electricity_demand", color = "0.61 0.6 0.85", style="rounded"]; + 25[label = "retrieve_electricity_demand", color = "0.08 0.6 0.85", style="rounded"]; + 26[label = "retrieve_synthetic_electricity_demand", color = "0.36 0.6 0.85", style="rounded"]; + 27[label = "build_gas_input_locations", color = "0.44 0.6 0.85", style="rounded"]; + 28[label = "prepare_network\nll: v1.5\nopts: ", color = "0.25 0.6 0.85", style="rounded"]; + 29[label = "add_extra_components", color = "0.39 0.6 0.85", style="rounded"]; + 30[label = "retrieve_eurostat_data", color = "0.20 0.6 0.85", style="rounded"]; + 31[label = "build_population_weighted_energy_totals\nkind: energy", color = "0.58 0.6 0.85", style="rounded"]; + 32[label = "build_energy_totals", color = "0.44 0.6 0.85", style="rounded"]; + 33[label = "retrieve_sector_databundle", color = "0.60 0.6 0.85", style="rounded"]; + 34[label = "build_clustered_population_layouts", color = "0.46 0.6 0.85", style="rounded"]; + 35[label = "build_population_layouts", color = "0.43 0.6 0.85", style="rounded"]; + 36[label = "build_population_weighted_energy_totals\nkind: heat", color = "0.58 0.6 0.85", style="rounded"]; + 37[label = "build_heat_totals", color = "0.11 0.6 0.85", style="rounded"]; + 38[label = "build_shipping_demand", color = "0.16 0.6 0.85", style="rounded"]; + 39[label = "build_transport_demand", color = "0.04 0.6 0.85", style="rounded"]; + 40[label = "build_temperature_profiles\nscope: total", color = "0.28 0.6 0.85", style="rounded"]; + 41[label = "build_biomass_potentials\nplanning_horizons: 2030", color = "0.07 0.6 0.85", style="rounded"]; + 42[label = "build_salt_cavern_potentials", color = "0.47 0.6 0.85", style="rounded"]; + 43[label = "build_simplified_population_layouts", color = "0.29 0.6 0.85", style="rounded"]; + 44[label = "build_industrial_energy_demand_per_node", color = "0.39 0.6 0.85", style="rounded"]; + 45[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2030", color = "0.57 0.6 0.85", style="rounded"]; + 46[label = "build_industry_sector_ratios", color = "0.55 0.6 0.85", style="rounded"]; + 47[label = "build_ammonia_production", color = "0.00 0.6 0.85", style="rounded"]; + 48[label = "build_industrial_energy_demand_per_country_today", color = "0.52 0.6 0.85", style="rounded"]; + 49[label = "build_industrial_production_per_country", color = "0.19 0.6 0.85", style="rounded"]; + 50[label = "build_industrial_production_per_node", color = "0.21 0.6 0.85", style="rounded"]; + 51[label = "build_industrial_distribution_key", color = "0.10 0.6 0.85", style="rounded"]; + 52[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2030", color = "0.63 0.6 0.85", style="rounded"]; + 53[label = "build_industrial_energy_demand_per_node_today", color = "0.18 0.6 0.85", style="rounded"]; + 54[label = "build_hourly_heat_demand", color = "0.13 0.6 0.85", style="rounded"]; + 55[label = "build_daily_heat_demand\nscope: total", color = "0.22 0.6 0.85", style="rounded"]; + 56[label = "build_district_heat_share\nplanning_horizons: 2030", color = "0.34 0.6 0.85", style="rounded"]; + 57[label = "build_temperature_profiles\nscope: rural", color = "0.28 0.6 0.85", style="rounded"]; + 58[label = "build_temperature_profiles\nscope: urban", color = "0.28 0.6 0.85", style="rounded"]; + 59[label = "build_cop_profiles", color = "0.65 0.6 0.85", style="rounded"]; + 60[label = "build_solar_thermal_profiles\nscope: total", color = "0.54 0.6 0.85", style="rounded"]; + 61[label = "build_solar_thermal_profiles\nscope: urban", color = "0.54 0.6 0.85", style="rounded"]; + 62[label = "build_solar_thermal_profiles\nscope: rural", color = "0.54 0.6 0.85", style="rounded"]; + 63[label = "plot_power_network_clustered", color = "0.15 0.6 0.85", style="rounded"]; + 64[label = "plot_power_network", color = "0.56 0.6 0.85", style="rounded"]; + 65[label = "plot_hydrogen_network", color = "0.60 0.6 0.85", style="rounded"]; + 66[label = "plot_gas_network", color = "0.53 0.6 0.85", style="rounded"]; 1 -> 0 2 -> 1 - 32 -> 1 + 30 -> 1 + 33 -> 1 3 -> 2 - 23 -> 2 - 19 -> 2 - 59 -> 2 - 60 -> 2 - 61 -> 2 + 22 -> 2 + 63 -> 2 + 64 -> 2 + 65 -> 2 + 66 -> 2 4 -> 3 5 -> 4 - 19 -> 4 + 13 -> 4 + 14 -> 4 + 27 -> 4 + 28 -> 4 + 30 -> 4 + 31 -> 4 + 36 -> 4 + 38 -> 4 + 39 -> 4 + 32 -> 4 + 33 -> 4 + 41 -> 4 + 22 -> 4 + 42 -> 4 + 18 -> 4 + 17 -> 4 + 34 -> 4 + 43 -> 4 + 44 -> 4 + 54 -> 4 + 56 -> 4 + 40 -> 4 + 57 -> 4 + 58 -> 4 + 59 -> 4 + 60 -> 4 + 61 -> 4 + 62 -> 4 6 -> 5 - 19 -> 5 + 8 -> 5 + 9 -> 5 + 10 -> 5 + 7 -> 5 12 -> 5 7 -> 6 - 14 -> 6 - 15 -> 6 - 18 -> 6 - 8 -> 6 - 19 -> 6 - 12 -> 6 - 20 -> 6 - 10 -> 6 - 21 -> 6 - 9 -> 6 8 -> 7 - 10 -> 7 - 11 -> 7 - 9 -> 7 - 12 -> 7 - 13 -> 7 - 9 -> 8 - 10 -> 9 - 9 -> 12 - 8 -> 12 - 8 -> 14 - 10 -> 14 - 11 -> 14 - 9 -> 14 - 12 -> 14 - 13 -> 14 - 8 -> 15 - 10 -> 15 - 11 -> 15 + 11 -> 10 + 12 -> 10 + 6 -> 13 + 8 -> 13 + 9 -> 13 + 10 -> 13 + 7 -> 13 + 12 -> 13 + 15 -> 14 + 17 -> 14 16 -> 15 - 9 -> 15 - 12 -> 15 - 13 -> 15 - 17 -> 16 - 13 -> 16 - 8 -> 18 - 10 -> 18 - 11 -> 18 - 16 -> 18 - 9 -> 18 - 12 -> 18 - 13 -> 18 + 18 -> 17 + 22 -> 17 + 19 -> 18 + 22 -> 18 + 6 -> 18 + 20 -> 19 + 21 -> 19 + 5 -> 19 + 13 -> 19 + 6 -> 19 + 22 -> 19 + 23 -> 19 + 8 -> 19 + 24 -> 19 + 7 -> 19 + 6 -> 20 8 -> 20 - 22 -> 21 - 24 -> 23 - 58 -> 23 + 9 -> 20 + 7 -> 20 + 12 -> 20 + 6 -> 21 + 8 -> 21 + 9 -> 21 + 7 -> 21 + 12 -> 21 + 6 -> 23 25 -> 24 - 28 -> 24 - 29 -> 24 - 31 -> 24 - 32 -> 24 - 33 -> 24 - 36 -> 24 - 37 -> 24 - 39 -> 24 - 19 -> 24 - 15 -> 24 - 18 -> 24 - 40 -> 24 - 5 -> 24 - 4 -> 24 - 34 -> 24 - 41 -> 24 - 42 -> 24 - 52 -> 24 - 54 -> 24 - 38 -> 24 - 55 -> 24 - 56 -> 24 - 57 -> 24 - 26 -> 25 - 4 -> 25 - 27 -> 26 - 27 -> 28 - 4 -> 28 - 30 -> 29 - 19 -> 29 - 4 -> 30 - 19 -> 30 - 9 -> 31 + 26 -> 24 + 16 -> 27 + 17 -> 27 + 29 -> 28 + 22 -> 28 + 17 -> 29 + 22 -> 29 32 -> 31 - 31 -> 33 - 34 -> 33 + 34 -> 31 + 7 -> 32 + 33 -> 32 + 30 -> 32 35 -> 34 - 4 -> 34 - 13 -> 34 - 9 -> 35 - 13 -> 35 - 9 -> 36 - 4 -> 36 - 31 -> 36 - 34 -> 37 - 33 -> 37 - 31 -> 37 + 17 -> 34 + 12 -> 34 + 7 -> 35 + 12 -> 35 + 37 -> 36 + 34 -> 36 32 -> 37 - 38 -> 37 - 35 -> 38 - 4 -> 38 - 13 -> 38 + 7 -> 38 + 17 -> 38 + 32 -> 38 + 34 -> 39 + 31 -> 39 32 -> 39 - 4 -> 39 - 10 -> 39 - 9 -> 39 - 32 -> 40 - 4 -> 40 - 35 -> 41 - 5 -> 41 - 13 -> 41 - 43 -> 42 - 48 -> 42 - 51 -> 42 - 44 -> 43 - 46 -> 43 - 47 -> 43 + 33 -> 39 + 40 -> 39 + 35 -> 40 + 17 -> 40 + 12 -> 40 + 33 -> 41 + 17 -> 41 + 8 -> 41 + 7 -> 41 + 33 -> 42 + 17 -> 42 + 35 -> 43 + 18 -> 43 + 12 -> 43 45 -> 44 - 32 -> 44 - 32 -> 45 - 32 -> 46 + 50 -> 44 + 53 -> 44 + 46 -> 45 + 48 -> 45 + 49 -> 45 47 -> 46 - 45 -> 47 - 32 -> 47 + 33 -> 46 + 33 -> 47 + 33 -> 48 49 -> 48 - 50 -> 48 - 4 -> 49 - 34 -> 49 - 32 -> 49 - 47 -> 50 - 49 -> 51 - 46 -> 51 - 53 -> 52 - 35 -> 53 - 4 -> 53 - 13 -> 53 - 31 -> 54 - 34 -> 54 + 47 -> 49 + 33 -> 49 + 30 -> 49 + 51 -> 50 + 52 -> 50 + 17 -> 51 + 34 -> 51 + 33 -> 51 + 49 -> 52 + 51 -> 53 + 48 -> 53 + 55 -> 54 35 -> 55 - 4 -> 55 - 13 -> 55 - 35 -> 56 - 4 -> 56 - 13 -> 56 - 38 -> 57 - 55 -> 57 - 56 -> 57 - 23 -> 59 - 4 -> 59 - 23 -> 60 - 4 -> 60 - 23 -> 61 - 4 -> 61 + 17 -> 55 + 12 -> 55 + 32 -> 56 + 34 -> 56 + 35 -> 57 + 17 -> 57 + 12 -> 57 + 35 -> 58 + 17 -> 58 + 12 -> 58 + 40 -> 59 + 57 -> 59 + 58 -> 59 + 35 -> 60 + 17 -> 60 + 12 -> 60 + 35 -> 61 + 17 -> 61 + 12 -> 61 + 35 -> 62 + 17 -> 62 + 12 -> 62 + 17 -> 63 + 3 -> 64 + 17 -> 64 + 3 -> 65 + 17 -> 65 + 3 -> 66 + 17 -> 66 } | @@ -429,386 +447,412 @@ workflow: graph[bgcolor=white, margin=0]; node[shape=box, style=rounded, fontname=sans, fontsize=10, penwidth=2]; edge[penwidth=2, color=grey]; - 0[label = "all", color = "0.46 0.6 0.85", style="rounded"]; - 1[label = "plot_summary", color = "0.40 0.6 0.85", style="rounded"]; - 2[label = "make_summary", color = "0.59 0.6 0.85", style="rounded"]; - 3[label = "plot_power_network_clustered", color = "0.17 0.6 0.85", style="rounded"]; - 4[label = "cluster_network\nclusters: 5", color = "0.49 0.6 0.85", style="rounded"]; - 5[label = "simplify_network\nsimpl: ", color = "0.16 0.6 0.85", style="rounded"]; - 6[label = "add_electricity", color = "0.32 0.6 0.85", style="rounded"]; - 7[label = "build_renewable_profiles\ntechnology: solar", color = "0.63 0.6 0.85", style="rounded"]; - 8[label = "base_network", color = "0.12 0.6 0.85", style="rounded"]; - 9[label = "build_shapes", color = "0.23 0.6 0.85", style="rounded"]; - 10[label = "retrieve_databundle", color = "0.61 0.6 0.85", style="rounded"]; - 11[label = "retrieve_natura_raster", color = "0.50 0.6 0.85", style="rounded"]; - 12[label = "build_bus_regions", color = "0.51 0.6 0.85", style="rounded"]; - 13[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.37 0.6 0.85", style="rounded,dashed"]; - 14[label = "build_renewable_profiles\ntechnology: onwind", color = "0.63 0.6 0.85", style="rounded"]; - 15[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.63 0.6 0.85", style="rounded"]; - 16[label = "build_ship_raster", color = "0.24 0.6 0.85", style="rounded"]; - 17[label = "retrieve_ship_raster", color = "0.14 0.6 0.85", style="rounded,dashed"]; - 18[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.63 0.6 0.85", style="rounded"]; - 19[label = "retrieve_cost_data\nyear: 2030", color = "0.04 0.6 0.85", style="rounded"]; - 20[label = "build_powerplants", color = "0.58 0.6 0.85", style="rounded"]; - 21[label = "build_electricity_demand", color = "0.04 0.6 0.85", style="rounded"]; - 22[label = "retrieve_electricity_demand", color = "0.62 0.6 0.85", style="rounded"]; - 23[label = "solve_sector_network_myopic", color = "0.30 0.6 0.85", style="rounded"]; - 24[label = "add_existing_baseyear", color = "0.34 0.6 0.85", style="rounded"]; - 25[label = "prepare_sector_network\nsector_opts: 24h-T-H-B-I-A-dist1", color = "0.42 0.6 0.85", style="rounded"]; - 26[label = "cluster_gas_network", color = "0.39 0.6 0.85", style="rounded"]; - 27[label = "build_gas_network", color = "0.59 0.6 0.85", style="rounded"]; - 28[label = "retrieve_gas_infrastructure_data", color = "0.15 0.6 0.85", style="rounded"]; - 29[label = "build_gas_input_locations", color = "0.07 0.6 0.85", style="rounded"]; - 30[label = "prepare_network\nll: v1.5\nopts: ", color = "0.56 0.6 0.85", style="rounded"]; - 31[label = "add_extra_components", color = "0.11 0.6 0.85", style="rounded"]; - 32[label = "build_energy_totals", color = "0.18 0.6 0.85", style="rounded"]; - 33[label = "retrieve_sector_databundle", color = "0.06 0.6 0.85", style="rounded"]; - 34[label = "build_population_weighted_energy_totals", color = "0.03 0.6 0.85", style="rounded"]; - 35[label = "build_clustered_population_layouts", color = "0.25 0.6 0.85", style="rounded"]; - 36[label = "build_population_layouts", color = "0.57 0.6 0.85", style="rounded"]; - 37[label = "build_shipping_demand", color = "0.45 0.6 0.85", style="rounded"]; - 38[label = "build_transport_demand", color = "0.18 0.6 0.85", style="rounded"]; - 39[label = "build_temperature_profiles\nscope: total", color = "0.54 0.6 0.85", style="rounded"]; - 40[label = "build_biomass_potentials\nplanning_horizons: 2030", color = "0.41 0.6 0.85", style="rounded"]; - 41[label = "build_salt_cavern_potentials", color = "0.02 0.6 0.85", style="rounded"]; - 42[label = "build_simplified_population_layouts", color = "0.15 0.6 0.85", style="rounded"]; - 43[label = "build_industrial_energy_demand_per_node", color = "0.47 0.6 0.85", style="rounded"]; - 44[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2030", color = "0.31 0.6 0.85", style="rounded"]; - 45[label = "build_industry_sector_ratios", color = "0.48 0.6 0.85", style="rounded"]; - 46[label = "build_ammonia_production", color = "0.00 0.6 0.85", style="rounded"]; - 47[label = "build_industrial_energy_demand_per_country_today", color = "0.32 0.6 0.85", style="rounded"]; - 48[label = "build_industrial_production_per_country", color = "0.60 0.6 0.85", style="rounded"]; - 49[label = "build_industrial_production_per_node", color = "0.05 0.6 0.85", style="rounded"]; - 50[label = "build_industrial_distribution_key", color = "0.21 0.6 0.85", style="rounded"]; - 51[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2030", color = "0.33 0.6 0.85", style="rounded"]; - 52[label = "build_industrial_energy_demand_per_node_today", color = "0.62 0.6 0.85", style="rounded"]; - 53[label = "build_hourly_heat_demand", color = "0.28 0.6 0.85", style="rounded"]; - 54[label = "build_daily_heat_demand\nscope: total", color = "0.22 0.6 0.85", style="rounded"]; - 55[label = "build_district_heat_share\nplanning_horizons: 2030", color = "0.21 0.6 0.85", style="rounded"]; - 56[label = "build_temperature_profiles\nscope: rural", color = "0.54 0.6 0.85", style="rounded"]; - 57[label = "build_temperature_profiles\nscope: urban", color = "0.54 0.6 0.85", style="rounded"]; - 58[label = "build_cop_profiles", color = "0.52 0.6 0.85", style="rounded"]; - 59[label = "build_existing_heating_distribution", color = "0.09 0.6 0.85", style="rounded"]; - 60[label = "copy_config", color = "0.42 0.6 0.85", style="rounded"]; - 61[label = "solve_sector_network_myopic", color = "0.30 0.6 0.85", style="rounded"]; - 62[label = "add_brownfield", color = "0.10 0.6 0.85", style="rounded"]; - 63[label = "prepare_sector_network\nsector_opts: 24h-T-H-B-I-A-dist1", color = "0.42 0.6 0.85", style="rounded"]; - 64[label = "build_biomass_potentials\nplanning_horizons: 2040", color = "0.41 0.6 0.85", style="rounded"]; - 65[label = "retrieve_cost_data\nyear: 2040", color = "0.04 0.6 0.85", style="rounded"]; - 66[label = "build_industrial_energy_demand_per_node", color = "0.47 0.6 0.85", style="rounded"]; - 67[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2040", color = "0.31 0.6 0.85", style="rounded"]; - 68[label = "build_industrial_production_per_node", color = "0.05 0.6 0.85", style="rounded"]; - 69[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2040", color = "0.33 0.6 0.85", style="rounded"]; - 70[label = "build_district_heat_share\nplanning_horizons: 2040", color = "0.21 0.6 0.85", style="rounded"]; - 71[label = "solve_sector_network_myopic", color = "0.30 0.6 0.85", style="rounded"]; - 72[label = "add_brownfield", color = "0.10 0.6 0.85", style="rounded"]; - 73[label = "prepare_sector_network\nsector_opts: 24h-T-H-B-I-A-dist1", color = "0.42 0.6 0.85", style="rounded"]; - 74[label = "build_biomass_potentials\nplanning_horizons: 2050", color = "0.41 0.6 0.85", style="rounded"]; - 75[label = "retrieve_cost_data\nyear: 2050", color = "0.04 0.6 0.85", style="rounded"]; - 76[label = "build_industrial_energy_demand_per_node", color = "0.47 0.6 0.85", style="rounded"]; - 77[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2050", color = "0.31 0.6 0.85", style="rounded"]; - 78[label = "build_industrial_production_per_node", color = "0.05 0.6 0.85", style="rounded"]; - 79[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2050", color = "0.33 0.6 0.85", style="rounded"]; - 80[label = "build_district_heat_share\nplanning_horizons: 2050", color = "0.21 0.6 0.85", style="rounded"]; - 81[label = "plot_power_network", color = "0.48 0.6 0.85", style="rounded"]; - 82[label = "plot_power_network", color = "0.48 0.6 0.85", style="rounded"]; - 83[label = "plot_power_network", color = "0.48 0.6 0.85", style="rounded"]; - 84[label = "plot_hydrogen_network", color = "0.37 0.6 0.85", style="rounded"]; - 85[label = "plot_hydrogen_network", color = "0.37 0.6 0.85", style="rounded"]; - 86[label = "plot_hydrogen_network", color = "0.37 0.6 0.85", style="rounded"]; + 0[label = "all", color = "0.20 0.6 0.85", style="rounded"]; + 1[label = "plot_summary", color = "0.55 0.6 0.85", style="rounded"]; + 2[label = "make_summary", color = "0.21 0.6 0.85", style="rounded"]; + 3[label = "solve_sector_network_myopic", color = "0.50 0.6 0.85", style="rounded"]; + 4[label = "add_existing_baseyear", color = "0.38 0.6 0.85", style="rounded"]; + 5[label = "prepare_sector_network\nsector_opts: 24h-T-H-B-I-A-dist1", color = "0.53 0.6 0.85", style="rounded"]; + 6[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.54 0.6 0.85", style="rounded"]; + 7[label = "base_network", color = "0.12 0.6 0.85", style="rounded"]; + 8[label = "build_shapes", color = "0.21 0.6 0.85", style="rounded"]; + 9[label = "retrieve_databundle", color = "0.41 0.6 0.85", style="rounded"]; + 10[label = "retrieve_natura_raster", color = "0.38 0.6 0.85", style="rounded"]; + 11[label = "build_ship_raster", color = "0.05 0.6 0.85", style="rounded"]; + 12[label = "retrieve_ship_raster", color = "0.25 0.6 0.85", style="rounded"]; + 13[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.23 0.6 0.85", style="rounded"]; + 14[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.54 0.6 0.85", style="rounded"]; + 15[label = "cluster_gas_network", color = "0.16 0.6 0.85", style="rounded"]; + 16[label = "build_gas_network", color = "0.26 0.6 0.85", style="rounded"]; + 17[label = "retrieve_gas_infrastructure_data", color = "0.04 0.6 0.85", style="rounded"]; + 18[label = "cluster_network\nclusters: 5", color = "0.10 0.6 0.85", style="rounded"]; + 19[label = "simplify_network\nsimpl: ", color = "0.02 0.6 0.85", style="rounded"]; + 20[label = "add_electricity", color = "0.56 0.6 0.85", style="rounded"]; + 21[label = "build_renewable_profiles\ntechnology: solar", color = "0.54 0.6 0.85", style="rounded"]; + 22[label = "build_renewable_profiles\ntechnology: onwind", color = "0.54 0.6 0.85", style="rounded"]; + 23[label = "retrieve_cost_data\nyear: 2030", color = "0.16 0.6 0.85", style="rounded"]; + 24[label = "build_powerplants", color = "0.63 0.6 0.85", style="rounded"]; + 25[label = "build_electricity_demand", color = "0.57 0.6 0.85", style="rounded"]; + 26[label = "retrieve_electricity_demand", color = "0.27 0.6 0.85", style="rounded"]; + 27[label = "retrieve_synthetic_electricity_demand", color = "0.58 0.6 0.85", style="rounded"]; + 28[label = "build_gas_input_locations", color = "0.28 0.6 0.85", style="rounded"]; + 29[label = "prepare_network\nll: v1.5\nopts: ", color = "0.14 0.6 0.85", style="rounded"]; + 30[label = "add_extra_components", color = "0.14 0.6 0.85", style="rounded"]; + 31[label = "retrieve_eurostat_data", color = "0.58 0.6 0.85", style="rounded"]; + 32[label = "build_population_weighted_energy_totals\nkind: energy", color = "0.36 0.6 0.85", style="rounded"]; + 33[label = "build_energy_totals", color = "0.65 0.6 0.85", style="rounded"]; + 34[label = "retrieve_sector_databundle", color = "0.46 0.6 0.85", style="rounded"]; + 35[label = "build_clustered_population_layouts", color = "0.52 0.6 0.85", style="rounded"]; + 36[label = "build_population_layouts", color = "0.13 0.6 0.85", style="rounded"]; + 37[label = "build_population_weighted_energy_totals\nkind: heat", color = "0.36 0.6 0.85", style="rounded"]; + 38[label = "build_heat_totals", color = "0.31 0.6 0.85", style="rounded"]; + 39[label = "build_shipping_demand", color = "0.01 0.6 0.85", style="rounded"]; + 40[label = "build_transport_demand", color = "0.51 0.6 0.85", style="rounded"]; + 41[label = "build_temperature_profiles\nscope: total", color = "0.00 0.6 0.85", style="rounded"]; + 42[label = "build_biomass_potentials\nplanning_horizons: 2030", color = "0.18 0.6 0.85", style="rounded"]; + 43[label = "build_salt_cavern_potentials", color = "0.25 0.6 0.85", style="rounded"]; + 44[label = "build_simplified_population_layouts", color = "0.27 0.6 0.85", style="rounded"]; + 45[label = "build_industrial_energy_demand_per_node", color = "0.30 0.6 0.85", style="rounded"]; + 46[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2030", color = "0.41 0.6 0.85", style="rounded"]; + 47[label = "build_industry_sector_ratios", color = "0.03 0.6 0.85", style="rounded"]; + 48[label = "build_ammonia_production", color = "0.37 0.6 0.85", style="rounded"]; + 49[label = "build_industrial_energy_demand_per_country_today", color = "0.10 0.6 0.85", style="rounded"]; + 50[label = "build_industrial_production_per_country", color = "0.03 0.6 0.85", style="rounded"]; + 51[label = "build_industrial_production_per_node", color = "0.63 0.6 0.85", style="rounded"]; + 52[label = "build_industrial_distribution_key", color = "0.17 0.6 0.85", style="rounded"]; + 53[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2030", color = "0.06 0.6 0.85", style="rounded"]; + 54[label = "build_industrial_energy_demand_per_node_today", color = "0.08 0.6 0.85", style="rounded"]; + 55[label = "build_hourly_heat_demand", color = "0.08 0.6 0.85", style="rounded"]; + 56[label = "build_daily_heat_demand\nscope: total", color = "0.60 0.6 0.85", style="rounded"]; + 57[label = "build_district_heat_share\nplanning_horizons: 2030", color = "0.32 0.6 0.85", style="rounded"]; + 58[label = "build_temperature_profiles\nscope: rural", color = "0.00 0.6 0.85", style="rounded"]; + 59[label = "build_temperature_profiles\nscope: urban", color = "0.00 0.6 0.85", style="rounded"]; + 60[label = "build_cop_profiles", color = "0.11 0.6 0.85", style="rounded"]; + 61[label = "build_solar_thermal_profiles\nscope: total", color = "0.01 0.6 0.85", style="rounded"]; + 62[label = "build_solar_thermal_profiles\nscope: urban", color = "0.01 0.6 0.85", style="rounded"]; + 63[label = "build_solar_thermal_profiles\nscope: rural", color = "0.01 0.6 0.85", style="rounded"]; + 64[label = "build_existing_heating_distribution", color = "0.40 0.6 0.85", style="rounded"]; + 65[label = "solve_sector_network_myopic", color = "0.50 0.6 0.85", style="rounded"]; + 66[label = "add_brownfield", color = "0.45 0.6 0.85", style="rounded"]; + 67[label = "prepare_sector_network\nsector_opts: 24h-T-H-B-I-A-dist1", color = "0.53 0.6 0.85", style="rounded"]; + 68[label = "build_biomass_potentials\nplanning_horizons: 2040", color = "0.18 0.6 0.85", style="rounded"]; + 69[label = "retrieve_cost_data\nyear: 2040", color = "0.16 0.6 0.85", style="rounded"]; + 70[label = "build_industrial_energy_demand_per_node", color = "0.30 0.6 0.85", style="rounded"]; + 71[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2040", color = "0.41 0.6 0.85", style="rounded"]; + 72[label = "build_industrial_production_per_node", color = "0.63 0.6 0.85", style="rounded"]; + 73[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2040", color = "0.06 0.6 0.85", style="rounded"]; + 74[label = "build_district_heat_share\nplanning_horizons: 2040", color = "0.32 0.6 0.85", style="rounded"]; + 75[label = "solve_sector_network_myopic", color = "0.50 0.6 0.85", style="rounded"]; + 76[label = "add_brownfield", color = "0.45 0.6 0.85", style="rounded"]; + 77[label = "prepare_sector_network\nsector_opts: 24h-T-H-B-I-A-dist1", color = "0.53 0.6 0.85", style="rounded"]; + 78[label = "build_biomass_potentials\nplanning_horizons: 2050", color = "0.18 0.6 0.85", style="rounded"]; + 79[label = "retrieve_cost_data\nyear: 2050", color = "0.16 0.6 0.85", style="rounded"]; + 80[label = "build_industrial_energy_demand_per_node", color = "0.30 0.6 0.85", style="rounded"]; + 81[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2050", color = "0.41 0.6 0.85", style="rounded"]; + 82[label = "build_industrial_production_per_node", color = "0.63 0.6 0.85", style="rounded"]; + 83[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2050", color = "0.06 0.6 0.85", style="rounded"]; + 84[label = "build_district_heat_share\nplanning_horizons: 2050", color = "0.32 0.6 0.85", style="rounded"]; + 85[label = "plot_power_network_clustered", color = "0.09 0.6 0.85", style="rounded"]; + 86[label = "plot_power_network", color = "0.43 0.6 0.85", style="rounded"]; + 87[label = "plot_power_network", color = "0.43 0.6 0.85", style="rounded"]; + 88[label = "plot_power_network", color = "0.43 0.6 0.85", style="rounded"]; + 89[label = "plot_hydrogen_network", color = "0.33 0.6 0.85", style="rounded"]; + 90[label = "plot_hydrogen_network", color = "0.33 0.6 0.85", style="rounded"]; + 91[label = "plot_hydrogen_network", color = "0.33 0.6 0.85", style="rounded"]; 1 -> 0 2 -> 1 - 33 -> 1 + 31 -> 1 + 34 -> 1 3 -> 2 + 65 -> 2 + 75 -> 2 23 -> 2 - 61 -> 2 - 71 -> 2 - 19 -> 2 - 81 -> 2 - 82 -> 2 - 83 -> 2 - 84 -> 2 85 -> 2 86 -> 2 + 87 -> 2 + 88 -> 2 + 89 -> 2 + 90 -> 2 + 91 -> 2 4 -> 3 + 23 -> 3 5 -> 4 + 24 -> 4 19 -> 4 + 18 -> 4 + 35 -> 4 + 23 -> 4 + 60 -> 4 + 64 -> 4 6 -> 5 + 14 -> 5 + 15 -> 5 + 28 -> 5 + 29 -> 5 + 31 -> 5 + 32 -> 5 + 37 -> 5 + 39 -> 5 + 40 -> 5 + 33 -> 5 + 34 -> 5 + 42 -> 5 + 23 -> 5 + 43 -> 5 19 -> 5 - 12 -> 5 + 18 -> 5 + 35 -> 5 + 44 -> 5 + 45 -> 5 + 55 -> 5 + 57 -> 5 + 41 -> 5 + 58 -> 5 + 59 -> 5 + 60 -> 5 + 61 -> 5 + 62 -> 5 + 63 -> 5 7 -> 6 - 14 -> 6 - 15 -> 6 - 18 -> 6 - 8 -> 6 - 19 -> 6 - 12 -> 6 - 20 -> 6 - 10 -> 6 - 21 -> 6 9 -> 6 + 10 -> 6 + 11 -> 6 + 8 -> 6 + 13 -> 6 8 -> 7 - 10 -> 7 - 11 -> 7 - 9 -> 7 - 12 -> 7 - 13 -> 7 9 -> 8 - 10 -> 9 - 9 -> 12 - 8 -> 12 - 8 -> 14 + 12 -> 11 + 13 -> 11 + 7 -> 14 + 9 -> 14 10 -> 14 11 -> 14 - 9 -> 14 - 12 -> 14 + 8 -> 14 13 -> 14 - 8 -> 15 - 10 -> 15 - 11 -> 15 16 -> 15 - 9 -> 15 - 12 -> 15 - 13 -> 15 + 18 -> 15 17 -> 16 - 13 -> 16 - 8 -> 18 - 10 -> 18 - 11 -> 18 - 16 -> 18 - 9 -> 18 - 12 -> 18 - 13 -> 18 + 19 -> 18 + 23 -> 18 + 20 -> 19 + 23 -> 19 + 7 -> 19 + 21 -> 20 + 22 -> 20 + 6 -> 20 + 14 -> 20 + 7 -> 20 + 23 -> 20 + 24 -> 20 + 9 -> 20 + 25 -> 20 8 -> 20 - 22 -> 21 - 24 -> 23 - 19 -> 23 - 60 -> 23 - 25 -> 24 - 20 -> 24 - 5 -> 24 - 4 -> 24 - 35 -> 24 - 19 -> 24 - 58 -> 24 - 59 -> 24 + 7 -> 21 + 9 -> 21 + 10 -> 21 + 8 -> 21 + 13 -> 21 + 7 -> 22 + 9 -> 22 + 10 -> 22 + 8 -> 22 + 13 -> 22 + 7 -> 24 26 -> 25 - 29 -> 25 - 30 -> 25 - 32 -> 25 - 33 -> 25 - 34 -> 25 - 37 -> 25 - 38 -> 25 - 40 -> 25 - 19 -> 25 - 15 -> 25 - 18 -> 25 - 41 -> 25 - 5 -> 25 - 4 -> 25 - 35 -> 25 - 42 -> 25 - 43 -> 25 - 53 -> 25 - 55 -> 25 - 39 -> 25 - 56 -> 25 - 57 -> 25 - 58 -> 25 - 27 -> 26 - 4 -> 26 - 28 -> 27 - 28 -> 29 - 4 -> 29 - 31 -> 30 - 19 -> 30 - 4 -> 31 - 19 -> 31 - 9 -> 32 + 27 -> 25 + 17 -> 28 + 18 -> 28 + 30 -> 29 + 23 -> 29 + 18 -> 30 + 23 -> 30 33 -> 32 - 32 -> 34 - 35 -> 34 + 35 -> 32 + 8 -> 33 + 34 -> 33 + 31 -> 33 36 -> 35 - 4 -> 35 + 18 -> 35 13 -> 35 - 9 -> 36 + 8 -> 36 13 -> 36 - 9 -> 37 - 4 -> 37 - 32 -> 37 - 35 -> 38 - 34 -> 38 - 32 -> 38 + 38 -> 37 + 35 -> 37 33 -> 38 - 39 -> 38 - 36 -> 39 - 4 -> 39 - 13 -> 39 + 8 -> 39 + 18 -> 39 + 33 -> 39 + 35 -> 40 + 32 -> 40 33 -> 40 - 4 -> 40 - 10 -> 40 - 9 -> 40 - 33 -> 41 - 4 -> 41 - 36 -> 42 - 5 -> 42 - 13 -> 42 - 44 -> 43 - 49 -> 43 - 52 -> 43 - 45 -> 44 - 47 -> 44 - 48 -> 44 + 34 -> 40 + 41 -> 40 + 36 -> 41 + 18 -> 41 + 13 -> 41 + 34 -> 42 + 18 -> 42 + 9 -> 42 + 8 -> 42 + 34 -> 43 + 18 -> 43 + 36 -> 44 + 19 -> 44 + 13 -> 44 46 -> 45 - 33 -> 45 - 33 -> 46 - 33 -> 47 + 51 -> 45 + 54 -> 45 + 47 -> 46 + 49 -> 46 + 50 -> 46 48 -> 47 - 46 -> 48 - 33 -> 48 + 34 -> 47 + 34 -> 48 + 34 -> 49 50 -> 49 - 51 -> 49 - 4 -> 50 - 35 -> 50 - 33 -> 50 - 48 -> 51 - 50 -> 52 - 47 -> 52 - 54 -> 53 - 36 -> 54 - 4 -> 54 - 13 -> 54 - 32 -> 55 - 35 -> 55 + 48 -> 50 + 34 -> 50 + 31 -> 50 + 52 -> 51 + 53 -> 51 + 18 -> 52 + 35 -> 52 + 34 -> 52 + 50 -> 53 + 52 -> 54 + 49 -> 54 + 56 -> 55 36 -> 56 - 4 -> 56 + 18 -> 56 13 -> 56 - 36 -> 57 - 4 -> 57 - 13 -> 57 - 39 -> 58 - 56 -> 58 - 57 -> 58 - 35 -> 59 - 34 -> 59 - 55 -> 59 - 62 -> 61 - 65 -> 61 - 60 -> 61 - 7 -> 62 - 14 -> 62 - 15 -> 62 + 33 -> 57 + 35 -> 57 + 36 -> 58 + 18 -> 58 + 13 -> 58 + 36 -> 59 + 18 -> 59 + 13 -> 59 + 41 -> 60 + 58 -> 60 + 59 -> 60 + 36 -> 61 + 18 -> 61 + 13 -> 61 + 36 -> 62 18 -> 62 - 5 -> 62 - 4 -> 62 - 63 -> 62 - 23 -> 62 - 65 -> 62 - 58 -> 62 - 26 -> 63 - 29 -> 63 - 30 -> 63 - 32 -> 63 - 33 -> 63 - 34 -> 63 - 37 -> 63 - 38 -> 63 - 64 -> 63 - 65 -> 63 - 15 -> 63 + 13 -> 62 + 36 -> 63 18 -> 63 - 41 -> 63 - 5 -> 63 - 4 -> 63 - 35 -> 63 - 42 -> 63 - 66 -> 63 - 53 -> 63 - 70 -> 63 - 39 -> 63 - 56 -> 63 - 57 -> 63 - 58 -> 63 - 33 -> 64 - 4 -> 64 - 10 -> 64 - 9 -> 64 + 13 -> 63 + 35 -> 64 + 32 -> 64 + 57 -> 64 + 66 -> 65 + 69 -> 65 + 21 -> 66 + 22 -> 66 + 6 -> 66 + 14 -> 66 + 19 -> 66 + 18 -> 66 67 -> 66 - 68 -> 66 - 52 -> 66 - 45 -> 67 - 47 -> 67 - 48 -> 67 - 50 -> 68 - 69 -> 68 - 48 -> 69 - 32 -> 70 - 35 -> 70 - 72 -> 71 - 75 -> 71 - 60 -> 71 - 7 -> 72 - 14 -> 72 - 15 -> 72 - 18 -> 72 - 5 -> 72 - 4 -> 72 + 3 -> 66 + 69 -> 66 + 60 -> 66 + 6 -> 67 + 14 -> 67 + 15 -> 67 + 28 -> 67 + 29 -> 67 + 31 -> 67 + 32 -> 67 + 37 -> 67 + 39 -> 67 + 40 -> 67 + 33 -> 67 + 34 -> 67 + 68 -> 67 + 69 -> 67 + 43 -> 67 + 19 -> 67 + 18 -> 67 + 35 -> 67 + 44 -> 67 + 70 -> 67 + 55 -> 67 + 74 -> 67 + 41 -> 67 + 58 -> 67 + 59 -> 67 + 60 -> 67 + 61 -> 67 + 62 -> 67 + 63 -> 67 + 34 -> 68 + 18 -> 68 + 9 -> 68 + 8 -> 68 + 71 -> 70 + 72 -> 70 + 54 -> 70 + 47 -> 71 + 49 -> 71 + 50 -> 71 + 52 -> 72 73 -> 72 - 61 -> 72 - 75 -> 72 - 58 -> 72 - 26 -> 73 - 29 -> 73 - 30 -> 73 - 32 -> 73 - 33 -> 73 - 34 -> 73 - 37 -> 73 - 38 -> 73 - 74 -> 73 - 75 -> 73 - 15 -> 73 - 18 -> 73 - 41 -> 73 - 5 -> 73 - 4 -> 73 - 35 -> 73 - 42 -> 73 - 76 -> 73 - 53 -> 73 - 80 -> 73 - 39 -> 73 - 56 -> 73 - 57 -> 73 - 58 -> 73 + 50 -> 73 33 -> 74 - 4 -> 74 - 10 -> 74 - 9 -> 74 + 35 -> 74 + 76 -> 75 + 79 -> 75 + 21 -> 76 + 22 -> 76 + 6 -> 76 + 14 -> 76 + 19 -> 76 + 18 -> 76 77 -> 76 - 78 -> 76 - 52 -> 76 - 45 -> 77 - 47 -> 77 - 48 -> 77 - 50 -> 78 - 79 -> 78 - 48 -> 79 - 32 -> 80 - 35 -> 80 - 23 -> 81 - 4 -> 81 - 61 -> 82 - 4 -> 82 - 71 -> 83 - 4 -> 83 - 23 -> 84 - 4 -> 84 - 61 -> 85 - 4 -> 85 - 71 -> 86 - 4 -> 86 + 65 -> 76 + 79 -> 76 + 60 -> 76 + 6 -> 77 + 14 -> 77 + 15 -> 77 + 28 -> 77 + 29 -> 77 + 31 -> 77 + 32 -> 77 + 37 -> 77 + 39 -> 77 + 40 -> 77 + 33 -> 77 + 34 -> 77 + 78 -> 77 + 79 -> 77 + 43 -> 77 + 19 -> 77 + 18 -> 77 + 35 -> 77 + 44 -> 77 + 80 -> 77 + 55 -> 77 + 84 -> 77 + 41 -> 77 + 58 -> 77 + 59 -> 77 + 60 -> 77 + 61 -> 77 + 62 -> 77 + 63 -> 77 + 34 -> 78 + 18 -> 78 + 9 -> 78 + 8 -> 78 + 81 -> 80 + 82 -> 80 + 54 -> 80 + 47 -> 81 + 49 -> 81 + 50 -> 81 + 52 -> 82 + 83 -> 82 + 50 -> 83 + 33 -> 84 + 35 -> 84 + 18 -> 85 + 3 -> 86 + 18 -> 86 + 65 -> 87 + 18 -> 87 + 75 -> 88 + 18 -> 88 + 3 -> 89 + 18 -> 89 + 65 -> 90 + 18 -> 90 + 75 -> 91 + 18 -> 91 } | diff --git a/scripts/base_network.py b/scripts/base_network.py index 1598568e..d8e1fb4a 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -59,8 +59,19 @@ Outputs .. image:: img/base.png :scale: 33 % +- ``resources/regions_onshore.geojson``: + + .. image:: img/regions_onshore.png + :scale: 33 % + +- ``resources/regions_offshore.geojson``: + + .. image:: img/regions_offshore.png + :scale: 33 % + Description ----------- +Creates the network topology from an ENTSO-E map extract, and create Voronoi shapes for each bus representing both onshore and offshore regions. """ import logging From fad5dd49d54bb2890a4d014e8d702a21e8edd60b Mon Sep 17 00:00:00 2001 From: Koen van Greevenbroek Date: Mon, 6 May 2024 09:03:37 +0200 Subject: [PATCH 584/591] Fix last workflow image to reflect removal of `build_bus_regions` --- doc/img/workflow.png | Bin 0 -> 716250 bytes doc/index.rst | 2 +- graphics/workflow.png | Bin 680340 -> 0 bytes 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 doc/img/workflow.png delete mode 100644 graphics/workflow.png diff --git a/doc/img/workflow.png b/doc/img/workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..96ce7f378295fc0d71048e051bc10daf53742759 GIT binary patch literal 716250 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≥VepZ!rLA8Fxgz2aV4+%`dNV#Dp%-v1jK$wk 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

na(>N8qd`b0~VwMSG>E;JpD|ccrZsWm{(P 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�(2I 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°)h)dFt$!j)chl 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