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

Transition from stores to storage units for LTES, introducing energy-to-power ratio #1444

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions config/config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,8 @@ plotting:
residential urban decentral water tanks discharger: '#baac9e'
services rural water tanks discharger: '#bbc2b8'
services urban decentral water tanks discharger: '#bdd8d3'
water pits: '#cc826a'
cpschau marked this conversation as resolved.
Show resolved Hide resolved
urban central hot water pits: '#d96f4c'
# heat demand
Heat load: '#cc1f1f'
heat: '#cc1f1f'
Expand Down
2 changes: 2 additions & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Release Notes
Upcoming Release
================

* Added PTES and transitioned LTES stores to storage units to implement an energy-to-power ratio in ``prepare_sector_network``.

* Feature: Introduce geothermal district heating (direct utilisation and heat pumps). Potentials are based on `Manz et al. 2024: Spatial analysis of renewable and excess heat potentials for climate-neutral district heating in Europe <https://www.sciencedirect.com/science/article/pii/S0960148124001769>`.

* Feature: Allow CHPs to use different fuel sources such as gas, oil, coal, and methanol. Note that the cost assumptions are based on a gas CHP (except for solid biomass-fired CHP).
Expand Down
76 changes: 43 additions & 33 deletions scripts/prepare_sector_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -2264,56 +2264,66 @@ def add_heat(
)

if options["tes"]:
n.add("Carrier", f"{heat_system} water tanks")

n.add(
"Bus",
nodes + f" {heat_system} water tanks",
location=nodes,
carrier=f"{heat_system} water tanks",
unit="MWh_th",
)

n.add(
"Link",
nodes + f" {heat_system} water tanks charger",
bus0=nodes + f" {heat_system} heat",
bus1=nodes + f" {heat_system} water tanks",
efficiency=costs.at["water tank charger", "efficiency"],
carrier=f"{heat_system} water tanks charger",
p_nom_extendable=True,
)

n.add(
"Link",
nodes + f" {heat_system} water tanks discharger",
bus0=nodes + f" {heat_system} water tanks",
bus1=nodes + f" {heat_system} heat",
carrier=f"{heat_system} water tanks discharger",
efficiency=costs.at["water tank discharger", "efficiency"],
p_nom_extendable=True,
)
n.add("Carrier", f"{heat_system} water tanks")

tes_time_constant_days = options["tes_tau"][
heat_system.central_or_decentral
]

n.add(
"Store",
"StorageUnit",
nodes + f" {heat_system} water tanks",
bus=nodes + f" {heat_system} water tanks",
e_cyclic=True,
e_nom_extendable=True,
bus=nodes + f" {heat_system} heat",
carrier=f"{heat_system} water tanks",
efficiency_store=costs.at[
heat_system.central_or_decentral + " water tank charger",
"efficiency",
],
max_hours=costs.at[
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TTES in district heating and decentral water tanks do not have the same EtP ratio.

heat_system.central_or_decentral + " water tank storage",
"energy to power ratio",
],
efficiency_dispatch=costs.at[
heat_system.central_or_decentral + " water tank discharger",
"efficiency",
],
p_nom_extendable=True,
standing_loss=1 - np.exp(-1 / 24 / tes_time_constant_days),
capital_cost=costs.at[
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capital costs are related to power not to energy capacity --> Conversion from €/MWh to €/MW using energy to power ratio.

heat_system.central_or_decentral + " water tank storage", "fixed"
],
lifetime=costs.at[
heat_system.central_or_decentral + " water tank storage", "lifetime"
],
cyclic_state_of_charge=True,
)

if heat_system == HeatSystem.URBAN_CENTRAL:

n.add("Carrier", f"{heat_system} water pits")

n.add(
"StorageUnit",
nodes + f" {heat_system} water pits",
bus=nodes + f" {heat_system} heat",
carrier=f"{heat_system} water pits",
efficiency_store=costs.at[
"central water pit charger", "efficiency"
],
max_hours=costs.at[
"central water pit storage", "energy to power ratio"
],
efficiency_dispatch=costs.at[
"central water pit discharger", "efficiency"
],
p_nom_extendable=True,
standing_loss=1 - np.exp(-1 / 24 / tes_time_constant_days),
capital_cost=costs.at["central water pit storage", "fixed"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Capital costs need to be converted according to unit.

lifetime=costs.at["central water pit storage", "lifetime"],
cyclic_state_of_charge=True,
)

if options["resistive_heaters"]:
key = f"{heat_system.central_or_decentral} resistive heater"

Expand Down Expand Up @@ -4254,7 +4264,7 @@ def define_clustering(attributes, aggregate_dict):
return agg

logger.info("Cluster residential and service heat buses.")
components = ["Bus", "Carrier", "Generator", "Link", "Load", "Store"]
components = ["Bus", "Carrier", "Generator", "Link", "Load", "Store", "StorageUnit"]

for c in n.iterate_components(components):
df = c.df
Expand Down