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

1import os 

2import re 

3import shutil 

4import sys 

5import unittest 

6import logging 

7from pathlib import Path 

8 

9from energyplus_regressions.diffs import math_diff, table_diff 

10from energyplus_regressions.diffs.thresh_dict import ThreshDict 

11 

12import bim2sim 

13from bim2sim.utilities.types import LOD, IFCDomain 

14from bim2sim.kernel.decision.decisionhandler import DebugDecisionHandler 

15from bim2sim.utilities.test import RegressionTestBase 

16 

17logger = logging.getLogger(__name__) 

18 

19 

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() 

30 

31 def tearDown(self): 

32 os.chdir(self.working_dir) 

33 sys.stderr = self.old_stderr 

34 super().tearDown() 

35 

36 def weather_file_path(self) -> Path: 

37 return (self.test_resources_path() / 

38 'weather_files/DEU_NW_Aachen.105010_TMYx.epw') 

39 

40 def create_regression_setup(self): 

41 """ 

42 Create a regression test setup for EnergyPlus. 

43 

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 

49 

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 

84 

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 

99 

100 return passed_regression_test 

101 

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 

116 

117 def create_regression_results(self): 

118 """Creates regression results based on simulation model. 

119 

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'] 

130 

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.") 

147 

148 

149class TestRegressionComfort(RegressionTestComfort, unittest.TestCase): 

150 """Regression tests for EnergyPlus.""" 

151 

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.") 

178 

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.") 

203 

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 

229 

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.")