Skip to content

Commit

Permalink
Temperature limit is part of the house data
Browse files Browse the repository at this point in the history
The temperature limit is connected to the efficiency status of the
house.
  • Loading branch information
uvchik committed Jun 21, 2022
1 parent 5d75001 commit 7cccf52
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 46 deletions.
10 changes: 5 additions & 5 deletions examples/vdi_profile_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,19 @@


my_houses = []
for n in range(1):
for n in range(2):
my_houses.append(
{
"N_Pers": 3,
"name": "EFH_{0}".format(n),
"N_WE": 1,
"Q_Heiz_a": 6000,
"TRY": 4,
"copies": 24,
"house_type": "EFH",
"sigma": 4,
"Q_TWW_a": 1500,
"W_a": 5250,
"summer_temperature_limit": 15,
"winter_temperature_limit": 5,
}
)
my_houses.append(
Expand All @@ -64,12 +64,12 @@
"name": "MFH_{0}".format(n),
"N_WE": 15,
"Q_Heiz_a": 60000,
"TRY": 4,
"copies": 24,
"house_type": "MFH",
"sigma": 2,
"Q_TWW_a": 15000,
"W_a": 45000,
"summer_temperature_limit": 15,
"winter_temperature_limit": 5,
}
)

Expand Down
3 changes: 0 additions & 3 deletions src/demandlib/demandlib.ini
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
[VDI]
summer_temperature_limit = 15
winter_temperature_limit = 5
118 changes: 80 additions & 38 deletions src/demandlib/vdi/regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@
import datetime
import os
import warnings
from collections import namedtuple

import pandas as pd

from demandlib import config as cfg
from demandlib.tools import add_weekdays2df
from demandlib.vdi import dwd_try

