Skip to content
This repository was archived by the owner on Mar 27, 2025. It is now read-only.

Commit 26c20a1

Browse files
JulianGeislindnemipre-commit-ci[bot]
authored
add function to scale carrier capacity (#285)
* add function to scale carrier capacity * add scaling for gas CHP and set lifetime of gas CHP to 40 years * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix negative investments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * only select extendable links * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * make must run function more general and add lignite in 2020 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Michael Lindner <michaellindner@posteo.de> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 7044a7a commit 26c20a1

File tree

4 files changed

+97
-22
lines changed

4 files changed

+97
-22
lines changed

config/config.yaml

Lines changed: 12 additions & 5 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: 20241120-correct-wind
7+
prefix: 20241121-fix-missing-gas-capa
88

99
name:
1010
# - CurrentPolicies
@@ -655,10 +655,11 @@ co2_price_add_on_fossils:
655655
2020: 25
656656
2025: 60
657657

658-
must_run_biogas:
659-
enable: false
660-
p_min_pu: 0.6
661-
regions: ['DE']
658+
must_run:
659+
2020:
660+
DE:
661+
lignite: 0.4
662+
# biogas: 0.6
662663

663664
transmission_projects:
664665
new_link_capacity: keep #keep or zero
@@ -672,3 +673,9 @@ onshore_nep_force:
672673
offshore_nep_force:
673674
cutin_year: 2025
674675
cutout_year: 2030
676+
677+
scale_capacity:
678+
2020:
679+
DE:
680+
CCGT: 10000
681+
"urban central gas CHP": 22000

workflow/Snakefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ rule modify_prenetwork:
235235
"sector", "H2_retrofit_capacity_per_CH4"
236236
),
237237
transmission_costs=config_provider("costs", "transmission"),
238-
biogas_must_run=config_provider("must_run_biogas"),
238+
must_run=config_provider("must_run"),
239239
clustering=config_provider("clustering", "temporal", "resolution_sector"),
240240
H2_plants=config_provider("electricity", "H2_plants_DE"),
241241
land_transport_electric_share=config_provider(
@@ -249,6 +249,7 @@ rule modify_prenetwork:
249249
shipping_oil_efficiency=config_provider("sector", "shipping_oil_efficiency"),
250250
shipping_methanol_share=config_provider("sector", "shipping_methanol_share"),
251251
mwh_meoh_per_tco2=config_provider("sector", "MWh_MeOH_per_tCO2"),
252+
scale_capacity=config_provider("scale_capacity"),
252253
input:
253254
costs_modifications="ariadne-data/costs_{planning_horizons}-modifications.csv",
254255
network=RESULTS

workflow/scripts/modify_cost_data.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,10 @@ def carbon_component_fossils(costs, co2_price):
146146
f"Scaling central water tank storage investment costs to KEA Technikkatalog: {costs.loc['central water tank storage', 'investment'].value} {costs.loc['central water tank storage', 'investment'].unit}."
147147
)
148148

149+
# increase central gas CHP lifetime to 40 years
150+
costs.at[("central gas CHP", "lifetime"), "value"] = 40
151+
logger.info(
152+
f"Setting lifetime of central gas CHP to {costs.at[("central gas CHP" , "lifetime") , "value"]} {costs.at[("central gas CHP" , "lifetime") , "unit"]}."
153+
)
154+
149155
costs.to_csv(snakemake.output[0])

workflow/scripts/modify_prenetwork.py

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -768,17 +768,23 @@ def transmission_costs_from_modified_cost_data(n, costs, transmission):
768768
n.links.loc[dc_b, "overnight_cost"] = overnight_cost
769769

770770

771-
def must_run_biogas(n, p_min_pu, regions):
771+
def must_run(n, params):
772772
"""
773-
Set p_min_pu for biogas generators to the specified value.
773+
Set p_min_pu for links to the specified value.
774774
"""
775-
logger.info(
776-
f"Must-run condition enabled: Setting p_min_pu = {p_min_pu} for biogas generators."
777-
)
778-
links_i = n.links[
779-
(n.links.carrier == "biogas") & (n.links.bus0.str.startswith(tuple(regions)))
780-
].index
781-
n.links.loc[links_i, "p_min_pu"] = p_min_pu
775+
investment_year = int(snakemake.wildcards.planning_horizons)
776+
if investment_year in params.keys():
777+
for region in params[investment_year].keys():
778+
for carrier in params[investment_year][region].keys():
779+
p_min_pu = params[investment_year][region][carrier]
780+
logger.info(
781+
f"Must-run condition enabled: Setting p_min_pu = {p_min_pu} for {carrier} in year {investment_year} and region {region}."
782+
)
783+
784+
links_i = n.links[
785+
(n.links.carrier == carrier) & n.links.index.str.contains(region)
786+
].index
787+
n.links.loc[links_i, "p_min_pu"] = p_min_pu
782788

