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

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

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/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 

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

115 

116 def create_regression_results(self): 

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

118 

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

129 

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

146 

147 

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

173 

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