ansys-fluent-core 0.31.dev1__py3-none-any.whl → 0.32.dev0__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.

Potentially problematic release.


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

Files changed (57) hide show
  1. ansys/fluent/core/__init__.py +11 -3
  2. ansys/fluent/core/codegen/settingsgen.py +6 -0
  3. ansys/fluent/core/codegen/tuigen.py +1 -2
  4. ansys/fluent/core/docker/docker_compose.py +243 -0
  5. ansys/fluent/core/field_data_interfaces.py +6 -0
  6. ansys/fluent/core/file_session.py +158 -128
  7. ansys/fluent/core/filereader/data_file.py +11 -0
  8. ansys/fluent/core/filereader/pre_processor.py +22 -0
  9. ansys/fluent/core/fluent_connection.py +48 -20
  10. ansys/fluent/core/generated/api_tree/api_objects.json +1 -1
  11. ansys/fluent/core/generated/datamodel_231/flicing.py +20 -20
  12. ansys/fluent/core/generated/datamodel_231/meshing.py +228 -228
  13. ansys/fluent/core/generated/datamodel_232/flicing.py +40 -40
  14. ansys/fluent/core/generated/datamodel_232/meshing.py +203 -203
  15. ansys/fluent/core/generated/datamodel_241/flicing.py +20 -20
  16. ansys/fluent/core/generated/datamodel_241/meshing.py +303 -303
  17. ansys/fluent/core/generated/datamodel_242/flicing.py +35 -35
  18. ansys/fluent/core/generated/datamodel_242/meshing.py +334 -334
  19. ansys/fluent/core/generated/datamodel_242/part_management.py +6 -6
  20. ansys/fluent/core/generated/datamodel_251/flicing.py +40 -40
  21. ansys/fluent/core/generated/datamodel_251/meshing.py +366 -366
  22. ansys/fluent/core/generated/datamodel_251/part_management.py +6 -6
  23. ansys/fluent/core/generated/datamodel_252/flicing.py +30 -30
  24. ansys/fluent/core/generated/datamodel_252/meshing.py +816 -454
  25. ansys/fluent/core/generated/datamodel_252/part_management.py +10 -10
  26. ansys/fluent/core/generated/datamodel_252/preferences.py +1 -1
  27. ansys/fluent/core/generated/fluent_version_252.py +4 -4
  28. ansys/fluent/core/generated/solver/settings_252.py +2241 -1649
  29. ansys/fluent/core/generated/solver/settings_252.pyi +1785 -1430
  30. ansys/fluent/core/generated/solver/settings_builtin.pyi +104 -0
  31. ansys/fluent/core/generated/solver/tui_252.py +126 -2
  32. ansys/fluent/core/launcher/container_launcher.py +39 -8
  33. ansys/fluent/core/launcher/fluent_container.py +60 -22
  34. ansys/fluent/core/launcher/launcher.py +24 -13
  35. ansys/fluent/core/launcher/launcher_utils.py +8 -0
  36. ansys/fluent/core/launcher/process_launch_string.py +2 -6
  37. ansys/fluent/core/report.py +2 -0
  38. ansys/fluent/core/services/deprecated_field_data.py +74 -46
  39. ansys/fluent/core/services/field_data.py +104 -69
  40. ansys/fluent/core/services/reduction.py +55 -66
  41. ansys/fluent/core/services/solution_variables.py +9 -1
  42. ansys/fluent/core/session.py +15 -12
  43. ansys/fluent/core/session_meshing.py +3 -0
  44. ansys/fluent/core/session_solver.py +20 -43
  45. ansys/fluent/core/session_utilities.py +429 -0
  46. ansys/fluent/core/solver/flobject.py +28 -0
  47. ansys/fluent/core/utils/deprecate.py +46 -0
  48. ansys/fluent/core/utils/file_transfer_service.py +19 -3
  49. ansys/fluent/core/utils/fluent_version.py +42 -11
  50. ansys/fluent/core/variable_strategies/__init__.py +29 -0
  51. ansys/fluent/core/variable_strategies/expr.py +186 -0
  52. ansys/fluent/core/variable_strategies/field.py +186 -0
  53. ansys/fluent/core/variable_strategies/svar.py +61 -0
  54. {ansys_fluent_core-0.31.dev1.dist-info → ansys_fluent_core-0.32.dev0.dist-info}/METADATA +7 -5
  55. {ansys_fluent_core-0.31.dev1.dist-info → ansys_fluent_core-0.32.dev0.dist-info}/RECORD +57 -51
  56. {ansys_fluent_core-0.31.dev1.dist-info → ansys_fluent_core-0.32.dev0.dist-info}/LICENSE +0 -0
  57. {ansys_fluent_core-0.31.dev1.dist-info → ansys_fluent_core-0.32.dev0.dist-info}/WHEEL +0 -0
