Skip to content

Commit 80fc857

Browse files
Michapre-commit-ci[bot]
andauthored
Further refining scenarios (#39)
* rewrite export ban on efuels * decrease hydrogen underground storage costs * hardcode heating stock * hardcode old REMod results, adjust for district heating * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * update variable template for ariadne * add comment * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent b509b4c commit 80fc857

11 files changed

+53
-84
lines changed

Snakefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ rule modify_district_heat_share:
281281

282282
rule modify_prenetwork:
283283
params:
284+
efuel_export_ban=config_provider("solving", "constraints", "efuel_export_ban"),
284285
enable_kernnetz=config_provider("wasserstoff_kernnetz", "enable"),
285286
costs=config_provider("costs"),
286287
max_hours=config_provider("electricity", "max_hours"),
@@ -476,7 +477,7 @@ rule cluster_wasserstoff_kernnetz:
476477
rule download_ariadne_template:
477478
input:
478479
storage(
479-
"https://github.com/iiasa/ariadne-intern-workflow/raw/main/attachments/2024-11-28_template_Ariadne.xlsx",
480+
"https://github.com/iiasa/ariadne-intern-workflow/raw/main/attachments/2025-01-27_template_Ariadne.xlsx",
480481
keep_local=True,
481482
),
482483
output:

config/config.yaml

Lines changed: 2 additions & 1 deletion
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: 20250124-finalfixes
7+
prefix: 20250130-morefinalfixes
88
name:
99
# - CurrentPolicies
1010
- KN2045_Bal_v4
@@ -432,6 +432,7 @@ solving:
432432
H2 pipeline retrofitted: 0.05
433433
fractional_last_unit_size: true
434434
constraints:
435+
efuel_export_ban: true
435436
limits_capacity_max:
436437
Generator:
437438
onwind:

config/scenarios.manual.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -896,4 +896,3 @@ KN2045_Bal_HighDemand:
896896
2035: 0.18
897897
2040: 0.24
898898
2045: 0.29
899-

scripts/build_existing_heating_distribution.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,6 @@ def build_existing_heating():
5757
# data is for buildings only (i.e. NOT district heating) and represents the year 2012
5858
# TODO start from original file
5959

60-
# Add existing heating capacities, data comes from the study
61-
# "Mapping and analyses of the current and future (2020 - 2030)
62-
# heating/cooling fuel deployment (fossil/renewables) "
63-
# https://energy.ec.europa.eu/publications/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment-fossilrenewables-1_en
64-
# file: "WP2_DataAnnex_1_BuildingTechs_ForPublication_201603.xls" -> "existing_heating_raw.csv".
65-
# data is for buildings only (i.e. NOT district heating) and represents the year 2012
66-
# TODO start from original file
67-
6860
existing_heating = pd.read_csv(
6961
snakemake.input.existing_heating, index_col=0, header=0
7062
)

scripts/pypsa-de/additional_functionality.py

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -668,44 +668,7 @@ def add_h2_derivate_limit(n, investment_year, limits_volume_max):
668668
carrier_attribute="",
669669
)
670670

671-
# The following export bans for DE are added unconditionally, independent of config
672-
ct = "DE"
673-
logger.info("Adding net export bans for H2 derivatives in DE")
674-
675-
for incarrier, outcarrier in [
676-
("EU methanol -> DE methanol", "DE methanol -> EU methanol"),
677-
("EU renewable gas -> DE gas", "DE renewable gas -> EU gas"),
678-
("EU renewable oil -> DE oil", "DE renewable oil -> EU oil"),
679-
]:
680-
incoming = n.links.index[n.links.index == incarrier]
681-
outgoing = n.links.index[n.links.index == outcarrier]
682-
incoming_p = (
683-
n.model["Link-p"].loc[:, incoming] * n.snapshot_weightings.generators
684-
).sum()
685-
outgoing_p = (
686-
n.model["Link-p"].loc[:, outgoing] * n.snapshot_weightings.generators
687-
).sum()
688-
689-
lhs = incoming_p - outgoing_p
690-
691-
cname = f"renewable{incarrier.split()[-1]}_export_ban-{ct}"
692-
693-
n.model.add_constraints(lhs >= 0, name=f"GlobalConstraint-{cname}")
694-
695-
if cname in n.global_constraints.index:
696-
logger.warning(
697-
f"Global constraint {cname} already exists. Dropping and adding it again."
698-
)
699-
n.global_constraints.drop(cname, inplace=True)
700-
701-
n.add(
702-
"GlobalConstraint",
703-
cname,
704-
constant=0,
705-
sense=">=",
706-
type="",
707-
carrier_attribute="",
708-
)
671+
# Export bans on efuels are implemented in modify_prenetwork by restricting p_max_pu of the DE -> EU links
709672

710673

711674
def adapt_nuclear_output(n):

scripts/pypsa-de/build_scenarios.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,7 @@ def write_to_scenario_yaml(input, output, scenarios, df):
178178
# f"For CO2 budget: Using {fallback_reference_scenario} as fallback reference scenario for {scenario}."
179179
# )
180180
co2_budget_fractions = get_co2_budget(
181-
df.loc[
182-
snakemake.params.leitmodelle["general"], reference_scenario
183-
],
181+
df.loc[snakemake.params.leitmodelle["general"], reference_scenario],
184182
co2_budget_source,
185183
)
186184

scripts/pypsa-de/export_ariadne_variables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
from numpy import isclose
1717

1818
from scripts._helpers import configure_logging, mock_snakemake
19-
from scripts.prepare_sector_network import prepare_costs
2019
from scripts.add_electricity import calculate_annuity
20+
from scripts.prepare_sector_network import prepare_costs
2121

