Merge remote-tracking branch 'origin/energy_system_central_data_model' into energy_system_central_data_model

This commit is contained in:
Saeed Ranjbar 2023-10-05 13:22:19 -04:00
commit 6f40a15609
41 changed files with 392 additions and 153 deletions

50
hub/LINUX_INSTALL.md Normal file
View File

@ -0,0 +1,50 @@
# LINUX_INSTALL
## Prepare your environment
### Install Miniconda
1. Get the link for the latest version of Miniconda from https://docs.conda.io/en/latest/miniconda.html
2. Download the installer using wget
````
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
````
3. Make the installer executable
````
chmod +x ./Miniconda3-latest-Linux-x86_64.sh
````
4. Run the installer
````
./Miniconda3-latest-Linux-x86_64.sh
````
5. Holder enter until you are prompted to accept the license terms. Enter yes.
6. Initialize the conda environment
````
conda init bash
````
7. Source .bashrc
````
source ~/.bashrc
````
8. Create a conda environment for the hub
````
conda create --name hub python=3.9.16
````
### Setup SRA
1. Get the sra binary and libshortwave.so library from Guille or Koa
2. Place the binary and the library into your directory of choice
3. Make a symlink for the binary and place it into /usr/local/bin/sra
````
sudo ln -s ~/sra /usr/local/bin/sra
````
4. Make a symlink for the library and place it into /usr/local/lib/libshortwave.so
````
sudo ln -s ~/libshortwave.so /usr/local/lib/libshortwave.so
````
### Setup INSEL
1. TBD
### Get a Python editor
You are welcome to use the Python editor of your preference. The CERC team generally uses PyCharm to develop the hub.
The latest version of PyCharm can be downloaded from [JetBrains website](https://www.jetbrains.com/pycharm/promo/?source=google&medium=cpc&campaign=14127625109&term=pycharm&content=536947779504&gad=1&gclid=CjwKCAjw0ZiiBhBKEiwA4PT9z2AxPfy39x_RcBqlYxJ6sm_s55T9qvA_sZ8ZfkhIVX6FOD-ySbmzARoCcpQQAvD_BwE).
For setup and installation instructions, please view the "Get a Python Editor"
from the [WINDOWS_INSTALL](https://nextgenerations-cities.encs.concordia.ca/gitea/CERC/hub/src/branch/main/hub/WINDOWS_INSTALL.md)
documentation.

View File

@ -2,16 +2,16 @@
This is an installation guide for Windows, covering all the steps needed to begin developing code for the Urban This is an installation guide for Windows, covering all the steps needed to begin developing code for the Urban
Simulation Platform 'Hub'. At the end of this process you will have installed and configured all the necessary applications, Simulation Platform 'Hub'. At the end of this process you will have installed and configured all the necessary applications,
set up your own project on CERC's Gitlab and created your first python file. set up your own project on CERC's Gitea and created your first python file.
## Prepare your environment ## Prepare your environment
g
To develop any new code for the Urban Simulation Platform you must have the right software applications installed and configured. To develop any new code for the Urban Simulation Platform you must have the right software applications installed and configured.
The Platform is written in python and so the applications you need are: The Platform is written in python and so the applications you need are:
* Miniconda * Miniconda
* SRA Files
* Python Editor * Python Editor
You also need to register a user account with the CERC's code repository on Gitlab and have the necessary permissions for You also need to register a user account with the CERC's code repository on Gitea and have the necessary permissions for
creating new code. For that purpose, please, contact Guillermo (guillermo.gutierrezmorote@concordia.ca) or creating new code. For that purpose, please, contact Guillermo (guillermo.gutierrezmorote@concordia.ca) or
Koa (kekoa.wells@concordia.ca) as soon as possible. Koa (kekoa.wells@concordia.ca) as soon as possible.
@ -47,6 +47,29 @@ _The term '...' is not recognized as the name of a cmdlet, function,..._
To solve it, type 'Set-ExecutionPolicy Unrestricted' as shown in the image. To solve it, type 'Set-ExecutionPolicy Unrestricted' as shown in the image.
### Setup SRA
1. Get the SRA executable and dll files from Guille or Koa
2. Create a folder in "C:\Program Files\" called "sra"
![create_sra](docs/img_windows_install/img_34.png)
3. Copy shortwave_integer.exe and pthreadGC2.dll into the sra folder.
![create_sra](docs/img_windows_install/img_35.png)
4. Add the newly created sra folder to the Path, similar to step 2 from the Miniconda setup above.
![create_sra](docs/img_windows_install/img_36.png)
### Install and setup INSEL
1. Get the INSEL installer from Guille or Koa
2. Run the installer to completion using the default installation path
3. Add the INSEL installation folder to the Path
![create_sra](docs/img_windows_install/img_41.png)
### Get a Python editor ### Get a Python editor
1. You will need a python editor in order to import the existing Hub source code and to write your own python code. 1. You will need a python editor in order to import the existing Hub source code and to write your own python code.
@ -55,7 +78,7 @@ an excellent open-source python editor.
2. Run the installer, and follow the installation instructions for PyCharm, you may change a few options, 2. Run the installer, and follow the installation instructions for PyCharm, you may change a few options,
but the default ones should be fine. but the default ones should be fine.
**NOTE:** If Pycharm asks you to create a Virtual Environment, click **Cancel**. You will do it later using Conda instead. **NOTE:** If PyCharm asks you to create a Virtual Environment, click **Cancel**. You will do it later using Conda instead.
![creating_virtual_environment](docs/img_windows_install/img_31.png) ![creating_virtual_environment](docs/img_windows_install/img_31.png)
@ -70,14 +93,12 @@ You can find it also at **Git->Clone...**
![pycharm get from version control](docs/img_windows_install/img_6.png) ![pycharm get from version control](docs/img_windows_install/img_6.png)
3. Select **Git** as the **Version control**. For the URL use the link to the Hub repository, as seen below. 3. Select **Git** as the **Version control**. Open the [hub repository](https://nextgenerations-cities.encs.concordia.ca/gitea/CERC/hub)
on Gitea and copy the URL from your browser to use as the URL inside PyCharm.
![pycharm get from version control screen](docs/img_windows_install/img_1.png) ![pycharm get from version control screen](docs/img_windows_install/img_1.png)
(You can also copy this URL by going to the Hub repository in [Gitlab](https://rs-loy-gitlab.concordia.ca/Guille/hub.git) ![gitea get https](docs/img_windows_install/img_39.png)
and clicking on the **Copy URL** button, next to **Clone with HTTPS**)
![gitlab get https](docs/img_windows_install/img_17.png)
The Directory to store the Hub source code locally is automatically created for you. Edit this if you prefer it to be stored somewhere else. The Directory to store the Hub source code locally is automatically created for you. Edit this if you prefer it to be stored somewhere else.
@ -152,7 +173,7 @@ _lca_classes_,... And, click on the **Create** button.
3. Click on the **Git** button in the bottom-left corner to pop-up the window showing the Git information. 3. Click on the **Git** button in the bottom-left corner to pop-up the window showing the Git information.
See your new branch has been created under _Local_. See your new branch has been created under _Local_.
4. Now we need to let the CERC Gitlab repository know about this new branch. You do this by right-clicking on 4. Now we need to let the CERC Gitea repository know about this new branch. You do this by right-clicking on
your branch and selecting **Push...** from the drop-down menu. your branch and selecting **Push...** from the drop-down menu.
5. Then click on the **Push** button at the bottom-right of the **Push Commits** window. 5. Then click on the **Push** button at the bottom-right of the **Push Commits** window.
@ -180,33 +201,35 @@ See the picture below.
![pycharm configuration screen](docs/img_windows_install/img_5.png) ![pycharm configuration screen](docs/img_windows_install/img_5.png)
## Set up a new project on Gitlab ## Set up a new project on Gitea
You will need an account before you can access the Gitea. Please contact Guillermo (guillermo.gutierrezmorote@concordia.ca) or
Koa (kekoa.wells@concordia.ca) to request an account.
1. Open a browser and to the [CERC Git](https://rs-loy-gitlab.concordia.ca/). Click on the blue **New project** button. 1. Open a browser and go to the [CERC Gitea](https://nextgenerations-cities.encs.concordia.ca/). Click on the **+** in the top right
and select "New Repository" or press the **+** below the Organization tab.
![git new project screen](docs/img_windows_install/img_14.png) ![git new project screen](docs/img_windows_install/img_37.png)
2. Choose the **Create blank project** option from the three options seen below. 2. Choose the **Create blank project** option from the three options seen below.
3. Type in a name that describes your project: _hp_workflow_, _bus_system_optimization_... 3. Type in a name that describes your project: _hp_workflow_, _bus_system_optimization_...
(remember to follow the CERC naming conventions described in the [Coding Style](PYGUIDE.md)). (remember to follow the CERC naming conventions described in the [Coding Style](PYGUIDE.md)).
Check the option **Initialize repository with a README**, and ideally, check the **Visibility Level** to be **Public**. Ideally, uncheck the option **Make Repository Private**, and check the **Initialize Repository**
Then click on the **Create project** button. Then click on the **Create project** button.
![git give a name](docs/img_windows_install/img_15.png) ![git give a name](docs/img_windows_install/img_38.png)
You should then see a confirmation screen with all the information about your new project. You should then see a confirmation screen with all the information about your new project.
## Get your project into Pycharm ## Get your project into Pycharm
1. Now you can make a clone of this project, within PyCharm. First, copy the URL by clicking on the blue **Clone** button 1. Now you can make a clone of this project, within PyCharm. First, go to the page of your repository on the Gitea and copy the URL.
and then click on the **Copy URL** button, next to the **Clone with HTTPS** link.
2. Switch back to PyCharm and close the Hub project by choosing **File->Close Project**. You will then see the 2. Switch back to PyCharm and close the Hub project by choosing **File->Close Project**. You will then see the
**Welcome To PyCharm** window again. **Welcome To PyCharm** window again.
3. Clone a copy of your Project into PyCharm, following the steps 2-6 of the _GET THE CERC HUB SOURCE CODE_ 3. Clone a copy of your Project into PyCharm, following the steps 2-6 of the _GET THE CERC HUB SOURCE CODE_
section above, but using the URL link that you just copied for your gitlab project. section above, but using the URL link that you just copied for your Gitea project.
4. Select **File->Settings** to open the **Settings** window. From the panel on the left click on 4. Select **File->Settings** to open the **Settings** window. From the panel on the left click on
**Project:<project name> -> Project Structure**. **Project:<project name> -> Project Structure**.
@ -242,5 +265,5 @@ city = GeometryFactory('citygml', path='myfile.gml').city
9. Always remember to push your own project changes as the last thing you do before ending your working day! 9. Always remember to push your own project changes as the last thing you do before ending your working day!
First, commit your changes by clicking on the green check in the top-right corner of Pycharm. Add a comment that explains briefly your changes. First, commit your changes by clicking on the green check in the top-right corner of Pycharm. Add a comment that explains briefly your changes.
Then, pull by clicking on the blue arrow to be sure that there are no conflicts between your version (local) and the remote one (gitlab). Then, pull by clicking on the blue arrow to be sure that there are no conflicts between your version (local) and the remote one (Gitea).
Once the conflicts are solved and the merge in local is done, push the changes by clicking on the green arrow. Once the conflicts are solved and the merge in local is done, push the changes by clicking on the green arrow.

View File

@ -50,11 +50,11 @@ class Archetype:
_systems = [] _systems = []
for _system in self.systems: for _system in self.systems:
_systems.append(_system.to_dictionary()) _systems.append(_system.to_dictionary())
content = {'Archetype': {'name': self.name, content = {
'Archetype': {
'name': self.name,
'level of detail': self.lod, 'level of detail': self.lod,
'systems': _systems 'systems': _systems
} }
} }
return content return content

View File

@ -30,9 +30,7 @@ class MontrealCustomCatalog(Catalog):
'demand', 'system_id')) 'demand', 'system_id'))
self._lod = float(self._archetypes['catalog']['@lod']) self._lod = float(self._archetypes['catalog']['@lod'])
self._catalog_generation_equipments, self._catalog_storage_equipments = self._load_generation_and_storage_equipments()
self._catalog_generation_equipments, self._catalog_storage_equipments = \
self._load_generation_and_storage_equipments()
self._catalog_distribution_equipments = self._load_distribution_equipments() self._catalog_distribution_equipments = self._load_distribution_equipments()
self._catalog_emission_equipments = self._load_emission_equipments() self._catalog_emission_equipments = self._load_emission_equipments()
self._catalog_systems = self._load_systems() self._catalog_systems = self._load_systems()
@ -63,6 +61,7 @@ class MontrealCustomCatalog(Catalog):
electricity_efficiency = None electricity_efficiency = None
if 'electrical_efficiency' in equipment: if 'electrical_efficiency' in equipment:
electricity_efficiency = float(equipment['electrical_efficiency']) electricity_efficiency = float(equipment['electrical_efficiency'])
# todo: this may be optionals instead?
generation_system = GenerationSystem(equipment_id, generation_system = GenerationSystem(equipment_id,
name, name,
None, None,

View File

@ -56,7 +56,7 @@ class NorthAmericaEnergySystemCatalog(Catalog):
boiler_maximum_heat_output = float(boiler['@maximumHeatOutput']) boiler_maximum_heat_output = float(boiler['@maximumHeatOutput'])
boiler_minimum_heat_output = float(boiler['@minimumHeatOutput']) boiler_minimum_heat_output = float(boiler['@minimumHeatOutput'])
boiler_heat_efficiency = float(boiler['@nominalEfficiency']) boiler_heat_efficiency = float(boiler['@nominalEfficiency'])
# todo: this may be optionals instead?
boiler_component = GenerationSystem(boiler_id, boiler_component = GenerationSystem(boiler_id,
boiler_name, boiler_name,
boiler_model_name, boiler_model_name,
@ -405,15 +405,16 @@ class NorthAmericaEnergySystemCatalog(Catalog):
for material in materials: for material in materials:
if int(material.id) == int(material_id): if int(material.id) == int(material_id):
_material = material _material = material
return _material break
if _material is None: if _material is None:
raise ValueError(f'Material with the id = [{material_id}] not found in catalog ') raise ValueError(f'Material with the id = [{material_id}] not found in catalog ')
return _material
@staticmethod @staticmethod
def _search_generation_equipment(generation_systems, generation_id): def _search_generation_equipment(generation_systems, generation_id):
_generation_systems = [] _generation_systems = []
if type(generation_id) == list:
if isinstance(generation_id, list):
integer_ids = [int(item) for item in generation_id] integer_ids = [int(item) for item in generation_id]
for generation in generation_systems: for generation in generation_systems:
if int(generation.id) in integer_ids: if int(generation.id) in integer_ids:

View File

@ -70,6 +70,9 @@ class Building(CityObject):
self._min_x = min(self._min_x, surface.lower_corner[0]) self._min_x = min(self._min_x, surface.lower_corner[0])
self._min_y = min(self._min_y, surface.lower_corner[1]) self._min_y = min(self._min_y, surface.lower_corner[1])
self._min_z = min(self._min_z, surface.lower_corner[2]) self._min_z = min(self._min_z, surface.lower_corner[2])
self._max_x = max(self._max_x, surface.upper_corner[0])
self._max_y = max(self._max_y, surface.upper_corner[1])
self._max_z = max(self._max_z, surface.upper_corner[2])
surface.id = surface_id surface.id = surface_id
if surface.type == cte.GROUND: if surface.type == cte.GROUND:
self._grounds.append(surface) self._grounds.append(surface)
@ -86,7 +89,7 @@ class Building(CityObject):
elif surface.type == cte.INTERIOR_SLAB: elif surface.type == cte.INTERIOR_SLAB:
self._interior_slabs.append(surface) self._interior_slabs.append(surface)
else: else:
logging.error(f'Building %s [%s] has an unexpected surface type %s.', self.name, self.aliases, surface.type) logging.error('Building %s [%s] has an unexpected surface type %s.', self.name, self.aliases, surface.type)
@property @property
def shell(self) -> Polyhedron: def shell(self) -> Polyhedron:
@ -681,11 +684,17 @@ class Building(CityObject):
for i, value in enumerate(item): for i, value in enumerate(item):
_working_hours[key][i] = max(_working_hours[key][i], saved_values[i]) _working_hours[key][i] = max(_working_hours[key][i], saved_values[i])
_total_hours = 0 working_hours = {}
values_months = []
for month in cte.WEEK_DAYS_A_MONTH.keys():
_total_hours_month = 0
for key in _working_hours: for key in _working_hours:
hours = sum(_working_hours[key]) hours = sum(_working_hours[key])
_total_hours += hours * cte.WEEK_DAYS_A_YEAR[key] _total_hours_month += hours * cte.WEEK_DAYS_A_MONTH[month][key]
return _total_hours values_months.append(_total_hours_month)
working_hours[cte.MONTH] = values_months
working_hours[cte.YEAR] = sum(working_hours[cte.MONTH])
return working_hours
@property @property
def distribution_systems_electrical_consumption(self): def distribution_systems_electrical_consumption(self):
@ -735,7 +744,7 @@ class Building(CityObject):
for key, item in self._distribution_systems_electrical_consumption.items(): for key, item in self._distribution_systems_electrical_consumption.items():
for i in range(0, len(item)): for i in range(0, len(item)):
self._distribution_systems_electrical_consumption[key][i] += _peak_load * _consumption_fix_flow \ self._distribution_systems_electrical_consumption[key][i] += _peak_load * _consumption_fix_flow \
* _working_hours * _working_hours[key] * cte.WATTS_HOUR_TO_JULES
return self._distribution_systems_electrical_consumption return self._distribution_systems_electrical_consumption
def _calculate_consumption(self, consumption_type, demand): def _calculate_consumption(self, consumption_type, demand):

View File

@ -59,6 +59,7 @@ class Layer:
Get material name Get material name
:return: str :return: str
""" """
# todo: this should be named material_name instead
return self._name return self._name
@name.setter @name.setter
@ -67,6 +68,7 @@ class Layer:
Set material name Set material name
:param value: string :param value: string
""" """
# todo: this should be named material_name instead
self._name = str(value) self._name = str(value)
@property @property

View File

@ -154,7 +154,6 @@ class Surface:
if self._inclination is None: if self._inclination is None:
self._inclination = np.arccos(self.perimeter_polygon.normal[2]) self._inclination = np.arccos(self.perimeter_polygon.normal[2])
return self._inclination return self._inclination
@property @property
def type(self): def type(self):
""" """

View File

@ -578,7 +578,7 @@ class ThermalZone:
for i_type, _ in enumerate(_types_reference): for i_type, _ in enumerate(_types_reference):
_schedules = [] _schedules = []
_schedule_type = _types_reference[i_type][1] _schedule_type = _types_reference[i_type][1]
for i_schedule, schedule_value in enumerate(_schedule_type): for _, schedule_value in enumerate(_schedule_type):
schedule = Schedule() schedule = Schedule()
schedule.type = schedule_value.type schedule.type = schedule_value.type
schedule.day_types = schedule_value.day_types schedule.day_types = schedule_value.day_types

View File

@ -14,6 +14,7 @@ import math
import pickle import pickle
import sys import sys
import pathlib import pathlib
import os
from pathlib import Path from pathlib import Path
from typing import List, Union from typing import List, Union
@ -299,6 +300,20 @@ class City:
with open(city_filename, 'rb') as file: with open(city_filename, 'rb') as file:
return pickle.load(file) return pickle.load(file)
@staticmethod
def load_compressed(compressed_city_filename, destination_filename) -> City:
"""
Load a city from compressed_city_filename
:param compressed_city_filename: Compressed pickle as source
:param destination_filename: Pickle file as destination
:return: City
"""
with open(str(compressed_city_filename), 'rb') as source, open(str(destination_filename), 'wb') as destination:
destination.write(bz2.decompress(source.read()))
loaded_city = City.load(destination_filename)
os.unlink(destination_filename)
return loaded_city
def save(self, city_filename): def save(self, city_filename):
""" """
Save a city into the given filename Save a city into the given filename

View File

@ -13,6 +13,9 @@ from hub.city_model_structure.energy_systems.generic_storage_system import Gener
class ElectricalStorageSystem: class ElectricalStorageSystem:
"""
Electrical Storage system class
"""
def __init__(self): def __init__(self):
self._model_name = None self._model_name = None
self._manufacturer = None self._manufacturer = None
@ -150,6 +153,3 @@ class ElectricalStorageSystem:
:return: float :return: float
""" """
self._self_discharge_rate = value self._self_discharge_rate = value

View File

@ -10,6 +10,9 @@ from __future__ import annotations
class GenericStorageSystem: class GenericStorageSystem:
"""
Generic storage System class
"""
def __init__(self): def __init__(self):
self._storage_type = None self._storage_type = None
self._nominal_capacity = None self._nominal_capacity = None
@ -62,4 +65,3 @@ class GenericStorageSystem:
:return: float :return: float
""" """
self._losses_ratio = value self._losses_ratio = value

View File

@ -101,5 +101,3 @@ class PerformanceCurves:
:return: [coefficients] :return: [coefficients]
""" """
self._coefficients = value self._coefficients = value

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -4,9 +4,10 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group Copyright © 2022 Concordia CERC group
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
from pathlib import Path from pathlib import Path
import numpy as np
class Obj: class Obj:
""" """
@ -17,41 +18,79 @@ class Obj:
self._path = path self._path = path
self._export() self._export()
def _to_vertex(self, coordinate): def _ground(self, coordinate):
x = coordinate[0] - self._city.lower_corner[0] x = coordinate[0] - self._city.lower_corner[0]
y = coordinate[1] - self._city.lower_corner[1] y = coordinate[1] - self._city.lower_corner[1]
z = coordinate[2] - self._city.lower_corner[2] z = coordinate[2] - self._city.lower_corner[2]
return f'v {x} {y} {z}\n' return x, y, z
def _to_vertex(self, coordinate):
x, y, z = self._ground(coordinate)
return f'v {x} {z} {y}\n'
def _to_texture_vertex(self, coordinate):
u, v, _ = self._ground(coordinate)
return f'vt {u} {v}\n'
def _to_normal_vertex(self, coordinates):
ground_vertex = []
for coordinate in coordinates:
x, y, z = self._ground(coordinate)
ground_vertex.append(np.array([x, y, z]))
# recalculate the normal to get grounded values
edge_1 = ground_vertex[1] - ground_vertex[0]
edge_2 = ground_vertex[2] - ground_vertex[0]
normal = np.cross(edge_1, edge_2)
normal = normal / np.linalg.norm(normal)
return f'vn {normal[0]} {normal[1]} {normal[2]}\n'
def _export(self): def _export(self):
if self._city.name is None: if self._city.name is None:
self._city.name = 'unknown_city' self._city.name = 'unknown_city'
file_name = self._city.name + '.obj' obj_name = f'{self._city.name}.obj'
file_path = (Path(self._path).resolve() / file_name).resolve() mtl_name = f'{self._city.name}.mtl'
obj_file_path = (Path(self._path).resolve() / obj_name).resolve()
mtl_file_path = (Path(self._path).resolve() / mtl_name).resolve()
with open(mtl_file_path, 'w', encoding='utf-8') as mtl:
mtl.write("newmtl cerc_base_material\n")
mtl.write("Ka 1.0 1.0 1.0 # Ambient color (white)\n")
mtl.write("Kd 0.3 0.8 0.3 # Diffuse color (greenish)\n")
mtl.write("Ks 1.0 1.0 1.0 # Specular color (white)\n")
mtl.write("Ns 400.0 # Specular exponent (defines shininess)\n")
vertices = {} vertices = {}
with open(file_path, 'w', encoding='utf-8') as obj:
obj.write("# cerc-hub export\n")
vertex_index = 0
faces = [] faces = []
vertex_index = 0
normal_index = 0
with open(obj_file_path, 'w', encoding='utf-8') as obj:
obj.write("# cerc-hub export\n")
obj.write(f'mtllib {mtl_name}')
for building in self._city.buildings: for building in self._city.buildings:
obj.write(f'# building {building.name}\n') obj.write(f'# building {building.name}\n')
obj.write(f'g {building.name}\n') obj.write(f'g {building.name}\n')
obj.write('s off\n') obj.write('s off\n')
for surface in building.surfaces: for surface in building.surfaces:
obj.write(f'# surface {surface.name}\n') obj.write(f'# surface {surface.name}\n')
face = 'f ' face = []
normal = self._to_normal_vertex(surface.perimeter_polygon.coordinates)
normal_index += 1
textures = []
for coordinate in surface.perimeter_polygon.coordinates: for coordinate in surface.perimeter_polygon.coordinates:
vertex = self._to_vertex(coordinate) vertex = self._to_vertex(coordinate)
if vertex not in vertices: if vertex not in vertices:
vertex_index += 1 vertex_index += 1
vertices[vertex] = vertex_index vertices[vertex] = vertex_index
current = vertex_index current = vertex_index
obj.write(vertex) obj.write(vertex)
textures.append(self._to_texture_vertex(coordinate)) # only append if non-existing
else: else:
current = vertices[vertex] current = vertices[vertex]
face = f'{face} {current}' face.insert(0, f'{current}/{current}/{normal_index}') # insert counterclockwise
obj.writelines(normal) # add the normal
obj.writelines(textures) # add the texture vertex
faces.append(f'{face} {face.split(" ")[1]}\n') faces.append(f"f {' '.join(face)}\n")
obj.writelines(faces) obj.writelines(faces)
faces = [] faces = []

View File

@ -49,36 +49,140 @@ WEEK_DAYS = 'Weekdays'
WEEK_ENDS = 'Weekends' WEEK_ENDS = 'Weekends'
ALL_DAYS = 'Alldays' ALL_DAYS = 'Alldays'
WEEK_DAYS_A_MONTH = {'monday': [5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 5], JANUARY = 'January'
'tuesday': [5, 4, 4, 4, 5, 4, 5, 4, 4, 5, 4, 4], FEBRUARY = 'February'
'wednesday': [5, 4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4], MARCH = 'March'
'thursday': [4, 4, 5, 4, 5, 4, 4, 5, 4, 4, 5, 4], APRIL = 'April'
'friday': [4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5, 4], MAY = 'May'
'saturday': [4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 4, 5], JUNE = 'June'
'sunday': [4, 4, 4, 5, 4, 4, 5, 4, 5, 4, 4, 5], JULY = 'July'
'holiday': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} AUGUST = 'August'
SEPTEMBER = 'September'
OCTOBER = 'October'
NOVEMBER = 'November'
DECEMBER = 'December'
WEEK_DAYS_A_YEAR = {'monday': 51, MONTHS = [JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER]
'tuesday': 50,
'wednesday': 50,
'thursday': 50,
'friday': 50,
'saturday': 52,
'sunday': 52,
'holiday': 10}
DAYS_A_MONTH = {'January': 31, WEEK_DAYS_A_MONTH = {JANUARY: {MONDAY: 5,
'February': 28, TUESDAY: 5,
'March': 31, WEDNESDAY: 5,
'April': 30, THURSDAY: 4,
'May': 31, FRIDAY: 4,
'June': 30, SATURDAY: 4,
'July': 31, SUNDAY: 4,
'August': 31, HOLIDAY: 0},
'September': 30, FEBRUARY: {MONDAY: 4,
'October': 31, TUESDAY: 4,
'November': 30, WEDNESDAY: 4,
'December': 31} THURSDAY: 4,
FRIDAY: 4,
SATURDAY: 4,
SUNDAY: 4,
HOLIDAY: 0},
MARCH: {MONDAY: 4,
TUESDAY: 4,
WEDNESDAY: 4,
THURSDAY: 5,
FRIDAY: 5,
SATURDAY: 5,
SUNDAY: 4,
HOLIDAY: 0},
APRIL: {MONDAY: 5,
TUESDAY: 4,
WEDNESDAY: 4,
THURSDAY: 4,
FRIDAY: 4,
SATURDAY: 4,
SUNDAY: 5,
HOLIDAY: 0},
MAY: {MONDAY: 4,
TUESDAY: 5,
WEDNESDAY: 5,
THURSDAY: 5,
FRIDAY: 4,
SATURDAY: 4,
SUNDAY: 4,
HOLIDAY: 0},
JUNE: {MONDAY: 4,
TUESDAY: 4,
WEDNESDAY: 4,
THURSDAY: 4,
FRIDAY: 5,
SATURDAY: 5,
SUNDAY: 4,
HOLIDAY: 0},
JULY: {MONDAY: 5,
TUESDAY: 5,
WEDNESDAY: 4,
THURSDAY: 4,
FRIDAY: 4,
SATURDAY: 4,
SUNDAY: 5,
HOLIDAY: 0},
AUGUST: {MONDAY: 4,
TUESDAY: 4,
WEDNESDAY: 5,
THURSDAY: 5,
FRIDAY: 5,
SATURDAY: 4,
SUNDAY: 4,
HOLIDAY: 0},
SEPTEMBER: {MONDAY: 4,
TUESDAY: 4,
WEDNESDAY: 4,
THURSDAY: 4,
FRIDAY: 4,
SATURDAY: 5,
SUNDAY: 5,
HOLIDAY: 0},
OCTOBER: {MONDAY: 5,
TUESDAY: 5,
WEDNESDAY: 5,
THURSDAY: 4,
FRIDAY: 4,
SATURDAY: 4,
SUNDAY: 4,
HOLIDAY: 0},
NOVEMBER: {MONDAY: 4,
TUESDAY: 4,
WEDNESDAY: 4,
THURSDAY: 5,
FRIDAY: 5,
SATURDAY: 4,
SUNDAY: 4,
HOLIDAY: 0},
DECEMBER: {MONDAY: 5,
TUESDAY: 4,
WEDNESDAY: 4,
THURSDAY: 4,
FRIDAY: 4,
SATURDAY: 5,
SUNDAY: 5,
HOLIDAY: 0},
}
WEEK_DAYS_A_YEAR = {MONDAY: 51,
TUESDAY: 50,
WEDNESDAY: 50,
THURSDAY: 50,
FRIDAY: 50,
SATURDAY: 52,
SUNDAY: 52,
HOLIDAY: 10}
DAYS_A_MONTH = {JANUARY: 31,
FEBRUARY: 28,
MARCH: 31,
APRIL: 30,
MAY: 31,
JUNE: 30,
JULY: 31,
AUGUST: 31,
SEPTEMBER: 30,
OCTOBER: 31,
NOVEMBER: 30,
DECEMBER: 31}
# data types # data types
ANY_NUMBER = 'any_number' ANY_NUMBER = 'any_number'

View File

@ -16,7 +16,9 @@ class HubFunctionToEilatConstructionFunction:
self._dictionary = { self._dictionary = {
cte.RESIDENTIAL: 'Residential_building', cte.RESIDENTIAL: 'Residential_building',
cte.HOTEL: 'Residential_building', cte.HOTEL: 'Residential_building',
cte.DORMITORY: 'Residential_building' cte.DORMITORY: 'Residential_building',
cte.DATACENTER: 'n/a',
cte.FARM: 'n/a'
} }
@property @property

View File

@ -73,7 +73,9 @@ class HubFunctionToMontrealCustomCostsFunction:
cte.AUTOMOTIVE_FACILITY: 'non-residential', cte.AUTOMOTIVE_FACILITY: 'non-residential',
cte.PARKING_GARAGE: 'non-residential', cte.PARKING_GARAGE: 'non-residential',
cte.RELIGIOUS: 'non-residential', cte.RELIGIOUS: 'non-residential',
cte.NON_HEATED: 'non-residential' cte.NON_HEATED: 'non-residential',
cte.DATACENTER: 'n/a',
cte.FARM: 'n/a'
} }
@property @property

View File

@ -72,7 +72,9 @@ class HubFunctionToNrcanConstructionFunction:
cte.AUTOMOTIVE_FACILITY: 'n/a', cte.AUTOMOTIVE_FACILITY: 'n/a',
cte.PARKING_GARAGE: 'n/a', cte.PARKING_GARAGE: 'n/a',
cte.RELIGIOUS: 'n/a', cte.RELIGIOUS: 'n/a',
cte.NON_HEATED: 'n/a' cte.NON_HEATED: 'n/a',
cte.DATACENTER: 'n/a',
cte.FARM: 'n/a'
} }
@property @property

View File

@ -73,7 +73,9 @@ class HubFunctionToNrelConstructionFunction:
cte.AUTOMOTIVE_FACILITY: 'n/a', cte.AUTOMOTIVE_FACILITY: 'n/a',
cte.PARKING_GARAGE: 'n/a', cte.PARKING_GARAGE: 'n/a',
cte.RELIGIOUS: 'n/a', cte.RELIGIOUS: 'n/a',
cte.NON_HEATED: 'n/a' cte.NON_HEATED: 'n/a',
cte.DATACENTER: 'n/a',
cte.FARM: 'n/a'
} }
@property @property

