"""This module contains function for AixLib model generation"""
import os
import warnings
import shutil
from mako.template import Template
from mako.lookup import TemplateLookup
import teaser.logic.utilities as utilities
[docs]def export_multizone(buildings, prj, path=None):
"""Exports models for AixLib library
Exports a building for
AixLib.ThermalZones.ReducedOrder.Multizone.MultizoneEquipped models
using the ThermalZoneEquipped and supporting models, like tables and weather
model. Depending on chosen calculation method the parameter set to 1,2,
3 or 4 element model. By default it uses the correction for solar
glazing (corG) and decoupled heat conduction through windows (
merge_windows=False). In contrast to versions < 0.5 TEASER now does not
support any other model options, as we observed no need, since single
ThermalZones are identical with IBPSA models. If you miss one of the
old options please contact us.
This function uses Mako Templates specified in
data.output.modelicatemplates.AixLib
Parameters
----------
buildings : list of instances of Building
list of TEASER instances of a Building that is exported to a AixLib
MultizoneEquipped models. If you want to export a single building,
please pass it over as a list containing only that building.
prj : instance of Project
Instance of TEASER Project object to access Project related
information, e.g. name or version of used libraries
path : string
if the Files should not be stored in default output path of TEASER,
an alternative path can be specified as a full path
Attributes
----------
lookup : TemplateLookup object
Instance of mako.TemplateLookup to store general functions for templates
zone_template_1 : Template object
Template for ThermalZoneRecord using 1 element model
zone_template_2 : Template object
Template for ThermalZoneRecord using 2 element model
zone_template_3 : Template object
Template for ThermalZoneRecord using 3 element model
zone_template_4 : Template object
Template for ThermalZoneRecord using 4 element model
model_template : Template object
Template for MultiZone model
"""
lookup = TemplateLookup(directories=[utilities.get_full_path(
os.path.join('data', 'output', 'modelicatemplate'))])
zone_template_1 = Template(
filename=utilities.get_full_path(
"data/output/modelicatemplate/AixLib"
"/AixLib_ThermalZoneRecord_OneElement"),
lookup=lookup)
zone_template_2 = Template(
filename=utilities.get_full_path(
"data/output/modelicatemplate/AixLib"
"/AixLib_ThermalZoneRecord_TwoElement"),
lookup=lookup)
zone_template_3 = Template(
filename=utilities.get_full_path(
"data/output/modelicatemplate/AixLib"
"/AixLib_ThermalZoneRecord_ThreeElement"),
lookup=lookup)
zone_template_4 = Template(
filename=utilities.get_full_path(
"data/output/modelicatemplate/AixLib"
"/AixLib_ThermalZoneRecord_FourElement"),
lookup=lookup)
model_template = Template(
filename=utilities.get_full_path(
"data/output/modelicatemplate/AixLib/AixLib_Multizone"),
lookup=lookup)
test_script_template = Template(
filename=utilities.get_full_path(
"data/output/modelicatemplate/modelica_test_script"),
lookup=lookup)
uses = [
'Modelica(version="' + prj.modelica_info.version + '")',
'AixLib(version="' + prj.buildings[-1].library_attr.version + '")']
_help_package(
path=path,
name=prj.name,
uses=uses,
within=None)
_help_package_order(
path=path,
package_list=buildings,
addition=None,
extra=None)
_copy_weather_data(prj.weather_file_path, path)
for i, bldg in enumerate(buildings):
ass_error = "You chose IBPSA calculation, " \
"but want to export AixLib models, " \
"this is not possible"
assert bldg.used_library_calc == 'AixLib', ass_error
bldg_path = os.path.join(path, bldg.name)
utilities.create_path(utilities.get_full_path(bldg_path))
utilities.create_path(utilities.get_full_path(
os.path.join(bldg_path,
bldg.name + "_DataBase")))
bldg.library_attr.modelica_set_temp(path=bldg_path)
bldg.library_attr.modelica_set_temp_cool(path=bldg_path)
bldg.library_attr.modelica_AHU_boundary(
path=bldg_path)
bldg.library_attr.modelica_gains_boundary(
path=bldg_path)
_help_package(path=bldg_path, name=bldg.name, within=bldg.parent.name)
_help_package_order(
path=bldg_path,
package_list=[bldg],
addition=None,
extra=bldg.name + "_DataBase")
if bldg.building_id is None:
bldg.building_id = i
else:
try:
bldg.building_id = int(bldg.building_id)
except UserWarning:
warnings.warn("Cannot convert building_id to integer, "
"is set to ", i, "which is the enumeration "
"number of the building in "
"the project list.")
bldg.building_id = i
with open(utilities.get_full_path(
os.path.join(bldg_path, bldg.name + ".mo")), 'w') as out_file:
out_file.write(model_template.render_unicode(
bldg=bldg,
weather=bldg.parent.weather_file_path,
modelica_info=bldg.parent.modelica_info))
out_file.close()
dir_resources = os.path.join(path, "Resources")
if not os.path.exists(dir_resources):
os.mkdir(dir_resources)
dir_scripts = os.path.join(dir_resources, "Scripts")
if not os.path.exists(dir_scripts):
os.mkdir(dir_scripts)
dir_dymola = os.path.join(dir_scripts, "Dymola")
if not os.path.exists(dir_dymola):
os.mkdir(dir_dymola)
_help_test_script(bldg, dir_dymola, test_script_template)
zone_path = os.path.join(bldg_path, bldg.name + "_DataBase")
for zone in bldg.thermal_zones:
with open(utilities.get_full_path(os.path.join(
zone_path,
bldg.name + '_' + zone.name + '.mo')), 'w') as out_file:
if type(zone.model_attr).__name__ == "OneElement":
out_file.write(zone_template_1.render_unicode(zone=zone))
elif type(zone.model_attr).__name__ == "TwoElement":
out_file.write(zone_template_2.render_unicode(zone=zone))
elif type(zone.model_attr).__name__ == "ThreeElement":
out_file.write(zone_template_3.render_unicode(zone=zone))
elif type(zone.model_attr).__name__ == "FourElement":
out_file.write(zone_template_4.render_unicode(zone=zone))
out_file.close()
_help_package(
path=zone_path,
name=bldg.name + '_DataBase',
within=prj.name + '.' + bldg.name)
_help_package_order(
path=zone_path,
package_list=bldg.thermal_zones,
addition=bldg.name + "_",
extra=None)
_copy_script_unit_tests(os.path.join(dir_scripts, "runUnitTests.py"))
_copy_reference_results(dir_resources, prj)
print("Exports can be found here:")
print(path)
def _copy_reference_results(dir_resources, prj):
"""Copy reference results to modelica output.
Parameters
----------
dir_resources : str
Resources directory of the modelica output
prj : teaser.project.Project
Project to be exported
"""
if prj.dir_reference_results is not None:
dir_ref_out = os.path.join(dir_resources, "ReferenceResults")
if not os.path.exists(dir_ref_out):
os.mkdir(dir_ref_out)
dir_ref_out_dymola = os.path.join(dir_ref_out, "Dymola")
if not os.path.exists(dir_ref_out_dymola):
os.mkdir(dir_ref_out_dymola)
for filename in os.listdir(prj.dir_reference_results):
if filename.endswith(".txt"):
shutil.copy2(
os.path.join(prj.dir_reference_results, filename),
os.path.join(dir_ref_out_dymola, filename)
)
def _help_test_script(bldg, dir_dymola, test_script_template):
"""Create a test script for regression testing with BuildingsPy
Parameters
----------
bldg : teaser.logic.buildingobjects.building.Building
Building for which test script is created
dir_dymola : str
Output directory for Dymola scripts
test_script_template : mako.template.Template
Template for the test script
Returns
-------
dir_scripts : str
Path to the scripts directory
"""
dir_building = os.path.join(dir_dymola, bldg.name)
if not os.path.exists(dir_building):
os.mkdir(dir_building)
with open(utilities.get_full_path(os.path.join(
dir_building, bldg.name + ".mos")), 'w') as out_file:
names_variables = []
for i, zone in enumerate(bldg.thermal_zones):
names_variables.append(f"multizone.PHeater[{i+1}]")
names_variables.append(f"multizone.PCooler[{i+1}]")
names_variables.append(f"multizone.TAir[{i+1}]")
out_file.write(test_script_template.render_unicode(
project=bldg.parent,
bldg=bldg,
stop_time=3600 * 24 * 365,
names_variables=names_variables,
))
out_file.close()
def _help_package(path, name, uses=None, within=None):
"""creates a package.mo file
private function, do not call
Parameters
----------
path : string
path of where the package.mo should be placed
name : string
name of the Modelica package
within : string
path of Modelica package containing this package
"""
package_template = Template(filename=utilities.get_full_path(
"data/output/modelicatemplate/package"))
with open(utilities.get_full_path(os.path.join(
path, "package.mo")), 'w') as out_file:
out_file.write(package_template.render_unicode(
name=name,
within=within,
uses=uses))
out_file.close()
def _help_package_order(path, package_list, addition=None, extra=None):
"""creates a package.order file
private function, do not call
Parameters
----------
path : string
path of where the package.order should be placed
package_list : [string]
name of all models or packages contained in the package
addition : string
if there should be a suffix in front of package_list.string it can
be specified
extra : string
an extra package or model not contained in package_list can be
specified
"""
order_template = Template(filename=utilities.get_full_path(
"data/output/modelicatemplate/package_order"))
with open(utilities.get_full_path(
path + "/" + "package" + ".order"), 'w') as out_file:
out_file.write(order_template.render_unicode
(list=package_list, addition=addition, extra=extra))
out_file.close()
def _copy_weather_data(source_path, destination_path):
"""Copies the imported .mos weather file to the results folder.
Parameters
----------
source_path : str
path of local weather file
destination_path : str
path of where the weather file should be placed
"""
shutil.copy2(source_path, destination_path)
def _copy_script_unit_tests(destination_path):
"""Copies the script to run the unit tests.
Parameters
----------
destination_path : str
path of where the weather file should be placed
"""
source_path = utilities.get_full_path("data/output/runUnitTests.py")
shutil.copy2(source_path, destination_path)