Coverage for steam_pysigma\utils\Utils.py: 91%

243 statements  

« prev     ^ index     » next       coverage.py v7.4.3, created at 2024-12-16 17:09 +0100

1import getpass 

2import logging 

3import os 

4import subprocess 

5from pathlib import Path 

6 

7import numpy as np 

8import pandas as pd 

9import ruamel.yaml 

10from matplotlib import pyplot as plt 

11from steam_pysigma.data.DataSettings import DataSettings 

12 

13logger = logging.getLogger(__name__) 

14 

15 

16def read_data_from_yaml(full_file_path, data_class): 

17 with open(full_file_path, 'r') as stream: 

18 yaml = ruamel.yaml.YAML(typ='safe', pure=True) 

19 yaml_str = yaml.load(stream) 

20 return data_class(**yaml_str) 

21 

22 

23def displayWaitAndClose(waitTimeBeforeMessage: float, waitTimeAfterMessage: float = 0, flag_show_text: bool = True): 

24 """ 

25 

26 **Function useful in Pycharm tests; it allows closing plots after some time that they are displayed ** 

27 

28 Wait a certain time, display a message, and wait a certain time 

29 

30 :param waitTimeBeforeMessage: Time to wait before the message [s] 

31 :type waitTimeBeforeMessage: float 

32 :param waitTimeAfterMessage: Time to wait after the message [s] 

33 :type waitTimeAfterMessage: float 

34 :return: 

35 """ 

36 # Show plots in Pycharm, wait a certain time, alert time is up, and close the window 

37 plt.ion() 

38 plt.tight_layout() 

39 plt.show() 

40 plt.draw() 

41 plt.pause(waitTimeBeforeMessage) 

42 if flag_show_text == True: 

43 plt.title('Figure will close in {} seconds...'.format(waitTimeAfterMessage)) 

44 plt.pause(waitTimeAfterMessage) 

45 

46 

47def create_coordinate_file(path_map2d, coordinate_file_path): 

48 """ 

49 Creates a csv file with same coordinates as the map2d. 

50 

51 :param path_map2d: Map2d file to read coordinates from 

52 :param coordinate_file_path: Path to csv filw to be created 

53 :return: 

54 """ 

55 df = pd.read_csv(path_map2d, delim_whitespace=True) 

56 df_new = pd.DataFrame() 

57 df_new["X-POS/MM"] = df["X-POS/MM"].apply(lambda x: x / 1000) 

58 df_new["Y-POS/MM"] = df["Y-POS/MM"].apply(lambda x: x / 1000) 

59 df_new.to_csv(coordinate_file_path, header=None, index=False) 

60 

61 

62def arcCenter(C, iH, oH, iL, oL, diff_radius=None): 

63 inner_radius = (np.sqrt(np.square(iH.x - C.x) + np.square(iH.y - C.y)) + 

64 np.sqrt(np.square(iL.x - C.x) + np.square(iL.y - C.y))) / 2 

65 if diff_radius: 

66 outer_radius = inner_radius + diff_radius 

67 else: 

68 outer_radius = (np.sqrt(np.square(oH.x - C.x) + np.square(oH.y - C.y)) + 

69 np.sqrt(np.square(oL.x - C.x) + np.square(oL.y - C.y))) / 2 

70 d_inner = [0.5 * abs((iL.x - iH.x)), 0.5 * abs((iH.y - iL.y))] 

71 d_outer = [0.5 * abs((oL.x - oH.x)), 0.5 * abs((oH.y - oL.y))] 

72 aa = [np.sqrt(np.square(d_inner[0]) + np.square(d_inner[1])), 

73 np.sqrt(np.square(d_outer[0]) + np.square(d_outer[1]))] 

74 bb = [np.sqrt(np.square(inner_radius) - np.square(aa[0])), np.sqrt(np.square(outer_radius) - np.square(aa[1]))] 

75 if iL.y < iH.y: 

76 M_inner = [iH.x + d_inner[0], iL.y + d_inner[1]] 

77 M_outer = [oH.x + d_outer[0], oL.y + d_outer[1]] 

78 if iL.y >= 0.: 

79 sign = [-1, -1] 

80 else: 

81 sign = [1, 1] 

82 else: 

83 M_inner = [iH.x + d_inner[0], iH.y + d_inner[1]] 

