Coverage for lasso/dyna/femzip_mapper.py: 73%

228 statements  

« prev     ^ index     » next       coverage.py v7.2.4, created at 2023-04-28 19:49 +0100

1import logging 

2import re 

3import traceback 

4from typing import Dict, List, Set, Tuple, Union 

5 

6import numpy as np 

7from lasso.dyna.array_type import ArrayType 

8from lasso.femzip.femzip_api import FemzipAPI, FemzipFileMetadata, VariableInfo 

9from lasso.femzip.fz_config import FemzipArrayType, FemzipVariableCategory, get_last_int_of_line 

10 

11 

12TRANSL_FEMZIP_ARRATYPE_TO_D3PLOT_ARRAYTYPE: Dict[ 

13 Tuple[FemzipArrayType, FemzipVariableCategory], Set[str] 

14] = { 

15 # GLOBAL 

16 (FemzipArrayType.GLOBAL_DATA, FemzipVariableCategory.GLOBAL): { 

17 # ArrayType.global_timesteps, 

18 ArrayType.global_internal_energy, 

19 ArrayType.global_kinetic_energy, 

20 ArrayType.global_total_energy, 

21 ArrayType.global_velocity, 

22 }, 

23 # PART 

24 (FemzipArrayType.PART_RESULTS, FemzipVariableCategory.PART): { 

25 ArrayType.part_hourglass_energy, 

26 ArrayType.part_internal_energy, 

27 ArrayType.part_kinetic_energy, 

28 ArrayType.part_mass, 

29 ArrayType.part_velocity, 

30 }, 

31 # NODE 

32 (FemzipArrayType.NODE_DISPLACEMENT, FemzipVariableCategory.NODE): {ArrayType.node_displacement}, 

33 (FemzipArrayType.NODE_ACCELERATIONS, FemzipVariableCategory.NODE): { 

34 ArrayType.node_acceleration 

35 }, 

36 (FemzipArrayType.NODE_VELOCITIES, FemzipVariableCategory.NODE): {ArrayType.node_velocity}, 

37 (FemzipArrayType.NODE_TEMPERATURES, FemzipVariableCategory.NODE): {ArrayType.node_temperature}, 

38 (FemzipArrayType.NODE_HEAT_FLUX, FemzipVariableCategory.NODE): {ArrayType.node_heat_flux}, 

39 (FemzipArrayType.NODE_MASS_SCALING, FemzipVariableCategory.NODE): {ArrayType.node_mass_scaling}, 

40 (FemzipArrayType.NODE_TEMPERATURE_GRADIENT, FemzipVariableCategory.NODE): { 

41 ArrayType.node_temperature_gradient 

42 }, 

43 # BEAM 

44 (FemzipArrayType.BEAM_AXIAL_FORCE, FemzipVariableCategory.BEAM): { 

45 ArrayType.element_beam_axial_force 

46 }, 

47 (FemzipArrayType.BEAM_S_BENDING_MOMENT, FemzipVariableCategory.BEAM): { 

48 ArrayType.element_beam_bending_moment 

49 }, 

50 (FemzipArrayType.BEAM_T_BENDING_MOMENT, FemzipVariableCategory.BEAM): { 

51 ArrayType.element_beam_bending_moment 

52 }, 

53 (FemzipArrayType.BEAM_S_SHEAR_RESULTANT, FemzipVariableCategory.BEAM): { 

54 ArrayType.element_beam_shear_force 

55 }, 

56 (FemzipArrayType.BEAM_T_SHEAR_RESULTANT, FemzipVariableCategory.BEAM): { 

57 ArrayType.element_beam_shear_force 

58 }, 

59 (FemzipArrayType.BEAM_TORSIONAL_MOMENT, FemzipVariableCategory.BEAM): { 

60 ArrayType.element_beam_torsion_moment 

61 }, 

62 (FemzipArrayType.BEAM_AXIAL_STRESS, FemzipVariableCategory.BEAM): { 

63 ArrayType.element_beam_axial_stress 

64 }, 

65 (FemzipArrayType.BEAM_SHEAR_STRESS_RS, FemzipVariableCategory.BEAM): { 

66 ArrayType.element_beam_shear_stress 

67 }, 

68 (FemzipArrayType.BEAM_SHEAR_STRESS_TR, FemzipVariableCategory.BEAM): { 

69 ArrayType.element_beam_shear_stress 

70 }, 

71 (FemzipArrayType.BEAM_PLASTIC_STRAIN, FemzipVariableCategory.BEAM): { 

72 ArrayType.element_beam_plastic_strain 

73 }, 

74 (FemzipArrayType.BEAM_AXIAL_STRAIN, FemzipVariableCategory.BEAM): { 

75 ArrayType.element_beam_axial_strain 

76 }, 

77 # SHELL 

78 (FemzipArrayType.STRESS_X, FemzipVariableCategory.SHELL): {ArrayType.element_shell_stress}, 

79 (FemzipArrayType.STRESS_Y, FemzipVariableCategory.SHELL): {ArrayType.element_shell_stress}, 

80 (FemzipArrayType.STRESS_Z, FemzipVariableCategory.SHELL): {ArrayType.element_shell_stress}, 

81 (FemzipArrayType.STRESS_XY, FemzipVariableCategory.SHELL): {ArrayType.element_shell_stress}, 

82 (FemzipArrayType.STRESS_YZ, FemzipVariableCategory.SHELL): {ArrayType.element_shell_stress}, 

83 (FemzipArrayType.STRESS_XZ, FemzipVariableCategory.SHELL): {ArrayType.element_shell_stress}, 

84 (FemzipArrayType.EFF_PSTRAIN, FemzipVariableCategory.SHELL): { 

85 ArrayType.element_shell_effective_plastic_strain 

86 }, 

87 (FemzipArrayType.HISTORY_VARS, FemzipVariableCategory.SHELL): { 

88 ArrayType.element_shell_history_vars 

89 }, 

90 (FemzipArrayType.BENDING_MOMENT_MX, FemzipVariableCategory.SHELL): { 

91 ArrayType.element_shell_bending_moment 

92 }, 

93 (FemzipArrayType.BENDING_MOMENT_MY, FemzipVariableCategory.SHELL): { 

94 ArrayType.element_shell_bending_moment 

95 }, 

96 (FemzipArrayType.BENDING_MOMENT_MXY, FemzipVariableCategory.SHELL): { 

97 ArrayType.element_shell_bending_moment 

98 }, 

99 (FemzipArrayType.SHEAR_FORCE_X, FemzipVariableCategory.SHELL): { 

100 ArrayType.element_shell_shear_force 

101 }, 

102 (FemzipArrayType.SHEAR_FORCE_Y, FemzipVariableCategory.SHELL): { 

103 ArrayType.element_shell_shear_force 

104 }, 

105 (FemzipArrayType.NORMAL_FORCE_X, FemzipVariableCategory.SHELL): { 

106 ArrayType.element_shell_normal_force 

107 }, 

108 (FemzipArrayType.NORMAL_FORCE_Y, FemzipVariableCategory.SHELL): { 

109 ArrayType.element_shell_normal_force 

110 }, 

111 (FemzipArrayType.NORMAL_FORCE_XY, FemzipVariableCategory.SHELL): { 

112 ArrayType.element_shell_normal_force 

113 }, 

114 (FemzipArrayType.THICKNESS, FemzipVariableCategory.SHELL): {ArrayType.element_shell_thickness}, 

115 (FemzipArrayType.UNKNOWN_1, FemzipVariableCategory.SHELL): { 

116 ArrayType.element_shell_unknown_variables 

117 }, 

118 (FemzipArrayType.UNKNOWN_2, FemzipVariableCategory.SHELL): { 

119 ArrayType.element_shell_unknown_variables 

120 }, 

121 (FemzipArrayType.STRAIN_INNER_X, FemzipVariableCategory.SHELL): { 

122 ArrayType.element_shell_strain 

123 }, 

124 (FemzipArrayType.STRAIN_INNER_Y, FemzipVariableCategory.SHELL): { 

125 ArrayType.element_shell_strain 

126 }, 

127 (FemzipArrayType.STRAIN_INNER_Z, FemzipVariableCategory.SHELL): { 

128 ArrayType.element_shell_strain 

129 }, 

130 (FemzipArrayType.STRAIN_INNER_XY, FemzipVariableCategory.SHELL): { 

131 ArrayType.element_shell_strain 

132 }, 

133 (FemzipArrayType.STRAIN_INNER_YZ, FemzipVariableCategory.SHELL): { 

134 ArrayType.element_shell_strain 

135 }, 

136 (FemzipArrayType.STRAIN_INNER_XZ, FemzipVariableCategory.SHELL): { 

137 ArrayType.element_shell_strain 

138 }, 

139 (FemzipArrayType.STRAIN_OUTER_X, FemzipVariableCategory.SHELL): { 

140 ArrayType.element_shell_strain 

141 }, 

142 (FemzipArrayType.STRAIN_OUTER_Y, FemzipVariableCategory.SHELL): { 

143 ArrayType.element_shell_strain 

144 }, 

145 (FemzipArrayType.STRAIN_OUTER_Z, FemzipVariableCategory.SHELL): { 

146 ArrayType.element_shell_strain 

147 }, 

148 (FemzipArrayType.STRAIN_OUTER_XY, FemzipVariableCategory.SHELL): { 

149 ArrayType.element_shell_strain 

150 }, 

151 (FemzipArrayType.STRAIN_OUTER_YZ, FemzipVariableCategory.SHELL): { 

152 ArrayType.element_shell_strain 

153 }, 

154 (FemzipArrayType.STRAIN_OUTER_XZ, FemzipVariableCategory.SHELL): { 

155 ArrayType.element_shell_strain 

156 }, 

157 (FemzipArrayType.INTERNAL_ENERGY, FemzipVariableCategory.SHELL): { 

158 ArrayType.element_shell_internal_energy 

159 }, 

160 # THICK SHELL 

161 (FemzipArrayType.STRESS_X, FemzipVariableCategory.THICK_SHELL): { 

162 ArrayType.element_tshell_stress 

163 }, 

164 (FemzipArrayType.STRESS_Y, FemzipVariableCategory.THICK_SHELL): { 

165 ArrayType.element_tshell_stress 

166 }, 

167 (FemzipArrayType.STRESS_Z, FemzipVariableCategory.THICK_SHELL): { 

168 ArrayType.element_tshell_stress 

169 }, 

170 (FemzipArrayType.STRESS_XY, FemzipVariableCategory.THICK_SHELL): { 

171 ArrayType.element_tshell_stress 

172 }, 

173 (FemzipArrayType.STRESS_YZ, FemzipVariableCategory.THICK_SHELL): { 

174 ArrayType.element_tshell_stress 

175 }, 

176 (FemzipArrayType.STRESS_XZ, FemzipVariableCategory.THICK_SHELL): { 

177 ArrayType.element_tshell_stress 

178 }, 

179 (FemzipArrayType.EFF_PSTRAIN, FemzipVariableCategory.THICK_SHELL): { 

180 ArrayType.element_tshell_effective_plastic_strain 

181 }, 

182 (FemzipArrayType.STRAIN_OUTER_X, FemzipVariableCategory.THICK_SHELL): { 

183 ArrayType.element_tshell_strain 

184 }, 

185 (FemzipArrayType.STRAIN_OUTER_Y, FemzipVariableCategory.THICK_SHELL): { 

186 ArrayType.element_tshell_strain 

187 }, 

188 (FemzipArrayType.STRAIN_OUTER_Z, FemzipVariableCategory.THICK_SHELL): { 

189 ArrayType.element_tshell_strain 

190 }, 

191 (FemzipArrayType.STRAIN_OUTER_XY, FemzipVariableCategory.THICK_SHELL): { 

192 ArrayType.element_tshell_strain 

193 }, 

194 (FemzipArrayType.STRAIN_OUTER_YZ, FemzipVariableCategory.THICK_SHELL): { 

195 ArrayType.element_tshell_strain 

196 }, 

197 (FemzipArrayType.STRAIN_OUTER_XZ, FemzipVariableCategory.THICK_SHELL): { 

198 ArrayType.element_tshell_strain 

199 }, 

200 (FemzipArrayType.STRAIN_INNER_X, FemzipVariableCategory.THICK_SHELL): { 

201 ArrayType.element_tshell_strain 

202 }, 

203 (FemzipArrayType.STRAIN_INNER_Y, FemzipVariableCategory.THICK_SHELL): { 

204 ArrayType.element_tshell_strain 

205 }, 

206 (FemzipArrayType.STRAIN_INNER_Z, FemzipVariableCategory.THICK_SHELL): { 

207 ArrayType.element_tshell_strain 

208 }, 

209 (FemzipArrayType.STRAIN_INNER_XY, FemzipVariableCategory.THICK_SHELL): { 

210 ArrayType.element_tshell_strain 

211 }, 

212 (FemzipArrayType.STRAIN_INNER_YZ, FemzipVariableCategory.THICK_SHELL): { 

213 ArrayType.element_tshell_strain 

214 }, 

215 (FemzipArrayType.STRAIN_INNER_XZ, FemzipVariableCategory.THICK_SHELL): { 

216 ArrayType.element_tshell_strain 

217 }, 

218 # SOLID 

219 (FemzipArrayType.STRESS_X, FemzipVariableCategory.SOLID): {ArrayType.element_solid_stress}, 

220 (FemzipArrayType.STRESS_Y, FemzipVariableCategory.SOLID): {ArrayType.element_solid_stress}, 

221 (FemzipArrayType.STRESS_Z, FemzipVariableCategory.SOLID): {ArrayType.element_solid_stress}, 

222 (FemzipArrayType.STRESS_XY, FemzipVariableCategory.SOLID): {ArrayType.element_solid_stress}, 

223 (FemzipArrayType.STRESS_YZ, FemzipVariableCategory.SOLID): {ArrayType.element_solid_stress}, 

224 (FemzipArrayType.STRESS_XZ, FemzipVariableCategory.SOLID): {ArrayType.element_solid_stress}, 

225 (FemzipArrayType.EFF_PSTRAIN, FemzipVariableCategory.SOLID): { 

226 ArrayType.element_solid_effective_plastic_strain 

227 }, 

228 (FemzipArrayType.HISTORY_VARS, FemzipVariableCategory.SOLID): { 

229 ArrayType.element_solid_history_variables 

230 }, 

231 (FemzipArrayType.STRAIN_X, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

232 (FemzipArrayType.STRAIN_Y, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

233 (FemzipArrayType.STRAIN_Z, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

234 (FemzipArrayType.STRAIN_XY, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

235 (FemzipArrayType.STRAIN_YZ, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

236 (FemzipArrayType.STRAIN_XZ, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

237 (FemzipArrayType.STRAIN_X, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

238 (FemzipArrayType.STRAIN_Y, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

239 (FemzipArrayType.STRAIN_Z, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

240 (FemzipArrayType.STRAIN_XY, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

241 (FemzipArrayType.STRAIN_YZ, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

242 (FemzipArrayType.STRAIN_XZ, FemzipVariableCategory.SOLID): {ArrayType.element_solid_strain}, 

243 # AIRBAG 

244 (FemzipArrayType.AIRBAG_STATE_GEOM, FemzipVariableCategory.CPM_AIRBAG): { 

245 ArrayType.airbag_n_active_particles, 

246 ArrayType.airbag_bag_volume, 

247 }, 

248 # AIRBAG PARTICLES 

249 (FemzipArrayType.AIRBAG_PARTICLE_GAS_CHAMBER_ID, FemzipVariableCategory.CPM_INT_VAR): { 

250 ArrayType.airbag_particle_gas_id 

251 }, 

252 (FemzipArrayType.AIRBAG_PARTICLE_CHAMBER_ID, FemzipVariableCategory.CPM_INT_VAR): { 

253 ArrayType.airbag_particle_chamber_id 

254 }, 

255 (FemzipArrayType.AIRBAG_PARTICLE_LEAKAGE, FemzipVariableCategory.CPM_INT_VAR): { 

256 ArrayType.airbag_particle_leakage 

257 }, 

258 (FemzipArrayType.AIRBAG_PARTICLE_MASS, FemzipVariableCategory.CPM_FLOAT_VAR): { 

259 ArrayType.airbag_particle_mass 

260 }, 

261 (FemzipArrayType.AIRBAG_PARTICLE_POS_X, FemzipVariableCategory.CPM_FLOAT_VAR): { 

262 ArrayType.airbag_particle_position 

263 }, 

264 (FemzipArrayType.AIRBAG_PARTICLE_POS_Y, FemzipVariableCategory.CPM_FLOAT_VAR): { 

265 ArrayType.airbag_particle_position 

266 }, 

267 (FemzipArrayType.AIRBAG_PARTICLE_POS_Z, FemzipVariableCategory.CPM_FLOAT_VAR): { 

268 ArrayType.airbag_particle_position 

269 }, 

270 (FemzipArrayType.AIRBAG_PARTICLE_VEL_X, FemzipVariableCategory.CPM_FLOAT_VAR): { 

271 ArrayType.airbag_particle_velocity 

272 }, 

273 (FemzipArrayType.AIRBAG_PARTICLE_VEL_Y, FemzipVariableCategory.CPM_FLOAT_VAR): { 

274 ArrayType.airbag_particle_velocity 

275 }, 

276 (FemzipArrayType.AIRBAG_PARTICLE_VEL_Z, FemzipVariableCategory.CPM_FLOAT_VAR): { 

277 ArrayType.airbag_particle_velocity 

278 }, 

279 (FemzipArrayType.AIRBAG_PARTICLE_RADIUS, FemzipVariableCategory.CPM_FLOAT_VAR): { 

280 ArrayType.airbag_particle_radius 

281 }, 

282 (FemzipArrayType.AIRBAG_PARTICLE_SPIN_ENERGY, FemzipVariableCategory.CPM_FLOAT_VAR): { 

283 ArrayType.airbag_particle_spin_energy 

284 }, 

285 (FemzipArrayType.AIRBAG_PARTICLE_TRAN_ENERGY, FemzipVariableCategory.CPM_FLOAT_VAR): { 

286 ArrayType.airbag_particle_translation_energy 

287 }, 

288 (FemzipArrayType.AIRBAG_PARTICLE_NEIGHBOR_DIST, FemzipVariableCategory.CPM_FLOAT_VAR): { 

289 ArrayType.airbag_particle_nearest_segment_distance 

290 }, 

291} 

292 

293# indexes for various femzip arrays 

294stress_index = { 

295 FemzipArrayType.STRESS_X.value: 0, 

296 FemzipArrayType.STRESS_Y.value: 1, 

297 FemzipArrayType.STRESS_Z.value: 2, 

298 FemzipArrayType.STRESS_XY.value: 3, 

299 FemzipArrayType.STRESS_YZ.value: 4, 

300 FemzipArrayType.STRESS_XZ.value: 5, 

301 FemzipArrayType.NORMAL_FORCE_X.value: 0, 

302 FemzipArrayType.NORMAL_FORCE_Y.value: 1, 

303 FemzipArrayType.NORMAL_FORCE_XY.value: 2, 

304 FemzipArrayType.SHEAR_FORCE_X.value: 0, 

305 FemzipArrayType.SHEAR_FORCE_Y.value: 1, 

306 FemzipArrayType.STRAIN_INNER_X.value: 0, 

307 FemzipArrayType.STRAIN_INNER_Y.value: 1, 

308 FemzipArrayType.STRAIN_INNER_Z.value: 2, 

309 FemzipArrayType.STRAIN_INNER_XY.value: 3, 

310 FemzipArrayType.STRAIN_INNER_YZ.value: 4, 

311 FemzipArrayType.STRAIN_INNER_XZ.value: 5, 

312 FemzipArrayType.STRAIN_OUTER_X.value: 0, 

313 FemzipArrayType.STRAIN_OUTER_Y.value: 1, 

314 FemzipArrayType.STRAIN_OUTER_Z.value: 2, 

315 FemzipArrayType.STRAIN_OUTER_XY.value: 3, 

316 FemzipArrayType.STRAIN_OUTER_YZ.value: 4, 

317 FemzipArrayType.STRAIN_OUTER_XZ.value: 5, 

318 FemzipArrayType.BEAM_S_SHEAR_RESULTANT.value: 0, 

319 FemzipArrayType.BEAM_T_SHEAR_RESULTANT.value: 1, 

320 FemzipArrayType.BEAM_S_BENDING_MOMENT.value: 0, 

321 FemzipArrayType.BEAM_T_BENDING_MOMENT.value: 1, 

322 FemzipArrayType.STRAIN_X.value: 0, 

323 FemzipArrayType.STRAIN_Y.value: 1, 

324 FemzipArrayType.STRAIN_Z.value: 2, 

325 FemzipArrayType.STRAIN_XY.value: 3, 

326 FemzipArrayType.STRAIN_YZ.value: 4, 

327 FemzipArrayType.STRAIN_XZ.value: 5, 

328 FemzipArrayType.BEAM_SHEAR_STRESS_RS.value: 0, 

329 FemzipArrayType.BEAM_SHEAR_STRESS_TR.value: 1, 

330 FemzipArrayType.AIRBAG_PARTICLE_POS_X.value: 0, 

331 FemzipArrayType.AIRBAG_PARTICLE_POS_Y.value: 1, 

332 FemzipArrayType.AIRBAG_PARTICLE_POS_Z.value: 2, 

333 FemzipArrayType.AIRBAG_PARTICLE_VEL_X.value: 0, 

334 FemzipArrayType.AIRBAG_PARTICLE_VEL_Y.value: 1, 

335 FemzipArrayType.AIRBAG_PARTICLE_VEL_Z.value: 2, 

336 FemzipArrayType.BENDING_MOMENT_MX.value: 0, 

337 FemzipArrayType.BENDING_MOMENT_MY.value: 1, 

338 FemzipArrayType.BENDING_MOMENT_MXY.value: 2, 

339 FemzipArrayType.UNKNOWN_1.value: 0, 

340 FemzipArrayType.UNKNOWN_2.value: 1, 

341} 

342 

343 

344def femzip_to_d3plot( 

345 result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray] 

346) -> Dict[str, np.ndarray]: 

347 """Map femzip arrays to d3plot arrays 

348 

349 Parameters 

350 ---------- 

351 result_arrays: 

352 femzip arrays 

353 """ 

354 mapper = FemzipMapper() 

355 mapper.map(result_arrays) 

356 

357 return mapper.d3plot_arrays 

358 

359 

360class ArrayShapeInfo: 

361 """ArrayShapeInfo describes the shape of arrays""" 

362 

363 n_layers: Union[int, None] = None 

364 n_vars: Union[int, None] = None 

365 n_entries: Union[int, None] = None 

366 n_timesteps: Union[int, None] = None 

367 

368 def _set_attr(self, attr_name: str, value: Union[int, None]) -> None: 

369 self_attr_value = getattr(self, attr_name) 

370 if value is not None: 

371 if self_attr_value is None: 

372 setattr(self, attr_name, value) 

373 else: 

374 setattr(self, attr_name, max(self_attr_value, value)) 

375 

376 def set_n_layers(self, n_layers: Union[int, None]) -> None: 

377 """Set the number of layers 

378 

379 Parameters 

380 ---------- 

381 n_layers : Union[int, None] 

382 number of layers 

383 """ 

384 self._set_attr("n_layers", n_layers) 

385 

386 def set_n_vars(self, n_vars: Union[int, None]) -> None: 

387 """Set the number of variables 

388 

389 Parameters 

390 ---------- 

391 n_vars : Union[int, None] 

392 number of variables 

393 """ 

394 self._set_attr("n_vars", n_vars) 

395 

396 def set_n_entries(self, n_entries: Union[int, None]) -> None: 

397 """Set the number of entries 

398 

399 Parameters 

400 ---------- 

401 n_vars : Union[int, None] 

402 number of entries 

403 """ 

404 self._set_attr("n_entries", n_entries) 

405 

406 def set_n_timesteps(self, n_timesteps: Union[int, None]) -> None: 

407 """Set the number of timesteps 

408 

409 Parameters 

410 ---------- 

411 n_vars : Union[int, None] 

412 number of timesteps 

413 """ 

414 self._set_attr("n_timesteps", n_timesteps) 

415 

416 def to_shape(self) -> Tuple[int, ...]: 

417 """Set the number of variables 

418 

419 Returns 

420 ---------- 

421 shape : Tuple[int, ...] 

422 total shape 

423 """ 

424 

425 shape = [self.n_timesteps, self.n_entries] 

426 fortran_offset = 1 

427 if self.n_layers is not None: 

428 shape.append(self.n_layers + fortran_offset) 

429 if self.n_vars is not None: 

430 shape.append(self.n_vars + fortran_offset) 

431 return tuple(shape) 

432 

433 

434class D3plotArrayMapping: 

435 """D3plotArrayMapping maps femzip arrays to d3plot arrays""" 

436 

437 d3plot_array_type: str 

438 d3_layer_slice: Union[slice, int, None] = None 

439 d3_var_slice: Union[slice, int, None] = None 

440 

441 fz_layer_slice: Union[slice, int, None] = None 

442 fz_var_slice: Union[slice, int, None] = None 

443 

444 just_assign: bool = False 

445 

446 def to_slice(self) -> Tuple[Union[int, slice], ...]: 

447 """Get the slices mapping a femzip array to a d3plot array 

448 

449 Returns 

450 ------- 

451 slices: Tuple[Union[int, slice], ...] 

452 """ 

453 slices: List[Union[slice, int]] = [slice(None), slice(None)] 

454 if self.d3_layer_slice is not None: 

455 slices.append(self.d3_layer_slice) 

456 if self.d3_var_slice is not None: 

457 slices.append(self.d3_var_slice) 

458 return tuple(slices) 

459 

460 

461class FemzipArrayInfo: 

462 """FemzipArrayInfo contains information about the femzip array""" 

463 

464 # pylint: disable = too-many-instance-attributes 

465 

466 full_name: str = "" 

467 short_name: str = "" 

468 index: int = -1 

469 category: FemzipVariableCategory 

470 array_type: FemzipArrayType 

471 array: np.ndarray 

472 

473 i_layer: Union[int, None] = None 

474 i_var: Union[int, None] = None 

475 

476 mappings: List[D3plotArrayMapping] 

477 

478 def __init__(self): 

479 self.mappings = [] 

480 

481 def __str__(self) -> str: 

482 return f"""FemzipArrayInfo: 

483 full_name = {self.full_name} 

484 short_name = {self.short_name} 

485 index = {self.index} 

486 category = {self.category} 

487 array_type = {self.array_type}> 

488 i_layer = {self.i_layer} 

489 i_var = {self.i_var}""" 

490 

491 

492class FemzipMapper: 

493 """Class for mapping femzip variable data to d3plots.""" 

494 

495 # regex pattern for reading variables 

496 name_separation_pattern = re.compile(r"(^[^(\n]+)(\([^\)]+\))*") 

497 

498 FORTRAN_OFFSET: int = 1 

499 

500 _d3plot_arrays: Dict[str, np.ndarray] = {} 

501 _fz_array_slices = {} 

502 

503 def __init__(self): 

504 pass 

505 

506 def map(self, result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray]): 

507 """Map femzip data to d3plot arrays. 

508 

509 Parameters 

510 ---------- 

511 result_arrays: 

512 femzip variable data 

513 """ 

514 self._d3plot_arrays = {} 

515 self._fz_array_slices = {} 

516 

517 # convert to internal datastructure 

518 array_infos = self._convert(result_arrays) 

519 

520 # build the array shapes 

521 d3plot_array_shapes = self._build(array_infos) 

522 

523 # init the numpy arrays 

524 self._d3plot_arrays = self._allocate_d3plot_arrays(d3plot_array_shapes) 

525 

526 # add all the data to its right place 

527 self._map_arrays(array_infos, self._d3plot_arrays) 

528 

529 def _convert( 

530 self, result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray] 

531 ) -> List[FemzipArrayInfo]: 

532 """Convert femzip result arrays into array infos 

533 

534 Parameters 

535 ---------- 

536 result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray] 

537 result arrays from femzip 

538 

539 Returns 

540 ------- 

541 array_infos: List[FemzipArrayInfo] 

542 infos about femzip arrays 

543 """ 

544 

545 array_infos = [] 

546 

547 # convert 

548 for (fz_index, fz_name, fz_cat), array in result_arrays.items(): 

549 femzip_array_info = FemzipArrayInfo() 

550 femzip_array_info.index = fz_index 

551 femzip_array_info.full_name = fz_name 

552 femzip_array_info.category = fz_cat 

553 femzip_array_info.array = array 

554 femzip_array_info.array_type = FemzipArrayType.from_string(fz_name) 

555 

556 var_name, i_layer, i_stress, i_history = self._parse_femzip_name(fz_name, fz_cat) 

557 

558 femzip_array_info.short_name = var_name 

559 femzip_array_info.i_layer = i_layer 

560 femzip_array_info.i_var = i_stress if i_stress is not None else i_history 

561 

562 array_infos.append(femzip_array_info) 

563 

564 return array_infos 

565 

566 @staticmethod 

567 def _build(fz_arrays: List[FemzipArrayInfo]) -> Dict[str, Tuple[int, ...]]: 

568 """Counts the occurrence of all variables in the result array such as the 

569 number of layers and stresses. 

570 

571 Parameters 

572 --------- 

573 fz_arrays: List[FemzipArrayInfo] 

574 infos about femzip arrays 

575 

576 Returns 

577 ------- 

578 d3plot_array_shapes: 

579 shapes of the d3plot arrays required to be allocated 

580 

581 Notes 

582 ----- 

583 Some variables only have partial stress results written for Sigma-x and Sigma-y 

584 and layers one to three for example. 

585 """ 

586 shape_infos: Dict[str, ArrayShapeInfo] = {} 

587 name_count: Dict[Tuple[str, FemzipVariableCategory], int] = {} 

588 

589 for arr_info in fz_arrays: 

590 # print(arr_info) 

591 

592 d3_array_types = TRANSL_FEMZIP_ARRATYPE_TO_D3PLOT_ARRAYTYPE[ 

593 (arr_info.array_type, arr_info.category) 

594 ] 

595 

596 # var_name = var_name.strip() 

597 for array_type in d3_array_types: 

598 # print(array_type) 

599 array_shape_info = shape_infos.get(array_type) or ArrayShapeInfo() 

600 

601 # beam layer vars always have same name but 

602 # must be counted up as layers 

603 if (arr_info.full_name, arr_info.category) in name_count: 

604 count = name_count[(arr_info.full_name, arr_info.category)] 

605 i_layer = count + 1 

606 name_count[(arr_info.full_name, arr_info.category)] = i_layer 

607 else: 

608 name_count[(arr_info.full_name, arr_info.category)] = 0 

609 

610 # update shape 

611 array_shape_info.set_n_timesteps(arr_info.array.shape[0]) 

612 array_shape_info.set_n_entries(arr_info.array.shape[1]) 

613 array_shape_info.set_n_layers(arr_info.i_layer) 

614 array_shape_info.set_n_vars(arr_info.i_var) 

615 

616 shape_infos[array_type] = array_shape_info 

617 

618 # where to put it 

619 mapping = D3plotArrayMapping() 

620 mapping.d3plot_array_type = array_type 

621 if arr_info.i_layer is not None: 

622 mapping.d3_layer_slice = arr_info.i_layer 

623 if arr_info.i_var is not None: 

624 mapping.d3_var_slice = arr_info.i_var 

625 # arrays to copy: 

626 # - node displacement, velocity, acceleration 

627 # - airbag integer vars (so we don't need to cast) 

628 if ( 

629 arr_info.array.ndim == 3 

630 or arr_info.category == FemzipVariableCategory.CPM_INT_VAR 

631 ): 

632 mapping.just_assign = True 

633 

634 arr_info.mappings.append(mapping) 

635 

636 # correct layers 

637 # if a field has the same name for multiple 

638 # layers such as beam axial stress, we needed 

639 # to count in order to determine if it had layers 

640 # now we need to correct i_layers from None to 0 for them 

641 name_count2 = {} 

642 for arr_info in fz_arrays: 

643 count = name_count[(arr_info.full_name, arr_info.category)] 

644 

645 if count != 0 and arr_info.i_layer is None: 

646 count2 = name_count2.get((arr_info.full_name, arr_info.category), -1) 

647 count2 += 1 

648 arr_info.i_layer = count2 

649 name_count2[(arr_info.full_name, arr_info.category)] = count2 

650 

651 for mapping in arr_info.mappings: 

652 shape_info = shape_infos[mapping.d3plot_array_type] 

653 shape_info.set_n_layers(count) 

654 mapping.d3_layer_slice = count2 

655 

656 # all arrays which are simply copied (slice has len 2 and only one target) 

657 # get a just assign flag 

658 if len(arr_info.mappings) == 2 and len(arr_info.mappings[0].to_slice()) == 2: 

659 arr_info.mappings[0].just_assign = True 

660 

661 d3_array_types = TRANSL_FEMZIP_ARRATYPE_TO_D3PLOT_ARRAYTYPE[ 

662 (arr_info.array_type, arr_info.category) 

663 ] 

664 

665 for array_type in d3_array_types: 

666 del shape_infos[array_type] 

667 

668 return {name: info.to_shape() for name, info in shape_infos.items()} 

669 

670 def _map_arrays(self, array_infos: List[FemzipArrayInfo], d3plot_arrays: Dict[str, np.ndarray]): 

671 """Allocate a femzip variable to its correct position in 

672 the d3plot array dictionary. 

673 

674 Parameters 

675 --------- 

676 array_infos: List[FemzipArrayInfo] 

677 femzip variables stored in a dictionary 

678 d3plot_arrays: Dict[str, np.ndarray] 

679 d3plot arrays pre-allocated 

680 

681 Notes 

682 ----- 

683 The keys are the femzip array name (un-parsed) 

684 and the category of the variable as an enum. 

685 """ 

686 for arr_info in array_infos: 

687 if arr_info.category == FemzipVariableCategory.CPM_AIRBAG: 

688 d3plot_arrays[ArrayType.airbag_n_active_particles] = arr_info.array[:, :, 0].view( 

689 np.int32 

690 ) 

691 d3plot_arrays[ArrayType.airbag_bag_volume] = arr_info.array[:, :, 1] 

692 else: 

693 for mapping in arr_info.mappings: 

694 if mapping.just_assign: 

695 d3plot_arrays[mapping.d3plot_array_type] = arr_info.array 

696 continue 

697 

698 slices = mapping.to_slice() 

699 d3plot_array = d3plot_arrays[mapping.d3plot_array_type] 

700 

701 # for femzip arrays with same name first var_index is missing 

702 if d3plot_array.ndim == 3 and len(slices) == 2 and arr_info.array.ndim == 2: 

703 slices = (*slices, 0) 

704 

705 d3plot_array[slices] = arr_info.array 

706 

707 def _allocate_d3plot_arrays( 

708 self, array_shapes: Dict[str, Tuple[int, ...]] 

709 ) -> Dict[str, np.ndarray]: 

710 """Initialize all the d3plot arrays. 

711 

712 Parameters 

713 ---------- 

714 array_shapes: array_shapes: Dict[str, Tuple[int, ...]] 

715 array shapes required to be allocated 

716 

717 Returns 

718 ------- 

719 d3plot_arrays: Dict[str, np.ndarray] 

720 d3plot arrays pre-allocated 

721 """ 

722 d3plot_arrays = {} 

723 for key, shape in array_shapes.items(): 

724 d3plot_arrays[key] = np.empty(shape, dtype=np.float32) 

725 return d3plot_arrays 

726 

727 @property 

728 def d3plot_arrays(self): 

729 """Returns the mapped d3plot arrays.""" 

730 return self._d3plot_arrays 

731 

732 def _parse_femzip_name( 

733 self, fz_name: str, var_type: FemzipVariableCategory 

734 ) -> Tuple[str, Union[int, None], Union[int, None], Union[int, None]]: 

735 """Parses the femzip variable names. 

736 

737 Parameters 

738 ---------- 

739 fz_name: 

740 cryptic femzip variable name we need to parse 

741 var_type: 

742 the category of this variable e.g. shells, parts, global etc. 

743 

744 Returns 

745 ------- 

746 var_name: 

747 femzip variable name without integration and layer info 

748 i_layer: 

749 layer index 

750 i_stress: 

751 stress index 

752 i_history: 

753 history variable index 

754 """ 

755 matches = self.name_separation_pattern.findall(fz_name) 

756 if not len(matches) == 1: 

757 err_msg = "Could not match femzip array name: {0}" 

758 raise ValueError(err_msg.format(fz_name)) 

759 if not len(matches[0]) == 2: 

760 err_msg = "Could not match femzip array name: {0}" 

761 raise ValueError(err_msg.format(fz_name)) 

762 

763 (first_grp, second_grp) = matches[0] 

764 var_name, extra_value = get_last_int_of_line(first_grp) 

765 var_name = var_name.strip() 

766 

767 # the slice 1:-1 leaves out the brackets '(' and ')' 

768 _, i_layer = get_last_int_of_line(second_grp[1:-1]) 

769 

770 if i_layer is not None: 

771 i_layer -= self.FORTRAN_OFFSET 

772 

773 i_history: Union[int, None] = None 

774 

775 if var_type != FemzipVariableCategory.PART or var_type != FemzipVariableCategory.GLOBAL: 

776 i_history = extra_value 

777 

778 if i_history: 

779 i_history -= self.FORTRAN_OFFSET 

780 

781 # set var name to the un-formatted femzip array type name 

782 if "Epsilon" in var_name: 

783 var_name = fz_name.strip() 

784 if "inner" in var_name: 

785 i_layer = 0 

786 elif "outer" in var_name: 

787 i_layer = 1 

788 else: 

789 # solid strain 

790 i_layer = 0 

791 

792 i_stress: Union[int, None] = stress_index.get(var_name, None) 

793 

794 return var_name, i_layer, i_stress, i_history 

795 

796 

797def filter_femzip_variables( 

798 file_metadata: FemzipFileMetadata, d3plot_array_filter: Union[Set[str], None] 

799) -> FemzipFileMetadata: 

800 """Filters variable infos regarding d3plot array types 

801 

802 Parameters 

803 ---------- 

804 file_metadata: FemzipFileMetadata 

805 metadata of femzip file including contained variables 

806 d3plot_array_filter: Union[Set[str], None] 

807 array types to filter for if wanted 

808 

809 Returns 

810 ------- 

811 file_metadata: FemzipFileMetadata 

812 filtered array according to array types 

813 """ 

814 

815 # pylint: disable = too-many-locals 

816 

817 # find out which arrays we need and 

818 vars_to_copy: List[int] = [] 

819 

820 for i_var in range(file_metadata.number_of_variables): 

821 try: 

822 var_info: VariableInfo = file_metadata.variable_infos[i_var] 

823 var_type: int = var_info.var_type 

824 var_index: int = var_info.var_index 

825 var_name: str = var_info.name.decode("utf-8") 

826 

827 logging.debug("%d, %d, %s", var_type, var_index, var_name.strip()) 

828 

829 if var_type == FemzipVariableCategory.GEOMETRY.value: 

830 continue 

831 

832 # find out which array from name 

833 try: 

834 fz_array_type = FemzipArrayType.from_string(var_name) 

835 except ValueError: 

836 warn_msg = ( 

837 "Warning: lasso-python does not support femzip result" 

838 f" field '{var_name.strip()}' category type '{var_type}'." 

839 ) 

840 logging.warning(warn_msg) 

841 continue 

842 

843 # check if we asked for the array 

844 matching_array_types = TRANSL_FEMZIP_ARRATYPE_TO_D3PLOT_ARRAYTYPE[ 

845 (fz_array_type, FemzipVariableCategory(var_type)) 

846 ] 

847 

848 if d3plot_array_filter is not None: 

849 if not matching_array_types.intersection(d3plot_array_filter): 

850 continue 

851 vars_to_copy.append(i_var) 

852 except Exception: 

853 trb_msg = traceback.format_exc() 

854 err_msg = "An error occurred while preprocessing femzip variable information: %s" 

855 logging.warning(err_msg, trb_msg) 

856 

857 # copy filtered data 

858 filtered_file_metadata = FemzipFileMetadata() 

859 FemzipAPI.copy_struct(file_metadata, filtered_file_metadata) 

860 filtered_file_metadata.number_of_variables = len(vars_to_copy) 

861 

862 # pylint: disable = invalid-name 

863 FilteredVariableInfoArrayType = len(vars_to_copy) * VariableInfo 

864 filtered_info_array_data = FilteredVariableInfoArrayType() 

865 

866 for i_var, src_i_var in enumerate(vars_to_copy): 

867 FemzipAPI.copy_struct( 

868 file_metadata.variable_infos[src_i_var], filtered_info_array_data[i_var] 

869 ) 

870 filtered_file_metadata.variable_infos = filtered_info_array_data 

871 

872 return filtered_file_metadata