ansys-fluent-core 0.34.1__py3-none-any.whl → 0.35.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.
- ansys/fluent/core/__init__.py +48 -84
- ansys/fluent/core/codegen/allapigen.py +2 -2
- ansys/fluent/core/codegen/builtin_settingsgen.py +50 -28
- ansys/fluent/core/codegen/datamodelgen.py +3 -1
- ansys/fluent/core/codegen/print_fluent_version.py +2 -2
- ansys/fluent/core/codegen/settingsgen.py +1 -1
- ansys/fluent/core/codegen/tuigen.py +4 -4
- ansys/fluent/core/data_model_cache.py +2 -2
- ansys/fluent/core/docker/docker_compose.py +8 -9
- ansys/fluent/core/docker/utils.py +1 -1
- ansys/fluent/core/examples/downloads.py +8 -11
- ansys/fluent/core/fluent_connection.py +23 -15
- ansys/fluent/core/generated/api_tree/api_objects.json +1 -1
- ansys/fluent/core/generated/datamodel_231/flicing.py +55 -55
- ansys/fluent/core/generated/datamodel_231/meshing.py +209 -209
- ansys/fluent/core/generated/datamodel_232/flicing.py +45 -45
- ansys/fluent/core/generated/datamodel_232/meshing.py +205 -205
- ansys/fluent/core/generated/datamodel_241/flicing.py +30 -30
- ansys/fluent/core/generated/datamodel_241/meshing.py +298 -298
- ansys/fluent/core/generated/datamodel_242/flicing.py +35 -35
- ansys/fluent/core/generated/datamodel_242/meshing.py +321 -321
- ansys/fluent/core/generated/datamodel_242/part_management.py +3 -3
- ansys/fluent/core/generated/datamodel_251/flicing.py +40 -40
- ansys/fluent/core/generated/datamodel_251/meshing.py +315 -315
- ansys/fluent/core/generated/datamodel_251/part_management.py +6 -6
- ansys/fluent/core/generated/datamodel_252/flicing.py +45 -45
- ansys/fluent/core/generated/datamodel_252/meshing.py +398 -398
- ansys/fluent/core/generated/datamodel_261/flicing.py +50 -50
- ansys/fluent/core/generated/datamodel_261/meshing.py +406 -406
- ansys/fluent/core/generated/datamodel_261/meshing_utilities.py +616 -296
- ansys/fluent/core/generated/datamodel_261/part_management.py +10 -10
- ansys/fluent/core/generated/fluent_version_252.py +1 -1
- ansys/fluent/core/generated/fluent_version_261.py +3 -3
- ansys/fluent/core/generated/meshing/tui_261.py +1178 -1133
- ansys/fluent/core/generated/solver/settings_261.py +2378 -3023
- ansys/fluent/core/generated/solver/settings_261.pyi +1537 -1456
- ansys/fluent/core/generated/solver/settings_builtin.py +515 -27
- ansys/fluent/core/generated/solver/settings_builtin.pyi +2 -18
- ansys/fluent/core/generated/solver/tui_261.py +2606 -3483
- ansys/fluent/core/launcher/container_launcher.py +19 -4
- ansys/fluent/core/launcher/fluent_container.py +48 -39
- ansys/fluent/core/launcher/launch_options.py +5 -4
- ansys/fluent/core/launcher/launcher.py +16 -3
- ansys/fluent/core/launcher/launcher_utils.py +63 -15
- ansys/fluent/core/launcher/pim_launcher.py +17 -3
- ansys/fluent/core/launcher/process_launch_string.py +3 -2
- ansys/fluent/core/launcher/server_info.py +7 -3
- ansys/fluent/core/launcher/slurm_launcher.py +4 -2
- ansys/fluent/core/launcher/standalone_launcher.py +6 -3
- ansys/fluent/core/launcher/watchdog.py +3 -3
- ansys/fluent/core/launcher/watchdog_exec +1 -1
- ansys/fluent/core/logger.py +3 -1
- ansys/fluent/core/module_config.py +358 -0
- ansys/fluent/core/pyfluent_warnings.py +2 -2
- ansys/fluent/core/report.py +0 -2
- ansys/fluent/core/search.py +31 -18
- ansys/fluent/core/services/api_upgrade.py +3 -2
- ansys/fluent/core/services/datamodel_se.py +4 -2
- ansys/fluent/core/services/health_check.py +3 -1
- ansys/fluent/core/services/interceptors.py +8 -6
- ansys/fluent/core/session.py +31 -3
- ansys/fluent/core/session_pure_meshing.py +1 -1
- ansys/fluent/core/session_shared.py +4 -4
- ansys/fluent/core/session_solver.py +8 -2
- ansys/fluent/core/session_utilities.py +7 -0
- ansys/fluent/core/solver/flobject.py +6 -4
- ansys/fluent/core/solver/settings_builtin_bases.py +3 -3
- ansys/fluent/core/solver/settings_builtin_data.py +2 -14
- ansys/fluent/core/streaming_services/datamodel_event_streaming.py +3 -2
- ansys/fluent/core/streaming_services/datamodel_streaming.py +3 -1
- ansys/fluent/core/streaming_services/events_streaming.py +2 -18
- ansys/fluent/core/system_coupling.py +3 -1
- ansys/fluent/core/utils/__init__.py +0 -7
- ansys/fluent/core/utils/data_transfer.py +3 -3
- ansys/fluent/core/utils/file_transfer_service.py +24 -15
- ansys/fluent/core/utils/fluent_version.py +3 -3
- ansys/fluent/core/utils/networking.py +2 -2
- {ansys_fluent_core-0.34.1.dist-info → ansys_fluent_core-0.35.dev0.dist-info}/METADATA +1 -1
- {ansys_fluent_core-0.34.1.dist-info → ansys_fluent_core-0.35.dev0.dist-info}/RECORD +81 -80
- {ansys_fluent_core-0.34.1.dist-info → ansys_fluent_core-0.35.dev0.dist-info}/LICENSE +0 -0
- {ansys_fluent_core-0.34.1.dist-info → ansys_fluent_core-0.35.dev0.dist-info}/WHEEL +0 -0
ansys/fluent/core/__init__.py
CHANGED
|
@@ -23,10 +23,14 @@
|
|
|
23
23
|
"""A package providing Fluent's Solver and Meshing capabilities in Python."""
|
|
24
24
|
|
|
25
25
|
import os
|
|
26
|
-
from pathlib import Path
|
|
27
26
|
import pydoc
|
|
27
|
+
import warnings
|
|
28
28
|
|
|
29
29
|
# isort: off
|
|
30
|
+
|
|
31
|
+
# config must be initialized before logging setup.
|
|
32
|
+
from ansys.fluent.core.module_config import config
|
|
33
|
+
|
|
30
34
|
# Logging has to be imported before importing other PyFluent modules
|
|
31
35
|
from ansys.fluent.core.logger import set_console_logging_level # noqa: F401
|
|
32
36
|
|
|
@@ -73,13 +77,13 @@ from ansys.fluent.core.session_utilities import ( # noqa: F401
|
|
|
73
77
|
SolverIcing,
|
|
74
78
|
)
|
|
75
79
|
from ansys.fluent.core.streaming_services.events_streaming import * # noqa: F401, F403
|
|
76
|
-
from ansys.fluent.core.utils import fldoc
|
|
80
|
+
from ansys.fluent.core.utils import fldoc
|
|
77
81
|
from ansys.fluent.core.utils.fluent_version import FluentVersion # noqa: F401
|
|
78
82
|
from ansys.fluent.core.utils.setup_for_fluent import setup_for_fluent # noqa: F401
|
|
79
83
|
|
|
80
|
-
__version__ = "0.
|
|
84
|
+
__version__ = "0.35.dev0"
|
|
81
85
|
|
|
82
|
-
_VERSION_INFO = "Build date: August
|
|
86
|
+
_VERSION_INFO = "Build date: August 12, 2025 05:58 UTC ShaID: c65664b"
|
|
83
87
|
"""
|
|
84
88
|
Global variable indicating the version info of the PyFluent package.
|
|
85
89
|
Build timestamp and commit hash are added to this variable during packaging.
|
|
@@ -108,86 +112,46 @@ def version_info() -> str:
|
|
|
108
112
|
return _VERSION_INFO if _VERSION_INFO is not None else __version__
|
|
109
113
|
|
|
110
114
|
|
|
111
|
-
# Latest released Fluent version
|
|
112
|
-
FLUENT_RELEASE_VERSION = "25.2.0"
|
|
113
|
-
|
|
114
|
-
# Current dev Fluent version
|
|
115
|
-
FLUENT_DEV_VERSION = "26.1.0"
|
|
116
|
-
|
|
117
|
-
# Path to the example input/data files are downloaded
|
|
118
|
-
EXAMPLES_PATH = str(get_examples_download_dir())
|
|
119
|
-
|
|
120
|
-
# Host path which is mounted to the container
|
|
121
|
-
CONTAINER_MOUNT_SOURCE = None
|
|
122
|
-
|
|
123
|
-
# Path inside the container where the host path is mounted
|
|
124
|
-
CONTAINER_MOUNT_TARGET = "/home/container/workdir"
|
|
125
|
-
|
|
126
|
-
# Set this to False to stop automatically inferring and setting REMOTING_SERVER_ADDRESS
|
|
127
|
-
INFER_REMOTING_IP = True
|
|
128
|
-
|
|
129
|
-
# Time in second to wait for response for each ip while inferring remoting ip
|
|
130
|
-
INFER_REMOTING_IP_TIMEOUT_PER_IP = 2
|
|
131
|
-
|
|
132
115
|
pydoc.text.docother = fldoc.docother.__get__(pydoc.text, pydoc.TextDoc)
|
|
133
116
|
|
|
134
|
-
# Whether to use datamodel state caching
|
|
135
|
-
DATAMODEL_USE_STATE_CACHE = True
|
|
136
|
-
|
|
137
|
-
# Whether to use datamodel attribute caching
|
|
138
|
-
DATAMODEL_USE_ATTR_CACHE = True
|
|
139
|
-
|
|
140
|
-
# Whether to stream and cache commands state
|
|
141
|
-
DATAMODEL_USE_NOCOMMANDS_DIFF_STATE = True
|
|
142
|
-
|
|
143
|
-
# Whether to return the state changes on mutating datamodel rpcs
|
|
144
|
-
DATAMODEL_RETURN_STATE_CHANGES = True
|
|
145
|
-
|
|
146
|
-
# Whether to use remote gRPC file transfer service
|
|
147
|
-
USE_FILE_TRANSFER_SERVICE = False
|
|
148
|
-
|
|
149
|
-
# Directory where API files are written out during codegen
|
|
150
|
-
CODEGEN_OUTDIR = os.getenv(
|
|
151
|
-
"PYFLUENT_CODEGEN_OUTDIR", (Path(__file__) / ".." / "generated").resolve()
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
# Whether to show mesh in Fluent after case read
|
|
155
|
-
FLUENT_SHOW_MESH_AFTER_CASE_READ = False
|
|
156
|
-
|
|
157
|
-
# Whether to write the automatic transcript in Fluent
|
|
158
|
-
FLUENT_AUTOMATIC_TRANSCRIPT = os.getenv("PYFLUENT_FLUENT_AUTOMATIC_TRANSCRIPT") == "1"
|
|
159
|
-
|
|
160
|
-
# Whether to interrupt Fluent solver from PyFluent
|
|
161
|
-
SUPPORT_SOLVER_INTERRUPT = False
|
|
162
|
-
|
|
163
|
-
# Whether to start watchdog
|
|
164
|
-
START_WATCHDOG = None
|
|
165
|
-
|
|
166
|
-
# Health check timeout in seconds
|
|
167
|
-
CHECK_HEALTH_TIMEOUT = 60
|
|
168
|
-
|
|
169
|
-
# Whether to skip health check
|
|
170
|
-
CHECK_HEALTH = True
|
|
171
|
-
|
|
172
|
-
# Whether to print search results
|
|
173
|
-
PRINT_SEARCH_RESULTS = True
|
|
174
|
-
|
|
175
|
-
# Whether to clear environment variables related to Fluent parallel mode
|
|
176
|
-
CLEAR_FLUENT_PARA_ENVS = False
|
|
177
|
-
|
|
178
|
-
# Set stdout of the launched Fluent process
|
|
179
|
-
# Valid values are same as subprocess.Popen's stdout argument
|
|
180
|
-
LAUNCH_FLUENT_STDOUT = None
|
|
181
|
-
|
|
182
|
-
# Set stderr of the launched Fluent process
|
|
183
|
-
# Valid values are same as subprocess.Popen's stderr argument
|
|
184
|
-
LAUNCH_FLUENT_STDERR = None
|
|
185
|
-
|
|
186
|
-
# Set the IP address of the Fluent server while launching Fluent
|
|
187
|
-
LAUNCH_FLUENT_IP = None
|
|
188
|
-
|
|
189
|
-
# Set the port of the Fluent server while launching Fluent
|
|
190
|
-
LAUNCH_FLUENT_PORT = None
|
|
191
117
|
|
|
192
|
-
|
|
193
|
-
|
|
118
|
+
_config_by_deprecated_name = {
|
|
119
|
+
"FLUENT_RELEASE_VERSION": "fluent_release_version",
|
|
120
|
+
"FLUENT_DEV_VERSION": "fluent_dev_version",
|
|
121
|
+
"EXAMPLES_PATH": "examples_path",
|
|
122
|
+
"CONTAINER_MOUNT_SOURCE": "container_mount_source",
|
|
123
|
+
"CONTAINER_MOUNT_TARGET": "container_mount_target",
|
|
124
|
+
"INFER_REMOTING_IP": "infer_remoting_ip",
|
|
125
|
+
"INFER_REMOTING_IP_TIMEOUT_PER_IP": "infer_remoting_ip_timeout_per_ip",
|
|
126
|
+
"DATAMODEL_USE_STATE_CACHE": "datamodel_use_state_cache",
|
|
127
|
+
"DATAMODEL_USE_ATTR_CACHE": "datamodel_use_attr_cache",
|
|
128
|
+
"DATAMODEL_USE_NOCOMMANDS_DIFF_STATE": "datamodel_use_nocommands_diff_state",
|
|
129
|
+
"DATAMODEL_RETURN_STATE_CHANGES": "datamodel_return_state_changes",
|
|
130
|
+
"USE_FILE_TRANSFER_SERVICE": "use_file_transfer_service",
|
|
131
|
+
"CODEGEN_OUTDIR": "codegen_outdir",
|
|
132
|
+
"FLUENT_SHOW_MESH_AFTER_CASE_READ": "fluent_show_mesh_after_case_read",
|
|
133
|
+
"FLUENT_AUTOMATIC_TRANSCRIPT": "fluent_automatic_transcript",
|
|
134
|
+
"SUPPORT_SOLVER_INTERRUPT": "support_solver_interrupt",
|
|
135
|
+
"START_WATCHDOG": "start_watchdog",
|
|
136
|
+
"CHECK_HEALTH_TIMEOUT": "check_health_timeout",
|
|
137
|
+
"CHECK_HEALTH": "check_health",
|
|
138
|
+
"PRINT_SEARCH_RESULTS": "print_search_results",
|
|
139
|
+
"CLEAR_FLUENT_PARA_ENVS": "clear_fluent_para_envs",
|
|
140
|
+
"LAUNCH_FLUENT_STDOUT": "launch_fluent_stdout",
|
|
141
|
+
"LAUNCH_FLUENT_STDERR": "launch_fluent_stderr",
|
|
142
|
+
"LAUNCH_FLUENT_IP": "launch_fluent_ip",
|
|
143
|
+
"LAUNCH_FLUENT_PORT": "launch_fluent_port",
|
|
144
|
+
"LAUNCH_FLUENT_SKIP_PASSWORD_CHECK": "launch_fluent_skip_password_check",
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def __getattr__(name: str) -> str:
|
|
149
|
+
"""Get the value of a deprecated configuration variable."""
|
|
150
|
+
if name in _config_by_deprecated_name:
|
|
151
|
+
config_name = _config_by_deprecated_name[name]
|
|
152
|
+
warnings.warn(
|
|
153
|
+
f"'{name}' is deprecated, use 'config.{config_name}' instead.",
|
|
154
|
+
category=PyFluentDeprecationWarning,
|
|
155
|
+
)
|
|
156
|
+
return getattr(config, config_name)
|
|
157
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"""Module to generate Fluent API classes."""
|
|
24
24
|
|
|
25
25
|
import argparse
|
|
26
|
-
import os
|
|
27
26
|
from pathlib import Path
|
|
28
27
|
import pickle
|
|
29
28
|
|
|
29
|
+
from ansys.fluent.core import config
|
|
30
30
|
from ansys.fluent.core.codegen import ( # noqa: F401
|
|
31
31
|
builtin_settingsgen,
|
|
32
32
|
datamodelgen,
|
|
@@ -51,7 +51,7 @@ def generate(version: str, static_infos: dict, verbose: bool = False):
|
|
|
51
51
|
Path(api_tree_file).parent.mkdir(parents=True, exist_ok=True)
|
|
52
52
|
with open(api_tree_file, "wb") as f:
|
|
53
53
|
pickle.dump(api_tree, f)
|
|
54
|
-
if
|
|
54
|
+
if not config.codegen_skip_builtin_settings:
|
|
55
55
|
builtin_settingsgen.generate(version)
|
|
56
56
|
|
|
57
57
|
|
|
@@ -22,25 +22,38 @@
|
|
|
22
22
|
|
|
23
23
|
"""Generate builtin setting classes."""
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
import re
|
|
26
|
+
|
|
27
|
+
from ansys.fluent.core import FluentVersion, config
|
|
28
|
+
from ansys.fluent.core.solver.flobject import (
|
|
29
|
+
CreatableNamedObjectMixin,
|
|
30
|
+
NamedObject,
|
|
31
|
+
_ChildNamedObjectAccessorMixin,
|
|
32
|
+
)
|
|
27
33
|
from ansys.fluent.core.solver.settings_builtin_data import DATA
|
|
28
34
|
from ansys.fluent.core.utils.fluent_version import all_versions
|
|
29
35
|
|
|
30
|
-
_PY_FILE =
|
|
31
|
-
_PYI_FILE =
|
|
36
|
+
_PY_FILE = config.codegen_outdir / "solver" / "settings_builtin.py"
|
|
37
|
+
_PYI_FILE = config.codegen_outdir / "solver" / "settings_builtin.pyi"
|
|
32
38
|
|
|
33
39
|
|
|
34
40
|
def _get_settings_root(version: str):
|
|
35
|
-
from ansys.fluent.core import
|
|
41
|
+
from ansys.fluent.core import config, utils
|
|
36
42
|
|
|
37
43
|
settings = utils.load_module(
|
|
38
44
|
f"settings_{version}",
|
|
39
|
-
|
|
45
|
+
config.codegen_outdir / "solver" / f"settings_{version}.py",
|
|
40
46
|
)
|
|
41
47
|
return settings.root
|
|
42
48
|
|
|
43
49
|
|
|
50
|
+
def _convert_camel_case_to_snake_case(name: str) -> str:
|
|
51
|
+
"""Convert CamelCase to snake_case."""
|
|
52
|
+
# Replace uppercase letters with lowercase and prepend an underscore
|
|
53
|
+
name = re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()
|
|
54
|
+
return name
|
|
55
|
+
|
|
56
|
+
|
|
44
57
|
def _get_named_objects_in_path(root, path, kind):
|
|
45
58
|
named_objects = []
|
|
46
59
|
cls = root
|
|
@@ -52,6 +65,8 @@ def _get_named_objects_in_path(root, path, kind):
|
|
|
52
65
|
cls = cls.child_object_type
|
|
53
66
|
final_type = ""
|
|
54
67
|
if kind == "NamedObject":
|
|
68
|
+
if not issubclass(cls, (NamedObject, _ChildNamedObjectAccessorMixin)):
|
|
69
|
+
raise TypeError(f"{cls.__name__} is not NamedObject type.")
|
|
55
70
|
if issubclass(cls, CreatableNamedObjectMixin):
|
|
56
71
|
final_type = "Creatable"
|
|
57
72
|
else:
|
|
@@ -62,7 +77,7 @@ def _get_named_objects_in_path(root, path, kind):
|
|
|
62
77
|
def generate(version: str):
|
|
63
78
|
"""Generate builtin setting classes."""
|
|
64
79
|
print("Generating builtin settings...")
|
|
65
|
-
|
|
80
|
+
config.codegen_outdir.mkdir(exist_ok=True)
|
|
66
81
|
root = _get_settings_root(version)
|
|
67
82
|
version = FluentVersion(version)
|
|
68
83
|
with open(_PY_FILE, "w") as f:
|
|
@@ -72,8 +87,11 @@ def generate(version: str):
|
|
|
72
87
|
"from ansys.fluent.core.solver.flobject import SettingsBase\n\n\n"
|
|
73
88
|
)
|
|
74
89
|
f.write("__all__ = [\n")
|
|
75
|
-
for name, _ in DATA.items():
|
|
90
|
+
for name, (kind, _) in DATA.items():
|
|
76
91
|
f.write(f' "{name}",\n')
|
|
92
|
+
if kind == "Command":
|
|
93
|
+
command_name = _convert_camel_case_to_snake_case(name)
|
|
94
|
+
f.write(f' "{command_name}",\n')
|
|
77
95
|
f.write("]\n\n")
|
|
78
96
|
for name, v in DATA.items():
|
|
79
97
|
kind, path = v
|
|
@@ -86,9 +104,31 @@ def generate(version: str):
|
|
|
86
104
|
if kind == "NamedObject":
|
|
87
105
|
kind = f"{final_type}NamedObject"
|
|
88
106
|
f.write(f"class {name}(_{kind}Setting):\n")
|
|
89
|
-
doc_kind = "command" if kind == "Command" else "setting"
|
|
107
|
+
doc_kind = "command object" if kind == "Command" else "setting"
|
|
90
108
|
f.write(f' """{name} {doc_kind}."""\n\n')
|
|
109
|
+
f.write(f' _db_name = "{name}"\n\n')
|
|
110
|
+
f.write(" def __init__(self")
|
|
111
|
+
for named_object in named_objects:
|
|
112
|
+
f.write(f", {named_object}: str")
|
|
113
|
+
f.write(", settings_source: SettingsBase | Solver | None = None")
|
|
114
|
+
if kind == "NonCreatableNamedObject":
|
|
115
|
+
f.write(", name: str = None")
|
|
116
|
+
elif kind == "CreatableNamedObject":
|
|
117
|
+
f.write(", name: str = None, new_instance_name: str = None")
|
|
118
|
+
f.write("):\n")
|
|
119
|
+
f.write(" super().__init__(settings_source=settings_source")
|
|
120
|
+
if kind == "NonCreatableNamedObject":
|
|
121
|
+
f.write(", name=name")
|
|
122
|
+
elif kind == "CreatableNamedObject":
|
|
123
|
+
f.write(", name=name, new_instance_name=new_instance_name")
|
|
124
|
+
for named_object in named_objects:
|
|
125
|
+
f.write(f", {named_object}={named_object}")
|
|
126
|
+
f.write(")\n\n")
|
|
91
127
|
if kind == "Command":
|
|
128
|
+
command_name = _convert_camel_case_to_snake_case(name)
|
|
129
|
+
f.write(f"class {command_name}(_{kind}Setting):\n")
|
|
130
|
+
f.write(f' """{command_name} command."""\n\n')
|
|
131
|
+
f.write(f' _db_name = "{name}"\n\n')
|
|
92
132
|
f.write(
|
|
93
133
|
" def __new__(cls, settings_source: SettingsBase | Solver | None = None, **kwargs):\n"
|
|
94
134
|
)
|
|
@@ -96,25 +136,7 @@ def generate(version: str):
|
|
|
96
136
|
f.write(
|
|
97
137
|
" instance.__init__(settings_source=settings_source, **kwargs)\n"
|
|
98
138
|
)
|
|
99
|
-
f.write(" return instance(**kwargs")
|
|
100
|
-
else:
|
|
101
|
-
f.write(" def __init__(self")
|
|
102
|
-
for named_object in named_objects:
|
|
103
|
-
f.write(f", {named_object}: str")
|
|
104
|
-
f.write(", settings_source: SettingsBase | Solver | None = None")
|
|
105
|
-
if kind == "NonCreatableNamedObject":
|
|
106
|
-
f.write(", name: str = None")
|
|
107
|
-
elif kind == "CreatableNamedObject":
|
|
108
|
-
f.write(", name: str = None, new_instance_name: str = None")
|
|
109
|
-
f.write("):\n")
|
|
110
|
-
f.write(" super().__init__(settings_source=settings_source")
|
|
111
|
-
if kind == "NonCreatableNamedObject":
|
|
112
|
-
f.write(", name=name")
|
|
113
|
-
elif kind == "CreatableNamedObject":
|
|
114
|
-
f.write(", name=name, new_instance_name=new_instance_name")
|
|
115
|
-
for named_object in named_objects:
|
|
116
|
-
f.write(f", {named_object}={named_object}")
|
|
117
|
-
f.write(")\n\n")
|
|
139
|
+
f.write(" return instance(**kwargs)\n\n")
|
|
118
140
|
|
|
119
141
|
with open(_PYI_FILE, "w") as f:
|
|
120
142
|
for version in FluentVersion:
|
|
@@ -210,7 +210,9 @@ class DataModelStaticInfo:
|
|
|
210
210
|
self.static_info = None
|
|
211
211
|
if rules_save_name == "":
|
|
212
212
|
rules_save_name = rules
|
|
213
|
-
datamodel_dir = (
|
|
213
|
+
datamodel_dir = (
|
|
214
|
+
pyfluent.config.codegen_outdir / f"datamodel_{version}"
|
|
215
|
+
).resolve()
|
|
214
216
|
datamodel_dir.mkdir(exist_ok=True)
|
|
215
217
|
self.file_name = (
|
|
216
218
|
datamodel_dir / f"{datamodel_file_name_map[rules_save_name]}.py"
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
|
|
23
23
|
"""Module to write Fluent version information."""
|
|
24
24
|
|
|
25
|
-
from ansys.fluent.core import
|
|
25
|
+
from ansys.fluent.core import FluentVersion, config, launch_fluent
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def print_fluent_version(app_utilities):
|
|
29
29
|
"""Write Fluent version information to file."""
|
|
30
30
|
version = FluentVersion(app_utilities.get_product_version()).number
|
|
31
31
|
build_info = app_utilities.get_build_info()
|
|
32
|
-
version_file = (
|
|
32
|
+
version_file = (config.codegen_outdir / f"fluent_version_{version}.py").resolve()
|
|
33
33
|
with open(version_file, "w", encoding="utf8") as f:
|
|
34
34
|
f.write(f'FLUENT_VERSION = "{version}"\n')
|
|
35
35
|
f.write(f'FLUENT_BUILD_TIME = "{build_info.build_time}"\n')
|
|
@@ -355,7 +355,7 @@ def generate(version: str, static_infos: dict, verbose: bool = False) -> None:
|
|
|
355
355
|
shash = _gethash(sinfo)
|
|
356
356
|
if not sinfo:
|
|
357
357
|
return {"<solver_session>": api_tree}
|
|
358
|
-
output_dir = (pyfluent.
|
|
358
|
+
output_dir = (pyfluent.config.codegen_outdir / "solver").resolve()
|
|
359
359
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
360
360
|
output_file = output_dir / f"settings_{version}.py"
|
|
361
361
|
output_stub_file = output_dir / f"settings_{version}.pyi"
|
|
@@ -69,7 +69,7 @@ _ROOT_DIR = Path(__file__) / ".." / ".." / ".." / ".." / ".." / ".."
|
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
def _get_tui_filepath(mode: str, version: str):
|
|
72
|
-
return (pyfluent.
|
|
72
|
+
return (pyfluent.config.codegen_outdir / mode / f"tui_{version}.py").resolve()
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
_INDENT_STEP = 4
|
|
@@ -96,8 +96,8 @@ _XML_HELPSTRINGS = {}
|
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def _copy_tui_help_xml_file(version: str):
|
|
99
|
-
if
|
|
100
|
-
image_tag =
|
|
99
|
+
if pyfluent.config.launch_fluent_container:
|
|
100
|
+
image_tag = pyfluent.config.fluent_image_tag
|
|
101
101
|
image_name = f"{get_ghcr_fluent_image_name(image_tag)}:{image_tag}"
|
|
102
102
|
container_name = uuid.uuid4().hex
|
|
103
103
|
is_linux = platform.system() == "Linux"
|
|
@@ -347,7 +347,7 @@ def generate(version, static_infos: dict, verbose: bool = False):
|
|
|
347
347
|
api_tree["<solver_session>"] = TUIGenerator(
|
|
348
348
|
"solver", version, static_infos, verbose
|
|
349
349
|
).generate()
|
|
350
|
-
if
|
|
350
|
+
if not pyfluent.config.hide_log_secrets:
|
|
351
351
|
logger.info(
|
|
352
352
|
"XML help is available but not picked for the following %i paths: ",
|
|
353
353
|
len(_XML_HELPSTRINGS),
|
|
@@ -126,7 +126,7 @@ class _CacheImpl:
|
|
|
126
126
|
|
|
127
127
|
def _is_dict_parameter_type(version: FluentVersion, rules: str, rules_path: str):
|
|
128
128
|
"""Check if a parameter is a dict type."""
|
|
129
|
-
from ansys.fluent.core import
|
|
129
|
+
from ansys.fluent.core import config
|
|
130
130
|
from ansys.fluent.core.services.datamodel_se import (
|
|
131
131
|
PyDictionary,
|
|
132
132
|
PyNamedObjectContainer,
|
|
@@ -136,7 +136,7 @@ def _is_dict_parameter_type(version: FluentVersion, rules: str, rules_path: str)
|
|
|
136
136
|
|
|
137
137
|
try:
|
|
138
138
|
module = load_module(
|
|
139
|
-
rules,
|
|
139
|
+
rules, config.codegen_outdir / f"datamodel_{version.number}" / f"{rules}.py"
|
|
140
140
|
)
|
|
141
141
|
except FileNotFoundError: # no codegen or during codegen
|
|
142
142
|
return False
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
23
|
# SOFTWARE.
|
|
24
24
|
|
|
25
|
-
import os
|
|
26
25
|
import subprocess
|
|
27
26
|
import uuid
|
|
28
27
|
|
|
@@ -32,10 +31,13 @@ from .utils import get_ghcr_fluent_image_name
|
|
|
32
31
|
class ComposeBasedLauncher:
|
|
33
32
|
"""Launch Fluent through docker or Podman compose."""
|
|
34
33
|
|
|
35
|
-
def __init__(self,
|
|
34
|
+
def __init__(self, compose_config, container_dict):
|
|
35
|
+
from ansys.fluent.core import config
|
|
36
|
+
|
|
37
|
+
self._compose_config = compose_config
|
|
36
38
|
self._compose_name = f"pyfluent_compose_{uuid.uuid4().hex}"
|
|
37
39
|
self._container_dict = container_dict
|
|
38
|
-
image_tag =
|
|
40
|
+
image_tag = config.fluent_image_tag
|
|
39
41
|
self._image_name = (
|
|
40
42
|
container_dict.get("fluent_image")
|
|
41
43
|
or f"{get_ghcr_fluent_image_name(image_tag)}:{image_tag}"
|
|
@@ -45,9 +47,6 @@ class ComposeBasedLauncher:
|
|
|
45
47
|
|
|
46
48
|
self._compose_file = self._get_compose_file(container_dict)
|
|
47
49
|
|
|
48
|
-
def _is_podman_selected(self):
|
|
49
|
-
return os.getenv("PYFLUENT_USE_PODMAN_COMPOSE") == "1"
|
|
50
|
-
|
|
51
50
|
def _get_compose_file(self, container_dict):
|
|
52
51
|
"""Generates compose file for the Docker Compose setup.
|
|
53
52
|
|
|
@@ -132,14 +131,14 @@ class ComposeBasedLauncher:
|
|
|
132
131
|
"""
|
|
133
132
|
|
|
134
133
|
# Determine the compose command
|
|
135
|
-
if
|
|
134
|
+
if self._compose_config.use_podman_compose:
|
|
136
135
|
self._compose_cmds = (
|
|
137
136
|
["sudo", "podman", "compose"]
|
|
138
137
|
if hasattr(self, "_container_source")
|
|
139
138
|
and "sudo" in self._container_source
|
|
140
139
|
else ["podman", "compose"]
|
|
141
140
|
)
|
|
142
|
-
elif
|
|
141
|
+
elif self._compose_config.use_docker_compose:
|
|
143
142
|
self._compose_cmds = ["docker", "compose"]
|
|
144
143
|
else:
|
|
145
144
|
raise RuntimeError("Neither Docker nor Podman is specified.")
|
|
@@ -151,7 +150,7 @@ class ComposeBasedLauncher:
|
|
|
151
150
|
try:
|
|
152
151
|
cmd = self._container_source + ["images", "-q", self._image_name]
|
|
153
152
|
# Podman users do not always configure rootless mode in /etc/subuids and /etc/subgids
|
|
154
|
-
if self.
|
|
153
|
+
if self._compose_config.use_podman_compose:
|
|
155
154
|
sudo_cmd = ["sudo"] + cmd
|
|
156
155
|
output_1 = subprocess.check_output(cmd)
|
|
157
156
|
output_2 = subprocess.check_output(sudo_cmd)
|
|
@@ -29,7 +29,7 @@ def get_ghcr_fluent_image_name(image_tag: str):
|
|
|
29
29
|
"""
|
|
30
30
|
Get the Fluent image name from GitHub registry based on the image tag.
|
|
31
31
|
"""
|
|
32
|
-
if image_tag >= "v26.1":
|
|
32
|
+
if image_tag.startswith("sha256:") or image_tag >= "v26.1":
|
|
33
33
|
return "ghcr.io/ansys/fluent"
|
|
34
34
|
else:
|
|
35
35
|
return "ghcr.io/ansys/pyfluent"
|
|
@@ -49,16 +49,16 @@ def delete_downloads():
|
|
|
49
49
|
|
|
50
50
|
Notes
|
|
51
51
|
-----
|
|
52
|
-
The default examples path is given by ``pyfluent.
|
|
52
|
+
The default examples path is given by ``pyfluent.config.examples_path``.
|
|
53
53
|
"""
|
|
54
|
-
shutil.rmtree(pyfluent.
|
|
55
|
-
os.makedirs(pyfluent.
|
|
54
|
+
shutil.rmtree(pyfluent.config.examples_path)
|
|
55
|
+
os.makedirs(pyfluent.config.examples_path)
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
def _decompress(file_name: str) -> None:
|
|
59
59
|
"""Decompress zipped file."""
|
|
60
60
|
zip_ref = zipfile.ZipFile(file_name, "r")
|
|
61
|
-
zip_ref.extractall(pyfluent.
|
|
61
|
+
zip_ref.extractall(pyfluent.config.examples_path)
|
|
62
62
|
return zip_ref.close()
|
|
63
63
|
|
|
64
64
|
|
|
@@ -81,10 +81,7 @@ def _retrieve_file(
|
|
|
81
81
|
"""Download specified file from specified URL."""
|
|
82
82
|
file_name = os.path.basename(file_name)
|
|
83
83
|
if save_path is None:
|
|
84
|
-
save_path = os.
|
|
85
|
-
"PYFLUENT_CONTAINER_MOUNT_SOURCE",
|
|
86
|
-
pyfluent.CONTAINER_MOUNT_SOURCE or os.getcwd(),
|
|
87
|
-
)
|
|
84
|
+
save_path = pyfluent.config.container_mount_source or os.getcwd()
|
|
88
85
|
else:
|
|
89
86
|
save_path = os.path.abspath(save_path)
|
|
90
87
|
local_path = os.path.join(save_path, file_name)
|
|
@@ -180,8 +177,8 @@ def download_file(
|
|
|
180
177
|
'bracket.iges'
|
|
181
178
|
"""
|
|
182
179
|
if return_without_path is None:
|
|
183
|
-
if
|
|
184
|
-
if pyfluent.
|
|
180
|
+
if pyfluent.config.launch_fluent_container:
|
|
181
|
+
if pyfluent.config.use_file_transfer_service:
|
|
185
182
|
return_without_path = False
|
|
186
183
|
else:
|
|
187
184
|
return_without_path = True
|
|
@@ -212,7 +209,7 @@ def path(file_name: str):
|
|
|
212
209
|
"""
|
|
213
210
|
if os.path.isabs(file_name):
|
|
214
211
|
return file_name
|
|
215
|
-
file_path = Path(pyfluent.
|
|
212
|
+
file_path = Path(pyfluent.config.examples_path) / file_name
|
|
216
213
|
if file_path.is_file():
|
|
217
214
|
return str(file_path)
|
|
218
215
|
else:
|
|
@@ -42,7 +42,7 @@ from deprecated.sphinx import deprecated
|
|
|
42
42
|
import grpc
|
|
43
43
|
|
|
44
44
|
import ansys.fluent.core as pyfluent
|
|
45
|
-
from ansys.fluent.core.launcher.launcher_utils import
|
|
45
|
+
from ansys.fluent.core.launcher.launcher_utils import ComposeConfig
|
|
46
46
|
from ansys.fluent.core.services import service_creator
|
|
47
47
|
from ansys.fluent.core.services.app_utilities import (
|
|
48
48
|
AppUtilitiesOld,
|
|
@@ -252,9 +252,9 @@ class FluentConnectionProperties:
|
|
|
252
252
|
|
|
253
253
|
def _get_ip_and_port(ip: str | None = None, port: int | None = None) -> (str, int):
|
|
254
254
|
if not ip:
|
|
255
|
-
ip =
|
|
255
|
+
ip = pyfluent.config.launch_fluent_ip or "127.0.0.1"
|
|
256
256
|
if not port:
|
|
257
|
-
port =
|
|
257
|
+
port = pyfluent.config.launch_fluent_port
|
|
258
258
|
if not port:
|
|
259
259
|
raise PortNotProvided()
|
|
260
260
|
return ip, port
|
|
@@ -381,6 +381,7 @@ class FluentConnection:
|
|
|
381
381
|
slurm_job_id: str | None = None,
|
|
382
382
|
inside_container: bool | None = None,
|
|
383
383
|
container: ContainerT | None = None,
|
|
384
|
+
compose_config: ComposeConfig | None = None,
|
|
384
385
|
):
|
|
385
386
|
"""Initialize a Session.
|
|
386
387
|
|
|
@@ -420,12 +421,15 @@ class FluentConnection:
|
|
|
420
421
|
container: ContainerT, optional
|
|
421
422
|
The container instance if the Fluent session is running inside
|
|
422
423
|
a container.
|
|
424
|
+
compose_config: ComposeConfig, optional
|
|
425
|
+
Configuration for Docker Compose or Podman Compose.
|
|
423
426
|
|
|
424
427
|
Raises
|
|
425
428
|
------
|
|
426
429
|
PortNotProvided
|
|
427
430
|
If port is not provided.
|
|
428
431
|
"""
|
|
432
|
+
self._compose_config = compose_config if compose_config else ComposeConfig()
|
|
429
433
|
self._error_state = ErrorState()
|
|
430
434
|
self._data_valid = False
|
|
431
435
|
self._channel_str = None
|
|
@@ -447,7 +451,7 @@ class FluentConnection:
|
|
|
447
451
|
# At this point, the server must be running. If the following check_health()
|
|
448
452
|
# throws, we should not proceed.
|
|
449
453
|
# TODO: Show user-friendly error message.
|
|
450
|
-
if pyfluent.
|
|
454
|
+
if pyfluent.config.check_health:
|
|
451
455
|
self._health_check.check_health()
|
|
452
456
|
|
|
453
457
|
self._slurm_job_id = slurm_job_id
|
|
@@ -472,7 +476,7 @@ class FluentConnection:
|
|
|
472
476
|
and cortex_host is not None
|
|
473
477
|
):
|
|
474
478
|
logger.info("Checking if Fluent is running inside a container.")
|
|
475
|
-
if not is_compose
|
|
479
|
+
if not self._compose_config.is_compose:
|
|
476
480
|
inside_container = get_container(cortex_host)
|
|
477
481
|
logger.debug(f"get_container({cortex_host}): {inside_container}")
|
|
478
482
|
if inside_container is False:
|
|
@@ -549,7 +553,10 @@ class FluentConnection:
|
|
|
549
553
|
>>> session = pyfluent.launch_fluent()
|
|
550
554
|
>>> session.force_exit()
|
|
551
555
|
"""
|
|
552
|
-
if
|
|
556
|
+
if (
|
|
557
|
+
self.connection_properties.inside_container
|
|
558
|
+
or self._compose_config.is_compose
|
|
559
|
+
):
|
|
553
560
|
self._force_exit_container()
|
|
554
561
|
elif self._remote_instance is not None:
|
|
555
562
|
logger.error("Cannot execute cleanup script, Fluent running remotely.")
|
|
@@ -601,7 +608,7 @@ class FluentConnection:
|
|
|
601
608
|
def _force_exit_container(self):
|
|
602
609
|
"""Immediately terminates the Fluent client running inside a container, losing
|
|
603
610
|
unsaved progress and data."""
|
|
604
|
-
if is_compose
|
|
611
|
+
if self._compose_config.is_compose and self._container:
|
|
605
612
|
self._container.stop()
|
|
606
613
|
else:
|
|
607
614
|
container = self.connection_properties.inside_container
|
|
@@ -679,7 +686,10 @@ class FluentConnection:
|
|
|
679
686
|
else:
|
|
680
687
|
raise WaitTypeError()
|
|
681
688
|
|
|
682
|
-
if
|
|
689
|
+
if (
|
|
690
|
+
self.connection_properties.inside_container
|
|
691
|
+
and not self._compose_config.is_compose
|
|
692
|
+
):
|
|
683
693
|
_response = timeout_loop(
|
|
684
694
|
get_container,
|
|
685
695
|
wait,
|
|
@@ -748,17 +758,15 @@ class FluentConnection:
|
|
|
748
758
|
)
|
|
749
759
|
|
|
750
760
|
if timeout is None:
|
|
751
|
-
|
|
752
|
-
if
|
|
753
|
-
logger.debug(
|
|
754
|
-
f"Found PYFLUENT_TIMEOUT_FORCE_EXIT env var: '{env_timeout}'"
|
|
755
|
-
)
|
|
761
|
+
config_timeout = pyfluent.config.force_exit_timeout
|
|
762
|
+
if config_timeout is not None:
|
|
763
|
+
logger.debug(f"Found force_exit_timeout config: '{config_timeout}'")
|
|
756
764
|
try:
|
|
757
|
-
timeout = float(
|
|
765
|
+
timeout = float(config_timeout)
|
|
758
766
|
logger.debug(f"Setting TIMEOUT_FORCE_EXIT to {timeout}")
|
|
759
767
|
except ValueError:
|
|
760
768
|
logger.debug(
|
|
761
|
-
"Invalid
|
|
769
|
+
"Invalid force_exit_timeout config. Must be a float or int. "
|
|
762
770
|
"Timeout forced exit is disabled."
|
|
763
771
|
)
|
|
764
772
|
|