Merge remote-tracking branch 'origin/master'
# Conflicts: # requirements.txt
This commit is contained in:
commit
3c79c2288c
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -805,4 +805,28 @@
|
|||||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||||
</archetype>
|
</archetype>
|
||||||
|
<archetype id="36" building_type="residential" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||||
|
<constructions>
|
||||||
|
<construction id="19" type="exterior wall" >
|
||||||
|
<window_ratio units="-">0.15</window_ratio>
|
||||||
|
<window>4</window>
|
||||||
|
</construction>
|
||||||
|
<construction id="22" type="exterior slab">
|
||||||
|
<window_ratio units="-">0</window_ratio>
|
||||||
|
<window/>
|
||||||
|
</construction>
|
||||||
|
<construction id="17" type="roof" >
|
||||||
|
<window_ratio units="-">0</window_ratio>
|
||||||
|
<window/>
|
||||||
|
</construction>
|
||||||
|
</constructions>
|
||||||
|
<average_storey_height units="m">3.05</average_storey_height>
|
||||||
|
<number_of_storeys units="-">3</number_of_storeys>
|
||||||
|
<thermal_capacity units="kJ/K m2">90</thermal_capacity>
|
||||||
|
<extra_loses_due_to_thermal_bridges units="W/K m2">0.15</extra_loses_due_to_thermal_bridges>
|
||||||
|
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||||
|
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||||
|
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||||
|
</archetype>
|
||||||
|
|
||||||
</archetypes>
|
</archetypes>
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
name = row[0]
|
||||||
|
data_type = row[1]
|
||||||
|
columns_names.append(row[2])
|
||||||
|
data1 = row[3:]
|
||||||
data = pd.concat([data, data1], axis=1)
|
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
|
||||||
|
@ -40,7 +40,7 @@ class UsBasePhysicsParameters:
|
|||||||
# ToDo: remove this in the future
|
# ToDo: remove this in the future
|
||||||
# ToDo: Raise WrongArchetype if not all the surface types are defined for the given city_object
|
# ToDo: Raise WrongArchetype if not all the surface types are defined for the given city_object
|
||||||
if archetype is None:
|
if archetype is None:
|
||||||
print('Building ', building.name, 'has unknown archetype')
|
print('Building ', building.name, 'has unknown archetype for building type: ', building_type)
|
||||||
print('type: ', building_type, UsToLibraryTypes.yoc_to_standard(building.year_of_construction),
|
print('type: ', building_type, UsToLibraryTypes.yoc_to_standard(building.year_of_construction),
|
||||||
self._climate_zone)
|
self._climate_zone)
|
||||||
continue
|
continue
|
||||||
|
@ -3,7 +3,7 @@ UsNewYorkCityPhysicsParameters import the construction and material information
|
|||||||
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
|
||||||
"""
|
"""
|
||||||
from factories.physics_feeders.helpers.us_pluto_to_function import UsPlutoToFunction as Pf
|
from factories.physics_feeders.helpers.us_pluto_to_function import UsPlutoToFunction as pf
|
||||||
from factories.physics_feeders.us_base_physics_parameters import UsBasePhysicsParameters
|
from factories.physics_feeders.us_base_physics_parameters import UsBasePhysicsParameters
|
||||||
|
|
||||||
|
|
||||||
@ -14,4 +14,4 @@ class UsNewYorkCityPhysicsParameters(UsBasePhysicsParameters):
|
|||||||
def __init__(self, city, base_path):
|
def __init__(self, city, base_path):
|
||||||
self._city = city
|
self._city = city
|
||||||
climate_zone = 'ASHRAE_2004:4A'
|
climate_zone = 'ASHRAE_2004:4A'
|
||||||
super().__init__(climate_zone, self._city.buildings, Pf.function, base_path)
|
super().__init__(climate_zone, self._city.buildings, pf.function, base_path)
|
||||||
|
@ -3,7 +3,7 @@ UsNewYorkCityUsageParameters model the usage properties for a NYC building
|
|||||||
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
|
||||||
"""
|
"""
|
||||||
from factories.usage_feeders.helpers.us_pluto_to_usage import UsPlutoToUsage as Pu
|
from factories.usage_feeders.helpers.us_pluto_to_usage import UsPlutoToUsage as pu
|
||||||
from factories.usage_feeders.us_base_usage_parameters import UsBaseUsageParameters
|
from factories.usage_feeders.us_base_usage_parameters import UsBaseUsageParameters
|
||||||
|
|
||||||
|
|
||||||
@ -13,4 +13,4 @@ class UsNewYorkCityUsageParameters(UsBaseUsageParameters):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, city):
|
def __init__(self, city):
|
||||||
self._city = city
|
self._city = city
|
||||||
super().__init__(self._city, Pu.usage)
|
super().__init__(self._city, pu.usage)
|
||||||
|
@ -55,3 +55,4 @@ esoreader~=1.2.3
|
|||||||
geomeppy~=0.11.8
|
geomeppy~=0.11.8
|
||||||
pyglet~=1.5.8
|
pyglet~=1.5.8
|
||||||
networkx~=2.5
|
networkx~=2.5
|
||||||
|
xlrd~=1.2.0
|
||||||
|
@ -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'])))
|
||||||
|
Loading…
Reference in New Issue
Block a user