84 M_outer = [oH.x + d_outer[0], oH.y + d_outer[1]] 

85 if iL.y >= 0.: 

86 sign = [1, -1] 

87 else: 

88 sign = [-1, 1] 

89 inner = [M_inner[0] + sign[0] * bb[0] * d_inner[1] / aa[0], M_inner[1] + sign[1] * bb[0] * d_inner[0] / aa[0]] 

90 outer = [M_outer[0] + sign[0] * bb[1] * d_outer[1] / aa[1], M_outer[1] + sign[1] * bb[1] * d_outer[0] / aa[1]] 

91 return inner, outer 

92 

93 

94def get_user_settings(settings_folder): 

95 """ 

96 Helper function for getting user settings. 

97 :return: dictionary with user settings 

98 :rtype: dict 

99 """ 

100 user_name = getpass.getuser() 

101 if user_name == 'root': 

102 user_name = 'SYSTEM' 

103 elif user_name == 'MP-WIN-02$': 

104 user_name = 'MP_WIN_02' 

105 if not settings_folder: 

106 settings_path = Path.joinpath(Path(__file__).parent.parent.parent, 'tests', f"settings.{user_name}.yaml") 

107 else: 

108 settings_path = Path(settings_folder).joinpath(f"settings.{user_name}.yaml") 

109 if Path.exists(settings_path): 

110 return read_data_from_yaml(settings_path, DataSettings) 

111 else: 

112 raise Exception(f'Settings file: {settings_path} does not exist!') 

113 

114 

115def make_folder_if_not_existing(folder: str, verbose: bool = False): 

116 if not os.path.isdir(folder): 

117 Path(folder).mkdir(parents=True, exist_ok=True) 

118 if verbose: 

119 print("Folder {} does not exist. Making it now".format(folder)) 

120 

121 

122def run(magnet_name, working_dir_path, model_java_file_path, model_class_file_path, output_path, model_name, 

123 split_java_file_path, COMSOL_compile_path, COMSOL_batch_path, compile_batch_file_path, java_jdk_path): 

124 os.chdir(working_dir_path) 

125 with open(model_java_file_path) as java_file: 

126 print("Creating java files initialized.") 

127 max_no_lines = 6e4 

128 public_indexes = [] 

129 files = [] 

130 content = java_file.readlines() 

131 for i, line in enumerate(content): 

132 if "public static" in line: 

133 public_indexes += [i] 

134 

135 no_lines = public_indexes[-1] - public_indexes[0] 

136 no_files = int(np.ceil(no_lines / max_no_lines)) 

137 max_no_lines = round(no_lines / no_files) 

138 real_indexes = [public_indexes[i] - public_indexes[0] for i in range(len(public_indexes))] 

139 closest = [min(real_indexes, key=lambda x: abs(x - max_no_lines * (i + 1))) + public_indexes[0] 

140 for i in range(no_files)] 

141 no_run = [int(content[i][content[i].index('run') + 3:content[i].index('(')]) for i in closest[0:-1]] 

142 no_run += [int(content[public_indexes[-2]][content[public_indexes[-2]].index('run') 

143 + 3:content[public_indexes[-2]].index('(')]) + 1] 

144 additional_lines = {} 

145 for i in range(no_files): 

146 file_path = os.path.join(output_path, model_name) 

147 files += [open(file_path + '_%d.java' % i, 'w')] 

148 name = model_name + '_%d' % i 

149 split_java_file_path += [f"{os.path.join(output_path, model_name + '_%d' % i)}"] 

150 files[i].writelines(content[0:public_indexes[0] - 2] + ['public class ' + name + ' {\n', '\n']) 

151 if i == 0: 

152 files[i].writelines('\tpublic static Model run1(Model mph) {\n') 

153 files[i].writelines(content[public_indexes[0] + 2:closest[i]] + ['}\n']) 

154 additional_lines[name] = {'start': 2, 'end': no_run[i] - 1} 

155 elif i + 1 == no_files: 

156 files[i].writelines(content[closest[i - 1]:public_indexes[-1]] + ['}\n']) 

157 additional_lines[name] = {'start': no_run[i - 1], 'end': len(public_indexes) - 1} 

158 else: 

159 files[i].writelines(content[closest[i - 1]:closest[i]] + ['}\n']) 

