move calculation of district heating share to its own script
Now the script build_district_heat_share.py does what the old function create_nodes_for_heating() in prepare_sector_networks.py did. There is no need to build nodes lists for each heating sector, since all nodes have district heating now.
This commit is contained in:
parent
bd8a5ecf2b
commit
1a477d6b32
@ -710,6 +710,27 @@ rule build_transport_demand:
|
|||||||
"../scripts/build_transport_demand.py"
|
"../scripts/build_transport_demand.py"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rule build_district_heat_share:
|
||||||
|
params:
|
||||||
|
sector=config["sector"],
|
||||||
|
input:
|
||||||
|
district_heat_share=RESOURCES + "district_heat_share.csv",
|
||||||
|
clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv",
|
||||||
|
output:
|
||||||
|
district_heat_share=RESOURCES + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv",
|
||||||
|
threads: 1
|
||||||
|
resources:
|
||||||
|
mem_mb=1000,
|
||||||
|
log:
|
||||||
|
LOGS + "build_district_heat_share_s{simpl}_{clusters}_{planning_horizons}.log",
|
||||||
|
conda:
|
||||||
|
"../envs/environment.yaml"
|
||||||
|
script:
|
||||||
|
"../scripts/build_district_heat_share.py"
|
||||||
|
|
||||||
|
|
||||||
rule prepare_sector_network:
|
rule prepare_sector_network:
|
||||||
params:
|
params:
|
||||||
co2_budget=config["co2_budget"],
|
co2_budget=config["co2_budget"],
|
||||||
@ -762,6 +783,7 @@ rule prepare_sector_network:
|
|||||||
industrial_demand=RESOURCES
|
industrial_demand=RESOURCES
|
||||||
+ "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv",
|
+ "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv",
|
||||||
hourly_heat_demand_total=RESOURCES + "hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc",
|
hourly_heat_demand_total=RESOURCES + "hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc",
|
||||||
|
district_heat_share=RESOURCES + "district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv",
|
||||||
temp_soil_total=RESOURCES + "temp_soil_total_elec_s{simpl}_{clusters}.nc",
|
temp_soil_total=RESOURCES + "temp_soil_total_elec_s{simpl}_{clusters}.nc",
|
||||||
temp_soil_rural=RESOURCES + "temp_soil_rural_elec_s{simpl}_{clusters}.nc",
|
temp_soil_rural=RESOURCES + "temp_soil_rural_elec_s{simpl}_{clusters}.nc",
|
||||||
temp_soil_urban=RESOURCES + "temp_soil_urban_elec_s{simpl}_{clusters}.nc",
|
temp_soil_urban=RESOURCES + "temp_soil_urban_elec_s{simpl}_{clusters}.nc",
|
||||||
|
77
scripts/build_district_heat_share.py
Normal file
77
scripts/build_district_heat_share.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
"""
|
||||||
|
Build district heat shares at each node, depending on investment year.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
from prepare_sector_network import get
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if "snakemake" not in globals():
|
||||||
|
from _helpers import mock_snakemake
|
||||||
|
|
||||||
|
snakemake = mock_snakemake(
|
||||||
|
"build_heat_demands",
|
||||||
|
simpl="",
|
||||||
|
clusters=48,
|
||||||
|
)
|
||||||
|
|
||||||
|
investment_year = int(snakemake.wildcards.planning_horizons[-4:])
|
||||||
|
|
||||||
|
pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout,
|
||||||
|
index_col=0)
|
||||||
|
|
||||||
|
district_heat_share = pd.read_csv(snakemake.input.district_heat_share,
|
||||||
|
index_col=0).squeeze()
|
||||||
|
|
||||||
|
# make ct-based share nodal
|
||||||
|
district_heat_share = district_heat_share.loc[pop_layout.ct]
|
||||||
|
district_heat_share.index = pop_layout.index
|
||||||
|
|
||||||
|
# total urban population per country
|
||||||
|
ct_urban = pop_layout.urban.groupby(pop_layout.ct).sum()
|
||||||
|
|
||||||
|
# distribution of urban population within a country
|
||||||
|
pop_layout["urban_ct_fraction"] = pop_layout.urban / pop_layout.ct.map(ct_urban.get)
|
||||||
|
|
||||||
|
# fraction of node that is urban
|
||||||
|
urban_fraction = pop_layout.urban / pop_layout[["rural", "urban"]].sum(axis=1)
|
||||||
|
|
||||||
|
# maximum potential of urban demand covered by district heating
|
||||||
|
central_fraction = snakemake.config["sector"]["district_heating"]["potential"]
|
||||||
|
|
||||||
|
# district heating share at each node
|
||||||
|
dist_fraction_node = (
|
||||||
|
district_heat_share * pop_layout["urban_ct_fraction"] / pop_layout["fraction"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# if district heating share larger than urban fraction -> set urban
|
||||||
|
# fraction to district heating share
|
||||||
|
urban_fraction = pd.concat([urban_fraction, dist_fraction_node], axis=1).max(axis=1)
|
||||||
|
|
||||||
|
# difference of max potential and today's share of district heating
|
||||||
|
diff = (urban_fraction * central_fraction) - dist_fraction_node
|
||||||
|
progress = get(snakemake.config["sector"]["district_heating"]["progress"], investment_year)
|
||||||
|
dist_fraction_node += diff * progress
|
||||||
|
logger.info(
|
||||||
|
f"Increase district heating share by a progress factor of {progress:.2%} "
|
||||||
|
f"resulting in new average share of {dist_fraction_node.mean():.2%}"
|
||||||
|
)
|
||||||
|
|
||||||
|
df = pd.DataFrame(dtype=float)
|
||||||
|
|
||||||
|
df["original district heat share"] = district_heat_share
|
||||||
|
df["district fraction of node"] = dist_fraction_node
|
||||||
|
df["urban fraction"] = urban_fraction
|
||||||
|
|
||||||
|
df.to_csv(snakemake.output.district_heat_share)
|
@ -568,7 +568,7 @@ def build_energy_totals(countries, eurostat, swiss, idees):
|
|||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
def build_district_heat_share(idees):
|
def build_district_heat_share(countries, idees):
|
||||||
|
|
||||||
# district heating share
|
# district heating share
|
||||||
district_heat = idees[
|
district_heat = idees[
|
||||||
@ -578,6 +578,8 @@ def build_district_heat_share(idees):
|
|||||||
|
|
||||||
district_heat_share = district_heat/total_heat
|
district_heat_share = district_heat/total_heat
|
||||||
|
|
||||||
|
district_heat_share = district_heat_share.reindex(countries)
|
||||||
|
|
||||||
# Missing district heating share
|
# Missing district heating share
|
||||||
dh_share = pd.read_csv(
|
dh_share = pd.read_csv(
|
||||||
snakemake.input.district_heat_share, index_col=0, usecols=[0, 1]
|
snakemake.input.district_heat_share, index_col=0, usecols=[0, 1]
|
||||||
@ -758,7 +760,7 @@ if __name__ == "__main__":
|
|||||||
energy = build_energy_totals(countries, eurostat, swiss, idees)
|
energy = build_energy_totals(countries, eurostat, swiss, idees)
|
||||||
energy.to_csv(snakemake.output.energy_name)
|
energy.to_csv(snakemake.output.energy_name)
|
||||||
|
|
||||||
district_heat_share = build_district_heat_share(idees)
|
district_heat_share = build_district_heat_share(countries, idees)
|
||||||
district_heat_share.to_csv(snakemake.output.district_heat_share)
|
district_heat_share.to_csv(snakemake.output.district_heat_share)
|
||||||
|
|
||||||
base_year_emissions = params["base_emissions_year"]
|
base_year_emissions = params["base_emissions_year"]
|
||||||
|
@ -26,9 +26,4 @@ if __name__ == "__main__":
|
|||||||
nodal_energy_totals.index = pop_layout.index
|
nodal_energy_totals.index = pop_layout.index
|
||||||
nodal_energy_totals = nodal_energy_totals.multiply(pop_layout.fraction, axis=0)
|
nodal_energy_totals = nodal_energy_totals.multiply(pop_layout.fraction, axis=0)
|
||||||
|
|
||||||
# district heating share should not be divided by population fraction
|
|
||||||
dh_share = energy_totals["district heat share"].loc[pop_layout.ct].fillna(0.0)
|
|
||||||
dh_share.index = pop_layout.index
|
|
||||||
nodal_energy_totals["district heat share"] = dh_share
|
|
||||||
|
|
||||||
nodal_energy_totals.to_csv(snakemake.output[0])
|
nodal_energy_totals.to_csv(snakemake.output[0])
|
||||||
|
@ -1678,7 +1678,10 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
heat_demand = build_heat_demand(n)
|
heat_demand = build_heat_demand(n)
|
||||||
|
|
||||||
nodes, dist_fraction, urban_fraction = create_nodes_for_heat_sector()
|
district_heat_info = pd.read_csv(snakemake.input.district_heat_share,
|
||||||
|
index_col=0)
|
||||||
|
dist_fraction = district_heat_info["district fraction of node"]
|
||||||
|
urban_fraction = district_heat_info["urban fraction"]
|
||||||
|
|
||||||
# NB: must add costs of central heating afterwards (EUR 400 / kWpeak, 50a, 1% FOM from Fraunhofer ISE)
|
# NB: must add costs of central heating afterwards (EUR 400 / kWpeak, 50a, 1% FOM from Fraunhofer ISE)
|
||||||
|
|
||||||
@ -1715,6 +1718,8 @@ def add_heat(n, costs):
|
|||||||
# 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2
|
# 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2
|
||||||
solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3
|
solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3
|
||||||
|
|
||||||
|
nodes = pop_layout.index
|
||||||
|
|
||||||
for name in heat_systems:
|
for name in heat_systems:
|
||||||
name_type = "central" if name == "urban central" else "decentral"
|
name_type = "central" if name == "urban central" else "decentral"
|
||||||
|
|
||||||
@ -1722,8 +1727,8 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Bus",
|
"Bus",
|
||||||
nodes[name] + f" {name} heat",
|
nodes + f" {name} heat",
|
||||||
location=nodes[name],
|
location=nodes,
|
||||||
carrier=name + " heat",
|
carrier=name + " heat",
|
||||||
unit="MWh_th",
|
unit="MWh_th",
|
||||||
)
|
)
|
||||||
@ -1731,9 +1736,9 @@ def add_heat(n, costs):
|
|||||||
if name == "urban central" and options.get("central_heat_vent"):
|
if name == "urban central" and options.get("central_heat_vent"):
|
||||||
n.madd(
|
n.madd(
|
||||||
"Generator",
|
"Generator",
|
||||||
nodes[name] + f" {name} heat vent",
|
nodes + f" {name} heat vent",
|
||||||
bus=nodes[name] + f" {name} heat",
|
bus=nodes + f" {name} heat",
|
||||||
location=nodes[name],
|
location=nodes,
|
||||||
carrier=name + " heat vent",
|
carrier=name + " heat vent",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
p_max_pu=0,
|
p_max_pu=0,
|
||||||
@ -1746,11 +1751,11 @@ def add_heat(n, costs):
|
|||||||
for sector in sectors:
|
for sector in sectors:
|
||||||
# heat demand weighting
|
# heat demand weighting
|
||||||
if "rural" in name:
|
if "rural" in name:
|
||||||
factor = 1 - urban_fraction[nodes[name]]
|
factor = 1 - urban_fraction[nodes]
|
||||||
elif "urban central" in name:
|
elif "urban central" in name:
|
||||||
factor = dist_fraction[nodes[name]]
|
factor = dist_fraction[nodes]
|
||||||
elif "urban decentral" in name:
|
elif "urban decentral" in name:
|
||||||
factor = urban_fraction[nodes[name]] - dist_fraction[nodes[name]]
|
factor = urban_fraction[nodes] - dist_fraction[nodes]
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
f" {name} not in " f"heat systems: {heat_systems}"
|
f" {name} not in " f"heat systems: {heat_systems}"
|
||||||
@ -1761,7 +1766,7 @@ def add_heat(n, costs):
|
|||||||
heat_demand[[sector + " water", sector + " space"]]
|
heat_demand[[sector + " water", sector + " space"]]
|
||||||
.T.groupby(level=1)
|
.T.groupby(level=1)
|
||||||
.sum()
|
.sum()
|
||||||
.T[nodes[name]]
|
.T[nodes]
|
||||||
.multiply(factor)
|
.multiply(factor)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1769,7 +1774,7 @@ def add_heat(n, costs):
|
|||||||
heat_load = (
|
heat_load = (
|
||||||
heat_demand.T.groupby(level=1)
|
heat_demand.T.groupby(level=1)
|
||||||
.sum()
|
.sum()
|
||||||
.T[nodes[name]]
|
.T[nodes]
|
||||||
.multiply(
|
.multiply(
|
||||||
factor * (1 + options["district_heating"]["district_heating_loss"])
|
factor * (1 + options["district_heating"]["district_heating_loss"])
|
||||||
)
|
)
|
||||||
@ -1777,9 +1782,9 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Load",
|
"Load",
|
||||||
nodes[name],
|
nodes,
|
||||||
suffix=f" {name} heat",
|
suffix=f" {name} heat",
|
||||||
bus=nodes[name] + f" {name} heat",
|
bus=nodes + f" {name} heat",
|
||||||
carrier=name + " heat",
|
carrier=name + " heat",
|
||||||
p_set=heat_load,
|
p_set=heat_load,
|
||||||
)
|
)
|
||||||
@ -1790,17 +1795,17 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
costs_name = f"{name_type} {heat_pump_type}-sourced heat pump"
|
costs_name = f"{name_type} {heat_pump_type}-sourced heat pump"
|
||||||
efficiency = (
|
efficiency = (
|
||||||
cop[heat_pump_type][nodes[name]]
|
cop[heat_pump_type][nodes]
|
||||||
if options["time_dep_hp_cop"]
|
if options["time_dep_hp_cop"]
|
||||||
else costs.at[costs_name, "efficiency"]
|
else costs.at[costs_name, "efficiency"]
|
||||||
)
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes[name],
|
nodes,
|
||||||
suffix=f" {name} {heat_pump_type} heat pump",
|
suffix=f" {name} {heat_pump_type} heat pump",
|
||||||
bus0=nodes[name],
|
bus0=nodes,
|
||||||
bus1=nodes[name] + f" {name} heat",
|
bus1=nodes + f" {name} heat",
|
||||||
carrier=f"{name} {heat_pump_type} heat pump",
|
carrier=f"{name} {heat_pump_type} heat pump",
|
||||||
efficiency=efficiency,
|
efficiency=efficiency,
|
||||||
capital_cost=costs.at[costs_name, "efficiency"]
|
capital_cost=costs.at[costs_name, "efficiency"]
|
||||||
@ -1814,17 +1819,17 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Bus",
|
"Bus",
|
||||||
nodes[name] + f" {name} water tanks",
|
nodes + f" {name} water tanks",
|
||||||
location=nodes[name],
|
location=nodes,
|
||||||
carrier=name + " water tanks",
|
carrier=name + " water tanks",
|
||||||
unit="MWh_th",
|
unit="MWh_th",
|
||||||
)
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes[name] + f" {name} water tanks charger",
|
nodes + f" {name} water tanks charger",
|
||||||
bus0=nodes[name] + f" {name} heat",
|
bus0=nodes + f" {name} heat",
|
||||||
bus1=nodes[name] + f" {name} water tanks",
|
bus1=nodes + f" {name} water tanks",
|
||||||
efficiency=costs.at["water tank charger", "efficiency"],
|
efficiency=costs.at["water tank charger", "efficiency"],
|
||||||
carrier=name + " water tanks charger",
|
carrier=name + " water tanks charger",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
@ -1832,9 +1837,9 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes[name] + f" {name} water tanks discharger",
|
nodes + f" {name} water tanks discharger",
|
||||||
bus0=nodes[name] + f" {name} water tanks",
|
bus0=nodes + f" {name} water tanks",
|
||||||
bus1=nodes[name] + f" {name} heat",
|
bus1=nodes + f" {name} heat",
|
||||||
carrier=name + " water tanks discharger",
|
carrier=name + " water tanks discharger",
|
||||||
efficiency=costs.at["water tank discharger", "efficiency"],
|
efficiency=costs.at["water tank discharger", "efficiency"],
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
@ -1853,8 +1858,8 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Store",
|
"Store",
|
||||||
nodes[name] + f" {name} water tanks",
|
nodes + f" {name} water tanks",
|
||||||
bus=nodes[name] + f" {name} water tanks",
|
bus=nodes + f" {name} water tanks",
|
||||||
e_cyclic=True,
|
e_cyclic=True,
|
||||||
e_nom_extendable=True,
|
e_nom_extendable=True,
|
||||||
carrier=name + " water tanks",
|
carrier=name + " water tanks",
|
||||||
@ -1868,9 +1873,9 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes[name] + f" {name} resistive heater",
|
nodes + f" {name} resistive heater",
|
||||||
bus0=nodes[name],
|
bus0=nodes,
|
||||||
bus1=nodes[name] + f" {name} heat",
|
bus1=nodes + f" {name} heat",
|
||||||
carrier=name + " resistive heater",
|
carrier=name + " resistive heater",
|
||||||
efficiency=costs.at[key, "efficiency"],
|
efficiency=costs.at[key, "efficiency"],
|
||||||
capital_cost=costs.at[key, "efficiency"] * costs.at[key, "fixed"],
|
capital_cost=costs.at[key, "efficiency"] * costs.at[key, "fixed"],
|
||||||
@ -1883,10 +1888,10 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes[name] + f" {name} gas boiler",
|
nodes + f" {name} gas boiler",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
bus0=spatial.gas.df.loc[nodes[name], "nodes"].values,
|
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
|
||||||
bus1=nodes[name] + f" {name} heat",
|
bus1=nodes + f" {name} heat",
|
||||||
bus2="co2 atmosphere",
|
bus2="co2 atmosphere",
|
||||||
carrier=name + " gas boiler",
|
carrier=name + " gas boiler",
|
||||||
efficiency=costs.at[key, "efficiency"],
|
efficiency=costs.at[key, "efficiency"],
|
||||||
@ -1900,13 +1905,13 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Generator",
|
"Generator",
|
||||||
nodes[name],
|
nodes,
|
||||||
suffix=f" {name} solar thermal collector",
|
suffix=f" {name} solar thermal collector",
|
||||||
bus=nodes[name] + f" {name} heat",
|
bus=nodes + f" {name} heat",
|
||||||
carrier=name + " solar thermal",
|
carrier=name + " solar thermal",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
capital_cost=costs.at[name_type + " solar thermal", "fixed"],
|
capital_cost=costs.at[name_type + " solar thermal", "fixed"],
|
||||||
p_max_pu=solar_thermal[nodes[name]],
|
p_max_pu=solar_thermal[nodes],
|
||||||
lifetime=costs.at[name_type + " solar thermal", "lifetime"],
|
lifetime=costs.at[name_type + " solar thermal", "lifetime"],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1914,10 +1919,10 @@ def add_heat(n, costs):
|
|||||||
# add gas CHP; biomass CHP is added in biomass section
|
# add gas CHP; biomass CHP is added in biomass section
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes[name] + " urban central gas CHP",
|
nodes + " urban central gas CHP",
|
||||||
bus0=spatial.gas.df.loc[nodes[name], "nodes"].values,
|
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
|
||||||
bus1=nodes[name],
|
bus1=nodes,
|
||||||
bus2=nodes[name] + " urban central heat",
|
bus2=nodes + " urban central heat",
|
||||||
bus3="co2 atmosphere",
|
bus3="co2 atmosphere",
|
||||||
carrier="urban central gas CHP",
|
carrier="urban central gas CHP",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
@ -1933,12 +1938,12 @@ def add_heat(n, costs):
|
|||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes[name] + " urban central gas CHP CC",
|
nodes + " urban central gas CHP CC",
|
||||||
bus0=spatial.gas.df.loc[nodes[name], "nodes"].values,
|
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
|
||||||
bus1=nodes[name],
|
bus1=nodes,
|
||||||
bus2=nodes[name] + " urban central heat",
|
bus2=nodes + " urban central heat",
|
||||||
bus3="co2 atmosphere",
|
bus3="co2 atmosphere",
|
||||||
bus4=spatial.co2.df.loc[nodes[name], "nodes"].values,
|
bus4=spatial.co2.df.loc[nodes, "nodes"].values,
|
||||||
carrier="urban central gas CHP CC",
|
carrier="urban central gas CHP CC",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
capital_cost=costs.at["central gas CHP", "fixed"]
|
capital_cost=costs.at["central gas CHP", "fixed"]
|
||||||
@ -1970,11 +1975,11 @@ def add_heat(n, costs):
|
|||||||
if options["chp"] and options["micro_chp"] and name != "urban central":
|
if options["chp"] and options["micro_chp"] and name != "urban central":
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes[name] + f" {name} micro gas CHP",
|
nodes + f" {name} micro gas CHP",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
bus0=spatial.gas.df.loc[nodes[name], "nodes"].values,
|
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
|
||||||
bus1=nodes[name],
|
bus1=nodes,
|
||||||
bus2=nodes[name] + f" {name} heat",
|
bus2=nodes + f" {name} heat",
|
||||||
bus3="co2 atmosphere",
|
bus3="co2 atmosphere",
|
||||||
carrier=name + " micro gas CHP",
|
carrier=name + " micro gas CHP",
|
||||||
efficiency=costs.at["micro CHP", "efficiency"],
|
efficiency=costs.at["micro CHP", "efficiency"],
|
||||||
@ -2105,50 +2110,6 @@ def add_heat(n, costs):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_nodes_for_heat_sector():
|
|
||||||
# TODO pop_layout
|
|
||||||
|
|
||||||
# rural are areas with low heating density and individual heating
|
|
||||||
# urban are areas with high heating density
|
|
||||||
# urban can be split into district heating (central) and individual heating (decentral)
|
|
||||||
|
|
||||||
ct_urban = pop_layout.urban.groupby(pop_layout.ct).sum()
|
|
||||||
# distribution of urban population within a country
|
|
||||||
pop_layout["urban_ct_fraction"] = pop_layout.urban / pop_layout.ct.map(ct_urban.get)
|
|
||||||
|
|
||||||
sectors = ["residential", "services"]
|
|
||||||
|
|
||||||
nodes = {}
|
|
||||||
urban_fraction = pop_layout.urban / pop_layout[["rural", "urban"]].sum(axis=1)
|
|
||||||
|
|
||||||
for sector in sectors:
|
|
||||||
nodes[sector + " rural"] = pop_layout.index
|
|
||||||
nodes[sector + " urban decentral"] = pop_layout.index
|
|
||||||
|
|
||||||
district_heat_share = pop_weighted_energy_totals["district heat share"]
|
|
||||||
|
|
||||||
# maximum potential of urban demand covered by district heating
|
|
||||||
central_fraction = options["district_heating"]["potential"]
|
|
||||||
# district heating share at each node
|
|
||||||
dist_fraction_node = (
|
|
||||||
district_heat_share * pop_layout["urban_ct_fraction"] / pop_layout["fraction"]
|
|
||||||
)
|
|
||||||
nodes["urban central"] = dist_fraction_node.index
|
|
||||||
# if district heating share larger than urban fraction -> set urban
|
|
||||||
# fraction to district heating share
|
|
||||||
urban_fraction = pd.concat([urban_fraction, dist_fraction_node], axis=1).max(axis=1)
|
|
||||||
# difference of max potential and today's share of district heating
|
|
||||||
diff = (urban_fraction * central_fraction) - dist_fraction_node
|
|
||||||
progress = get(options["district_heating"]["progress"], investment_year)
|
|
||||||
dist_fraction_node += diff * progress
|
|
||||||
logger.info(
|
|
||||||
f"Increase district heating share by a progress factor of {progress:.2%} "
|
|
||||||
f"resulting in new average share of {dist_fraction_node.mean():.2%}"
|
|
||||||
)
|
|
||||||
|
|
||||||
return nodes, dist_fraction_node, urban_fraction
|
|
||||||
|
|
||||||
|
|
||||||
def add_biomass(n, costs):
|
def add_biomass(n, costs):
|
||||||
logger.info("Add biomass")
|
logger.info("Add biomass")
|
||||||
|
|
||||||
@ -2366,7 +2327,7 @@ def add_biomass(n, costs):
|
|||||||
|
|
||||||
if options["biomass_boiler"]:
|
if options["biomass_boiler"]:
|
||||||
# TODO: Add surcharge for pellets
|
# TODO: Add surcharge for pellets
|
||||||
nodes_heat = create_nodes_for_heat_sector()[0]
|
nodes = pop_layout.index
|
||||||
for name in [
|
for name in [
|
||||||
"residential rural",
|
"residential rural",
|
||||||
"services rural",
|
"services rural",
|
||||||
@ -2375,10 +2336,10 @@ def add_biomass(n, costs):
|
|||||||
]:
|
]:
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes_heat[name] + f" {name} biomass boiler",
|
nodes + f" {name} biomass boiler",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
bus0=spatial.biomass.df.loc[nodes_heat[name], "nodes"].values,
|
bus0=spatial.biomass.df.loc[nodes, "nodes"].values,
|
||||||
bus1=nodes_heat[name] + f" {name} heat",
|
bus1=nodes + f" {name} heat",
|
||||||
carrier=name + " biomass boiler",
|
carrier=name + " biomass boiler",
|
||||||
efficiency=costs.at["biomass boiler", "efficiency"],
|
efficiency=costs.at["biomass boiler", "efficiency"],
|
||||||
capital_cost=costs.at["biomass boiler", "efficiency"]
|
capital_cost=costs.at["biomass boiler", "efficiency"]
|
||||||
@ -2821,7 +2782,7 @@ def add_industry(n, costs):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if options["oil_boilers"]:
|
if options["oil_boilers"]:
|
||||||
nodes_heat = create_nodes_for_heat_sector()[0]
|
nodes = pop_layout.index
|
||||||
|
|
||||||
for name in [
|
for name in [
|
||||||
"residential rural",
|
"residential rural",
|
||||||
@ -2831,10 +2792,10 @@ def add_industry(n, costs):
|
|||||||
]:
|
]:
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes_heat[name] + f" {name} oil boiler",
|
nodes + f" {name} oil boiler",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
bus0=spatial.oil.nodes,
|
bus0=spatial.oil.nodes,
|
||||||
bus1=nodes_heat[name] + f" {name} heat",
|
bus1=nodes + f" {name} heat",
|
||||||
bus2="co2 atmosphere",
|
bus2="co2 atmosphere",
|
||||||
carrier=f"{name} oil boiler",
|
carrier=f"{name} oil boiler",
|
||||||
efficiency=costs.at["decentral oil boiler", "efficiency"],
|
efficiency=costs.at["decentral oil boiler", "efficiency"],
|
||||||
|
Loading…
Reference in New Issue
Block a user