From bf79b4a817b33c8909121ff58ee405f629d676e0 Mon Sep 17 00:00:00 2001 From: LukasFrankenQ Date: Sun, 12 Nov 2023 20:14:04 +0000 Subject: [PATCH] added flexible operation --- config/config.default.yaml | 2 ++ scripts/prepare_sector_network.py | 22 ++++++++++++++++++++++ scripts/solve_network.py | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/config/config.default.yaml b/config/config.default.yaml index c00c6e25..7bb75c40 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -513,6 +513,8 @@ sector: enhanced_geothermal_performant: true # if true, adds only the cheapest patch of EGS potential to each region enhanced_geothermal_flexible: true # if true, adds a storage unit simulating flexible operation of EGS, see Ricks et al. 2023 enhanced_geothermal_var_cf: true # if true, adds time-dependent capacity factor to EGS, see Ricks et al. 2023 + enhanced_geothermal_reservoir_max_hours: 240 # relavant for flexible EGS, see Ricks et al. 2023 + enhanced_geothermal_reservoir_max_boost: 0.25 # share of generation that can be added by flexible EGS, see Ricks et al. 2023 # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#industry industry: diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 68374785..2017e9d6 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3468,6 +3468,28 @@ def add_enhanced_geothermal( efficiency=efficiency_dh * 2., p_nom_extendable=True, ) + else: + n.links.at[bus + " geothermal organic rankine cycle", "efficiency"] = efficiency_orc + + if snakemake.params.sector["enhanced_geothermal_flexible"]: + + # this StorageUnit represents flexible operation using the geothermal reservoir. + # Hence, it is intuitively wrong to install it at the surface bus, + # this is however the more lean and computationally efficient solution. + + max_hours = snakemake.params.sector["enhanced_geothermal_reservoir_max_hours"] + boost = snakemake.params.sector["enhanced_geothermal_reservoir_max_boost"] + + max_hours = max_hours * boost + n.add( + "StorageUnit", + bus + ' geothermal reservoir', + bus=f"geothermal heat surface {bus}", + carrier="geothermal heat", + p_nom_extendable=True, + p_min_pu=-1. - boost, + max_hours=max_hours, + ) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index bdd75532..c299a0f1 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -777,6 +777,23 @@ def add_geothermal_chp_constraint(n): ) +def add_flexible_egs_constraint(n): + well_index = n.links.loc[n.links.carrier == 'geothermal heat'].index + storage_index = n.storage_units.loc[n.storage_units.carrier == 'geothermal heat '].index + + p_nom_rhs = ( + n.model["Link-p_nom"].loc[well_index] + ) + p_nom_lhs = ( + n.model["StorageUnit-p_nom"].loc[storage_index] + ) + + n.model.add_constraints( + p_nom_lhs <= p_nom_rhs, + name="Upper bounds the charging capacity of the storage unit", + ) + + def extra_functionality(n, snapshots): """ Collects supplementary constraints which will be passed to @@ -808,6 +825,8 @@ def extra_functionality(n, snapshots): add_retrofit_gas_boiler_constraint(n, snapshots) if "geothermal district heat" in n.links.carrier: add_geothermal_chp_constraint(n) + if config["sector"]["enhanced_geothermal_flexible"]: + add_flexible_egs_constraint(n) def solve_network(n, config, solving, opts="", **kwargs):