Skip to content

Commit d7e0c3d

Browse files
authored
Improvements from 2030 study (#151)
* improve gas price 2025 * limit ttes capacity before 2025, and no ptes availability before 2035 * improve emission data for 2025 and 2030 * improve RES capacity constraints for 2025 and 2030 * allow a small amount of derivatives to be imported (mostly MeOH) * decrease land_transport electric share towards pypsa-eur defaults * take more configs from config.default.yaml * disable some config changes in pypsa-eur * limit cross-border AC flows * rename script * add UBA industry data and processing, activate it in 2025; activate UBA for mobility in 2025 * improve uba mobility data pipeline and technology occurence definition * national co2 budget: apply domestic factor for shipping * address pylint errors * update assumptions for nonco2 in 2020 and 2025 * add an entry for Bus: to first_tech_occurence to avoid empty buses * fix custom_costs scaling * avoid code duplication * minor fix * add a little documentation of changes
1 parent 804f3a5 commit d7e0c3d

13 files changed

Lines changed: 319 additions & 116 deletions

.gitignore

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@ gurobi.log
2828
# Allowlist a small subset under data/pypsa-de.
2929
# Important: parent directories must be un-ignored for negations to take effect.
3030
!/data/pypsa-de/
31-
/data/pypsa-de/*
32-
!/data/pypsa-de/custom_costs_nep_2021.csv
33-
!/data/pypsa-de/custom_costs_nep_2023.csv
34-
!/data/pypsa-de/offshore_connection_points.csv
35-
!/data/pypsa-de/wasserstoff_kernnetz/
36-
!/data/pypsa-de/wasserstoff_kernnetz/**
3731
/cutouts
3832
/tmp
3933
doc/_build

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
# Changelog
2+
- added 2 delay years to the offshore NEP, s.t. capacity in 2030 is ~20GW
3+
- improved script name `modify_industry_demand` -> `modify_industry_production`
4+
- excluded international shipping from DE-specific CO2 emisisons
5+
- improved land transport shares, and some RES constraints
6+
- disabled ptes before 2035
7+
- add function to limit cross border electricity flows, to comply with the 0.7 security margin and the 0.7 EU trade capacity goals
8+
- Added an option to source industry energy demand from UBA MWMS (Projektionsbericht 2025) for the years 2025-2035
9+
- renamed some scripts
210
- Upstream: PyPSA-Eur adopted a new functionality for overwriting costs. PyPSA-DE follows this convention now. As a consequence, the `costs:horizon:optimist/mean/pessimist` is no longer available. `Mean` will be provided exclusively from now on. Also, the costs assumptions for onwind turbines changed sligthly. Furthermore, "costs:NEP_year:2021/2023" is no longer available, instead one of the custom_cost files for these NEP years provided in the `data/pypsa-de` folder has to be specified.
311
- The `ariadne-data` folder has been moved and renamed to `data/pypsa-de` to conform with the syntax of `scripts/pypsa-de`
412
- Bugfix: Enforce stricter power import limit to avoid that import from one country compensate from exports to another

Snakefile

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,13 @@ rule modify_prenetwork:
654654
bev_charge_rate=config_provider("sector", "bev_charge_rate"),
655655
bev_energy=config_provider("sector", "bev_energy"),
656656
bev_dsm_availability=config_provider("sector", "bev_dsm_availability"),
657+
uba_for_industry=config_provider("pypsa-de", "uba_for_industry", "enable"),
658+
scale_industry_non_energy=config_provider(
659+
"pypsa-de", "uba_for_industry", "scale_industry_non_energy"
660+
),
661+
limit_cross_border_flows_ac=config_provider(
662+
"pypsa-de", "limit_cross_border_flows_ac"
663+
),
657664
input:
658665
network=resources(
659666
"networks/base_s_{clusters}_{opts}_{sector_opts}_{planning_horizons}_brownfield.nc"
@@ -675,13 +682,20 @@ rule modify_prenetwork:
675682
industrial_demand=resources(
676683
"industrial_energy_demand_base_s_{clusters}_{planning_horizons}.csv"
677684
),
685+
industrial_production_per_country_tomorrow=resources(
686+
"industrial_production_per_country_tomorrow_{planning_horizons}-modified.csv"
687+
),
688+
industry_sector_ratios=resources(
689+
"industry_sector_ratios_{planning_horizons}.csv"
690+
),
678691
pop_weighted_energy_totals=resources(
679692
"pop_weighted_energy_totals_s_{clusters}.csv"
680693
),
681694
shipping_demand=resources("shipping_demand_s_{clusters}.csv"),
682695
regions_onshore=resources("regions_onshore_base_s_{clusters}.geojson"),
683696
regions_offshore=resources("regions_offshore_base_s_{clusters}.geojson"),
684697
offshore_connection_points="data/pypsa-de/offshore_connection_points.csv",
698+
new_industrial_energy_demand="data/pypsa-de/UBA_Projektionsbericht2025_Abbildung31_MWMS.csv",
685699
output:
686700
network=resources(
687701
"networks/base_s_{clusters}_{opts}_{sector_opts}_{planning_horizons}_final.nc"
@@ -695,7 +709,7 @@ rule modify_prenetwork:
695709
"scripts/pypsa-de/modify_prenetwork.py"
696710

697711

698-
ruleorder: modify_industry_demand > build_industrial_production_per_country_tomorrow
712+
ruleorder: modify_industry_production > build_industrial_production_per_country_tomorrow
699713

700714

701715
rule modify_existing_heating:
@@ -740,7 +754,7 @@ rule build_existing_chp_de:
740754
"scripts/pypsa-de/build_existing_chp_de.py"
741755

742756

743-
rule modify_industry_demand:
757+
rule modify_industry_production:
744758
params:
745759
reference_scenario=config_provider("pypsa-de", "reference_scenario"),
746760
input:
@@ -755,9 +769,9 @@ rule modify_industry_demand:
755769
resources:
756770
mem_mb=1000,
757771
log:
758-
logs("modify_industry_demand_{planning_horizons}.log"),
772+
logs("modify_industry_production_{planning_horizons}.log"),
759773
script:
760-
"scripts/pypsa-de/modify_industry_demand.py"
774+
"scripts/pypsa-de/modify_industry_production.py"
761775

762776

763777
rule build_wasserstoff_kernnetz:

config/config.de.yaml

Lines changed: 49 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#run
66
run:
7-
prefix: 20251017_improve_power_limits
7+
prefix: 20260114_limit_cross_border_flows
88
name:
99
# - ExPol
1010
- KN2045_Mix
@@ -36,7 +36,20 @@ pypsa-de:
3636
reference_scenario: KN2045_Mix
3737
region: Deutschland
3838
ageb_for_mobility: true # In 2020 use AGEB data for final energy demand and KBA for vehicles
39-
uba_for_mobility: false # For 2025–2035 use MWMS scenario from UBA Projektionsbericht 2025
39+
uba_for_mobility: # Available for 2025–2035; uses MWMS scenario from UBA Projektionsbericht 2025
40+
- 2025
41+
uba_for_industry: # Available for 2025–2035; uses MWMS scenario from UBA Projektionsbericht 2025
42+
scale_non_energy: false # Scale non-energy demand directly proportional to energy demand
43+
enable: # Allowed values are "false" or a subset of [2025, 2030, 2035]
44+
- 2025
45+
limit_cross_border_flows_ac: # relevant if only one node per country is used
46+
2020: 0.4
47+
2025: 0.4
48+
2030: 0.45
49+
2035: 0.49 # = 0.7 * 0.7 <=> security margin * CEP target
50+
2040: 0.49
51+
2045: 0.49
52+
2050: 0.49
4053

4154
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#foresight
4255
foresight: myopic
@@ -261,7 +274,12 @@ first_technology_occurrence:
261274
H2 pipeline: 2025
262275
H2 Electrolysis: 2025
263276
H2 pipeline retrofitted: 2025
264-
277+
urban central water pits charger: 2035
278+
urban central water pits discharger: 2035
279+
Store:
280+
urban central water pits: 2035
281+
Bus:
282+
urban central water pits: 2035
265283
costs:
266284
custom_cost_fn: data/pypsa-de/custom_costs_nep_2023.csv
267285
transmission: "overhead" # either overhead line ("overhead") or underground cable ("underground")
@@ -336,44 +354,30 @@ sector:
336354
2045: 0.36
337355
2050: 0.43
338356
# For Germany these settings get overwritten in build_exogenous_mobility_data
357+
# Essentially all PyPSA-EUR settings but with a little bit of hydrogen to allow for the later overwrites
339358
land_transport_fuel_cell_share:
340-
2020: 0.01
341-
2025: 0.01
342-
2030: 0.02
343-
2035: 0.03
344-
2040: 0.03
345-
2045: 0.03
346-
2050: 0.03
359+
2020: 0.001
360+
2025: 0.001
361+
2030: 0.001
362+
2035: 0.001
363+
2040: 0.001
364+
2045: 0.001
365+
2050: 0.001
347366
land_transport_electric_share:
348-
2020: 0.05
349-
2025: 0.15
350-
2030: 0.3
351-
2035: 0.45
352-
2040: 0.72
353-
2045: 0.87
354-
2050: 0.97
367+
2050: 0.999
355368
land_transport_ice_share:
356-
2020: 0.94
357-
2025: 0.84
358-
2030: 0.68
359-
2035: 0.52
360-
2040: 0.25
361-
2045: 0.1
362-
2050: 0.0
369+
2020: 0.999
370+
2025: 0.949
371+
2030: 0.799
372+
2035: 0.549
373+
2040: 0.299
374+
2045: 0.149
363375

364376
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#industry
365377
industry:
366378
steam_biomass_fraction: 0.4
367379
steam_hydrogen_fraction: 0.3
368380
steam_electricity_fraction: 0.3
369-
St_primary_fraction:
370-
2020: 0.6
371-
2025: 0.55
372-
2030: 0.5
373-
2035: 0.45
374-
2040: 0.4
375-
2045: 0.35
376-
2050: 0.3
377381
DRI_fraction:
378382
2020: 0
379383
2025: 0
@@ -394,22 +398,6 @@ industry:
394398
2040: 0.6
395399
2045: 0.5
396400
2050: 0.4
397-
HVC_mechanical_recycling_fraction:
398-
2020: 0.12
399-
2025: 0.15
400-
2030: 0.18
401-
2035: 0.21
402-
2040: 0.24
403-
2045: 0.27
404-
2050: 0.30
405-
HVC_chemical_recycling_fraction:
406-
2020: 0.0
407-
2025: 0.0
408-
2030: 0.04
409-
2035: 0.08
410-
2040: 0.12
411-
2045: 0.16
412-
2050: 0.20
413401
# 15 Mt HVC production (from IDEES) -> 6 Mt Plastikabfälle,
414402
# To substitute for other waste, assume all Plastikabfall is used energetically whereas in reality ~40% is recycled
415403
# see https://github.com/PyPSA/pypsa-ariadne/pull/292
@@ -468,7 +456,7 @@ solving:
468456
onwind:
469457
DE:
470458
2020: 54.5
471-
2025: 69
459+
2025: 68 # # Abb. 4_9 https://www.agora-energiewende.de/fileadmin/Projekte/2025/2025-28_DE_JAW25/A-EW_391_Die_Energiewende_in_Deutschland_Stand_der_Dinge_2025_WEB.pdf
472460
2030: 115 # EEG2023 Ziel für 2030
473461
2035: 160 # EEG2023 Ziel für 2040
474462
2040: 250
@@ -478,15 +466,15 @@ solving:
478466
DE:
479467
2020: 7.8
480468
2025: 11.3
481-
2030: 29.3 # uba Projektionsbericht and NEP without delayed BalWin 3
482-
2035: 50 # Planned projects until 2035 (offshore_connection_points.csv) -1.3 GW for potential delays
469+
2030: 24 # very optimistic upper ceiling to "Mittelfristprognose zur deutschlandweiten Stromerzeugung"
470+
2035: 50 # Planned projects until 2035 (offshore_connection_points.csv) -1.3 GW for potential delays
483471
2040: 65 # Planned projects until 2040 -1.5 GW for potential retirments
484472
2045: 70
485473
2050: 70
486474
solar:
487475
DE:
488476
2020: 53.7
489-
2025: 110 # EEG2023; assumes for 2026: 128 GW, assuming a fair share reached by end of 2025
477+
2025: 119 # Abb. 4_9 https://www.agora-energiewende.de/fileadmin/Projekte/2025/2025-28_DE_JAW25/A-EW_391_Die_Energiewende_in_Deutschland_Stand_der_Dinge_2025_WEB.pdf
490478
2030: 235 # PV Ziel 2030 + 20 GW
491479
2035: 400
492480
2040: 800
@@ -502,6 +490,9 @@ solving:
502490
2040: 50000
503491
2045: 80000
504492
2050: 80000
493+
urban central water tanks:
494+
DE:
495+
2025: 120 # GWh, https://www.hamburg-institut.com/wp-content/uploads/2023/12/Referenzblatt_SysGF-1.pdf
505496
Link:
506497
methanolisation:
507498
DE:
@@ -530,21 +521,20 @@ solving:
530521
Generator:
531522
onwind:
532523
DE:
524+
2025: 67 # Abb. 4_9 https://www.agora-energiewende.de/fileadmin/Projekte/2025/2025-28_DE_JAW25/A-EW_391_Die_Energiewende_in_Deutschland_Stand_der_Dinge_2025_WEB.pdf
533525
2030: 99 # Wind-an-Land Law 2028
534526
2035: 115 # Wind-an-Land Law 2030
535527
2040: 157 # target 2035
536528
2045: 160 # target 2040
537529
offwind:
538530
DE:
539-
2030: 22.5 # 75% Wind-auf-See Law
531+
2030: 18 # Mittelfristprognose zur deutschlandweiten Stromerzeugung
540532
2035: 35
541533
2040: 42
542534
2045: 50
543535
solar:
544536
DE:
545-
# EEG2023; Ziel for 2024: 88 GW and for 2026: 128 GW,
546-
# assuming at least 1/3 of difference reached in 2025
547-
2025: 101
537+
2025: 118 # Abb. 4_9 https://www.agora-energiewende.de/fileadmin/Projekte/2025/2025-28_DE_JAW25/A-EW_391_Die_Energiewende_in_Deutschland_Stand_der_Dinge_2025_WEB.pdf
548538
Link:
549539
H2 Electrolysis:
550540
DE:
@@ -601,8 +591,8 @@ solving:
601591
# boundary condition lower?
602592
DE:
603593
2020: 0
604-
2025: 0
605-
2030: 10
594+
2025: 6
595+
2030: 20
606596
2035: 105
607597
2040: 200
608598
2045: 300
@@ -720,7 +710,7 @@ onshore_nep_force:
720710
offshore_nep_force:
721711
cutin_year: 2025
722712
cutout_year: 2030
723-
delay_years: 0
713+
delay_years: 2
724714

725715
scale_capacity:
726716
2020:
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
carrier,2025,2030,2035
2+
fossil,324,258,191
3+
industry electricity,211,234,249
4+
solid biomass for industry,31,35,31
5+
H2 for industry,0,6,42
6+
low-temperature heat for industry,48,59,63

data/pypsa-de/custom_costs_nep_2021.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ all,hydrogen storage underground,investment,0.55,EUR/kWh,Langfristszenarien Szen
4141
2020,coal,fuel,5.7048,EUR2020/MWh,Ariadne,"$2020 = 0.8775 EUR2020, 1t = 8.06 MWh"
4242
2020,decentral air-sourced heat pump,investment,1685,EUR2020/kW_th,https://ariadneprojekt.de/media/2024/01/Ariadne-Analyse_HeizkostenEmissionenGebaeude_Januar2024.pdf https://www.enpal.de/waermepumpe/kosten/ https://www.bdew.de/media/documents/BDEW-HKV_Altbau.pdf
4343
2020,decentral ground-sourced heat pump,investment,2774,EUR2020/kW_th,https://ariadneprojekt.de/media/2024/01/Ariadne-Analyse_HeizkostenEmissionenGebaeude_Januar2024.pdf https://www.enpal.de/waermepumpe/kosten/ https://www.bdew.de/media/documents/BDEW-HKV_Altbau.pdf
44-
2025,gas,fuel,40,EUR/MWh_th,Ariadne,
44+
2025,gas,fuel,30,EUR2020/MWh_th,Ariadne,Näherungsweise Durchschnittspreis 2025 (Annahme 36€) korrigiert für Inflation (Annahme 20%)
4545
2025,oil,fuel,32.9876,EUR2020/MWh,Ariadne,"$2020 = 0.8775 EUR2020, 1bbl = 1.6998MWh"
4646
2025,coal,fuel,10.6694,EUR2020/MWh,Ariadne,"$2020 = 0.8775 EUR2020, 1t = 8.06 MWh"
4747
2025,decentral air-sourced heat pump,investment,1604,EUR2020/kW_th,https://ariadneprojekt.de/media/2024/01/Ariadne-Analyse_HeizkostenEmissionenGebaeude_Januar2024.pdf https://www.enpal.de/waermepumpe/kosten/ https://www.bdew.de/media/documents/BDEW-HKV_Altbau.pdf and cost reduction from DEA

data/pypsa-de/custom_costs_nep_2023.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ all,hydrogen storage underground,investment,0.55,EUR/kWh,Langfristszenarien Szen
4141
2020,coal,fuel,5.7048,EUR2020/MWh,Ariadne,"$2020 = 0.8775 EUR2020, 1t = 8.06 MWh"
4242
2020,decentral air-sourced heat pump,investment,1685,EUR2020/kW_th,https://ariadneprojekt.de/media/2024/01/Ariadne-Analyse_HeizkostenEmissionenGebaeude_Januar2024.pdf https://www.enpal.de/waermepumpe/kosten/ https://www.bdew.de/media/documents/BDEW-HKV_Altbau.pdf
4343
2020,decentral ground-sourced heat pump,investment,2774,EUR2020/kW_th,https://ariadneprojekt.de/media/2024/01/Ariadne-Analyse_HeizkostenEmissionenGebaeude_Januar2024.pdf https://www.enpal.de/waermepumpe/kosten/ https://www.bdew.de/media/documents/BDEW-HKV_Altbau.pdf
44-
2025,gas,fuel,40,EUR/MWh_th,Ariadne,
44+
2025,gas,fuel,30,EUR2020/MWh_th,Ariadne,Näherungsweise Durchschnittspreis 2025 (Annahme 36€) korrigiert für Inflation (Annahme 20%)
4545
2025,oil,fuel,32.9876,EUR2020/MWh,Ariadne,"$2020 = 0.8775 EUR2020, 1bbl = 1.6998MWh"
4646
2025,coal,fuel,10.6694,EUR2020/MWh,Ariadne,"$2020 = 0.8775 EUR2020, 1t = 8.06 MWh"
4747
2025,decentral air-sourced heat pump,investment,1604,EUR2020/kW_th,https://ariadneprojekt.de/media/2024/01/Ariadne-Analyse_HeizkostenEmissionenGebaeude_Januar2024.pdf https://www.enpal.de/waermepumpe/kosten/ https://www.bdew.de/media/documents/BDEW-HKV_Altbau.pdf and cost reduction from DEA

scripts/process_cost_data.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ def prepare_costs(
105105
DataFrame containing the prepared cost data
106106
107107
"""
108+
109+
def _convert_to_MW(cost_df: pd.DataFrame) -> pd.DataFrame:
110+
# correct units to MW and EUR
111+
cost_df.loc[cost_df.unit.str.contains("/kW"), "value"] *= 1e3
112+
cost_df.loc[cost_df.unit.str.contains("/GW"), "value"] /= 1e3
113+
114+
cost_df.unit = cost_df.unit.str.replace("/kW", "/MW")
115+
cost_df.unit = cost_df.unit.str.replace("/GW", "/MW")
116+
return cost_df
117+
108118
# Load custom costs and categorize into two sets:
109119
# - Raw attributes: overwritten before cost preparation
110120
# - Prepared attributes: overwritten after cost preparation
@@ -115,9 +125,12 @@ def prepare_costs(
115125
index_col=["technology", "parameter"],
116126
).query("planning_horizon in [@planning_horizon, 'all']")
117127

128+
custom_costs = _convert_to_MW(custom_costs)
129+
118130
custom_costs = custom_costs.drop("planning_horizon", axis=1).value.unstack(
119131
level=1
120132
)
133+
121134
prepared_attrs = ["marginal_cost", "capital_cost"]
122135
raw_attrs = list(set(custom_costs.columns) - set(prepared_attrs))
123136
custom_raw = custom_costs[raw_attrs].dropna(axis=0, how="all")
@@ -128,12 +141,7 @@ def prepare_costs(
128141
if key in config:
129142
config["overwrites"][key] = config[key]
130143

131-
# correct units to MW and EUR
132-
costs.loc[costs.unit.str.contains("/kW"), "value"] *= 1e3
133-
costs.loc[costs.unit.str.contains("/GW"), "value"] /= 1e3
134-
135-
costs.unit = costs.unit.str.replace("/kW", "/MW")
136-
costs.unit = costs.unit.str.replace("/GW", "/MW")
144+
costs = _convert_to_MW(costs)
137145

138146
# min_count=1 is important to generate NaNs which are then filled by fillna
139147
costs = costs.value.unstack(level=1).groupby("technology").sum(min_count=1)

0 commit comments

Comments
 (0)