Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add perfect foresight #301

Closed
wants to merge 11 commits into from
233 changes: 162 additions & 71 deletions Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,21 @@ SDIR = config['summary_dir'] + '/' + config['run']
RDIR = config['results_dir'] + config['run']



subworkflow pypsaeur:
workdir: "../pypsa-eur"
snakefile: "../pypsa-eur/Snakefile"
configfile: "../pypsa-eur/config.yaml"

rule all:
input: SDIR + '/graphs/costs.pdf'
if config["foresight"] in ["myopic", "overnight"]:
rule all:
input: SDIR + '/graphs/costs.pdf'


rule solve_all_networks:
input:
expand(RDIR + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
**config['scenario'])
rule solve_all_networks:
input:
expand(RDIR + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
**config['scenario'])


rule prepare_sector_networks:
Expand Down Expand Up @@ -491,7 +493,7 @@ rule prepare_sector_network:
co2="data/eea/UNFCCC_v23.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",
costs= "data/costs_{}.csv".format(config['costs']['year']) if config["foresight"] == "overnight" else "data/costs_{planning_horizons}.csv",
profile_offwind_ac=pypsaeur("resources/profile_offwind-ac.nc"),
profile_offwind_dc=pypsaeur("resources/profile_offwind-dc.nc"),
h2_cavern="resources/salt_cavern_potentials_s{simpl}_{clusters}.csv",
Expand Down Expand Up @@ -528,18 +530,18 @@ rule prepare_sector_network:
script: "scripts/prepare_sector_network.py"


rule plot_network:
input:
overrides="data/override_component_attrs",
network=RDIR + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
regions=pypsaeur('resources/regions_onshore_elec_s{simpl}_{clusters}.geojson')
output:
map=RDIR + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf",
today=RDIR + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}-today.pdf"
threads: 2
resources: mem_mb=10000
benchmark: RDIR + "/benchmarks/plot_network/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}"
script: "scripts/plot_network.py"
if config["foresight"] in ["myopic", "overnight"]:
rule plot_network:
input:
overrides="data/override_component_attrs",
network=RDIR + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc"
output:
map=RDIR + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf",
today=RDIR + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}-today.pdf"
threads: 2
resources: mem_mb=10000
benchmark: RDIR + "/benchmarks/plot_network/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}"
script: "scripts/plot_network.py"


rule copy_config:
Expand All @@ -549,64 +551,62 @@ rule copy_config:
benchmark: SDIR + "/benchmarks/copy_config"
script: "scripts/copy_config.py"


rule copy_conda_env:
output: SDIR + '/configs/environment.yaml'
threads: 1
resources: mem_mb=500
benchmark: SDIR + "/benchmarks/copy_conda_env"
shell: "conda env export -f {output} --no-builds"

if config["foresight"] in ["myopic", "overnight"]:
rule make_summary:
input:
overrides="data/override_component_attrs",
networks=expand(
RDIR + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
**config['scenario']
),
costs= "data/costs_{}.csv".format(config['scenario']['planning_horizons'][0]),
plots=expand(
RDIR + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf",
**config['scenario']
)
output:
nodal_costs=SDIR + '/csvs/nodal_costs.csv',
nodal_capacities=SDIR + '/csvs/nodal_capacities.csv',
nodal_cfs=SDIR + '/csvs/nodal_cfs.csv',
cfs=SDIR + '/csvs/cfs.csv',
costs=SDIR + '/csvs/costs.csv',
capacities=SDIR + '/csvs/capacities.csv',
curtailment=SDIR + '/csvs/curtailment.csv',
energy=SDIR + '/csvs/energy.csv',
supply=SDIR + '/csvs/supply.csv',
supply_energy=SDIR + '/csvs/supply_energy.csv',
prices=SDIR + '/csvs/prices.csv',
weighted_prices=SDIR + '/csvs/weighted_prices.csv',
market_values=SDIR + '/csvs/market_values.csv',
price_statistics=SDIR + '/csvs/price_statistics.csv',
metrics=SDIR + '/csvs/metrics.csv'
threads: 2
resources: mem_mb=10000
benchmark: SDIR + "/benchmarks/make_summary"
script: "scripts/make_summary.py"