Expand Down Expand Up @@ -115,21 +115,43 @@ def __init__(

self._year = year
self.weather = None
self.type_days = self._get_typical_days(holidays)
self._load_profiles = self._load_profile_factors()

self.houses = []
if houses is not None:
self.add_houses(houses)

if resample_rule is not None:
self._resample_profiles(resample_rule)
self.temperature_limits = self._get_temperature_level_combinations()
self.type_days = {}
self._load_profiles = {}
for temp_limit in self.temperature_limits:
self.type_days[temp_limit] = self._get_typical_days(
holidays, temp_limit
)
self._load_profiles[temp_limit] = self._load_profile_factors(
temp_limit
)

if resample_rule is not None:
self._resample_profiles(resample_rule, temp_limit)

def _resample_profiles(self, rule):
self._load_profiles = self._load_profiles.resample(rule).sum()
self.type_days = self.type_days.resample(rule).first()
def _resample_profiles(self, rule, tl):
self._load_profiles[tl] = self._load_profiles[tl].resample(rule).sum()
self.type_days[tl] = self.type_days[tl].resample(rule).first()

def _get_temperature_level_combinations(self):
t_limit = namedtuple("temperature_limit", "summer winter")
return set(
[
t_limit(
summer=h["summer_temperature_limit"],
winter=h["winter_temperature_limit"],
)
for h in self.houses
]
)

def _get_typical_days(self, holidays, set_season="temperature"):
def _get_typical_days(
self, holidays, temperature_limit, set_season="temperature"
):
"""
Find the code for the typical days from dwd. The code consists of three
letters:
Expand Down Expand Up @@ -198,8 +220,8 @@ def _get_typical_days(self, holidays, set_season="temperature"):
"transition": "U",
}
days.replace(to_replace=seasons_dict, inplace=True)
wtl = cfg.get("VDI", "winter_temperature_limit")
stl = cfg.get("VDI", "summer_temperature_limit")
wtl = temperature_limit.winter
stl = temperature_limit.summer
days.loc[days["TAMB"] < wtl, "season_t"] = "W"
days.loc[days["TAMB"] >= wtl, "season_t"] = "U"
days.loc[days["TAMB"] > stl, "season_t"] = "S"
Expand Down Expand Up @@ -235,7 +257,7 @@ def _get_typical_days(self, holidays, set_season="temperature"):
)
return days

def _load_profile_factors(self):
def _load_profile_factors(self, tl):
"""Run VDI 4655 - Step 2.
Match 'typtag' keys and reference load profile factors for each
Expand Down Expand Up @@ -281,21 +303,21 @@ def _load_profile_factors(self):

# Set reference time (first hour of the day) to calculate minutes of
# the day.
self.type_days["ref_dt"] = self.type_days.index
self.type_days[tl]["ref_dt"] = self.type_days[tl].index

# Fill data into the large table with minute index
self.type_days = pd.concat(
[self.type_days, minute_table], axis=1
self.type_days[tl] = pd.concat(
[self.type_days[tl], minute_table], axis=1
).ffill()

# Add columns to merge with (house types, minute of day and day_types)
self.type_days["datetime"] = self.type_days.index
self.type_days["minute_of_day"] = (
self.type_days[tl]["datetime"] = self.type_days[tl].index
self.type_days[tl]["minute_of_day"] = (
pd.to_timedelta(
self.type_days.pop("datetime")
self.type_days[tl].pop("datetime")
- pd.Series(
index=self.type_days.index,
data=self.type_days.pop("ref_dt"),
index=self.type_days[tl].index,
data=self.type_days[tl].pop("ref_dt"),
)
)
.dt.total_seconds()
Expand All @@ -307,13 +329,17 @@ def _load_profile_factors(self):
# the typical days for every minute of the year.
house_profiles = {}
for house_type in house_types:
self.type_days["ht"] = house_type
house_profiles[house_type] = self.type_days.merge(
typtage_df,
how="left",
left_on=["day_types", "minute_of_day", "ht"],
right_on=["day_types", "minute_of_day", "ht"],
).sort_index()
self.type_days[tl]["ht"] = house_type
house_profiles[house_type] = (
self.type_days[tl]
.merge(
typtage_df,
how="left",
left_on=["day_types", "minute_of_day", "ht"],
right_on=["day_types", "minute_of_day", "ht"],
)
.sort_index()
)

# Combine the table of both house type
load_profile = (
Expand Down Expand Up @@ -359,7 +385,7 @@ def add_houses(self, houses):
if len(houses) > 0:
self.houses.extend(houses)

def get_daily_energy_demand_houses(self):
def get_daily_energy_demand_houses(self, tl):
"""Determine the houses' energy demand values for each 'typtag'.
.. note::
Expand Down Expand Up @@ -407,7 +433,7 @@ def get_daily_energy_demand_houses(self):
multiindex = pd.MultiIndex.from_product(
iterables, names=["house", "energy"]
)
typtage_combinations = self.type_days["day_types"].unique()
typtage_combinations = self.type_days[tl]["day_types"].unique()

daily_energy_demand_houses = pd.DataFrame(
index=multiindex, columns=typtage_combinations
Expand Down Expand Up @@ -507,21 +533,34 @@ def get_load_curve_houses(self):
value with the daily energy demand. It returns the result: the energy
demand values for all houses and energy types (in kWh)
"""
daily_energy_demand_houses = self.get_daily_energy_demand_houses()
daily_energy_demand_houses = {}
for temp_limit in self.temperature_limits:
daily_energy_demand_houses[
temp_limit
] = self.get_daily_energy_demand_houses(temp_limit)

house_profiles = {}

for house in self.houses:
df_typ = self.type_days.merge(
daily_energy_demand_houses.T[house["name"]],
left_on="day_types",
right_index=True,
).sort_index()
t_limit = namedtuple("temperature_limit", "summer winter")
tl = t_limit(
summer=house["summer_temperature_limit"],
winter=house["winter_temperature_limit"],
)
df_typ = (
self.type_days[tl]
.merge(
daily_energy_demand_houses[tl].T[house["name"]],
left_on="day_types",
right_index=True,
)
.sort_index()
)
df_typ.drop(
["day_types", "minute_of_day", "ht"], axis=1, inplace=True
)

load_profile_df = self._load_profiles.rename(
load_profile_df = self._load_profiles[tl].rename(
columns={
"F_Heiz_n_TT": "Q_Heiz_TT",
"F_el_n_TT": "W_TT",
Expand Down Expand Up @@ -551,6 +590,9 @@ def get_load_curve_houses(self):
]
)
house_profiles[house["name"]] = load_curve_house
return pd.concat(
df = pd.concat(
house_profiles.values(), keys=house_profiles.keys(), axis=1
)

df.columns = df.columns.set_names(["name", "house_type", "energy"])
return df

0 comments on commit 7cccf52

Please sign in to comment.