ansys-pyensight-core 0.7.7__tar.gz → 0.7.8__tar.gz

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.

Potentially problematic release.


This version of ansys-pyensight-core might be problematic. Click here for more details.

Files changed (34) hide show
  1. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/PKG-INFO +1 -1
  2. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/pyproject.toml +1 -1
  3. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/renderable.py +42 -21
  4. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/omniverse.py +59 -24
  5. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/omniverse_dsg_server.py +42 -5
  6. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/variables.py +119 -107
  7. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/LICENSE +0 -0
  8. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/README.rst +0 -0
  9. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/__init__.py +0 -0
  10. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/deep_pixel_view.html +0 -0
  11. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/dockerlauncher.py +0 -0
  12. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/enscontext.py +0 -0
  13. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/enshell_grpc.py +0 -0
  14. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/ensight_grpc.py +0 -0
  15. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/ensobj.py +0 -0
  16. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/launch_ensight.py +0 -0
  17. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/launcher.py +0 -0
  18. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/listobj.py +0 -0
  19. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/locallauncher.py +0 -0
  20. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/py.typed +0 -0
  21. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/session.py +0 -0
  22. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/sgeo_poll.html +0 -0
  23. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/__init__.py +0 -0
  24. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/adr.py +0 -0
  25. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/export.py +0 -0
  26. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/parts.py +0 -0
  27. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/query.py +0 -0
  28. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/resources/Materials/000_sky.exr +0 -0
  29. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/resources/Materials/Fieldstone/Fieldstone_BaseColor.png +0 -0
  30. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/resources/Materials/Fieldstone/Fieldstone_N.png +0 -0
  31. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/resources/Materials/Fieldstone/Fieldstone_ORM.png +0 -0
  32. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/resources/Materials/Fieldstone.mdl +0 -0
  33. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/support.py +0 -0
  34. {ansys_pyensight_core-0.7.7 → ansys_pyensight_core-0.7.8}/src/ansys/pyensight/core/utils/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ansys-pyensight-core
3
- Version: 0.7.7
3
+ Version: 0.7.8
4
4
  Summary: A python wrapper for Ansys EnSight
5
5
  Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
6
6
  Maintainer-email: "ANSYS, Inc." <pyansys.core@ansys.com>
@@ -6,7 +6,7 @@ build-backend = "flit_core.buildapi"
6
6
 
7
7
  [project]
8
8
  name = "ansys-pyensight-core"
9
- version = "0.7.7"
9
+ version = "0.7.8"
10
10
  description = "A python wrapper for Ansys EnSight"
11
11
  readme = "README.rst"
12
12
  requires-python = ">=3.9,<4"
@@ -540,6 +540,20 @@ class RenderableVNC(Renderable):
540
540
  self._rendertype = "remote"
541
541
  self.update()
542
542
 
543
+ def _update_2023R2_or_less(self):
544
+ """Update the remote rendering widget and display it for
545
+ backend EnSight of version earlier than 2024R1
546
+ """
547
+ query_params = {
548
+ "autoconnect": "true",
549
+ "host": self._session.html_hostname,
550
+ "port": self._session.ws_port,
551
+ }
552
+ url = f"{self._http_protocol}://{self._session.html_hostname}:{self._session.html_port}"
553
+ url += "/ansys/nexus/novnc/vnc_envision.html"
554
+ url += self._get_query_parameters_str(query_params)
555
+ self._url = url
556
+
543
557
  def update(self):
544
558
  """Update the remote rendering widget and display it.
545
559
 
@@ -549,29 +563,36 @@ class RenderableVNC(Renderable):
549
563
  """
550
564
  optional_query = self._get_query_parameters_str()
551
565
  version = _get_ansysnexus_version(self._session._cei_suffix)