rule make_summary:
input:
overrides="data/override_component_attrs",
networks=expand(
RDIR + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
**config['scenario']
),
costs="data/costs_{}.csv".format(config['costs']['year']) if config["foresight"] == "overnight" else "data/costs_{}.csv".format(config['scenario']['planning_horizons'][0]),
plots=expand(
RDIR + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf",
**config['scenario']
)
output:
nodal_costs=SDIR + '/csvs/nodal_costs.csv',
nodal_capacities=SDIR + '/csvs/nodal_capacities.csv',
nodal_cfs=SDIR + '/csvs/nodal_cfs.csv',
cfs=SDIR + '/csvs/cfs.csv',
costs=SDIR + '/csvs/costs.csv',
capacities=SDIR + '/csvs/capacities.csv',
curtailment=SDIR + '/csvs/curtailment.csv',
energy=SDIR + '/csvs/energy.csv',
supply=SDIR + '/csvs/supply.csv',
supply_energy=SDIR + '/csvs/supply_energy.csv',
prices=SDIR + '/csvs/prices.csv',
weighted_prices=SDIR + '/csvs/weighted_prices.csv',
market_values=SDIR + '/csvs/market_values.csv',
price_statistics=SDIR + '/csvs/price_statistics.csv',
metrics=SDIR + '/csvs/metrics.csv'
threads: 2
resources: mem_mb=10000
benchmark: SDIR + "/benchmarks/make_summary"
script: "scripts/make_summary.py"


rule plot_summary:
input:
costs=SDIR + '/csvs/costs.csv',
energy=SDIR + '/csvs/energy.csv',
balances=SDIR + '/csvs/supply_energy.csv',
eurostat=input_eurostat,
country_codes='data/Country_codes.csv',
output:
costs=SDIR + '/graphs/costs.pdf',
energy=SDIR + '/graphs/energy.pdf',
balances=SDIR + '/graphs/balances-energy.pdf'
threads: 2
resources: mem_mb=10000
benchmark: SDIR + "/benchmarks/plot_summary"
script: "scripts/plot_summary.py"
rule plot_summary:
input:
costs=SDIR + '/csvs/costs.csv',
energy=SDIR + '/csvs/energy.csv',
balances=SDIR + '/csvs/supply_energy.csv',
eurostat=input_eurostat,
country_codes='data/Country_codes.csv',
output:
costs=SDIR + '/graphs/costs.pdf',
energy=SDIR + '/graphs/energy.pdf',
balances=SDIR + '/graphs/balances-energy.pdf'
threads: 2
resources: mem_mb=10000
benchmark: SDIR + "/benchmarks/plot_summary"
script: "scripts/plot_summary.py"


if config["foresight"] == "overnight":
Expand All @@ -630,7 +630,7 @@ if config["foresight"] == "overnight":
script: "scripts/solve_network.py"


if config["foresight"] == "myopic":
if config["foresight"] in ["myopic","perfect"]:

rule add_existing_baseyear:
input:
Expand All @@ -657,6 +657,9 @@ if config["foresight"] == "myopic":
script: "scripts/add_existing_baseyear.py"


if config["foresight"] == "myopic":


def solved_previous_horizon(wildcards):
planning_horizons = config["scenario"]["planning_horizons"]
i = planning_horizons.index(int(wildcards.planning_horizons))
Expand All @@ -681,7 +684,6 @@ if config["foresight"] == "myopic":

ruleorder: add_existing_baseyear > add_brownfield


rule solve_network_myopic:
input:
overrides="data/override_component_attrs",
Expand All @@ -698,3 +700,92 @@ if config["foresight"] == "myopic":
resources: mem_mb=config['solving']['mem']
benchmark: RDIR + "/benchmarks/solve_network/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}"
script: "scripts/solve_network.py"

if config["foresight"] == "perfect":
rule prepare_perfect_foresight:
input:
**{f"network_{year}": RDIR + "/prenetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_" + f"{year}.nc"
for year in config['scenario']["planning_horizons"][1:]},
brownfield_network = lambda w: (RDIR + "/prenetworks-brownfield/" + "elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_" + "{}.nc"
.format(str(config['scenario']["planning_horizons"][0]))),
overrides="data/override_component_attrs",
output: RDIR + "/prenetworks-brownfield/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_brownfield_all_years.nc"
threads: 2
resources: mem_mb=10000
script: "scripts/prepare_perfect_foresight.py"

rule solve_network_perfect:
input:
overrides="data/override_component_attrs",
network= RDIR + "/prenetworks-brownfield/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_brownfield_all_years.nc",
costs="data/costs_2030.csv",
config=SDIR + '/configs/config.yaml'
output: RDIR + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_brownfield_all_years.nc"
shadow: "shallow"
log:
solver=RDIR + "/logs/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_brownfield_all_years_solver.log",
python=RDIR + "/logs/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_brownfield_all_years_python.log",
memory=RDIR + "/logs/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_brownfield_all_years_memory.log"
threads: 4
resources: mem_mb=config['solving']['mem']
benchmark: RDIR + "/benchmarks/solve_network/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_brownfield_all_years"
script: "scripts/solve_network.py"

