ansys-pyensight-core 0.11.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. ansys/pyensight/core/__init__.py +41 -0
  2. ansys/pyensight/core/common.py +341 -0
  3. ansys/pyensight/core/deep_pixel_view.html +98 -0
  4. ansys/pyensight/core/dockerlauncher.py +1124 -0
  5. ansys/pyensight/core/dvs.py +872 -0
  6. ansys/pyensight/core/enscontext.py +345 -0
  7. ansys/pyensight/core/enshell_grpc.py +641 -0
  8. ansys/pyensight/core/ensight_grpc.py +874 -0
  9. ansys/pyensight/core/ensobj.py +515 -0
  10. ansys/pyensight/core/launch_ensight.py +296 -0
  11. ansys/pyensight/core/launcher.py +388 -0
  12. ansys/pyensight/core/libuserd.py +2110 -0
  13. ansys/pyensight/core/listobj.py +280 -0
  14. ansys/pyensight/core/locallauncher.py +579 -0
  15. ansys/pyensight/core/py.typed +0 -0
  16. ansys/pyensight/core/renderable.py +880 -0
  17. ansys/pyensight/core/session.py +1923 -0
  18. ansys/pyensight/core/sgeo_poll.html +24 -0
  19. ansys/pyensight/core/utils/__init__.py +21 -0
  20. ansys/pyensight/core/utils/adr.py +111 -0
  21. ansys/pyensight/core/utils/dsg_server.py +1220 -0
  22. ansys/pyensight/core/utils/export.py +606 -0
  23. ansys/pyensight/core/utils/omniverse.py +769 -0
  24. ansys/pyensight/core/utils/omniverse_cli.py +614 -0
  25. ansys/pyensight/core/utils/omniverse_dsg_server.py +1196 -0
  26. ansys/pyensight/core/utils/omniverse_glb_server.py +848 -0
  27. ansys/pyensight/core/utils/parts.py +1221 -0
  28. ansys/pyensight/core/utils/query.py +487 -0
  29. ansys/pyensight/core/utils/readers.py +300 -0
  30. ansys/pyensight/core/utils/resources/Materials/000_sky.exr +0 -0
  31. ansys/pyensight/core/utils/support.py +128 -0
  32. ansys/pyensight/core/utils/variables.py +2019 -0
  33. ansys/pyensight/core/utils/views.py +674 -0
  34. ansys_pyensight_core-0.11.0.dist-info/METADATA +309 -0
  35. ansys_pyensight_core-0.11.0.dist-info/RECORD +37 -0
  36. ansys_pyensight_core-0.11.0.dist-info/WHEEL +4 -0
  37. ansys_pyensight_core-0.11.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,2019 @@
