solved bug in nrcan catalog and partially cleaned ep exporter
This commit is contained in:
parent
d4029aee10
commit
d82ada6240
|
@ -131,10 +131,9 @@ class NrcanCatalog(Catalog):
|
||||||
mechanical_air_change = space_type['ventilation_air_changes']
|
mechanical_air_change = space_type['ventilation_air_changes']
|
||||||
# cfm/ft2 to m3/m2.s
|
# cfm/ft2 to m3/m2.s
|
||||||
ventilation_rate = space_type['ventilation_per_area'] / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
|
ventilation_rate = space_type['ventilation_per_area'] / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)
|
||||||
if ventilation_rate == 0:
|
|
||||||
# cfm/person to m3/m2.s
|
# cfm/person to m3/m2.s
|
||||||
ventilation_rate = space_type['ventilation_per_person'] / (cte.METERS_TO_FEET * cte.MINUTES_TO_SECONDS)\
|
ventilation_rate += space_type['ventilation_per_person'] / (pow(cte.METERS_TO_FEET, 3) * cte.MINUTES_TO_SECONDS)\
|
||||||
/ occupancy_density
|
* occupancy_density
|
||||||
|
|
||||||
lighting_radiative_fraction = space_type['lighting_fraction_radiant']
|
lighting_radiative_fraction = space_type['lighting_fraction_radiant']
|
||||||
lighting_convective_fraction = 0
|
lighting_convective_fraction = 0
|
||||||
|
|
|
@ -4,6 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2022 Concordia CERC group
|
Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Guille Guillermo.GutierrezMorote@concordia.ca
|
Project Coder Guille Guillermo.GutierrezMorote@concordia.ca
|
||||||
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
|
Oriol Gavaldà Torrellas oriol.gavalda@concordia.ca
|
||||||
"""
|
"""
|
||||||
import copy
|
import copy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -100,7 +101,6 @@ class Idf:
|
||||||
self._adjacent_buildings = adjacent_buildings
|
self._adjacent_buildings = adjacent_buildings
|
||||||
if self._adjacent_buildings is None:
|
if self._adjacent_buildings is None:
|
||||||
self._adjacent_buildings = []
|
self._adjacent_buildings = []
|
||||||
|
|
||||||
self._export()
|
self._export()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -202,9 +202,13 @@ class Idf:
|
||||||
_infiltration_values = []
|
_infiltration_values = []
|
||||||
for hvac_value in hvac_availability_schedule.values:
|
for hvac_value in hvac_availability_schedule.values:
|
||||||
if hvac_value == 0:
|
if hvac_value == 0:
|
||||||
_infiltration_values.append(thermal_zone.infiltration_rate_system_off)
|
_infiltration_values.append(1.0)
|
||||||
else:
|
else:
|
||||||
_infiltration_values.append(thermal_zone.infiltration_rate_system_on)
|
if thermal_zone.infiltration_rate_system_off == 0:
|
||||||
|
_infiltration_values.append(0.0)
|
||||||
|
else:
|
||||||
|
_infiltration_values.append(
|
||||||
|
thermal_zone.infiltration_rate_system_on / thermal_zone.infiltration_rate_system_off)
|
||||||
_schedule.values = _infiltration_values
|
_schedule.values = _infiltration_values
|
||||||
_infiltration_schedules.append(_schedule)
|
_infiltration_schedules.append(_schedule)
|
||||||
for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
|
for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
|
||||||
|
@ -315,7 +319,6 @@ class Idf:
|
||||||
for zone in self._idf.idfobjects['ZONE']:
|
for zone in self._idf.idfobjects['ZONE']:
|
||||||
if zone.Name == name:
|
if zone.Name == name:
|
||||||
return
|
return
|
||||||
# todo: what do we need to define a zone in energy plus?
|
|
||||||
self._idf.newidfobject(self._ZONE, Name=name, Volume=thermal_zone.volume)
|
self._idf.newidfobject(self._ZONE, Name=name, Volume=thermal_zone.volume)
|
||||||
self._add_heating_system(thermal_zone, name)
|
self._add_heating_system(thermal_zone, name)
|
||||||
|
|
||||||
|
@ -362,13 +365,9 @@ class Idf:
|
||||||
|
|
||||||
def _add_lighting(self, thermal_zone: ThermalZone, zone_name: str):
|
def _add_lighting(self, thermal_zone: ThermalZone, zone_name: str):
|
||||||
fraction_radiant = thermal_zone.lighting.radiative_fraction
|
fraction_radiant = thermal_zone.lighting.radiative_fraction
|
||||||
# todo: fraction visible should come from catalog
|
|
||||||
fraction_visible = 0.3
|
|
||||||
method = 'Watts/Area'
|
method = 'Watts/Area'
|
||||||
factor_size = thermal_zone.total_floor_area / thermal_zone.footprint_area
|
storeys_number = int(thermal_zone.total_floor_area / thermal_zone.footprint_area)
|
||||||
watts_per_zone_floor_area = thermal_zone.lighting.density * factor_size
|
watts_per_zone_floor_area = thermal_zone.lighting.density * storeys_number
|
||||||
# todo: fraction replaceable should come from catalog
|
|
||||||
fraction_replaceable = 1
|
|
||||||
subcategory = f'ELECTRIC EQUIPMENT#{zone_name}#GeneralLights'
|
subcategory = f'ELECTRIC EQUIPMENT#{zone_name}#GeneralLights'
|
||||||
|
|
||||||
self._idf.newidfobject(self._LIGHTS,
|
self._idf.newidfobject(self._LIGHTS,
|
||||||
|
@ -378,21 +377,17 @@ class Idf:
|
||||||
Design_Level_Calculation_Method=method,
|
Design_Level_Calculation_Method=method,
|
||||||
Watts_per_Zone_Floor_Area=watts_per_zone_floor_area,
|
Watts_per_Zone_Floor_Area=watts_per_zone_floor_area,
|
||||||
Fraction_Radiant=fraction_radiant,
|
Fraction_Radiant=fraction_radiant,
|
||||||
Fraction_Visible=fraction_visible,
|
|
||||||
Fraction_Replaceable=fraction_replaceable,
|
|
||||||
EndUse_Subcategory=subcategory
|
EndUse_Subcategory=subcategory
|
||||||
)
|
)
|
||||||
|
|
||||||
def _add_appliances(self, thermal_zone, zone_name):
|
def _add_appliances(self, thermal_zone, zone_name):
|
||||||
fuel_type = 'Electricity'
|
fuel_type = 'Electricity'
|
||||||
fraction_radiant = thermal_zone.appliances.radiative_fraction
|
fraction_radiant = thermal_zone.appliances.radiative_fraction
|
||||||
fraction_latent = 0
|
fraction_latent = thermal_zone.appliances.latent_fraction
|
||||||
method = 'Watts/Area'
|
method = 'Watts/Area'
|
||||||
factor_size = thermal_zone.total_floor_area / thermal_zone.footprint_area
|
storeys_number = int(thermal_zone.total_floor_area / thermal_zone.footprint_area)
|
||||||
watts_per_zone_floor_area = thermal_zone.appliances.density * factor_size
|
watts_per_zone_floor_area = thermal_zone.appliances.density * storeys_number
|
||||||
subcategory = f'ELECTRIC EQUIPMENT#{zone_name}#InteriorEquipment'
|
subcategory = f'ELECTRIC EQUIPMENT#{zone_name}#InteriorEquipment'
|
||||||
# _object = self._idf.newidfobject(self._APPLIANCES)
|
|
||||||
# print(vars(_object))
|
|
||||||
self._idf.newidfobject(self._APPLIANCES,
|
self._idf.newidfobject(self._APPLIANCES,
|
||||||
Fuel_Type=fuel_type,
|
Fuel_Type=fuel_type,
|
||||||
Name=f'{zone_name}_appliance',
|
Name=f'{zone_name}_appliance',
|
||||||
|
@ -406,36 +401,30 @@ class Idf:
|
||||||
)
|
)
|
||||||
|
|
||||||
def _add_infiltration(self, thermal_zone, zone_name):
|
def _add_infiltration(self, thermal_zone, zone_name):
|
||||||
# for zone in self._idf.idfobjects["ZONE"]:
|
|
||||||
# if zone.Name == f'{zone_name}_infiltration':
|
for zone in self._idf.idfobjects["ZONE"]:
|
||||||
# return
|
if zone.Name == f'{zone_name}_infiltration':
|
||||||
|
return
|
||||||
schedule = f'Infiltration schedules {thermal_zone.usage_name}'
|
schedule = f'Infiltration schedules {thermal_zone.usage_name}'
|
||||||
# if schedule not in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
|
if schedule not in self._idf.idfobjects[self._HOURLY_SCHEDULE]:
|
||||||
# return
|
return
|
||||||
# todo: eliminate the factor
|
|
||||||
factorreduct = 0.5
|
|
||||||
self._idf.newidfobject(self._INFILTRATION,
|
self._idf.newidfobject(self._INFILTRATION,
|
||||||
Name=f'{zone_name}_infiltration',
|
Name=f'{zone_name}_infiltration',
|
||||||
Zone_or_ZoneList_Name=zone_name,
|
Zone_or_ZoneList_Name=zone_name,
|
||||||
Schedule_Name=schedule,
|
Schedule_Name=schedule,
|
||||||
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
Design_Flow_Rate_Calculation_Method='AirChanges/Hour',
|
||||||
Air_Changes_per_Hour=thermal_zone.infiltration_rate_system_off * factorreduct
|
Air_Changes_per_Hour=thermal_zone.infiltration_rate_system_off
|
||||||
)
|
)
|
||||||
|
|
||||||
def _add_dhw(self, thermal_zone, zone_name):
|
def _add_dhw(self, building, thermal_zone, zone_name):
|
||||||
fuel_type = 'Electricity'
|
|
||||||
method = 'Watts/Area'
|
|
||||||
factor_size = thermal_zone.total_floor_area / thermal_zone.footprint_area
|
|
||||||
# todo: revision of values of peak flow (too low). Added a factor, but to check original units
|
|
||||||
peak_flow_rate = thermal_zone.domestic_hot_water.peak_flow * thermal_zone.total_floor_area
|
peak_flow_rate = thermal_zone.domestic_hot_water.peak_flow * thermal_zone.total_floor_area
|
||||||
# = self._idf.newidfobject(self._dhw)
|
|
||||||
# print(vars(_object))
|
|
||||||
self._idf.newidfobject(self._DHW,
|
self._idf.newidfobject(self._DHW,
|
||||||
Name=f'DHW {zone_name}',
|
Name=f'DHW {zone_name}',
|
||||||
Peak_Flow_Rate=peak_flow_rate,
|
Peak_Flow_Rate=peak_flow_rate,
|
||||||
Flow_Rate_Fraction_Schedule_Name=f'DHW_prof schedules {thermal_zone.usage_name}',
|
Flow_Rate_Fraction_Schedule_Name=f'DHW_prof schedules {thermal_zone.usage_name}',
|
||||||
Target_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}',
|
Target_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}',
|
||||||
Hot_Water_Supply_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}',
|
Hot_Water_Supply_Temperature_Schedule_Name=f'DHW_temp schedules {thermal_zone.usage_name}',
|
||||||
|
Cold_Water_Supply_Temperature_Schedule_Name=f'cold_temp schedules {building.name}',
|
||||||
EndUse_Subcategory=f'DHW {zone_name}',
|
EndUse_Subcategory=f'DHW {zone_name}',
|
||||||
Zone_Name=zone_name
|
Zone_Name=zone_name
|
||||||
)
|
)
|
||||||
|
@ -489,7 +478,7 @@ class Idf:
|
||||||
self._add_schedules(usage, 'Lighting', thermal_zone.lighting.schedules)
|
self._add_schedules(usage, 'Lighting', thermal_zone.lighting.schedules)
|
||||||
self._add_schedules(usage, 'Appliance', thermal_zone.appliances.schedules)
|
self._add_schedules(usage, 'Appliance', thermal_zone.appliances.schedules)
|
||||||
self._add_schedules(usage, 'DHW_prof', thermal_zone.domestic_hot_water.schedules)
|
self._add_schedules(usage, 'DHW_prof', thermal_zone.domestic_hot_water.schedules)
|
||||||
# self._add_service_temp_schedules(thermal_zone)
|
# todo self._add_service_temp_schedules(thermal_zone)
|
||||||
value = int(thermal_zone.domestic_hot_water.service_temperature)
|
value = int(thermal_zone.domestic_hot_water.service_temperature)
|
||||||
self._add_constant_hourly_year_schedules(thermal_zone, value, 'DHW_temp')
|
self._add_constant_hourly_year_schedules(thermal_zone, value, 'DHW_temp')
|
||||||
self._add_people_activity_level_schedules(thermal_zone)
|
self._add_people_activity_level_schedules(thermal_zone)
|
||||||
|
@ -519,8 +508,6 @@ class Idf:
|
||||||
Variable_Name="Zone Ideal Loads Supply Air Total Heating Energy",
|
Variable_Name="Zone Ideal Loads Supply Air Total Heating Energy",
|
||||||
Reporting_Frequency="Monthly",
|
Reporting_Frequency="Monthly",
|
||||||
)
|
)
|
||||||
# _object = self._idf.newidfobject("OUTPUT:VARIABLE")
|
|
||||||
# print(vars(_object))
|
|
||||||
|
|
||||||
self._idf.newidfobject(
|
self._idf.newidfobject(
|
||||||
"OUTPUT:VARIABLE",
|
"OUTPUT:VARIABLE",
|
||||||
|
@ -534,18 +521,6 @@ class Idf:
|
||||||
Reporting_Frequency="Monthly",
|
Reporting_Frequency="Monthly",
|
||||||
)
|
)
|
||||||
|
|
||||||
# self._idf.newidfobject(
|
|
||||||
# "OUTPUTCONTROL:TABLE:STYLE",
|
|
||||||
# Variable_Name="CommaAndHTML, JtoKWH",
|
|
||||||
# )
|
|
||||||
|
|
||||||
# self._idf.match()
|
|
||||||
# try:
|
|
||||||
# self._idf.intersect_match()
|
|
||||||
# except IndexError:
|
|
||||||
# seems to be a bug from geomeppy when surfaces cannot be intersected
|
|
||||||
# pass
|
|
||||||
|
|
||||||
# post-process to erase windows associated to adiabatic walls
|
# post-process to erase windows associated to adiabatic walls
|
||||||
windows_list = []
|
windows_list = []
|
||||||
for window in self._idf.idfobjects[self._WINDOW]:
|
for window in self._idf.idfobjects[self._WINDOW]:
|
||||||
|
@ -598,15 +573,12 @@ class Idf:
|
||||||
Fraction_of_Shading_Surface_That_Is_Glazed=0)
|
Fraction_of_Shading_Surface_That_Is_Glazed=0)
|
||||||
|
|
||||||
def _add_pure_geometry(self, building, zone_name):
|
def _add_pure_geometry(self, building, zone_name):
|
||||||
|
|
||||||
for surface in building.surfaces:
|
for surface in building.surfaces:
|
||||||
outside_boundary_condition = 'Outdoors'
|
outside_boundary_condition = 'Outdoors'
|
||||||
sun_exposure = 'SunExposed'
|
sun_exposure = 'SunExposed'
|
||||||
wind_exposure = 'WindExposed'
|
wind_exposure = 'WindExposed'
|
||||||
outside_boundary_condition_object = None
|
outside_boundary_condition_object = None
|
||||||
# TODO: set assumption in constants, to select minimun shared area
|
if surface.percentage_shared is not None and surface.percentage_shared > 0.5:
|
||||||
#print(f'wall {surface.name} {surface.percentage_shared}')
|
|
||||||
if surface.percentage_shared is not None and surface.percentage_shared > 0.1:
|
|
||||||
outside_boundary_condition = 'Surface'
|
outside_boundary_condition = 'Surface'
|
||||||
outside_boundary_condition_object = surface.name
|
outside_boundary_condition_object = surface.name
|
||||||
sun_exposure = 'NoSun'
|
sun_exposure = 'NoSun'
|
||||||
|
@ -645,8 +617,7 @@ class Idf:
|
||||||
sun_exposure = 'SunExposed'
|
sun_exposure = 'SunExposed'
|
||||||
wind_exposure = 'WindExposed'
|
wind_exposure = 'WindExposed'
|
||||||
outside_boundary_condition_object = ''
|
outside_boundary_condition_object = ''
|
||||||
# TODO: set assumption in constants, to select minimun shared area
|
if boundary.parent_surface.percentage_shared is not None and boundary.parent_surface.percentage_shared >= 0.5:
|
||||||
if boundary.parent_surface.percentage_shared is not None and boundary.parent_surface.percentage_shared >= 0.1:
|
|
||||||
outside_boundary_condition = 'Surface'
|
outside_boundary_condition = 'Surface'
|
||||||
outside_boundary_condition_object = boundary.parent_surface.name
|
outside_boundary_condition_object = boundary.parent_surface.name
|
||||||
sun_exposure = 'NoSun'
|
sun_exposure = 'NoSun'
|
||||||
|
@ -659,7 +630,6 @@ class Idf:
|
||||||
construction_name = f'{boundary.construction_name}_{boundary.parent_surface.vegetation.name}'
|
construction_name = f'{boundary.construction_name}_{boundary.parent_surface.vegetation.name}'
|
||||||
else:
|
else:
|
||||||
construction_name = boundary.construction_name
|
construction_name = boundary.construction_name
|
||||||
#print(f'shared wall {boundary.parent_surface.name} {outside_boundary_condition_object} {idf_surface_type}')
|
|
||||||
surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.parent_surface.name}',
|
surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.parent_surface.name}',
|
||||||
Surface_Type=idf_surface_type,
|
Surface_Type=idf_surface_type,
|
||||||
Zone_Name=zone_name,
|
Zone_Name=zone_name,
|
||||||
|
|
|
@ -45,12 +45,12 @@ class NrcanUsageParameters:
|
||||||
sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
|
sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
usage_name = Dictionaries().hub_usage_to_comnet_usage[building.function]
|
comnet_usage_name = Dictionaries().hub_usage_to_comnet_usage[building.function]
|
||||||
try:
|
try:
|
||||||
comnet_archetype_usage = self._search_archetypes(comnet_catalog, usage_name)
|
comnet_archetype_usage = self._search_archetypes(comnet_catalog, comnet_usage_name)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logger.error(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
|
logger.error(f'Building {building.name} has unknown usage archetype for usage: {comnet_usage_name}\n')
|
||||||
sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {usage_name}\n')
|
sys.stderr.write(f'Building {building.name} has unknown usage archetype for usage: {comnet_usage_name}\n')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for internal_zone in building.internal_zones:
|
for internal_zone in building.internal_zones:
|
||||||
|
@ -81,8 +81,10 @@ class NrcanUsageParameters:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _assign_values(usage, archetype, volume_per_area, cold_water_temperature):
|
def _assign_values(usage, archetype, volume_per_area, cold_water_temperature):
|
||||||
if archetype.mechanical_air_change > 0:
|
if archetype.mechanical_air_change > 0:
|
||||||
|
# ACH
|
||||||
usage.mechanical_air_change = archetype.mechanical_air_change
|
usage.mechanical_air_change = archetype.mechanical_air_change
|
||||||
elif archetype.ventilation_rate > 0:
|
elif archetype.ventilation_rate > 0:
|
||||||
|
# m3/m2.s to ACH
|
||||||
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area * cte.HOUR_TO_SECONDS
|
usage.mechanical_air_change = archetype.ventilation_rate / volume_per_area * cte.HOUR_TO_SECONDS
|
||||||
else:
|
else:
|
||||||
usage.mechanical_air_change = 0
|
usage.mechanical_air_change = 0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user