Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapt calculation of flats per building #7

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
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
203 changes: 133 additions & 70 deletions classes/users.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
# -*- coding: utf-8 -*-

import os, math
import math
import os
import random as rd

import functions.heating_profile_5R1C as heating
import numpy as np
from classes.profils import Profiles
import richardsonpy
import richardsonpy.classes.stochastic_el_load_wrapper as wrap
import richardsonpy.classes.appliance as app_model
import richardsonpy.classes.lighting as light_model
import functions.heating_profile_5R1C as heating
import richardsonpy.classes.stochastic_el_load_wrapper as wrap
from classes.profils import Profiles
from scipy.stats import truncpareto


class Users:
Expand Down Expand Up @@ -69,15 +72,15 @@ def __init__(self, building, area):
self.gains = None
self.heat = None

self.generate_number_flats(area)
self.generate_number_flats()
self.generate_number_occupants()
self.generate_annual_el_consumption()
self.generate_lighting_index()
self.create_el_wrapper()

def generate_number_flats(self, area):
def generate_number_flats(self):
"""
Generate number of flats for different of building types.
Generate number of flats for different building types.
Possible building types are:
- single family house (SFH)
- terraced house (TH)
Expand All @@ -86,28 +89,64 @@ def generate_number_flats(self, area):

Parameters
----------
area : integer
Floor area of different building types.
None.

Returns
-------
None.
"""

if self.building == "SFH":
self.nb_flats = 1
elif self.building == "TH":
self.nb_flats = 1
# SFH and TH have the same procedure
if self.building == "SFH" or self.building == "TH":
"""
The TABLUA building category "SFH" and "TH" are comprised of
houses with one flat and two flats.
The probability of having one or two flats is calculated from
the german Zensus 2011 data.
"""
prob = 0.793 # probability of a 1 flat SFH (2 flat = 1-0.793)
random = np.random.uniform(low=0, high=1, size=None)
if random <= prob:
self.nb_flats = 1
else:
self.nb_flats = 2
elif self.building == "MFH":
if area <= 4 * 100:
self.nb_flats = 4
elif area > 4 * 100:
self.nb_flats = math.floor(area / 100)
"""
The TABLUA building category "MFH" is comprised of houses with
three to 12 flats.
The probability of occurence of the amount of flats is calculated
from the german Zensus 2011 data. The number of flats per building
is given in categories (3-6 flats, 7-12 flats) and only the
category probability is known. Within the categories, a uniform
distribution is assumed.
"""
prob = 0.718 # probability of a 3-6 flat MFH
random = np.random.uniform(low=0, high=1, size=None) # get random value
if (
random <= prob
): # if the probability says we are in the smaller group of MFH
self.nb_flats = rd.randint(
3, 6
) # select value between 3 and 6 (inclusive) on random
else:
self.nb_flats = rd.randint(7, 12)
elif self.building == "AB":
if area <= 10 * 100:
self.nb_flats = 10
elif area > 10 * 100:
self.nb_flats = math.floor(area / 100)
"""
The TABULA building category "GMH" (given here as "AB") contains
buildings with 13 or more flats.
The range of flats per building and probability of occurence is not
given.
A truncated pareto distribution is assumed, where all values are between
13 and 100. Therefore, it is assumed that no house will have more than
100 flats.
"""
max_flats = 100.0
min_flats = 12.0 # the `scale` is added to this, so it's effectively 13
scale = 1.0
b = 1.0
c = (max_flats - min_flats) / scale
nb_flats = truncpareto.rvs(b=b, c=c, loc=min_flats, scale=scale, size=1)
# round to nearest integer
self.nb_flats = int(round(nb_flats[0], 0))

