Coverage for bim2sim/plugins/PluginEnergyPlus/test/regression/test_energyplus.py: 0%
106 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 17:09 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 17:09 +0000
1import os
2import re
3import shutil
4import sys
5import unittest
6import logging
7from pathlib import Path
9from energyplus_regressions.diffs import math_diff, table_diff
10from energyplus_regressions.diffs.thresh_dict import ThreshDict
12import bim2sim
13from bim2sim.utilities.types import LOD, IFCDomain
14from bim2sim.kernel.decision.decisionhandler import DebugDecisionHandler
15from bim2sim.utilities.test import RegressionTestBase
17logger = logging.getLogger(__name__)
20class RegressionTestEnergyPlus(RegressionTestBase):
21 """Class to set up and run EnergyPlus regression tests."""
22 def setUp(self):
23 self.old_stderr = sys.stderr
24 self.working_dir = os.getcwd()
25 self.ref_results_src_path = None
26 self.results_src_dir = None
27 self.results_dst_dir = None
28 self.tester = None
29 super().setUp()
31 def tearDown(self):
32 os.chdir(self.working_dir)
33 sys.stderr = self.old_stderr
34 super().tearDown()
36 def weather_file_path(self) -> Path:
37 return (self.test_resources_path() /
38 'weather_files/DEU_NW_Aachen.105010_TMYx.epw')
40 def create_regression_setup(self):
41 """
42 Create a regression test setup for EnergyPlus.
44 This method uses the energyplus_regressions library to create a
45 regression test for the passed project EnergyPlus simulation model
46 export.
47 """
48 passed_regression_test = False
50 regex = re.compile("[^a-zA-z0-9]")
51 model_export_name = regex.sub("", self.project.name)
52 ref_csv = self.ref_results_src_path / str(self.project.name +
53 '_eplusout.csv')
54 ref_htm = self.ref_results_src_path / str(self.project.name +
55 '_eplustbl.htm')
56 diff_config = ThreshDict(Path(bim2sim.__file__).parent /
57 "plugins/PluginEnergyPlus/test/regression/ep_diff.config")
58 # set path to current simulation results
59 export_path = self.project.paths.export / \
60 'EnergyPlus'/'SimResults'/self.project.name
61 sim_csv = export_path / 'eplusout.csv'
62 sim_htm = export_path / 'eplustbl.htm'
63 # set directory for regression test results
64 regression_results_dir = self.project.paths.root / \
65 'regression_results' / 'bps' / \
66 self.project.name / 'EnergyPlus'
67 if not Path.exists(regression_results_dir):
68 Path.mkdir(regression_results_dir, parents=True)
69 csv_regression = math_diff.math_diff(
70 # csv_regression returns diff_type ('All Equal', 'Big Diffs',
71 # 'Small Diffs'), num_records (length of validated csv file
72 # (#timesteps)), num_big (#big errors),
73 # num_small (#small errors)
74 diff_config,
75 str(ref_csv),
76 str(sim_csv),
77 os.path.join(regression_results_dir, 'abs_diff_math.csv'),
78 os.path.join(regression_results_dir, 'rel_diff_math.csv'),
79 os.path.join(regression_results_dir, 'math_diff_math.log'),
80 os.path.join(regression_results_dir, 'summary_math.csv'),
81 )
82 if csv_regression[0] in ['Small Diffs', 'All Equal']:
83 passed_regression_test = True # only passes with small diffs
85 htm_regression = table_diff.table_diff(
86 # htm_regression returns message, #tables, #big_diff,
87 # #small_diff, #equals, #string_diff,
88 # #size_diff, #not_in_file1, #not_in_file2
89 diff_config,
90 str(ref_htm),
91 str(sim_htm),
92 os.path.join(regression_results_dir, 'abs_diff_table.htm'),
93 os.path.join(regression_results_dir, 'rel_diff_table.htm'),
94 os.path.join(regression_results_dir, 'math_diff_table.log'),
95 os.path.join(regression_results_dir, 'summary_table.csv'),
96 )
97 if htm_regression[2] == 0:
98 passed_regression_test = True # only passes without big diffs
100 return passed_regression_test
102 def run_regression_test(self):
103 """Run the EnergyPlus regression test."""
104 self.ref_results_src_path = \
105 Path(bim2sim.__file__).parent.parent \
106 / "test/resources/arch/regression_results" \
107 / self.project.name / 'EnergyPlus'
108 if not (list(self.ref_results_src_path.rglob("*.htm")) and list(
109 self.ref_results_src_path.rglob("*.csv"))):
110 logger.error(
111 f"No Regression Results found in {self.ref_results_src_path} "
112 f"to perform regression test via simulation.")
113 passed_regression = self.create_regression_setup()
114 return passed_regression
116 def create_regression_results(self):
117 """Creates regression results based on simulation model.
119 If simulation is successful and regression results differ from
120 new simulation results, the user is asked if the results should be
121 overwritten.
122 If simulation is successful and simulation results are same with
123 regression results nothing happens.
124 If simulation is not successful nothing happens.
125 """
126 self.tester.run()
127 sim_sucessful = self.tester._comp_info[0]['simulation']['success']
128 comp_sucessful = self.tester._comp_info[0]['comparison']['test_passed']
130 # sim and comparison
131 if sim_sucessful and all(comp_sucessful):
132 logger.info("No differences between simulation and regression "
133 "results. No fresh results created.")
134 # sim successful but comparison not (new results were created based if
135 # user decided to simulate
136 elif sim_sucessful and not all(comp_sucessful):
137 # copy updated ref results to assets
138 shutil.rmtree(self.ref_results_src_path.parent,
139 ignore_errors=True)
140 shutil.copytree(self.ref_results_dst_path,
141 self.ref_results_src_path)
142 logger.info("Regression results were updated with new results.")
143 elif not sim_sucessful:
144 logger.error(f"The simulation was not successful, "
145 f"no new regression results were created.")
148class TestRegressionEnergyPlus(RegressionTestEnergyPlus, unittest.TestCase):
149 """Regression tests for EnergyPlus."""
150 def test_regression_AC20_FZK_Haus(self):
151 """Run EnergyPlus regression test with AC20-FZK-Haus.ifc."""
152 ifc_names = {IFCDomain.arch: 'AC20-FZK-Haus.ifc'}
153 project = self.create_project(ifc_names, 'energyplus')
154 project.sim_settings.create_external_elements = True
155 project.sim_settings.cooling_tz_overwrite = True
156 project.sim_settings.split_bounds = True
157 project.sim_settings.add_shadings = True
158 project.sim_settings.split_shadings = True
159 project.sim_settings.run_full_simulation = True
160 project.sim_settings.use_maintained_illuminance = False
161 # project.sim_settings.ep_install_path = 'C://EnergyPlusV9-4-0/'
162 handler = DebugDecisionHandler(())
163 for decision, answer in handler.decision_answer_mapping(project.run()):
164 decision.value = answer
165 self.assertEqual(0, handler.return_value,
166 "Project export and simulation did not finish "
167 "successfully.")
168 self.assertEqual(len(project.playground.elements), 213)
169 reg_test_res = self.run_regression_test()
170 self.assertEqual(True, reg_test_res,
171 "EnergyPlus Regression test did not finish "
172 "successfully or created deviations.")
174 def test_regression_DigitalHub_SB89(self):
175 """Test DigitalHub IFC, includes regression test."""
176 ifc_names = {IFCDomain.arch: 'FM_ARC_DigitalHub_with_SB89.ifc'}
177 project = self.create_project(ifc_names, 'energyplus')
178 project.sim_settings.create_external_elements = True
179 project.sim_settings.cooling_tz_overwrite = True
180 project.sim_settings.construction_class_windows = \
181 'Waermeschutzverglasung, dreifach'
182 project.sim_settings.prj_use_conditions = Path(
183 bim2sim.__file__).parent.parent / \
184 "test/resources/arch/custom_usages/" \
185 "UseConditionsFM_ARC_DigitalHub.json"
186 project.sim_settings.prj_custom_usages = Path(
187 bim2sim.__file__).parent.parent / \
188 "test/resources/arch/custom_usages/" \
189 "customUsagesFM_ARC_DigitalHub_with_SB89.json"
190 # project.sim_settings.ep_install_path = 'C://EnergyPlusV9-4-0/'
191 space_boundary_genenerator = 'Other'
192 handle_proxies = (*(None,) * 12,)
193 construction_year = 2015
194 project.sim_settings.split_bounds = False
195 project.sim_settings.add_shadings = True
196 project.sim_settings.split_shadings = False
197 project.sim_settings.run_full_simulation = False
198 answers = (space_boundary_genenerator,
199 *handle_proxies,
200 construction_year)
201 handler = DebugDecisionHandler(answers)
202 handler.handle(project.run())
203 self.assertEqual(0, handler.return_value,
204 "Project export and simulation did not finish "
205 "successfully.")
206 reg_test_res = self.run_regression_test()
207 self.assertEqual(True, reg_test_res,
208 "EnergyPlus Regression test did not finish "
209 "successfully or created deviations.")