160 additional_lines[name] = {'start': no_run[i - 1], 'end': no_run[i] - 1} 

161 files[i].close() 

162 

163 with open(model_java_file_path, 'w') as java_file: 

164 content = content[0:public_indexes[0] + 2] + ['\n'] + \ 

165 content[public_indexes[-1]:public_indexes[-1] + 2] + ['\t}\n'] + ['}\n'] 

166 content.insert(public_indexes[0] + 2, '\t\tmph = ' + model_name + '_0.run1(mph);\n') 

167 ll = 1 

168 for name, item in additional_lines.items(): 

169 for j in range(item['end'] - item['start'] + 1): 

170 content.insert(public_indexes[0] + 2 + ll + j, 

171 '\t\tmph = ' + name + '.run' + str(item['start'] + j) + '(mph);\n') 

172 ll += j + 1 

173 content.insert(public_indexes[0] + 2 + ll, '\t\treturn mph;\n') 

174 content.insert(public_indexes[0] + 3 + ll, '\t}\n') 

175 java_file.writelines(content) 

176 print("Creating java files DONE.") 

177 print("Excecuting bat file") 

178 script_lines = [] 

179 class_paths = '' 

180 for file in split_java_file_path: 

181 script_lines += [f'"{COMSOL_compile_path}" -jdkroot "{java_jdk_path}" -XX:+DisableExplicitGC "{file}.java"', 

182 f'"{java_jdk_path}\\bin\\jar.exe" cf "{file}.jar" "{file}.class"'] 

183 class_paths += f'-classpathadd "{file}.jar" ' 

184 

185 script_lines += [ 

186 f'"{COMSOL_compile_path}" -jdkroot "{java_jdk_path}" {class_paths}"{model_java_file_path}" -XX:+DisableExplicitGC', 

187 f'"{COMSOL_batch_path}" -inputfile "{model_class_file_path}" ' 

188 f'-outputfile "{os.path.join(output_path, magnet_name)}.mph" '] 

189 

190 with open(compile_batch_file_path, "w") as outfile: 

191 outfile.write("\n".join(str(line) for line in script_lines)) 

192 

193 # Excecute process without DriverSIGMA 