def generate_number_occupants(self):
"""
Expand Down Expand Up @@ -194,32 +233,34 @@ def generate_annual_el_consumption(self):

# source: https://www.stromspiegel.de/stromverbrauch-verstehen/stromverbrauch-im-haushalt/#c120951
# method: https://www.stromspiegel.de/ueber-uns-partner/methodik-des-stromspiegels/
standard_consumption = {"SFH": {1: 2300,
2: 3000,
3: 3500,
4: 4000,
5: 5000},
"MFH": {1: 1300,
2: 2000,
3: 2500,
4: 2600,
5: 3000}}
standard_consumption = {
"SFH": {1: 2300, 2: 3000, 3: 3500, 4: 4000, 5: 5000},
"MFH": {1: 1300, 2: 2000, 3: 2500, 4: 2600, 5: 3000},
}

self.annual_el_demand = np.zeros(self.nb_flats)
# assumption: standard deviation 10% of mean value
for j in range(self.nb_flats):
if self.building == "SFH":
annual_el_demand_temp = standard_consumption["SFH"][self.nb_occ[j]]
self.annual_el_demand[j] = rd.gauss(annual_el_demand_temp, annual_el_demand_temp * 0.10)
self.annual_el_demand[j] = rd.gauss(
annual_el_demand_temp, annual_el_demand_temp * 0.10
)
if self.building == "TH":
annual_el_demand_temp = standard_consumption["SFH"][self.nb_occ[j]]
self.annual_el_demand[j] = rd.gauss(annual_el_demand_temp, annual_el_demand_temp * 0.10)
self.annual_el_demand[j] = rd.gauss(
annual_el_demand_temp, annual_el_demand_temp * 0.10
)
if self.building == "MFH":
annual_el_demand_temp = standard_consumption["MFH"][self.nb_occ[j]]
self.annual_el_demand[j] = rd.gauss(annual_el_demand_temp, annual_el_demand_temp * 0.10)
self.annual_el_demand[j] = rd.gauss(
annual_el_demand_temp, annual_el_demand_temp * 0.10
)
if self.building == "AB":
annual_el_demand_temp = standard_consumption["MFH"][self.nb_occ[j]]
self.annual_el_demand[j] = rd.gauss(annual_el_demand_temp, annual_el_demand_temp * 0.10)
self.annual_el_demand[j] = rd.gauss(
annual_el_demand_temp, annual_el_demand_temp * 0.10
)

def generate_lighting_index(self):
"""
Expand Down Expand Up @@ -262,27 +303,28 @@ def create_el_wrapper(self):
"""

src_path = os.path.dirname(richardsonpy.__file__)
path_app = os.path.join(src_path, 'inputs', 'Appliances.csv')
path_light = os.path.join(src_path, 'inputs', 'LightBulbs.csv')
path_app = os.path.join(src_path, "inputs", "Appliances.csv")
path_light = os.path.join(src_path, "inputs", "LightBulbs.csv")

for j in range(self.nb_flats):

# annual demand of the electric appliances (annual demand minus lighting)
# source: https://www.umweltbundesamt.de/daten/private-haushalte-konsum/wohnen/energieverbrauch-privater-haushalte#stromverbrauch-mit-einem-anteil-von-rund-einem-funftel
# values from diagram for 2018 without heating, dhw and cooling: 8,1 / 81,1 = 10,0%
appliancesDemand = 0.9 * self.annual_el_demand[j]

# Create and save appliances object
appliances = \
app_model.Appliances(path_app,
annual_consumption=appliancesDemand,
randomize_appliances=True,
max_iter=15,
prev_heat_dev=True)
appliances = app_model.Appliances(
path_app,
annual_consumption=appliancesDemand,
randomize_appliances=True,
max_iter=15,
prev_heat_dev=True,
)

# Create and save light configuration object
lights = light_model.load_lighting_profile(filename=path_light,
index=self.lighting_index[j])
lights = light_model.load_lighting_profile(
filename=path_light, index=self.lighting_index[j]
)

# Create wrapper object
self.el_wrapper.append(wrap.ElectricityProfile(appliances, lights))
Expand Down Expand Up @@ -312,7 +354,7 @@ def calcProfiles(self, site, time_resolution, time_horizon, initial_day=1):
T_e = site["T_e"]

time_day = 24 * 60 * 60
nb_days = int(time_horizon/time_day)
nb_days = int(time_horizon / time_day)

self.occ = np.zeros(int(time_horizon / time_resolution))
self.dhw = np.zeros(int(time_horizon / time_resolution))
Expand All @@ -323,9 +365,11 @@ def calcProfiles(self, site, time_resolution, time_horizon, initial_day=1):
temp_obj = Profiles(self.nb_occ[j], initial_day, nb_days, time_resolution)
self.occ = self.occ + temp_obj.generate_occupancy_profiles()
self.dhw = self.dhw + temp_obj.generate_dhw_profile()
self.elec = self.elec + temp_obj.generate_el_profile(irradiance=irradiation,
el_wrapper=self.el_wrapper[j],
annual_demand=self.annual_el_demand[j])
self.elec = self.elec + temp_obj.generate_el_profile(
irradiance=irradiation,
el_wrapper=self.el_wrapper[j],
annual_demand=self.annual_el_demand[j],
)
self.gains = self.gains + temp_obj.generate_gain_profile()
# currently only one car per building possible
self.car = self.car + temp_obj.generate_EV_profile()
Expand All @@ -351,7 +395,7 @@ def calcHeatingProfile(self, site, envelope, time_resolution):
None.
"""

