trnslator/tests/test_trnsys.py

1340 lines
42 KiB
Python
Raw Normal View History

2020-06-23 10:40:49 -04:00
import io
import os
import glob
import shutil
import pytest
2020-06-23 10:58:35 -04:00
import translator as tr
2020-06-23 10:40:49 -04:00
import pandas as pd
from path import Path
from copy import deepcopy
2020-06-23 10:58:35 -04:00
from translator import (
2020-06-23 10:40:49 -04:00
convert_idf_to_trnbuild,
parallel_process,
trnbuild_idf,
copy_file,
load_idf,
settings,
choose_window,
run_eplus,
ReportData,
get_eplus_dirs,
)
# Function round to hundreds
2020-06-23 10:58:35 -04:00
from translator.trnsys import (
2020-06-23 10:40:49 -04:00
_assert_files,
load_idf_file_and_clean_names,
clear_name_idf_objects,
get_idf_objects,
_get_constr_list,
_order_objects,
_get_schedules,
_yearlySched_to_csv,
_remove_low_conductivity,
_write_version,
_write_building,
_add_change_adj_surf,
_write_location_geomrules,
_is_coordSys_world,
_change_relative_coords,
_get_ground_vertex,
_write_zone_buildingSurf_fenestrationSurf,
_write_constructions,
_write_constructions_end,
_write_materials,
_write_gains,
_write_conditioning,
_write_schedules,
_write_window,
_write_winPool,
_save_t3d,
_relative_to_absolute,
infilt_to_b18,
gains_to_b18,
conditioning_to_b18,
adds_sch_ground,
adds_sch_setpoint,
t_initial_to_b18,
closest_coords,
)
from tests.conftest import get_platform
@pytest.fixture(
scope="class", params=["tests/input_data/trnsys/simple_2_zone_sched.idf",],
)
def converttesteasy(request):
file = request.param
window_file = "W74-lib.dat"
2020-06-23 10:58:35 -04:00
template_dir = os.path.join("translator", "ressources")
2020-06-23 10:40:49 -04:00
window_filepath = os.path.join(template_dir, window_file)
template_d18 = "tests/input_data/trnsys/NewFileTemplate.d18"
trnsidf_exe = "docker/trnsidf/trnsidf.exe" # 'docker/trnsidf/trnsidf.exe'
# prepare args (key=value). Key is a unique id for the runs (here the
# file basename is used). Value is a dict of the function arguments
kwargs_dict = {
"u_value": 2.5,
"shgc": 0.6,
"t_vis": 0.78,
"tolerance": 0.05,
"ordered": True,
}
idf = load_idf(file)
weather_file = os.path.join(
"tests", "input_data", "CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw"
)
output_folder = os.path.relpath(settings.data_folder)
yield idf, file, weather_file, window_filepath, trnsidf_exe, template_d18, output_folder, kwargs_dict
del idf
class TestConvertEasy:
"""Tests functions of trnsys.py using 1 simple/small IDF file"""
def test_assert_files(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
_,
) = converttesteasy
# Tests assertion if idf_file is None
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(None, None, None, None, None, None)
# Tests assertion if weather file is None
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(idf_file, None, None, None, None, None)
# Tests assertion if window_lib is None
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(idf_file, weather_file, None, None, None, None)
# Tests assertion if output_folder is None
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(idf_file, weather_file, window_lib, None, None, None)
# Tests assertion if trnsidf_exe and template_d18 is None
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(
idf_file, weather_file, window_lib, output_folder, None, None
)
# Tests assertion if idf_file is a string but not a path
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files("wrong_string", None, None, None, None, None)
# Tests assertion if weather_file is a string but not a path
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(idf_file, "wrong_string", None, None, None, None)
# Tests assertion if window_lib is a string but not a path
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(idf_file, weather_file, "wrong_string", None, None, None)
# Tests assertion if window_lib is not a string AND not None
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(idf_file, weather_file, 2, None, None, None)
# Tests assertion if trnsidf_exe is a string but not a path
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(
idf_file, weather_file, window_lib, output_folder, "wrong_string", None
)
# Tests assertion if template_d18 is a string but not a path
with pytest.raises(IOError):
(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
template,
) = _assert_files(
idf_file,
weather_file,
window_lib,
output_folder,
trnsidf_exe,
"wrong_string",
)
assert output_folder == os.path.relpath(settings.data_folder)
def test_get_save_write_schedules_as_sched(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
_,
) = converttesteasy
# Read IDF_T3D template and write lines in variable
lines = io.TextIOWrapper(io.BytesIO(settings.template_BUI)).readlines()
# Copy IDF object, making sure we don't change/overwrite original IDF file
idf_2 = deepcopy(idf)
# Gets all schedule from IDF
schedule_names, schedules = _get_schedules(idf_2)
# Save schedules in a csv file
_yearlySched_to_csv(idf_file, output_folder, schedule_names, schedules)
# Write schedules directly in T3D file (in lines)
schedule_as_input = False
schedules_not_written = _write_schedules(
lines, schedule_names, schedules, schedule_as_input, idf_file
)
# Asserts csv with schedules exists and schedules are written in lines
assert os.path.exists(glob.glob(settings.data_folder + "/*.csv")[0])
assert "!-SCHEDULE " + schedule_names[0] + "\n" in lines
def test_write_version_and_building(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
_,
) = converttesteasy
# Copy IDF object, making sure we don't change/overwrite original IDF file
idf_2 = deepcopy(idf)
# Get objects from IDF
(
buildingSurfs,
buildings,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
versions,
zones,
zonelists,
) = get_idf_objects(idf_2)
# Read IDF_T3D template and write lines in variable
lines = io.TextIOWrapper(io.BytesIO(settings.template_BUI)).readlines()
# Write VERSION and BUILDING info from IDF to lines (T3D)
_write_version(lines, versions)
_write_building(buildings, lines)
# Asserts version and building information written in lines
assert "Version," + settings.ep_version.replace("-", ".")[:3] + ";\n" in lines
assert buildings[0] in lines
def test_write_material(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
_,
) = converttesteasy
# Read IDF_T3D template and write lines in variable
lines = io.TextIOWrapper(io.BytesIO(settings.template_BUI)).readlines()
# Copy IDF object, making sure we don't change/overwrite original IDF file
idf_2 = deepcopy(idf)
# Get objects from IDF
(
buildingSurfs,
buildings,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
versions,
zones,
zonelists,
) = get_idf_objects(idf_2)
# Write LAYER from IDF to lines (T3D)
_write_materials(lines, materialAirGap, materialNoMass, materials)
# Asserts materials (material, AirGap, NoMass, etc.) are written in lines
assert "!-LAYER " + materialAirGap[0].Name + "\n" in lines
assert "!-LAYER " + materialNoMass[0].Name + "\n" in lines
assert "!-LAYER " + materials[0].Name + "\n" in lines
def test_relative_to_absolute(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
_,
) = converttesteasy
# Copy IDF object, making sure we don't change/overwrite original IDF file
idf_2 = deepcopy(idf)
# Clean names of idf objects (e.g. 'MATERIAL')
log_clear_names = False
clear_name_idf_objects(idf_2, log_clear_names)
# Get objects from IDF
(
buildingSurfs,
buildings,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
versions,
zones,
zonelists,
) = get_idf_objects(idf_2)
# Getting surface to test, by copying it (like that object stay unchanged)
# And can be used after for assertion
surface_init = deepcopy(buildingSurfs[0])
# Transform relative coords of a surface to absolute coords
_relative_to_absolute(buildingSurfs[0], 1, 2, 3)
# Asserts relative coords converted to absolute ones
assert (
buildingSurfs[0]["Vertex_" + str(1) + "_Xcoordinate"]
== surface_init["Vertex_" + str(1) + "_Xcoordinate"] + 1
)
assert (
buildingSurfs[0]["Vertex_" + str(1) + "_Ycoordinate"]
== surface_init["Vertex_" + str(1) + "_Ycoordinate"] + 2
)
assert (
buildingSurfs[0]["Vertex_" + str(1) + "_Zcoordinate"]
== surface_init["Vertex_" + str(1) + "_Zcoordinate"] + 3
)
def test_save_t3d(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
_,
) = converttesteasy
# Read IDF_T3D template and write lines in variable
lines = io.TextIOWrapper(io.BytesIO(settings.template_BUI)).readlines()
# Save T3D file at output_folder
output_folder, t3d_path = _save_t3d(idf_file, lines, output_folder)
# Asserts path to T3D file exists
assert t3d_path in glob.glob(settings.data_folder + "/*.idf")
def test_t_initial_to_b18(self, config, converttesteasy):
# Deletes cache folder
if os.path.exists(settings.cache_folder):
shutil.rmtree(settings.cache_folder)
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
kwargs,
) = converttesteasy
# Copy IDF object, making sure we don't change/overwrite original IDF file
idf_2 = deepcopy(idf)
# Clean names of idf objects (e.g. 'MATERIAL')
log_clear_names = False
clear_name_idf_objects(idf_2, log_clear_names)
# Get objects from IDF
(
buildingSurfs,
buildings,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
versions,
zones,
zonelists,
) = get_idf_objects(idf_2)
# Read a b18 file and write lines in variable (b18_lines)
b18_path = "tests/input_data/trnsys/T3D_simple_2_zone.b18"
with open(b18_path) as b18_file:
b18_lines = b18_file.readlines()
# Creates a constant schedule setpoint over the year
schedules = {"sch_h_setpoint_" + zones[0].Name: {"all values": [18] * 8760}}
zones = [zones[0]]
# Writes initial temperature of zone in b18_lines (b18 file)
t_initial_to_b18(b18_lines, zones, schedules)
# Asserts initial temperature is written in b18_lines
assert any("TINITIAL= 18" in mystring for mystring in b18_lines[200:])
def test_closest_coords(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
kwargs,
) = converttesteasy
# Copy IDF object, making sure we don't change/overwrite original IDF file
idf_2 = deepcopy(idf)
# Get objects from IDF
(
buildingSurfs,
buildings,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
versions,
zones,
zonelists,
) = get_idf_objects(idf_2)
# Find closest surface to origin (0,0,0)
x, y, z = closest_coords(buildingSurfs, to=[0, 0, 0])
# Asserts closest coords
assert x == -5
assert y == 215
assert z == 0
def test_write_to_b18(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
kwargs,
) = converttesteasy
# Runs EnergyPlus Simulation
res = run_eplus(
idf_file,
weather_file,
output_directory=None,
ep_version=None,
output_report="htm",
prep_outputs=True,
design_day=True,
)
# Copy IDF object, making sure we don't change/overwrite original IDF file
idf_2 = deepcopy(idf)
# Clean names of idf objects (e.g. 'MATERIAL')
log_clear_names = False
clear_name_idf_objects(idf_2, log_clear_names)
# Get old:new names equivalence
old_new_names = pd.read_csv(
os.path.join(
settings.data_folder,
Path(idf_file).basename().stripext() + "_old_new_names_equivalence.csv",
)
).to_dict()
# Get objects from IDF
(
buildingSurfs,
buildings,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
versions,
zones,
zonelists,
) = get_idf_objects(idf_2)
# Read a b18 file and write lines in variable (b18_lines)
b18_path = "tests/input_data/trnsys/T3D_simple_2_zone.b18"
with open(b18_path) as b18_file:
b18_lines = b18_file.readlines()
# initialize variable
schedules_not_written = []
# Gets conditioning (heating and cooling) info from simulation results
heat_name = {}
for i in range(0, len(res["Zone Sensible Heating"])):
key = res["Zone Sensible Heating"].iloc[i, 0]
name = "HEAT_z" + str(res["Zone Sensible Heating"].iloc[i].name)
heat_name[key] = name
cool_name = {}
for i in range(0, len(res["Zone Sensible Cooling"])):
key = res["Zone Sensible Cooling"].iloc[i, 0]
name = "HEAT_z" + str(res["Zone Sensible Cooling"].iloc[i].name)
cool_name[key] = name
# Selects only 2 first zones
zones = zones[0:2]
peoples = peoples[0:2]
equipments = equipments[0:2]
lights = lights[0:2]
# Writes infiltration in b18_lines (b18 file)
infilt_to_b18(b18_lines, zones, res)
# Tests both cases, whether schedules are taken as inputs or written in b18_lines
for cond in [True, False]:
schedule_as_input = cond
gains_to_b18(
b18_lines,
zones,
zonelists,
peoples,
lights,
equipments,
schedules_not_written,
res,
old_new_names,
schedule_as_input,
)
# Writes conditioning (heating and cooling) in b18_lines (b18 file)
conditioning_to_b18(b18_lines, heat_name, cool_name, zones, old_new_names)
# Asserts infiltration, internal gains and conditioning are written in b18_lines
assert "INFILTRATION Constant" + "\n" in b18_lines
assert " INFILTRATION = Constant" + "\n" in b18_lines
assert any(peoples[0].Name in mystring for mystring in b18_lines[200:])
assert any(lights[0].Name in mystring for mystring in b18_lines[200:])
assert any(equipments[0].Name in mystring for mystring in b18_lines[200:])
assert any(
heat_name[old_new_names[zones[0].Name.upper()][0]] in mystring
for mystring in b18_lines[200:]
)
def test_load_idf_file_and_clean_names(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
_,
) = converttesteasy
# Clean names of idf objects (e.g. 'MATERIAL')
log_clear_names = False
idf_2 = load_idf_file_and_clean_names(idf_file, log_clear_names)
# Makes sure material names are unique and are 8 characters long
name = None
unique = False
length = False
for liste in idf_2.idfobjects["MATERIAL"].list2:
if liste[1] != name:
unique = True
name = liste[1]
else:
unique = False
if len(liste[1]) == 8:
length = True
else:
length = False
assert isinstance(idf_2, tr.idfclass.IDF)
assert unique
assert length
def test_add_object_and_run_ep(self, config, converttesteasy):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
kwargs,
) = converttesteasy
ep_version = None
# Adds Output variable in IDF
outputs = [
{
"ep_object": "Output:Variable".upper(),
"kwargs": dict(
Variable_Name="Zone Thermostat Heating Setpoint Temperature",
Reporting_Frequency="hourly",
save=True,
),
},
{
"ep_object": "Output:Variable".upper(),
"kwargs": dict(
Variable_Name="Zone Thermostat Cooling Setpoint Temperature",
Reporting_Frequency="hourly",
save=True,
),
},
]
# Runs EnergyPlus Simulation
_, idf = run_eplus(
idf_file,
weather_file,
output_directory=None,
ep_version=ep_version,
output_report=None,
prep_outputs=outputs,
design_day=False,
annual=True,
expandobjects=True,
return_idf=True,
)
# Makes sure idf vriable is an IDF
assert isinstance(idf, tr.idfclass.IDF)
@pytest.fixture(
scope="class", params=["5ZoneGeometryTransform.idf",],
)
def converttest(request):
file = get_eplus_dirs(settings.ep_version) / "ExampleFiles" / request.param
# file = request.param
window_file = "W74-lib.dat"
2020-06-23 10:58:35 -04:00
template_dir = os.path.join("translator", "ressources")
2020-06-23 10:40:49 -04:00
window_filepath = os.path.join(template_dir, window_file)
template_d18 = "tests/input_data/trnsys/NewFileTemplate.d18"
trnsidf_exe = "docker/trnsidf/trnsidf.exe" # 'docker/trnsidf/trnsidf.exe'
# prepare args (key=value). Key is a unique id for the runs (here the
# file basename is used). Value is a dict of the function arguments
kwargs_dict = {
"u_value": 2.5,
"shgc": 0.6,
"t_vis": 0.78,
"tolerance": 0.05,
"ordered": True,
}
idf = load_idf(file)
weather_file = os.path.join(
"tests", "input_data", "CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw"
)
output_folder = os.path.relpath(settings.data_folder)
yield idf, file, weather_file, window_filepath, trnsidf_exe, template_d18, output_folder, kwargs_dict
del idf
class TestConvert:
"""Tests convert_idf_to_trnbuild() with several files"""
def test_get_save_write_schedules_as_input(self, config, converttest):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
_,
) = converttest
# Read IDF_T3D template and write lines in variable
lines = io.TextIOWrapper(io.BytesIO(settings.template_BUI)).readlines()
# Gets all schedule from IDF
schedule_names, schedules = _get_schedules(idf)
# Save schedules in a csv file
_yearlySched_to_csv(idf_file, output_folder, schedule_names, schedules)
# Write schedules as inputs in T3D file (in lines)
schedule_as_input = True
schedules_not_written = _write_schedules(
lines, schedule_names, schedules, schedule_as_input, idf_file
)
def test_write_idf_objects(self, config, converttest):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
kwargs,
) = converttest
# Read IDF_T3D template and write lines in variable
lines = io.TextIOWrapper(io.BytesIO(settings.template_BUI)).readlines()
# Get objects from IDF file
(
buildingSurfs,
buildings,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
versions,
zones,
zonelists,
) = get_idf_objects(idf)
# Creates low thermal resistance construction and materials to be deleted
# To improve coverage of test
idf.newidfobject(
"MATERIAL",
Name="low_res_mat",
Roughness="Smooth",
Thickness=0.0008,
Conductivity=45.28,
Density=7824,
Specific_Heat=500,
Thermal_Absorptance=0.7,
Solar_Absorptance=0.7,
Visible_Absorptance=0.7,
)
idf.newidfobject(
"CONSTRUCTION", Name="low_res_constr", Outside_Layer="low_res_mat"
)
# Changes Outside boundary of surface to adiabatic
# To improve coverage of test
buildingSurfs[0].Outside_Boundary_Condition = "Adiabatic"
# Changes coords of zone
# To improve coverage of test
zones[0].X_Origin = ""
zones[0].Y_Origin = ""
zones[0].Z_Origin = ""
zones[0].Multiplier = ""
# Get all construction EXCEPT fenestration ones
constr_list = _get_constr_list(buildingSurfs)
# If ordered=True, ordering idf objects
ordered = True
(
buildingSurfs,
buildings,
constr_list,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
zones,
zonelists,
) = _order_objects(
buildingSurfs,
buildings,
constr_list,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
zones,
zonelists,
ordered,
)
# Removes low conductivity material and constructions
mat_name = _remove_low_conductivity(constructions, idf, materials)
# Determine if coordsSystem is "World" (all zones at (0,0,0))
coordSys = _is_coordSys_world("Relative", zones)
# Changes Geom Rule to "Relative"
# To improve coverage of test
globGeomRules[0].Coordinate_System = "Relative"
globGeomRules[0].Daylighting_Reference_Point_Coordinate_System = "Relative"
globGeomRules[0].Rectangular_Surface_Coordinate_System = "Relative"
# Change Outside boundary condition of surface to itself
# To improve coverage of test
buildingSurfs[5].Outside_Boundary_Condition_Object = "C5-1"
# Change Outside boundary condition of surface to Zone and adjacent to Outdoors
# To improve coverage of test
buildingSurfs[0].Outside_Boundary_Condition = "Zone"
buildingSurfs[0].Outside_Boundary_Condition_Object = buildingSurfs[6].Zone_Name
buildingSurfs[6].Outside_Boundary_Condition = "Outdoors"
# Change Outside boundary condition of surface to Zone and adjacent to Zone.Name
# To improve coverage of test
buildingSurfs[1].Outside_Boundary_Condition = "Zone"
buildingSurfs[1].Outside_Boundary_Condition_Object = "SPACE3-1"
# Write LOCATION and GLOBALGEOMETRYRULES from IDF to lines (T3D) and
# define if coordinate system is "Relative"
coordSys = _write_location_geomrules(globGeomRules, lines, locations)
# Change coordinates from relative to absolute for building surfaces
_change_relative_coords(buildingSurfs, coordSys, idf)
# Adds or changes adjacent surface if needed
_add_change_adj_surf(buildingSurfs, idf)
buildingSurfs = idf.idfobjects["BUILDINGSURFACE:DETAILED"]
# Get all surfaces having Outside boundary condition with the ground.
# To be used to find the window's slopes
n_ground = _get_ground_vertex(buildingSurfs)
# Writing zones in lines
schedule_as_input = True
win_slope_dict = _write_zone_buildingSurf_fenestrationSurf(
buildingSurfs,
coordSys,
fenestrationSurfs,
idf,
lines,
n_ground,
zones,
schedule_as_input,
)
# Write CONSTRUCTION from IDF to lines (T3D)
_write_constructions(constr_list, idf, lines, mat_name, materials)
# Write CONSTRUCTION from IDF to lines, at the end of the T3D file
_write_constructions_end(constr_list, idf, lines)
# region Write WINDOWS chosen by the user (from Berkeley lab library) in
# lines (T3D)
# Get window from library
# window = (win_id, description, design, u_win, shgc_win, t_sol_win,
# rf_sol, t_vis_win, lay_win, width, window_bunches[win_id], and maybe tolerance)
win_u_value = kwargs.get("u_value", 2.2)
win_shgc = kwargs.get("shgc", 0.64)
win_tvis = kwargs.get("t_vis", 0.8)
win_tolerance = kwargs.get("tolerance", 0.05)
window = choose_window(
win_u_value, win_shgc, win_tvis, win_tolerance, window_lib
)
# Write windows in lines
_write_window(lines, win_slope_dict, window)
# Write window pool in lines
_write_winPool(lines, window)
def test_write_gains_conditioning(self, config, converttest):
# Gets from fixture paths to files and IDF object to be used in test
(
idf,
idf_file,
weather_file,
window_lib,
trnsidf_exe,
template,
output_folder,
_,
) = converttest
# Gets EnergyPlus version
ep_version = settings.ep_version
# Adds Output variable in IDF
outputs = [
{
"ep_object": "Output:Variable".upper(),
"kwargs": dict(
Variable_Name="Zone Thermostat Heating Setpoint Temperature",
Reporting_Frequency="hourly",
save=True,
),
},
{
"ep_object": "Output:Variable".upper(),
"kwargs": dict(
Variable_Name="Zone Thermostat Cooling Setpoint Temperature",
Reporting_Frequency="hourly",
save=True,
),
},
]
# Run EnergyPlus Simulation
_, idf = run_eplus(
idf_file,
weather_file,
output_directory=None,
ep_version=ep_version,
output_report=None,
prep_outputs=outputs,
design_day=False,
annual=True,
expandobjects=True,
return_idf=True,
)
# Output reports
htm = idf.htm
sql = idf.sql
sql_file = idf.sql_file
# Check if cache exists
log_clear_names = False
# Clean names of idf objects (e.g. 'MATERIAL')
idf_2 = deepcopy(idf)
clear_name_idf_objects(idf_2, log_clear_names)
# Get old:new names equivalence
old_new_names = pd.read_csv(
os.path.join(
settings.data_folder,
Path(idf_file).basename().stripext() + "_old_new_names_equivalence.csv",
)
).to_dict()
# Read IDF_T3D template and write lines in variable
lines = io.TextIOWrapper(io.BytesIO(settings.template_BUI)).readlines()
# Get objects from IDF file
(
buildingSurfs,
buildings,
constructions,
equipments,
fenestrationSurfs,
globGeomRules,
lights,
locations,
materialAirGap,
materialNoMass,
materials,
peoples,
versions,
zones,
zonelists,
) = get_idf_objects(idf_2)
# Write GAINS (People, Lights, Equipment) from IDF to lines (T3D)
_write_gains(equipments, lights, lines, peoples, htm, old_new_names)
# Gets schedules from IDF
schedule_names, schedules = _get_schedules(idf_2)
# Adds ground temperature to schedules
adds_sch_ground(htm, schedule_names, schedules)
# Adds "sch_setpoint_ZONES" to schedules
df_heating_setpoint = ReportData.from_sqlite(
sql_file, table_name="Zone Thermostat Heating Setpoint Temperature"
)
df_cooling_setpoint = ReportData.from_sqlite(
sql_file, table_name="Zone Thermostat Cooling Setpoint Temperature"
)
# Heating
adds_sch_setpoint(
zones, df_heating_setpoint, old_new_names, schedule_names, schedules, "h"
)
# Cooling
adds_sch_setpoint(
zones, df_cooling_setpoint, old_new_names, schedule_names, schedules, "c"
)
# Writes conditioning in lines
schedule_as_input = True
heat_dict, cool_dict = _write_conditioning(
htm, lines, schedules, old_new_names, schedule_as_input
)
@pytest.fixture(
params=[
"RefBldgWarehouseNew2004_Chicago.idf",
"ASHRAE9012016_Warehouse_Denver.idf",
"ASHRAE9012016_ApartmentMidRise_Denver.idf",
"5ZoneGeometryTransform.idf",
]
)
def trnbuild_file(config, request):
idf_file = get_eplus_dirs(settings.ep_version) / "ExampleFiles" / request.param
idf_file = copy_file(idf_file, where=settings.cache_folder)
yield idf_file
@pytest.mark.skipif(
get_platform() > (10, 15, 0),
reason="Skipping since wine 32bit can't run on MacOs >10.15 (Catalina)",
)
@pytest.mark.skipif(
os.environ.get("CI", "False").lower() == "true",
reason="Skipping this test on CI environment.",
)
class TestTrnBuild:
def test_trnbuild_from_idf(self, config, trnbuild_file):
# Gets file paths/names
window_file = "W74-lib.dat"
2020-06-23 10:58:35 -04:00
template_dir = os.path.join("translator", "ressources")
2020-06-23 10:40:49 -04:00
window_filepath = os.path.join(template_dir, window_file)
weather_file = os.path.join(
"tests", "input_data", "CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw"
)
# prepare args (key=value)f or EnergyPlus version to use, windows parameters,etc.
kwargs_dict = {
"ep_version": settings.ep_version,
"u_value": 2.5,
"shgc": 0.6,
"t_vis": 0.78,
"tolerance": 0.05,
"fframe": 0.1,
"uframe": 7.5,
"ordered": True,
}
# Gets IDF file path from fixture
file = trnbuild_file
# Convert IDF to BUI file
convert_idf_to_trnbuild(
idf_file=file,
weather_file=weather_file,
window_lib=window_filepath,
template="tests/input_data/trnsys/NewFileTemplate.d18",
trnsidf_exe="docker/trnsidf/trnsidf.exe",
**kwargs_dict
)
@pytest.mark.win32
def test_trnbuild_from_idf_parallel(self, config, trnbuild_file):
# Gets IDF file path from fixture
files = trnbuild_file
# Path to weather file
weather_file = os.path.join(
"tests", "input_data", "CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw"
)
# prepare args (key=value). Key is a unique id for the runs (here the
# file basename is used). Value is a dict of the function arguments
in_dict = {
os.path.basename(file): dict(idf_file=file, weather_file=weather_file)
for file in files
}
# Convert IDF files to BUI ones usinf parallel process
result = parallel_process(in_dict, convert_idf_to_trnbuild, 4, use_kwargs=True)
assert not any(isinstance(a, Exception) for a in result.values())
@pytest.mark.darwin
@pytest.mark.linux
def test_trnbuild_from_idf_parallel_darwin_or_linux(self, config):
# Path to EnergyPlus example files
file_upper_path = os.path.join(
get_eplus_dirs(settings.ep_version), "ExampleFiles"
)
# IDF file names
files = [
"RefBldgWarehouseNew2004_Chicago.idf",
"ASHRAE9012016_Warehouse_Denver.idf",
"ASHRAE9012016_ApartmentMidRise_Denver.idf",
"5ZoneGeometryTransform.idf",
]
# Path to weather file
weather_file = os.path.join(
"tests", "input_data", "CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw"
)
# prepare args (key=value). Key is a unique id for the runs (here the
# file basename is used). Value is a dict of the function arguments
in_dict = {
os.path.basename(file): dict(
idf_file=os.path.join(file_upper_path, file),
weather_file=weather_file,
template="tests/input_data/trnsys/NewFileTemplate.d18",
trnsidf_exe="docker/trnsidf/trnsidf.exe",
)
for file in files
}
# Convert IDF files to BUI ones usinf parallel process
result = parallel_process(in_dict, convert_idf_to_trnbuild, 4, use_kwargs=True)
# Print results
[print(a) for a in result.values() if isinstance(a, Exception)]
assert not any(isinstance(a, Exception) for a in result.values())
@pytest.mark.win32
def test_trnbuild_idf_win32(self, config):
# Paths to T3D and B18 template files
idf_file = "tests/input_data/trnsys/Building.idf"
template = "tests/input_data/trnsys/NewFileTemplate.d18"
# Convert T3D file to BUI file
res = trnbuild_idf(idf_file, template=template, nonum=True)
assert res
@pytest.mark.darwin
@pytest.mark.linux
@pytest.mark.xfail(
not Path("docker/trnsidf/trnsidf.exe").exists(),
reason="xfail since trnsidf.exe is not installed. This test can work if the "
"trnsidf.exe is copied in ./docker/trnsidf",
)
def test_trnbuild_idf_darwin_or_linux(self, config):
# Paths to T3D, B18 template and trnsidf.exe files
idf_file = "tests/input_data/trnsys/Building.idf"
template = "tests/input_data/trnsys/NewFileTemplate.d18"
trnsidf_exe = "docker/trnsidf/trnsidf.exe"
# Convert T3D file to BUI file
res = trnbuild_idf(
idf_file,
template=template,
dck=True,
nonum=False,
refarea=False,
volume=False,
capacitance=True,
trnsidf_exe=trnsidf_exe,
)
assert res
@pytest.mark.skipif(
get_platform() > (10, 15, 0),
reason="Skipping since wine 32bit can't run on MacOs >10.15 (Catalina)",
)
@pytest.mark.skipif(
os.environ.get("CI", "False").lower() == "true",
reason="Skipping this test on CI environment.",
)
def test_trnbuild_from_simple_idf(config):
# Path to weather file, window library and T3D template
window_file = "W74-lib.dat"
2020-06-23 10:58:35 -04:00
template_dir = os.path.join("translator", "ressources")
2020-06-23 10:40:49 -04:00
window_filepath = os.path.join(template_dir, window_file)
weather_file = os.path.join(
"tests", "input_data", "CAN_QC_Montreal-McTavish.716120_CWEC2016.epw"
)
# prepare args (key=value)f or EnergyPlus version to use, windows parameters,etc.
# WINDOW = 2-WSV_#3_Air
kwargs_dict = {
"ep_version": "9-2-0",
"u_value": 1.62,
"shgc": 0.64,
"t_vis": 0.8,
"tolerance": 0.05,
"fframe": 0.0,
"uframe": 0.5,
"ordered": True,
}
# Path to IDF file
file = os.path.join("tests", "input_data", "trnsys", "simple_2_zone.idf")
# Converts IDF to BUI
convert_idf_to_trnbuild(
idf_file=file,
weather_file=weather_file,
window_lib=window_filepath,
template="tests/input_data/trnsys/NewFileTemplate.d18",
trnsidf_exe="docker/trnsidf/trnsidf.exe",
schedule_as_input=False,
**kwargs_dict
)