diff --git a/README.md b/README.md index 7056270..afdf4fa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # peak_demands -This project includes model to calculate the fillowing yearly peak demands of a building: +This project includes model to calculate the following yearly peak demands of a building: - heating +- cooling diff --git a/loads_calculation.py b/loads_calculation.py new file mode 100644 index 0000000..0b8dbb7 --- /dev/null +++ b/loads_calculation.py @@ -0,0 +1,116 @@ +""" +Calculation of loads for peak heating and cooling +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +""" + + +import helpers.constants as cte + +AIR_DENSITY = 1.293 # kg/m3 +AIR_HEAT_CAPACITY = 1005.2 # J/kgK + + +class LoadsCalculation: + """ + LoadsCalculation class + """ + def __init__(self, building): + self._building = building + + @staticmethod + def _get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature, ground_temperature): + load_transmitted_opaque = 0 + load_transmitted_transparent = 0 + for thermal_boundary in thermal_zone.thermal_boundaries: + if thermal_boundary.type == cte.GROUND: + external_temperature = ground_temperature + elif thermal_boundary.type == cte.INTERIOR_WALL: + external_temperature = internal_temperature + else: + external_temperature = ambient_temperature + + load_transmitted_opaque += thermal_boundary.u_value * thermal_boundary.opaque_area \ + * (internal_temperature - external_temperature) + for thermal_opening in thermal_boundary.thermal_openings: + load_transmitted_transparent += thermal_opening.overall_u_value \ + * (internal_temperature - external_temperature) + load_transmitted_opaque += thermal_zone.additional_thermal_bridge_u_value * thermal_zone.footprint_area \ + * (internal_temperature - ambient_temperature) + + load_transmitted = load_transmitted_opaque + load_transmitted_transparent + return load_transmitted + + @staticmethod + def _get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature): + load_renovation_sensible = 0 + for usage in thermal_zone.usage_zones: + load_renovation_sensible += AIR_DENSITY * AIR_HEAT_CAPACITY * usage.mechanical_air_change \ + * thermal_zone.volume * cte.HOUR_TO_MINUTES * cte.MINUTES_TO_SECONDS \ + * (internal_temperature - ambient_temperature) + + load_infiltration_sensible = AIR_DENSITY * AIR_HEAT_CAPACITY * thermal_zone.infiltration_rate_system_off \ + * thermal_zone.volume * cte.HOUR_TO_MINUTES * cte.MINUTES_TO_SECONDS \ + * (internal_temperature - ambient_temperature) + + load_ventilation = load_renovation_sensible + load_infiltration_sensible + + return load_ventilation + + def get_heating_transmitted_load(self, ambient_temperature, ground_temperature): + heating_load_transmitted = 0 + for thermal_zone in self._building.thermal_zones: + internal_temperature = thermal_zone.thermal_control.mean_heating_set_point + heating_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature, + ground_temperature) + return heating_load_transmitted + + def get_cooling_transmitted_load(self, ambient_temperature, ground_temperature): + cooling_load_transmitted = 0 + for thermal_zone in self._building.thermal_zones: + internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point + cooling_load_transmitted += self._get_load_transmitted(thermal_zone, internal_temperature, ambient_temperature, + ground_temperature) + return cooling_load_transmitted + + def get_heating_ventilation_load_sensible(self, ambient_temperature): + heating_ventilation_load = 0 + for thermal_zone in self._building.thermal_zones: + internal_temperature = thermal_zone.thermal_control.mean_heating_set_point + heating_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature) + return heating_ventilation_load + + def get_cooling_ventilation_load_sensible(self, ambient_temperature): + cooling_ventilation_load = 0 + for thermal_zone in self._building.thermal_zones: + internal_temperature = thermal_zone.thermal_control.mean_cooling_set_point + cooling_ventilation_load += self._get_load_ventilation(thermal_zone, internal_temperature, ambient_temperature) + return cooling_ventilation_load + + def get_internal_load_sensible(self): + cooling_load_occupancy_sensible = 0 + cooling_load_lighting = 0 + cooling_load_equipment_sensible = 0 + for thermal_zone in self._building.thermal_zones: + cooling_load_occupancy_sensible += (thermal_zone.occupancy.sensible_convective_internal_gain + + thermal_zone.occupancy.sensible_radiative_internal_gain) \ + * thermal_zone.footprint_area + cooling_load_lighting += (thermal_zone.lighting.density * thermal_zone.lighting.convective_fraction + + thermal_zone.lighting.density * thermal_zone.lighting.radiative_fraction) \ + * thermal_zone.footprint_area + cooling_load_equipment_sensible += (thermal_zone.appliances.density * thermal_zone.appliances.convective_fraction + + thermal_zone.appliances.density * thermal_zone.appliances.radiative_fraction) \ + * thermal_zone.footprint_area + internal_load = cooling_load_occupancy_sensible + cooling_load_lighting + cooling_load_equipment_sensible + return internal_load + + def get_radiation_load(self, hour): + cooling_load_radiation = 0 + for thermal_zone in self._building.thermal_zones: + for thermal_boundary in thermal_zone.thermal_boundaries: + radiation = thermal_boundary.parent_surface.radiation[hour] + for thermal_opening in thermal_boundary.thermal_openings: + cooling_load_radiation += thermal_opening.area * (1 - thermal_opening.frame_ratio) * thermal_opening.g_value \ + * radiation + return cooling_load_radiation diff --git a/main.py b/main.py new file mode 100644 index 0000000..617fe5e --- /dev/null +++ b/main.py @@ -0,0 +1,87 @@ +""" +Peak loads calculation workflow +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +""" + +import glob +import os +import sys +from pathlib import Path + +import helpers.constants as cte +from imports.geometry_factory import GeometryFactory +from imports.construction_factory import ConstructionFactory +from imports.usage_factory import UsageFactory +from loads_calculation import LoadsCalculation + +try: + gml = '' + for argument_tuple in sys.argv[1:]: + print(argument_tuple) + argument = argument_tuple.split(' ') + option = argument[0] + value = argument[1] + if option == '-g': + gml = value + out_path = (Path(__file__).parent.parent / 'out_files') + files = glob.glob(f'{out_path}/*') + for file in files: + if file != '.gitignore': + os.remove(file) + + print('[simulation start]') + city = GeometryFactory('citygml', gml).city + print(f'city created from {gml}') + for building in city.buildings: + building.year_of_construction = 2006 + if building.function is None: + building.function = 'large office' + ConstructionFactory('nrel', city).enrich() + print('enrich constructions... done') + UsageFactory('comnet', city).enrich() + print('enrich usage... done') + + print('calculating:') + + weather_format = 'epw' + + for building in city.buildings: + ambient_temperature = building.external_temperature[cte.HOUR][[weather_format]] + ground_temperature = 0 + heating_ambient_temperature = 100 + cooling_ambient_temperature = -100 + heating_calculation_hour = -1 + cooling_calculation_hour = -1 + for hour, temperature in enumerate(ambient_temperature): + ground_temperature += temperature / 8760 + if temperature < heating_ambient_temperature: + heating_ambient_temperature = temperature + heating_calculation_hour = hour + if temperature > cooling_ambient_temperature: + cooling_ambient_temperature = temperature + cooling_calculation_hour = hour + + loads = LoadsCalculation(building) + heating_load_transmitted = loads.get_heating_transmitted_load(heating_ambient_temperature, ground_temperature) + heating_load_ventilation_sensible = loads.get_heating_ventilation_load_sensible(heating_ambient_temperature) + heating_load_ventilation_latent = 0 + heating_load = heating_load_transmitted + heating_load_ventilation_sensible + heating_load_ventilation_latent + + cooling_load_transmitted = loads.get_cooling_transmitted_load(cooling_ambient_temperature, ground_temperature) + cooling_load_renovation_sensible = loads.get_cooling_ventilation_load_sensible(cooling_ambient_temperature) + cooling_load_internal_gains_sensible = loads.get_internal_load_sensible() + cooling_load_radiation = loads.get_radiation_load(cooling_calculation_hour) + cooling_load_sensible = cooling_load_transmitted + cooling_load_renovation_sensible + cooling_load_radiation \ + + cooling_load_internal_gains_sensible + cooling_load_latent = 0 + cooling_load = cooling_load_sensible + cooling_load_latent + + print('[calculation end]') + +except Exception as ex: + print(ex) + print('error: ', ex) + print('[simulation abort]') +sys.stdout.flush()