dt = time_resolution/(60*60)
dt = time_resolution / (60 * 60)
# calculate the temperatures (Q_HC, T_op, T_m, T_air, T_s)
(Q_HC, T_i, T_s, T_m, T_op) = heating.calculate(envelope, site["T_e"], dt)
# heating load for the current time step in Watt
Expand All @@ -375,18 +419,34 @@ def saveProfiles(self, unique_name, path):
None.
"""

np.savetxt(path + '/elec_' + unique_name + '.csv', self.elec, fmt='%1.2f', delimiter=',')
np.savetxt(path + '/dhw_' + unique_name + '.csv', self.dhw, fmt='%1.2f', delimiter=',')
np.savetxt(path + '/occ_' + unique_name + '.csv', self.occ, fmt='%1.2f', delimiter=',')
np.savetxt(path + '/gains_' + unique_name + '.csv', self.gains, fmt='%1.2f', delimiter=',')
np.savetxt(path + '/car_' + unique_name + '.csv', self.car, fmt='%1.2f', delimiter=',')
np.savetxt(
path + "/elec_" + unique_name + ".csv",
self.elec,
fmt="%1.2f",
delimiter=",",
)
np.savetxt(
path + "/dhw_" + unique_name + ".csv", self.dhw, fmt="%1.2f", delimiter=","
)
np.savetxt(
path + "/occ_" + unique_name + ".csv", self.occ, fmt="%1.2f", delimiter=","
)
np.savetxt(
path + "/gains_" + unique_name + ".csv",
self.gains,
fmt="%1.2f",
delimiter=",",
)
np.savetxt(
path + "/car_" + unique_name + ".csv", self.car, fmt="%1.2f", delimiter=","
)

'''
"""
fields = [name + "_" + str(id), str(sum(self.nb_occ))]
with open(path + '/_nb_occupants.csv','a') as f :
writer = csv.writer(f)
writer.writerow(fields)
'''
"""

def saveHeatingProfile(self, unique_name, path):
"""
Expand All @@ -404,7 +464,12 @@ def saveHeatingProfile(self, unique_name, path):
None.
"""

np.savetxt(path + '/heating_' + unique_name + '.csv', self.heat, fmt='%1.2f', delimiter=',')
np.savetxt(
path + "/heating_" + unique_name + ".csv",
self.heat,
fmt="%1.2f",
delimiter=",",
)

def loadProfiles(self, unique_name, path):
"""
Expand All @@ -422,16 +487,14 @@ def loadProfiles(self, unique_name, path):
None.
"""

self.elec = np.loadtxt(path + '/elec_' + unique_name + '.csv', delimiter=',')
self.dhw = np.loadtxt(path + '/dhw_' + unique_name + '.csv', delimiter=',')
self.occ = np.loadtxt(path + '/occ_' + unique_name + '.csv', delimiter=',')
self.gains = np.loadtxt(path + '/gains_' + unique_name + '.csv', delimiter=',')
self.car = np.loadtxt(path + '/car_' + unique_name + '.csv', delimiter=',')

self.elec = np.loadtxt(path + "/elec_" + unique_name + ".csv", delimiter=",")
self.dhw = np.loadtxt(path + "/dhw_" + unique_name + ".csv", delimiter=",")
self.occ = np.loadtxt(path + "/occ_" + unique_name + ".csv", delimiter=",")
self.gains = np.loadtxt(path + "/gains_" + unique_name + ".csv", delimiter=",")
self.car = np.loadtxt(path + "/car_" + unique_name + ".csv", delimiter=",")

if __name__ == '__main__':

test = Users(building="SFH",
area=1000)
if __name__ == "__main__":
test = Users(building="SFH", area=1000)

test.calcProfiles()
test.calcProfiles()