Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion config/config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -549,13 +549,48 @@ sector:
geothermal:
constant_temperature_celsius: 65
ignore_missing_regions: false
requires_generator: true
electrolysis excess:
constant_temperature_celsius: 70
ignore_missing_regions: false
requires_generator: false
fuel cell excess:
constant_temperature_celsius: 70 # assume same as electrolysis
ignore_missing_regions: false
requires_generator: false
Fischer-Tropsch excess:
constant_temperature_celsius: 200 # assuming steam
ignore_missing_regions: false
requires_generator: false
Haber-Bosch excess:
constant_temperature_celsius: 45 # 30-60C acc. to DEA catalogue
ignore_missing_regions: false
requires_generator: false
Sabatier excess:
constant_temperature_celsius: 200 # Agora report states process temperature of catalytic methanation of at least 200C
ignore_missing_regions: false
requires_generator: false
methanolisation excess:
constant_temperature_celsius: 70 # 50-100
ignore_missing_regions: false
requires_generator: false
direct_utilisation_heat_sources:
- geothermal
- electrolysis excess
- fuel cell excess
- Fischer-Tropsch excess
- Haber-Bosch excess
- Sabatier excess
- methanolisation excess
temperature_limited_stores:
- ptes
heat_pump_sources:
urban central:
- air
- electrolysis excess
- fuel cell excess
- Haber-Bosch excess
- methanolisation excess
urban decentral:
- air
rural:
Expand Down Expand Up @@ -743,7 +778,6 @@ sector:
use_methanolisation_waste_heat: 0.25
use_methanation_waste_heat: 0.25
use_fuel_cell_waste_heat: 1
use_electrolysis_waste_heat: 0.25
electricity_transmission_grid: true
electricity_distribution_grid: true
electricity_grid_connection: true
Expand Down
3 changes: 3 additions & 0 deletions config/plotting.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,9 @@ plotting:
H2 turbine: '#991f83'
H2 Electrolysis: '#ff29d9'
H2 electrolysis: '#ff29d9'
electrolysis excess heat: '#8c1549'
electrolysis excess heat pump: '#f593e3'
electrolysis excess heat direct utilisation: '#ff29d9'
# ammonia
NH3: '#46caf0'
ammonia: '#46caf0'
Expand Down
10 changes: 5 additions & 5 deletions rules/build_sector.smk
Original file line number Diff line number Diff line change
Expand Up @@ -1250,18 +1250,18 @@ rule build_egs_potentials:


def input_heat_source_power(w):

limited_heat_sources = config_provider(
"sector", "district_heating", "limited_heat_sources"
)(w)
return {
heat_source_name: resources(
"heat_source_power_" + heat_source_name + "_base_s_{clusters}.csv"
)
for heat_source_name in config_provider(
"sector", "heat_pump_sources", "urban central"
)(w)
if heat_source_name
in config_provider("sector", "district_heating", "limited_heat_sources")(
w
).keys()
if heat_source_name in limited_heat_sources.keys()
and limited_heat_sources[heat_source_name]["requires_generator"]
}


Expand Down
2 changes: 1 addition & 1 deletion scripts/build_cop_profiles/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def get_cop(
)
else:
raise ValueError(
f"Unknown heat source {heat_source}. Must be one of [ground, air] or {snakemake.params.heat_sources.keys()}."
f"Unknown heat source {heat_source}. Must be one of [ground, air, ptes] or {snakemake.params.limited_heat_sources.keys()}."
)

