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.
- ansys/pyensight/core/__init__.py +41 -0
- ansys/pyensight/core/common.py +341 -0
- ansys/pyensight/core/deep_pixel_view.html +98 -0
- ansys/pyensight/core/dockerlauncher.py +1124 -0
- ansys/pyensight/core/dvs.py +872 -0
- ansys/pyensight/core/enscontext.py +345 -0
- ansys/pyensight/core/enshell_grpc.py +641 -0
- ansys/pyensight/core/ensight_grpc.py +874 -0
- ansys/pyensight/core/ensobj.py +515 -0
- ansys/pyensight/core/launch_ensight.py +296 -0
- ansys/pyensight/core/launcher.py +388 -0
- ansys/pyensight/core/libuserd.py +2110 -0
- ansys/pyensight/core/listobj.py +280 -0
- ansys/pyensight/core/locallauncher.py +579 -0
- ansys/pyensight/core/py.typed +0 -0
- ansys/pyensight/core/renderable.py +880 -0
- ansys/pyensight/core/session.py +1923 -0
- ansys/pyensight/core/sgeo_poll.html +24 -0
- ansys/pyensight/core/utils/__init__.py +21 -0
- ansys/pyensight/core/utils/adr.py +111 -0
- ansys/pyensight/core/utils/dsg_server.py +1220 -0
- ansys/pyensight/core/utils/export.py +606 -0
- ansys/pyensight/core/utils/omniverse.py +769 -0
- ansys/pyensight/core/utils/omniverse_cli.py +614 -0
- ansys/pyensight/core/utils/omniverse_dsg_server.py +1196 -0
- ansys/pyensight/core/utils/omniverse_glb_server.py +848 -0
- ansys/pyensight/core/utils/parts.py +1221 -0
- ansys/pyensight/core/utils/query.py +487 -0
- ansys/pyensight/core/utils/readers.py +300 -0
- ansys/pyensight/core/utils/resources/Materials/000_sky.exr +0 -0
- ansys/pyensight/core/utils/support.py +128 -0
- ansys/pyensight/core/utils/variables.py +2019 -0
- ansys/pyensight/core/utils/views.py +674 -0
- ansys_pyensight_core-0.11.0.dist-info/METADATA +309 -0
- ansys_pyensight_core-0.11.0.dist-info/RECORD +37 -0
- ansys_pyensight_core-0.11.0.dist-info/WHEEL +4 -0
- 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
|
+
}
|