783789

784790
def aladin_mobility_demand(n):
@@ -1168,6 +1174,63 @@ def drop_duplicate_transmission_projects(n):
11681174
n.remove("Line", to_drop)
11691175

11701176

1177+
def scale_capacity(n, scaling):
1178+
"""
1179+
Scale the output capacity of energy system links based on predefined scaling limits.
1180+
1181+
Parameters:
1182+
- n: The network/model object representing the energy system.
1183+
- scaling: A dictionary with scaling limits structured as
1184+
{year: {region: {carrier: limit}}}.
1185+
"""
1186+
investment_year = int(snakemake.wildcards.planning_horizons)
1187+
if investment_year in scaling.keys():
1188+
for region in scaling[investment_year].keys():
1189+
for carrier in scaling[investment_year][region].keys():
1190+
limit = scaling[investment_year][region][carrier]
1191+
logger.info(
1192+
f"Scaling output capacity (bus1) of {carrier} in region {region} to {limit} MW"
1193+
)
1194+
1195+
links_i = n.links[
1196+
(n.links.carrier == carrier) & n.links.index.str.contains(region)
1197+
].index
1198+
1199+
installed_cap = n.links.loc[links_i].eval("p_nom * efficiency").sum()
1200+
if installed_cap == 0:
1201+
logger.warning(
1202+
f"No installed capacity for {carrier} in region {region}. Skipping adjustment."
1203+
)
1204+
continue
1205+
1206+
diff_cap = limit - installed_cap
1207+
avg_efficiency = n.links.loc[links_i, "efficiency"].mean()
1208+
if avg_efficiency == 0 or np.isnan(avg_efficiency):
1209+
logger.warning(
1210+
f"Invalid average efficiency for {carrier} in region {region}. Skipping adjustment."
1211+
)
1212+
continue
1213+
1214+
diff_cap_0 = diff_cap / avg_efficiency
1215+
p_nom_sum = n.links.loc[links_i, "p_nom"].sum()
1216+
if p_nom_sum == 0:
1217+
logger.warning(
1218+
f"Zero total p_nom for {carrier} in region {region}. Skipping adjustment."
1219+
)
1220+
continue
1221+
1222+
scaling_factors = n.links.loc[links_i].eval("p_nom / @p_nom_sum")
1223+
n.links.loc[links_i, "p_nom"] += scaling_factors * diff_cap_0
1224+
1225+
links_i_current = n.links.loc[links_i][
1226+
(n.links.loc[links_i].p_nom_min != 0)
1227+
& n.links.loc[links_i].p_nom_extendable
1228+
].index
1229+
n.links.loc[links_i_current, "p_nom_min"] = n.links.loc[
1230+
links_i_current, "p_nom"
1231+
]
1232+
1233+
11711234
if __name__ == "__main__":
11721235
if "snakemake" not in globals():
11731236
import os
@@ -1184,7 +1247,7 @@ def drop_duplicate_transmission_projects(n):
11841247
opts="",
11851248
ll="vopt",
11861249
sector_opts="none",
1187-
planning_horizons="2025",
1250+
planning_horizons="2020",
11881251
run="KN2045_Bal_v4",
11891252
)
11901253

@@ -1241,12 +1304,8 @@ def drop_duplicate_transmission_projects(n):
12411304
snakemake.params.transmission_costs,
12421305
)
12431306

1244-
if snakemake.params.biogas_must_run["enable"]:
1245-
must_run_biogas(
1246-
n,
1247-
snakemake.params.biogas_must_run["p_min_pu"],
1248-
snakemake.params.biogas_must_run["regions"],
1249-
)
1307+
if snakemake.params.must_run is not None:
1308+
must_run(n, snakemake.params.must_run)
12501309

12511310
if snakemake.params.H2_plants["enable"]:
12521311
if snakemake.params.H2_plants["start"] <= int(
@@ -1266,4 +1325,6 @@ def drop_duplicate_transmission_projects(n):
12661325

12671326
force_connection_nep_offshore(n, current_year)
12681327

1328+
scale_capacity(n, snakemake.params.scale_capacity)
1329+
12691330
n.export_to_netcdf(snakemake.output.network)

0 commit comments

Comments
 (0)