Update central heating temperatures based on Euroheat data and AGFW-Hauptbericht (#1264)
* chore: update config.default Using Euroheat market outlook 2024 and AGFW-Hauptbericht * feat: extrapolate missing values in central_heating_temperature_profile.run * update release notes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: map_temperature_dict_to_onshore regions and correct use of extrapolation function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: extrapolation_ration in build_central_heating_temperature_profiles.run * style: remove obsolete time index in min/max fwd, return temperatures * feat: throw exception if max_fwd_temp < min_fwd_temp or min_fwd_temp < return_temp * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Amos Schledorn <a.schledorn@tu-berlin.de> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
0423366db6
commit
5cf706fe4d
@ -451,21 +451,18 @@ sector:
|
||||
district_heating_loss: 0.15
|
||||
supply_temperature_approximation:
|
||||
max_forward_temperature:
|
||||
default: 90
|
||||
DK: 70
|
||||
SE: 70
|
||||
NO: 70
|
||||
FR: 110
|
||||
DK: 75
|
||||
DE: 109
|
||||
CZ: 130
|
||||
FI: 115
|
||||
PL: 130
|
||||
SE: 102
|
||||
IT: 90
|
||||
min_forward_temperature:
|
||||
default: 68
|
||||
DK: 54
|
||||
SE: 54
|
||||
NO: 54
|
||||
DE: 82
|
||||
return_temperature:
|
||||
default: 50
|
||||
DK: 40
|
||||
SE: 40
|
||||
NO: 40
|
||||
FI: 40
|
||||
DE: 58
|
||||
lower_threshold_ambient_temperature: 0
|
||||
upper_threshold_ambient_temperature: 10
|
||||
rolling_window_ambient_temperature: 72
|
||||
|
@ -9,8 +9,8 @@ Release Notes
|
||||
##########################################
|
||||
|
||||
.. Upcoming Release
|
||||
.. ================
|
||||
|
||||
* Updated district heating supply temperatures based on `Euroheat's DHC Market Outlook 2024<https://api.euroheat.org/uploads/Market_Outlook_2024_beeecd62d4.pdf>`__ and `AGFW-Hauptbericht 2022 <https://www.agfw.de/securedl/sdl-eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3MjU2MjI2MTUsImV4cCI6MTcyNTcxMjYxNSwidXNlciI6MCwiZ3JvdXBzIjpbMCwtMV0sImZpbGUiOiJmaWxlYWRtaW4vdXNlcl91cGxvYWQvWmFobGVuX3VuZF9TdGF0aXN0aWtlbi9IYXVwdGJlcmljaHRfMjAyMi9BR0ZXX0hhdXB0YmVyaWNodF8yMDIyLnBkZiIsInBhZ2UiOjQzNn0.Bhma3PKg9uJnC57Ixi2p9STW5-II9VXPTDXS544M208/AGFW_Hauptbericht_2022.pdf>`__. `min_forward_temperature` and `return_temperature` (not given by Euroheat) are extrapolated based on German values.
|
||||
* Made the overdimensioning factor for heating systems specific for central/decentral heating, defaults to no overdimensionining for central heating and no changes to decentral heating compared to previous version.
|
||||
|
||||
* bugfix: The carrier of stores was silently overwritten by their bus_carrier as a side effect when building the co2 constraints
|
||||
|
@ -58,6 +58,15 @@ class CentralHeatingTemperatureApproximator:
|
||||
rolling_window_ambient_temperature : int
|
||||
Rolling window size for averaging ambient temperature.
|
||||
"""
|
||||
|
||||
if any(max_forward_temperature < min_forward_temperature):
|
||||
raise ValueError(
|
||||
"max_forward_temperature must be greater than min_forward_temperature"
|
||||
)
|
||||
if any(min_forward_temperature < fixed_return_temperature):
|
||||
raise ValueError(
|
||||
"min_forward_temperature must be greater than fixed_return_temperature"
|
||||
)
|
||||
self._ambient_temperature = ambient_temperature
|
||||
self.max_forward_temperature = max_forward_temperature
|
||||
self.min_forward_temperature = min_forward_temperature
|
||||
|
@ -9,8 +9,8 @@ al. 2019, where for ambient temperatures below 0C, the highest possible forward
|
||||
temperature is assumed and vice versa for temperatures above 10C. Between these
|
||||
threshold levels, forward temperatures are linearly interpolated.
|
||||
|
||||
By default, temperature levels are increased for non-Scandinavian countries.
|
||||
The default ratios between min. and max. forward temperatures is based on AGFW-Hauptbericht 2022.
|
||||
By default, `max_forward_temperature` from Euroheat DHC Market Outlook 2024 is used; `min_forward_temperature` and `return_temperature` for Germany is used from AGFW-Hauptbericht 2022.
|
||||
`min_forward_temperature` and `return_temperature` for other countries are extrapolated based on the ratio between `max_forward_temperature` and `min_forward_temperature` and `return_temperature` for those countries not missing (by default only Germany).
|
||||
|
||||
Relevant Settings
|
||||
-----------------
|
||||
@ -47,26 +47,68 @@ from central_heating_temperature_approximator import (
|
||||
)
|
||||
|
||||
|
||||
def extrapolate_missing_supply_temperatures_by_country(
|
||||
extrapolate_from: dict, extrapolate_to: dict
|
||||
) -> xr.DataArray:
|
||||
"""
|
||||
Extrapolates missing supply temperatures by country.
|
||||
|
||||
Parameters:
|
||||
extrapolate_from (dict): A dictionary containing supply temperatures to extrapolate from. Should contain all countries.
|
||||
extrapolate_to (dict): A dictionary containing supply temperatures to extrapolate to. Where `country` is present, average ratio between `extrapolate_to[country]` and `extrapolate_from[country]` is applied to all countries for which `country` is not present in `extrapolate_from.keys()` to infer ratio for extrapolation.
|
||||
|
||||
Returns:
|
||||
xr.DataArray: A DataArray containing the extrapolated supply temperatures.
|
||||
"""
|
||||
|
||||
if not all([key in extrapolate_from.keys() for key in extrapolate_to.keys()]):
|
||||
raise ValueError(
|
||||
"Not all countries in extrapolate_to are present in extrapolate_from."
|
||||
)
|
||||
# average ratio between extrapolate_from and extrapolate_to for those countries that are in both dictionaries
|
||||
extrapolation_ratio = np.mean(
|
||||
[extrapolate_to[key] / extrapolate_from[key] for key in extrapolate_to.keys()]
|
||||
)
|
||||
|
||||
# apply extrapolation ratio to all keys missing in extrapolate_to
|
||||
return {
|
||||
key: (
|
||||
extrapolate_to[key]
|
||||
if key in extrapolate_to.keys()
|
||||
else extrapolate_from[key] * extrapolation_ratio
|
||||
)
|
||||
for key in extrapolate_from.keys()
|
||||
}
|
||||
|
||||
|
||||
def get_country_from_node_name(node_name: str) -> str:
|
||||
"""
|
||||
Extracts the country code from a given node name.
|
||||
|
||||
Parameters:
|
||||
node_name (str): The name of the node.
|
||||
|
||||
Returns:
|
||||
str: The country code extracted from the node name.
|
||||
"""
|
||||
return node_name[:2]
|
||||
|
||||
|
||||
def map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country: dict,
|
||||
regions_onshore: pd.Index,
|
||||
snapshots: pd.DatetimeIndex,
|
||||
) -> xr.DataArray:
|
||||
"""
|
||||
Map dictionary of temperatures to onshore regions.
|
||||
|
||||
Missing values are replaced by the mean of all values.
|
||||
|
||||
Parameters:
|
||||
----------
|
||||
supply_temperature_by_country : dictionary
|
||||
Dictionary with temperatures as values and country keys as keys. One key must be named "default"
|
||||
Dictionary with temperatures as values and country keys as keys.
|
||||
regions_onshore : pd.Index
|
||||
Names of onshore regions
|
||||
snapshots : pd.DatetimeIndex
|
||||
Time stamps
|
||||
|
||||
Returns:
|
||||
-------
|
||||
@ -75,20 +117,16 @@ def map_temperature_dict_to_onshore_regions(
|
||||
"""
|
||||
return xr.DataArray(
|
||||
[
|
||||
[
|
||||
(
|
||||
supply_temperature_by_country[get_country_from_node_name(node_name)]
|
||||
if get_country_from_node_name(node_name)
|
||||
in supply_temperature_by_country.keys()
|
||||
else supply_temperature_by_country["default"]
|
||||
)
|
||||
for node_name in regions_onshore.values
|
||||
]
|
||||
# pass both nodes and snapshots as dimensions to preserve correct data structure
|
||||
for _ in snapshots
|
||||
(
|
||||
supply_temperature_by_country[get_country_from_node_name(node_name)]
|
||||
if get_country_from_node_name(node_name)
|
||||
in supply_temperature_by_country.keys()
|
||||
else np.mean(list(supply_temperature_by_country.values()))
|
||||
)
|
||||
for node_name in regions_onshore.values
|
||||
],
|
||||
dims=["time", "name"],
|
||||
coords={"time": snapshots, "name": regions_onshore},
|
||||
dims=["name"],
|
||||
coords={"name": regions_onshore},
|
||||
)
|
||||
|
||||
|
||||
@ -104,28 +142,35 @@ if __name__ == "__main__":
|
||||
|
||||
set_scenario_config(snakemake)
|
||||
|
||||
max_forward_temperature = snakemake.params.max_forward_temperature_central_heating
|
||||
min_forward_temperature = extrapolate_missing_supply_temperatures_by_country(
|
||||
extrapolate_from=max_forward_temperature,
|
||||
extrapolate_to=snakemake.params.min_forward_temperature_central_heating,
|
||||
)
|
||||
return_temperature = extrapolate_missing_supply_temperatures_by_country(
|
||||
extrapolate_from=max_forward_temperature,
|
||||
extrapolate_to=snakemake.params.return_temperature_central_heating,
|
||||
)
|
||||
|
||||
# map forward and return temperatures specified on country-level to onshore regions
|
||||
regions_onshore = gpd.read_file(snakemake.input.regions_onshore)["name"]
|
||||
snapshots = pd.date_range(freq="h", **snakemake.params.snapshots)
|
||||
max_forward_temperature_central_heating_by_node_and_time: xr.DataArray = (
|
||||
map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country=snakemake.params.max_forward_temperature_central_heating,
|
||||
supply_temperature_by_country=max_forward_temperature,
|
||||
regions_onshore=regions_onshore,
|
||||
snapshots=snapshots,
|
||||
)
|
||||
)
|
||||
min_forward_temperature_central_heating_by_node_and_time: xr.DataArray = (
|
||||
map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country=snakemake.params.min_forward_temperature_central_heating,
|
||||
supply_temperature_by_country=min_forward_temperature,
|
||||
regions_onshore=regions_onshore,
|
||||
snapshots=snapshots,
|
||||
)
|
||||
)
|
||||
return_temperature_central_heating_by_node_and_time: xr.DataArray = (
|
||||
map_temperature_dict_to_onshore_regions(
|
||||
supply_temperature_by_country=snakemake.params.return_temperature_central_heating,
|
||||
supply_temperature_by_country=return_temperature,
|
||||
regions_onshore=regions_onshore,
|
||||
snapshots=snapshots,
|
||||
)
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user