Performance improvements completed

This commit is contained in:
Guille Gutierrez 2023-03-21 14:22:28 -04:00
parent 2781696f95
commit 927771081d
7 changed files with 256105 additions and 33 deletions

View File

@ -26,8 +26,6 @@ class Polygon:
""" """
Polygon class Polygon class
""" """
# todo: review with @Guille: Points, Coordinates, Vertices, Faces
def __init__(self, coordinates): def __init__(self, coordinates):
self._area = None self._area = None
self._points = None self._points = None

View File

@ -234,6 +234,10 @@ class City:
else: else:
if city_object in self._buildings: if city_object in self._buildings:
self._buildings.remove(city_object) self._buildings.remove(city_object)
# regenerate hash map
self._city_objects_dictionary.clear()
for i, city_object in enumerate(self._buildings):
self._city_objects_dictionary[city_object.name] = i
@property @property
def srs_name(self) -> Union[None, str]: def srs_name(self) -> Union[None, str]:

View File

@ -4,6 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import datetime
import sys import sys
import math import math
import numpy as np import numpy as np
@ -39,7 +40,7 @@ class StoreysGeneration:
number_of_storeys, height = self._calculate_number_storeys_and_height(self._building.average_storey_height, number_of_storeys, height = self._calculate_number_storeys_and_height(self._building.average_storey_height,
self._building.eave_height, self._building.eave_height,
self._building.storeys_above_ground) self._building.storeys_above_ground)
number_of_storeys = 1
if not self._divide_in_storeys or number_of_storeys == 1: if not self._divide_in_storeys or number_of_storeys == 1:
storey = Storey('storey_0', self._building.surfaces, [None, None], self._internal_zone.volume, storey = Storey('storey_0', self._building.surfaces, [None, None], self._internal_zone.volume,
self._internal_zone, self._floor_area) self._internal_zone, self._floor_area)
@ -55,7 +56,6 @@ class StoreysGeneration:
else: else:
thermal_zones = [storey.neighbours[1], storey.thermal_zone] thermal_zones = [storey.neighbours[1], storey.thermal_zone]
thermal_boundary.thermal_zones = thermal_zones thermal_boundary.thermal_zones = thermal_zones
return [storey.thermal_zone] return [storey.thermal_zone]
if number_of_storeys == 0: if number_of_storeys == 0:

View File

@ -4,7 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import datetime
import math import math
import sys import sys
from hub.hub_logger import logger from hub.hub_logger import logger
@ -37,17 +37,21 @@ class NrcanPhysicsParameters:
for building in city.buildings: for building in city.buildings:
try: try:
function = Dictionaries().hub_function_to_nrcan_construction_function[building.function] function = Dictionaries().hub_function_to_nrcan_construction_function[building.function]
archetype = self._search_archetype(nrcan_catalog, function, building.year_of_construction, self._climate_zone) archetype = self._search_archetype(nrcan_catalog, function, building.year_of_construction, self._climate_zone)
except KeyError: except KeyError:
logger.error(f'Building {building.name} has unknown construction archetype for building function: ' logger.error(f'Building {building.name} has unknown construction archetype for building function: '
f'{building.function}, building year of construction: {building.year_of_construction} ' f'{function} [{building.function}], building year of construction: {building.year_of_construction} '
f'and climate zone {self._climate_zone}\n') f'and climate zone {self._climate_zone}\n')
sys.stderr.write(f'Building {building.name} has unknown construction archetype for building function: ' sys.stderr.write(f'Building {building.name} has unknown construction archetype for building function: '
f'{building.function}, building year of construction: {building.year_of_construction} ' f'{function} [{building.function}], building year of construction: {building.year_of_construction} '
f'and climate zone {self._climate_zone}\n') f'and climate zone {self._climate_zone}\n')
continue continue
# if building has no thermal zones defined from geometry, and the building will be divided in storeys, # if building has no thermal zones defined from geometry, and the building will be divided in storeys,
# one thermal zone per storey is assigned # one thermal zone per storey is assigned
if len(building.internal_zones) == 1: if len(building.internal_zones) == 1:
if building.internal_zones[0].thermal_zones is None: if building.internal_zones[0].thermal_zones is None:
self._create_storeys(building, archetype, self._divide_in_storeys) self._create_storeys(building, archetype, self._divide_in_storeys)
@ -63,7 +67,6 @@ class NrcanPhysicsParameters:
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones:
thermal_zone.total_floor_area = thermal_zone.footprint_area thermal_zone.total_floor_area = thermal_zone.footprint_area
for internal_zone in building.internal_zones: for internal_zone in building.internal_zones:
self._assign_values(internal_zone.thermal_zones, archetype) self._assign_values(internal_zone.thermal_zones, archetype)
for thermal_zone in internal_zone.thermal_zones: for thermal_zone in internal_zone.thermal_zones:
@ -74,7 +77,7 @@ class NrcanPhysicsParameters:
nrcan_archetypes = nrcan_catalog.entries('archetypes') nrcan_archetypes = nrcan_catalog.entries('archetypes')
for building_archetype in nrcan_archetypes: for building_archetype in nrcan_archetypes:
construction_period_limits = building_archetype.construction_period.split('_') construction_period_limits = building_archetype.construction_period.split('_')
if int(construction_period_limits[0]) <= 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 \ if (str(function) == str(building_archetype.function)) and \
(climate_zone == str(building_archetype.climate_zone)): (climate_zone == str(building_archetype.climate_zone)):
return building_archetype return building_archetype

