Coverage for bim2sim/plugins/PluginComfort/test/regression/test_comfort.py: 0%
129 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 RegressionTestComfort(RegressionTestBase):
21 """Class to set up and run EnergyPlus Comfort 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/PluginComfort/test/regression/ep_diff_comfort.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 / 'Comfort'
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 / 'Comfort'
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 return False
114 passed_regression = self.create_regression_setup()
115 return passed_regression
117 def create_regression_results(self):
118 """Creates regression results based on simulation model.
120 If simulation is successful and regression results differ from
121 new simulation results, the user is asked if the results should be
122 overwritten.
123 If simulation is successful and simulation results are same with
124 regression results nothing happens.
125 If simulation is not successful nothing happens.
126 """
127 self.tester.run()
128 sim_sucessful = self.tester._comp_info[0]['simulation']['success']
129 comp_sucessful = self.tester._comp_info[0]['comparison']['test_passed']
131 # sim and comparison
132 if sim_sucessful and all(comp_sucessful):
133 logger.info("No differences between simulation and regression "
134 "results. No fresh results created.")
135 # sim successful but comparison not (new results were created based if
136 # user decided to simulate
137 elif sim_sucessful and not all(comp_sucessful):
138 # copy updated ref results to assets
139 shutil.rmtree(self.ref_results_src_path.parent,
140 ignore_errors=True)
141 shutil.copytree(self.ref_results_dst_path,
142 self.ref_results_src_path)
143 logger.info("Regression results were updated with new results.")
144 elif not sim_sucessful:
145 logger.error(f"The simulation was not successful, "
146 f"no new regression results were created.")
149class TestRegressionComfort(RegressionTestComfort, unittest.TestCase):
150 """Regression tests for EnergyPlus."""
152 @unittest.skip("No regression results available")
153 def test_regression_AC20_FZK_Haus_SB55(self):
154 """Run EnergyPlus regression test with AC20-FZK-Haus.ifc."""
155 ifc_names = {IFCDomain.arch: 'AC20-FZK-Haus_with_SB55.ifc'}
156 project = self.create_project(ifc_names, 'comfort')
157 project.sim_settings.create_external_elements = True
158 project.sim_settings.setpoints_from_template = True
159 project.sim_settings.add_window_shading = 'Exterior'
160 project.sim_settings.cooling_tz_overwrite = False
161 project.sim_settings.rename_plot_keys = True
162 project.sim_settings.add_natural_ventilation = True
163 project.sim_settings.add_shadings = True
164 project.sim_settings.split_shadings = True
165 project.sim_settings.run_full_simulation = True
166 # project.sim_settings.ep_install_path = 'C://EnergyPlusV9-4-0/'
167 space_boundary_genenerator = 'Other'
168 answers = (space_boundary_genenerator, *('Single office',) * 4,)
169 handler = DebugDecisionHandler(answers)
170 handler.handle(project.run())
171 self.assertEqual(0, handler.return_value,
172 "Project export and simulation did not finish "
173 "successfully.")
174 reg_test_res = self.run_regression_test()
175 self.assertEqual(True, reg_test_res,
176 "EnergyPlus Regression test did not finish "
177 "successfully or created deviations.")
179 def test_regression_AC20_FZK_Haus(self):
180 """Run EnergyPlus regression test with AC20-FZK-Haus.ifc."""
181 ifc_names = {IFCDomain.arch: 'AC20-FZK-Haus.ifc'}
182 project = self.create_project(ifc_names, 'comfort')
183 project.sim_settings.create_external_elements = True
184 project.sim_settings.setpoints_from_template = True
185 project.sim_settings.add_window_shading = 'Exterior'
186 project.sim_settings.cooling_tz_overwrite = False
187 project.sim_settings.rename_plot_keys = True
188 project.sim_settings.add_natural_ventilation = True
189 project.sim_settings.add_shadings = True
190 project.sim_settings.split_shadings = True
191 project.sim_settings.run_full_simulation = True
192 # project.sim_settings.ep_install_path = 'C://EnergyPlusV9-4-0/'
193 answers = ()
194 handler = DebugDecisionHandler(answers)
195 handler.handle(project.run())
196 self.assertEqual(0, handler.return_value,
197 "Project export and simulation did not finish "
198 "successfully.")
199 reg_test_res = self.run_regression_test()
200 self.assertEqual(True, reg_test_res,
201 "EnergyPlus Regression test did not finish "
202 "successfully or created deviations.")
204 @unittest.skip("No regression results available")
205 def test_regression_DigitalHub_SB89(self):
206 """Test DigitalHub IFC, includes regression test."""
207 ifc_names = {IFCDomain.arch: 'FM_ARC_DigitalHub_with_SB89.ifc'}
208 project = self.create_project(ifc_names, 'comfort')
209 project.sim_settings.create_external_elements = True
210 project.sim_settings.cooling_tz_overwrite = True
211 project.sim_settings.construction_class_windows = \
212 'Waermeschutzverglasung, dreifach'
213 project.sim_settings.prj_use_conditions = Path(
214 bim2sim.__file__).parent.parent / \
215 "test/resources/arch/custom_usages/" \
216 "UseConditionsFM_ARC_DigitalHub.json"
217 project.sim_settings.prj_custom_usages = Path(
218 bim2sim.__file__).parent.parent / \
219 "test/resources/arch/custom_usages/" \
220 "customUsagesFM_ARC_DigitalHub_with_SB89.json"
221 # project.sim_settings.ep_install_path = 'C://EnergyPlusV9-4-0/'
222 space_boundary_genenerator = 'Other'
223 handle_proxies = (*(None,) * 12,)
224 construction_year = 2015
225 project.sim_settings.setpoints_from_template = True
226 project.sim_settings.add_window_shading = 'Exterior'
227 project.sim_settings.cooling_tz_overwrite = False
228 project.sim_settings.rename_plot_keys = True
230 answers = (space_boundary_genenerator,
231 *handle_proxies,
232 construction_year)
233 handler = DebugDecisionHandler(answers)
234 handler.handle(project.run())
235 self.assertEqual(0, handler.return_value,
236 "Project export and simulation did not finish "
237 "successfully.")
238 reg_test_res = self.run_regression_test()
239 self.assertEqual(True, reg_test_res,
240 "EnergyPlus Regression test did not finish "
241 "successfully or created deviations.")