modified files to include occupancy schedules and create yearly schedules from typical week days

This commit is contained in:
pilar 2020-11-02 13:41:42 -05:00
parent ec5b5f626c
commit 96ec16a6b8
7 changed files with 105 additions and 44 deletions

View File

@ -2,33 +2,35 @@
Building module Building module
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca
Contributors Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
import calendar as cal
class Occupancy: class Occupancy:
""" """
Occupancy class Occupancy class
""" """
def __init__(self, internal_heat_gain, heat_dissipation, occupant_rate, occupant_type, occupant_zone, def __init__(self):
number_of_occupants, arrival_time=None, departure_time=None, break_time=None, day_of_week=None,
pd_of_meetings_duration=None, occupant_schedule=None):
""" """
Constructor Constructor
""" """
self._internal_heat_gain = internal_heat_gain self._internal_heat_gain = None
self._heat_dissipation = heat_dissipation self._heat_dissipation = None
self._occupant_rate = occupant_rate self._occupant_rate = None
self._occupant_type = occupant_type self._occupant_type = None
self._occupant_zone = occupant_zone self._occupant_zone = None
self._occupant_schedule = occupant_schedule self._occupant_schedule = None
self._number_of_occupants = number_of_occupants self._number_of_occupants = None
self._arrival_time = arrival_time self._arrival_time = None
self._departure_time = departure_time self._departure_time = None
self._break_time = break_time self._break_time = None
self._day_of_week = day_of_week self._day_of_week = None
self._pd_of_meetings_duration = pd_of_meetings_duration self._pd_of_meetings_duration = None
self._complete_year_schedule = None
@property @property
def internal_heat_gain(self): def internal_heat_gain(self):
@ -125,3 +127,23 @@ class Occupancy:
:return: probability distribution of the meeting duration :return: probability distribution of the meeting duration
""" """
return self._pd_of_meetings_duration return self._pd_of_meetings_duration
def get_complete_year_schedule(self, schedules):
if self._complete_year_schedule is None:
self._complete_year_schedule = []
for i in range(1, 13):
month_range = cal.monthrange(2015, i)
for day in range(1, month_range[1]+1):
if cal.weekday(2015, i, day) < 5:
for j in range(0, 24):
week_schedule = schedules['WD'][j]
self._complete_year_schedule.append(week_schedule)
elif cal.weekday(2015, i, day) == 5:
for j in range(0, 24):
week_schedule = schedules['Sat'][j]
self._complete_year_schedule.append(week_schedule)
else:
for j in range(0, 24):
week_schedule = schedules['Sun'][j]
self._complete_year_schedule.append(week_schedule)
return self._complete_year_schedule

View File

@ -2,6 +2,7 @@
UsageZone module UsageZone module
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
Contributors Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
from typing import List from typing import List
@ -21,10 +22,11 @@ class UsageZone:
self._cooling_setpoint = None self._cooling_setpoint = None
self._hours_day = None self._hours_day = None
self._days_year = None self._days_year = None
# todo: this must come from library, talk to Rabeeh # todo: mechanical_air_change must come from library, talk to Rabeeh
self._mechanical_air_change = ConfigurationHelper().min_air_change self._mechanical_air_change = ConfigurationHelper().min_air_change
self._occupancy = None self._occupancy = None
self._schedules = None self._schedules = None
self._heating_schedule = None
@property @property
def internal_gains(self) -> List[InternalGains]: def internal_gains(self) -> List[InternalGains]:
@ -193,3 +195,19 @@ class UsageZone:
:param value: Sunday schedules :param value: Sunday schedules
""" """
self._schedules = value self._schedules = value
@property
def heating_schedule(self):
"""
Get heating schedule
:return: dict{DtaFrame(int)}
"""
return self._heating_schedule
@heating_schedule.setter
def heating_schedule(self, values):
"""
Get heating schedule
:param values: dict{DtaFrame(int)}
"""
self._heating_schedule = values

View File

