Coverage for steam_pysigma\comsol\BuildGlobalVariables.py: 81%

191 statements  

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

1# STEAM PySigma is a python wrapper of STEAM-SIGMA written in Java. 

2# Copyright (C) 2023, CERN, Switzerland. All rights reserved. 

3# 

4# This program is free software: you can redistribute it and/or modify 

5# it under the terms of the GNU General Public License as published by 

6# the Free Software Foundation, version 3 of the License. 

7# 

8# This program is distributed in the hope that it will be useful, 

9# but WITHOUT ANY WARRANTY; without even the implied warranty of 

10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

11# GNU General Public License for more details. 

12# 

13# You should have received a copy of the GNU General Public License 

14# along with this program. If not, see <https://www.gnu.org/licenses/>. 

15 

16import logging 

17import os 

18 

19class BuildGlobalVariables: 

20 

21 def __init__(self, g, model_data): 

22 self.g = g 

23 self.model_data = model_data 

24 

25 

26 def validate_sigma_model_data(self): 

27 """ 

28 Method checks the SIGMA options in the model_data to be valid to parse into SIGMA. 

29 :return: 

30 """ 

31 model_data = self.model_data 

32 constants = self.g.MPHC 

33 logging.getLogger().setLevel(logging.INFO) 

34 

35 # logging.warning('And this, too') 

36 options_sigma = model_data.Options_SIGMA 

37 # Check key time_vector_solution.time_step 

38 time_step = options_sigma.time_vector_solution.time_step 

39 # Check type list[list] with three values 

40 if type(time_step) == list: 

41 if any(isinstance(el, list) for el in time_step): 

42 # Check data in vector is valid; 

43 for i in range(len(time_step)): 

44 if len(time_step[i]) == 3: 

45 if time_step[i][0] > time_step[i][2]: 

46 raise ValueError( 

47 "options_sigma.time_vector_solution.time_step has invalid data. Start value can not be larger than end value.") 

48 else: 

49 pass 

50 if i <= len(time_step) - 2: 

51 if time_step[i][2] > time_step[i + 1][0]: 

52 raise ValueError( 

53 "options_sigma.time_vector_solution.time_step has overlapping time step intervals") 

54 else: 

55 raise ValueError( 

56 "options_sigma.time_vector_solution.time_step has invalid data. Three element per sublist needed") 

57 

58 # Check options_sigma.simulation 

59 study_type = options_sigma.simulation.study_type 

60 print(f"Running study type: {study_type}") 

61 if study_type == constants.LABEL_TRANSIENT or study_type == constants.LABEL_STATIONARY: 

62 pass 

63 else: 

64 raise ValueError(f"String is not Transient or Stationary.") 

65 

66 # Check options_sigma.physics 

67 if study_type == constants.LABEL_TRANSIENT: 

68 for key, value in options_sigma.physics: 

69 if key == "tauCC_PE": 

70 pass 

71 elif value is None: 

72 raise ValueError(f'{key} is set to null. To make sigma run this will be set to 0 as default.') 

73 

74 # Check options_sigma.quench_initialization only valid if Transient 

75 if options_sigma.simulation.study_type == constants.LABEL_TRANSIENT: 

76 for key, value in options_sigma.quench_initialization: 

77 if "FLAG" in key: 

78 if value is None: 

79 raise ValueError(f'{key} is set to null. To make sigma run this will be set to 0 as default.') 

80 if key == "num_qh_div": 

81 if len(value) != model_data.Quench_Protection.Quench_Heaters.N_strips: 

82 raise ValueError( 

83 f"The number of quench heater divisions must be {model_data.Quench_Protection.Quench_Heaters.N_strips}") 

84 if key == "quench_init_heat": 

85 if value is None: 

86 raise ValueError(f"{key} can't be none") 

87 else: 

88 if value < 0: 

89 raise ValueError("Power for initialize quench can't be negative") 

90 if key == "quench_stop_temp": 

91 if value is None: 

92 raise ValueError(f"{key} can't be none") 

93 if value < 0: 

94 raise ValueError("Tempereatur for initialize quench can't be negative") 

95 

96 # Check options_sigma.postprocessing.out_2D_at_points 

97 options_sigma.postprocessing.out_2D_at_points.coordinate_source = None 

98 for key, value in options_sigma.postprocessing.out_2D_at_points: 

99 if key == "coordinate_source": 

100 # Check if source exists 

101 if value is not None: 

102 if not os.path.exists(value): 

103 raise ValueError("Given coordinate file path does not exist") 

104 

105 else: 

106 logging.info("Using coordinate file to evaluate 2D plots") 

