diff --git a/hub/catalog_factories/construction/nrel_catalog.py b/hub/catalog_factories/construction/nrel_catalog.py index bf1374af..c9235cfe 100644 --- a/hub/catalog_factories/construction/nrel_catalog.py +++ b/hub/catalog_factories/construction/nrel_catalog.py @@ -40,7 +40,7 @@ class NrelCatalog(Catalog): _catalog_windows = [] windows = self._constructions['library']['windows']['window'] for window in windows: - frame_ratio = window['frame_ratio']['#text'] + frame_ratio = float(window['frame_ratio']['#text']) g_value = window['shgc'] overall_u_value = float(window['conductivity']['#text']) / float(window['thickness']['#text']) name = window['@name'] @@ -54,9 +54,9 @@ class NrelCatalog(Catalog): for material in materials: material_id = material['@id'] name = material['@name'] - solar_absorptance = material['solar_absorptance']['#text'] - thermal_absorptance = material['thermal_absorptance']['#text'] - visible_absorptance = material['visible_absorptance']['#text'] + solar_absorptance = float(material['solar_absorptance']['#text']) + thermal_absorptance = float(material['thermal_absorptance']['#text']) + visible_absorptance = float(material['visible_absorptance']['#text']) no_mass = False thermal_resistance = None, conductivity = None, @@ -64,11 +64,11 @@ class NrelCatalog(Catalog): specific_heat = None if 'no_mass' in material and material['no_mass'] == 'true': no_mass = True - thermal_resistance = material['thermal_resistance']['#text'] + thermal_resistance = float(material['thermal_resistance']['#text']) else: - conductivity = material['conductivity']['#text'] - density = material['density']['#text'] - specific_heat = material['specific_heat']['#text'] + conductivity = float(material['conductivity']['#text']) + density = float(material['density']['#text']) + specific_heat = float(material['specific_heat']['#text']) _material = Material(material_id, name, solar_absorptance, @@ -96,7 +96,7 @@ class NrelCatalog(Catalog): material_id = layer['material'][0] thickness = 0 if 'thickness' in layer: - thickness = layer['thickness']['#text'] + thickness = float(layer['thickness']['#text']) for material in self._catalog_materials: if str(material_id) == str(material.id): layers.append(Layer(layer_id, layer_name, material, thickness)) @@ -114,18 +114,20 @@ class NrelCatalog(Catalog): climate_zone = archetype['@climate_zone'] construction_period = \ ConstructionHelper().reference_standard_to_construction_period[archetype['@reference_standard']] - average_storey_height = archetype['average_storey_height']['#text'] - thermal_capacity = str(float(archetype['thermal_capacity']['#text']) * 1000) - extra_loses_due_to_thermal_bridges = archetype['extra_loses_due_to_thermal_bridges']['#text'] - indirect_heated_ratio = archetype['indirect_heated_ratio']['#text'] - infiltration_rate_for_ventilation_system_off = archetype['infiltration_rate_for_ventilation_system_off']['#text'] - infiltration_rate_for_ventilation_system_on = archetype['infiltration_rate_for_ventilation_system_on']['#text'] + average_storey_height = float(archetype['average_storey_height']['#text']) + thermal_capacity = float(archetype['thermal_capacity']['#text']) * 1000 + extra_loses_due_to_thermal_bridges = float(archetype['extra_loses_due_to_thermal_bridges']['#text']) + indirect_heated_ratio = float(archetype['indirect_heated_ratio']['#text']) + infiltration_rate_for_ventilation_system_off = \ + float(archetype['infiltration_rate_for_ventilation_system_off']['#text']) + infiltration_rate_for_ventilation_system_on = \ + float(archetype['infiltration_rate_for_ventilation_system_on']['#text']) archetype_constructions = [] for archetype_construction in archetype['constructions']['construction']: for construction in self._catalog_constructions: if construction.id == archetype_construction['@id']: - window_ratio = archetype_construction['window_ratio']['#text'] + window_ratio = float(archetype_construction['window_ratio']['#text']) window_id = archetype_construction['window'] _construction = None _window = None diff --git a/hub/city_model_structure/attributes/plane.py b/hub/city_model_structure/attributes/plane.py index 700be8fb..8dc0fa77 100644 --- a/hub/city_model_structure/attributes/plane.py +++ b/hub/city_model_structure/attributes/plane.py @@ -55,7 +55,7 @@ class Plane: self._equation = (a, b, c, d) return self._equation - def distance(self, point): + def distance_to_point(self, point): """ Distance between the given point and the plane :return: float diff --git a/hub/city_model_structure/building.py b/hub/city_model_structure/building.py index d5129142..e2a30906 100644 --- a/hub/city_model_structure/building.py +++ b/hub/city_model_structure/building.py @@ -441,3 +441,26 @@ class Building(CityObject): for usage in internal_zone.usages: _usage = f'{_usage}{usage.name}_{usage.percentage} ' return _usage.rstrip() + + def identify_shared_walls(self): + """ + Identifies which building' walls adjoin the neighbouring building and saves that information in the + corresponding surfaces + """ + x = int((self.upper_corner[0] - self.lower_corner[0]) / 2) + y = int((self.upper_corner[1] - self.lower_corner[1]) / 2) + city_map = [['' for _ in range(y+1)] for _ in range(x+1)] + city_image = [[0 for _ in range(y+1)] for _ in range(x+1)] + for building_name in building_names: + building = city.city_object(building_name) + for ground in building.grounds: + length = len(ground.perimeter_polygon.coordinates) - 1 + for i, coordinate in enumerate(ground.perimeter_polygon.coordinates): + j = i+1 + if i == length: + j = 0 + next_coordinate = ground.perimeter_polygon.coordinates[j] + point_1 = GeometryHelper.coordinate_to_map_point(coordinate, city) + point_2 = GeometryHelper.coordinate_to_map_point(next_coordinate, city) + for x in range(point_1.x, point_2.x): + y = GeometryHelper.point_between_point(point_1, point_2, x).y diff --git a/hub/city_model_structure/building_demand/thermal_zone.py b/hub/city_model_structure/building_demand/thermal_zone.py index db873ce4..beb26045 100644 --- a/hub/city_model_structure/building_demand/thermal_zone.py +++ b/hub/city_model_structure/building_demand/thermal_zone.py @@ -510,10 +510,14 @@ class ThermalZone: _schedule.values = values[:day] _schedules.append(_schedule) - _internal_gain.convective_fraction = _convective_fraction / _average_internal_gain - _internal_gain.radiative_fraction = _radiative_fraction / _average_internal_gain - _internal_gain.latent_fraction = _latent_fraction / _average_internal_gain _internal_gain.average_internal_gain = _average_internal_gain + _internal_gain.convective_fraction = 0 + _internal_gain.radiative_fraction = 0 + _internal_gain.latent_fraction = 0 + if _average_internal_gain != 0: + _internal_gain.convective_fraction = _convective_fraction / _average_internal_gain + _internal_gain.radiative_fraction = _radiative_fraction / _average_internal_gain + _internal_gain.latent_fraction = _latent_fraction / _average_internal_gain _internal_gain.type = 'mean_value' _internal_gain.schedules = _schedules self._internal_gains = [_internal_gain] diff --git a/hub/city_model_structure/building_demand/usage.py b/hub/city_model_structure/building_demand/usage.py index f623ee91..36240038 100644 --- a/hub/city_model_structure/building_demand/usage.py +++ b/hub/city_model_structure/building_demand/usage.py @@ -91,9 +91,13 @@ class Usage: + self.occupancy.sensible_radiative_internal_gain + self.occupancy.latent_internal_gain) _internal_gain.average_internal_gain = _total_heat_gain - _internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain - _internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain - _internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain + _internal_gain.latent_fraction = 0 + _internal_gain.radiative_fraction = 0 + _internal_gain.convective_fraction = 0 + if _total_heat_gain != 0: + _internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain + _internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain + _internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain _internal_gain.schedules = self.occupancy.occupancy_schedules self._internal_gains = [_internal_gain] if self.lighting is not None: diff --git a/hub/city_model_structure/building_demand/usage_zone.py b/hub/city_model_structure/building_demand/usage_zone.py index 43a69c20..6357cff8 100644 --- a/hub/city_model_structure/building_demand/usage_zone.py +++ b/hub/city_model_structure/building_demand/usage_zone.py @@ -91,9 +91,13 @@ class UsageZone: + self.occupancy.sensible_radiative_internal_gain + self.occupancy.latent_internal_gain) _internal_gain.average_internal_gain = _total_heat_gain - _internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain - _internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain - _internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain + _internal_gain.latent_fraction = 0 + _internal_gain.radiative_fraction = 0 + _internal_gain.convective_fraction = 0 + if _total_heat_gain != 0: + _internal_gain.latent_fraction = self.occupancy.latent_internal_gain / _total_heat_gain + _internal_gain.radiative_fraction = self.occupancy.sensible_radiative_internal_gain / _total_heat_gain + _internal_gain.convective_fraction = self.occupancy.sensible_convective_internal_gain / _total_heat_gain _internal_gain.schedules = self.occupancy.occupancy_schedules self._internal_gains = [_internal_gain] if self.lighting is not None: diff --git a/hub/city_model_structure/city_object.py b/hub/city_model_structure/city_object.py index b5b84fcc..ab50250c 100644 --- a/hub/city_model_structure/city_object.py +++ b/hub/city_model_structure/city_object.py @@ -24,11 +24,15 @@ class CityObject: self._surfaces = surfaces self._type = None self._city_object_lower_corner = None + self._city_object_upper_corner = None self._detailed_polyhedron = None self._simplified_polyhedron = None self._min_x = ConfigurationHelper().max_coordinate self._min_y = ConfigurationHelper().max_coordinate self._min_z = ConfigurationHelper().max_coordinate + self._max_x = ConfigurationHelper().min_coordinate + self._max_y = ConfigurationHelper().min_coordinate + self._max_z = ConfigurationHelper().min_coordinate self._centroid = None self._external_temperature = dict() self._global_horizontal = dict() @@ -212,6 +216,16 @@ class CityObject: self._city_object_lower_corner = [self._min_x, self._min_y, self._min_z] return self._city_object_lower_corner + @property + def upper_corner(self): + """ + Get city object upper corner coordinates [x, y, z] + :return: [x,y,z] + """ + if self._city_object_upper_corner is None: + self._city_object_upper_corner = [self._max_x, self._max_y, self._max_z] + return self._city_object_upper_corner + @property def sensors(self) -> List[Sensor]: """ diff --git a/hub/exports/building_energy/idf.py b/hub/exports/building_energy/idf.py index e33a6d34..b4a63a7d 100644 --- a/hub/exports/building_energy/idf.py +++ b/hub/exports/building_energy/idf.py @@ -130,10 +130,7 @@ class Idf: self._idf.newidfobject(self._MATERIAL_NOMASS, Name=layer.material.name, Roughness=self._ROUGHNESS, - Thermal_Resistance=layer.material.thermal_resistance, - Thermal_Absorptance=layer.material.thermal_absorptance, - Solar_Absorptance=layer.material.solar_absorptance, - Visible_Absorptance=layer.material.visible_absorptance + Thermal_Resistance=layer.material.thermal_resistance ) else: self._idf.newidfobject(self._MATERIAL, @@ -323,9 +320,12 @@ class Idf: def _add_occupancy(self, thermal_zone, zone_name): number_of_people = thermal_zone.occupancy.occupancy_density * thermal_zone.total_floor_area - fraction_radiant = thermal_zone.occupancy.sensible_radiative_internal_gain / \ - (thermal_zone.occupancy.sensible_radiative_internal_gain + - thermal_zone.occupancy.sensible_convective_internal_gain) + fraction_radiant = 0 + total_sensible = thermal_zone.occupancy.sensible_radiative_internal_gain + \ + thermal_zone.occupancy.sensible_convective_internal_gain + if total_sensible != 0: + fraction_radiant = thermal_zone.occupancy.sensible_radiative_internal_gain / total_sensible + self._idf.newidfobject(self._PEOPLE, Name=f'{zone_name}_occupancy', Zone_or_ZoneList_Name=zone_name, @@ -377,7 +377,6 @@ class Idf: self._rename_building(self._city.name) self._lod = self._city.level_of_detail.geometry for building in self._city.buildings: - for internal_zone in building.internal_zones: for thermal_zone in internal_zone.thermal_zones: for thermal_boundary in thermal_zone.thermal_boundaries: diff --git a/hub/exports/building_energy/insel/insel_monthly_energy_balance.py b/hub/exports/building_energy/insel/insel_monthly_energy_balance.py index 6f831ac4..47e0bff9 100644 --- a/hub/exports/building_energy/insel/insel_monthly_energy_balance.py +++ b/hub/exports/building_energy/insel/insel_monthly_energy_balance.py @@ -117,7 +117,9 @@ class InselMonthlyEnergyBalance(Insel): for thermal_boundary in thermal_zone.thermal_boundaries: type_code = _CONSTRUCTION_CODE[thermal_boundary.type] - window_area = thermal_boundary.opaque_area * thermal_boundary.window_ratio / (1 - thermal_boundary.window_ratio) + window_area = 0 + if thermal_boundary.window_ratio < 1: + window_area = thermal_boundary.opaque_area * thermal_boundary.window_ratio / (1 - thermal_boundary.window_ratio) parameters.append(type_code) if thermal_boundary.type != cte.GROUND: diff --git a/hub/helpers/geometry_helper.py b/hub/helpers/geometry_helper.py index 0327f97b..d650eefd 100644 --- a/hub/helpers/geometry_helper.py +++ b/hub/helpers/geometry_helper.py @@ -49,6 +49,7 @@ class GeometryHelper: """ Geometry helper class """ + # todo: complete dictionary srs_transformations = { 'urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH': 'epsg:25832' } @@ -63,15 +64,25 @@ class GeometryHelper: @staticmethod def city_mapping(city, building_names=None, plot=False): + """ + Returns a shared_information dictionary like + + { + "building_name" : [{line: 0 coordinate_1: [x,y,z], coordinate_2:[x, y, z], points: 0}] + } + """ + shared_information = {} if building_names is None: building_names = [b.name for b in city.buildings] x = int((city.upper_corner[0] - city.lower_corner[0]) * 0.5) + 1 y = int((city.upper_corner[1] - city.lower_corner[1]) * 0.5) + 1 - city_map = [['' for _ in range(y + 1)] for _ in range(x + 1)] + city_map = [[{} for _ in range(y + 1)] for _ in range(x + 1)] img = Image.new('RGB', (x + 1, y + 1), "black") # create a new black image city_image = img.load() # create the pixel map for building_name in building_names: building = city.city_object(building_name) + shared_information[building_name]: [] + line = 0 for ground in building.grounds: length = len(ground.perimeter_polygon.coordinates) - 1 for i, coordinate in enumerate(ground.perimeter_polygon.coordinates): @@ -79,6 +90,8 @@ class GeometryHelper: if i == length: j = 0 next_coordinate = ground.perimeter_polygon.coordinates[j] + line_dictionary = {"line": line, "coordinate_1": coordinate, "coordinate_2":next_coordinate, "points": 0} + print(line_dictionary) point = GeometryHelper.coordinate_to_map_point(coordinate, city) distance = GeometryHelper.distance_between_points(coordinate, next_coordinate) if distance == 0: @@ -101,6 +114,7 @@ class GeometryHelper: neighbour.neighbours = [building] elif building not in neighbour.neighbours: neighbour.neighbours.append(building) + line += 1 if plot: img.show() diff --git a/hub/imports/construction/nrcan_physics_parameters.py b/hub/imports/construction/nrcan_physics_parameters.py index eb499080..4ceb4e57 100644 --- a/hub/imports/construction/nrcan_physics_parameters.py +++ b/hub/imports/construction/nrcan_physics_parameters.py @@ -51,7 +51,7 @@ class NrcanPhysicsParameters: for thermal_zone in internal_zone.thermal_zones: thermal_zone.total_floor_area = thermal_zone.footprint_area else: - number_of_storeys = int(float(building.eave_height) / float(building.average_storey_height)) + number_of_storeys = int(building.eave_height / building.average_storey_height) thermal_zone = building.internal_zones[0].thermal_zones[0] thermal_zone.total_floor_area = thermal_zone.footprint_area * number_of_storeys else: @@ -69,7 +69,7 @@ class NrcanPhysicsParameters: nrcan_archetypes = nrcan_catalog.entries('archetypes') for building_archetype in nrcan_archetypes: construction_period_limits = building_archetype.construction_period.split('_') - if int(construction_period_limits[0]) <= int(year_of_construction) < int(construction_period_limits[1]): + if int(construction_period_limits[0]) <= year_of_construction < int(construction_period_limits[1]): if (str(function) == str(building_archetype.function)) and \ (climate_zone == str(building_archetype.climate_zone)): return building_archetype @@ -135,12 +135,12 @@ class NrcanPhysicsParameters: # The agreement is that the layers are defined from outside to inside external_layer = construction_archetype.layers[0] external_surface = thermal_boundary.parent_surface - external_surface.short_wave_reflectance = 1 - float(external_layer.material.solar_absorptance) - external_surface.long_wave_emittance = 1 - float(external_layer.material.solar_absorptance) + external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance + external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1] internal_surface = thermal_boundary.internal_surface - internal_surface.short_wave_reflectance = 1 - float(internal_layer.material.solar_absorptance) - internal_surface.long_wave_emittance = 1 - float(internal_layer.material.solar_absorptance) + internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance + internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance for thermal_opening in thermal_boundary.thermal_openings: if construction_archetype.window is not None: diff --git a/hub/imports/construction/nrel_physics_parameters.py b/hub/imports/construction/nrel_physics_parameters.py index 6de4771a..e1e3fa06 100644 --- a/hub/imports/construction/nrel_physics_parameters.py +++ b/hub/imports/construction/nrel_physics_parameters.py @@ -58,7 +58,7 @@ class NrelPhysicsParameters: for thermal_zone in internal_zone.thermal_zones: thermal_zone.total_floor_area = thermal_zone.footprint_area else: - number_of_storeys = int(float(building.eave_height) / float(building.average_storey_height)) + number_of_storeys = int(building.eave_height / building.average_storey_height) thermal_zone = building.internal_zones[0].thermal_zones[0] thermal_zone.total_floor_area = thermal_zone.footprint_area * number_of_storeys else: @@ -78,7 +78,7 @@ class NrelPhysicsParameters: construction_period_limits = building_archetype.construction_period.split(' - ') if construction_period_limits[1] == 'PRESENT': construction_period_limits[1] = 3000 - if int(construction_period_limits[0]) <= int(year_of_construction) < int(construction_period_limits[1]): + if int(construction_period_limits[0]) <= year_of_constructionF < int(construction_period_limits[1]): if (str(function) == str(building_archetype.function)) and \ (climate_zone == str(building_archetype.climate_zone)): return building_archetype @@ -130,12 +130,12 @@ class NrelPhysicsParameters: # The agreement is that the layers are defined from outside to inside external_layer = construction_archetype.layers[0] external_surface = thermal_boundary.parent_surface - external_surface.short_wave_reflectance = 1 - float(external_layer.material.solar_absorptance) - external_surface.long_wave_emittance = 1 - float(external_layer.material.solar_absorptance) + external_surface.short_wave_reflectance = 1 - external_layer.material.solar_absorptance + external_surface.long_wave_emittance = 1 - external_layer.material.solar_absorptance internal_layer = construction_archetype.layers[len(construction_archetype.layers) - 1] internal_surface = thermal_boundary.internal_surface - internal_surface.short_wave_reflectance = 1 - float(internal_layer.material.solar_absorptance) - internal_surface.long_wave_emittance = 1 - float(internal_layer.material.solar_absorptance) + internal_surface.short_wave_reflectance = 1 - internal_layer.material.solar_absorptance + internal_surface.long_wave_emittance = 1 - internal_layer.material.solar_absorptance for thermal_opening in thermal_boundary.thermal_openings: if construction_archetype.window is not None: diff --git a/hub/imports/geometry/rhino.py b/hub/imports/geometry/rhino.py index dab5cd2e..c4bf354d 100644 --- a/hub/imports/geometry/rhino.py +++ b/hub/imports/geometry/rhino.py @@ -124,7 +124,7 @@ class Rhino: # todo: this is a hack for dompark project it should not be done this way windows should be correctly modeled # if the distance between the wall plane and the window is less than 2m # and the window Z coordinate it's between the wall Z, it's a window of that wall - if plane.distance(corner) <= 2: + if plane.distance_to_point(corner) <= 2: # check if the window is in the right high. if surface.upper_corner[2] >= corner[2] >= surface.lower_corner[2]: if surface.holes_polygons is None: diff --git a/hub/imports/usage/comnet_usage_parameters.py b/hub/imports/usage/comnet_usage_parameters.py index 7c6c137e..6dcab450 100644 --- a/hub/imports/usage/comnet_usage_parameters.py +++ b/hub/imports/usage/comnet_usage_parameters.py @@ -189,10 +189,15 @@ class ComnetUsageParameters: _schedule_values[v, day] += value * archetype.appliances.density _sum += value * archetype.appliances.density * _number_of_days_per_type[day] - _latent_fraction = _latent_heat_gain / _total_heat_gain - _radiative_fraction = _radiative_heat_gain / _total_heat_gain - _convective_fraction = _convective_heat_gain / _total_heat_gain - _average_internal_gain = _sum / _total_heat_gain + _latent_fraction = 0 + _radiative_fraction = 0 + _convective_fraction = 0 + _average_internal_gain = 0 + if _total_heat_gain != 0: + _latent_fraction = _latent_heat_gain / _total_heat_gain + _radiative_fraction = _radiative_heat_gain / _total_heat_gain + _convective_fraction = _convective_heat_gain / _total_heat_gain + _average_internal_gain = _sum / _total_heat_gain _schedules = [] for day in range(0, len(_DAYS)):