Merge branch 'fneum/services_heat'

This commit is contained in:
Fabian Neumann 2024-01-05 14:39:29 +01:00
commit 6dd9d6a9c1
5 changed files with 38 additions and 15 deletions

View File

@ -457,6 +457,7 @@ sector:
decentral: 3
central: 180
boilers: true
resistive_heaters: true
oil_boilers: false
biomass_boiler: true
chp: true

View File

@ -62,7 +62,8 @@ tes,--,"{true, false}",Add option for storing thermal energy in large water pits
tes_tau,,,The time constant used to calculate the decay of thermal energy in thermal energy storage (TES): 1- :math:`e^{-1/24τ}`.
-- decentral,days,float,The time constant in decentralized thermal energy storage (TES)
-- central,days,float,The time constant in centralized thermal energy storage (TES)
boilers,--,"{true, false}",Add option for transforming electricity into heat using resistive heater
boilers,--,"{true, false}",Add option for transforming gas into heat using gas boilers
resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers)
oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers
biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers
chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP)

1 Unit Values Description
62 tes_tau The time constant used to calculate the decay of thermal energy in thermal energy storage (TES): 1- :math:`e^{-1/24τ}`.
63 -- decentral days float The time constant in decentralized thermal energy storage (TES)
64 -- central days float The time constant in centralized thermal energy storage (TES)
65 boilers -- {true, false} Add option for transforming electricity into heat using resistive heater Add option for transforming gas into heat using gas boilers
66 resistive_heaters -- {true, false} Add option for transforming electricity into heat using resistive heaters (independently from gas boilers)
67 oil_boilers -- {true, false} Add option for transforming oil into heat using boilers
68 biomass_boiler -- {true, false} Add option for transforming biomass into heat using boilers
69 chp -- {true, false} Add option for using Combined Heat and Power (CHP)

View File

@ -28,6 +28,13 @@ Upcoming Release
* Default to approximating transmission losses in HVAC lines
(``transmission_losses: 2``).
* Add separate option to add resistive heaters to the technology choices
(``sector: resistive_heaters:``). Previously they were always added when
boilers were added.
* Resolve code issues for endogenous building retrofitting. Select correct
sector names, address deprecations, distinguish between district heating, decentral
heating in urban areas or rural areas for floor area calculations.
* Remove all negative loads on the ``co2 atmosphere`` bus representing emissions
for e.g. fixed fossil demands for transport oil. Instead these are handled

12
scripts/build_retro_cost.py Normal file → Executable file
View File

@ -533,16 +533,16 @@ def prepare_temperature_data():
"""
temperature = xr.open_dataarray(snakemake.input.air_temperature).to_pandas()
d_heat = (
temperature.groupby(temperature.columns.str[:2], axis=1)
temperature.T.groupby(temperature.columns.str[:2])
.mean()
.resample("1D")
.T.resample("1D")
.mean()
< t_threshold
).sum()
temperature_average_d_heat = (
temperature.groupby(temperature.columns.str[:2], axis=1)
temperature.T.groupby(temperature.columns.str[:2])
.mean()
.apply(
.T.apply(
lambda x: get_average_temperature_during_heating_season(x, t_threshold=15)
)
)
@ -610,7 +610,7 @@ def calculate_costs(u_values, l, cost_retro, window_assumptions):
cost_retro.loc[x.name[3], "cost_var"]
* 100
* float(l)
* l_weight.loc[x.name[3]][0]
* l_weight.loc[x.name[3]].iloc[0]
+ cost_retro.loc[x.name[3], "cost_fix"]
)
* x.A_element
@ -720,6 +720,7 @@ def map_to_lstrength(l_strength, df):
.swaplevel(axis=1)
.dropna(axis=1)
)
return pd.concat([df.drop([2, 3], axis=1, level=1), l_strength_df], axis=1)
@ -800,6 +801,7 @@ def calculate_heat_losses(u_values, data_tabula, l_strength, temperature_factor)
* data_tabula.A_envelope
/ data_tabula.A_C_Ref
)
heat_transfer_perm2 = pd.concat(
[
heat_transfer_perm2,

30
scripts/prepare_sector_network.py Normal file → Executable file
View File

@ -460,7 +460,7 @@ def update_wind_solar_costs(n, costs):
logger.info(
"Added connection cost of {:0.0f}-{:0.0f} Eur/MW/a to {}".format(
connection_cost[0].min(), connection_cost[0].max(), tech
connection_cost.min(), connection_cost.max(), tech
)
)
@ -1910,7 +1910,7 @@ def add_heat(n, costs):
lifetime=costs.at[name_type + " water tank storage", "lifetime"],
)
if options["boilers"]:
if options["resistive_heaters"]:
key = f"{name_type} resistive heater"
n.madd(
@ -1925,6 +1925,7 @@ def add_heat(n, costs):
lifetime=costs.at[key, "lifetime"],
)
if options["boilers"]:
key = f"{name_type} gas boiler"
n.madd(
@ -2062,7 +2063,7 @@ def add_heat(n, costs):
)
w_space["tot"] = (
heat_demand_r["services space"] + heat_demand_r["residential space"]
) / heat_demand_r.groupby(level=[1], axis=1).sum()
) / heat_demand_r.T.groupby(level=[1]).sum().T
for name in n.loads[
n.loads.carrier.isin([x + " heat" for x in heat_systems])
@ -2071,11 +2072,21 @@ def add_heat(n, costs):
ct = pop_layout.loc[node, "ct"]
# weighting 'f' depending on the size of the population at the node
f = urban_fraction[node] if "urban" in name else (1 - urban_fraction[node])
if "urban central" in name:
f = dist_fraction[node]
elif "urban decentral" in name:
f = urban_fraction[node] - dist_fraction[node]
else:
f = 1 - urban_fraction[node]
if f == 0:
continue
# get sector name ("residential"/"services"/or both "tot" for urban central)
sec = [x if x in name else "tot" for x in sectors][0]
if "urban central" in name:
sec = "tot"
if "residential" in name:
sec = "residential"
if "services" in name:
sec = "services"
# get floor aread at node and region (urban/rural) in m^2
floor_area_node = (
@ -2119,14 +2130,15 @@ def add_heat(n, costs):
strengths = strengths.drop(s)
# reindex normed time profile of space heat demand back to hourly resolution
space_pu = space_pu.reindex(index=heat_demand.index).fillna(method="ffill")
space_pu = space_pu.reindex(index=heat_demand.index).ffill()
# add for each retrofitting strength a generator with heat generation profile following the profile of the heat demand
for strength in strengths:
node_name = " ".join(name.split(" ")[2::])
n.madd(
"Generator",
[node],
suffix=" retrofitting " + strength + " " + name[6::],
suffix=" retrofitting " + strength + " " + node_name,
bus=name,
carrier="retrofitting",
p_nom_extendable=True,
@ -3464,7 +3476,7 @@ def cluster_heat_buses(n):
def renamer(s):
return s.replace("residential ", "").replace("services ", "")
pnl[k] = pnl[k].groupby(renamer, axis=1).agg(agg[k], **agg_group_kwargs)
pnl[k] = pnl[k].T.groupby(renamer).agg(agg[k], **agg_group_kwargs).T
# remove unclustered assets of service/residential
to_drop = c.df.index.difference(df.index)
@ -3722,7 +3734,7 @@ if __name__ == "__main__":
if "I" in opts:
add_industry(n, costs)
if "I" in opts and "H" in opts:
if "H" in opts:
add_waste_heat(n)
if "A" in opts: # requires H and I