View File

@ -76,7 +76,6 @@ class HubUsageToNrcanUsage:
cte.NON_HEATED: 'n/a', cte.NON_HEATED: 'n/a',
cte.DATACENTER: 'n/a', cte.DATACENTER: 'n/a',
cte.FARM: 'n/a' cte.FARM: 'n/a'
} }
@property @property

View File

@ -32,7 +32,7 @@ class EilatPhysicsParameters:
city = self._city city = self._city
eilat_catalog = ConstructionCatalogFactory('eilat').catalog eilat_catalog = ConstructionCatalogFactory('eilat').catalog
for building in city.buildings: for building in city.buildings:
if building.function not in Dictionaries().hub_function_to_eilat_construction_function.keys(): if building.function not in Dictionaries().hub_function_to_eilat_construction_function:
logging.error('Building %s has an unknown building function %s', building.name, building.function) logging.error('Building %s has an unknown building function %s', building.name, building.function)
continue continue
function = Dictionaries().hub_function_to_eilat_construction_function[building.function] function = Dictionaries().hub_function_to_eilat_construction_function[building.function]

View File

@ -32,8 +32,8 @@ class NrcanPhysicsParameters:
city = self._city city = self._city
nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog nrcan_catalog = ConstructionCatalogFactory('nrcan').catalog
for building in city.buildings: for building in city.buildings:
if building.function not in Dictionaries().hub_function_to_nrcan_construction_function.keys(): if building.function not in Dictionaries().hub_function_to_nrcan_construction_function:
logging.error(f'Building %s has an unknown building function %s', building.name, building.function) logging.error('Building %s has an unknown building function %s', building.name, building.function)
continue continue
function = Dictionaries().hub_function_to_nrcan_construction_function[building.function] function = Dictionaries().hub_function_to_nrcan_construction_function[building.function]
try: try:

View File

@ -6,21 +6,20 @@ Project Coder Saeed Ranjbar saeed.ranjbar@concordia.ca
Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
import logging
import copy import copy
import logging
from pandas import DataFrame from pandas import DataFrame
from hub.catalog_factories.energy_systems_catalog_factory import EnergySystemsCatalogFactory from hub.catalog_factories.energy_systems_catalog_factory import EnergySystemsCatalogFactory
from hub.city_model_structure.energy_systems.generic_energy_system import GenericEnergySystem
from hub.city_model_structure.energy_systems.generic_generation_system import GenericGenerationSystem
from hub.city_model_structure.energy_systems.energy_system import EnergySystem
from hub.city_model_structure.energy_systems.generation_system import GenerationSystem
from hub.city_model_structure.energy_systems.distribution_system import DistributionSystem from hub.city_model_structure.energy_systems.distribution_system import DistributionSystem
from hub.city_model_structure.energy_systems.emission_system import EmissionSystem from hub.city_model_structure.energy_systems.emission_system import EmissionSystem
from hub.helpers.dictionaries import Dictionaries from hub.city_model_structure.energy_systems.energy_system import EnergySystem
from hub.city_model_structure.energy_systems.generic_storage_system import GenericStorageSystem from hub.city_model_structure.energy_systems.generation_system import GenerationSystem
from hub.city_model_structure.energy_systems.generic_energy_system import GenericEnergySystem
from hub.city_model_structure.energy_systems.generic_generation_system import GenericGenerationSystem
from hub.city_model_structure.energy_systems.thermal_storage_system import ThermalStorageSystem from hub.city_model_structure.energy_systems.thermal_storage_system import ThermalStorageSystem
from hub.helpers.dictionaries import Dictionaries
class NorthAmericaCustomEnergySystemParameters: class NorthAmericaCustomEnergySystemParameters:
@ -83,7 +82,7 @@ class NorthAmericaCustomEnergySystemParameters:
energy_system = GenericEnergySystem() energy_system = GenericEnergySystem()
_hub_demand_types = [] _hub_demand_types = []
demand_types = system.demand_types demand_types = system.demand_types
if type(demand_types) == str: if isinstance(demand_types, str):
demand_types = [demand_types] demand_types = [demand_types]
for demand_type in demand_types: for demand_type in demand_types:
_hub_demand_types.append(Dictionaries().north_america_demand_type_to_hub_energy_demand_type[demand_type]) _hub_demand_types.append(Dictionaries().north_america_demand_type_to_hub_energy_demand_type[demand_type])
@ -105,17 +104,17 @@ class NorthAmericaCustomEnergySystemParameters:
_generation_system.source_mass_flow = archetype_generation_equipment.source_mass_flow _generation_system.source_mass_flow = archetype_generation_equipment.source_mass_flow
_generation_system.storage = None _generation_system.storage = None
_generation_system.auxiliary_equipment = None _generation_system.auxiliary_equipment = None
_generation_system._supply_medium = archetype_generation_equipment.supply_medium _generation_system.supply_medium = archetype_generation_equipment.supply_medium
_generation_system._maximum_heat_supply_temperature = archetype_generation_equipment.maximum_heat_supply_temperature _generation_system.maximum_heat_supply_temperature = archetype_generation_equipment.maximum_heat_supply_temperature
_generation_system._minimum_heat_supply_temperature = archetype_generation_equipment.minimum_heat_supply_temperature _generation_system.minimum_heat_supply_temperature = archetype_generation_equipment.minimum_heat_supply_temperature
_generation_system._maximum_cooling_supply_temperature = archetype_generation_equipment.maximum_cooling_supply_temperature _generation_system.maximum_cooling_supply_temperature = archetype_generation_equipment.maximum_cooling_supply_temperature
_generation_system._minimum_cooling_supply_temperature = archetype_generation_equipment.minimum_cooling_supply_temperature _generation_system.minimum_cooling_supply_temperature = archetype_generation_equipment.minimum_cooling_supply_temperature
_generation_system._heat_output_curve = archetype_generation_equipment.heat_output_curve _generation_system.heat_output_curve = archetype_generation_equipment.heat_output_curve
_generation_system._heat_fuel_consumption_curve = archetype_generation_equipment.heat_fuel_consumption_curve _generation_system.heat_fuel_consumption_curve = archetype_generation_equipment.heat_fuel_consumption_curve
_generation_system._heat_efficiency_curve = archetype_generation_equipment.heat_efficiency_curve _generation_system.heat_efficiency_curve = archetype_generation_equipment.heat_efficiency_curve
_generation_system._cooling_output_curve = archetype_generation_equipment.cooling_output_curve _generation_system.cooling_output_curve = archetype_generation_equipment.cooling_output_curve
_generation_system._cooling_fuel_consumption_curve = archetype_generation_equipment.cooling_fuel_consumption_curve _generation_system.cooling_fuel_consumption_curve = archetype_generation_equipment.cooling_fuel_consumption_curve
_generation_system._cooling_efficiency_curve = archetype_generation_equipment.cooling_efficiency_curve _generation_system.cooling_efficiency_curve = archetype_generation_equipment.cooling_efficiency_curve
_generation_systems.append(_generation_system) _generation_systems.append(_generation_system)
energy_system.generation_systems = _generation_systems energy_system.generation_systems = _generation_systems