552
- html = f"<script src='/ansys{version}/nexus/viewer-loader.js{optional_query}'></script>\n"
553
- rest_uri = (
554
- f"{self._http_protocol}://{self._session.html_hostname}:{self._session.html_port}"
555
- )
556
- ws_uri = f"{self._http_protocol}://{self._session.html_hostname}:{self._session.ws_port}"
557
-
558
- query_args = ""
559
- if self._using_proxy and optional_query:
560
- query_args = f', "extra_query_args":"{optional_query[1:]}"'
561
-
562
- attributes = ' renderer="envnc"'
563
- attributes += ' ui="simple"'
564
- attributes += ' active="true"'
565
- attributes += (
566
- " renderer_options='"
567
- + f'{{ "ws":"{ws_uri}", "http":"{rest_uri}", "security_token":"{self._session.secret_key}", "connect_to_running_ens":true {query_args} }}'
568
- + "'"
569
- )
566
+ if int(self._session._cei_suffix) < 241:
567
+ self._update_2023R2_or_less()
568
+ else:
569
+ html = (
570
+ f"<script src='/ansys{version}/nexus/viewer-loader.js{optional_query}'></script>\n"
571
+ )
572
+ rest_uri = (
573
+ f"{self._http_protocol}://{self._session.html_hostname}:{self._session.html_port}"
574
+ )
575
+ ws_uri = (
576
+ f"{self._http_protocol}://{self._session.html_hostname}:{self._session.ws_port}"
577
+ )
570
578
 
571
- html += f"<ansys-nexus-viewer {attributes}></ansys-nexus-viewer>\n"
579
+ query_args = ""
580
+ if self._using_proxy and optional_query:
581
+ query_args = f', "extra_query_args":"{optional_query[1:]}"'
582
+
583
+ attributes = ' renderer="envnc"'
584
+ attributes += ' ui="simple"'
585
+ attributes += ' active="true"'
586
+ attributes += (
587
+ " renderer_options='"
588
+ + f'{{ "ws":"{ws_uri}", "http":"{rest_uri}", "security_token":"{self._session.secret_key}", "connect_to_running_ens":true {query_args} }}'
589
+ + "'"
590
+ )
572
591
 
573
- # refresh the remote HTML
574
- self._save_remote_html_page(html)
592
+ html += f"<ansys-nexus-viewer {attributes}></ansys-nexus-viewer>\n"
593
+
594
+ # refresh the remote HTML
595
+ self._save_remote_html_page(html)
575
596
  super().update()
576
597
 
577
598
 
@@ -2,7 +2,7 @@ import os
2
2
  import subprocess
3
3
  import sys
4
4
  from types import ModuleType
5
- from typing import TYPE_CHECKING, Optional, Union
5
+ from typing import TYPE_CHECKING, List, Optional, Union
6
6
 
7
7
  import psutil
8
8
 
@@ -17,7 +17,7 @@ class Omniverse:
17
17
  """Provides the ``ensight.utils.omniverse`` interface.
18
18
 
19
19
  The omniverse class methods provide an interface between an EnSight session
20
- and an Omniverse instance.
20
+ and an Omniverse instance. See :ref:`omniverse_info` for additional details.
21
21
 
22
22
  Note
23
23
  ----
@@ -48,26 +48,60 @@ class Omniverse:
48
48
  def __init__(self, interface: Union["ensight_api.ensight", "ensight"]):
49
49
  self._ensight = interface
50
50
  self._server_pid: Optional[int] = None
51
+ self._interpreter: List[str] = []
51
52
 
52
- @staticmethod
53
- def _check_modules() -> None:
53
+ def _check_modules(self) -> None:
54
54
  """Verify that the Python interpreter is correct
55
55
 
56
- Check for omni and pxr modules. If not present, raise an exception.
56
+ Check for omni module. If not present, raise an exception.
57
+ If pxr is there as well, then we can just use sys.executable.
58
+ If not, check to see if 'kit.bat' or 'kit.sh' can be found and
59
+ arrange to use those instead.
57
60
 
58
61
  Raises
59
62
  ------
60
63
  RuntimeError if the necessary modules are missing.
61
64
 