rule make_summary_perfect:
input:
**{f"networks_{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}":
RDIR + f"/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{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 lv in config['scenario']['lv']},
costs="data/costs_2020.csv",
overrides="data/override_component_attrs",
output:
nodal_costs="results" + '/' + config['run'] + '/csvs/nodal_costs.csv',
nodal_capacities="results" + '/' + config['run'] + '/csvs/nodal_capacities.csv',
nodal_cfs="results" + '/' + config['run'] + '/csvs/nodal_cfs.csv',
cfs="results" + '/' + config['run'] + '/csvs/cfs.csv',
costs="results" + '/' + config['run'] + '/csvs/costs.csv',
capacities="results" + '/' + config['run'] + '/csvs/capacities.csv',
curtailment="results" + '/' + config['run'] + '/csvs/curtailment.csv',
capital_cost="results" + '/' + config['run'] + '/csvs/capital_cost.csv',
energy="results" + '/' + config['run'] + '/csvs/energy.csv',
supply="results" + '/' + config['run'] + '/csvs/supply.csv',
supply_energy="results" + '/' + config['run'] + '/csvs/supply_energy.csv',
prices="results" + '/' + config['run'] + '/csvs/prices.csv',
weighted_prices="results" + '/' + config['run'] + '/csvs/weighted_prices.csv',
market_values="results" + '/' + config['run'] + '/csvs/market_values.csv',
price_statistics="results" + '/' + config['run'] + '/csvs/price_statistics.csv',
metrics="results" + '/' + config['run'] + '/csvs/metrics.csv',
co2_emissions="results" + '/' + config['run'] + '/csvs/co2_emissions.csv',
threads: 2
resources: mem_mb=10000
script:
'scripts/make_summary_perfect.py'

rule plot_summary_perfect:
input:
costs_csv="results" + '/' + config['run'] + '/csvs/costs.csv',
**{f"costs_{year}": f"data/costs_{year}.csv"
for year in config['scenario']["planning_horizons"]},
energy="results" + '/' + config['run'] + '/csvs/energy.csv',
balances="results" + '/' + config['run'] + '/csvs/supply_energy.csv',
eea ="data/eea/UNFCCC_v24.csv",
countries="results" + '/' + config['run'] + '/csvs/nodal_capacities.csv',
co2_emissions="results" + '/' + config['run'] + '/csvs/co2_emissions.csv',
capacities="results" + '/' + config['run'] + '/csvs/capacities.csv',
capital_cost="results" + '/' + config['run'] + '/csvs/capital_cost.csv',
output:
costs1="results" + '/' + config['run'] + '/graphs/costs.pdf',
costs2="results" + '/' + config['run'] + '/graphs/costs2.pdf',
costs3="results" + '/' + config['run'] + '/graphs/total_costs_per_year.pdf',
# energy="results" + '/' + config['run'] + '/graphs/energy.pdf',
balances="results" + '/' + config['run'] + '/graphs/balances-energy.pdf',
co2_emissions="results" + '/' + config['run'] + '/graphs/carbon_budget_plot.pdf',
capacities="results" + '/' + config['run'] + '/graphs/capacities.pdf',
threads: 2
resources: mem_mb=10000
script:
'scripts/plot_summary_perfect.py'
6 changes: 6 additions & 0 deletions config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ co2_budget:
2040: 0.0712365591
2045: 0.0322580645
2050: 0
# update of IPCC 6th AR compared to the 1.5SR. (discussed here: https://twitter.com/JoeriRogelj/status/1424743828339167233)
1p5 : 34.2 # 25.7 # Budget in Gt CO2 for 1.5 for Europe, global 420 Gt, assuming per capita share
1p6 : 43.259666 # 35 # Budget in Gt CO2 for 1.6 for Europe, global 580 Gt
1p7 : 51.4 # 45 # Budget in Gt CO2 for 1.7 for Europe, global 800 Gt
2p0 : 69.778 # 73.9 # Budget in Gt CO2 for 2 for Europe, global 1170 Gt

# snapshots are originally set in PyPSA-Eur/config.yaml but used again by PyPSA-Eur-Sec
snapshots:
Expand Down Expand Up @@ -345,6 +350,7 @@ costs:
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
social_discountrate: 0.02

# Marginal and capital costs can be overwritten
# capital_cost:
Expand Down
Loading