194 proc = subprocess.Popen([compile_batch_file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, 

195 universal_newlines=True) 

196 (stdout, stderr) = proc.communicate() 

197 

198 if proc.returncode != 0: 

199 print(stderr) 

200 else: 

201 print(stdout) 

202 

203 

204def build_global_variables(g, model_data): 

205 map = g.gateway.jvm.java.util.HashMap() 

206 constants = g.constants 

207 end_sim_time = model_data.Options_SIGMA.time_vector_solution.time_step[-1][-1] 

208 # Cliq variables: 

209 R_crow = model_data.Circuit.R_circuit 

210 L_circuit = model_data.Circuit.L_circuit 

211 C_cliq = model_data.Quench_Protection.CLIQ.C 

212 L_cliq = model_data.Quench_Protection.CLIQ.L 

213 

214 V_cliq_0 = model_data.Quench_Protection.CLIQ.U0 

215 I_cliq_0 = model_data.Quench_Protection.CLIQ.I0 

216 

217 sym_factor = model_data.Quench_Protection.CLIQ.sym_factor 

218 cliq_time = model_data.Quench_Protection.CLIQ.t_trigger 

219 if cliq_time > end_sim_time: 

220 with_cliq = 0 

221 else: 

222 with_cliq = 1 

223 

224 if V_cliq_0 == None: 

225 V_cliq_0 = 0 

226 if I_cliq_0 == None: 

227 I_cliq_0 = 0 

228 if sym_factor == None: 

229 sym_factor = 1 

230 if L_circuit == None: 

231 L_circuit = "1e-6" 

232 if L_cliq == None: 

233 L_cliq = "1e-6" 

234 map.put(constants.LABEL_CLIQ_RCROW, str(R_crow)) 

235 map.put(constants.LABEL_CLIQ_LCIR, str(L_circuit)) 

236 map.put(constants.LABEL_CLIQ_CAPASITOR, str(C_cliq)) 

237 map.put(constants.LABEL_CLIQ_INDUCTANCE, str(L_cliq)) 

238 map.put(constants.LABEL_CLIQ_VOLTAGE_INITIAL, str(V_cliq_0)) 

239 map.put(constants.LABEL_CLIQ_CURRENT_INITIAL, str(I_cliq_0)) 

240 map.put(constants.LABEL_CLIQ_SYMFACTOR, str(sym_factor)) 

241 map.put(constants.LABEL_CLIQ_SWITCH, str(with_cliq)) 

242 

243 FLAG_M_pers = model_data.Options_SIGMA.physics.FLAG_M_pers 

244 FLAG_M_pers = "0" if FLAG_M_pers is None else FLAG_M_pers 

245 

246 FLAG_ifcc = model_data.Options_SIGMA.physics.FLAG_ifcc 

247 FLAG_ifcc = "0" if FLAG_ifcc is None else FLAG_ifcc 

248 

249 FLAG_iscc_crossover = model_data.Options_SIGMA.physics.FLAG_iscc_crossover 

250 FLAG_iscc_crossover = "0" if FLAG_iscc_crossover is None else FLAG_iscc_crossover 

251 

252 FLAG_iscc_adjw = model_data.Options_SIGMA.physics.FLAG_iscc_adjw 

253 FLAG_iscc_adjw = "0" if FLAG_iscc_adjw is None else FLAG_iscc_adjw 

254 

255 FLAG_iscc_adjn = model_data.Options_SIGMA.physics.FLAG_iscc_adjn 

256 FLAG_iscc_adjn = "0" if FLAG_iscc_adjn is None else FLAG_iscc_adjn 

257 

258 FLAG_quench_all = model_data.Options_SIGMA.quench_initialization.FLAG_quench_all 

259 FLAG_quench_all = "0" if FLAG_quench_all is None else FLAG_quench_all 

260 

261 FLAG_quench_off = model_data.Options_SIGMA.quench_initialization.FLAG_quench_off 

262 FLAG_quench_off = "0" if FLAG_quench_off is None else FLAG_quench_off 

263 

264 PARAM_time_quench = model_data.Options_SIGMA.quench_initialization.PARAM_time_quench 

265 PARAM_time_quench = "0" if PARAM_time_quench is None else PARAM_time_quench 

266 

267 magnetic_length = model_data.GeneralParameters.magnetic_length 

268 T_initial = model_data.GeneralParameters.T_initial 

269 

270 map.put(constants.LABEL_FLAG_IFCC, FLAG_ifcc) 

271 map.put(constants.LABEL_FLAG_ISCC_CROSSOVER, FLAG_iscc_crossover) 

272 map.put(constants.LABEL_FLAG_ISCC_ADJW, FLAG_iscc_adjw) 

273 map.put(constants.LABEL_FLAG_ISCC_ADJN, FLAG_iscc_adjn) 

274 map.put(constants.LABEL_FLAG_MPERS, FLAG_M_pers) 

275 map.put(constants.LABEL_FLAG_QUENCH_ALL, FLAG_quench_all) 

276 map.put(constants.LABEL_FLAG_QUENCH_OFF, FLAG_quench_off) 

277 map.put(constants.LABEL_PARAM_QUENCH_TIME, PARAM_time_quench) 

278 map.put(constants.LABEL_MAGNETIC_LENGTH, magnetic_length) 

279 map.put(constants.LABEL_OPERATIONAL_TEMPERATUR, str(T_initial)) 

280 map.put(constants.LABEL_INIT_QUENCH_HEAT, str(50000)) 

281 map.put(constants.LABEL_QUENCH_TEMP, str(10)) 

282 

283 num_qh = model_data.Quench_Protection.Quench_Heaters.N_strips 

284 ins_list = model_data.Quench_Protection.Quench_Heaters.s_ins 

285 w_list = model_data.Quench_Protection.Quench_Heaters.w 

286 qh_to_bath_list = model_data.Quench_Protection.Quench_Heaters.s_ins_He 

287 qh_steel_strip = model_data.Quench_Protection.Quench_Heaters.h 

288 tau = [round(a * b, 4) for a, b in zip(model_data.Quench_Protection.Quench_Heaters.R_warm, 

289 model_data.Quench_Protection.Quench_Heaters.C)] 

290 num_qh_div = model_data.Options_SIGMA.quench_initialization.num_qh_div 

291 u_init = model_data.Quench_Protection.Quench_Heaters.U0 

292 frac_heater = [round(a / b, 4) for a, b in 

293 zip(model_data.Quench_Protection.Quench_Heaters.l_stainless_steel, [sum(x) for x in zip( 

294 model_data.Quench_Protection.Quench_Heaters.l_stainless_steel, 

295 model_data.Quench_Protection.Quench_Heaters.l_copper)])] 

296 trigger_time = model_data.Quench_Protection.Quench_Heaters.t_trigger 

297 ins_thick_to_coil = model_data.Options_SIGMA.quench_initialization.th_coils 

298 lengths_qh = model_data.Quench_Protection.Quench_Heaters.l 

299 

300 for i in range(num_qh): 

301 if model_data.Options_SIGMA.time_vector_solution.time_step[-1][-1] < trigger_time[i]: 

302 trigger_time[i] = end_sim_time + model_data.Options_SIGMA.time_vector_solution.time_step[-1][-2] 

303 map.put(constants.LABEL_INSULATION_THICKNESS_QH_TO_COIL + str(i + 1), str(ins_list[i])) 

304 map.put(constants.LABEL_WIDTH_QH + str(i + 1), str(w_list[i])) 

305 map.put(constants.LABEL_INSULATION_THICKNESS_QH_TO_BATH + str(i + 1), str(qh_to_bath_list[i])) 

306 map.put(constants.LABEL_INSULATION_THICKNESS_QH_STRIP + str(i + 1), str(qh_steel_strip[i])) 

307 map.put(constants.LABEL_EXPONENTIAL_TIME_CONSTANT_DECAY + str(i + 1), str(tau[i])) 

308 map.put(constants.LABEL_NUMBER_OF_QH_SUBDIVISIONS + str(i + 1), str(num_qh_div[i])) 

309 map.put(constants.LABEL_QH + constants.LABEL_L + str(i + 1), str(lengths_qh[i])) 

310 map.put(constants.LABEL_QH + str(i + 1) + constants.LABEL_FRACTION_OF_QH_STATION, str(frac_heater[i])) 

311 map.put(constants.LABEL_TRIGGER_TIME_QH + str(i + 1), str(trigger_time[i])) 

312 map.put(constants.LABEL_INSULATION_THICKNESS_TO_COIL + str(i + 1), str(ins_thick_to_coil[i])) 

313 map.put(constants.LABEL_INITIAL_QH_VOLTAGE + str(i + 1), str(u_init[i])) 

314 

315 return map 

316 

317 

318def build_study(study_type, srv, cfg, study_API, timeRange): 

319 if study_type is not None: 

320 if study_type == "Stationary": 

321 # Add code to create and run study 

322 study_API.setNewBasicStationaryStudy(srv, cfg, "sol1") 

323 elif (study_type == "Transient"): 

324 study_API.setNewMonolithicStudy(srv, cfg, "Default_study", timeRange) 

325 

326 

327def create_results(srv, cfg, variables1DvsTime, time2DConverted, variables2DConverted, time1DConverted, 

328 variables1DvsTimeVector, 

329 result_api, input_coordinates_path, path_to_results): 

330 for i in range(len(variables2DConverted)): 

331 if len(time2DConverted) > 1: 

332 time_vector_2D = ', '.join(str(x) for x in time2DConverted[i]) 

333 

334 else: 

335 time_vector_2D = time2DConverted[0] 

336 result_api.create2DResultNode(srv, cfg, variables2DConverted[i], time_vector_2D, f"data {i}", 

337 input_coordinates_path, path_to_results) 

338 for j in range(len(time1DConverted)): 

339 if len(time2DConverted) > 1: 

340 time_vector_1D = ', '.join(str(x) for x in time1DConverted[j]) 

341 

342 else: 

343 time_vector_1D = time1DConverted[0] 

344 

345 if cfg.getStudyType() == "Transient": 

346 for j in range(len(variables1DvsTime)): 

347 result_api.create1DResultNodeAllTimes(srv, cfg, variables1DvsTime[j], f"1DExport_{j}", path_to_results) 

348 

349 for k in range(len(variables1DvsTimeVector)): 

350 result_api.create1DResultNodeTimeVector(srv, cfg, variables1DvsTimeVector[k], time_vector_1D, 

351 f"data {i + j + 1 + k}", path_to_results)