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/generation of number inhabitants #8

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
209 changes: 102 additions & 107 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 @@ -112,6 +115,9 @@ def generate_number_flats(self, area):
def generate_number_occupants(self):
"""
Generate number of occupants for different of building types.
Number of inhabitants is always between 1 and 5 (inclusive),
irrespective of building type. The probability of a certain number of
inhabitants changes with building type, based on Zensus2011 data.

Parameters
----------
Expand All @@ -122,61 +128,26 @@ def generate_number_occupants(self):
None.
"""

if self.building == "SFH":
# choose random number of occupants (2-5) for single family houses (assumption)

# loop over all flats of current building
for j in range(self.nb_flats):
random_nb = rd.random() # picking random number in [0,1)
j = 1 # staring with one (additional) occupant
# the random number decides how many occupants are chosen (2-5)
while j <= 4:
if random_nb < j / 4:
self.nb_occ.append(1 + j) # minimum is 2 occupants
break
j += 1

if self.building == "TH":
# choose random number of occupants (2-5) for terraced houses (assumption)

# loop over all flats of current building
for j in range(self.nb_flats):
random_nb = rd.random() # picking random number in [0,1)
j = 1 # staring with one (additional) occupant
# the random number decides how many occupants are chosen (2-5)
while j <= 4:
if random_nb < j / 4:
self.nb_occ.append(1 + j) # minimum is 2 occupants
break
j += 1

if self.building == "MFH":
# choose random number of occupants (1-4) for each flat in the multifamily house (assumption)

# loop over all flats of current building
for j in range(self.nb_flats):
random_nb = rd.random() # picking random number in [0,1)
k = 1
# the random number decides how many occupants are chosen (1-4)
while k <= 4:
if random_nb < k / 4:
self.nb_occ.append(k)
break
k += 1

if self.building == "AB":
# choose random number of occupants (1-4) for each flat in the apartment block (assumption)

# loop over all flats of current building
for j in range(self.nb_flats):
random_nb = rd.random() # picking random number in [0,1)
k = 1
# the random number decides how many occupants are chosen (1-4)
while k <= 4:
if random_nb < k / 4:
self.nb_occ.append(k)
break
k += 1
# probability table calculated from Zensus2011
# probability for 6 inhabitants is subsumed as 5 inhabitants
inhabitant_options = [1, 2, 3, 4, 5]
probability_distributions = {
"SFH": [0.223, 0.358, 0.189, 0.157, 0.073],
"TH": [0.223, 0.358, 0.189, 0.157, 0.073],
"MFH": [0.468, 0.326, 0.116, 0.063, 0.027],
"AB": [0.609, 0.249, 0.077, 0.043, 0.022],
}

# loop over all flats of the current building
for flat in range(self.nb_flats):
# select the number of inhabitants respecting the probability distribution
inh = rd.choices(
population=inhabitant_options,
weights=probability_distributions[self.building],
k=1,
)[0]
# append the number of occupants
self.nb_occ.append(inh)

def generate_annual_el_consumption(self):
"""
Expand All @@ -194,32 +165,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 +235,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 +286,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 +297,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 +327,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 +351,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 +396,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 +419,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()