@ -5,16 +5,18 @@ Copyright © 2020 Project Author Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
import pandas as pd import pandas as pd
import helpers.constants as cte import helpers.constants as cte
from city_model_structure.attributes.occupancy import Occupancy
import calendar as cal
class MonthlyToHourlyDemand: class MonthlyToHourlyDemand:
""" """
MonthlyToHourlyDemand class MonthlyToHourlyDemand class
""" """
def __init__(self, building): def __init__(self, building, conditioning_seasons):
self._hourly_heating = pd.DataFrame() self._hourly_heating = pd.DataFrame()
self._hourly_cooling = pd.DataFrame() self._hourly_cooling = pd.DataFrame()
self._building = building self._building = building
self._conditioning_seasons = conditioning_seasons
@property @property
def hourly_heating(self): def hourly_heating(self):
@ -23,38 +25,45 @@ class MonthlyToHourlyDemand:
:return: [hourly_heating] :return: [hourly_heating]
""" """
# todo: this method and the insel model have to be reviewed for more than one thermal zone # todo: this method and the insel model have to be reviewed for more than one thermal zone
external_temp = self._building.hourly_external_temperature external_temp = self._building.external_temperature['hour']
# todo: review index depending on how the schedules are defined, either 8760 or 24 hours # todo: review index depending on how the schedules are defined, either 8760 or 24 hours
period = 'day'
for usage_zone in self._building.usage_zones: for usage_zone in self._building.usage_zones:
temp_set = usage_zone.heating_setpoint temp_set = float(usage_zone.heating_setpoint)
temp_back = usage_zone.heating_setback temp_back = float(usage_zone.heating_setback)
occupancy = usage_zone.occupancy.occupant_schedule(period) occupancy = Occupancy().get_complete_year_schedule(usage_zone.schedules['Occupancy'])
# todo: heating_schedule is still missing heating_schedule = self._conditioning_seasons['heating']
heating_schedule = usage_zone.heating_schedule_month
self._hourly_heating = pd.DataFrame(columns=['monthly to hourly']) hourly_heating = []
i = 0 i = 0
for month in range(0, 12): temp_grad_day = []
for month in range(1, 13):
temp_grad_month = 0 temp_grad_month = 0
for day in cte.days_of_month[month]: month_range = cal.monthrange(2015, month)
for day in range(1, month_range[1]+1):
external_temp_med = 0 external_temp_med = 0
for hour in range(0, 24): for hour in range(0, 24):
external_temp_med += external_temp[i]/24 external_temp_med += external_temp['inseldb'][i]/24
for hour in range(0, 24): for hour in range(0, 24):
if external_temp_med < temp_set[i] & heating_schedule[month] == 1: if external_temp_med < temp_set and heating_schedule[month-1] == 1:
if occupancy[hour] == 1: if occupancy[hour] > 0:
temp_grad_day = temp_set[i] - external_temp[i] temp_grad_day.append(temp_set - external_temp['inseldb'][i])
else: else:
temp_grad_day = temp_back[i] - external_temp[i] temp_grad_day.append(temp_back - external_temp['inseldb'][i])
else: else:
temp_grad_day = 0 temp_grad_day.append(0)
temp_grad_month += temp_grad_day temp_grad_month += temp_grad_day[i]
self._hourly_heating.append(self._building.monthly_heating(month)*temp_grad_day/temp_grad_month)
i += 1 i += 1
for day in range(1, month_range[1] + 1):
for hour in range(0, 24):
j = (day - 1) * 24 + hour
monthly_demand = self._building.heating['month']['INSEL'][month-1]
hourly_demand = float(monthly_demand)*float(temp_grad_day[j])/float(temp_grad_month)
hourly_heating.append(hourly_demand)
self._hourly_heating = pd.DataFrame(data=hourly_heating, columns=['monthly to hourly'])
return self._hourly_heating return self._hourly_heating
@property @property

View File