cop_da = get_cop(
Expand Down
2 changes: 1 addition & 1 deletion scripts/build_direct_heat_source_utilisation_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def get_source_temperature(heat_source_key: str):
else:
raise ValueError(
f"Unknown heat source {heat_source_key}. Must be one of "
f"{snakemake.params.heat_sources.keys()}."
f"{snakemake.params.direct_utilisation_heat_sources.keys()}."
)


Expand Down
2 changes: 1 addition & 1 deletion scripts/definitions/heat_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def heat_pump_costs_name(self, heat_source: str) -> str:
str
The name for the heat pump costs.
"""
if heat_source in ["ptes", "geothermal"]:
if heat_source in ["ptes", "geothermal", "electrolysis excess"]:
return f"{self.central_or_decentral} excess-heat-sourced heat pump"
else:
return f"{self.central_or_decentral} {heat_source}-sourced heat pump"
Expand Down
132 changes: 72 additions & 60 deletions scripts/prepare_sector_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -3195,12 +3195,6 @@ def add_heat(
)

if heat_source in params.limited_heat_sources:
# get potential
p_max_source = pd.read_csv(
heat_source_profile_files[heat_source],
index_col=0,
).squeeze()[nodes]

# add resource
heat_carrier = f"{heat_system} {heat_source} heat"
n.add("Carrier", heat_carrier)
Expand All @@ -3212,32 +3206,42 @@ def add_heat(
carrier=heat_carrier,
)

if heat_source in params.direct_utilisation_heat_sources:
capital_cost = (
costs.at[
heat_system.heat_source_costs_name(heat_source),
"capital_cost",
# Check if heat source requires a separate generator
heat_source_config = params.limited_heat_sources[heat_source]
requires_generator = heat_source_config["requires_generator"]

if requires_generator:
# Standard heat source with potential file and generator
p_max_source = pd.read_csv(
heat_source_profile_files[heat_source],
index_col=0,
).squeeze()[nodes]

if heat_source in params.direct_utilisation_heat_sources:
capital_cost = (
costs.at[
heat_system.heat_source_costs_name(heat_source),
"capital_cost",
]
* overdim_factor
)
lifetime = costs.at[
heat_system.heat_source_costs_name(heat_source), "lifetime"
]
* overdim_factor
else:
capital_cost = 0.0
lifetime = np.inf
n.add(
"Generator",
nodes,
suffix=f" {heat_carrier}",
bus=nodes + f" {heat_carrier}",
carrier=heat_carrier,
p_nom_extendable=True,
capital_cost=capital_cost,
lifetime=lifetime,
p_nom_max=p_max_source,
)
lifetime = costs.at[
heat_system.heat_source_costs_name(heat_source), "lifetime"
]
else:
capital_cost = 0.0
lifetime = np.inf
n.add(
"Generator",
nodes,
suffix=f" {heat_carrier}",
bus=nodes + f" {heat_carrier}",
carrier=heat_carrier,
p_nom_extendable=True,
capital_cost=capital_cost,
lifetime=lifetime,
p_nom_max=p_max_source,
)

# add heat pump converting source heat + electricity to urban central heat
n.add(
"Link",
Expand Down Expand Up @@ -5346,75 +5350,83 @@ def add_waste_heat(

# Fischer-Tropsch waste heat
if (
options["use_fischer_tropsch_waste_heat"]
"Fischer-Tropsch excess" in options["heat_pump_sources"]["urban central"]
and "Fischer-Tropsch" in link_carriers
):
n.links.loc[urban_central + " Fischer-Tropsch", "bus3"] = (
urban_central + " urban central heat"
)
n.links.loc[urban_central + " Fischer-Tropsch", "efficiency3"] = (
0.95 - n.links.loc[urban_central + " Fischer-Tropsch", "efficiency"]
) * options["use_fischer_tropsch_waste_heat"]
n.links.loc[urban_central + " Fischer-Tropsch", "efficiency3"] = costs.at[
"Fischer-Tropsch", "efficiency-heat"
]

# Sabatier process waste heat
if options["use_methanation_waste_heat"] and "Sabatier" in link_carriers:
if (
"Sabatier excess" in options["heat_pump_sources"]["urban central"]
and "Sabatier" in link_carriers
):
n.links.loc[urban_central + " Sabatier", "bus3"] = (
urban_central + " urban central heat"
)
n.links.loc[urban_central + " Sabatier", "efficiency3"] = (
0.95 - n.links.loc[urban_central + " Sabatier", "efficiency"]
) * options["use_methanation_waste_heat"]
1
- costs.at["methanation", "heat-losses"]
- n.links.loc[urban_central + " Sabatier", "efficiency"]
)

# Haber-Bosch process waste heat
if options["use_haber_bosch_waste_heat"] and "Haber-Bosch" in link_carriers:
if (
"Haber-Bosch excess" in options["heat_pump_sources"]["urban central"]
and "Haber-Bosch" in link_carriers
):
n.links.loc[urban_central + " Haber-Bosch", "bus3"] = (
urban_central + " urban central heat"
)
total_energy_input = (
cf_industry["MWh_H2_per_tNH3_electrolysis"]
+ cf_industry["MWh_elec_per_tNH3_electrolysis"]
) / cf_industry["MWh_NH3_per_tNH3"]
electricity_input = (
cf_industry["MWh_elec_per_tNH3_electrolysis"]
/ cf_industry["MWh_NH3_per_tNH3"]
)
n.links.loc[urban_central + " Haber-Bosch", "efficiency3"] = (
0.15 * total_energy_input / electricity_input
) * options["use_haber_bosch_waste_heat"]
n.links.loc[urban_central + " Haber-Bosch", "efficiency3"] = costs.at[
"Haber-Bosch", "efficiency-heat"
]

# Methanolisation waste heat
if (
options["use_methanolisation_waste_heat"]
"methanolisation excess" in options["heat_pump_sources"]["urban central"]
and "methanolisation" in link_carriers
):
n.links.loc[urban_central + " methanolisation", "bus4"] = (
urban_central + " urban central heat"
)
n.links.loc[urban_central + " methanolisation", "efficiency4"] = (
costs.at["methanolisation", "heat-output"]
/ costs.at["methanolisation", "hydrogen-input"]
) * options["use_methanolisation_waste_heat"]
n.links.loc[urban_central + " methanolisation", "efficiency4"] = costs.at[
"methanolisation", "efficiency-heat"
]

# Electrolysis waste heat
if (
options["use_electrolysis_waste_heat"]
"electrolysis excess" in options["heat_pump_sources"]["urban central"]
and "H2 Electrolysis" in link_carriers
):
# Connect electrolysis waste heat to electrolysis excess heat bus for heat pump boosting
n.links.loc[urban_central + " H2 Electrolysis", "bus2"] = (
urban_central + " urban central heat"
urban_central + " urban central electrolysis excess heat"
)
n.links.loc[urban_central + " H2 Electrolysis", "efficiency2"] = (
0.84 - n.links.loc[urban_central + " H2 Electrolysis", "efficiency"]
) * options["use_electrolysis_waste_heat"]
n.links.loc[urban_central + " H2 Electrolysis", "efficiency2"] = costs.at[
"H2 Electrolysis", "efficiency-heat"
]

# Fuel cell waste heat
if options["use_fuel_cell_waste_heat"] and "H2 Fuel Cell" in link_carriers:
if (
"fuel cell excess" in options["heat_pump_sources"]["urban central"]
and "H2 Fuel Cell" in link_carriers
):
n.links.loc[urban_central + " H2 Fuel Cell", "bus2"] = (
urban_central + " urban central heat"
)
n.links.loc[urban_central + " H2 Fuel Cell", "efficiency2"] = (
0.95 - n.links.loc[urban_central + " H2 Fuel Cell", "efficiency"]
) * options["use_fuel_cell_waste_heat"]
n.links.loc[urban_central + " H2 Fuel Cell", "efficiency2"] = (
1
- costs.at["fuel cell", "heat-losses"]
- n.links.loc[urban_central + " H2 Fuel Cell", "efficiency"]
)


def add_agriculture(
Expand Down
Loading