solved bug in nrcan catalog and partially cleaned ep exporter

This commit is contained in:
Pilar Monsalvete 2023-05-03 11:39:32 -04:00
parent d4029aee10
commit d82ada6240
3 changed files with 33 additions and 62 deletions

View File

@ -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

View File

@ -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,

View File

@ -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