107 

108 if options_sigma.simulation.study_type == constants.LABEL_TRANSIENT: 

109 if key == "time": 

110 # Check number of values 

111 if len(value) != len(options_sigma.postprocessing.out_2D_at_points.variables): 

112 raise ValueError("Number of time vectors must be the same as number of variables.") 

113 else: 

114 for i in range(len(value)): 

115 if len(value[i]) == 3: 

116 if value[0] > value[2]: 

117 raise ValueError( 

118 "options_sigma.postprocessing.out_2D_at_points.time has invalid data. Start value can not be larger than end value.") 

119 else: 

120 pass 

121 else: 

122 raise ValueError( 

123 "options_sigma.postprocessing.out_2D_at_points.time has invalid data. Three elements needed.") 

124 if options_sigma.simulation.study_type == constants.LABEL_TRANSIENT: 

125 for key, value in options_sigma.postprocessing.out_1D_vs_times: 

126 if key == "time": 

127 # Check number of values 

128 if len(value) != len(options_sigma.postprocessing.out_1D_vs_times.variables): 

129 raise ValueError("Number of time vectors must be the same as number of variables.") 

130 else: 

131 for i in range(len(value)): 

132 if len(value[i]) == 3: 

133 if value[i][0] > value[i][2]: 

134 raise ValueError( 

135 f"options_sigma.postprocessing.out_1D_vs_times.time has invalid data for value {value}. Start value can not be larger than end value.") 

136 else: 

137 raise ValueError( 

138 "options_sigma.postprocessing.out_1D_vs_times.time has invalid data. Three elements needed.") 

139 

140 # options_sigma.quench_heaters 

141 if options_sigma.simulation.study_type == constants.LABEL_TRANSIENT: 

142 th_coils = options_sigma.quench_heaters.th_coils 

143 if 0 in th_coils: 

144 raise ValueError("List contains zero values, change model_data.yaml to valid value.") 

145 

146 if self.model_data.Quench_Protection.Quench_Heaters.N_strips == None: 

147 raise ValueError("N_strips can't be null. Edit the model_data.yaml file.") 

148 

149 def helper_check_time_step_valid(self, time_step): 

150 if type(time_step) == list: 

151 if any(isinstance(el, list) for el in time_step): 

152 # Check data in vector is valid; 

153 for i in range(len(time_step)): 

154 if len(time_step[i]) == 3: 

155 if time_step[i][0] > time_step[i][2]: 

156 raise ValueError( 

157 "#options_sigma.time_vector_solution.time_step has invalid data. Start value can not be larger than end value.") 

158 else: 

159 pass 

160 if i <= len(time_step) - 2: 

161 if time_step[i][2] > time_step[i + 1][0]: 

162 raise ValueError( 

163 "options_sigma.time_vector_solution.time_step has overlapping time step intervals") 

164 else: 

165 raise ValueError( 

166 "options_sigma.time_vector_solution.time_step has invalid data. Three element per sublist needed") 

167 def build_global_variables(self): 

168 """ 

169 Function builds all global variables nessesary for QH simulations. 

170 :return: map with global variables 

171 """ 

172 map = self.g.gateway.jvm.java.util.HashMap() 

173 constants = self.g.MPHC 

174 # Cliq variables: 

175 end_sim_time = self.model_data.Options_SIGMA.time_vector_solution.time_step[-1][-1] 

176 

177 R_crow = self.model_data.Circuit.R_circuit 

178 L_circuit = self.model_data.Circuit.L_circuit 

179 C_cliq = self.model_data.Quench_Protection.CLIQ.C 

180 L_cliq = self.model_data.Quench_Protection.CLIQ.L 

181 

182 V_cliq_0 = self.model_data.Quench_Protection.CLIQ.U0 

183 I_cliq_0 = self.model_data.Quench_Protection.CLIQ.I0 

184 

185 sym_factor = self.model_data.Quench_Protection.CLIQ.sym_factor 

186 cliq_time = self.model_data.Quench_Protection.CLIQ.t_trigger 

187 if cliq_time > end_sim_time: 

188 with_cliq = 0 

189 else: 

190 with_cliq = 1 

191 

192 if V_cliq_0 == None: 

193 V_cliq_0 = 0 

194 if I_cliq_0 == None: 

195 I_cliq_0 = 0 

196 if sym_factor == None: 

197 sym_factor = 1 

198 if L_circuit == None: 

199 L_circuit = "1e-6" 

200 if L_cliq == None: 

201 L_cliq = "1e-6" 

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

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

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

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

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

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

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

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

210 