2222
logger = logging.getLogger(__name__)
2323

scripts/pypsa-de/modify_cost_data.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,12 @@ def carbon_component_fossils(costs, co2_price):
156156
)
157157
costs.at[("Fischer-Tropsch", "efficiency"), "source"] = "inverse of hydrogen-input"
158158

159+
logger.info(
160+
f"Setting Fischer-Tropsch efficiency to 1 / hydrogen-input. New value: {costs.loc['Fischer-Tropsch', 'efficiency'].value} {costs.loc['Fischer-Tropsch', 'efficiency'].unit}."
161+
)
162+
159163
# increase FOM of offshore wind connection (fix for costs.csv)
164+
logger.info(f"Setting FOM of offshore wind connections to 0.35 %.")
160165
costs.loc[("offwind-dc-connection-submarine", "FOM"), "value"] = 0.35
161166
costs.loc[("offwind-dc-connection-submarine", "FOM"), "unit"] = costs.at[
162167
("offwind", "FOM"), "unit"
@@ -174,4 +179,7 @@ def carbon_component_fossils(costs, co2_price):
174179
("offwind", "FOM"), "unit"
175180
]
176181

182+
logger.info(f"Setting investment cost of hydrogen storage to 0.55 EUR/kWh.")
183+
costs.loc[("hydrogen storage underground", "investment"), "value"] = 0.55
184+
177185
costs.to_csv(snakemake.output[0])

scripts/pypsa-de/modify_existing_heating.py

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,9 @@
1717

1818
configure_logging(snakemake)
1919

20-
leitmodell = snakemake.params.leitmodelle["buildings"]
21-
logger.info(f"Using {leitmodell} for heating demand modification.")
22-
2320
existing_heating = pd.read_csv(snakemake.input.existing_heating, index_col=0)
2421

25-
ariadne = pd.read_csv(
26-
snakemake.input.ariadne,
27-
index_col=["model", "scenario", "region", "variable", "unit"],
28-
).loc[
29-
leitmodell,
30-
snakemake.params.fallback_reference_scenario,
31-
"Deutschland",
32-
:,
33-
"million",
34-
]
35-
36-
logger.info("Heating demand before modification:{existing_heating.loc['Germany']}")
22+
logger.info(f"Heating demand before modification:{existing_heating.loc['Germany']}")
3723

3824
mapping = {
3925
"gas boiler": "Gas Boiler",
@@ -43,22 +29,26 @@
4329
"biomass boiler": "Biomass Boiler",
4430
}
4531

46-
year = "2020"
47-
for tech in mapping:
48-
stock = ariadne.at[
49-
f"Stock|Space Heating|{mapping[tech]}",
50-
year,
51-
]
52-
53-
peak = (
54-
stock
55-
* existing_heating.loc["Germany"].sum()
56-
/ ariadne.at[f"Stock|Space Heating", year]
57-
)
32+
new_values = pd.Series()
33+
34+
logger.warning(
35+
f"Adjusting heating stock towards hard coded values from a previous REMod run. This is only a hotfix."
36+
) # Because REMod is not consistent and a better solution takes too long.
37+
38+
new_values["gas boiler"] = 11.44 # million
39+
new_values["oil boiler"] = 5.99
40+
new_values["air heat pump"] = 0.38
41+
new_values["ground heat pump"] = 0.38
42+
new_values["biomass boiler"] = 2.8
43+
44+
total_stock = new_values.sum()
45+
existing_factor = existing_heating.loc["Germany"].sum() / total_stock
46+
47+
new_values *= existing_factor
48+
49+
for tech, peak in new_values.items():
5850
existing_heating.at["Germany", tech] = peak
5951

60-
logger.info(
61-
f"Heating demand after modification with {leitmodell}: {existing_heating.loc['Germany']}"
62-
)
52+
logger.info(f"Heating demand after modification: {existing_heating.loc['Germany']}")
6353

6454
existing_heating.to_csv(snakemake.output.existing_heating)

scripts/pypsa-de/modify_prenetwork.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,12 @@ def unravel_carbonaceous_fuels(n):
405405
marginal_cost=0.01,
406406
)
407407

408+
if snakemake.params.efuel_export_ban:
409+
logger.info(
410+
"Efuel export ban: Setting p_max_pu to 0 for DE renewable oil -> EU oil"
411+
)
412+
n.links.loc["DE renewable oil -> EU oil", "p_max_pu"] = 0
413+
408414
n.add(
409415
"Link",
410416
[
@@ -482,6 +488,12 @@ def unravel_carbonaceous_fuels(n):
482488
marginal_cost=0.01,
483489
)
484490

491+
if snakemake.params.efuel_export_ban:
492+
logger.info(
493+
"Efuel export ban: Setting p_max_pu to 0 for DE methanol -> EU methanol"
494+
)
495+
n.links.loc["DE methanol -> EU methanol", "p_max_pu"] = 0
496+
485497
# add stores
486498
EU_meoh_store = n.stores.loc["EU methanol Store"].copy()
487499
n.add(
@@ -702,6 +714,12 @@ def unravel_gasbus(n, costs):
702714
marginal_cost=0.01,
703715
)
704716

717+
if snakemake.params.efuel_export_ban:
718+
logger.info(
719+
"Efuel export ban: Setting p_max_pu to 0 for DE renewable gas -> EU gas"
720+
)
721+
n.links.loc["DE renewable gas -> EU gas", "p_max_pu"] = 0
722+
705723
### add links between renewable and fossil gas buses
706724
n.add(
707725
"Link",

0 commit comments

Comments
 (0)