62
65
  """
66
+ # One time check for this
67
+ if len(self._interpreter):
68
+ return
63
69
  try:
64
70
  # Note: the EnSight embedded interpreter will not have these
65
- import omni # noqa: F401
66
- import pxr # noqa: F401
71
+ import omni.client # noqa: F401
72
+ except ImportError:
73
+ raise RuntimeError("The module requires the omni module to be installed.") from None
74
+
75
+ try:
76
+ # if we can import pxr, then we can just use sys.executable
77
+ from pxr import Gf, Sdf, Usd, UsdGeom, UsdLux, UsdShade # noqa: F401
78
+
79
+ if os.path.basename(sys.executable).startswith("kit"):
80
+ # we are running inside of an Omniverse app like Create, use the 'kit' script
81
+ raise ImportError("Internal retry")
82
+
83
+ self._interpreter = [sys.executable]
84
+ return
67
85
  except ImportError:
68
- raise RuntimeError(
69
- "The module requires the omni and pxr modules to be installed."
70
- ) from None
86
+ # Can we find 'kit.bat' or 'kit.sh' (we may be running in it)?
87
+ # Interesting cases: something/kit/python/python.exe,
88
+ # something/kit/kit.exe. All mapped to something/kit.{bat,sh} if found.
89
+ ov_dir = os.path.dirname(sys.executable)
90
+ for _ in range(3):
91
+ for name in ("kit.bat", "kit.sh"):
92
+ exe_name = os.path.join(ov_dir, name)
93
+ if os.path.exists(exe_name):
94
+ self._interpreter = [
95
+ exe_name,
96
+ "--enable",
97
+ "omni.client",
98
+ "--enable",
99
+ "omni.usd",
100
+ "--exec",
101
+ ]
102
+ return
103
+ ov_dir = os.path.dirname(ov_dir)
104
+ raise RuntimeError("Unable to detect a copy of the Omniverse kit executable.") from None
71
105
 
72
106
  def _is_running_omniverse(self) -> bool:
73
107
  """Check that an Omniverse connection is active
@@ -88,7 +122,6 @@ class Omniverse:
88
122
  include_camera: bool = False,
89
123
  normalize_geometry: bool = False,
90
124
  live: bool = True,
91
- temporal: bool = False,
92
125
  debug_filename: str = "",
93
126
  ) -> None:
