cerc idf implementation refactoring and added systems

This commit is contained in:
Guille Gutierrez 2024-09-23 17:52:52 +02:00
parent 5e384c8185
commit 27514d4d77
3 changed files with 142 additions and 14 deletions

View File

@ -7,10 +7,12 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord
Oriol Gavalda Torrellas oriol.gavalda@concordia.ca Oriol Gavalda Torrellas oriol.gavalda@concordia.ca
""" """
import copy import copy
import os
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
import hub.helpers.constants as cte
import hub.exports.building_energy.idf_helper as idf_cte import hub.exports.building_energy.idf_helper as idf_cte
import hub.helpers.constants as cte
from hub.city_model_structure.attributes.schedule import Schedule from hub.city_model_structure.attributes.schedule import Schedule
from hub.city_model_structure.building_demand.layer import Layer from hub.city_model_structure.building_demand.layer import Layer
@ -43,11 +45,13 @@ class CercIdf:
'occupancy': str((output_path / 'occupancy.idf').resolve()), 'occupancy': str((output_path / 'occupancy.idf').resolve()),
'lighting': str((output_path / 'lights.idf').resolve()), 'lighting': str((output_path / 'lights.idf').resolve()),
'appliances': str((output_path / 'appliances.idf').resolve()), 'appliances': str((output_path / 'appliances.idf').resolve()),
'surfaces': str((output_path / 'surfaces.idf').resolve()),
'shading': str((output_path / 'shading.idf').resolve()),
'infiltration': str((output_path / 'infiltration.idf').resolve()), 'infiltration': str((output_path / 'infiltration.idf').resolve()),
'ventilation': str((output_path / 'ventilation.idf').resolve()), 'ventilation': str((output_path / 'ventilation.idf').resolve()),
'thermostat': str((output_path / 'thermostat.idf').resolve()), 'thermostat': str((output_path / 'thermostat.idf').resolve()),
'ideal_load_system': str((output_path / 'ideal_load_system.idf').resolve()), 'ideal_load_system': str((output_path / 'ideal_load_system.idf').resolve()),
'surfaces': str((output_path / 'surfaces.idf').resolve()) # todo: move surface to the right position after appliances 'dhw': str((output_path / 'dhw.idf').resolve()),
} }
self._files = {} self._files = {}
for key, value in self._file_paths.items(): for key, value in self._file_paths.items():
@ -55,7 +59,9 @@ class CercIdf:
self._idd_file_path = str(idd_file_path) self._idd_file_path = str(idd_file_path)
self._idf_file_path = str(idf_file_path) self._idf_file_path = str(idf_file_path)
self._outputs_file_path = str(Path(idf_file_path).parent / 'outputs.idf')
self._epw_file_path = str(epw_file_path) self._epw_file_path = str(epw_file_path)
self._target_buildings = target_buildings self._target_buildings = target_buildings
self._adjacent_buildings = [] self._adjacent_buildings = []
@ -83,6 +89,13 @@ class CercIdf:
with open(path, 'r') as file: with open(path, 'r') as file:
lines = file.readlines() lines = file.readlines()
self._idf_file.writelines(lines) self._idf_file.writelines(lines)
for path in self._file_paths.values():
os.unlink(path)
def _add_outputs(self):
with open(self._outputs_file_path, 'r') as base_idf:
lines = base_idf.readlines()
self._idf_file.writelines(lines)
def _create_geometry_rules(self): def _create_geometry_rules(self):
file = self._files['zones'] file = self._files['zones']
@ -330,13 +343,6 @@ class CercIdf:
self._write_to_idf_format(file, thermal_opening.g_value, 'Solar Heat Gain Coefficient', ';') self._write_to_idf_format(file, thermal_opening.g_value, 'Solar Heat Gain Coefficient', ';')
def _add_constructions(self, thermal_boundary): def _add_constructions(self, thermal_boundary):
"""
CONSTRUCTION,
1000_1900_6 Roof, !- Name
Asphalt 1, !- Outside Layer
virtual_no_mass_13, !- Layer 2
MW Glass Wool (rolls); !- Layer 3
"""
if thermal_boundary.layers is None: if thermal_boundary.layers is None:
thermal_boundary.layers = [self._add_default_material()] thermal_boundary.layers = [self._add_default_material()]
name = f'{thermal_boundary.construction_name} {thermal_boundary.parent_surface.type}' name = f'{thermal_boundary.construction_name} {thermal_boundary.parent_surface.type}'
@ -493,7 +499,6 @@ class CercIdf:
def _add_ventilation(self, thermal_zone, zone_name): def _add_ventilation(self, thermal_zone, zone_name):
schedule_name = f'Ventilation schedules {thermal_zone.usage_name}' schedule_name = f'Ventilation schedules {thermal_zone.usage_name}'
air_change = thermal_zone.mechanical_air_change * cte.HOUR_TO_SECONDS air_change = thermal_zone.mechanical_air_change * cte.HOUR_TO_SECONDS
infiltration = thermal_zone.infiltration_rate_system_off * cte.HOUR_TO_SECONDS
file = self._files['ventilation'] file = self._files['ventilation']
self._write_to_idf_format(file, idf_cte.VENTILATION) self._write_to_idf_format(file, idf_cte.VENTILATION)
self._write_to_idf_format(file, f'{zone_name}_ventilation', 'Name') self._write_to_idf_format(file, f'{zone_name}_ventilation', 'Name')
@ -572,17 +577,70 @@ class CercIdf:
self._write_to_idf_format(file, 0.70, 'Sensible Heat Recovery Effectiveness') self._write_to_idf_format(file, 0.70, 'Sensible Heat Recovery Effectiveness')
self._write_to_idf_format(file, 0.65, 'Latent Heat Recovery Effectiveness', ';') self._write_to_idf_format(file, 0.65, 'Latent Heat Recovery Effectiveness', ';')
def _add_dhw(self, thermal_zone, zone_name):
name = f'DHW {zone_name}'
peak_flow_rate = thermal_zone.domestic_hot_water.peak_flow * thermal_zone.total_floor_area
flow_rate_schedule = f'DHW_prof schedules {thermal_zone.usage_name}'
dhw_schedule = f'DHW_temp schedules {thermal_zone.usage_name}'
cold_temp_schedule = f'cold_temp schedules {thermal_zone.usage_name}'
file = self._files['dhw']
self._write_to_idf_format(file, idf_cte.DHW)
self._write_to_idf_format(file, name, 'Name')
self._write_to_idf_format(file, name, 'EndUse Subcategory')
self._write_to_idf_format(file, peak_flow_rate, 'Peak Flow Rate')
self._write_to_idf_format(file, flow_rate_schedule, 'Flow Rate Fraction Schedule Name')
self._write_to_idf_format(file, dhw_schedule, 'Target Temperature Schedule Name')
self._write_to_idf_format(file, dhw_schedule, 'Hot Water Supply Temperature Schedule Name')
self._write_to_idf_format(file, cold_temp_schedule, 'Cold Water Supply Temperature Schedule Name')
self._write_to_idf_format(file, zone_name, 'Zone Name', ';')
def _add_shading(self, building):
name = building.name
file = self._files['shading']
for s, surface in enumerate(building.surfaces):
self._write_to_idf_format(file, idf_cte.SHADING)
self._write_to_idf_format(file, f'{name}_{s}', 'Name')
self._write_to_idf_format(file, idf_cte.EMPTY, 'Transmittance Schedule Name')
self._write_to_idf_format(file, idf_cte.AUTOCALCULATE, 'Number of Vertices')
eol = ','
coordinates = self._matrix_to_list(surface.solid_polygon.coordinates, self._city.lower_corner)
coordinates_length = len(coordinates)
for i, coordinate in enumerate(coordinates):
vertex = i + 1
if vertex == coordinates_length:
eol = ';'
self._write_to_idf_format(file, coordinate[0], f'Vertex {vertex} Xcoordinate')
self._write_to_idf_format(file, coordinate[1], f'Vertex {vertex} Ycoordinate')
self._write_to_idf_format(file, coordinate[2], f'Vertex {vertex} Zcoordinate', eol)
def _add_window_construction_and_material(self, thermal_opening):
for window_material in self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]:
if window_material['UFactor'] == thermal_opening.overall_u_value and \
window_material['Solar_Heat_Gain_Coefficient'] == thermal_opening.g_value:
return
order = str(len(self._idf.idfobjects[self._WINDOW_MATERIAL_SIMPLE]) + 1)
material_name = 'glazing_' + order
_kwargs = {'Name': material_name, 'UFactor': thermal_opening.overall_u_value,
'Solar_Heat_Gain_Coefficient': thermal_opening.g_value}
self._idf.newidfobject(self._WINDOW_MATERIAL_SIMPLE, **_kwargs)
window_construction_name = 'window_construction_' + order
_kwargs = {'Name': window_construction_name, 'Outside_Layer': material_name}
self._idf.newidfobject(self._CONSTRUCTION, **_kwargs)
def _export(self): def _export(self):
start = datetime.now()
for building in self._city.buildings: for building in self._city.buildings:
is_target = building.name in self._target_buildings or building.name in self._adjacent_buildings is_target = building.name in self._target_buildings or building.name in self._adjacent_buildings
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
if internal_zone.thermal_zones_from_internal_zones is None: if internal_zone.thermal_zones_from_internal_zones is None:
self._target_buildings.remove(building.name)
is_target = False is_target = False
continue continue
for thermal_zone in internal_zone.thermal_zones_from_internal_zones: for thermal_zone in internal_zone.thermal_zones_from_internal_zones:
if is_target: if is_target:
start = datetime.now()
service_temperature = thermal_zone.domestic_hot_water.service_temperature service_temperature = thermal_zone.domestic_hot_water.service_temperature
usage = thermal_zone.usage_name usage = thermal_zone.usage_name
occ = thermal_zone.occupancy occ = thermal_zone.occupancy
@ -624,9 +682,14 @@ class CercIdf:
self._add_ventilation(thermal_zone, building.name) self._add_ventilation(thermal_zone, building.name)
self._add_thermostat(thermal_zone) self._add_thermostat(thermal_zone)
self._add_heating_system(thermal_zone, building.name) self._add_heating_system(thermal_zone, building.name)
self._add_dhw(thermal_zone, building.name)
if is_target: if is_target:
self._add_surfaces(building, building.name) self._add_surfaces(building, building.name)
else:
self._add_shading(building)
self._create_output_control_lighting() # Add lighting control to the lighting self._create_output_control_lighting() # Add lighting control to the lighting
# Merge files # Merge files
self._merge_files() self._merge_files()
self._add_outputs()
print(f'Export completed in: {datetime.now() - start}')

