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
« 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
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
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}
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}
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
349 Parameters
350 ----------
351 result_arrays:
352 femzip arrays
353 """
354 mapper = FemzipMapper()
355 mapper.map(result_arrays)
357 return mapper.d3plot_arrays
360class ArrayShapeInfo:
361 """ArrayShapeInfo describes the shape of arrays"""
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
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))
376 def set_n_layers(self, n_layers: Union[int, None]) -> None:
377 """Set the number of layers
379 Parameters
380 ----------
381 n_layers : Union[int, None]
382 number of layers
383 """
384 self._set_attr("n_layers", n_layers)
386 def set_n_vars(self, n_vars: Union[int, None]) -> None:
387 """Set the number of variables
389 Parameters
390 ----------
391 n_vars : Union[int, None]
392 number of variables
393 """
394 self._set_attr("n_vars", n_vars)
396 def set_n_entries(self, n_entries: Union[int, None]) -> None:
397 """Set the number of entries
399 Parameters
400 ----------
401 n_vars : Union[int, None]
402 number of entries
403 """
404 self._set_attr("n_entries", n_entries)
406 def set_n_timesteps(self, n_timesteps: Union[int, None]) -> None:
407 """Set the number of timesteps
409 Parameters
410 ----------
411 n_vars : Union[int, None]
412 number of timesteps
413 """
414 self._set_attr("n_timesteps", n_timesteps)
416 def to_shape(self) -> Tuple[int, ...]:
417 """Set the number of variables
419 Returns
420 ----------
421 shape : Tuple[int, ...]
422 total shape
423 """
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)
434class D3plotArrayMapping:
435 """D3plotArrayMapping maps femzip arrays to d3plot arrays"""
437 d3plot_array_type: str
438 d3_layer_slice: Union[slice, int, None] = None
439 d3_var_slice: Union[slice, int, None] = None
441 fz_layer_slice: Union[slice, int, None] = None
442 fz_var_slice: Union[slice, int, None] = None
444 just_assign: bool = False
446 def to_slice(self) -> Tuple[Union[int, slice], ...]:
447 """Get the slices mapping a femzip array to a d3plot array
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)
461class FemzipArrayInfo:
462 """FemzipArrayInfo contains information about the femzip array"""
464 # pylint: disable = too-many-instance-attributes
466 full_name: str = ""
467 short_name: str = ""
468 index: int = -1
469 category: FemzipVariableCategory
470 array_type: FemzipArrayType
471 array: np.ndarray
473 i_layer: Union[int, None] = None
474 i_var: Union[int, None] = None
476 mappings: List[D3plotArrayMapping]
478 def __init__(self):
479 self.mappings = []
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}"""
492class FemzipMapper:
493 """Class for mapping femzip variable data to d3plots."""
495 # regex pattern for reading variables
496 name_separation_pattern = re.compile(r"(^[^(\n]+)(\([^\)]+\))*")
498 FORTRAN_OFFSET: int = 1
500 _d3plot_arrays: Dict[str, np.ndarray] = {}
501 _fz_array_slices = {}
503 def __init__(self):
504 pass
506 def map(self, result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray]):
507 """Map femzip data to d3plot arrays.
509 Parameters
510 ----------
511 result_arrays:
512 femzip variable data
513 """
514 self._d3plot_arrays = {}
515 self._fz_array_slices = {}
517 # convert to internal datastructure
518 array_infos = self._convert(result_arrays)
520 # build the array shapes
521 d3plot_array_shapes = self._build(array_infos)
523 # init the numpy arrays
524 self._d3plot_arrays = self._allocate_d3plot_arrays(d3plot_array_shapes)
526 # add all the data to its right place
527 self._map_arrays(array_infos, self._d3plot_arrays)
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
534 Parameters
535 ----------
536 result_arrays: Dict[Tuple[int, str, FemzipVariableCategory], np.ndarray]
537 result arrays from femzip
539 Returns
540 -------
541 array_infos: List[FemzipArrayInfo]
542 infos about femzip arrays
543 """
545 array_infos = []
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)
556 var_name, i_layer, i_stress, i_history = self._parse_femzip_name(fz_name, fz_cat)
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
562 array_infos.append(femzip_array_info)
564 return array_infos
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.
571 Parameters
572 ---------
573 fz_arrays: List[FemzipArrayInfo]
574 infos about femzip arrays
576 Returns
577 -------
578 d3plot_array_shapes:
579 shapes of the d3plot arrays required to be allocated
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] = {}
589 for arr_info in fz_arrays:
590 # print(arr_info)
592 d3_array_types = TRANSL_FEMZIP_ARRATYPE_TO_D3PLOT_ARRAYTYPE[
593 (arr_info.array_type, arr_info.category)
594 ]
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()
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
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)
616 shape_infos[array_type] = array_shape_info
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
634 arr_info.mappings.append(mapping)
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)]
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
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
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
661 d3_array_types = TRANSL_FEMZIP_ARRATYPE_TO_D3PLOT_ARRAYTYPE[
662 (arr_info.array_type, arr_info.category)
663 ]
665 for array_type in d3_array_types:
666 del shape_infos[array_type]
668 return {name: info.to_shape() for name, info in shape_infos.items()}
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.
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
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
698 slices = mapping.to_slice()
699 d3plot_array = d3plot_arrays[mapping.d3plot_array_type]
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)
705 d3plot_array[slices] = arr_info.array
707 def _allocate_d3plot_arrays(
708 self, array_shapes: Dict[str, Tuple[int, ...]]
709 ) -> Dict[str, np.ndarray]:
710 """Initialize all the d3plot arrays.
712 Parameters
713 ----------
714 array_shapes: array_shapes: Dict[str, Tuple[int, ...]]
715 array shapes required to be allocated
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
727 @property
728 def d3plot_arrays(self):
729 """Returns the mapped d3plot arrays."""
730 return self._d3plot_arrays
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.
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.
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))
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()
767 # the slice 1:-1 leaves out the brackets '(' and ')'
768 _, i_layer = get_last_int_of_line(second_grp[1:-1])
770 if i_layer is not None:
771 i_layer -= self.FORTRAN_OFFSET
773 i_history: Union[int, None] = None
775 if var_type != FemzipVariableCategory.PART or var_type != FemzipVariableCategory.GLOBAL:
776 i_history = extra_value
778 if i_history:
779 i_history -= self.FORTRAN_OFFSET
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
792 i_stress: Union[int, None] = stress_index.get(var_name, None)
794 return var_name, i_layer, i_stress, i_history
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
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
809 Returns
810 -------
811 file_metadata: FemzipFileMetadata
812 filtered array according to array types
813 """
815 # pylint: disable = too-many-locals
817 # find out which arrays we need and
818 vars_to_copy: List[int] = []
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")
827 logging.debug("%d, %d, %s", var_type, var_index, var_name.strip())
829 if var_type == FemzipVariableCategory.GEOMETRY.value:
830 continue
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
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 ]
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)
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)
862 # pylint: disable = invalid-name
863 FilteredVariableInfoArrayType = len(vars_to_copy) * VariableInfo
864 filtered_info_array_data = FilteredVariableInfoArrayType()
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
872 return filtered_file_metadata