94
127
  """Ensure that an EnSight dsg -> omniverse server is running
@@ -103,21 +136,18 @@ class Omniverse:
103
136
  omniverse_path : str
104
137
  The URI to the Omniverse server. It will look like this:
105
138
  "omniverse://localhost/Users/test"
106
- include_camera: bool
139
+ include_camera : bool
107
140
  If True, apply the EnSight camera to the Omniverse scene. This option
108
141
  should be used if the target viewer is in AR/VR mode. Defaults to False.
109
- normalize_geometry: bool
142
+ normalize_geometry : bool
110
143
  Omniverse units are in meters. If the source dataset is not in the correct
111
144
  unit system or is just too large/small, this option will remap the geometry
112
145
  to a unit cube. Defaults to False.
113
- live: bool
146
+ live : bool
114
147
  If True, one can call 'update()' to send updated geometry to Omniverse.
115
148
  If False, the Omniverse connection will push a single update and then
116
149
  disconnect. Defaults to True.
117
- temporal: bool
118
- If True, all EnSight timesteps will be pushed to Omniverse. Defaults to False, only
119
- the current timestep is pushed.
120
- debug_filename: str
150
+ debug_filename : str
121
151
  If the name of a file is provided, it will be used to save logging information on
122
152
  the connection between EnSight and Omniverse.
123
153
 
@@ -136,7 +166,6 @@ class Omniverse:
136
166
  script_name = "omniverse_dsg_server.py"
137
167
  working_dir = os.path.dirname(__file__)
138
168
  cmd = [
139
- sys.executable,
140
169
  script_name,
141
170
  "--host",
142
171
  hostname,
@@ -151,17 +180,23 @@ class Omniverse:
151
180
  cmd.extend(["--vrmode"])
152
181
  if token:
153
182
  cmd.extend(["--security", token])
154
- if temporal:
155
- cmd.extend(["--animation"])
156
- else:
157
- cmd.extend(["--no-animation"])
183
+ # if temporal:
184
+ # cmd.extend(["--animation"])
185
+ # else:
186
+ # cmd.extend(["--no-animation"])
158
187
  if debug_filename:
159
188
  cmd.extend(["--log_file", debug_filename])
160
189
  cmd.extend(["--verbose", "1"])
161
190
  if normalize_geometry:
162
191
  cmd.extend(["--normalize_geometry"])
192
+ # if using kit.bat, convert args into a string, otherwise, just use them
193
+ cmdline = []
194
+ cmdline.extend(self._interpreter)
195
+ if len(self._interpreter) > 1:
196
+ cmd = [" ".join(cmd)]
197
+ cmdline.extend(cmd)
163
198
  env_vars = os.environ.copy()
164
- process = subprocess.Popen(cmd, close_fds=True, env=env_vars, cwd=working_dir)
199
+ process = subprocess.Popen(cmdline, close_fds=True, env=env_vars, cwd=working_dir)
165
200
  self._server_pid = process.pid
166
201
 
167
202
  def close_connection(self) -> None:
@@ -63,6 +63,8 @@ class OmniverseWrapper:
63
63
  path: str = "omniverse://localhost/Users/test",
64
64
  verbose: int = 0,
65
65
  ):
66
+ self._cleaned_index = 0
67
+ self._cleaned_names: dict = {}
66
68
  self._connectionStatusSubscription = None
67
69
  self._stage = None
68
70
  self._destinationPath = path
@@ -299,17 +301,51 @@ class OmniverseWrapper:
299
301
  self.save_stage()
300
302
  return boxPrim
301
303
 
302
- @staticmethod
303
- def clean_name(name: str, id_name: Any = None) -> str:
304
- name = name.replace(" ", "_").replace("-", "_")
304
+ def clear_cleaned_names(self) -> None:
305
+ """Clear the list of cleaned names"""
306
+ self._cleaned_names = {}
307
+ self._cleaned_index = 0
308
+
309
+ def clean_name(self, name: str, id_name: Any = None) -> str:
310
+ """Generate a vais USD name
311
+
312
+ From a base (EnSight) varname, partname, etc. and the DSG id, generate
313
+ a unique, valid USD name. Save the names so that if the same name
314
+ comes in again, the previously computed name is returned and if the
315
+ manipulation results in a conflict, the name can be made unique.
316
+
317
+ Parameters
318
+ ----------
319
+ name:
320
+ The name to generate a USD name for.
321
+
322
+ id_name:
323
+ The DSG id associated with the DSG name, if any.
324
+
325
+ Returns
326
+ -------
327
+ A unique USD name.
328
+ """
329
+ # return any previously generated name
330
+ if (name, id_name) in self._cleaned_names:
331
+ return self._cleaned_names[(name, id_name)]
332
+ # replace invalid characters
333
+ name = name.replace("+", "_").replace("-", "_")
305
334
  name = name.replace(".", "_").replace(":", "_")
306
335
  name = name.replace("[", "_").replace("]", "_")
307
336
  name = name.replace("(", "_").replace(")", "_")
308
337
  name = name.replace("<", "_").replace(">", "_")
309
338
  name = name.replace("/", "_").replace("=", "_")
310
- name = name.replace(",", "_")
311
- if id is not None:
339
+ name = name.replace(",", "_").replace(" ", "_")
340
+ if id_name is not None:
312
341
  name = name + "_" + str(id_name)
342
+ if name in self._cleaned_names.values():
343
+ # Make the name unique
344
+ while f"{name}_{self._cleaned_index}" in self._cleaned_names.values():
345
+ self._cleaned_index += 1
346
+ name = f"{name}_{self._cleaned_index}"
347
+ # store off the cleaned name
348
+ self._cleaned_names[(name, id_name)] = name
313
349
  return name
314
350
 
315
351
  @staticmethod
@@ -1011,6 +1047,7 @@ class DSGOmniverseLink(object):
1011
1047
  self._part = Part(self)
1012
1048
  self._scene_bounds = None
1013
1049
  self._mesh_block_count = 0 # reset when a new group shows up
1050
+ self._omni.clear_cleaned_names()
1014
1051
 
1015
1052
  # handle the various commands until UPDATE_SCENE_END
1016
1053
  cmd = self.get_next_message()
@@ -1266,6 +1266,7 @@ class Variables:
1266
1266
  """
1267
1267
  frames = (
1268
1268
  self.ensight.objs.core.FRAMES is not None
1269
+ and len(self.ensight.objs.core.FRAMES) > 0
1269
1270
  and "frame_index" in params
1270
1271
  and int(params["frame_index"]) > 0
1271
1272
  )
@@ -1460,34 +1461,38 @@ class Variables:
1460
1461
  # Coefficient shear force components then magnitude
1461
1462
  #
1462
1463
  if shear_coeff_list is not None and press_coeff_list is not None:
1463
- fp.write(" , ")
1464
- for jj in range(3):
1465
- fp.write(str(shear_coeff_list[ii][jj]))
1464
+ if len(shear_coeff_list) > 0 and len(press_coeff_list) > 0:
1466
1465
  fp.write(" , ")
1467
- fp.write(str(vec_mag(shear_coeff_list[ii][:3])))
1468
- fp.write(" , ")
1469
- if frames:
1470
1466
  for jj in range(3):
1471
- fp.write(str(shear_coeff_list[ii][jj + 3]))
1467
+ fp.write(str(shear_coeff_list[ii][jj]))
1472
1468
  fp.write(" , ")
1473
- fp.write(str(vec_mag(shear_coeff_list[ii][3:])))
1474
- fp.write(" , ")
1475
- # sum of pressure and shear Coefficient components then magnitude
1476
- for jj in range(3):
1477
- temp_list[jj] = press_coeff_list[ii][jj] + shear_coeff_list[ii][jj]
1478
- fp.write(str(temp_list[jj]))
1479
- fp.write(" , ")
1480
- fp.write(str(vec_mag(temp_list)))
1481
- if frames:
1469
+ fp.write(str(vec_mag(shear_coeff_list[ii][:3])))
1482
1470
  fp.write(" , ")
1471
+ if frames:
1472
+ for jj in range(3):
1473
+ fp.write(str(shear_coeff_list[ii][jj + 3]))
1474
+ fp.write(" , ")
1475
+ fp.write(str(vec_mag(shear_coeff_list[ii][3:])))
1476
+ fp.write(" , ")
1477
+ # sum of pressure and shear Coefficient components then magnitude
1483
1478
  for jj in range(3):
1484
1479
  temp_list[jj] = (
1485
- press_coeff_list[ii][jj + 3] + shear_coeff_list[ii][jj + 3]
1480
+ press_coeff_list[ii][jj] + shear_coeff_list[ii][jj]
1486
1481
  )
1487
1482
  fp.write(str(temp_list[jj]))
1488
1483
  fp.write(" , ")
1489
1484
  fp.write(str(vec_mag(temp_list)))
1490
- fp.write(" , ")
1485
+ if frames:
1486
+ fp.write(" , ")
1487
+ for jj in range(3):
1488
+ temp_list[jj] = (
1489
+ press_coeff_list[ii][jj + 3]
1490
+ + shear_coeff_list[ii][jj + 3]
1491
+ )
1492
+ fp.write(str(temp_list[jj]))
1493
+ fp.write(" , ")
1494
+ fp.write(str(vec_mag(temp_list)))
1495
+ fp.write(" , ")
1491
1496
  #
1492
1497
  # Lift, Drag and Side Force
1493
1498
  # No cylindrical stuff here
@@ -1501,43 +1506,49 @@ class Variables:
1501
1506
  fp.write(" , ")
1502
1507
  # LDS shear force components then magnitude
1503
1508
  if shear_LDS_force_list is not None and press_LDS_force_list is not None:
1504
- for jj in range(3):
1505
- fp.write(str(shear_LDS_force_list[ii][jj]))
1506
- fp.write(" , ")
1507
- fp.write(str(vec_mag(shear_LDS_force_list[ii][:3])))
1508
- fp.write(" , ")
1509
- # LDS sum of pressure and shear forces components then magnitude
1510
- for jj in range(3):
1511
- temp_list[jj] = (
1512
- press_LDS_force_list[ii][jj] + shear_LDS_force_list[ii][jj]
1513
- )
1514
- fp.write(str(temp_list[jj]))
1515
- fp.write(" , ")
1516
- fp.write(str(vec_mag(temp_list)))
1517
- fp.write(" , ")
1518
- # LDS Coefficient of pressure force components then magnitude
1519
- if press_LDS_coeff_list:
1520
- for jj in range(3):
1521
- fp.write(str(press_LDS_coeff_list[ii][jj]))
1509
+ if len(shear_LDS_force_list) > 0 and len(press_LDS_force_list) > 0:
1510
+ for jj in range(3):
1511
+ fp.write(str(shear_LDS_force_list[ii][jj]))
1512
+ fp.write(" , ")
1513
+ fp.write(str(vec_mag(shear_LDS_force_list[ii][:3])))
1522
1514
  fp.write(" , ")
