partial implementation of trnsys export
This commit is contained in:
parent
0015a3efd7
commit
39951a76a9
|
@ -359,6 +359,8 @@ class City:
|
|||
Get city latitude in degrees
|
||||
:return: None or float
|
||||
"""
|
||||
if self._latitude is None:
|
||||
return self._get_location().climate_reference_city_latitude
|
||||
return self._latitude
|
||||
|
||||
@latitude.setter
|
||||
|
@ -376,6 +378,8 @@ class City:
|
|||
Get city longitude in degrees
|
||||
:return: None or float
|
||||
"""
|
||||
if self._longitude is None:
|
||||
return self._get_location().climate_reference_city_longitude
|
||||
return self._longitude
|
||||
|
||||
@longitude.setter
|
||||
|
|
|
@ -4,9 +4,18 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
"""
|
||||
|
||||
import json
|
||||
import math
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from urllib.error import URLError
|
||||
from urllib.request import urlopen
|
||||
|
||||
import pytz
|
||||
from timezonefinder import TimezoneFinder
|
||||
|
||||
from hub.version import __version__
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
|
||||
class Trnsys:
|
||||
|
@ -18,6 +27,8 @@ class Trnsys:
|
|||
self._city = city
|
||||
self._path = path
|
||||
self._buildings = self._city.buildings
|
||||
self._tf = TimezoneFinder()
|
||||
|
||||
if target_buildings is not None:
|
||||
buildings = []
|
||||
for building in target_buildings:
|
||||
|
@ -32,9 +43,9 @@ class Trnsys:
|
|||
f.write('***************************************\n')
|
||||
f.write('* Building descriptions file TRNSYS\n')
|
||||
location = (
|
||||
self._city.location.climate_reference_city_latitude, self._city.location.climate_reference_city_longitude
|
||||
self._city.latitude, self._city.longitude
|
||||
)
|
||||
f.write(f'* Export: {self._city.location.city} {self._city.location.country} {location}')
|
||||
f.write(f'* Export: {self._city.location.city} {self._city.location.country} {location}\n')
|
||||
f.write(f'* For building: {building.name}')
|
||||
if building.aliases is not None:
|
||||
f.write(f' {building.aliases})')
|
||||
|
@ -43,8 +54,19 @@ class Trnsys:
|
|||
f.write(f'* Year build: {building.year_of_construction}\n')
|
||||
f.write('***************************************\n')
|
||||
|
||||
@staticmethod
|
||||
def _properties(f):
|
||||
def _properties(self, f):
|
||||
latitude = self._city.latitude
|
||||
longitude = self._city.longitude
|
||||
utc_offset = datetime.now(
|
||||
pytz.timezone(self._tf.timezone_at(lng=longitude, lat=latitude))
|
||||
).utcoffset().total_seconds()/60/60
|
||||
elevation = 200
|
||||
try:
|
||||
elevation = json.loads(
|
||||
urlopen(f'https://api.open-elevation.com/api/v1/lookup?locations={latitude},{longitude}').read()
|
||||
)['results'][0]['elevation']
|
||||
except URLError:
|
||||
pass
|
||||
f.write('***************************************\n')
|
||||
f.write(f'* Properties\n')
|
||||
f.write('***************************************\n')
|
||||
|
@ -57,7 +79,7 @@ class Trnsys:
|
|||
f.write(' KVERTICAL=5.76 : EVERTICAL=0.3\n')
|
||||
f.write('* Radiance parameters\n')
|
||||
f.write(' SCENE_ROTATION_ANGLE=0 : GROUND_IDS= : GROUND_REFLECTANCE=0.2 : SHADER_REFLECTANCE=0\n')
|
||||
f.write(' CALC_MODE=RAD : LATITUDE=48 : LONGITUDE=-9.2 : TIME_ZONE=-15 : SITE_ELEVATION=200\n')
|
||||
f.write(f' CALC_MODE=RAD : LATITUDE={latitude} : LONGITUDE={longitude} : TIME_ZONE={utc_offset} : SITE_ELEVATION={elevation}\n')
|
||||
f.write(' AB=5 : AD=1000 : AS=20 : AR=300 : AA=0.1\n')
|
||||
f.write(' LR=6 : ST=0.15 : SJ=1 : LW=0.004 : DJ=0 : DS=0.2 : DR=2 : DP=512\n')
|
||||
f.write('* Comfort parameters\n')
|
||||
|
@ -75,15 +97,27 @@ class Trnsys:
|
|||
f.write(f'* Layers\n')
|
||||
f.write('***************************************\n')
|
||||
layers = {}
|
||||
|
||||
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
for layer in thermal_boundary.layers:
|
||||
capacity = 0
|
||||
conductivity = 0
|
||||
density = 0
|
||||
if layer.thermal_absorptance is not None:
|
||||
capacity = layer.thermal_absorptance
|
||||
if layer.conductivity is not None:
|
||||
conductivity = layer.conductivity
|
||||
if layer.density is not None:
|
||||
density = layer.density
|
||||
|
||||
|
||||
layers[layer.material_name] = {
|
||||
'conductivity': layer.conductivity,
|
||||
'capacity': '1', # todo: ask oriol about this
|
||||
'density': layer.density,
|
||||
'pert': '0', # todo: ask oriol about this
|
||||
'penrt': '0', # todo: ask oriol about this
|
||||
'conductivity': conductivity,
|
||||
'capacity': capacity, # todo: transform units
|
||||
'density': density,
|
||||
'pert': '0',
|
||||
'penrt': '0'
|
||||
}
|
||||
f.write('PROPERTIES\n')
|
||||
for layer_name, values in layers.items():
|
||||
|
@ -92,31 +126,41 @@ class Trnsys:
|
|||
f.write(f'{attribute.upper()}=\t{value}\t')
|
||||
f.write('\n')
|
||||
|
||||
@staticmethod
|
||||
def _inputs(f):
|
||||
f.write('***************************************\n')
|
||||
f.write(f'* Inputs\n')
|
||||
f.write('***************************************\n')
|
||||
f.write('INPUTS TGROUND TBOUNDARY SHADE_CLOSE SHADE_OPEN MAX_ISHADE MAX_ESHADE\n')
|
||||
f.write('INPUTS_DESCRIPTION\n')
|
||||
f.write('TGROUND : C : Ground Temperature (boundary temperature used for floors adjacent to the ground)\n')
|
||||
f.write('TBOUNDARY : C : Boundary Temperature (boundary temperature used for boundary floors, walls, ceilings)\n')
|
||||
f.write('SHADE_CLOSE : kJ/hr.m^2 : threshold of total radiation on facade where shading device is activated\n')
|
||||
f.write('SHADE_OPEN : kJ/hr.m^2 : threshold of total radiation on facade where shading device is deactivated\n')
|
||||
f.write('MAX_ISHADE : any : max shading factor of internal shading\n')
|
||||
f.write('MAX_ESHADE : any : max shading factor of external shading\n')
|
||||
|
||||
@staticmethod
|
||||
def _geometry_information(f, building):
|
||||
f.write('[Geometry]\n')
|
||||
f.write(f'Length: {building.upper_corner[0] - building.lower_corner[0]}\n')
|
||||
f.write(f'Width: {building.upper_corner[1] - building.lower_corner[1]}\n')
|
||||
f.write(f'Height: {building.upper_corner[2] - building.lower_corner[2]}\n')
|
||||
|
||||
@staticmethod
|
||||
def _wall_construction(f, building):
|
||||
basic_thermal_boundary = building.walls[0].associated_thermal_boundaries[0]
|
||||
|
||||
f.write('[Wall Construction]\n')
|
||||
f.write(f'Wall Type: Multi-Layered Wall\n')
|
||||
f.write(f'Layers: {len(basic_thermal_boundary.layers)}')
|
||||
for i, layer in enumerate(basic_thermal_boundary.layers):
|
||||
f.write(f'Layer {i}: {layer.material_name}\n')
|
||||
f.write(f'Thickness: {layer.thickness}m\n')
|
||||
|
||||
@staticmethod
|
||||
def _wall_information(f, building):
|
||||
f.write('[Wall Section]\n')
|
||||
f.write(f'Material: {building.upper_corner[0] - building.lower_corner[0]}\n')
|
||||
f.write(f'Width: {building.upper_corner[1] - building.lower_corner[1]}\n')
|
||||
f.write(f'Height: {building.upper_corner[2] - building.lower_corner[2]}\n')
|
||||
def _schedules(f, building):
|
||||
f.write('***************************************\n')
|
||||
f.write(f'* Schedules\n')
|
||||
f.write('***************************************\n')
|
||||
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
for usage in thermal_zone.usages:
|
||||
for schedule in usage.occupancy.occupancy_schedules:
|
||||
if schedule.time_step is cte.HOUR:
|
||||
for day_type in schedule.day_types:
|
||||
f.write(f'SCHEDULE {day_type.upper()}\n')
|
||||
hours = 'HOURS= '
|
||||
values = 'VALUES= '
|
||||
previous = math.inf
|
||||
for hour, value in enumerate(schedule.values):
|
||||
if previous != value:
|
||||
hours = f'{hours} {hour}.000'
|
||||
values = f'{values} {value}'
|
||||
previous = value
|
||||
f.write(f'{hours} 24.0\n')
|
||||
f.write(f'{values} {schedule.values[0]}\n')
|
||||
|
||||
def export(self):
|
||||
print("export")
|
||||
|
@ -125,11 +169,9 @@ class Trnsys:
|
|||
with open(path, 'w', encoding='utf-8') as f:
|
||||
print(path)
|
||||
self._header(f, building)
|
||||
Trnsys._properties(f)
|
||||
self._properties(f)
|
||||
Trnsys._types(f, building)
|
||||
Trnsys._inputs(f)
|
||||
Trnsys._schedules(f, building)
|
||||
|
||||
|
||||
"""
|
||||
self._building_information(f, building)
|
||||
Trnsys._geometry_information(f, building)
|
||||
Trnsys._wall_information(f, building)
|
||||
"""
|
||||
|
|
|
@ -23,4 +23,5 @@ geopandas
|
|||
triangle
|
||||
psycopg2-binary
|
||||
Pillow
|
||||
pathlib
|
||||
pathlib
|
||||
timezonefinder
|
|
@ -162,12 +162,7 @@ class TestExports(TestCase):
|
|||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
|
||||
self.assertIsNotNone(city, 'city is none')
|
||||
EnergyBuildingsExportsFactory('trnsys', city, self._output_path).export()
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
EnergyBuildingsExportsFactory('idf', city, self._output_path).export()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
WeatherFactory('epw', city).enrich()
|
||||
try:
|
||||
EnergyBuildingsExportsFactory('trnsys', city, self._output_path).export()
|
||||
except Exception:
|
||||
self.fail("Trnsys ExportsFactory raised ExceptionType unexpectedly!")
|
||||
EnergyBuildingsExportsFactory('trnsys', city, self._output_path).export()
|
Loading…
Reference in New Issue
Block a user