211 FLAG_M_pers = self.model_data.Options_SIGMA.physics.FLAG_M_pers 

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

213 

214 FLAG_ifcc = self.model_data.Options_SIGMA.physics.FLAG_ifcc 

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

216 

217 FLAG_iscc_crossover = self.model_data.Options_SIGMA.physics.FLAG_iscc_crossover 

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

219 

220 FLAG_iscc_adjw = self.model_data.Options_SIGMA.physics.FLAG_iscc_adjw 

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

222 

223 FLAG_iscc_adjn = self.model_data.Options_SIGMA.physics.FLAG_iscc_adjn 

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

225 

226 FLAG_quench_all = self.model_data.Options_SIGMA.quench_initialization.FLAG_quench_all 

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

228 

229 FLAG_quench_off = self.model_data.Options_SIGMA.quench_initialization.FLAG_quench_off 

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

231 

232 PARAM_time_quench = self.model_data.Options_SIGMA.quench_initialization.PARAM_time_quench 

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

234 

235 magnetic_length = self.model_data.GeneralParameters.magnetic_length 

236 T_initial = self.model_data.GeneralParameters.T_initial 

237 

238 quench_heat = self.model_data.Options_SIGMA.quench_initialization.quench_init_heat 

239 quench_temp = self.model_data.Options_SIGMA.quench_initialization.quench_stop_temp 

240 

241 map.put(constants.LABEL_FLAG_IFCC, str(FLAG_ifcc)) 

242 map.put(constants.LABEL_FLAG_ISCC_CROSSOVER, str(FLAG_iscc_crossover)) 

243 map.put(constants.LABEL_FLAG_ISCC_ADJW, str(FLAG_iscc_adjw)) 

244 map.put(constants.LABEL_FLAG_ISCC_ADJN, str(FLAG_iscc_adjn)) 

245 map.put(constants.LABEL_FLAG_MPERS, str(FLAG_M_pers)) 

246 map.put(constants.LABEL_FLAG_QUENCH_ALL, str(FLAG_quench_all)) 

247 map.put(constants.LABEL_FLAG_QUENCH_OFF, str(FLAG_quench_off)) 

248 map.put(constants.LABEL_PARAM_QUENCH_TIME, str(PARAM_time_quench)) 

249 map.put(constants.LABEL_MAGNETIC_LENGTH, str(magnetic_length)) 

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

251 map.put(constants.LABEL_INIT_QUENCH_HEAT, str(quench_heat)) 

252 map.put(constants.LABEL_QUENCH_TEMP, str(quench_temp)) 

253 

254 ins_list = self.model_data.Quench_Protection.Quench_Heaters.s_ins 

255 w_list = self.model_data.Quench_Protection.Quench_Heaters.w 

256 qh_to_bath_list = self.model_data.Quench_Protection.Quench_Heaters.s_ins_He 

257 qh_steel_strip = self.model_data.Quench_Protection.Quench_Heaters.h 

258 tau = [round(a * b, 4) for a, b in 

259 zip(self.model_data.Quench_Protection.Quench_Heaters.R_warm, self.model_data.Quench_Protection.Quench_Heaters.C)] 

260 num_qh_div = self.model_data.Options_SIGMA.quench_initialization.num_qh_div 

261 u_init = self.model_data.Quench_Protection.Quench_Heaters.U0 

262 

263 # In case R_warm = 0 

264 try: i_init = [round(a / b, 3) for a, b in zip(self.model_data.Quench_Protection.Quench_Heaters.U0, 

265 self.model_data.Quench_Protection.Quench_Heaters.R_warm)] 

266 except: i_init = [0 for a, b in zip(self.model_data.Quench_Protection.Quench_Heaters.U0, 

267 self.model_data.Quench_Protection.Quench_Heaters.R_warm)] 

268 

269 frac_heater = self.model_data.Quench_Protection.Quench_Heaters.f_cover 

270 trigger_time = self.model_data.Quench_Protection.Quench_Heaters.t_trigger 

271 ins_thick_to_coil = self.model_data.Options_SIGMA.quench_heaters.th_coils 

272 lengths_qh = self.model_data.Quench_Protection.Quench_Heaters.l 

273 

274 for i in range(self.model_data.Quench_Protection.Quench_Heaters.N_strips): 

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

276 trigger_time[i] = self.model_data.Options_SIGMA.time_vector_solution.time_step[-1][-1] 

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

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

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

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

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

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

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

284 map.put(constants.LABEL_INITIAL_QH_CURRENT + str(i + 1), str(i_init[i])) 

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

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

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

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

289 

290 return map