@@ -57,14 +57,22 @@ from ansys.fluent.core.pyfluent_warnings import ( # noqa: F401
57
57
  from ansys.fluent.core.search import search # noqa: F401
58
58
  from ansys.fluent.core.services.batch_ops import BatchOps # noqa: F401
59
59
  from ansys.fluent.core.session import BaseSession as Fluent # noqa: F401
60
+ from ansys.fluent.core.session_utilities import ( # noqa: F401
61
+ Meshing,
62
+ PrePost,
63
+ PureMeshing,
64
+ Solver,
65
+ SolverAero,
66
+ SolverIcing,
67
+ )
60
68
  from ansys.fluent.core.streaming_services.events_streaming import * # noqa: F401, F403
61
69
  from ansys.fluent.core.utils import fldoc, get_examples_download_dir
62
70
  from ansys.fluent.core.utils.fluent_version import FluentVersion # noqa: F401
63
71
  from ansys.fluent.core.utils.setup_for_fluent import setup_for_fluent # noqa: F401
64
72
 
65
- __version__ = "0.31.dev1"
73
+ __version__ = "0.32.dev0"
66
74
 
67
- _VERSION_INFO = "Build date: April 29, 2025 11:50 UTC ShaID: 41afeb4"
75
+ _VERSION_INFO = "Build date: May 22, 2025 07:46 UTC ShaID: 8295dd2"
68
76
  """
69
77
  Global variable indicating the version info of the PyFluent package.
70
78
  Build timestamp and commit hash are added to this variable during packaging.
@@ -106,7 +114,7 @@ EXAMPLES_PATH = str(get_examples_download_dir())
106
114
  CONTAINER_MOUNT_SOURCE = None
107
115
 
108
116
  # Path inside the container where the host path is mounted
109
- CONTAINER_MOUNT_TARGET = "/mnt/pyfluent"
117
+ CONTAINER_MOUNT_TARGET = "/home/container/workdir"
110
118
 
111
119
  # Set this to False to stop automatically inferring and setting REMOTING_SERVER_ADDRESS
112
120
  INFER_REMOTING_IP = True
@@ -124,6 +124,7 @@ def _populate_data(cls, api_tree: dict, version: str) -> dict:
124
124
  data["argument_names"] = getattr(cls, "argument_names", [])
125
125
  data["child_aliases"] = getattr(cls, "_child_aliases", {})
126
126
  data["return_type"] = getattr(cls, "return_type", None)
127
+ data["deprecated_version"] = getattr(cls, "_deprecated_version", None)
127
128
  child_classes = data.setdefault("child_classes", {})
128
129
  for k, v in cls._child_classes.items():
129
130
  if k in command_names:
@@ -227,6 +228,11 @@ def _write_data(cls_name: str, python_name: str, data: dict, f: IO, f_stub: IO |
227
228
  s.write(f" {doc}\n")
228
229
  s.write(' """\n')
229
230
  s.write(f" _version = {data['version']!r}\n")
231
+ deprecated = data["deprecated_version"]
232
+ if deprecated:
233
+ release_version = "20" + data["deprecated_version"].replace(".", "R")
234
+ s.write(f" _deprecated_version = {release_version!r}\n")
235
+ s_stub.write(" _deprecated_version: str\n")
230
236
  s.write(f" fluent_name = {data['fluent_name']!r}\n")
231
237
  # _python_name preserves the original non-suffixed name of the class.
232
238
  s.write(f" _python_name = {python_name!r}\n")
@@ -58,7 +58,6 @@ from ansys.fluent.core.services.datamodel_tui import (
58
58
  )
59
59
  from ansys.fluent.core.utils.fix_doc import escape_wildcards
60
60
  from ansys.fluent.core.utils.fluent_version import (
61
- AnsysVersionNotFound,
62
61
  FluentVersion,
63
62
  get_version_for_file_name,
64
63
  )
@@ -130,7 +129,7 @@ def _copy_tui_help_xml_file(version: str):
130
129
  shutil.copy(str(xml_source), _XML_HELP_FILE)
131
130
  else:
132
131
  logger.warning("fluent_gui_help.xml is not found.")
133
- except AnsysVersionNotFound:
132
+ except FileNotFoundError:
134
133
  logger.warning("fluent_gui_help.xml is not found.")
135
134
 
136
135
 
@@ -0,0 +1,243 @@
1
+ """Launch Fluent through docker compose."""
2
+
3
+ # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
4
+ # SPDX-License-Identifier: MIT
5
+ #
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+
25
+ import os
26
+ import subprocess
27
+ import uuid
28
+
29
+
30
+ class ComposeBasedLauncher:
31
+ """Launch Fluent through docker or Podman compose."""
32
+
33
+ def __init__(self, *, container_dict):
34
+ self._compose_name = f"pyfluent_compose_{uuid.uuid4().hex}"
35
+ self._container_dict = container_dict
36
+ self._image_name = (
37
+ container_dict.get("fluent_image")
38
+ or f"ghcr.io/ansys/pyfluent:{os.getenv('FLUENT_IMAGE_TAG')}"
39
+ )
40
+ self._container_source = self._set_compose_cmds()
41
+ self._container_source.remove("compose")
42
+
43
+ self._compose_file = self._get_compose_file(container_dict)
44
+
45
+ def _is_podman_selected(self):
46
+ return os.getenv("PYFLUENT_USE_PODMAN_COMPOSE") == "1"
47
+
48
+ def _get_compose_file(self, container_dict):
49
+ """Generates compose file for the Docker Compose setup.
50
+
51
+ Parameters
52
+ ----------
53
+ container_dict: dict
54
+ A dictionary containing container configuration.
55
+ """
56
+
57
+ indent = " "
58
+
59
+ if container_dict.get("ports"):
60
+ ports = list(container_dict.get("ports").values())
61
+ else:
62
+ ports = [container_dict.get("fluent_port", "")]
63
+
64
+ compose_file = f"""
65
+ services:
66
+ fluent:
67
+ image: {container_dict.get("fluent_image")}
68
+ command: {" ".join(container_dict["command"])}
69
+ working_dir: {container_dict.get("mount_target")}
70
+ volumes:
71
+ {indent}- {container_dict.get("mount_source")}:{container_dict.get("mount_target")}
72
+ ports:
73
+ """
74
+
75
+ for port in ports:
76
+ if len(ports) == 1:
77
+ compose_file += f"{indent * 3}- {port}:{port}"
78
+ else:
79
+ if port == ports[0]:
80
+ compose_file += f"{indent * 3}- {port}:{port}\n"
81
+ elif port == ports[-1]:
82
+ compose_file += f"{indent * 7}- {port}:{port}"
83
+ else:
84
+ compose_file += f"{indent * 7}- {port}:{port}\n"
85
+
86
+ compose_file_env = f"""
87
+ {indent * 2}environment:
88
+ """
89
+
90
+ for key, value in container_dict["environment"].items():
91
+ if key == "ANSYSLMD_LICENSE_FILE":
92
+ compose_file_env += f"""{indent * 3}- {key}={value}\n"""
93
+ else:
94
+ compose_file_env += f"""{indent * 7}- {key}={value}\n"""
95
+
96
+ compose_file += compose_file_env
97
+
98
+ return compose_file
99
+
100
+ def _extract_ports(self, port_string):
101
+ """
102
+ Extracts ports from a string containing port mappings.
103
+
104
+ Parameters
105
+ ----------
106
+ port_string: str
107
+ A string containing port mappings.
108
+
109
+ Returns
110
+ -------
111
+ ports: list
112
+ A list of extracted ports.
113
+ """
114
+ ports = []
115
+ for line in port_string.split("\n"):
116
+ if line:
117
+ _, target = line.split("->")
118
+ port = target.split(":")[1]
119
+ ports.append(port)
120
+ return [port for port in ports if port.isdigit()]
121
+
122
+ def _set_compose_cmds(self):
123
+ """Sets the compose commands based on available tools and permissions.
124
+
125
+ Raises
126
+ ------
127
+ RuntimeError
128
+ If neither Docker nor Podman is specified.
129
+ """
130
+
131
+ # Determine the compose command
132
+ if os.getenv("PYFLUENT_USE_PODMAN_COMPOSE") == "1":
133
+ self._compose_cmds = (
134
+ ["sudo", "podman", "compose"]
135
+ if hasattr(self, "_container_source")
136
+ and "sudo" in self._container_source
137
+ else ["podman", "compose"]
138
+ )
139
+ elif os.getenv("PYFLUENT_USE_DOCKER_COMPOSE") == "1":
140
+ self._compose_cmds = ["docker", "compose"]
141
+ else:
142
+ raise RuntimeError("Neither Docker nor Podman is specified.")
143
+
144
+ return self._compose_cmds
145
+
146
+ def check_image_exists(self) -> bool:
147
+ """Check if the image exists locally."""
148
+ try:
149
+ cmd = self._container_source + ["images", "-q", self._image_name]
150
+ # Podman users do not always configure rootless mode in /etc/subuids and /etc/subgids
151
+ if self._is_podman_selected():
152
+ sudo_cmd = ["sudo"] + cmd
153
+ output_1 = subprocess.check_output(cmd)
154
+ output_2 = subprocess.check_output(sudo_cmd)
155
+ output_1_result = output_1.decode("utf-8").strip() != ""
156
+ output_2_result = output_2.decode("utf-8").strip() != ""
157
+ if output_2_result and not output_1_result:
158
+ self._container_source.insert(0, "sudo")
159
+ return output_1_result or output_2_result
160
+ else:
161
+ output = subprocess.check_output(cmd)
162
+ return output.decode("utf-8").strip() != ""
163
+ except subprocess.CalledProcessError as e: # noqa: F841
164
+ return False
165
+
166
+ def pull_image(self) -> None:
167
+ """Pull a Docker image if it does not exist locally."""
168
+
169
+ cmd = self._container_source + ["pull", self._image_name]
170
+
171
+ subprocess.check_call(cmd)
172
+
173
+ def _start_stop_helper(
174
+ self, compose_cmd: list[str], cmd: list[str], timeout: float
175
+ ) -> None:
176
+ """Helper function to start or stop the services.
177
+ Parameters
178
+ ----------
179
+ compose_cmd: list[str]
180
+ The command to run.
181
+ cmd: list[str]
182
+ The command to run.
183
+ timeout: float
184
+ The timeout for the command.
185
+ """
186
+ process = subprocess.Popen(
187
+ compose_cmd + cmd,
188
+ stdin=subprocess.PIPE,
189
+ text=True,
190
+ stdout=subprocess.DEVNULL,
191
+ stderr=subprocess.DEVNULL,
192
+ )
193
+ process.communicate(input=self._compose_file, timeout=timeout)
194
+ return_code = process.wait(timeout=timeout)
195
+
196
+ if return_code != 0:
197
+ raise subprocess.CalledProcessError(return_code, compose_cmd + cmd)
198
+
199
+ def start(self) -> None:
200
+ """Start the services.
201
+
202
+ Raises
203
+ ------
204
+ subprocess.CalledProcessError
205
+ If the command fails.
206
+ """
207
+
208
+ cmd = [
209
+ "-f",
210
+ "-",
211
+ "--project-name",
212
+ self._compose_name,
213
+ "up",
214
+ "--detach",
215
+ ]
216
+
217
+ self._start_stop_helper(self._set_compose_cmds(), cmd, 60)
218
+
219
+ def stop(self) -> None:
220
+ """Stop the services.
221
+
222
+ Raises
223
+ ------
224
+ subprocess.CalledProcessError
225
+ If the command fails.
226
+ """
227
+ cmd = [
228
+ "-f",
229
+ "-",
230
+ "--project-name",
231
+ self._compose_name,
232
+ "down",
233
+ ]
234
+
235
+ self._start_stop_helper(self._set_compose_cmds(), cmd, 30)
236
+
237
+ @property
238
+ def ports(self) -> list[str]:
239
+ """Return the ports of the launched services."""
240
+ output = subprocess.check_output(
241
+ self._container_source + ["port", f"{self._compose_name}-fluent-1"],
242
+ )
243
+ return self._extract_ports(output.decode("utf-8").strip())
@@ -30,6 +30,11 @@ import numpy as np
30
30
  import numpy.typing as npt
31
31
 
32
32
  from ansys.fluent.core.exceptions import DisallowedValuesError
33
+ from ansys.fluent.core.variable_strategies import (
34
+ FluentFieldDataNamingStrategy as naming_strategy,
35
+ )
36
+
37
+ _to_field_name_str = naming_strategy().to_string if naming_strategy else lambda s: s
33
38
 
34
39
 
35
40
  class SurfaceDataType(Enum):
@@ -311,6 +316,7 @@ class _AllowedFieldNames(_AllowedNames):
311
316
 
312
317
  def valid_name(self, field_name):
313
318
  """Returns valid names."""
319
+ field_name = _to_field_name_str(field_name)
314
320
  if validate_inputs:
315
321
  names = self
316
322
  if not names.is_valid(field_name, respect_data_valid=False):