@ -12,7 +12,7 @@ class OccupancyFactory:
""" """
PhysicsFactor class PhysicsFactor class
""" """
def __init__(self, handler, city, base_path=Path(Path(__file__).parent.parent.parent / 'data/occupancy')): def __init__(self, handler, city, base_path=Path(Path(__file__).parent.parent / 'data/occupancy')):
self._handler = '_' + handler.lower().replace(' ', '_') self._handler = '_' + handler.lower().replace(' ', '_')
self._city = city self._city = city
self._base_path = base_path self._base_path = base_path

View File

@ -2,6 +2,7 @@
PhysicsFactory retrieve the specific physics module for the given region PhysicsFactory retrieve the specific physics module for the given region
SPDX - License - Identifier: LGPL - 3.0 - or -later SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
contributors Pilar Monsalvete pilar_monsalvete@yahoo.es
""" """
import pandas as pd import pandas as pd
from factories.occupancy_feeders.helpers.occupancy_helper import OccupancyHelper from factories.occupancy_feeders.helpers.occupancy_helper import OccupancyHelper
@ -12,19 +13,27 @@ class DemoOccupancyParameters:
def __init__(self, city, base_path): def __init__(self, city, base_path):
self._city = city self._city = city
self._demo_schedules_path = base_path / 'demo_schedules.xlsx' self._demo_schedules_path = base_path / 'demo_schedules.xlsx'
print('schedules: ', self._demo_schedules_path)
xls = pd.ExcelFile(self._demo_schedules_path) xls = pd.ExcelFile(self._demo_schedules_path)
# todo: review for more than one usage_zones per building # todo: review for more than one usage_zones per building
for building in city.buildings: for building in city.buildings:
schedules = dict() schedules = dict()
occupancy = pd.read_excel(xls, sheet_name=OccupancyHelper.pluto_occupancy_function(building.function), occupancy = pd.read_excel(xls, sheet_name=OccupancyHelper.pluto_occupancy_function(building.function),
skiprows=[0, 1, 2, 3], nrows=39, usecols="A:AA") skiprows=[0, 1, 2, 3], nrows=39, usecols="A:AA")
# todo: should we safe the data type? How?
for index in range(0, 13): for index in range(0, 13):
row = occupancy.iloc[3 * index] data = pd.DataFrame()
data = row[1:] columns_names = []
name = row[0] name = ''
for i in range(1, 3): data_type = ''
for i in range(0, 3):
row = occupancy.iloc[3*index + i] row = occupancy.iloc[3*index + i]
data1 = row[1:] if i == 0:
data = pd.concat([data, data1], axis=1) name = row[0]
data_type = row[1]
columns_names.append(row[2])
data1 = row[3:]
data = pd.concat([data, data1], axis=1)
data.columns = columns_names
schedules[name] = data schedules[name] = data
building.usage_zones[0].schedules = schedules building.usage_zones[0].schedules = schedules

View File

@ -52,4 +52,5 @@ kiwisolver~=1.2.0
zipp~=3.1.0 zipp~=3.1.0
requests~=2.24.0 requests~=2.24.0
esoreader~=1.2.3 esoreader~=1.2.3
geomeppy~=0.11.8 geomeppy~=0.11.8
xlrd~=1.2.0

View File

@ -9,6 +9,7 @@ from unittest import TestCase
from factories.geometry_factory import GeometryFactory from factories.geometry_factory import GeometryFactory
from factories.usage_factory import UsageFactory from factories.usage_factory import UsageFactory
from factories.occupancy_factory import OccupancyFactory from factories.occupancy_factory import OccupancyFactory
from city_model_structure.attributes.occupancy import Occupancy
class TestOccupancyFactory(TestCase): class TestOccupancyFactory(TestCase):
@ -46,3 +47,4 @@ class TestOccupancyFactory(TestCase):
for building in city.buildings: for building in city.buildings:
for usage_zone in building.usage_zones: for usage_zone in building.usage_zones:
self.assertTrue(usage_zone.schedules) self.assertTrue(usage_zone.schedules)
print(len(Occupancy().get_complete_year_schedule(usage_zone.schedules['Occupancy'])))