View File

@ -116,6 +116,7 @@ class Geojson:
if self._extrusion_height_field is not None: if self._extrusion_height_field is not None:
extrusion_height = float(feature['properties'][self._extrusion_height_field]) extrusion_height = float(feature['properties'][self._extrusion_height_field])
lod = 1 lod = 1
self._max_z = max(self._max_z, extrusion_height)
year_of_construction = None year_of_construction = None
if self._year_of_construction_field is not None: if self._year_of_construction_field is not None:
year_of_construction = int(feature['properties'][self._year_of_construction_field]) year_of_construction = int(feature['properties'][self._year_of_construction_field])

View File

@ -6,13 +6,16 @@ Project Coder Saeed Ranjbar saeed.ranjbar@concordia.ca
Project collaborator Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca Project collaborator Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
""" """
from pathlib import Path from pathlib import Path
from hub.helpers.monthly_values import MonthlyValues
import csv import csv
from hub.helpers.monthly_values import MonthlyValues
import hub.helpers.constants as cte import hub.helpers.constants as cte
class EnergyPlusWorkflow: class EnergyPlus:
"""
Energy plus class
"""
def __init__(self, city, base_path): def __init__(self, city, base_path):
self._city = city self._city = city
self._base_path = base_path self._base_path = base_path

View File