View File

@ -0,0 +1,64 @@
Output:Table:SummaryReports,
AnnualBuildingUtilityPerformanceSummary, !- Report 1 Name
DemandEndUseComponentsSummary, !- Report 2 Name
SensibleHeatGainSummary, !- Report 3 Name
InputVerificationandResultsSummary, !- Report 4 Name
AdaptiveComfortSummary, !- Report 5 Name
Standard62.1Summary, !- Report 6 Name
ClimaticDataSummary, !- Report 7 Name
EquipmentSummary, !- Report 8 Name
EnvelopeSummary, !- Report 9 Name
LightingSummary, !- Report 10 Name
HVACSizingSummary, !- Report 11 Name
SystemSummary, !- Report 12 Name
ComponentSizingSummary, !- Report 13 Name
OutdoorAirSummary, !- Report 14 Name
ObjectCountSummary, !- Report 15 Name
EndUseEnergyConsumptionOtherFuelsMonthly, !- Report 16 Name
PeakEnergyEndUseOtherFuelsMonthly; !- Report 17 Name
OutputControl:Table:Style,
CommaAndHTML, !- Column Separator
JtoKWH; !- Unit Conversion
OUTPUT:VARIABLE,
*, !- Key Value
Zone Ideal Loads Supply Air Total Heating Energy, !- Variable Name
Hourly; !- Reporting Frequency
OUTPUT:VARIABLE,
*, !- Key Value
Zone Ideal Loads Supply Air Total Cooling Energy, !- Variable Name
Hourly; !- Reporting Frequency
OUTPUT:VARIABLE,
*, !- Key Value
Water Use Equipment Heating Rate, !- Variable Name
Hourly; !- Reporting Frequency
OUTPUT:VARIABLE,
*, !- Key Value
Zone Lights Electricity Rate, !- Variable Name
Hourly; !- Reporting Frequency
OUTPUT:VARIABLE,
*, !- Key Value
Other Equipment Electricity Rate, !- Variable Name
Hourly; !- Reporting Frequency
Output:Meter,
DISTRICTHEATING:Facility, !- Key Name
hourly; !- Reporting Frequency
Output:Meter,
DISTRICTCOOLING:Facility, !- Key Name
hourly; !- Reporting Frequency
Output:Meter,
InteriorEquipment:Electricity, !- Key Name
hourly; !- Reporting Frequency
Output:Meter,
InteriorLights:Electricity, !- Key Name
hourly; !- Reporting Frequency

View File

@ -17,7 +17,8 @@ INFILTRATION = '\nZONEINFILTRATION:DESIGNFLOWRATE,\n'
VENTILATION = '\nZONEVENTILATION:DESIGNFLOWRATE,\n' VENTILATION = '\nZONEVENTILATION:DESIGNFLOWRATE,\n'
THERMOSTAT = '\nHVACTEMPLATE:THERMOSTAT,\n' THERMOSTAT = '\nHVACTEMPLATE:THERMOSTAT,\n'
IDEAL_LOAD_SYSTEM = '\nHVACTEMPLATE:ZONE:IDEALLOADSAIRSYSTEM,\n' IDEAL_LOAD_SYSTEM = '\nHVACTEMPLATE:ZONE:IDEALLOADSAIRSYSTEM,\n'
DHW = '\nWATERUSE:EQUIPMENT,\n'
SHADING = '\nSHADING:BUILDING:DETAILED,\n'
AUTOCALCULATE = 'autocalculate' AUTOCALCULATE = 'autocalculate'
ROUGHNESS = 'MediumRough' ROUGHNESS = 'MediumRough'