diff --git a/city_model_structure/building.py b/city_model_structure/building.py index 97f643d1..43090b1d 100644 --- a/city_model_structure/building.py +++ b/city_model_structure/building.py @@ -397,8 +397,8 @@ class Building(CityObject): if self.internal_zones is None: return False for internal_zone in self.internal_zones: - if internal_zone.usage_zones is not None: - for usage_zone in internal_zone.usage_zones: + if internal_zone.usages is not None: + for usage_zone in internal_zone.usages: if usage_zone.thermal_control is not None: return True return False diff --git a/city_model_structure/building_demand/internal_zone.py b/city_model_structure/building_demand/internal_zone.py index 6c1a536e..ddbb3b8c 100644 --- a/city_model_structure/building_demand/internal_zone.py +++ b/city_model_structure/building_demand/internal_zone.py @@ -24,7 +24,7 @@ class InternalZone: self._volume = None self._area = area self._thermal_zones = None - self._usage_zones = None + self._usages = None self._hvac_system = None @property @@ -75,20 +75,20 @@ class InternalZone: return self._area @property - def usage_zones(self) -> [Usage]: + def usages(self) -> [Usage]: """ Get internal zone usage zones :return: [UsageZone] """ - return self._usage_zones + return self._usages - @usage_zones.setter - def usage_zones(self, value): + @usages.setter + def usages(self, value): """ Set internal zone usage zones :param value: [UsageZone] """ - self._usage_zones = value + self._usages = value @property def hvac_system(self) -> Union[None, HvacSystem]: diff --git a/city_model_structure/building_demand/thermal_zone.py b/city_model_structure/building_demand/thermal_zone.py index 1e66402e..c09b8acf 100644 --- a/city_model_structure/building_demand/thermal_zone.py +++ b/city_model_structure/building_demand/thermal_zone.py @@ -58,14 +58,14 @@ class ThermalZone: def usage_zones(self): # example 70-office_30-residential if self._usage_from_parent: - self._usages = copy.deepcopy(self._parent_internal_zone.usage_zones) + self._usages = copy.deepcopy(self._parent_internal_zone.usages) else: values = self._usage.split('_') usages = [] for value in values: usages.append(value.split('-')) self._usages = [] - for parent_usage in self._parent_internal_zone.usage_zones: + for parent_usage in self._parent_internal_zone.usages: for value in usages: if parent_usage.usage == value[1]: new_usage = copy.deepcopy(parent_usage) @@ -230,11 +230,11 @@ class ThermalZone: :return: None or str """ if self._usage_from_parent: - if self._parent_internal_zone.usage_zones is None: + if self._parent_internal_zone.usages is None: return None self._usage = '' - for usage_zone in self._parent_internal_zone.usage_zones: - self._usage += str(round(usage_zone.percentage * 100)) + '-' + usage_zone.usage + '_' + for usage_zone in self._parent_internal_zone.usages: + self._usage += str(round(usage_zone.percentage * 100)) + '-' + usage_zone.name + '_' self._usage = self._usage[:-1] return self._usage diff --git a/exports/building_energy/energy_ade.py b/exports/building_energy/energy_ade.py index 9b9d1e6e..1ccd8d2a 100644 --- a/exports/building_energy/energy_ade.py +++ b/exports/building_energy/energy_ade.py @@ -169,7 +169,7 @@ class EnergyAde: def _building_geometry(self, building, building_dic, city): building_dic['bldg:Building']['bldg:function'] = building.function - building_dic['bldg:Building']['bldg:usage'] = ', '.join([u.name for u in building.usage_zones]) + building_dic['bldg:Building']['bldg:usage'] = ', '.join([u.name for u in building.usages]) building_dic['bldg:Building']['bldg:yearOfConstruction'] = building.year_of_construction building_dic['bldg:Building']['bldg:roofType'] = building.roof_type building_dic['bldg:Building']['bldg:measuredHeight'] = { @@ -266,7 +266,7 @@ class EnergyAde: thermal_zones = [] for index, thermal_zone in enumerate(building.thermal_zones): usage_zones = [] - for usage_zone in thermal_zone.usage_zones: + for usage_zone in thermal_zone.usages: usage_zones.append({'@xlink:href': f'#GML_{usage_zone.id}'}) thermal_zone_dic = { 'energy:ThermalZone': { diff --git a/exports/building_energy/idf.py b/exports/building_energy/idf.py index 57cad3c1..43fa23d0 100644 --- a/exports/building_energy/idf.py +++ b/exports/building_energy/idf.py @@ -207,9 +207,9 @@ class Idf: _schedule.values = _infiltration_values _infiltration_schedules.append(_schedule) for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]: - if schedule.Name == f'Infiltration schedules {thermal_zone.name}': + if schedule.Name == f'Infiltration schedules {thermal_zone.usage}': return - return self._add_standard_compact_hourly_schedule(thermal_zone.name, 'Infiltration', _infiltration_schedules) + return self._add_standard_compact_hourly_schedule(thermal_zone.usage, 'Infiltration', _infiltration_schedules) def _add_people_activity_level_schedules(self, thermal_zone): _occ = thermal_zone.occupancy @@ -219,9 +219,9 @@ class Idf: _total_heat = (_occ.sensible_convective_internal_gain + _occ.sensible_radiative_internal_gain + _occ.latent_internal_gain) / _occ.occupancy_density for schedule in self._idf.idfobjects[self._COMPACT_SCHEDULE]: - if schedule.Name == f'Activity Level schedules {thermal_zone.name}': + if schedule.Name == f'Activity Level schedules {thermal_zone.usage}': return - _kwargs = {'Name': f'Activity Level schedules {thermal_zone.name}', + _kwargs = {'Name': f'Activity Level schedules {thermal_zone.usage}', 'Schedule_Type_Limits_Name': self.idf_type_limits[cte.ANY_NUMBER], 'Field_1': 'Through: 12/31', 'Field_2': 'For AllDays', @@ -300,15 +300,15 @@ class Idf: self._add_heating_system(thermal_zone, name) def _add_thermostat(self, thermal_zone): - thermostat_name = f'Thermostat {thermal_zone.name}' + thermostat_name = f'Thermostat {thermal_zone.usage}' for thermostat in self._idf.idfobjects[self._THERMOSTAT]: if thermostat.Name == thermostat_name: return thermostat # todo: change schedules to schedule name and create schedules using the add_schedule function return self._idf.newidfobject(self._THERMOSTAT, Name=thermostat_name, - Heating_Setpoint_Schedule_Name=f'Heating thermostat schedules {thermal_zone.name}', - Cooling_Setpoint_Schedule_Name=f'Cooling thermostat schedules {thermal_zone.name}') + Heating_Setpoint_Schedule_Name=f'Heating thermostat schedules {thermal_zone.usage}', + Cooling_Setpoint_Schedule_Name=f'Cooling thermostat schedules {thermal_zone.usage}') def _add_heating_system(self, thermal_zone, zone_name): for air_system in self._idf.idfobjects[self._IDEAL_LOAD_AIR_SYSTEM]: @@ -317,9 +317,9 @@ class Idf: thermostat = self._add_thermostat(thermal_zone) self._idf.newidfobject(self._IDEAL_LOAD_AIR_SYSTEM, Zone_Name=zone_name, - System_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.name}', - Heating_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.name}', - Cooling_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.name}', + System_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage}', + Heating_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage}', + Cooling_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage}', Template_Thermostat_Name=thermostat.Name) def _add_occupancy(self, thermal_zone, zone_name): @@ -330,11 +330,11 @@ class Idf: self._idf.newidfobject(self._PEOPLE, Name=f'{zone_name}_occupancy', Zone_or_ZoneList_Name=zone_name, - Number_of_People_Schedule_Name=f'Occupancy schedules {thermal_zone.name}', + Number_of_People_Schedule_Name=f'Occupancy schedules {thermal_zone.usage}', Number_of_People_Calculation_Method="People", Number_of_People=number_of_people, Fraction_Radiant=fraction_radiant, - Activity_Level_Schedule_Name=f'Activity Level schedules {thermal_zone.name}' + Activity_Level_Schedule_Name=f'Activity Level schedules {thermal_zone.usage}' ) def _add_infiltration(self, thermal_zone, zone_name): @@ -344,7 +344,7 @@ class Idf: self._idf.newidfobject(self._INFILTRATION, Name=f'{zone_name}_infiltration', Zone_or_ZoneList_Name=zone_name, - Schedule_Name=f'Infiltration schedules {thermal_zone.name}', + Schedule_Name=f'Infiltration schedules {thermal_zone.usage}', Design_Flow_Rate_Calculation_Method='AirChanges/Hour', Air_Changes_per_Hour=thermal_zone.mechanical_air_change ) @@ -387,7 +387,7 @@ class Idf: self._add_vegetation_material(thermal_boundary.parent_surface.vegetation) for thermal_opening in thermal_boundary.thermal_openings: self._add_window_construction_and_material(thermal_opening) - usage = thermal_zone.name + usage = thermal_zone.usage if building.name in self._target_buildings or building.name in self._adjacent_buildings: self._add_infiltration_schedules(thermal_zone) self._add_schedules(usage, 'Occupancy', thermal_zone.occupancy.occupancy_schedules) @@ -449,7 +449,7 @@ class Idf: if surface.Type == self.idf_surfaces[boundary.surface.type]: surface.Construction_Name = boundary.construction_name break - for usage_zone in thermal_zone.usage_zones: + for usage_zone in thermal_zone.usages: surface.Zone_Name = usage_zone.id break break diff --git a/exports/building_energy/insel/insel_monthly_energy_balance.py b/exports/building_energy/insel/insel_monthly_energy_balance.py index 55f08443..262c2b4d 100644 --- a/exports/building_energy/insel/insel_monthly_energy_balance.py +++ b/exports/building_energy/insel/insel_monthly_energy_balance.py @@ -77,9 +77,9 @@ class InselMonthlyEnergyBalance(Insel): parameters.append('1 % BP(9) Usage type (0=standard, 1=IWU)') # ZONES AND SURFACES - parameters.append(f'{len(internal_zone.usage_zones)} % BP(10) Number of zones') + parameters.append(f'{len(internal_zone.usages)} % BP(10) Number of zones') - for i, usage_zone in enumerate(internal_zone.usage_zones): + for i, usage_zone in enumerate(internal_zone.usages): percentage_usage = usage_zone.percentage parameters.append(f'{float(internal_zone.area) * percentage_usage} % BP(11) #1 Area of zone {i + 1} (m2)') total_internal_gain = 0 diff --git a/helpers/monthly_to_hourly_demand.py b/helpers/monthly_to_hourly_demand.py index bc7d11d4..1dfeb5ad 100644 --- a/helpers/monthly_to_hourly_demand.py +++ b/helpers/monthly_to_hourly_demand.py @@ -29,7 +29,7 @@ class MonthlyToHourlyDemand: # todo: this method and the insel model have to be reviewed for more than one thermal zone external_temp = self._building.external_temperature[cte.HOUR] # todo: review index depending on how the schedules are defined, either 8760 or 24 hours - for usage_zone in self._building.usage_zones: + for usage_zone in self._building.usages: temp_set = float(usage_zone.heating_setpoint)-3 temp_back = float(usage_zone.heating_setback)-3 # todo: if these are data frames, then they should be called as (Occupancy should be in low case): @@ -90,7 +90,7 @@ class MonthlyToHourlyDemand: # todo: this method and the insel model have to be reviewed for more than one thermal zone external_temp = self._building.external_temperature[cte.HOUR] # todo: review index depending on how the schedules are defined, either 8760 or 24 hours - for usage_zone in self._building.usage_zones: + for usage_zone in self._building.usages: temp_set = float(usage_zone.cooling_setpoint) temp_back = 100 occupancy = Occupant().get_complete_year_schedule(usage_zone.schedules['Occupancy']) diff --git a/imports/construction/data_classes/building_achetype.py b/imports/construction/data_classes/building_achetype.py deleted file mode 100644 index 708549b5..00000000 --- a/imports/construction/data_classes/building_achetype.py +++ /dev/null @@ -1,98 +0,0 @@ -""" -BuildingArchetype stores construction information by building archetypes -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -from typing import List -from imports.construction.data_classes.thermal_boundary_archetype import ThermalBoundaryArchetype - - -class BuildingArchetype: - """ - BuildingArchetype class - """ - def __init__(self, archetype_keys, average_storey_height, storeys_above_ground, effective_thermal_capacity, - additional_thermal_bridge_u_value, indirectly_heated_area_ratio, infiltration_rate_system_off, - infiltration_rate_system_on, thermal_boundary_archetypes): - self._archetype_keys = archetype_keys - self._average_storey_height = average_storey_height - self._storeys_above_ground = storeys_above_ground - self._effective_thermal_capacity = effective_thermal_capacity - self._additional_thermal_bridge_u_value = additional_thermal_bridge_u_value - self._indirectly_heated_area_ratio = indirectly_heated_area_ratio - self._infiltration_rate_system_off = infiltration_rate_system_off - self._infiltration_rate_system_on = infiltration_rate_system_on - self._thermal_boundary_archetypes = thermal_boundary_archetypes - - @property - def archetype_keys(self) -> {}: - """ - Get keys that define the archetype - :return: dictionary - """ - return self._archetype_keys - - @property - def average_storey_height(self): - """ - Get archetype's building storey height in meters - :return: float - """ - return self._average_storey_height - - @property - def storeys_above_ground(self): - """ - Get archetype's building storey height in meters - :return: float - """ - return self._storeys_above_ground - - @property - def effective_thermal_capacity(self): - """ - Get archetype's effective thermal capacity in J/m2K - :return: float - """ - return self._effective_thermal_capacity - - @property - def additional_thermal_bridge_u_value(self): - """ - Get archetype's additional U value due to thermal bridges per area of shell in W/m2K - :return: float - """ - return self._additional_thermal_bridge_u_value - - @property - def indirectly_heated_area_ratio(self): - """ - Get archetype's indirectly heated area ratio - :return: float - """ - return self._indirectly_heated_area_ratio - - @property - def infiltration_rate_system_off(self): - """ - Get archetype's infiltration rate when conditioning systems OFF in air changes per hour (ACH) - :return: float - """ - return self._infiltration_rate_system_off - - @property - def infiltration_rate_system_on(self): - """ - Get archetype's infiltration rate when conditioning systems ON in air changes per hour (ACH) - :return: float - """ - return self._infiltration_rate_system_on - - @property - def thermal_boundary_archetypes(self) -> List[ThermalBoundaryArchetype]: - """ - Get thermal boundary archetypes associated to the building archetype - :return: list of boundary archetypes - """ - return self._thermal_boundary_archetypes diff --git a/imports/construction/data_classes/layer_archetype.py b/imports/construction/data_classes/layer_archetype.py deleted file mode 100644 index ece0efc5..00000000 --- a/imports/construction/data_classes/layer_archetype.py +++ /dev/null @@ -1,104 +0,0 @@ -""" -LayerArchetype stores layer and materials information, complementing the BuildingArchetype class -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - - -class LayerArchetype: - """ - LayerArchetype class - """ - def __init__(self, name, solar_absorptance, thermal_absorptance, visible_absorptance, thickness=None, - conductivity=None, specific_heat=None, density=None, no_mass=False, thermal_resistance=None): - self._thickness = thickness - self._conductivity = conductivity - self._specific_heat = specific_heat - self._density = density - self._solar_absorptance = solar_absorptance - self._thermal_absorptance = thermal_absorptance - self._visible_absorptance = visible_absorptance - self._no_mass = no_mass - self._name = name - self._thermal_resistance = thermal_resistance - - @property - def thickness(self): - """ - Get thickness in meters - :return: float - """ - return self._thickness - - @property - def conductivity(self): - """ - Get conductivity in W/mK - :return: float - """ - return self._conductivity - - @property - def specific_heat(self): - """ - Get specific heat in J/kgK - :return: float - """ - return self._specific_heat - - @property - def density(self): - """ - Get density in kg/m3 - :return: float - """ - return self._density - - @property - def solar_absorptance(self): - """ - Get solar absorptance - :return: float - """ - return self._solar_absorptance - - @property - def thermal_absorptance(self): - """ - Get thermal absorptance - :return: float - """ - return self._thermal_absorptance - - @property - def visible_absorptance(self): - """ - Get visible absorptance - :return: float - """ - return self._visible_absorptance - - @property - def no_mass(self) -> bool: - """ - Get no mass flag - :return: Boolean - """ - return self._no_mass - - @property - def name(self): - """ - Get name - :return: str - """ - return self._name - - @property - def thermal_resistance(self): - """ - Get thermal resistance in m2K/W - :return: float - """ - return self._thermal_resistance diff --git a/imports/construction/data_classes/thermal_boundary_archetype.py b/imports/construction/data_classes/thermal_boundary_archetype.py deleted file mode 100644 index 36ed66bd..00000000 --- a/imports/construction/data_classes/thermal_boundary_archetype.py +++ /dev/null @@ -1,137 +0,0 @@ -""" -ThermalBoundaryArchetype stores thermal boundaries information, complementing the BuildingArchetype class -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -from typing import List - -from imports.construction.data_classes.layer_archetype import LayerArchetype -from imports.construction.data_classes.thermal_opening_archetype import ThermalOpeningArchetype - - -class ThermalBoundaryArchetype: - """ - ThermalBoundaryArchetype class - """ - def __init__(self, boundary_type, window_ratio, construction_name, layers, thermal_opening, - outside_solar_absorptance=None, outside_thermal_absorptance=None, outside_visible_absorptance=None, - overall_u_value=None, shortwave_reflectance=None, inside_emissivity=None, alpha_coefficient=None, - radiative_coefficient=None): - self._boundary_type = boundary_type - self._outside_solar_absorptance = outside_solar_absorptance - self._outside_thermal_absorptance = outside_thermal_absorptance - self._outside_visible_absorptance = outside_visible_absorptance - self._window_ratio = window_ratio - self._construction_name = construction_name - self._overall_u_value = overall_u_value - self._layers = layers - self._thermal_opening_archetype = thermal_opening - self._shortwave_reflectance = shortwave_reflectance - self._inside_emissivity = inside_emissivity - self._alpha_coefficient = alpha_coefficient - self._radiative_coefficient = radiative_coefficient - - @property - def boundary_type(self): - """ - Get type - :return: str - """ - return self._boundary_type - - @property - def outside_solar_absorptance(self): - """ - Get outside solar absorptance - :return: float - """ - return self._outside_solar_absorptance - - @property - def outside_thermal_absorptance(self): - """ - Get outside thermal absorptance - :return: float - """ - return self._outside_thermal_absorptance - - @property - def outside_visible_absorptance(self): - """ - Get outside visible absorptance - :return: float - """ - return self._outside_visible_absorptance - - @property - def window_ratio(self): - """ - Get window ratio - :return: float - """ - return self._window_ratio - - @property - def construction_name(self): - """ - Get construction name - :return: str - """ - return self._construction_name - - @property - def layers(self) -> List[LayerArchetype]: - """ - Get layers - :return: [NrelLayerArchetype] - """ - return self._layers - - @property - def thermal_opening_archetype(self) -> ThermalOpeningArchetype: - """ - Get thermal opening archetype - :return: ThermalOpeningArchetype - """ - return self._thermal_opening_archetype - - @property - def overall_u_value(self): - """ - Get overall U-value in W/m2K - :return: float - """ - return self._overall_u_value - - @property - def shortwave_reflectance(self): - """ - Get shortwave reflectance - :return: float - """ - return self._shortwave_reflectance - - @property - def inside_emissivity(self): - """ - Get emissivity inside - :return: float - """ - return self._inside_emissivity - - @property - def alpha_coefficient(self): - """ - Get alpha coefficient - :return: float - """ - return self._alpha_coefficient - - @property - def radiative_coefficient(self): - """ - Get radiative coefficient - :return: float - """ - return self._radiative_coefficient diff --git a/imports/construction/data_classes/thermal_opening_archetype.py b/imports/construction/data_classes/thermal_opening_archetype.py deleted file mode 100644 index bfa7a026..00000000 --- a/imports/construction/data_classes/thermal_opening_archetype.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -ThermalOpeningArchetype stores thermal openings information, complementing the BuildingArchetype class -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - - -class ThermalOpeningArchetype: - """ - ThermalOpeningArchetype class - """ - def __init__(self, conductivity=None, frame_ratio=None, g_value=None, thickness=None, - back_side_solar_transmittance_at_normal_incidence=None, - front_side_solar_transmittance_at_normal_incidence=None, overall_u_value=None, - openable_ratio=None, inside_emissivity=None, alpha_coefficient=None, radiative_coefficient=None, - construction_name=None): - self._conductivity = conductivity - self._frame_ratio = frame_ratio - self._g_value = g_value - self._thickness = thickness - self._back_side_solar_transmittance_at_normal_incidence = back_side_solar_transmittance_at_normal_incidence - self._front_side_solar_transmittance_at_normal_incidence = front_side_solar_transmittance_at_normal_incidence - self._overall_u_value = overall_u_value - self._openable_ratio = openable_ratio - self._inside_emissivity = inside_emissivity - self._alpha_coefficient = alpha_coefficient - self._radiative_coefficient = radiative_coefficient - self._construction_name = construction_name - - @property - def conductivity(self): - """ - Get conductivity in W/mK - :return: float - """ - return self._conductivity - - @property - def frame_ratio(self): - """ - Get frame ratio - :return: float - """ - return self._frame_ratio - - @property - def g_value(self): - """ - Get g-value, also called shgc - :return: float - """ - return self._g_value - - @property - def thickness(self): - """ - Get thickness in meters - :return: float - """ - return self._thickness - - @property - def back_side_solar_transmittance_at_normal_incidence(self): - """ - Get back side solar transmittance at normal incidence - :return: float - """ - return self._back_side_solar_transmittance_at_normal_incidence - - @property - def front_side_solar_transmittance_at_normal_incidence(self): - """ - Get front side solar transmittance at normal incidence - :return: float - """ - return self._front_side_solar_transmittance_at_normal_incidence - - @property - def overall_u_value(self): - """ - Get overall U-value in W/m2K - :return: float - """ - return self._overall_u_value - - @property - def openable_ratio(self): - """ - Get openable ratio - :return: float - """ - return self._openable_ratio - - @property - def inside_emissivity(self): - """ - Get emissivity inside - :return: float - """ - return self._inside_emissivity - - @property - def alpha_coefficient(self): - """ - Get alpha coefficient - :return: float - """ - return self._alpha_coefficient - - @property - def radiative_coefficient(self): - """ - Get radiative coefficient - :return: float - """ - return self._radiative_coefficient - - @property - def construction_name(self): - """ - Get thermal opening construction name - """ - return self._construction_name - - @construction_name.setter - def construction_name(self, value): - """ - Set thermal opening construction name - """ - self._construction_name = value diff --git a/imports/construction/helpers/storeys_generation.py b/imports/construction/helpers/storeys_generation.py index 19bad00e..4dbe7ab6 100644 --- a/imports/construction/helpers/storeys_generation.py +++ b/imports/construction/helpers/storeys_generation.py @@ -49,7 +49,7 @@ class StoreysGeneration: thermal_zones = [storey.thermal_zone] else: # internal thermal boundary -> two thermal zones - grad = np.rad2deg(thermal_boundary.inclination) + grad = np.rad2deg(thermal_boundary.parent_surface.inclination) if grad >= 170: thermal_zones = [storey.thermal_zone, storey.neighbours[0]] else: @@ -116,7 +116,7 @@ class StoreysGeneration: thermal_zones = [storey.thermal_zone] else: # internal thermal boundary -> two thermal zones - grad = np.rad2deg(thermal_boundary.inclination) + grad = np.rad2deg(thermal_boundary.parent_surface.inclination) if grad >= 170: thermal_zones = [storey.thermal_zone, storey.neighbours[0]] else: diff --git a/imports/construction/nrel_physics_interface.py b/imports/construction/nrel_physics_interface.py deleted file mode 100644 index 354b3176..00000000 --- a/imports/construction/nrel_physics_interface.py +++ /dev/null @@ -1,71 +0,0 @@ -""" -Nrel-based interface, it reads format defined within the CERC team based on NREL structure -and enriches the city with archetypes and materials -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from imports.construction.helpers.storeys_generation import StoreysGeneration - - -class NrelPhysicsInterface: - """ - NrelPhysicsInterface abstract class - """ - - # todo: verify windows - @staticmethod - def _calculate_view_factors(thermal_zone): - """ - Get thermal zone view factors matrix - :return: [[float]] - """ - total_area = 0 - for thermal_boundary in thermal_zone.thermal_boundaries: - total_area += thermal_boundary.opaque_area - for thermal_opening in thermal_boundary.thermal_openings: - total_area += thermal_opening.area - - view_factors_matrix = [] - for thermal_boundary_1 in thermal_zone.thermal_boundaries: - values = [] - for thermal_boundary_2 in thermal_zone.thermal_boundaries: - value = 0 - if thermal_boundary_1.id != thermal_boundary_2.id: - value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area) - values.append(value) - for thermal_boundary in thermal_zone.thermal_boundaries: - for thermal_opening in thermal_boundary.thermal_openings: - value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area) - values.append(value) - view_factors_matrix.append(values) - - for thermal_boundary_1 in thermal_zone.thermal_boundaries: - values = [] - for thermal_opening_1 in thermal_boundary_1.thermal_openings: - for thermal_boundary_2 in thermal_zone.thermal_boundaries: - value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area) - values.append(value) - for thermal_boundary in thermal_zone.thermal_boundaries: - for thermal_opening_2 in thermal_boundary.thermal_openings: - value = 0 - if thermal_opening_1.id != thermal_opening_2.id: - value = thermal_opening_2.area / (total_area - thermal_opening_1.area) - values.append(value) - view_factors_matrix.append(values) - thermal_zone.view_factors_matrix = view_factors_matrix - - @staticmethod - def _create_storeys(building, archetype, divide_in_storeys): - building.average_storey_height = archetype.average_storey_height - building.storeys_above_ground = 1 - thermal_zones = StoreysGeneration(building, building.internal_zones[0], - divide_in_storeys=divide_in_storeys).thermal_zones - building.internal_zones[0].thermal_zones = thermal_zones - - def enrich_buildings(self): - """ - Raise not implemented error - """ - raise NotImplementedError diff --git a/imports/construction/us_physics_parameters.py b/imports/construction/nrel_physics_parameters.py similarity index 74% rename from imports/construction/us_physics_parameters.py rename to imports/construction/nrel_physics_parameters.py index cee5840c..22df677f 100644 --- a/imports/construction/us_physics_parameters.py +++ b/imports/construction/nrel_physics_parameters.py @@ -1,5 +1,5 @@ """ -UsPhysicsParameters import the construction and material information for US +NrelPhysicsParameters import the construction and material information defined by NREL SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca @@ -7,23 +7,22 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord """ import sys -from imports.construction.nrel_physics_interface import NrelPhysicsInterface from catalog_factories.construction_catalog_factory import ConstructionCatalogFactory from city_model_structure.building_demand.layer import Layer from city_model_structure.building_demand.material import Material from imports.construction.helpers.construction_helper import ConstructionHelper +from imports.construction.helpers.storeys_generation import StoreysGeneration -class UsPhysicsParameters(NrelPhysicsInterface): +class NrelPhysicsParameters: """ - UsPhysicsParameters class + NrelPhysicsParameters class """ def __init__(self, city, base_path, divide_in_storeys=False): self._city = city self._path = base_path self._divide_in_storeys = divide_in_storeys self._climate_zone = ConstructionHelper.city_to_nrel_climate_zone(city.name) - super().__init__() def enrich_buildings(self): """ @@ -136,3 +135,53 @@ class UsPhysicsParameters(NrelPhysicsInterface): thermal_opening.frame_ratio = window_archetype.frame_ratio thermal_opening.g_value = window_archetype.g_value thermal_opening.overall_u_value = window_archetype.overall_u_value + + # todo: verify windows + @staticmethod + def _calculate_view_factors(thermal_zone): + """ + Get thermal zone view factors matrix + :return: [[float]] + """ + total_area = 0 + for thermal_boundary in thermal_zone.thermal_boundaries: + total_area += thermal_boundary.opaque_area + for thermal_opening in thermal_boundary.thermal_openings: + total_area += thermal_opening.area + + view_factors_matrix = [] + for thermal_boundary_1 in thermal_zone.thermal_boundaries: + values = [] + for thermal_boundary_2 in thermal_zone.thermal_boundaries: + value = 0 + if thermal_boundary_1.id != thermal_boundary_2.id: + value = thermal_boundary_2.opaque_area / (total_area - thermal_boundary_1.opaque_area) + values.append(value) + for thermal_boundary in thermal_zone.thermal_boundaries: + for thermal_opening in thermal_boundary.thermal_openings: + value = thermal_opening.area / (total_area - thermal_boundary_1.opaque_area) + values.append(value) + view_factors_matrix.append(values) + + for thermal_boundary_1 in thermal_zone.thermal_boundaries: + values = [] + for thermal_opening_1 in thermal_boundary_1.thermal_openings: + for thermal_boundary_2 in thermal_zone.thermal_boundaries: + value = thermal_boundary_2.opaque_area / (total_area - thermal_opening_1.area) + values.append(value) + for thermal_boundary in thermal_zone.thermal_boundaries: + for thermal_opening_2 in thermal_boundary.thermal_openings: + value = 0 + if thermal_opening_1.id != thermal_opening_2.id: + value = thermal_opening_2.area / (total_area - thermal_opening_1.area) + values.append(value) + view_factors_matrix.append(values) + thermal_zone.view_factors_matrix = view_factors_matrix + + @staticmethod + def _create_storeys(building, archetype, divide_in_storeys): + building.average_storey_height = archetype.average_storey_height + building.storeys_above_ground = 1 + thermal_zones = StoreysGeneration(building, building.internal_zones[0], + divide_in_storeys=divide_in_storeys).thermal_zones + building.internal_zones[0].thermal_zones = thermal_zones diff --git a/imports/construction_factory.py b/imports/construction_factory.py index 7f136ed0..acf35988 100644 --- a/imports/construction_factory.py +++ b/imports/construction_factory.py @@ -5,7 +5,7 @@ Copyright © 2022 Concordia CERC group Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ from pathlib import Path -from imports.construction.us_physics_parameters import UsPhysicsParameters +from imports.construction.nrel_physics_parameters import NrelPhysicsParameters class ConstructionFactory: @@ -23,7 +23,7 @@ class ConstructionFactory: """ Enrich the city by using NREL information """ - UsPhysicsParameters(self._city, self._base_path).enrich_buildings() + NrelPhysicsParameters(self._city, self._base_path).enrich_buildings() self._city.level_of_detail.construction = 2 def enrich(self): @@ -38,4 +38,4 @@ class ConstructionFactory: Enrich the city given to the class using the class given handler :return: None """ - UsPhysicsParameters(self._city, self._base_path).enrich_buildings() \ No newline at end of file + NrelPhysicsParameters(self._city, self._base_path).enrich_buildings() diff --git a/imports/usage/ca_usage_parameters.py b/imports/usage/ca_usage_parameters.py deleted file mode 100644 index cc5c4f41..00000000 --- a/imports/usage/ca_usage_parameters.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -CaUsageParameters model the usage properties -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 sys - -from imports.geometry.helpers.geometry_helper import GeometryHelper -from imports.usage.hft_usage_interface import HftUsageInterface -from imports.usage.helpers.usage_helper import UsageHelper - - -class HftUsageParameters(HftUsageInterface): - """ - CaUsageParameters class - """ - def __init__(self, city, base_path): - super().__init__(base_path, 'ca_archetypes_reduced.xml') - self._city = city - - def enrich_buildings(self): - """ - Returns the city with the usage parameters assigned to the buildings - :return: - """ - city = self._city - for building in city.buildings: - usage = GeometryHelper().libs_usage_from_libs_function(building.function) - try: - archetype = self._search_archetype(usage) - except KeyError: - sys.stderr.write(f'Building {building.name} has unknown archetype for building function:' - f' {building.function}, that assigns building usage as ' - f'{GeometryHelper().libs_usage_from_libs_function(building.function)}\n') - return - - for internal_zone in building.internal_zones: - usage_zone = self._assign_values(building.function, archetype) - usage_zone.percentage = 1 - internal_zone.usage_zones = [usage_zone] diff --git a/imports/usage/comnet_usage_parameters.py b/imports/usage/comnet_usage_parameters.py index c1cf1117..b2265fe1 100644 --- a/imports/usage/comnet_usage_parameters.py +++ b/imports/usage/comnet_usage_parameters.py @@ -15,7 +15,7 @@ from helpers.configuration_helper import ConfigurationHelper as ch from imports.geometry.helpers.geometry_helper import GeometryHelper from imports.usage.helpers.usage_helper import UsageHelper from imports.usage.helpers.schedules_helper import SchedulesHelper -from city_model_structure.building_demand.usage_zone import UsageZone +from city_model_structure.building_demand.usage import Usage from city_model_structure.building_demand.lighting import Lighting from city_model_structure.building_demand.occupancy import Occupancy from city_model_structure.building_demand.appliances import Appliances @@ -74,7 +74,7 @@ class ComnetUsageParameters: @staticmethod def _parse_usage_type(comnet_usage, data, schedules_data): - _usage_zone = UsageZone() + _usage = Usage() # lighting _lighting = Lighting() @@ -105,7 +105,7 @@ class ComnetUsageParameters: * ch().comnet_occupancy_sensible_radiant _occupancy.latent_internal_gain = data['occupancy'][comnet_usage][2] - _usage_zone.mechanical_air_change = data['ventilation rate'][comnet_usage][0] + _usage.mechanical_air_change = data['ventilation rate'][comnet_usage][0] schedules_usage = UsageHelper.schedules_key(data['schedules_key'][comnet_usage][0]) @@ -158,9 +158,9 @@ class ComnetUsageParameters: _schedules.append(schedules[schedules_types['Receptacle']+pointer]) _appliances.schedules = _schedules - _usage_zone.occupancy = _occupancy - _usage_zone.lighting = _lighting - _usage_zone.appliances = _appliances + _usage.occupancy = _occupancy + _usage.lighting = _lighting + _usage.appliances = _appliances _control = ThermalControl() _schedules = [] @@ -175,9 +175,9 @@ class ComnetUsageParameters: for pointer in range(0, 3): _schedules.append(schedules[schedules_types['HVAC Avail']+pointer]) _control.hvac_availability_schedules = _schedules - _usage_zone.thermal_control = _control + _usage.thermal_control = _control - return _usage_zone + return _usage def _search_archetypes(self, libs_usage): for item in self._data['lighting']: @@ -213,13 +213,13 @@ class ComnetUsageParameters: if internal_zone.volume <= 0: raise Exception('Internal zone volume is zero, ACH cannot be calculated') volume_per_area = internal_zone.volume / internal_zone.area - usage_zone = UsageZone() - usage_zone.usage = usage + usage_zone = Usage() + usage_zone.name = usage self._assign_values_usage_zone(usage_zone, archetype_usage, volume_per_area) usage_zone.percentage = 1 self._calculate_reduced_values_from_extended_library(usage_zone, archetype_usage) - internal_zone.usage_zones = [usage_zone] + internal_zone.usages = [usage_zone] @staticmethod def _assign_values_usage_zone(usage_zone, archetype, volume_per_area): diff --git a/imports/usage/hft_usage_parameters.py b/imports/usage/hft_usage_parameters.py index afe7e300..3d869242 100644 --- a/imports/usage/hft_usage_parameters.py +++ b/imports/usage/hft_usage_parameters.py @@ -39,4 +39,4 @@ class HftUsageParameters(HftUsageInterface): libs_usage = GeometryHelper().libs_usage_from_libs_function(building.function) usage_zone = self._assign_values(UsageHelper().hft_from_libs_usage(libs_usage), archetype) usage_zone.percentage = 1 - internal_zone.usage_zones = [usage_zone] + internal_zone.usages = [usage_zone] diff --git a/imports/usage/nrcan_usage_parameters.py b/imports/usage/nrcan_usage_parameters.py deleted file mode 100644 index 19034827..00000000 --- a/imports/usage/nrcan_usage_parameters.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -NrcanUsageParameters imports the usage information for Canada and feeds the central data model classes with it -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2022 Concordia CERC group -Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from catalog_factories.usage_catalog_factory import UsageCatalogFactory - -class NrcanUsageParameters: - """ - NrcanUsageParameters class - """ - @staticmethod - def _search_archetype(usage_name, year_of_construction, climate_zone): - nrcan_catalog = UsageCatalogFactory('nrcan').catalog - nrcan_archetypes = nrcan_catalog.entries('archetypes') - for building_archetype in nrcan_archetypes: - - return None - - @staticmethod - def _search_usage_in_archetype(archetype, usage_name): - usage_archetypes = archetype. - for usage_archetype in archetypes_archetypes: - if str(usage_name) == str(usage_archetype.type): - return usage_archetype - return None - - def _assign_values(self, usage, archetype): - for thermal_zone in thermal_zones: - thermal_zone.additional_thermal_bridge_u_value = archetype.extra_loses_due_to_thermal_bridges - - def enrich_buildings(self): - """ - Raise not implemented error - """ - raise NotImplementedError diff --git a/imports/usage_factory.py b/imports/usage_factory.py index 50d94915..3ec4e45d 100644 --- a/imports/usage_factory.py +++ b/imports/usage_factory.py @@ -27,14 +27,14 @@ class UsageFactory: Enrich the city with HFT usage library """ self._city.level_of_detail.usage = 2 - return HftUsageParameters(self._city, self._base_path).enrich_buildings() + HftUsageParameters(self._city, self._base_path).enrich_buildings() def _comnet(self): """ Enrich the city with COMNET usage library """ self._city.level_of_detail.usage = 2 - return ComnetUsageParameters(self._city, self._base_path).enrich_buildings() + ComnetUsageParameters(self._city, self._base_path).enrich_buildings() def enrich(self): """ diff --git a/unittests/test_construction_factory.py b/unittests/test_construction_factory.py index 075abf72..6ba75ee9 100644 --- a/unittests/test_construction_factory.py +++ b/unittests/test_construction_factory.py @@ -122,7 +122,7 @@ class TestConstructionFactory(TestCase): self.assertIsNone(thermal_zone.ordinate_number, 'thermal_zone ordinate number is not none') self.assertIsNotNone(thermal_zone.view_factors_matrix, 'thermal_zone view factors matrix is none') self.assertIsNotNone(thermal_zone.total_floor_area, 'thermal zone total_floor_area is none') - self.assertIsNone(thermal_zone.name, 'thermal_zone usage is not none') + self.assertIsNone(thermal_zone.usage, 'thermal_zone usage is not none') self.assertIsNone(thermal_zone.hours_day, 'thermal_zone hours a day is not none') self.assertIsNone(thermal_zone.days_year, 'thermal_zone days a year is not none') self.assertIsNone(thermal_zone.mechanical_air_change, 'thermal_zone mechanical air change is not none') diff --git a/unittests/test_enrichement.py b/unittests/test_enrichement.py index e1c7b7d7..1e7fc6d3 100644 --- a/unittests/test_enrichement.py +++ b/unittests/test_enrichement.py @@ -35,8 +35,8 @@ class TestGeometryFactory(TestCase): self._check_buildings(city) for building in city.buildings: for internal_zone in building.internal_zones: - self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined') - for usage_zone in internal_zone.usage_zones: + self.assertIsNot(len(internal_zone.usages), 0, 'no building usage_zones defined') + for usage_zone in internal_zone.usages: self.assertIsNotNone(usage_zone.id, 'usage id is none') for thermal_zone in internal_zone.thermal_zones: self._check_thermal_zone(thermal_zone) @@ -45,7 +45,7 @@ class TestGeometryFactory(TestCase): for building in city.buildings: self.assertIsNotNone(building.internal_zones, 'no internal zones created') for internal_zone in building.internal_zones: - self.assertIsNotNone(internal_zone.usage_zones, 'usage zones are not defined') + self.assertIsNotNone(internal_zone.usages, 'usage zones are not defined') self.assertIsNotNone(internal_zone.thermal_zones, 'thermal zones are not defined') self.assertIsNone(building.basement_heated, 'building basement_heated is not none') self.assertIsNone(building.attic_heated, 'building attic_heated is not none') @@ -55,7 +55,7 @@ class TestGeometryFactory(TestCase): def _check_thermal_zone(self, thermal_zone): self.assertIsNotNone(thermal_zone.id, 'thermal_zone id is none') - self.assertIsNotNone(thermal_zone.name, 'thermal_zone usage is not none') + self.assertIsNotNone(thermal_zone.usage, 'thermal_zone usage is not none') self.assertIsNotNone(thermal_zone.hours_day, 'thermal_zone hours a day is none') self.assertIsNotNone(thermal_zone.days_year, 'thermal_zone days a year is none') self.assertIsNotNone(thermal_zone.occupancy, 'thermal_zone occupancy is none') diff --git a/unittests/test_geometry_factory.py b/unittests/test_geometry_factory.py index 5da32682..e6e61355 100644 --- a/unittests/test_geometry_factory.py +++ b/unittests/test_geometry_factory.py @@ -59,7 +59,7 @@ class TestGeometryFactory(TestCase): self.assertIsNotNone(building.roofs, 'building roofs is none') self.assertIsNotNone(building.internal_zones, 'building internal zones is none') for internal_zone in building.internal_zones: - self.assertIsNone(internal_zone.usage_zones, 'usage zones are defined') + self.assertIsNone(internal_zone.usages, 'usage zones are defined') self.assertIsNone(internal_zone.thermal_zones, 'thermal zones are defined') self.assertIsNone(building.basement_heated, 'building basement_heated is not none') self.assertIsNone(building.attic_heated, 'building attic_heated is not none') diff --git a/unittests/test_insel_exports.py b/unittests/test_insel_exports.py index bc6b2776..ae5bf283 100644 --- a/unittests/test_insel_exports.py +++ b/unittests/test_insel_exports.py @@ -133,13 +133,13 @@ class TestExports(TestCase): if thermal_boundary.type is not cte.GROUND: self.assertIsNotNone(thermal_boundary.parent_surface.short_wave_reflectance) - for usage_zone in internal_zone.usage_zones: - self.assertIsNotNone(usage_zone.percentage, f'usage zone {usage_zone.usage} percentage is none') - self.assertIsNotNone(usage_zone.internal_gains, f'usage zone {usage_zone.usage} internal_gains is none') - self.assertIsNotNone(usage_zone.thermal_control, f'usage zone {usage_zone.usage} thermal_control is none') - self.assertIsNotNone(usage_zone.hours_day, f'usage zone {usage_zone.usage} hours_day is none') - self.assertIsNotNone(usage_zone.days_year, f'usage zone {usage_zone.usage} days_year is none') - self.assertIsNotNone(usage_zone.mechanical_air_change, f'usage zone {usage_zone.usage} ' + for usage_zone in internal_zone.usages: + self.assertIsNotNone(usage_zone.percentage, f'usage zone {usage_zone.name} percentage is none') + self.assertIsNotNone(usage_zone.internal_gains, f'usage zone {usage_zone.name} internal_gains is none') + self.assertIsNotNone(usage_zone.thermal_control, f'usage zone {usage_zone.name} thermal_control is none') + self.assertIsNotNone(usage_zone.hours_day, f'usage zone {usage_zone.name} hours_day is none') + self.assertIsNotNone(usage_zone.days_year, f'usage zone {usage_zone.name} days_year is none') + self.assertIsNotNone(usage_zone.mechanical_air_change, f'usage zone {usage_zone.name} ' f'mechanical_air_change is none') # export files try: diff --git a/unittests/test_usage_factory.py b/unittests/test_usage_factory.py index 1e4202ba..1a593493 100644 --- a/unittests/test_usage_factory.py +++ b/unittests/test_usage_factory.py @@ -51,7 +51,7 @@ class TestUsageFactory(TestCase): self.assertIsNotNone(building.walls, 'building walls is none') self.assertIsNotNone(building.roofs, 'building roofs is none') for internal_zone in building.internal_zones: - self.assertTrue(len(internal_zone.usage_zones) > 0, 'usage zones are not defined') + self.assertTrue(len(internal_zone.usages) > 0, 'usage zones are not defined') self.assertIsNone(internal_zone.thermal_zones, 'thermal zones are defined') self.assertIsNone(building.basement_heated, 'building basement_heated is not none') self.assertIsNone(building.attic_heated, 'building attic_heated is not none') @@ -91,8 +91,8 @@ class TestUsageFactory(TestCase): self._check_buildings(city) for building in city.buildings: for internal_zone in building.internal_zones: - self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined') - for usage_zone in internal_zone.usage_zones: + self.assertIsNot(len(internal_zone.usages), 0, 'no building usage_zones defined') + for usage_zone in internal_zone.usages: self._check_usage_zone(usage_zone) self.assertIsNotNone(usage_zone.mechanical_air_change, 'mechanical air change is none') self.assertIsNotNone(usage_zone.thermal_control.heating_set_point_schedules, @@ -139,8 +139,8 @@ class TestUsageFactory(TestCase): self._check_buildings(city) for building in city.buildings: for internal_zone in building.internal_zones: - self.assertIsNot(len(internal_zone.usage_zones), 0, 'no building usage_zones defined') - for usage_zone in internal_zone.usage_zones: + self.assertIsNot(len(internal_zone.usages), 0, 'no building usage_zones defined') + for usage_zone in internal_zone.usages: self._check_usage_zone(usage_zone) self.assertIsNone(usage_zone.mechanical_air_change, 'mechanical air change is not none') self.assertIsNotNone(usage_zone.thermal_control.heating_set_point_schedules,