1523
- fp.write(str(vec_mag(press_LDS_coeff_list[ii][:3])))
1524
- fp.write(" , ")
1525
- # LDS Coefficient shear force components then magnitude
1526
- if shear_LDS_coeff_list is not None and press_LDS_coeff_list is not None:
1527
- for jj in range(3):
1528
- fp.write(str(shear_LDS_coeff_list[ii][jj]))
1515
+ # LDS sum of pressure and shear forces components then magnitude
1516
+ for jj in range(3):
1517
+ temp_list[jj] = (
1518
+ press_LDS_force_list[ii][jj] + shear_LDS_force_list[ii][jj]
1519
+ )
1520
+ fp.write(str(temp_list[jj]))
1521
+ fp.write(" , ")
1522
+ fp.write(str(vec_mag(temp_list)))
1529
1523
  fp.write(" , ")
1530
- fp.write(str(vec_mag(shear_LDS_coeff_list[ii][:3])))
1531
- fp.write(" , ")
1532
- # LDS sum of pressure and shear Coefficient components then magnitude
1533
- for jj in range(3):
1534
- temp_list[jj] = (
1535
- press_LDS_coeff_list[ii][jj] + shear_LDS_coeff_list[ii][jj]
1536
- )
1537
- fp.write(str(temp_list[jj]))
1524
+ # LDS Coefficient of pressure force components then magnitude
1525
+ if press_LDS_coeff_list:
1526
+ for jj in range(3):
1527
+ fp.write(str(press_LDS_coeff_list[ii][jj]))
1528
+ fp.write(" , ")
1529
+ fp.write(str(vec_mag(press_LDS_coeff_list[ii][:3])))
1538
1530
  fp.write(" , ")
1539
- fp.write(str(vec_mag(temp_list)))
1540
- fp.write("\n")
1531
+ # LDS Coefficient shear force components then magnitude
1532
+ if (
1533
+ shear_LDS_coeff_list is not None
1534
+ and press_LDS_coeff_list is not None
1535
+ ):
1536
+ if len(shear_LDS_coeff_list) > 0 and len(press_LDS_coeff_list) > 0:
1537
+ for jj in range(3):
1538
+ fp.write(str(shear_LDS_coeff_list[ii][jj]))
1539
+ fp.write(" , ")
1540
+ fp.write(str(vec_mag(shear_LDS_coeff_list[ii][:3])))
1541
+ fp.write(" , ")
1542
+ # LDS sum of pressure and shear Coefficient components then magnitude
1543
+ for jj in range(3):
1544
+ temp_list[jj] = (
1545
+ press_LDS_coeff_list[ii][jj]
1546
+ + shear_LDS_coeff_list[ii][jj]
1547
+ )
1548
+ fp.write(str(temp_list[jj]))
1549
+ fp.write(" , ")
1550
+ fp.write(str(vec_mag(temp_list)))
1551
+ fp.write("\n")
1541
1552
  # FIX ME keep track of and write out totals here when loop is done on last line?
1542
1553
  fp.close()
1543
1554
  return True
@@ -1843,61 +1854,62 @@ class Variables:
1843
1854
  self._lds_forces(np.array(part_force), lift_vec, drag_vec, side_vec)
1844
1855
  )
1845
1856
  if export_filename is not None and pobj_list is not None:
1846
- press_varname = None
1847
- shear_varname = None
1848
- if press_var_obj:
1849
- _press_var_id = convert_variable(self.ensight, press_var_obj)
1850
- if _press_var_id:
1851
- press_varnames = [
1852
- v for v in self.ensight.objs.core.VARIABLES if v.ID == _press_var_id
1853
- ]
1854
- if press_varnames:
1855
- press_varname = str(press_varnames[0].DESCRIPTION)
1856
- if shear_var_obj:
1857
- _shear_var_id = convert_variable(self.ensight, shear_var_obj)
1858
- if _shear_var_id:
1859
- shear_varnames = [
1860
- v for v in self.ensight.objs.core.VARIABLES if v.ID == _press_var_id
1861
- ]
1862
- if shear_varnames:
1863
- shear_varname = str(shear_varnames[0].DESCRIPTION)
1864
- params = {}
1865
- if press_varname:
1866
- params["press_varname"] = press_varname
1867
- if shear_varname:
1868
- params["shear_varname"] = shear_varname
1869
- if shear_var_type is not None:
1870
- value = shear_map.get(shear_var_type)
1871
- if value:
1872
- params["shear_vartype"] = value
1873
- if area_ref:
1874
- params["Area_ref"] = str(area_ref)
1875
- if density_ref:
1876
- params["Dens_ref"] = str(density_ref)
1877
- if velocity_x_ref:
1878
- params["Vx_ref"] = str(velocity_x_ref)
1879
- if velocity_y_ref:
1880
- params["Vy_ref"] = str(velocity_y_ref)
1881
- if velocity_z_ref:
1882
- params["Vz_ref"] = str(velocity_z_ref)
1883
- if up_vector:
1884
- params["up_vector"] = up_vector
1885
- if frame_index > 0:
1886
- params["frame_index"] = str(frame_index)
1887
-
1888
- self._write_out_force_data(
1889
- export_filename,
1890
- _pobj_list,
1891
- params=params,
1892
- press_force_list=computed_press_forces,
1893
- shear_force_list=computed_shear_forces,
1894
- press_coeff_list=computed_press_force_coeffs,
1895
- shear_coeff_list=computed_shear_force_coeffs,
1896
- press_LDS_force_list=computed_press_forces_lds,
1897
- shear_LDS_force_list=computed_shear_forces_lds,
1898
- press_LDS_coeff_list=computed_press_forces_lds_coeffs,
1899
- shear_LDS_coeff_list=computed_shear_forces_lds_coeffs,
1900
- )
1857
+ if len(pobj_list) > 0:
1858
+ press_varname = None
1859
+ shear_varname = None
1860
+ if press_var_obj:
1861
+ _press_var_id = convert_variable(self.ensight, press_var_obj)
1862
+ if _press_var_id:
1863
+ press_varnames = [
1864
+ v for v in self.ensight.objs.core.VARIABLES if v.ID == _press_var_id
1865
+ ]
1866
+ if press_varnames:
1867
+ press_varname = str(press_varnames[0].DESCRIPTION)
1868
+ if shear_var_obj:
1869
+ _shear_var_id = convert_variable(self.ensight, shear_var_obj)
1870
+ if _shear_var_id:
1871
+ shear_varnames = [
1872
+ v for v in self.ensight.objs.core.VARIABLES if v.ID == _press_var_id
1873
+ ]
1874
+ if shear_varnames:
1875
+ shear_varname = str(shear_varnames[0].DESCRIPTION)
1876
+ params = {}
1877
+ if press_varname:
1878
+ params["press_varname"] = press_varname
1879
+ if shear_varname:
1880
+ params["shear_varname"] = shear_varname
1881
+ if shear_var_type is not None:
1882
+ value = shear_map.get(shear_var_type)
1883
+ if value:
1884
+ params["shear_vartype"] = value
1885
+ if area_ref:
1886
+ params["Area_ref"] = str(area_ref)
1887
+ if density_ref:
1888
+ params["Dens_ref"] = str(density_ref)
1889
+ if velocity_x_ref:
1890
+ params["Vx_ref"] = str(velocity_x_ref)
1891
+ if velocity_y_ref:
1892
+ params["Vy_ref"] = str(velocity_y_ref)
1893
+ if velocity_z_ref:
1894
+ params["Vz_ref"] = str(velocity_z_ref)
1895
+ if up_vector:
1896
+ params["up_vector"] = up_vector
1897
+ if frame_index > 0:
1898
+ params["frame_index"] = str(frame_index)
1899
+
1900
+ self._write_out_force_data(
1901
+ export_filename,
1902
+ _pobj_list,
1903
+ params=params,
1904
+ press_force_list=computed_press_forces,
1905
+ shear_force_list=computed_shear_forces,
1906
+ press_coeff_list=computed_press_force_coeffs,
1907
+ shear_coeff_list=computed_shear_force_coeffs,
1908
+ press_LDS_force_list=computed_press_forces_lds,
1909
+ shear_LDS_force_list=computed_shear_forces_lds,
1910
+ press_LDS_coeff_list=computed_press_forces_lds_coeffs,
1911
+ shear_LDS_coeff_list=computed_shear_forces_lds_coeffs,
1912
+ )
1901
1913
  return {
1902
1914
  "pressure_forces": {
1903
1915
  p.DESCRIPTION: computed_press_forces[idx]