View File

@ -70,7 +70,8 @@ class Geojson:
points = igh.invert_points(points) points = igh.invert_points(points)
polygon = Polygon(points) polygon = Polygon(points)
polygon.area = igh.ground_area(points) polygon.area = igh.ground_area(points)
surfaces.append(Surface(polygon, polygon)) surface = Surface(polygon, polygon)
surfaces.append(surface)
buildings.append(Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function)) buildings.append(Building(f'{name}_zone_{zone}', surfaces, year_of_construction, function))
return buildings return buildings
@ -82,6 +83,7 @@ class Geojson:
for zone, lod0_building in enumerate(lod0_buildings): for zone, lod0_building in enumerate(lod0_buildings):
for surface in lod0_building.grounds: for surface in lod0_building.grounds:
volume = surface.solid_polygon.area * height volume = surface.solid_polygon.area * height
surfaces.append(surface) surfaces.append(surface)
roof_coordinates = [] roof_coordinates = []
@ -91,6 +93,7 @@ class Geojson:
# insert the roof rotated already # insert the roof rotated already
roof_coordinates.insert(0, roof_coordinate) roof_coordinates.insert(0, roof_coordinate)
polygon = Polygon(roof_coordinates) polygon = Polygon(roof_coordinates)
polygon.area = surface.solid_polygon.area
roof = Surface(polygon, polygon) roof = Surface(polygon, polygon)
surfaces.append(roof) surfaces.append(roof)
# adding a wall means add the point coordinates and the next point coordinates with Z's height and 0 # adding a wall means add the point coordinates and the next point coordinates with Z's height and 0

View File

