cerc idf implementation
This commit is contained in:
parent
cc2ee61ada
commit
62c9a5aab7
@ -25,7 +25,7 @@ class CercIdf:
|
||||
_windows_added_to_idf = {'glazing_index': 0}
|
||||
_constructions_added_to_idf = {}
|
||||
|
||||
def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path, export_type="Surfaces",
|
||||
def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path,
|
||||
target_buildings=None):
|
||||
self._city = city
|
||||
self._output_path = str(output_path.resolve())
|
||||
@ -41,9 +41,10 @@ class CercIdf:
|
||||
self._output_lighting_path = str((output_path / 'lights.idf').resolve())
|
||||
self._output_appliances_path = str((output_path / 'appliances.idf').resolve())
|
||||
self._output_surfaces_path = str((output_path / 'surfaces.idf').resolve())
|
||||
self._output_infiltration_path = str((output_path / 'infiltration.idf').resolve())
|
||||
self._output_ventilation_path = str((output_path / 'ventilation.idf').resolve())
|
||||
self._output_file_path = str((output_path / f'{city.name}.idf').resolve())
|
||||
|
||||
self._export_type = export_type
|
||||
self._idd_file_path = str(idd_file_path)
|
||||
self._idf_file_path = str(idf_file_path)
|
||||
self._epw_file_path = str(epw_file_path)
|
||||
@ -71,7 +72,12 @@ class CercIdf:
|
||||
self._output_lighting = open(self._output_lighting_path, 'w')
|
||||
self._output_appliances = open(self._output_appliances_path, 'w')
|
||||
self._output_surfaces = open(self._output_surfaces_path, 'w')
|
||||
self._output_infiltration = open(self._output_infiltration_path, 'w')
|
||||
self._output_ventilation = open(self._output_ventilation_path, 'w')
|
||||
|
||||
# Create base values
|
||||
self._create_geometry_rules()
|
||||
|
||||
with open(self._output_file_path, 'w') as self._idf_file:
|
||||
self._idf_file.writelines(lines)
|
||||
self._export()
|
||||
@ -88,20 +94,21 @@ class CercIdf:
|
||||
self._output_lighting.close()
|
||||
self._output_appliances.close()
|
||||
self._output_surfaces.close()
|
||||
self._output_infiltration.close()
|
||||
self._output_ventilation.close()
|
||||
|
||||
def _create_geometry_rules(self):
|
||||
"""
|
||||
GlobalGeometryRules,
|
||||
UpperLeftCorner, !- Starting Vertex Position
|
||||
CounterClockWise, !- Vertex Entry Direction
|
||||
World; !- Coordinate System
|
||||
"""
|
||||
file = self._output_zones
|
||||
self._write_to_idf_format(file, idf_cte.GLOBAL_GEOMETRY_RULES)
|
||||
self._write_to_idf_format(file, 'UpperLeftCorner', 'Starting Vertex Position')
|
||||
self._write_to_idf_format(file, 'CounterClockWise', 'Vertex Entry Direction')
|
||||
self._write_to_idf_format(file, 'World', 'Coordinate System', ';')
|
||||
|
||||
def _create_output_control_lighting(self):
|
||||
file = self._output_appliances
|
||||
self._write_to_idf_format(file, idf_cte.OUTPUT_CONTROL)
|
||||
self._write_to_idf_format(file, 'Comma', 'Column Separator', ';')
|
||||
|
||||
@staticmethod
|
||||
def _write_to_idf_format(file, field, comment='', eol=','):
|
||||
if comment != '':
|
||||
@ -235,7 +242,8 @@ class CercIdf:
|
||||
for schedule in schedules:
|
||||
if schedule_name not in self._schedules_added_to_idf:
|
||||
self._schedules_added_to_idf[schedule_name] = True
|
||||
file_name = str((Path(self._output_path) / f'{schedule_type} schedules {usage.replace("/", "_")}.csv').resolve())
|
||||
file_name = str(
|
||||
(Path(self._output_path) / f'{schedule_type} schedules {usage.replace("/", "_")}.csv').resolve())
|
||||
with open(file_name, 'w', encoding='utf8') as file:
|
||||
for value in schedule.values:
|
||||
file.write(f'{str(value)},\n')
|
||||
@ -437,11 +445,12 @@ class CercIdf:
|
||||
storeys_number = int(thermal_zone.total_floor_area / thermal_zone.footprint_area)
|
||||
watts_per_zone_floor_area = thermal_zone.lighting.density * storeys_number
|
||||
subcategory = f'ELECTRIC EQUIPMENT#{zone_name}#GeneralLights'
|
||||
schedule_name = f'Lighting schedules {thermal_zone.usage_name}'
|
||||
file = self._output_lighting
|
||||
self._write_to_idf_format(file, idf_cte.LIGHTS)
|
||||
self._write_to_idf_format(file, f'{zone_name}_lights', 'Name')
|
||||
self._write_to_idf_format(file, zone_name, 'Zone or ZoneList or Space or SpaceList Name')
|
||||
self._write_to_idf_format(file, f'Lighting schedules {thermal_zone.usage_name}', 'Schedule Name')
|
||||
self._write_to_idf_format(file, schedule_name, 'Schedule Name')
|
||||
self._write_to_idf_format(file, 'Watts/Area', 'Design Level Calculation Method')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Lighting Level')
|
||||
self._write_to_idf_format(file, watts_per_zone_floor_area, 'Watts per Zone Floor Area')
|
||||
@ -476,6 +485,57 @@ class CercIdf:
|
||||
self._write_to_idf_format(file, 0, 'Carbon Dioxide Generation Rate')
|
||||
self._write_to_idf_format(file, subcategory, 'EndUse Subcategory', ';')
|
||||
|
||||
def _add_infiltration(self, thermal_zone, zone_name):
|
||||
schedule_name = f'Infiltration schedules {thermal_zone.usage_name}'
|
||||
infiltration = thermal_zone.infiltration_rate_system_off * cte.HOUR_TO_SECONDS
|
||||
file = self._output_infiltration
|
||||
self._write_to_idf_format(file, idf_cte.INFILTRATION)
|
||||
self._write_to_idf_format(file, f'{zone_name}_infiltration', 'Name')
|
||||
self._write_to_idf_format(file, zone_name, 'Zone or ZoneList or Space or SpaceList Name')
|
||||
self._write_to_idf_format(file, schedule_name, 'Schedule Name')
|
||||
self._write_to_idf_format(file, 'AirChanges/Hour', 'Design Flow Rate Calculation Method')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Design Flow Rate')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Flow Rate per Floor Area')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Flow Rate per Exterior Surface Area')
|
||||
self._write_to_idf_format(file, infiltration, 'Air Changes per Hour')
|
||||
self._write_to_idf_format(file, 1, 'Constant Term Coefficient')
|
||||
self._write_to_idf_format(file, 0, 'Temperature Term Coefficient')
|
||||
self._write_to_idf_format(file, 0, 'Velocity Term Coefficient')
|
||||
self._write_to_idf_format(file, 0, 'Velocity Squared Term Coefficient', ';')
|
||||
|
||||
def _add_ventilation(self, thermal_zone, zone_name):
|
||||
schedule_name = f'Ventilation schedules {thermal_zone.usage_name}'
|
||||
air_change = thermal_zone.mechanical_air_change * cte.HOUR_TO_SECONDS
|
||||
infiltration = thermal_zone.infiltration_rate_system_off * cte.HOUR_TO_SECONDS
|
||||
file = self._output_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, zone_name, 'Zone or ZoneList or Space or SpaceList Name')
|
||||
self._write_to_idf_format(file, schedule_name, 'Schedule Name')
|
||||
self._write_to_idf_format(file, 'AirChanges/Hour', 'Design Flow Rate Calculation Method')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Design Flow Rate')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Flow Rate per Floor Area')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Flow Rate per Person')
|
||||
self._write_to_idf_format(file, air_change, 'Air Changes per Hour')
|
||||
self._write_to_idf_format(file, 'Natural', 'Ventilation Type')
|
||||
self._write_to_idf_format(file, 0, 'Fan Pressure Rise')
|
||||
self._write_to_idf_format(file, 1, 'Fan Total Efficiency')
|
||||
self._write_to_idf_format(file, 1, 'Constant Term Coefficient')
|
||||
self._write_to_idf_format(file, 0, 'Temperature Term Coefficient')
|
||||
self._write_to_idf_format(file, 0, 'Velocity Term Coefficient')
|
||||
self._write_to_idf_format(file, 0, 'Velocity Squared Term Coefficient')
|
||||
self._write_to_idf_format(file, -100, 'Minimum Indoor Temperature')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Minimum Indoor Temperature Schedule Name')
|
||||
self._write_to_idf_format(file, 100, 'Maximum Indoor Temperature')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Maximum Indoor Temperature Schedule Name')
|
||||
self._write_to_idf_format(file, -100, 'Delta Temperature')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Delta Temperature Schedule Name')
|
||||
self._write_to_idf_format(file, -100, 'Minimum Outdoor Temperature')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Minimum Outdoor Temperature Schedule Name')
|
||||
self._write_to_idf_format(file, 100, 'Maximum Outdoor Temperature')
|
||||
self._write_to_idf_format(file, idf_cte.EMPTY, 'Maximum Outdoor Temperature Schedule Name')
|
||||
self._write_to_idf_format(file, 40, 'Maximum Wind Speed', ';')
|
||||
|
||||
def _merge_files(self):
|
||||
self._output_schedules.flush()
|
||||
with open(self._output_schedules_path, 'r') as file:
|
||||
@ -517,6 +577,15 @@ class CercIdf:
|
||||
with open(self._output_appliances_path, 'r') as file:
|
||||
lines = file.readlines()
|
||||
self._idf_file.writelines(lines)
|
||||
# todo: this should be move down instead it's here to simplify validation
|
||||
self._output_infiltration.flush()
|
||||
with open(self._output_infiltration_path, 'r') as file:
|
||||
lines = file.readlines()
|
||||
self._idf_file.writelines(lines)
|
||||
self._output_ventilation.flush()
|
||||
with open(self._output_ventilation_path, 'r') as file:
|
||||
lines = file.readlines()
|
||||
self._idf_file.writelines(lines)
|
||||
self._output_surfaces.flush()
|
||||
with open(self._output_surfaces_path, 'r') as file:
|
||||
lines = file.readlines()
|
||||
@ -548,14 +617,18 @@ class CercIdf:
|
||||
self._add_idf_schedules(usage, 'Ventilation', self._create_ventilation_schedules(thermal_zone))
|
||||
self._add_idf_schedules(usage, 'Occupancy', thermal_zone.occupancy.occupancy_schedules)
|
||||
self._add_idf_schedules(usage, 'HVAC AVAIL', thermal_zone.thermal_control.hvac_availability_schedules)
|
||||
self._add_idf_schedules(usage, 'Heating thermostat', thermal_zone.thermal_control.heating_set_point_schedules)
|
||||
self._add_idf_schedules(usage, 'Cooling thermostat', thermal_zone.thermal_control.cooling_set_point_schedules)
|
||||
self._add_idf_schedules(usage, 'Heating thermostat',
|
||||
thermal_zone.thermal_control.heating_set_point_schedules)
|
||||
self._add_idf_schedules(usage, 'Cooling thermostat',
|
||||
thermal_zone.thermal_control.cooling_set_point_schedules)
|
||||
self._add_idf_schedules(usage, 'Lighting', thermal_zone.lighting.schedules)
|
||||
self._add_idf_schedules(usage, 'Appliance', thermal_zone.appliances.schedules)
|
||||
self._add_idf_schedules(usage, 'DHW_prof', thermal_zone.domestic_hot_water.schedules)
|
||||
self._add_idf_schedules(usage, 'DHW_temp', self._create_constant_value_schedules(service_temperature, 24))
|
||||
self._add_idf_schedules(usage, 'Activity Level', self._create_constant_value_schedules(total_heat, 24))
|
||||
self._add_file_schedules(usage, 'cold_temp', self._create_constant_value_schedules(building.cold_water_temperature[cte.HOUR], 24))
|
||||
self._add_file_schedules(usage, 'cold_temp',
|
||||
self._create_constant_value_schedules(building.cold_water_temperature[cte.HOUR],
|
||||
24))
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
self._add_materials(thermal_boundary)
|
||||
self._add_constructions(thermal_boundary)
|
||||
@ -566,8 +639,11 @@ class CercIdf:
|
||||
self._add_occupancy(thermal_zone, building.name)
|
||||
self._add_lighting(thermal_zone, building.name)
|
||||
self._add_appliances(thermal_zone, building.name)
|
||||
self._add_infiltration(thermal_zone, building.name)
|
||||
self._add_ventilation(thermal_zone, building.name)
|
||||
if is_target:
|
||||
self._add_surfaces(building, building.name)
|
||||
|
||||
self._create_output_control_lighting() # Add lighting control to the lighting
|
||||
# Merge files
|
||||
self._merge_files()
|
||||
|
@ -12,6 +12,10 @@ GLOBAL_GEOMETRY_RULES = '\nGlobalGeometryRules,\n'
|
||||
PEOPLE = '\nPEOPLE,\n'
|
||||
LIGHTS = '\nLIGHTS,\n'
|
||||
APPLIANCES = '\nOTHEREQUIPMENT,\n'
|
||||
OUTPUT_CONTROL = '\nOutputControl:IlluminanceMap:Style,\n'
|
||||
INFILTRATION = '\nZONEINFILTRATION:DESIGNFLOWRATE,\n'
|
||||
VENTILATION = '\nZONEVENTILATION:DESIGNFLOWRATE,\n'
|
||||
|
||||
|
||||
AUTOCALCULATE = 'autocalculate'
|
||||
ROUGHNESS = 'MediumRough'
|
||||
|
@ -138,9 +138,9 @@ class TestExports(TestCase):
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
|
||||
self.assertIsNotNone(city, 'city is none')
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
#EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
# EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
WeatherFactory('epw', city).enrich()
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user