@ -59,7 +59,7 @@ class InselMonthlyEnergyBalance:
lighting_density = thermal_zone.lighting.density lighting_density = thermal_zone.lighting.density
appliances_density = thermal_zone.appliances.density appliances_density = thermal_zone.appliances.density
for month in range(0, 12): for i_month, month in enumerate(cte.MONTHS):
total_dhw_demand = 0 total_dhw_demand = 0
total_lighting = 0 total_lighting = 0
total_appliances = 0 total_appliances = 0
@ -69,7 +69,7 @@ class InselMonthlyEnergyBalance:
for value in schedule.values: for value in schedule.values:
total_day += value total_day += value
for day_type in schedule.day_types: for day_type in schedule.day_types:
total_lighting += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] \ total_lighting += total_day * cte.WEEK_DAYS_A_MONTH[month][day_type] \
* lighting_density / cte.WATTS_HOUR_TO_JULES * lighting_density / cte.WATTS_HOUR_TO_JULES
lighting_demand.append(total_lighting * area) lighting_demand.append(total_lighting * area)
@ -78,7 +78,7 @@ class InselMonthlyEnergyBalance:
for value in schedule.values: for value in schedule.values:
total_day += value total_day += value
for day_type in schedule.day_types: for day_type in schedule.day_types:
total_appliances += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] \ total_appliances += total_day * cte.WEEK_DAYS_A_MONTH[month][day_type] \
* appliances_density / cte.WATTS_HOUR_TO_JULES * appliances_density / cte.WATTS_HOUR_TO_JULES
appliances_demand.append(total_appliances * area) appliances_demand.append(total_appliances * area)
@ -89,9 +89,9 @@ class InselMonthlyEnergyBalance:
for day_type in schedule.day_types: for day_type in schedule.day_types:
demand = ( demand = (
peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY
* (service_temperature - cold_water[month]) / cte.WATTS_HOUR_TO_JULES * (service_temperature - cold_water[i_month]) / cte.WATTS_HOUR_TO_JULES
) )
total_dhw_demand += total_day * cte.WEEK_DAYS_A_MONTH[day_type][month] * demand total_dhw_demand += total_day * cte.WEEK_DAYS_A_MONTH[month][day_type] * demand
domestic_hot_water_demand.append(total_dhw_demand * area) domestic_hot_water_demand.append(total_dhw_demand * area)
except AttributeError: except AttributeError:
domestic_hot_water_demand = [0] * 12 domestic_hot_water_demand = [0] * 12