@ -4,14 +4,12 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import datetime
from pathlib import Path from pathlib import Path
from unittest import TestCase from unittest import TestCase
from hub.helpers.geometry_helper import GeometryHelper
from numpy import inf
import hub.exports.exports_factory import hub.exports.exports_factory
from hub.helpers.dictionaries import MontrealFunctionToHubFunction
from hub.helpers.geometry_helper import GeometryHelper
from hub.imports.construction_factory import ConstructionFactory from hub.imports.construction_factory import ConstructionFactory
from hub.imports.geometry_factory import GeometryFactory from hub.imports.geometry_factory import GeometryFactory
@ -21,6 +19,7 @@ class TestGeometryFactory(TestCase):
Non-functional TestGeometryFactory Non-functional TestGeometryFactory
Load testing Load testing
""" """
def setUp(self) -> None: def setUp(self) -> None:
""" """
Test setup Test setup
@ -36,7 +35,8 @@ class TestGeometryFactory(TestCase):
path=file_path, path=file_path,
height_field=height_field, height_field=height_field,
year_of_construction_field=year_of_construction_field, year_of_construction_field=year_of_construction_field,
function_field=function_field).city function_field=function_field,
).city
self.assertIsNotNone(self._city, 'city is none') self.assertIsNotNone(self._city, 'city is none')
return self._city return self._city
@ -134,20 +134,14 @@ class TestGeometryFactory(TestCase):
""" """
Test geojson import Test geojson import
""" """
file = '10000_buildings.geojson' file = '2000_buildings.geojson'
start = datetime.datetime.now() city = GeometryFactory('geojson',
city = self._get_city(file, 'geojson', path=(self._example_path / file).resolve(),
height_field='building_height', height_field='building_height',
year_of_construction_field='ANNEE_CONS', year_of_construction_field='ANNEE_CONS',
function_field='CODE_UTILI') function_field='CODE_UTILI',
end = datetime.datetime.now() function_to_hub=MontrealFunctionToHubFunction().dictionary).city
print(f'geometry load in {end-start} s')
start = datetime.datetime.now()
hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export()
end = datetime.datetime.now()
print(f'geometry export in {end - start} s')
self.assertEqual(2356, len(city.buildings), 'wrong number of buildings') self.assertEqual(2356, len(city.buildings), 'wrong number of buildings')
self._check_buildings(city)
def test_map_neighbours(self): def test_map_neighbours(self):
""" """
@ -162,15 +156,16 @@ class TestGeometryFactory(TestCase):
city = self._get_city(file, 'geojson', city = self._get_city(file, 'geojson',
year_of_construction_field='ANNEE_CONS', year_of_construction_field='ANNEE_CONS',
function_field='LIBELLE_UT') function_field='LIBELLE_UT')
info_lod0 = GeometryHelper.city_mapping(city, plot=False) info_lod0 = GeometryHelper.city_mapping(city, plot=False)
hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export() hub.exports.exports_factory.ExportsFactory('obj', city, self._output_path).export()
self.assertEqual(info_lod0, info_lod1) self.assertEqual(info_lod0, info_lod1)
for building in city.buildings: for building in city.buildings:
self.assertEqual(2, len(building.neighbours)) self.assertEqual(2, len(building.neighbours))
self.assertEqual('2_part_0_zone_0',city.city_object('1_part_0_zone_0').neighbours[0].name) self.assertEqual('2_part_0_zone_0', city.city_object('1_part_0_zone_0').neighbours[0].name)
self.assertEqual('3_part_0_zone_0',city.city_object('1_part_0_zone_0').neighbours[1].name) self.assertEqual('3_part_0_zone_0', city.city_object('1_part_0_zone_0').neighbours[1].name)
self.assertEqual('1_part_0_zone_0',city.city_object('2_part_0_zone_0').neighbours[0].name) self.assertEqual('1_part_0_zone_0', city.city_object('2_part_0_zone_0').neighbours[0].name)
self.assertEqual('3_part_0_zone_0',city.city_object('2_part_0_zone_0').neighbours[1].name) self.assertEqual('3_part_0_zone_0', city.city_object('2_part_0_zone_0').neighbours[1].name)
self.assertEqual('1_part_0_zone_0', city.city_object('3_part_0_zone_0').neighbours[0].name) self.assertEqual('1_part_0_zone_0', city.city_object('3_part_0_zone_0').neighbours[0].name)
self.assertEqual('2_part_0_zone_0', city.city_object('3_part_0_zone_0').neighbours[1].name) self.assertEqual('2_part_0_zone_0', city.city_object('3_part_0_zone_0').neighbours[1].name)

File diff suppressed because one or more lines are too long