1
+ # Copyright (C) 2022 - 2026 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ """Variables module.
24
+
25
+ This module provides simplified interface to compute specific variables via PyEnSight
26
+
27
+ """
28
+ import math
29
+ import os
30
+ from typing import TYPE_CHECKING, Dict, List, Optional, Union
31
+
32
+ from ansys.api.pyensight.calc_funcs import ens_calculator
33
+ from ansys.pyensight.core.utils.parts import convert_variable
34
+ import numpy as np
35
+
36
+ try:
37
+ import ensight
38
+ except ImportError:
39
+ pass
40
+
41
+ if TYPE_CHECKING:
42
+ from ansys.api.pyensight import ensight_api
43
+ from ansys.api.pyensight.ens_part import ENS_PART
44
+ from ansys.api.pyensight.ens_var import ENS_VAR
45
+
46
+ """
47
+ Compute the vector magnitude of the input vector
48
+
49
+ Parameters
50
+ ----------
51
+ inval: list
52
+ the vector components
53
+
54
+ Returns
55
+ -------
56
+ float
57
+ the value of the vector magnitude. 0.0 if the vector is not a 3D vector
58
+
59
+ """
60
+
61
+
62
+ def vec_mag(inval: List[float]) -> float:
63
+ if len(inval) == 3:
64
+ vm = math.sqrt(inval[0] * inval[0] + inval[1] * inval[1] + inval[2] * inval[2])
65
+ else:
66
+ vm = 0.0
67
+ return vm
68
+
69
+
70
+ class Variables:
71
+ """Controls the variables in the current EnSight ``Session`` instance."""
72
+
73
+ def __init__(self, ensight: Union["ensight_api.ensight", "ensight"]):
74
+ self.ensight = ensight
75
+ self._calculator = ens_calculator(self.ensight)
76
+
77
+ @property
78
+ def calculator(self) -> "ens_calculator":
79
+ """
80
+ The calculator interface presents a Pythonic mechanism to access all the
81
+ EnSight calculator functions: :doc:`Calculator Functions <../calc_functions>`.
82
+
83
+ Unlike the native API function :func:`pyensight.ensight_api.variables.evaluate`
84
+ and the object API function :func:`pyensight.ens_globals.ENS_GLOBALS.create_variable`
85
+ which take a string as the function definition, the methods on the calculator
86
+ object take natural Python objects and return any newly created ``ENS_VARIABLE``
87
+ object.
88
+
89
+ Returns
90
+ -------
91
+ ens_calculator
92
+ An object supporting a method for each EnSight calculator function.
93
+
94
+ Examples
95
+ --------
96
+ The following are equivalent:
97
+
98
+ >>> # Native API
99
+ >>> session.ensight.part.select_all()
100
+ >>> session.ensight.variables.evaluate("EleSize = EleSize(plist)")
101
+ >>> var1 = session.ensight.objs.core.VARIABLES["EleSize"][0]
102
+ >>> session.ensight.variables.evaluate("OffsetVar = OffsetVar(plist,Momentum,2e-05)")
103
+ >>> var2 = session.ensight.objs.core.VARIABLES["OffsetVar"][0]
104
+ >>> # Object API
105
+ >>> parts = session.ensight.objs.core.PARTS
106
+ >>> var1 = session.ensight.objs.core.create_variable("EleSize", "EleSize(plist)", sources=parts)
107
+ >>> var2 = session.ensight.objs.core.create_variable("OffsetVar", "OffsetVar(plist,Momentum,2e-05)", sources=parts)
108
+ >>> # ens_calculator API
109
+ >>> parts = session.ensight.objs.core.PARTS
110
+ >>> var1 = session.ensight.utils.variables.calculator.elesize(parts, output_varname="EleSize")
111
+ >>> momentum = session.objs.core.PARTS["Momentum"]
112
+ >>> var2 = session.ensight.utils.variables.calculator.offsetvar(parts, momentum[0], 2.e-5, output_varname="OffsetVar")
113
+
114
+ """
115
+ return self._calculator
116
+
117
+ def _check_for_var_elem(
118
+ self, var_name: str, pobj_list: List["ENS_PART"]
119
+ ) -> Optional["ENS_VAR"]:
120
+ """
121
+ Check for the existence of a variable whose name is the input
122
+ var_name in the list of available variables. Check also if
123
+ the variable is defined in the input part object list
124
+
125
+ Parameters
126
+ ----------
127
+ var_name: str
128
+ the variable name to look for
129
+ pobj_list: list
130
+ the list of parts to see if the variable is defined on them
131
+
132
+ Returns
133
+ -------
134
+ ENS_VAR
135
+ the variable found if defined on all the input parts, None otherwise
136
+ """
137
+ vlist = self.ensight.objs.core.VARIABLES.find(var_name)
138
+ if len(vlist) > 0:
139
+ var = vlist[0]
140
+ # Check to see that selected parts are all
141
+ # within the list of parts used to calc var
142
+ # if NOT then return None
143
+ for prt in pobj_list:
144
+ if prt not in var.PARTS: # pragma: no cover
145
+ return None # pragma: no cover
146
+ return var
147
+ return None
148
+
149
+ def _move_var_to_elem(
150
+ self, pobj_list: List["ENS_PART"], var_obj: "ENS_VAR"
151
+ ) -> Optional[List["ENS_VAR"]]:
152
+ """
153
+ Check the input variable to see if it is an elemental variable.
154
+ If not, compute the equivalent Nodal variable via the NodeToElem
155
+ EnSight calculator function.
156
+
157
+ Parameters
158
+ ----------
159
+ pobj_list: list
160
+ the list of part objects to compute eventually the variable on
161
+ var_obj: ENS_VAR
162
+ the variable object to check
163
+
164
+ Returns
165
+ -------
166
+ list
167
+ A list containing either the original variable if already elemental,
168
+ or the computed nodal equivalent variable
169
+ """
170
+ # get the last created var obj to use as a test to see if a new one is created
171
+ last_var_obj = max(self.ensight.objs.core.VARIABLES)
172
+ #
173
+ var_name = var_obj.DESCRIPTION
174
+ calc_var_name = ""
175
+ if self.ensight.objs.enums.ENS_VAR_ELEM != var_obj.LOCATION:
176
+ calc_var_name = "_E"
177
+ ret_val = self._check_for_var_elem(var_name + calc_var_name, pobj_list)
178
+ if not ret_val:
179
+ print("Calculating elemental variable: {} {}".format(var_name, calc_var_name))
180
+ self.ensight.utils.parts.select_parts(pobj_list)
181
+ calc_string = "(plist," + var_name + ")"
182
+ per_node_var = var_name + calc_var_name + " = NodeToElem"
183
+ temp_string = per_node_var + calc_string
184
+ if not self._calc_var(pobj_list, temp_string): # pragma: no cover
185
+ raise RuntimeError("Failed to calculate elemental variable") # pragma: no cover
186
+ else:
187
+ print(
188
+ "Using elemental variable that already exists: {}".format(ret_val.DESCRIPTION)
189
+ )
190
+ return [ret_val]
191
+
192
+ new_var_obj = max(self.ensight.objs.core.VARIABLES)
193
+ if new_var_obj != last_var_obj: # a new, elemental one was created!
194
+ return [new_var_obj]
195
+ else: # return the input value as a new one wasn't created
196
+ return [var_obj]
197
+
198
+ def _calc_var(
199
+ self, pobj_list: Optional[List["ENS_PART"]] = None, calc_string: Optional[str] = None
200
+ ) -> bool:
201
+ """
202
+ Computes a variable using the input calculator function on
203
+ the input part object list
204
+
205
+ Parameters
206
+ ----------
207
+ pobj_list: list
208
+ the list of part objects to compute the variable on
209
+ calc_string: str
210
+ the calculator function to compute
211
+
212
+ Returns
213
+ -------
214
+ bool
215
+ True if the computation was successful
216
+ """
217
+ err = -1
218
+ if not pobj_list or not calc_string:
219
+ return False
220
+ if len(calc_string) > 0 and len(pobj_list) > 0: # pragma: no cover
221
+ self.ensight.utils.parts.select_parts(pobj_list)
222
+ err = self.ensight.variables.evaluate(calc_string) # ,record=1)
223
+ if err != 0: # pragma: no cover
224
+ err_string = "Error calculating " + calc_string # pragma: no cover
225
+ raise RuntimeError(err_string) # pragma: no cover
226
+ return err == 0
227
+
228
+ def _shear_force_xyz_rtz(
229
+ self,
230
+ pobj_list: Optional[List[Union[str, int, "ENS_PART"]]] = None,
231
+ shear_var_obj: Optional[Union[str, int, "ENS_VAR"]] = None,
232
+ shear_or_force_flag: Optional[str] = "Shear stress",
233
+ frame_index: Optional[int] = 0,
234
+ ) -> bool:
235
+ """
236
+ Compute the shear force in the cartesian and cylindrical space.
237
+ It creates (or recreates) several intermediate vars:
238
+
239
+ - ENS_Force_Norm
240
+
241
+ depending on if the shear variable is Force or Stress:
242
+
243
+ - ENS_Force_Dot_prod_Flu_shear_<Force or Stress>_Norm
244
+ - ENS_Force_NomalShear<Force or Stress>
245
+
246
+ - ENS_Force_TangentialShear<Force or Stress>
247
+
248
+ - ENS_Force_TangentialShear<Force or Stress>_X
249
+ - ENS_Force_TangentialShear<Force or Stress>_Y
250
+ - ENS_Force_TangentialShear<Force or Stress>_Z
251
+
252
+ if the variable is shear stress
253
+ - ENS_Force_ElementArea
254
+
255
+ And finally the shear force components:
256
+ - ENS_Force_TangentialShearForce_X
257
+ - ENS_Force_TangentialShearForce_Y
258
+ - ENS_Force_TangentialShearForce_Z
259
+
260
+ If there is more than one frame and the input frame exists, also the
261
+ cylindrical components are computed, whose names will be:
262
+
263
+ - ENS_Force_Tan_ShearForce (which is a vector composed of the above components)
264
+ - ENS_Force_Tan_ShearForce_cyl (which is cylindrical resolved in the frame index coordinate sys)
265
+ and the components of the cylindrical vector:
266
+ - ENS_Force_Tan_ShearForce_R - Radial component
267
+ - ENS_Force_Tan_ShearForce_T - Theta (angular) component
268
+ - ENS_Force_Tan_ShearForce_A - Axial (frame index Z) component
269
+
270
+ WARNING: Each time you call this function, it
271
+ overwrites all these EnSight variables.
272
+
273
+ WARNING: These variable names are the same
274
+ as the 10.0 Pressure Force Python Tool
275
+
276
+ Parameters
277
+ ----------
278
+ pobj_list: list
279
+ The list of part objects to compute the forces on. It can either be a list of names
280
+ a list of IDs (integers or strings) or directly a list of ENS_PART objects
281
+ var_object: ENS_VAR
282
+ The variable object to use as shear variable. If nodal, it will be converted
283
+ into an elemental variable
284
+ shear_or_force_flag: str
285
+ It can either be "Shear stress" or "Shear force" to indicate the kind of shear variable
286
+ supplied
287
+ frame_index: int
288
+ The eventual frame index on which to compute the cylindrical components of the forces
289
+
290
+ Returns
291
+ -------
292
+ bool
293
+ True if the computation was successful
294
+
295
+ """
296
+ if not frame_index:
297
+ frame_index = 0
298
+ #
299
+ # This pobj_list should contain only 2D parts
300
+ #
301
+
302
+ # tricks for mypy
303
+ varid = convert_variable(self.ensight, shear_var_obj)
304
+ _shear_var_obj: "ENS_VAR"
305
+ values = self.ensight.objs.core.VARIABLES.find(varid, "ID")
306
+ ensvar_values: List["ENS_VAR"]
307
+ ensvar_values = [v for v in values]
308
+ _shear_var_obj = ensvar_values[0]
309
+
310
+ if not pobj_list: # pragma: no cover
311
+ raise RuntimeError("Error, no part provided") # pragma: no cover
312
+ #
313
+ # select all parts in list
314
+ #
315
+ _pobj_list: List["ENS_PART"]
316
+ _pobj_list = self.ensight.utils.parts.select_parts(pobj_list)
317
+ if not _pobj_list: # pragma: no cover
318
+ return False # pragma: no cover
319
+ #
320
+ # can be using shear force or shear stress
321
+ #
322
+ if shear_or_force_flag == "Shear stress": # pragma: no cover
323
+ stemp_string = "Stress"
324
+ else: # pragma: no cover
325
+ stemp_string = "Force" # pragma: no cover
326
+ # create a surface normal vector variable using the
327
+ # "Normal" function in the variable calculator.
328
+ #
329
+ temp_string = "ENS_Force_Norm = Normal(plist)"
330
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
331
+ return False # pragma: no cover
332
+ #
333
+ # makes a new elem var if input var is nodal
334
+ #
335
+ #
336
+ new_shear_var_obj: "ENS_VAR"
337
+ shear_var_name: str
338
+ if _shear_var_obj.LOCATION != self.ensight.objs.enums.ENS_VAR_ELEM: # pragma: no cover
339
+ # tricks for mypy
340
+ values = self._move_var_to_elem(_pobj_list, _shear_var_obj)
341
+ ensvar_values = [v for v in values]
342
+ new_shear_var_obj = ensvar_values[0]
343
+ shear_var_name = new_shear_var_obj.DESCRIPTION
344
+ else: # pragma: no cover
345
+ shear_var_name = _shear_var_obj.DESCRIPTION # pragma: no cover
346
+
347
+ #
348
+ # Compute the Dot product of the Vector Normal and the FluidShearVector
349
+ #
350
+ temp_string = (
351
+ "ENS_Force_Dot_prod_Flu_shear_"
352
+ + stemp_string
353
+ + "_Norm = DOT("
354
+ + shear_var_name
355
+ + ",ENS_Force_Norm)"
356
+ )
357
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
358
+ return False # pragma: no cover
359
+
360
+ # multiplying this DOT product by the surface normal vector produces
361
+ # the normal component of the shear stress vector.
362
+ #
363
+ temp_string = (
364
+ "ENS_Force_NomalShear"
365
+ + stemp_string
366
+ + " = ENS_Force_Dot_prod_Flu_shear_"
367
+ + stemp_string
368
+ + "_Norm*ENS_Force_Norm"
369
+ )
370
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
371
+ return False # pragma: no cover
372
+ #
373
+ # The tangential component is now computed by subtracting this normal
374
+ # component from the shear stress vector, or Vt = V - Vn,
375
+ # where V represents the shear stress vector.
376
+ #
377
+ temp_string = (
378
+ "ENS_Force_TangentialShear"
379
+ + stemp_string
380
+ + " = "
381
+ + shear_var_name
382
+ + "-ENS_Force_NomalShear"
383
+ + stemp_string
384
+ )
385
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
386
+ return False # pragma: no cover
387
+ #
388
+ # Decompose the TangentialShearStress Vector into its x, y, z component of
389
+ # TangentialShearStress_X, TangentialShearStress_Y, and TangentialShearStress_Z
390
+ temp_string = (
391
+ "ENS_Force_TangentialShear"
392
+ + stemp_string
393
+ + "_X = ENS_Force_TangentialShear"
394
+ + stemp_string
395
+ + "[X]"
396
+ )
397
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
398
+ return False # pragma: no cover
399
+
400
+ temp_string = (
401
+ "ENS_Force_TangentialShear"
402
+ + stemp_string
403
+ + "_Y = ENS_Force_TangentialShear"
404
+ + stemp_string
405
+ + "[Y]"
406
+ )
407
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
408
+ return False # pragma: no cover
409
+
410
+ temp_string = (
411
+ "ENS_Force_TangentialShear"
412
+ + stemp_string
413
+ + "_Z = ENS_Force_TangentialShear"
414
+ + stemp_string
415
+ + "[Z]"
416
+ )
417
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
418
+ return False # pragma: no cover
419
+
420
+ #
421
+ #
422
+ # Calculate the Tangential Shear stress forces by multiplying each of the
423
+ # Components of the Tangential Shear stress with Element Size scalar.
424
+ if shear_or_force_flag == "Shear stress": # pragma: no cover
425
+ #
426
+ # Calculate the element area Scalar using the "EleSize function in the Variable Calculator
427
+ #
428
+ temp_string = "ENS_Force_ElementArea = EleSize(plist)"
429
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
430
+ return False # pragma: no cover
431
+
432
+ temp_string = (
433
+ "ENS_Force_Tan_ShearForce_X = ENS_Force_TangentialShear"
434
+ + stemp_string
435
+ + "_X*ENS_Force_ElementArea"
436
+ )
437
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
438
+ return False # pragma: no cover
439
+
440
+ temp_string = (
441
+ "ENS_Force_Tan_ShearForce_Y = ENS_Force_TangentialShear"
442
+ + stemp_string
443
+ + "_Y*ENS_Force_ElementArea"
444
+ )
445
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
446
+ return False # pragma: no cover
447
+
448
+ temp_string = (
449
+ "ENS_Force_Tan_ShearForce_Z = ENS_Force_TangentialShear"
450
+ + stemp_string
451
+ + "_Z*ENS_Force_ElementArea"
452
+ )
453
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
454
+ return False # pragma: no cover
455
+
456
+ else:
457
+ temp_string = ( # pragma: no cover
458
+ "ENS_Force_Tan_ShearForce_X = ENS_Force_TangentialShear" + stemp_string + "_X"
459
+ )
460
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
461
+ return False # pragma: no cover
462
+
463
+ temp_string = ( # pragma: no cover
464
+ "ENS_Force_Tan_ShearForce_Y = ENS_Force_TangentialShear" + stemp_string + "_Y"
465
+ )
466
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
467
+ return False # pragma: no cover
468
+
469
+ temp_string = ( # pragma: no cover
470
+ "ENS_Force_Tan_ShearForce_Z = ENS_Force_TangentialShear" + stemp_string + "_Z"
471
+ )
472
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
473
+ return False # pragma: no cover
474
+
475
+ if frame_index > 0 and frame_index < len(self.ensight.objs.core.FRAMES):
476
+ # remake the vector
477
+ temp_string = "ENS_Force_Tan_ShearForce = MakeVect(plist, ENS_Force_Tan_ShearForce_X, ENS_Force_Tan_ShearForce_Y, ENS_Force_Tan_ShearForce_Z)"
478
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
479
+ return False # pragma: no cover
480
+
481
+ # resolve it in cylindrical coords
482
+ temp_string = (
483
+ "ENS_Force_Tan_ShearForce_cyl = RectToCyl(plist,ENS_Force_Tan_ShearForce,"
484
+ + str(frame_index)
485
+ + ")"
486
+ )
487
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
488
+ return False # pragma: no cover
489
+
490
+ # Radial, theta , axial
491
+ temp_string = "ENS_Force_Tan_ShearForce_R = ENS_Force_Tan_ShearForce_cyl[X]"
492
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
493
+ return False # pragma: no cover
494
+
495
+ temp_string = "ENS_Force_Tan_ShearForce_T = ENS_Force_Tan_ShearForce_cyl[Y]"
496
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
497
+ return False # pragma: no cover
498
+
499
+ temp_string = "ENS_Force_Tan_ShearForce_A = ENS_Force_Tan_ShearForce_cyl[Z]"
500
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
501
+ return False # pragma: no cover
502
+ return True
503
+
504
+ def _sum_shear_forces_xyz_rtz(
505
+ self,
506
+ pobj_list: Optional[List[Union[str, int, "ENS_PART"]]] = None,
507
+ frame_index: Optional[int] = 0,
508
+ ) -> Optional[List[List[float]]]:
509
+ """
510
+ Compute the sum of the shear forces on the input part objects list
511
+ and on the eventual frame selected via the StatMoment calculator function in EnSight
512
+
513
+ Parameters
514
+ ----------
515
+ pobj_list: list
516
+ The list of part objects to compute the forces on. It can either be a list of names
517
+ a list of IDs (integers or strings) or directly a list of ENS_PART objects
518
+ frame_index: int
519
+ The eventual frame index on which to compute the cylindrical components of the forces
520
+
521
+ Returns
522
+ -------
523
+ list
524
+ The list of computed force values. These will be per part constant variables.
525
+ Three if only cartesian, six if also the cylindrical components were computed.
526
+ """
527
+ if not frame_index:
528
+ frame_index = 0
529
+ #
530
+ # This pobj_list should contain only 2D parts
531
+ #
532
+ #
533
+ fcn_name = "sum_shear_forces_xyz_rtz"
534
+ if not pobj_list: # pragma: no cover
535
+ raise RuntimeError("Error, no part provided") # pragma: no cover
536
+ #
537
+ # select all parts in list
538
+ #
539
+ self.ensight.utils.parts.select_parts(pobj_list)
540
+ #
541
+ # Sum up each of the Tangential Shear Stress Force Components to get Constants in each
542
+ # of the directions ENS_Force_Net_Tan_Shear_X, ENS_Force_Net_Tan_Shear_Y, ENS_Force_Net_Tan_Shear_X
543
+ #
544
+ #
545
+ temp_string = "ENS_Force_Net_Tan_ShearForce_X = StatMoment(plist,ENS_Force_Tan_ShearForce_X, 0, Compute_Per_part)"
546
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
547
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
548
+ raise RuntimeError(err_string) # pragma: no cover
549
+
550
+ temp_string = "ENS_Force_Net_Tan_ShearForce_Y = StatMoment(plist,ENS_Force_Tan_ShearForce_Y, 0, Compute_Per_part)"
551
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
552
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
553
+ raise RuntimeError(err_string) # pragma: no cover
554
+
555
+ temp_string = "ENS_Force_Net_Tan_ShearForce_Z = StatMoment(plist,ENS_Force_Tan_ShearForce_Z, 0, Compute_Per_part)"
556
+ if not self._calc_var(pobj_list, temp_string): # pragma: no cover
557
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
558
+ raise RuntimeError(err_string) # pragma: no cover
559
+ #
560
+ # get the 3 constant force values XYZ
561
+ # 10.1.6(b) use ens_utils, 10.2.0(d) Now gets all the per part constants in a list
562
+
563
+ # In this case we know that the value returned by get_const_val will be a List of floats,
564
+ # but mypy doesn't know about it. The next code just makes it happy
565
+ Fx: List[float] = []
566
+ Fy: List[float] = []
567
+ Fz: List[float] = []
568
+ val = self.get_const_val("ENS_Force_Net_Tan_ShearForce_X", pobj_list)
569
+ if not val: # pragma: no cover
570
+ return None # pragma: no cover
571
+ if val:
572
+ if isinstance(val, list):
573
+ for v in val:
574
+ if v is None: # pragma: no cover
575
+ return None # pragma: no cover
576
+ Fx.append(v)
577
+ else:
578
+ return None
579
+ val = self.get_const_val("ENS_Force_Net_Tan_ShearForce_Y", pobj_list)
580
+ if not val: # pragma: no cover
581
+ return None # pragma: no cover
582
+ if val:
583
+ if isinstance(val, list):
584
+ for v in val:
585
+ if v is None: # pragma: no cover
586
+ return None # pragma: no cover
587
+ Fy.append(v)
588
+ else:
589
+ return None
590
+ val = self.get_const_val("ENS_Force_Net_Tan_ShearForce_Z", pobj_list)
591
+ if not val: # pragma: no cover
592
+ return None # pragma: no cover
593
+ if val:
594
+ if isinstance(val, list):
595
+ for v in val:
596
+ if v is None: # pragma: no cover
597
+ return None # pragma: no cover
598
+ Fz.append(v)
599
+ else:
600
+ return None # pragma: no cover
601
+ #
602
+ # Calculate the Total Shear force X, Y, and Z , 10.2.0(d) now case constant variable
603
+ # Totals are a case constants. We don't do anything with these vars
604
+ # they are calc'd to give the user the totals.
605
+ #
606
+ temp_string = "ENS_Force_Total_Net_Tan_ShearForce_X = StatMoment(plist,ENS_Force_Tan_ShearForce_X, 0, Compute_Per_case)"
607
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
608
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
609
+ raise RuntimeError(err_string) # pragma: no cover
610
+
611
+ temp_string = "ENS_Force_Total_Net_Tan_ShearForce_Y = StatMoment(plist,ENS_Force_Tan_ShearForce_Y, 0, Compute_Per_case)"
612
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
613
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
614
+ raise RuntimeError(err_string) # pragma: no cover
615
+
616
+ temp_string = "ENS_Force_Total_Net_Tan_ShearForce_Z = StatMoment(plist,ENS_Force_Tan_ShearForce_Z, 0, Compute_Per_case)"
617
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
618
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
619
+ raise RuntimeError(err_string) # pragma: no cover
620
+
621
+ if frame_index > 0 and frame_index < len(self.ensight.objs.core.FRAMES):
622
+ temp_string = "ENS_Force_Net_Tan_ShearForce_R = StatMoment(plist,ENS_Force_Tan_ShearForce_R,0, Compute_Per_part)"
623
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
624
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
625
+ raise RuntimeError(err_string) # pragma: no cover
626
+
627
+ temp_string = "ENS_Force_Net_Tan_ShearForce_T = StatMoment(plist,ENS_Force_Tan_ShearForce_T,0, Compute_Per_part)"
628
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
629
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
630
+ raise RuntimeError(err_string) # pragma: no cover
631
+
632
+ temp_string = "ENS_Force_Net_Tan_ShearForce_A = StatMoment(plist,ENS_Force_Tan_ShearForce_A,0, Compute_Per_part)"
633
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
634
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
635
+ raise RuntimeError(err_string) # pragma: no cover
636
+ #
637
+ # Totals
638
+ #
639
+ temp_string = "ENS_Force_Total_Net_Tan_ShearForce_R = StatMoment(plist,ENS_Force_Tan_ShearForce_R,0, Compute_Per_case)"
640
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
641
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
642
+ raise RuntimeError(err_string) # pragma: no cover
643
+
644
+ temp_string = "ENS_Force_Total_Net_Tan_ShearForce_T = StatMoment(plist,ENS_Force_Tan_ShearForce_T,0, Compute_Per_case)"
645
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
646
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
647
+ raise RuntimeError(err_string) # pragma: no cover
648
+
649
+ temp_string = "ENS_Force_Total_Net_Tan_ShearForce_A = StatMoment(plist,ENS_Force_Tan_ShearForce_A,0, Compute_Per_case)"
650
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
651
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
652
+ raise RuntimeError(err_string) # pragma: no cover
653
+ #
654
+ # get the 3 constant force values Radial, Theta, Axial
655
+ # new use ens_utils 10.1.6(b)
656
+
657
+ # we know that the output of get_const_val will be a list of floats,
658
+ # buy mypy doesn't know it. So the next code is just to make it happy
659
+
660
+ Fr: List[float] = []
661
+ Ft: List[float] = []
662
+ Fa: List[float] = []
663
+ val = self.get_const_val("ENS_Force_Net_Tan_ShearForce_R", pobj_list)
664
+ if not val: # pragma: no cover
665
+ return None # pragma: no cover
666
+ if val:
667
+ if isinstance(val, list):
668
+ for v in val:
669
+ if v is None: # pragma: no cover
670
+ return None # pragma: no cover
671
+ Fr.append(v)
672
+ else:
673
+ return None # pragma: no cover
674
+ val = self.get_const_val("ENS_Force_Net_Tan_ShearForce_T", pobj_list)
675
+ if not val:
676
+ return None # pragma: no cover
677
+ if val:
678
+ if isinstance(val, list):
679
+ for v in val:
680
+ if v is None: # pragma: no cover
681
+ return None # pragma: no cover
682
+ Ft.append(v)
683
+ else:
684
+ return None
685
+ val = self.get_const_val("ENS_Force_Net_Tan_ShearForce_A", pobj_list)
686
+ if not val: # pragma: no cover
687
+ return None # pragma: no cover
688
+ if val:
689
+ if isinstance(val, list):
690
+ for v in val:
691
+ if v is None: # pragma: no cover
692
+ return None # pragma: no cover
693
+ Fa.append(v)
694
+ else:
695
+ return None # pragma: no cover
696
+ if all([Fr, Fa, Ft, Fx, Fy, Fz]):
697
+ ret_val = []
698
+ for ii in range(len(pobj_list)):
699
+ ret_val.append([Fx[ii], Fy[ii], Fz[ii], Fr[ii], Ft[ii], Fa[ii]])
700
+ return ret_val
701
+ else: # pragma: no cover
702
+ raise RuntimeError(
703
+ "Error getting ENS_Force_Net_Tan_ShearForce_R, T and/or A"
704
+ ) # pragma: no cover
705
+ else: # Only one frame or user picked frame 0 (None) for cylindrical frame calc
706
+ if all([Fx, Fy, Fz]):
707
+ ret_val = []
708
+ for ii in range(len(pobj_list)):
709
+ ret_val.append([Fx[ii], Fy[ii], Fz[ii], 0.0, 0.0, 0.0])
710
+ return ret_val
711
+ else: # pragma: no cover
712
+ raise RuntimeError( # pragma: no cover
713
+ "Error getting Fx, Fy, and/or Fz Shear Net force per part constant values"
714
+ )
715
+
716
+ def get_const_vars(self, var_type: Optional[int] = None) -> List["ENS_VAR"]:
717
+ """
718
+ Get all constant OR per part constant variables
719
+
720
+ Parameters
721
+ ----------
722
+ var_type: int
723
+ enums.ENS_VAR_CONSTANT (default) if not provided
724
+ or enums.ENS_VAR_CONSTANT_PER_PART
725
+
726
+ Returns
727
+ -------
728
+ list
729
+ List containing ENS_VAR objects
730
+ """
731
+ if not var_type:
732
+ var_type = self.ensight.objs.enums.ENS_VAR_CONSTANT
733
+ return [v for v in self.ensight.objs.core.VARIABLES if v.VARTYPE == var_type]
734
+
735
+ def get_const_var_names(self, v_type: Optional[int] = None) -> List[str]:
736
+ """
737
+ Get the names of all constant OR per part constant variables
738
+
739
+ Parameters
740
+ ----------
741
+ v_type: int
742
+ enums.ENS_VAR_CONSTANT (default) if not provided
743
+ or enums.ENS_VAR_CONSTANT_PER_PART
744
+
745
+ Returns
746
+ -------
747
+ list
748
+ List containing names of constants
749
+ """
750
+ if not v_type:
751
+ v_type = self.ensight.objs.enums.ENS_VAR_CONSTANT
752
+ name_list = []
753
+ vars = self.get_const_vars(var_type=v_type)
754
+ for var in vars:
755
+ name_list.append(var.DESCRIPTION)
756
+ return name_list
757
+
758
+ def get_const_val(
759
+ self,
760
+ cname: str,
761
+ part_list: Optional[List[Union[str, int, "ENS_PART"]]] = None,
762
+ undef_none=False,
763
+ ) -> Optional[Union[Optional[float], Optional[List[Optional[float]]]]]:
764
+ """
765
+ Return a float value of a variable Case constant at the current timestep,
766
+ or return a list of values one for each part if a per part constant.
767
+
768
+ Parameters
769
+ ----------
770
+ cname: str
771
+ the text name of the constant or ENS_VAR object
772
+
773
+ part_list: list
774
+ The list of part objects to get the constant values on. It can either be a list of names
775
+ a list of IDs (integers or strings) or directly a list of ENS_PART objects.
776
+ If not provided, all the parts will be considered.
777
+
778
+ undef_none: bool
779
+ if False (default) returns undef value (ensight.Undefined) if var
780
+ value is undefined. If False, for undefined values None will be returned
781
+
782
+ Returns
783
+ -------
784
+ float or list of float:
785
+ if the variable is a constant, it will either return the constant value, ensight.Undefined or None
786
+ depending on the input.
787
+ If the variable is a constant per part, a list of floats, ensight.Undefined or None will be returned
788
+ """
789
+ if not part_list:
790
+ part_list = self.ensight.objs.core.PARTS
791
+ ens_routine = " 'get_const_val' "
792
+ const_name = ""
793
+ #
794
+ # error checking
795
+ #
796
+ if isinstance(cname, str):
797
+ if len(cname) > 0:
798
+ const_name = cname
799
+ if const_name in self.get_const_var_names(
800
+ v_type=self.ensight.objs.enums.ENS_VAR_CONSTANT_PER_PART
801
+ ):
802
+ const_type = self.ensight.objs.enums.ENS_VAR_CONSTANT_PER_PART
803
+ elif const_name in self.get_const_var_names(
804
+ v_type=self.ensight.objs.enums.ENS_VAR_CONSTANT
805
+ ):
806
+ const_type = self.ensight.objs.enums.ENS_VAR_CONSTANT
807
+ else: # pragma: no cover
808
+ raise RuntimeError( # pragma: no cover
809
+ "Error, {} Constant name {} is not a constant nor a per part constant".format(
810
+ ens_routine, const_name
811
+ )
812
+ )
813
+ else: # pragma: no cover
814
+ raise RuntimeError( # pragma: no cover
815
+ "Error, {} must supply a valid constant variable name ".format(ens_routine)
816
+ )
817
+ elif isinstance(cname, self.ensight.objs.ENS_VAR):
818
+ const_name = cname.DESCRIPTION
819
+ const_type = cname.VARTYPEENUM
820
+ if ( # pragma: no cover
821
+ const_type != self.ensight.objs.enums.ENS_VAR_CONSTANT
822
+ and const_type != self.ensight.objs.enums.ENS_VAR_CONSTANT_PER_PART
823
+ ):
824
+ raise RuntimeError( # pragma: no cover
825
+ "Error, Variable {} is not a constant nor a per part constant".format(cname)
826
+ )
827
+ else: # pragma: no cover
828
+ raise RuntimeError(
829
+ "Error, 'get_const_val' Constant name is neither string nor ENS_VAR"
830
+ ) # pragma: no cover
831
+ #
832
+ #
833
+ # Now get it
834
+ #
835
+ self.ensight.variables.activate(const_name) # bug fixed 10.1.6(c)
836
+
837
+ if const_type == self.ensight.objs.enums.ENS_VAR_CONSTANT_PER_PART: # new in 10.2
838
+ if not part_list: # pragma: no cover
839
+ part_list = self.ensight.objs.core.PARTS # pragma: no cover
840
+
841
+ plist = self.ensight.utils.parts.get_part_id_obj_name(part_list, "obj")
842
+ ret_val: List[Optional[float]] = []
843
+ #
844
+ for prt in plist:
845
+ if isinstance(prt, self.ensight.objs.ENS_PART):
846
+ val_dict = prt.get_values([const_name])
847
+ if val_dict: # pragma: no cover
848
+ val = float(val_dict[const_name][0])
849
+ if undef_none and np.isclose(
850
+ val, self.ensight.Undefined, rtol=1e-6, atol=1e-16
851
+ ):
852
+ ret_val.append(None) # pragma: no cover
853
+ else:
854
+ ret_val.append(val)
855
+ else: # pragma: no cover
856
+ raise RuntimeError( # pragma: no cover
857
+ "Error {} part list must contain a list of only ENS_PARTs".format(
858
+ ens_routine
859
+ )
860
+ )
861
+ return ret_val
862
+ # the legacy way using the interface manual ch 6
863
+ (val, type_val, scope_val) = self.ensight.ensvariable(const_name)
864
+
865
+ # type = 0 if the value is an integer, 1 if the value is a float and 2 if the value is a string
866
+ # scope = -1 if it is a constant computed in EnSight, and
867
+ # scope will be >= 0 if a command language global
868
+ # (0 if command language global and >0 if local to a file or loop)
869
+ if scope_val == -1 and type_val == 1: # EnSight constant and float
870
+ if undef_none and np.isclose(
871
+ val, self.ensight.Undefined, rtol=1e-6, atol=1e-16
872
+ ): # pragma: no cover
873
+ return None # pragma: no cover
874
+ else:
875
+ return val
876
+ else: # pragma: no cover
877
+ raise RuntimeError( # pragma: no cover
878
+ "Error, {} return value from ensight.ensvariable indicates it is not a float from an Ensight Constant".format(
879
+ ens_routine
880
+ )
881
+ )
882
+
883
+ #
884
+ #
885
+ # IN:
886
+ # part object list
887
+ # var_object - Must be an elemental variable
888
+ # frame_index - if > 0 and frame exists, use that frame to calc cylindrical forces
889
+ # OUT:
890
+ #
891
+ # Creates (or recreates)
892
+ # several intermediate vars:
893
+ # ENS_Force_press
894
+ # ENS_Force_press_X
895
+ # ENS_Force_press_Y
896
+ # ENS_Force_press_Z
897
+ # if frame index > 0 and less than the number of frames,
898
+ # ENS_Force_press_cyl is the conversion of ENS_Force_press to cylindrical coords
899
+ # ENS_Force_press_R - Radial component of the pressure force in frame index
900
+ # ENS_Force_press_T - Angular (theta) component of the pressure force in frame index
901
+ # ENS_Force_press_A - Axial (z component of chosen frame) of the pressure force
902
+ #
903
+ # WARNING: Each time you call this function, it
904
+ # overwrites all these EnSight variables.
905
+ #
906
+ # WARNING: These variable names are the same
907
+ # as the 10.0 Pressure Force Python Tool
908
+ #
909
+ # Return: True if success
910
+ # False if error
911
+ #
912
+ def _press_force_xyz_rtz(
913
+ self,
914
+ pobj_list: Optional[List[Union[str, int, "ENS_PART"]]] = None,
915
+ press_var_obj: Optional["ENS_VAR"] = None,
916
+ frame_index: Optional[int] = 0,
917
+ ) -> bool:
918
+ """
919
+ Compute the pressure force in the cartesian and cylindrical space.
920
+ It creates (or recreates) several intermediate vars:
921
+
922
+ - ENS_Force_press
923
+ - ENS_Force_press_X
924
+ - ENS_Force_press_Y
925
+ - ENS_Force_press_Z
926
+ if frame index > 0 and the frame exists:
927
+ - ENS_Force_press_cyl is the conversion of ENS_Force_press to cylindrical coords
928
+ - ENS_Force_press_R - Radial component of the pressure force in frame index
929
+ - ENS_Force_press_T - Angular (theta) component of the pressure force in frame index
930
+ - ENS_Force_press_A - Axial (z component of chosen frame) of the pressure force
931
+
932
+ WARNING: Each time you call this function, it
933
+ overwrites all these EnSight variables.
934
+
935
+
936
+ Parameters
937
+ ----------
938
+ pobj_list: list
939
+ The list of part objects to compute the forces on. It can either be a list of names
940
+ a list of IDs (integers or strings) or directly a list of ENS_PART objects
941
+ press_var_obj: ENS_VAR
942
+ The variable object to use as pressure variable. If nodal, it will be converted
943
+ into an elemental variable
944
+ frame_index: int
945
+ The eventual frame index on which to compute the cylindrical components of the forces
946
+
947
+ Returns
948
+ -------
949
+ bool
950
+ True if the computation was successful
951
+
952
+ """
953
+ #
954
+ # This pobj_list should contain only 2D parts
955
+ #
956
+ if not frame_index:
957
+ frame_index = 0
958
+ varid = convert_variable(self.ensight, press_var_obj)
959
+ _press_var_obj: "ENS_VAR"
960
+ values = self.ensight.objs.core.VARIABLES.find(varid, "ID")
961
+ ensvar_values: List["ENS_VAR"]
962
+ ensvar_values = [v for v in values]
963
+ _press_var_obj = ensvar_values[0]
964
+ if not pobj_list: # pragma: no cover
965
+ raise RuntimeError("Error, no part provided") # pragma: no cover
966
+ #
967
+ # select all parts in list
968
+ #
969
+ _pobj_list: List["ENS_PART"]
970
+ _pobj_list = self.ensight.utils.parts.select_parts(pobj_list)
971
+ if not _pobj_list: # pragma: no cover
972
+ return False # pragma: no cover
973
+ #
974
+ # makes a new elem var if input var is nodal
975
+ #
976
+ new_pres_var_obj: "ENS_VAR"
977
+ press_var_name: str
978
+ if _press_var_obj.LOCATION != self.ensight.objs.enums.ENS_VAR_ELEM: # pragma: no cover
979
+ # tricks for mypy
980
+ values = self._move_var_to_elem(_pobj_list, _press_var_obj)
981
+ ensvar_values = [v for v in values]
982
+ new_pres_var_obj = ensvar_values[0]
983
+ press_var_name = new_pres_var_obj.DESCRIPTION
984
+ else:
985
+ press_var_name = _press_var_obj.DESCRIPTION # pragma: no cover
986
+
987
+ #
988
+ # Calculate the Force vector
989
+ #
990
+ calc_string = "(plist," + press_var_name + ")"
991
+ force_calc_string = "ENS_Force_press = Force"
992
+ temp_string = force_calc_string + calc_string
993
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
994
+ raise RuntimeError("Error calculating: '" + temp_string + "'") # pragma: no cover
995
+
996
+ temp_string = "ENS_Force_press_X = ENS_Force_press[X]"
997
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
998
+ raise RuntimeError("Error calculating: '" + temp_string + "'") # pragma: no cover
999
+
1000
+ temp_string = "ENS_Force_press_Y = ENS_Force_press[Y]"
1001
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
1002
+ raise RuntimeError("Error calculating: '" + temp_string + "'") # pragma: no cover
1003
+
1004
+ temp_string = "ENS_Force_press_Z = ENS_Force_press[Z]"
1005
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
1006
+ raise RuntimeError("Error calculating: '" + temp_string + "'") # pragma: no cover
1007
+ #
1008
+ # RTZ Cylindrical force
1009
+ #
1010
+ if frame_index > 0 and frame_index < len(self.ensight.objs.core.FRAMES):
1011
+ temp_string = (
1012
+ "ENS_Force_press_cyl = RectToCyl(plist,ENS_Force_press," + str(frame_index) + ")"
1013
+ )
1014
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
1015
+ raise RuntimeError("Error calculating: '" + temp_string + "'") # pragma: no cover
1016
+
1017
+ temp_string = "ENS_Force_press_R = ENS_Force_press_cyl[X]"
1018
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
1019
+ raise RuntimeError("Error calculating: '" + temp_string + "'") # pragma: no cover
1020
+
1021
+ temp_string = "ENS_Force_press_T = ENS_Force_press_cyl[Y]"
1022
+ if not self._calc_var(pobj_list, temp_string): # pragma: no cover
1023
+ raise RuntimeError("Error calculating: '" + temp_string + "'") # pragma: no cover
1024
+
1025
+ temp_string = "ENS_Force_press_A = ENS_Force_press_cyl[Z]"
1026
+ if not self._calc_var(_pobj_list, temp_string): # pragma: no cover
1027
+ raise RuntimeError("Error calculating: '" + temp_string + "'") # pragma: no cover
1028
+ return True
1029
+
1030
+ def _sum_pressure_forces_xyz_rtz(
1031
+ self,
1032
+ pobj_list: Optional[List[Union[str, int, "ENS_PART"]]] = None,
1033
+ frame_index: Optional[int] = 0,
1034
+ ) -> Optional[List[List[float]]]:
1035
+ """
1036
+ Compute the sum of the pressure forces on the input part objects list
1037
+ and on the eventual frame selected via the StatMoment calculator function in EnSight
1038
+
1039
+ Parameters
1040
+ ----------
1041
+ pobj_list: list
1042
+ The list of part objects to compute the forces on. It can either be a list of names
1043
+ a list of IDs (integers or strings) or directly a list of ENS_PART objects
1044
+ frame_index: int
1045
+ The eventual frame index on which to compute the cylindrical components of the forces
1046
+
1047
+ Returns
1048
+ -------
1049
+ list
1050
+ The list of computed force values. These will be per part constant variables.
1051
+ Three if only cartesian, six if also the cylindrical components were computed.
1052
+ """
1053
+ #
1054
+ # This pobj_list should contain only 2D parts
1055
+ #
1056
+ if not frame_index:
1057
+ frame_index = 0
1058
+ if not pobj_list: # pragma: no cover
1059
+ raise RuntimeError("Error, no part provided") # pragma: no cover
1060
+ #
1061
+ # Select the part(s) in the list
1062
+ # ensight.variables.evaluate("ENS_Force_Net_press_Y = StatMoment(plist,pressure,0,Compute_Per_part)")
1063
+ fcn_name = "sum_press_forces_xyz_rtz"
1064
+ self.ensight.utils.parts.select_parts(pobj_list)
1065
+ #
1066
+ # Calculate the net force X, Y, and Z , 10.2.0(d) now per part constant variable
1067
+ #
1068
+ force_calc_string = "ENS_Force_Net_press_X = StatMoment"
1069
+ calc_string = "(plist," + "ENS_Force_press_X , 0, Compute_Per_part )"
1070
+ temp_string = force_calc_string + calc_string
1071
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1072
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1073
+ raise RuntimeError(err_string) # pragma: no cover
1074
+ #
1075
+ force_calc_string = "ENS_Force_Net_press_Y = StatMoment"
1076
+ calc_string = "(plist," + "ENS_Force_press_Y , 0, Compute_Per_part )"
1077
+ temp_string = force_calc_string + calc_string
1078
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1079
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1080
+ raise RuntimeError(err_string) # pragma: no cover
1081
+ #
1082
+ force_calc_string = "ENS_Force_Net_press_Z = StatMoment"
1083
+ calc_string = "(plist," + "ENS_Force_press_Z , 0, Compute_Per_part )"
1084
+ temp_string = force_calc_string + calc_string
1085
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1086
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1087
+ raise RuntimeError(err_string) # pragma: no cover
1088
+ #
1089
+ # Calculate the Total force X, Y, and Z , 10.2.0(d) now case constant variable
1090
+ # Totals are a case constants. We don't do anything with these vars
1091
+ # they are calc'd to give the user the totals.
1092
+ #
1093
+ force_calc_string = "ENS_Force_Total_Net_press_X = StatMoment"
1094
+ calc_string = "(plist," + "ENS_Force_press_X , 0, Compute_Per_case )"
1095
+ temp_string = force_calc_string + calc_string
1096
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1097
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1098
+ raise RuntimeError(err_string) # pragma: no cover
1099
+ #
1100
+ force_calc_string = "ENS_Force_Total_Net_press_Y = StatMoment"
1101
+ calc_string = "(plist," + "ENS_Force_press_Y , 0, Compute_Per_case )"
1102
+ temp_string = force_calc_string + calc_string
1103
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1104
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1105
+ raise RuntimeError(err_string) # pragma: no cover
1106
+ #
1107
+ force_calc_string = "ENS_Force_Total_Net_press_Z = StatMoment"
1108
+ calc_string = "(plist," + "ENS_Force_press_Z , 0, Compute_Per_case )"
1109
+ temp_string = force_calc_string + calc_string
1110
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1111
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1112
+ raise RuntimeError(err_string) # pragma: no cover
1113
+ #
1114
+ # get a list with a per part force, one for each part, new 10.1.6(b)
1115
+ #
1116
+
1117
+ Fx: List[float] = []
1118
+ Fy: List[float] = []
1119
+ Fz: List[float] = []
1120
+ val = self.get_const_val("ENS_Force_Net_press_X", pobj_list)
1121
+ if not val: # pragma: no cover
1122
+ return None # pragma: no cover
1123
+ if val:
1124
+ if isinstance(val, list):
1125
+ for v in val:
1126
+ if v is None: # pragma: no cover
1127
+ return None # pragma: no cover
1128
+ Fx.append(v)
1129
+ else:
1130
+ return None # pragma: no cover
1131
+ val = self.get_const_val("ENS_Force_Net_press_Y", pobj_list)
1132
+ if not val: # pragma: no cover
1133
+ return None # pragma: no cover
1134
+ if val:
1135
+ if isinstance(val, list):
1136
+ for v in val:
1137
+ if v is None: # pragma: no cover
1138
+ return None # pragma: no cover
1139
+ Fy.append(v)
1140
+ else:
1141
+ return None # pragma: no cover
1142
+ val = self.get_const_val("ENS_Force_Net_press_Z", pobj_list)
1143
+ if not val: # pragma: no cover
1144
+ return None # pragma: no cover
1145
+ if val:
1146
+ if isinstance(val, list):
1147
+ for v in val:
1148
+ if v is None: # pragma: no cover
1149
+ return None # pragma: no cover
1150
+ Fz.append(v)
1151
+ else:
1152
+ return None # pragma: no cover
1153
+ #
1154
+ #
1155
+ # Fr, Ft, Fa
1156
+ #
1157
+ if frame_index > 0 and frame_index < len(
1158
+ self.ensight.objs.core.FRAMES
1159
+ ): # user picked non-zero frame index
1160
+ #
1161
+ self.ensight.utils.parts.select_parts(pobj_list)
1162
+ #
1163
+ # per part constant as of 10.2.0(d)
1164
+ #
1165
+ force_calc_string = "ENS_Force_Net_press_R = StatMoment"
1166
+ calc_string = "(plist," + "ENS_Force_press_R, 0, Compute_Per_part )"
1167
+ temp_string = force_calc_string + calc_string
1168
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1169
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1170
+ raise RuntimeError(err_string) # pragma: no cover
1171
+ #
1172
+ force_calc_string = "ENS_Force_Net_press_T = StatMoment"
1173
+ calc_string = "(plist," + "ENS_Force_press_T, 0, Compute_Per_part )"
1174
+ temp_string = force_calc_string + calc_string
1175
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1176
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1177
+ raise RuntimeError(err_string) # pragma: no cover
1178
+ #
1179
+ force_calc_string = "ENS_Force_Net_press_A = StatMoment"
1180
+ calc_string = "(plist," + "ENS_Force_press_A, 0, Compute_Per_part )"
1181
+ temp_string = force_calc_string + calc_string
1182
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1183
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1184
+ raise RuntimeError(err_string) # pragma: no cover
1185
+ #
1186
+ # Totals are a case constants. We don't do anything with these vars
1187
+ # they are calc'd to give the user the totals.
1188
+ #
1189
+ force_calc_string = "ENS_Force_Total_Net_press_R = StatMoment"
1190
+ calc_string = "(plist," + "ENS_Force_press_R, 0, Compute_Per_case )"
1191
+ temp_string = force_calc_string + calc_string
1192
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1193
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1194
+ raise RuntimeError(err_string) # pragma: no cover
1195
+ #
1196
+ force_calc_string = "ENS_Force_Total_Net_press_T = StatMoment"
1197
+ calc_string = "(plist," + "ENS_Force_press_T, 0, Compute_Per_case )"
1198
+ temp_string = force_calc_string + calc_string
1199
+ if self._calc_var(pobj_list, temp_string) is False: # pragma: no cover
1200
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1201
+ raise RuntimeError(err_string) # pragma: no cover
1202
+ #
1203
+ force_calc_string = "ENS_Force_Total_Net_press_A = StatMoment"
1204
+ calc_string = "(plist," + "ENS_Force_press_A, 0, Compute_Per_case )"
1205
+ temp_string = force_calc_string + calc_string
1206
+ if not self._calc_var(pobj_list, temp_string): # pragma: no cover
1207
+ err_string = f"Error, failed to calculate {temp_string} in {fcn_name}" # pragma: no cover # pragma: no cover # pragma: no cover
1208
+ raise RuntimeError(err_string) # pragma: no cover
1209
+ #
1210
+ # get a list with a per part force, one for each part, new 10.1.6(b)
1211
+ #
1212
+ Fr: List[float] = []
1213
+ Ft: List[float] = []
1214
+ Fa: List[float] = []
1215
+ val = self.get_const_val("ENS_Force_Net_press_R", pobj_list)
1216
+ if not val: # pragma: no cover
1217
+ return None # pragma: no cover
1218
+ if val:
1219
+ if isinstance(val, list):
1220
+ for v in val:
1221
+ if v is None: # pragma: no cover
1222
+ return None # pragma: no cover
1223
+ Fr.append(v)
1224
+ else:
1225
+ return None # pragma: no cover
1226
+ val = self.get_const_val("ENS_Force_Net_press_T", pobj_list)
1227
+ if not val: # pragma: no cover
1228
+ return None # pragma: no cover
1229
+ if val:
1230
+ if isinstance(val, list):
1231
+ for v in val:
1232
+ if v is None: # pragma: no cover
1233
+ return None # pragma: no cover
1234
+ Ft.append(v)
1235
+ else:
1236
+ return None # pragma: no cover
1237
+ val = self.get_const_val("ENS_Force_Net_press_A", pobj_list)
1238
+ if not val: # pragma: no cover
1239
+ return None # pragma: no cover
1240
+ if val:
1241
+ if isinstance(val, list):
1242
+ for v in val:
1243
+ if v is None: # pragma: no cover
1244
+ return None # pragma: no cover
1245
+ Fa.append(v)
1246
+ else:
1247
+ return None # pragma: no cover
1248
+ #
1249
+ if all([Fr, Ft, Fz, Fx, Fy, Fz]):
1250
+ ret_val = []
1251
+ for ii in range(len(pobj_list)):
1252
+ ret_val.append([Fx[ii], Fy[ii], Fz[ii], Fr[ii], Ft[ii], Fa[ii]])
1253
+ return ret_val
1254
+ else:
1255
+ err_string = "Error getting XYZ and/or Cylindrical RTZ Pressure Net Force per part constant values" # pragma: no cover
1256
+ raise RuntimeError(err_string) # pragma: no cover
1257
+ else: # either only one Frame or Frame 0 has been chosen so no cylindrical calc
1258
+ if all([Fx, Fy, Fz]):
1259
+ ret_val = []
1260
+ for ii in range(len(pobj_list)):
1261
+ ret_val.append([Fx[ii], Fy[ii], Fz[ii], 0.0, 0.0, 0.0])
1262
+ return ret_val
1263
+ else: # pragma: no cover
1264
+ err_string = "Error getting Fx, Fy, and/or Fz Pressure Net force per part constant values" # pragma: no cover # pragma: no cover
1265
+ raise RuntimeError(err_string) # pragma: no cover
1266
+
1267
+ def _write_out_force_data(
1268
+ self,
1269
+ filename: str,
1270
+ original_part_selection_list: List["ENS_PART"],
1271
+ params: Dict[str, str],
1272
+ press_force_list: Optional[List[List[float]]] = None,
1273
+ shear_force_list: Optional[List[List[float]]] = None,
1274
+ press_coeff_list: Optional[List[List[float]]] = None,
1275
+ shear_coeff_list: Optional[List[List[float]]] = None,
1276
+ press_LDS_force_list: Optional[List[List[float]]] = None,
1277
+ shear_LDS_force_list: Optional[List[List[float]]] = None,
1278
+ press_LDS_coeff_list: Optional[List[List[float]]] = None,
1279
+ shear_LDS_coeff_list: Optional[List[List[float]]] = None,
1280
+ ) -> bool:
1281
+ """
1282
+ Write the computed forces in a file split part by part
1283
+
1284
+ Parameters
1285
+ ----------
1286
+ filename: str
1287
+ the file on which to write the force data
1288
+ params: dict
1289
+ A dictionary containing the settings for the file. It can contain:
1290
+ press_varname: the name of the pressure variable
1291
+ shear_varname: the name of the shear variable
1292
+ shear_vartype: the type of shear variable
1293
+ Area_ref: the reference area for the force coefficients computation
1294
+ Dens_ref: the reference density for the force coefficients computation
1295
+ Vx_ref: the X velocity reference for the force coefficients computation
1296
+ Vy_ref: the Y velocity reference for the force coefficients computation
1297
+ Vz_ref: the Z velocity reference for the force coefficients computation
1298
+ up_vector: the "Up vector" used for the force components computation
1299
+ frame_index: the index of the frame used for the cylindrical components computation
1300
+ press_force_list: list
1301
+ the list of pressure forces to write
1302
+ shear_force_list: list
1303
+ the list of shear forces to write
1304
+ press_coeff_list:
1305
+ the list of pressure force coefficients to write
1306
+ shear_coeff_list:
1307
+ the list of shear force coefficients to write
1308
+ press_LDS_force_list:
1309
+ the list of pressure Lift, Drag, Side force components to write
1310
+ shear_LDS_force_list:
1311
+ the list of shear Lift, Drag, Side force components to write
1312
+ press_LDS_coeff_list:
1313
+ the list of pressure Lift, Drag, Side force coefficients components to write
1314
+ shear_LDS_coeff_list:
1315
+ the list of pressure Lift, Drag, Side force coefficients components to write
1316
+
1317
+ Returns
1318
+ -------
1319
+ bool
1320
+ True if the export was successful
1321
+ """
1322
+ frames = (
1323
+ self.ensight.objs.core.FRAMES is not None
1324
+ and len(self.ensight.objs.core.FRAMES) > 0
1325
+ and "frame_index" in params
1326
+ and int(params["frame_index"]) > 0
1327
+ )
1328
+ shear = (
1329
+ "shear_varname" in params
1330
+ and params["shear_varname"] != "None"
1331
+ and params["shear_vartype"] != "None"
1332
+ )
1333
+ if (
1334
+ press_force_list
1335
+ ): # FIX ME what if we have no pressure force list but do have shear force list???
1336
+ try:
1337
+ with open(filename, "w") as fp:
1338
+ temp_list = [0.0, 0.0, 0.0]
1339
+ #
1340
+ # get the input data filename from the server and write the filename for the current case
1341
+ #
1342
+ c = self.ensight.objs.core.CURRENTCASE[
1343
+ 0
1344
+ ] # for c in ensight.objs.core.CASES.find(True, attr=ensight.objs.enums.ACTIVE):
1345
+ fp.write("'" + os.path.join(c.SERVERDIR, c.SERVERINFO.get("file", "")) + "'\n")
1346
+ #
1347
+ # Write the gui input values to the .csv output file as a second
1348
+ # line in the header
1349
+ #
1350
+ fp.write("Pressure variable name ," + params["press_varname"] + "\n")
1351
+ if frames:
1352
+ fp.write(
1353
+ "Cylindrical reference frame coordinate system frame, "
1354
+ + str(params["frame_index"])
1355
+ + "\n"
1356
+ )
1357
+ if shear:
1358
+ fp.write("Shear variable name ," + params["shear_varname"] + ", " + "\n")
1359
+ fp.write("Shear variable type ," + params["shear_vartype"] + "\n")
1360
+ if (
1361
+ params.get("Area_ref")
1362
+ and params.get("Dens_ref")
1363
+ and params.get("Vx_ref")
1364
+ and params.get("Vy_ref")
1365
+ and params.get("Vz_ref")
1366
+ ):
1367
+ if float(params["Area_ref"]) > 0.0:
1368
+ fp.write("Reference Area, %.5f \n" % float(params["Area_ref"]))
1369
+ fp.write("Reference Density, %.5f \n" % float(params["Dens_ref"]))
1370
+ fp.write("Reference Velocity xyz, %.5f," % float(params["Vx_ref"]))
1371
+ fp.write("%.5f, " % float(params["Vy_ref"]))
1372
+ fp.write("%.5f \n" % float(params["Vz_ref"]))
1373
+ if params.get("up_vector"):
1374
+ if params["up_vector"] != "None":
1375
+ fp.write("Up vector," + params["up_vector"] + "\n")
1376
+ fp.write("\n")
1377
+ fp.write(
1378
+ "Part ID, Part Name , Pressure Force X , Pressure Force Y , Pressure Force Z , Total Pressure Force "
1379
+ )
1380
+ if frames:
1381
+ fp.write(
1382
+ ", Pressure Force Radial , Pressure Force Theta , Pressure Force Axial, Total Cyl Pressure Force "
1383
+ )
1384
+ if shear_force_list: # pragma: no cover
1385
+ fp.write(
1386
+ ", Shear Force X , Shear Force Y , Shear Force Z , Total Shear Force "
1387
+ )
1388
+ if frames:
1389
+ fp.write(
1390
+ ", Shear Force Radial , Shear Force Theta , Shear Force Axial , Total Cyl Shear Force "
1391
+ )
1392
+ fp.write(
1393
+ ", Press + Shear Force X , Press + Shear Force Y , Press + Shear Force Z , Total Press + Shear Force "
1394
+ )
1395
+ if frames:
1396
+ fp.write(
1397
+ ", Press + Shear Force Radial , Press + Shear Force Theta , Press + Shear Force Axial , Total Press + Shear Force "
1398
+ )
1399
+ if press_coeff_list: # pragma: no cover
1400
+ fp.write(
1401
+ ", Coeff Press X , Coeff Press Y , Coeff Press Z , Total Coeff Press "
1402
+ )
1403
+ if frames:
1404
+ fp.write(
1405
+ ", Coeff Press Radial , Coeff Press Theta , Coeff Press Axial , Total Coeff Press "
1406
+ )
1407
+ if shear_coeff_list: # pragma: no cover
1408
+ fp.write(
1409
+ ", Coeff Shear X , Coeff Shear Y , Coeff Shear Z , Total Coeff Shear ,"
1410
+ )
1411
+ if frames:
1412
+ fp.write(
1413
+ "Coeff Shear Radial , Coeff Shear Theta , Coeff Shear Axial , Total Coeff Shear ,"
1414
+ )
1415
+ fp.write(
1416
+ "Coeff Press + Shear X , Coeff Press + Shear Y , Coeff Press + Shear Z , Total Coeff Press + Shear"
1417
+ )
1418
+ if frames:
1419
+ fp.write(
1420
+ ", Coeff Press + Shear Radial , Coeff Press + Shear Theta , Coeff Press + Shear Axial , Total Coeff Press + Shear"
1421
+ )
1422
+ if press_LDS_force_list: # pragma: no cover
1423
+ fp.write(", Lift Force , Drag Force , Side Force , Total Pressure Force ")
1424
+ if shear_LDS_force_list: # pragma: no cover
1425
+ fp.write(
1426
+ ", Shear Force L , Shear Force D , Shear Force Side , Total Shear Force LDS "
1427
+ )
1428
+ fp.write(
1429
+ ", Press + Shear Force L , Press + Shear Force D , Press + Shear Force Side , Total Press + Shear Force LDS "
1430
+ )
1431
+ if press_LDS_coeff_list: # pragma: no cover
1432
+ fp.write(
1433
+ ", Lift Coeff Press , Drag Coeff Press , Side Coeff Press , Total Coeff Press "
1434
+ )
1435
+ if shear_LDS_coeff_list: # pragma: no cover
1436
+ fp.write(
1437
+ ", Lift Coeff Shear , Drag Coeff Shear , Side Coeff Shear , Coeff Shear LDS Total,"
1438
+ )
1439
+ fp.write(
1440
+ "Coeff Press + Shear L , Coeff Press + Shear D , Coeff Press + Shear Side , Coeff Press + Shear LDS Total"
1441
+ )
1442
+ fp.write("\n")
1443
+ #
1444
+ # Loop through and write out the vals
1445
+ #
1446
+ for ii in range(len(press_force_list)):
1447
+ fp.write(
1448
+ str(original_part_selection_list[ii].PARTNUMBER)
1449
+ + " , "
1450
+ + original_part_selection_list[ii].DESCRIPTION
1451
+ + " , "
1452
+ )
1453
+ #
1454
+ # pressure force components then magnitude
1455
+ #
1456
+ for jj in range(3):
1457
+ fp.write(str(press_force_list[ii][jj]))
1458
+ fp.write(" , ")
1459
+ fp.write(str(vec_mag(press_force_list[ii][:3]))) # magnitude of Fx, Fy, Fz
1460
+ if frames:
1461
+ fp.write(" , ")
1462
+ for jj in range(3):
1463
+ fp.write(str(press_force_list[ii][jj + 3]))
1464
+ fp.write(" , ")
1465
+ fp.write(
1466
+ str(vec_mag(press_force_list[ii][3:]))
1467
+ ) # magnitude of Cyl Fr, Ft, Fa
1468
+ #
1469
+ # shear force components then magnitude
1470
+ #
1471
+ if shear_force_list: # pragma: no cover
1472
+ fp.write(" , ")
1473
+ for jj in range(3):
1474
+ fp.write(str(shear_force_list[ii][jj]))
1475
+ fp.write(" , ")
1476
+ fp.write(str(vec_mag(shear_force_list[ii][:3])))
1477
+ if frames:
1478
+ fp.write(" , ")
1479
+ for jj in range(3):
1480
+ fp.write(str(shear_force_list[ii][jj + 3]))
1481
+ fp.write(" , ")
1482
+ fp.write(str(vec_mag(shear_force_list[ii][3:])))
1483
+ fp.write(" , ")
1484
+ # sum of pressure and shear forces components then magnitude
1485
+ for jj in range(3):
1486
+ temp_list[jj] = press_force_list[ii][jj] + shear_force_list[ii][jj]
1487
+ fp.write(str(temp_list[jj]))
1488
+ fp.write(" , ")
1489
+ fp.write(str(vec_mag(temp_list[:3])))
1490
+ if frames:
1491
+ fp.write(" , ")
1492
+ for jj in range(3):
1493
+ temp_list[jj] = (
1494
+ press_force_list[ii][jj + 3] + shear_force_list[ii][jj + 3]
1495
+ )
1496
+ fp.write(str(temp_list[jj]))
1497
+ fp.write(" , ")
1498
+ fp.write(str(vec_mag(temp_list[:3])))
1499
+
1500
+ #
1501
+ # Coefficient of pressure force components then magnitude
1502
+ #
1503
+ if press_coeff_list: # pragma: no cover
1504
+ fp.write(" , ")
1505
+ for jj in range(3):
1506
+ fp.write(str(press_coeff_list[ii][jj]))
1507
+ fp.write(" , ")
1508
+ fp.write(str(vec_mag(press_coeff_list[ii][:3])))
1509
+ if frames:
1510
+ fp.write(" , ")
1511
+ for jj in range(3):
1512
+ fp.write(str(press_coeff_list[ii][jj + 3]))
1513
+ fp.write(" , ")
1514
+ fp.write(str(vec_mag(press_coeff_list[ii][3:])))
1515
+ #
1516
+ # Coefficient shear force components then magnitude
1517
+ #
1518
+ if (
1519
+ shear_coeff_list is not None and press_coeff_list is not None
1520
+ ): # pragma: no cover
1521
+ if (
1522
+ len(shear_coeff_list) > 0 and len(press_coeff_list) > 0
1523
+ ): # pragma: no cover
1524
+ fp.write(" , ")
1525
+ for jj in range(3):
1526
+ fp.write(str(shear_coeff_list[ii][jj]))
1527
+ fp.write(" , ")
1528
+ fp.write(str(vec_mag(shear_coeff_list[ii][:3])))
1529
+ fp.write(" , ")
1530
+ if frames:
1531
+ for jj in range(3):
1532
+ fp.write(str(shear_coeff_list[ii][jj + 3]))
1533
+ fp.write(" , ")
1534
+ fp.write(str(vec_mag(shear_coeff_list[ii][3:])))
1535
+ fp.write(" , ")
1536
+ # sum of pressure and shear Coefficient components then magnitude
1537
+ for jj in range(3):
1538
+ temp_list[jj] = (
1539
+ press_coeff_list[ii][jj] + shear_coeff_list[ii][jj]
1540
+ )
1541
+ fp.write(str(temp_list[jj]))
1542
+ fp.write(" , ")
1543
+ fp.write(str(vec_mag(temp_list)))
1544
+ if frames:
1545
+ fp.write(" , ")
1546
+ for jj in range(3):
1547
+ temp_list[jj] = (
1548
+ press_coeff_list[ii][jj + 3]
1549
+ + shear_coeff_list[ii][jj + 3]
1550
+ )
1551
+ fp.write(str(temp_list[jj]))
1552
+ fp.write(" , ")
1553
+ fp.write(str(vec_mag(temp_list)))
1554
+ fp.write(" , ")
1555
+ #
1556
+ # Lift, Drag and Side Force
1557
+ # No cylindrical stuff here
1558
+ # LDS pressure force components then magnitude
1559
+ #
1560
+ if press_LDS_force_list: # pragma: no cover
1561
+ for jj in range(3):
1562
+ fp.write(str(press_LDS_force_list[ii][jj]))
1563
+ fp.write(" , ")
1564
+ fp.write(str(vec_mag(press_LDS_force_list[ii][:3])))
1565
+ fp.write(" , ")
1566
+ # LDS shear force components then magnitude
1567
+ if (
1568
+ shear_LDS_force_list is not None and press_LDS_force_list is not None
1569
+ ): # pragma: no cover
1570
+ if (
1571
+ len(shear_LDS_force_list) > 0 and len(press_LDS_force_list) > 0
1572
+ ): # pragma: no cover
1573
+ for jj in range(3):
1574
+ fp.write(str(shear_LDS_force_list[ii][jj]))
1575
+ fp.write(" , ")
1576
+ fp.write(str(vec_mag(shear_LDS_force_list[ii][:3])))
1577
+ fp.write(" , ")
1578
+ # LDS sum of pressure and shear forces components then magnitude
1579
+ for jj in range(3):
1580
+ temp_list[jj] = (
1581
+ press_LDS_force_list[ii][jj] + shear_LDS_force_list[ii][jj]
1582
+ )
1583
+ fp.write(str(temp_list[jj]))
1584
+ fp.write(" , ")
1585
+ fp.write(str(vec_mag(temp_list)))
1586
+ fp.write(" , ")
1587
+ # LDS Coefficient of pressure force components then magnitude
1588
+ if press_LDS_coeff_list: # pragma: no cover
1589
+ for jj in range(3):
1590
+ fp.write(str(press_LDS_coeff_list[ii][jj]))
1591
+ fp.write(" , ")
1592
+ fp.write(str(vec_mag(press_LDS_coeff_list[ii][:3])))
1593
+ fp.write(" , ")
1594
+ # LDS Coefficient shear force components then magnitude
1595
+ if ( # pragma: no cover
1596
+ shear_LDS_coeff_list is not None
1597
+ and press_LDS_coeff_list is not None
1598
+ ):
1599
+ if (
1600
+ len(shear_LDS_coeff_list) > 0 and len(press_LDS_coeff_list) > 0
1601
+ ): # pragma: no cover
1602
+ for jj in range(3):
1603
+ fp.write(str(shear_LDS_coeff_list[ii][jj]))
1604
+ fp.write(" , ")
1605
+ fp.write(str(vec_mag(shear_LDS_coeff_list[ii][:3])))
1606
+ fp.write(" , ")
1607
+ # LDS sum of pressure and shear Coefficient components then magnitude
1608
+ for jj in range(3):
1609
+ temp_list[jj] = (
1610
+ press_LDS_coeff_list[ii][jj]
1611
+ + shear_LDS_coeff_list[ii][jj]
1612
+ )
1613
+ fp.write(str(temp_list[jj]))
1614
+ fp.write(" , ")
1615
+ fp.write(str(vec_mag(temp_list)))
1616
+ fp.write("\n")
1617
+ # FIX ME keep track of and write out totals here when loop is done on last line?
1618
+ fp.close()
1619
+ return True
1620
+ except IOError: # pragma: no cover
1621
+ raise RuntimeError( # pragma: no cover
1622
+ "Error Failed to open output csv filename for writing '" + filename + "'"
1623
+ )
1624
+ raise RuntimeError("Error no pressure force list to write out") # pragma: no cover
1625
+
1626
+ @staticmethod
1627
+ def _force_coeffs(
1628
+ Forces: List[float], area_ref: float, vel_ref: float, dens_ref: float
1629
+ ) -> List[float]:
1630
+ """Compute the force coefficients for the input list of forces
1631
+
1632
+ Parameters
1633
+ ----------
1634
+
1635
+ Forces: list
1636
+ A list of force values to compute the coefficients for
1637
+ area_ref: float
1638
+ the reference area value for the coefficients computation
1639
+ vel_ref: float
1640
+ the reference velocity magnitude value for the coefficients computation
1641
+ dens_ref: float
1642
+ the reference velocity magnitude value for the coefficients computation
1643
+
1644
+ Returns
1645
+ -------
1646
+ list
1647
+ The list of force coefficients computed
1648
+ """
1649
+ coeffs = []
1650
+ qS = area_ref * vel_ref * vel_ref * dens_ref / 2.0
1651
+ if qS > 0: # pragma: no cover
1652
+ for ff in Forces:
1653
+ coeffs.append(ff / qS)
1654
+ else:
1655
+ coeffs = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # pragma: no cover
1656
+ return coeffs
1657
+
1658
+ @staticmethod
1659
+ def _get_up_vec(up_str: str) -> np.array: # pragma: no cover
1660
+ """
1661
+ Convert the up_vector string to the actual components
1662
+
1663
+ Parameters
1664
+ ----------
1665
+ up_str: str
1666
+ the up_vector string
1667
+
1668
+ Returns
1669
+ -------
1670
+ numpy.array
1671
+ The up vector components as a numpy array
1672
+ """
1673
+ if up_str == "+X":
1674
+ up_vec = [1.0, 0.0, 0.0]
1675
+ elif up_str == "+Y":
1676
+ up_vec = [0.0, 1.0, 0.0]
1677
+ elif up_str == "+Z":
1678
+ up_vec = [0.0, 0.0, 1.0]
1679
+ elif up_str == "-X":
1680
+ up_vec = [-1.0, 0.0, 0.0]
1681
+ elif up_str == "-Y":
1682
+ up_vec = [0.0, -1.0, 0.0]
1683
+ elif up_str == "-Z":
1684
+ up_vec = [0.0, 0.0, -1.0]
1685
+ else: # pragma: no cover
1686
+ raise RuntimeError( # pragma: no cover
1687
+ f"Up vector {up_str} not allowed. It can only be +X, +Y, +Z, -X, -Y, -Z."
1688
+ )
1689
+ return np.array(up_vec)
1690
+
1691
+ @staticmethod
1692
+ def _lds_forces(
1693
+ f_np_vec: np.array, lift_vec: np.array, drag_vec: np.array, side_vec: np.array
1694
+ ) -> List[float]:
1695
+ """
1696
+ Compute the lift, drag and side force components for the input vector of forces
1697
+
1698
+ Parameters
1699
+ ----------
1700
+ f_np_vec: numpy.array
1701
+ the numpy array representing the force vector in the X,Y,Z directions of the model
1702
+ lift_vec: numpy.array
1703
+ a numpy array representing the lift direction in the X,Y,Z space
1704
+ drag_vec: numpy.array
1705
+ a numpy array representing the drag direction in the X,Y,Z space
1706
+ side_vec: numpy.array
1707
+ a numpy array representing the side force direction in the X,Y,Z space
1708
+
1709
+ Returns
1710
+ -------
1711
+ list:
1712
+ the computed lift, drag and side force component values
1713
+ """
1714
+ lf = np.dot(f_np_vec[:3], lift_vec)
1715
+ df = np.dot(f_np_vec[:3], drag_vec)
1716
+ sf = np.dot(f_np_vec[:3], side_vec)
1717
+ return [lf, df, sf]
1718
+
1719
+ SHEAR_VAR_TYPE_STRESS = 0
1720
+ SHEAR_VAR_TYPE_FORCE = 1
1721
+ UP_VECTOR_PLUS_X = "+X"
1722
+ UP_VECTOR_PLUS_Y = "+Y"
1723
+ UP_VECTOR_PLUS_Z = "+Z"
1724
+ UP_VECTOR_MINUS_X = "-X"
1725
+ UP_VECTOR_MINUS_Y = "-Y"
1726
+ UP_VECTOR_MINUS_Z = "-Z"
1727
+
1728
+ def compute_forces(
1729
+ self,
1730
+ pobj_list: Optional[List[Union[str, int, "ENS_PART"]]] = None,
1731
+ press_var_obj: Optional[Union["ENS_VAR", str, int]] = None,
1732
+ shear_var_obj: Optional[Union["ENS_VAR", str, int]] = None,
1733
+ shear_var_type: Optional[int] = None,
1734
+ area_ref: Optional[float] = None,
1735
+ density_ref: Optional[float] = None,
1736
+ velocity_x_ref: Optional[float] = None,
1737
+ velocity_y_ref: Optional[float] = None,
1738
+ velocity_z_ref: Optional[float] = None,
1739
+ up_vector: Optional[str] = None,
1740
+ export_filename: Optional[str] = None,
1741
+ frame_index: Optional[int] = 0,
1742
+ ) -> Optional[Dict[str, Dict[str, List[float]]]]:
1743
+ """
1744
+ Compute the force values for the current model.
1745
+ During the force computation process, several intermediate EnSight variables are computed.
1746
+ These can always be retrieved for later use.
1747
+ If area_ref, density_ref, velocity_x_ref, velocity_y_ref and velocity_z_ref are supplied,
1748
+ also the normalized forces will be computed.
1749
+ If velocity_x_ref, velocity_y_ref, velocity_z_ref and up_vector are supplied, also the
1750
+ lift, drag and side components of the force will be computed. Eventually, also the normalized
1751
+ lift, drag and side force components are computed if also area_ref and density_ref are supplied.
1752
+ The forces are returned in a dictionary, which will split the force values in pressure, shear, normalized pressure,
1753
+ normalized shear, lds pressure, lds shear, normalized lds pressure and normalized lds shear components,
1754
+ populated depending on the input (lds stands for lift, drag and side components). They can optionatally be
1755
+ saved into a .csv file, which will also report the total values for each group.
1756
+
1757
+ Parameters
1758
+ ----------
1759
+ pobj_list: list
1760
+ The list of part objects to compute the forces on. It can either be a list of names
1761
+ a list of IDs (integers or strings) or directly a list of ENS_PART objects.
1762
+ The list must contain 2D surfaces.
1763
+ press_var_obj: str, ENS_VAR or int
1764
+ The variable to use for the pressure force computation. It can be supplied as variable name,
1765
+ variable ID or ENS_VAR object. It must be a scalar.
1766
+ shear_var_obj: str, ENS_VAR or int
1767
+ The variable to use for the shear force computation. It can be supplied as variable name,
1768
+ variable ID or ENS_VAR object. It must be a vector.
1769
+ shear_var_type: int
1770
+ The kind of shear variable supplied. It can be:
1771
+
1772
+ ===================== ========================================================
1773
+ Name Shear variable type
1774
+ ===================== ========================================================
1775
+ SHEAR_VAR_TYPE_STRESS The variable represents the shear stresses distribution
1776
+ SHEAR_VAR_TYPE_FORCE The variable represents the shear forces distribution
1777
+ ===================== ========================================================
1778
+
1779
+ If not supplied, it will be defaulted to SHEAR_VAR_TYPE_STRESS
1780
+ area_ref: float
1781
+ the area reference value for the force coefficients computation
1782
+ density_ref: float
1783
+ the area reference value for the force coefficients computation
1784
+ velocity_x_ref: float
1785
+ the X velocity reference component. Needed For the coefficients computation and/or the
1786
+ lift/drag/side components computation. The X direction is the X direction for the model.
1787
+ velocity_y_ref: float
1788
+ the Y velocity reference component. Needed For the coefficients computation and/or the
1789
+ lift/drag/side components computation. The Y direction is the Y direction for the model.
1790
+ velocity_z_ref: float
1791
+ the Z velocity reference component. Needed For the coefficients computation and/or the
1792
+ lift/drag/side components computation. The Z direction is the Z direction for the model.
1793
+ up_vector: str
1794
+ Define the "up vector" for the lift/drag/side decomposition. It can be:
1795
+ ================== =================
1796
+ Name Up vector value
1797
+ ================== =================
1798
+ UP_VECTOR_PLUS_X +X
1799
+ UP_VECTOR_PLUS_Y +Y
1800
+ UP_VECTOR_PLUS_Z +Z
1801
+ UP_VECTOR_MINUS_X -X
1802
+ UP_VECTOR_MINUS_Y -Y
1803
+ UP_VECTOR_MINUS_Z -Z
1804
+ ================== =================
1805
+
1806
+ If not provided, it will default to +Z
1807
+ export_filename: str
1808
+ The filename for the export file. If not provided, not file will be exported.
1809
+ The file will be exported relative to the PyEnSight session, not to the EnSight session.
1810
+ frame_index: int
1811
+ The eventual frame index on which to compute the cylindrical components of the forces.
1812
+ If not provided, the cylindrical components won't be computed.
1813
+
1814
+ Returns
1815
+ -------
1816
+ dict:
1817
+ A dictionary containing all the forces computed, split by force kind and part name
1818
+ """
1819
+ if not frame_index:
1820
+ frame_index = 0
1821
+ if not shear_var_type: # pragma: no cover
1822
+ shear_var_type = self.SHEAR_VAR_TYPE_STRESS
1823
+ shear_map = {
1824
+ self.SHEAR_VAR_TYPE_STRESS: "Shear stress",
1825
+ self.SHEAR_VAR_TYPE_FORCE: "Shear force",
1826
+ }
1827
+ if not up_vector: # pragma: no cover
1828
+ up_vector = self.UP_VECTOR_PLUS_Z # pragma: no cover
1829
+ _pobj_list = self.ensight.utils.parts.select_parts(pobj_list)
1830
+ computed_press_forces: List[List[float]] = []
1831
+ computed_shear_forces: List[List[float]] = []
1832
+ computed_press_force_coeffs: List[List[float]] = []
1833
+ computed_shear_force_coeffs: List[List[float]] = []
1834
+ computed_press_forces_lds: List[List[float]] = []
1835
+ computed_shear_forces_lds: List[List[float]] = []
1836
+ computed_press_forces_lds_coeffs: List[List[float]] = []
1837
+ computed_shear_forces_lds_coeffs: List[List[float]] = []
1838
+ if press_var_obj: # pragma: no cover
1839
+ success = self._press_force_xyz_rtz(
1840
+ pobj_list=pobj_list, press_var_obj=press_var_obj, frame_index=frame_index
1841
+ )
1842
+ if not success: # pragma: no cover
1843
+ return None # pragma: no cover
1844
+ temp = self._sum_pressure_forces_xyz_rtz(pobj_list=pobj_list, frame_index=frame_index)
1845
+ if not temp: # pragma: no cover
1846
+ return None # pragma: no cover
1847
+ computed_press_forces = temp.copy()
1848
+ if shear_var_obj:
1849
+ success = self._shear_force_xyz_rtz(
1850
+ pobj_list=pobj_list,
1851
+ shear_var_obj=shear_var_obj,
1852
+ shear_or_force_flag=shear_map.get(shear_var_type),
1853
+ frame_index=frame_index,
1854
+ )
1855
+ if not success:
1856
+ return None
1857
+ temp = self._sum_shear_forces_xyz_rtz(pobj_list=pobj_list, frame_index=frame_index)
1858
+ if not temp:
1859
+ return None
1860
+ computed_shear_forces = temp.copy()
1861
+ coeffs_computation = all(
1862
+ [
1863
+ x is not None
1864
+ for x in [area_ref, velocity_x_ref, velocity_y_ref, velocity_z_ref, density_ref]
1865
+ ]
1866
+ )
1867
+ # Just making mypy happy
1868
+ if ( # pragma: no cover
1869
+ coeffs_computation
1870
+ and velocity_x_ref is not None
1871
+ and velocity_y_ref is not None
1872
+ and velocity_z_ref is not None
1873
+ and area_ref is not None
1874
+ and density_ref is not None
1875
+ ):
1876
+ _vec_mag = vec_mag([velocity_x_ref, velocity_y_ref, velocity_z_ref])
1877
+ # We need to compute the force coeffs
1878
+ if computed_press_forces: # pragma: no cover
1879
+ for part_force in computed_press_forces:
1880
+ computed_press_force_coeffs.append(
1881
+ self._force_coeffs(part_force, area_ref, _vec_mag, density_ref)
1882
+ )
1883
+ if computed_shear_forces: # pragma: no cover
1884
+ for part_force in computed_shear_forces:
1885
+ computed_shear_force_coeffs.append(
1886
+ self._force_coeffs(part_force, area_ref, _vec_mag, density_ref)
1887
+ )
1888
+ lds = all(
1889
+ [x is not None for x in [up_vector, velocity_x_ref, velocity_y_ref, velocity_z_ref]]
1890
+ )
1891
+ if lds: # pragma: no cover
1892
+ temp_np_vec = np.array([velocity_x_ref, velocity_y_ref, velocity_z_ref])
1893
+ drag_vec = temp_np_vec / np.sqrt(np.dot(temp_np_vec, temp_np_vec))
1894
+ up_vec = self._get_up_vec(up_vector)
1895
+ temp_np_vec = np.cross(drag_vec, up_vec)
1896
+ side_vec = temp_np_vec / np.sqrt(np.dot(temp_np_vec, temp_np_vec))
1897
+ # Lift vec normalized
1898
+ temp_np_vec = np.cross(side_vec, drag_vec)
1899
+ lift_vec = temp_np_vec / np.sqrt(np.dot(temp_np_vec, temp_np_vec))
1900
+ if computed_press_forces: # pragma: no cover
1901
+ for part_force in computed_press_forces:
1902
+ computed_press_forces_lds.append(
1903
+ self._lds_forces(np.array(part_force), lift_vec, drag_vec, side_vec)
1904
+ )
1905
+ if computed_shear_forces: # pragma: no cover
1906
+ for part_force in computed_shear_forces:
1907
+ computed_shear_forces_lds.append(
1908
+ self._lds_forces(np.array(part_force), lift_vec, drag_vec, side_vec)
1909
+ )
1910
+ if coeffs_computation: # pragma: no cover
1911
+ if computed_press_force_coeffs: # pragma: no cover
1912
+ for part_force in computed_press_force_coeffs:
1913
+ computed_press_forces_lds_coeffs.append(
1914
+ self._lds_forces(np.array(part_force), lift_vec, drag_vec, side_vec)
1915
+ )
1916
+ if computed_shear_force_coeffs: # pragma: no cover
1917
+ for part_force in computed_shear_force_coeffs:
1918
+ computed_shear_forces_lds_coeffs.append(
1919
+ self._lds_forces(np.array(part_force), lift_vec, drag_vec, side_vec)
1920
+ )
1921
+ if export_filename is not None and pobj_list is not None: # pragma: no cover
1922
+ if len(pobj_list) > 0: # pragma: no cover
1923
+ press_varname = None
1924
+ shear_varname = None
1925
+ if press_var_obj: # pragma: no cover
1926
+ _press_var_id = convert_variable(self.ensight, press_var_obj)
1927
+ if _press_var_id: # pragma: no cover
1928
+ press_varnames = [
1929
+ v for v in self.ensight.objs.core.VARIABLES if v.ID == _press_var_id
1930
+ ]
1931
+ if press_varnames:
1932
+ press_varname = str(press_varnames[0].DESCRIPTION)
1933
+ if shear_var_obj: # pragma: no cover
1934
+ _shear_var_id = convert_variable(self.ensight, shear_var_obj)
1935
+ if _shear_var_id: # pragma: no cover
1936
+ shear_varnames = [
1937
+ v for v in self.ensight.objs.core.VARIABLES if v.ID == _press_var_id
1938
+ ]
1939
+ if shear_varnames: # pragma: no cover
1940
+ shear_varname = str(shear_varnames[0].DESCRIPTION)
1941
+ params = {}
1942
+ if press_varname: # pragma: no cover
1943
+ params["press_varname"] = press_varname
1944
+ if shear_varname: # pragma: no cover
1945
+ params["shear_varname"] = shear_varname
1946
+ if shear_var_type is not None: # pragma: no cover
1947
+ value = shear_map.get(shear_var_type)
1948
+ if value: # pragma: no cover
1949
+ params["shear_vartype"] = value
1950
+ if area_ref is not None: # pragma: no cover
1951
+ params["Area_ref"] = str(area_ref)
1952
+ if density_ref is not None: # pragma: no cover
1953
+ params["Dens_ref"] = str(density_ref)
1954
+ if velocity_x_ref is not None: # pragma: no cover
1955
+ params["Vx_ref"] = str(velocity_x_ref)
1956
+ if velocity_y_ref is not None: # pragma: no cover
1957
+ params["Vy_ref"] = str(velocity_y_ref)
1958
+ if velocity_z_ref is not None: # pragma: no cover
1959
+ params["Vz_ref"] = str(velocity_z_ref)
1960
+ if up_vector is not None: # pragma: no cover
1961
+ params["up_vector"] = up_vector
1962
+ if frame_index > 0:
1963
+ params["frame_index"] = str(frame_index)
1964
+
1965
+ self._write_out_force_data(
1966
+ export_filename,
1967
+ _pobj_list,
1968
+ params=params,
1969
+ press_force_list=computed_press_forces,
1970
+ shear_force_list=computed_shear_forces,
1971
+ press_coeff_list=computed_press_force_coeffs,
1972
+ shear_coeff_list=computed_shear_force_coeffs,
1973
+ press_LDS_force_list=computed_press_forces_lds,
1974
+ shear_LDS_force_list=computed_shear_forces_lds,
1975
+ press_LDS_coeff_list=computed_press_forces_lds_coeffs,
1976
+ shear_LDS_coeff_list=computed_shear_forces_lds_coeffs,
1977
+ )
1978
+ return {
1979
+ "pressure_forces": {
1980
+ p.DESCRIPTION: computed_press_forces[idx]
1981
+ for idx, p in enumerate(_pobj_list)
1982
+ if idx < len(computed_press_forces)
1983
+ },
1984
+ "shear_forces": {
1985
+ p.DESCRIPTION: computed_shear_forces[idx]
1986
+ for idx, p in enumerate(_pobj_list)
1987
+ if idx < len(computed_shear_forces)
1988
+ },
1989
+ "normalized_pressure_forces": {
1990
+ p.DESCRIPTION: computed_press_force_coeffs[idx]
1991
+ for idx, p in enumerate(_pobj_list)
1992
+ if idx < len(computed_press_force_coeffs)
1993
+ },
1994
+ "normalized_shear_forces": {
1995
+ p.DESCRIPTION: computed_shear_force_coeffs[idx]
1996
+ for idx, p in enumerate(_pobj_list)
1997
+ if idx < len(computed_shear_force_coeffs)
1998
+ },
1999
+ "pressure_forces_lds_direction": {
2000
+ p.DESCRIPTION: computed_press_forces_lds[idx]
2001
+ for idx, p in enumerate(_pobj_list)
2002
+ if idx < len(computed_press_forces_lds)
2003
+ },
2004
+ "shear_forces_lds_direction": {
2005
+ p.DESCRIPTION: computed_shear_forces_lds[idx]
2006
+ for idx, p in enumerate(_pobj_list)
2007
+ if idx < len(computed_shear_forces_lds)
2008
+ },
2009
+ "normalized_pressure_forces_lds_direction": {
2010
+ p.DESCRIPTION: computed_press_forces_lds_coeffs[idx]
2011
+ for idx, p in enumerate(_pobj_list)
2012
+ if idx < len(computed_press_forces_lds_coeffs)
2013
+ },
2014
+ "normalized_shear_forces_lds_direction": {
2015
+ p.DESCRIPTION: computed_shear_forces_lds[idx]
2016
+ for idx, p in enumerate(_pobj_list)
2017
+ if idx < len(computed_shear_forces_lds_coeffs)
2018
+ },
2019
+ }