View File

@ -10,7 +10,7 @@ from pathlib import Path
from hub.helpers.utils import validate_import_export_type from hub.helpers.utils import validate_import_export_type
from hub.imports.results.insel_monthly_energry_balance import InselMonthlyEnergyBalance from hub.imports.results.insel_monthly_energry_balance import InselMonthlyEnergyBalance
from hub.imports.results.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm from hub.imports.results.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm
from hub.imports.results.energy_plus_workflow import EnergyPlusWorkflow from hub.imports.results.energy_plus import EnergyPlusWorkflow
class ResultFactory: class ResultFactory:
""" """

View File

@ -7,7 +7,7 @@ Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
import datetime import datetime
import logging import logging
from sqlalchemy import select, or_ from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session from sqlalchemy.orm import Session

View File

@ -1,4 +1,4 @@
""" """
Hub version number Hub version number
""" """
__version__ = '0.1.8.10' __version__ = '0.1.8.11'

View File

@ -18,16 +18,14 @@ with open(version) as f:
exec(f.read(), main_ns) exec(f.read(), main_ns)
setup( setup(
name='cerc-hub', name='cerc-hub',
version=main_ns['__version__'], version=main_ns['__version__'],
description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help researchers " description="CERC Hub consist of a set of classes (Central data model), importers and exporters to help researchers "
"to create better and sustainable cities", "to create better and more sustainable cities",
long_description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help " long_description="CERC Hub consist of a set of classes (Central data model), importers and exporters to help "
"researchers to create better and sustainable cities.\n\nDevelop at Concordia university in canada " "researchers to create better and more sustainable cities.\n\nDeveloped at Concordia university in Canada "
"as part of the research group from the next generation cities institute our aim among others it's " "as part of the research group from the Next Generation Cities Institute, our aim among others is "
"to provide a comprehensive set of tools to help researchers and urban developers to make decisions " "to provide a comprehensive set of tools to help researchers and urban developers to make decisions "
"to improve the livability and efficiency of our cities", "to improve the livability and efficiency of our cities",
classifiers=[ classifiers=[
@ -88,7 +86,8 @@ setup(
data_files=[ data_files=[
('hub', glob.glob('requirements.txt')), ('hub', glob.glob('requirements.txt')),
('hub/config', glob.glob('hub/config/*.ini')), ('hub/config', glob.glob('hub/config/*.ini')),
('hub/catalog_factories/greenery/ecore_greenery', glob.glob('hub/catalog_factories/greenery/ecore_greenery/*.ecore')), ('hub/catalog_factories/greenery/ecore_greenery',
glob.glob('hub/catalog_factories/greenery/ecore_greenery/*.ecore')),
('hub/data/construction', glob.glob('hub/data/construction/*')), ('hub/data/construction', glob.glob('hub/data/construction/*')),
('hub/data/costs', glob.glob('hub/data/costs/montreal_costs.xml')), ('hub/data/costs', glob.glob('hub/data/costs/montreal_costs.xml')),
('hub/data/customized_imports', glob.glob('hub/data/customized_imports/ashrae_archetypes.xml')), ('hub/data/customized_imports', glob.glob('hub/data/customized_imports/ashrae_archetypes.xml')),

View File

@ -66,12 +66,7 @@ class TestExports(TestCase):
def _export(self, export_type, from_pickle=False): def _export(self, export_type, from_pickle=False):
self._complete_city = self._get_complete_city(from_pickle) self._complete_city = self._get_complete_city(from_pickle)
try:
ExportsFactory(export_type, self._complete_city, self._output_path).export() ExportsFactory(export_type, self._complete_city, self._output_path).export()
except ValueError as err:
if export_type != 'stl':
logging.warning('No backend export for STL test, skipped')
raise err
def _export_building_energy(self, export_type, from_pickle=False): def _export_building_energy(self, export_type, from_pickle=False):
self._complete_city = self._get_complete_city(from_pickle) self._complete_city = self._get_complete_city(from_pickle)
@ -83,12 +78,6 @@ class TestExports(TestCase):
""" """
self._export('obj', False) self._export('obj', False)
def test_stl_export(self):
"""
export to stl
"""
self._export('stl', False)
def test_energy_ade_export(self): def test_energy_ade_export(self):
""" """
export to energy ADE export to energy ADE

View File

@ -40,7 +40,7 @@ class TestResultsImport(TestCase):
function_to_hub=Dictionaries().montreal_function_to_hub_function).city function_to_hub=Dictionaries().montreal_function_to_hub_function).city
ConstructionFactory('nrcan', self._city).enrich() ConstructionFactory('nrcan', self._city).enrich()
UsageFactory('nrcan', self._city).enrich() UsageFactory('comnet', self._city).enrich()
def test_sra_import(self): def test_sra_import(self):
ExportsFactory('sra', self._city, self._output_path).export() ExportsFactory('sra', self._city, self._output_path).export()