ansys-fluent-core 0.35.dev0__py3-none-any.whl → 0.36.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 +2 -2
- ansys/fluent/core/codegen/__init__.py +1 -0
- ansys/fluent/core/codegen/builtin_settingsgen.py +4 -0
- ansys/fluent/core/codegen/datamodelgen.py +13 -2
- ansys/fluent/core/codegen/settingsgen.py +7 -0
- ansys/fluent/core/docker/docker_compose.py +30 -1
- ansys/fluent/core/examples/downloads.py +3 -4
- ansys/fluent/core/fluent_connection.py +2 -3
- ansys/fluent/core/generated/api_tree/api_objects.json +1 -1
- ansys/fluent/core/generated/datamodel_231/flicing.py +20 -20
- ansys/fluent/core/generated/datamodel_231/meshing.py +236 -236
- ansys/fluent/core/generated/datamodel_232/flicing.py +50 -50
- ansys/fluent/core/generated/datamodel_232/meshing.py +187 -187
- ansys/fluent/core/generated/datamodel_241/flicing.py +45 -45
- ansys/fluent/core/generated/datamodel_241/meshing.py +229 -229
- ansys/fluent/core/generated/datamodel_242/flicing.py +50 -50
- ansys/fluent/core/generated/datamodel_242/meshing.py +275 -275
- ansys/fluent/core/generated/datamodel_242/part_management.py +3 -3
- ansys/fluent/core/generated/datamodel_251/flicing.py +45 -45
- ansys/fluent/core/generated/datamodel_251/meshing.py +417 -417
- ansys/fluent/core/generated/datamodel_251/part_management.py +9 -9
- ansys/fluent/core/generated/datamodel_252/flicing.py +30 -30
- ansys/fluent/core/generated/datamodel_252/meshing.py +418 -418
- ansys/fluent/core/generated/datamodel_252/part_management.py +5 -5
- ansys/fluent/core/generated/datamodel_261/flicing.py +35 -35
- ansys/fluent/core/generated/datamodel_261/meshing.py +481 -425
- ansys/fluent/core/generated/datamodel_261/meshing_utilities.py +296 -616
- ansys/fluent/core/generated/datamodel_261/meshing_workflow.py +61694 -0
- ansys/fluent/core/generated/datamodel_261/part_management.py +10 -10
- ansys/fluent/core/generated/datamodel_261/preferences.py +56 -0
- ansys/fluent/core/generated/datamodel_261/solver_workflow.py +14 -0
- ansys/fluent/core/generated/fluent_version_261.py +3 -3
- ansys/fluent/core/generated/meshing/tui_261.py +408 -10
- ansys/fluent/core/generated/solver/settings_261.py +15135 -5725
- ansys/fluent/core/generated/solver/settings_261.pyi +10252 -3619
- ansys/fluent/core/generated/solver/tui_261.py +2632 -834
- ansys/fluent/core/launcher/container_launcher.py +12 -3
- ansys/fluent/core/launcher/fluent_container.py +7 -1
- ansys/fluent/core/launcher/launch_options.py +2 -2
- ansys/fluent/core/launcher/launcher.py +2 -6
- ansys/fluent/core/launcher/pim_launcher.py +76 -3
- ansys/fluent/core/launcher/process_launch_string.py +1 -2
- ansys/fluent/core/launcher/slurm_launcher.py +4 -3
- ansys/fluent/core/launcher/standalone_launcher.py +3 -2
- ansys/fluent/core/module_config.py +10 -10
- ansys/fluent/core/report.py +1 -1
- ansys/fluent/core/search.py +12 -0
- ansys/fluent/core/services/__init__.py +2 -0
- ansys/fluent/core/services/datamodel_se.py +4 -1
- ansys/fluent/core/services/field_data.py +24 -0
- ansys/fluent/core/services/reduction.py +2 -0
- ansys/fluent/core/services/settings.py +1 -1
- ansys/fluent/core/services/solution_variables.py +92 -0
- ansys/fluent/core/session.py +1 -2
- ansys/fluent/core/session_base_meshing.py +8 -0
- ansys/fluent/core/session_meshing.py +5 -0
- ansys/fluent/core/session_pure_meshing.py +6 -0
- ansys/fluent/core/session_pure_meshing.pyi +5 -0
- ansys/fluent/core/session_solver.py +5 -4
- ansys/fluent/core/session_utilities.py +8 -5
- ansys/fluent/core/solver/flobject.py +19 -0
- ansys/fluent/core/solver/flunits.py +2 -0
- ansys/fluent/core/solver/function/reduction.py +2 -0
- ansys/fluent/core/ui/__init__.py +64 -0
- ansys/fluent/core/ui/jupyter_ui.py +203 -0
- ansys/fluent/core/ui/standalone_web_ui.py +296 -0
- ansys/fluent/core/ui/utils.py +173 -0
- ansys/fluent/core/utils/deprecate.py +1 -0
- ansys/fluent/core/utils/networking.py +11 -2
- {ansys_fluent_core-0.35.dev0.dist-info → ansys_fluent_core-0.36.dev0.dist-info}/METADATA +29 -22
- {ansys_fluent_core-0.35.dev0.dist-info → ansys_fluent_core-0.36.dev0.dist-info}/RECORD +73 -68
- {ansys_fluent_core-0.35.dev0.dist-info → ansys_fluent_core-0.36.dev0.dist-info}/WHEEL +1 -1
- {ansys_fluent_core-0.35.dev0.dist-info → ansys_fluent_core-0.36.dev0.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# Copyright (C) 2021 - 2025 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
|
+
"""Web UI for Fluent settings using Panel with lazy loading and batched property access."""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from typing import Any, Callable, Dict, List
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
import panel as pn
|
|
31
|
+
import param
|
|
32
|
+
except ModuleNotFoundError as exc:
|
|
33
|
+
raise ModuleNotFoundError(
|
|
34
|
+
"Missing dependencies, use 'pip install ansys-fluent-core[ui]' to install them."
|
|
35
|
+
) from exc
|
|
36
|
+
|
|
37
|
+
from ansys.fluent.core.solver.flobject import (
|
|
38
|
+
BaseCommand,
|
|
39
|
+
Group,
|
|
40
|
+
NamedObject,
|
|
41
|
+
)
|
|
42
|
+
from ansys.fluent.core.ui.utils import (
|
|
43
|
+
_parse_path,
|
|
44
|
+
_render_widget_from_props_generic,
|
|
45
|
+
_safe_get_properties,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
_path_backup_dict = {}
|
|
49
|
+
|
|
50
|
+
AUTO_REFRESH = False
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def set_auto_refresh():
|
|
54
|
+
"""Refreshes the UI w.r.t. server state for each command execution or parameter invocation."""
|
|
55
|
+
global AUTO_REFRESH
|
|
56
|
+
AUTO_REFRESH = True
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
pn.extension()
|
|
60
|
+
|
|
61
|
+
# global trigger for refresh (Panel Param depends on it)
|
|
62
|
+
_refresh = pn.state.cache.get("fluent_refresh", None)
|
|
63
|
+
if _refresh is None:
|
|
64
|
+
|
|
65
|
+
class Refresh(param.Parameterized):
|
|
66
|
+
"""Refresh."""
|
|
67
|
+
|
|
68
|
+
bump = param.Event()
|
|
69
|
+
|
|
70
|
+
_refresh = Refresh()
|
|
71
|
+
pn.state.cache["fluent_refresh"] = _refresh
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _render_widget_from_props(
|
|
75
|
+
settings_obj, label: str, props: Dict[str, Any]
|
|
76
|
+
) -> pn.viewable.Viewable:
|
|
77
|
+
"""Produce a Panel widget from type+props. No backend mutation here."""
|
|
78
|
+
return _render_widget_from_props_generic(settings_obj, label, props, pn.widgets)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _param_view(settings_obj, props: Dict[str, Any]) -> pn.viewable.Viewable:
|
|
82
|
+
label = props["python_name"].replace("_", " ").capitalize()
|
|
83
|
+
|
|
84
|
+
def get_fn():
|
|
85
|
+
try:
|
|
86
|
+
return getattr(props["parent"], props["python_name"])
|
|
87
|
+
except AttributeError:
|
|
88
|
+
return props["parent"][props["obj_name"]]
|
|
89
|
+
|
|
90
|
+
def set_fn(v):
|
|
91
|
+
return setattr(settings_obj.parent, props["python_name"], v)
|
|
92
|
+
|
|
93
|
+
w = _render_widget_from_props(get_fn(), label, props)
|
|
94
|
+
obj_apth = _parse_path(settings_obj)
|
|
95
|
+
if obj_apth in _path_backup_dict:
|
|
96
|
+
console = pn.pane.Markdown(
|
|
97
|
+
f"```\n{obj_apth} = {_path_backup_dict[obj_apth]}\n```",
|
|
98
|
+
sizing_mode="stretch_width",
|
|
99
|
+
)
|
|
100
|
+
else:
|
|
101
|
+
console = pn.pane.Markdown(f"```\n{obj_apth}\n```", sizing_mode="stretch_width")
|
|
102
|
+
|
|
103
|
+
# Change handlers
|
|
104
|
+
if hasattr(w, "_is_list_text"):
|
|
105
|
+
typ, parse_csv = w._is_list_text
|
|
106
|
+
|
|
107
|
+
def _commit_list(event):
|
|
108
|
+
if event is None:
|
|
109
|
+
return
|
|
110
|
+
newv = event.new
|
|
111
|
+
if parse_csv:
|
|
112
|
+
raw = newv or ""
|
|
113
|
+
vals = [typ(v.strip()) for v in raw.split(",") if v.strip()]
|
|
114
|
+
else:
|
|
115
|
+
vals = list(newv or [])
|
|
116
|
+
try:
|
|
117
|
+
set_fn(vals)
|
|
118
|
+
console.object = f"```\n{_parse_path(settings_obj)} = {vals}\n```"
|
|
119
|
+
_path_backup_dict[_parse_path(settings_obj)] = vals
|
|
120
|
+
if AUTO_REFRESH:
|
|
121
|
+
_refresh.bump = True
|
|
122
|
+
except Exception as e:
|
|
123
|
+
console.object = f"```\nError setting {label}: {e}\n```"
|
|
124
|
+
|
|
125
|
+
w.param.watch(_commit_list, "value", onlychanged=True)
|
|
126
|
+
else:
|
|
127
|
+
|
|
128
|
+
def _commit(event):
|
|
129
|
+
if event is None:
|
|
130
|
+
return
|
|
131
|
+
try:
|
|
132
|
+
set_fn(event.new)
|
|
133
|
+
console.object = f"```\n{_parse_path(settings_obj)} = {event.new}\n```"
|
|
134
|
+
_path_backup_dict[_parse_path(settings_obj)] = event.new
|
|
135
|
+
if AUTO_REFRESH:
|
|
136
|
+
_refresh.bump = True
|
|
137
|
+
except Exception as e:
|
|
138
|
+
console.object = f"```\nError setting {label}: {e}\n```"
|
|
139
|
+
|
|
140
|
+
w.param.watch(_commit, "value", onlychanged=True)
|
|
141
|
+
|
|
142
|
+
return pn.Column(
|
|
143
|
+
w, console, sizing_mode="stretch_width", margin=(10, 20), align="start"
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _command_view(func, props: Dict[str, Any]) -> pn.viewable.Viewable:
|
|
148
|
+
"""Render command arguments (on demand) and execute only on click."""
|
|
149
|
+
# Safely fetch argument names (does NOT execute the command)
|
|
150
|
+
if not hasattr(func, "argument_names"):
|
|
151
|
+
return pn.pane.HTML("<i>Command has no 'argument_names()'.</i>")
|
|
152
|
+
arg_names = func.argument_names
|
|
153
|
+
arg_widgets: Dict[str, Any] = {}
|
|
154
|
+
controls: List[pn.viewable.Viewable] = []
|
|
155
|
+
|
|
156
|
+
# Build argument widgets immediately when this view is created
|
|
157
|
+
for name in arg_names:
|
|
158
|
+
param_obj = getattr(func, name) # safe: this just references the arg handle
|
|
159
|
+
pprops = _safe_get_properties(param_obj)
|
|
160
|
+
widget = _render_widget_from_props(param_obj, name, pprops)
|
|
161
|
+
arg_widgets[name] = widget
|
|
162
|
+
controls.append(widget)
|
|
163
|
+
|
|
164
|
+
btn = pn.widgets.Button(name=f"Run {props['python_name']}", button_type="success")
|
|
165
|
+
obj_path = _parse_path(func)
|
|
166
|
+
if obj_path in _path_backup_dict:
|
|
167
|
+
console = pn.pane.Markdown(
|
|
168
|
+
f"```\n{_path_backup_dict[obj_path]}\n```", sizing_mode="stretch_width"
|
|
169
|
+
)
|
|
170
|
+
else:
|
|
171
|
+
console = pn.pane.Markdown(f"```\n{obj_path}\n```", sizing_mode="stretch_width")
|
|
172
|
+
|
|
173
|
+
def _run(_):
|
|
174
|
+
kwargs = {n: w.value for n, w in arg_widgets.items()}
|
|
175
|
+
try:
|
|
176
|
+
func(**kwargs) # Executes ONLY here
|
|
177
|
+
# Render kwargs similarly to your ipywidgets formatter
|
|
178
|
+
parts = []
|
|
179
|
+
for k, v in kwargs.items():
|
|
180
|
+
if isinstance(v, str):
|
|
181
|
+
if v != "":
|
|
182
|
+
parts.append(f"{k}='{v}'")
|
|
183
|
+
else:
|
|
184
|
+
parts.append(f"{k}={v}")
|
|
185
|
+
call = f"{_parse_path(func)}({', '.join(parts)})"
|
|
186
|
+
console.object = f"```\n{call}\n```"
|
|
187
|
+
_path_backup_dict[_parse_path(func)] = call
|
|
188
|
+
if AUTO_REFRESH:
|
|
189
|
+
_refresh.bump = True
|
|
190
|
+
except Exception as e:
|
|
191
|
+
console.object = f"```\nError: {e}\n```"
|
|
192
|
+
|
|
193
|
+
btn.on_click(_run)
|
|
194
|
+
return pn.Column(
|
|
195
|
+
*controls,
|
|
196
|
+
btn,
|
|
197
|
+
console,
|
|
198
|
+
sizing_mode="stretch_width",
|
|
199
|
+
margin=(10, 20),
|
|
200
|
+
align="start",
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# ---------------------------
|
|
205
|
+
# Lazy accordion (recursive)
|
|
206
|
+
# ---------------------------
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _lazy_section(
|
|
210
|
+
title: str, loader: Callable[[], pn.viewable.Viewable]
|
|
211
|
+
) -> pn.Accordion:
|
|
212
|
+
"""
|
|
213
|
+
A single-node Accordion whose body is constructed ON FIRST EXPAND.
|
|
214
|
+
Subsequent expands reuse the existing content.
|
|
215
|
+
"""
|
|
216
|
+
placeholder = pn.pane.Markdown("*(loading…)*")
|
|
217
|
+
acc = pn.Accordion((title, placeholder), sizing_mode="stretch_width")
|
|
218
|
+
|
|
219
|
+
def _load_content():
|
|
220
|
+
try:
|
|
221
|
+
return loader()
|
|
222
|
+
except Exception as e:
|
|
223
|
+
return pn.pane.Markdown(f"**Error loading section**: {e}")
|
|
224
|
+
|
|
225
|
+
def _maybe_load(event=None):
|
|
226
|
+
if acc.active and 0 in acc.active:
|
|
227
|
+
content = _load_content()
|
|
228
|
+
acc[0] = (title, content)
|
|
229
|
+
|
|
230
|
+
# Trigger when first opened
|
|
231
|
+
acc.param.watch(_maybe_load, "active", onlychanged=True)
|
|
232
|
+
|
|
233
|
+
def _on_refresh(event):
|
|
234
|
+
if acc.active and 0 in acc.active:
|
|
235
|
+
_maybe_load()
|
|
236
|
+
|
|
237
|
+
_refresh.param.watch(_on_refresh, "bump")
|
|
238
|
+
|
|
239
|
+
return acc
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# ---------------------------
|
|
243
|
+
# Main entry (recursive renderer)
|
|
244
|
+
# ---------------------------
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _settings_view(obj, indent: int = 0) -> pn.viewable.Viewable:
|
|
248
|
+
"""Recursively build the view for a settings object (lazy children)."""
|
|
249
|
+
props = _safe_get_properties(obj)
|
|
250
|
+
|
|
251
|
+
if isinstance(obj, (Group, NamedObject)):
|
|
252
|
+
if isinstance(obj, Group):
|
|
253
|
+
command_names = obj.get_active_command_names()
|
|
254
|
+
child_names = obj.get_active_child_names() + command_names
|
|
255
|
+
else:
|
|
256
|
+
command_names = obj.command_names
|
|
257
|
+
child_names = list(obj) + command_names
|
|
258
|
+
else:
|
|
259
|
+
if isinstance(obj, BaseCommand):
|
|
260
|
+
return _command_view(obj, props) if props["is_active"] else pn.pane.HTML("")
|
|
261
|
+
else:
|
|
262
|
+
return _param_view(obj, props) if props["is_active"] else pn.pane.HTML("")
|
|
263
|
+
|
|
264
|
+
sections: List[pn.viewable.Viewable] = []
|
|
265
|
+
|
|
266
|
+
for child_name in child_names:
|
|
267
|
+
# Build a lazy loader that only resolves the child on expand
|
|
268
|
+
def _loader(name=child_name, parent=obj, lvl=indent + 1):
|
|
269
|
+
try:
|
|
270
|
+
child_obj = getattr(parent, name)
|
|
271
|
+
except AttributeError:
|
|
272
|
+
child_obj = parent[name]
|
|
273
|
+
return _settings_view(child_obj, lvl)
|
|
274
|
+
|
|
275
|
+
# Each child gets its own one-item accordion (mirrors your ipywidgets UX)
|
|
276
|
+
if child_name in command_names:
|
|
277
|
+
display_name = f"⚡ {child_name}"
|
|
278
|
+
else:
|
|
279
|
+
display_name = child_name
|
|
280
|
+
sections.append(_lazy_section(display_name, _loader))
|
|
281
|
+
|
|
282
|
+
return pn.Column(
|
|
283
|
+
*(pn.Column(sec, margin=(5, 0)) for sec in sections),
|
|
284
|
+
sizing_mode="fixed",
|
|
285
|
+
margin=(10, 20),
|
|
286
|
+
align="start",
|
|
287
|
+
css_classes=["rounded-box"],
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def build_settings_view(settings_obj) -> pn.viewable.Viewable:
|
|
292
|
+
"""
|
|
293
|
+
Public API: pass any Fluent settings object.
|
|
294
|
+
Internally uses _root to render absolute paths and builds a lazy, web UI.
|
|
295
|
+
"""
|
|
296
|
+
return _settings_view(settings_obj)
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Copyright (C) 2021 - 2025 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
|
+
"""Utilities methods for ui rendering."""
|
|
24
|
+
|
|
25
|
+
from ansys.fluent.core.solver.flobject import (
|
|
26
|
+
BaseCommand,
|
|
27
|
+
Boolean,
|
|
28
|
+
Integer,
|
|
29
|
+
IntegerList,
|
|
30
|
+
NamedObject,
|
|
31
|
+
Real,
|
|
32
|
+
RealList,
|
|
33
|
+
String,
|
|
34
|
+
StringList,
|
|
35
|
+
)
|
|
36
|
+
from ansys.fluent.core.ui import in_jupyter
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _parse_path(settings_obj):
|
|
40
|
+
"""Convert a settings object path to a string representation
|
|
41
|
+
with proper indexing for NamedObject keys."""
|
|
42
|
+
local_obj = settings_obj._root
|
|
43
|
+
path_str = "<solver_session>.settings."
|
|
44
|
+
for path in settings_obj.path.replace("/", ".").replace("?", "").split("."):
|
|
45
|
+
py_path = path.replace("-", "_")
|
|
46
|
+
if not path:
|
|
47
|
+
break
|
|
48
|
+
if isinstance(local_obj, NamedObject):
|
|
49
|
+
try:
|
|
50
|
+
local_obj = local_obj[path]
|
|
51
|
+
path_str = path_str[:-1] + f"['{path}']" + "."
|
|
52
|
+
except KeyError:
|
|
53
|
+
local_obj = getattr(local_obj, py_path)
|
|
54
|
+
path_str += f"{py_path}."
|
|
55
|
+
else:
|
|
56
|
+
local_obj = getattr(local_obj, py_path)
|
|
57
|
+
path_str += f"{py_path}."
|
|
58
|
+
|
|
59
|
+
return path_str[:-1]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _safe_get_properties(settings_obj):
|
|
63
|
+
"""Fetch potentially expensive properties once."""
|
|
64
|
+
props = {}
|
|
65
|
+
try:
|
|
66
|
+
props["is_active"] = settings_obj.is_active()
|
|
67
|
+
except RuntimeError:
|
|
68
|
+
props["is_active"] = False
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
if isinstance(settings_obj, BaseCommand):
|
|
72
|
+
props["value"] = ""
|
|
73
|
+
else:
|
|
74
|
+
props["value"] = settings_obj() if props["is_active"] else ""
|
|
75
|
+
except RuntimeError:
|
|
76
|
+
props["value"] = ""
|
|
77
|
+
|
|
78
|
+
props["allowed_values"] = None
|
|
79
|
+
if hasattr(settings_obj, "allowed_values"):
|
|
80
|
+
try:
|
|
81
|
+
av = settings_obj.allowed_values()
|
|
82
|
+
props["allowed_values"] = list(av) if av else None
|
|
83
|
+
except RuntimeError:
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
props["path"] = getattr(settings_obj, "path", "")
|
|
87
|
+
props["python_name"] = getattr(settings_obj, "python_name", "")
|
|
88
|
+
props["obj_name"] = getattr(settings_obj, "obj_name", "")
|
|
89
|
+
props["parent"] = getattr(settings_obj, "parent", None)
|
|
90
|
+
return props
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _render_widget_from_props_generic(
|
|
94
|
+
settings_obj, label: str, props: dict, parent_widget
|
|
95
|
+
):
|
|
96
|
+
"""
|
|
97
|
+
Render a widget from type+props using either ipywidgets or Panel.
|
|
98
|
+
"""
|
|
99
|
+
if in_jupyter():
|
|
100
|
+
widget_map = {
|
|
101
|
+
"bool": lambda v: parent_widget.Checkbox(
|
|
102
|
+
value=v, description=label, indent=False
|
|
103
|
+
),
|
|
104
|
+
"int": lambda v: parent_widget.IntText(value=v, description=label),
|
|
105
|
+
"float": lambda v: parent_widget.FloatText(value=v, description=label),
|
|
106
|
+
"text": lambda v: parent_widget.Text(value=v, description=label),
|
|
107
|
+
"select": lambda opts, v: parent_widget.Dropdown(
|
|
108
|
+
options=opts, value=v, description=label
|
|
109
|
+
),
|
|
110
|
+
"multi": lambda opts, v: parent_widget.SelectMultiple(
|
|
111
|
+
options=opts, value=v, description=label
|
|
112
|
+
),
|
|
113
|
+
}
|
|
114
|
+
else:
|
|
115
|
+
widget_map = {
|
|
116
|
+
"bool": lambda v: parent_widget.Checkbox(name=label, value=v),
|
|
117
|
+
"int": lambda v: parent_widget.IntInput(name=label, value=v),
|
|
118
|
+
"float": lambda v: parent_widget.FloatInput(name=label, value=v),
|
|
119
|
+
"text": lambda v: parent_widget.TextInput(name=label, value=v),
|
|
120
|
+
"select": lambda opts, v: parent_widget.Select(
|
|
121
|
+
name=label, options=opts, value=v
|
|
122
|
+
),
|
|
123
|
+
"multi": lambda opts, v: parent_widget.MultiChoice(
|
|
124
|
+
name=label, options=opts, value=v
|
|
125
|
+
),
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
settings_val = props.get("value")
|
|
129
|
+
allowed = props.get("allowed_values")
|
|
130
|
+
|
|
131
|
+
try:
|
|
132
|
+
if isinstance(settings_obj, Boolean):
|
|
133
|
+
return widget_map["bool"](bool(settings_val))
|
|
134
|
+
elif isinstance(settings_obj, Integer):
|
|
135
|
+
return widget_map["int"](int(settings_val))
|
|
136
|
+
elif isinstance(settings_obj, Real):
|
|
137
|
+
return widget_map["float"](float(settings_val))
|
|
138
|
+
elif isinstance(settings_obj, String):
|
|
139
|
+
if allowed:
|
|
140
|
+
options = [str(v) for v in allowed]
|
|
141
|
+
val = str(settings_val)
|
|
142
|
+
if val not in options:
|
|
143
|
+
val = options[0]
|
|
144
|
+
return widget_map["select"](options, val)
|
|
145
|
+
else:
|
|
146
|
+
if settings_val is False:
|
|
147
|
+
settings_val = ""
|
|
148
|
+
return widget_map["text"](str(settings_val))
|
|
149
|
+
elif isinstance(settings_obj, StringList):
|
|
150
|
+
if allowed:
|
|
151
|
+
options = [str(v) for v in allowed]
|
|
152
|
+
current = [str(v) for v in (settings_val or []) if str(v) in options]
|
|
153
|
+
w = widget_map["multi"](options, current)
|
|
154
|
+
w._is_list_text = (str, False)
|
|
155
|
+
return w
|
|
156
|
+
else:
|
|
157
|
+
w = widget_map["text"](",".join(map(str, settings_val or [])))
|
|
158
|
+
w._is_list_text = (str, True)
|
|
159
|
+
return w
|
|
160
|
+
elif isinstance(settings_obj, IntegerList):
|
|
161
|
+
w = widget_map["text"](",".join(map(str, settings_val or [])))
|
|
162
|
+
w._is_list_text = (int, True)
|
|
163
|
+
return w
|
|
164
|
+
elif isinstance(settings_obj, RealList):
|
|
165
|
+
w = widget_map["text"](",".join(map(str, settings_val or [])))
|
|
166
|
+
w._is_list_text = (float, True)
|
|
167
|
+
return w
|
|
168
|
+
else:
|
|
169
|
+
if settings_val is False:
|
|
170
|
+
settings_val = ""
|
|
171
|
+
return widget_map["text"](str(settings_val))
|
|
172
|
+
except ValueError:
|
|
173
|
+
return widget_map["text"](str(settings_val))
|
|
@@ -34,6 +34,7 @@ from ansys.fluent.core.pyfluent_warnings import PyFluentDeprecationWarning
|
|
|
34
34
|
logger = logging.getLogger("pyfluent.general")
|
|
35
35
|
|
|
36
36
|
|
|
37
|
+
# TODO: Refactor 'all_deprecators' to remove boilerplate code from implementation
|
|
37
38
|
def all_deprecators(
|
|
38
39
|
deprecate_arg_mappings,
|
|
39
40
|
data_type_converter,
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
from concurrent import futures
|
|
26
26
|
import logging
|
|
27
27
|
import socket
|
|
28
|
+
import ssl
|
|
28
29
|
from typing import Any
|
|
29
30
|
import urllib.request
|
|
30
31
|
|
|
@@ -130,12 +131,20 @@ def check_url_exists(url: str) -> bool:
|
|
|
130
131
|
-------
|
|
131
132
|
bool
|
|
132
133
|
True if the URL exists, False otherwise
|
|
134
|
+
|
|
135
|
+
Raises
|
|
136
|
+
------
|
|
137
|
+
ssl.SSLError
|
|
138
|
+
If there is an SSL error while checking the URL
|
|
133
139
|
"""
|
|
134
140
|
try:
|
|
135
141
|
with urllib.request.urlopen(url) as response:
|
|
136
142
|
return response.status == 200
|
|
137
|
-
except
|
|
138
|
-
|
|
143
|
+
except urllib.error.URLError as ex:
|
|
144
|
+
if ex.__context__ and isinstance(ex.__context__, ssl.SSLError):
|
|
145
|
+
raise ex.__context__
|
|
146
|
+
else:
|
|
147
|
+
return False
|
|
139
148
|
|
|
140
149
|
|
|
141
150
|
def get_url_content(url: str) -> str:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: ansys-fluent-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.36.dev0
|
|
4
4
|
Summary: PyFluent provides Pythonic access to Ansys Fluent.
|
|
5
5
|
Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
|
|
6
6
|
Maintainer-email: "ANSYS, Inc." <pyansys.core@ansys.com>
|
|
@@ -10,10 +10,11 @@ Classifier: Development Status :: 4 - Beta
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
|
+
License-File: LICENSE
|
|
13
14
|
Requires-Dist: ansys-api-fluent>=0.3.36
|
|
14
15
|
Requires-Dist: ansys-platform-instancemanagement~=1.1
|
|
15
16
|
Requires-Dist: ansys-tools-filetransfer>=0.1,<0.3
|
|
16
|
-
Requires-Dist: ansys-units>=0.
|
|
17
|
+
Requires-Dist: ansys-units>=0.8.1,<1.0
|
|
17
18
|
Requires-Dist: defusedxml>=0.7.1
|
|
18
19
|
Requires-Dist: deprecated>=1.2.18
|
|
19
20
|
Requires-Dist: docker>=7.1.0
|
|
@@ -28,8 +29,8 @@ Requires-Dist: pyyaml>=6.0
|
|
|
28
29
|
Requires-Dist: Sphinx==8.1.3 ; extra == "docs"
|
|
29
30
|
Requires-Dist: jupyter_sphinx==0.5.3 ; extra == "docs"
|
|
30
31
|
Requires-Dist: numpydoc==1.9.0 ; extra == "docs"
|
|
31
|
-
Requires-Dist: matplotlib==3.10.
|
|
32
|
-
Requires-Dist: ansys-sphinx-theme==1.
|
|
32
|
+
Requires-Dist: matplotlib==3.10.6 ; extra == "docs"
|
|
33
|
+
Requires-Dist: ansys-sphinx-theme==1.6.1 ; extra == "docs"
|
|
33
34
|
Requires-Dist: pypandoc==1.15 ; extra == "docs"
|
|
34
35
|
Requires-Dist: pytest-sphinx==0.6.3 ; extra == "docs"
|
|
35
36
|
Requires-Dist: sphinx-autobuild==2024.10.3 ; extra == "docs"
|
|
@@ -38,28 +39,33 @@ Requires-Dist: sphinx-copybutton==0.5.2 ; extra == "docs"
|
|
|
38
39
|
Requires-Dist: sphinx-gallery==0.19.0 ; extra == "docs"
|
|
39
40
|
Requires-Dist: sphinx-notfound-page==1.1.0 ; extra == "docs"
|
|
40
41
|
Requires-Dist: sphinxcontrib-websupport==2.0.0 ; extra == "docs"
|
|
42
|
+
Requires-Dist: sphinx_design==0.6.1 ; extra == "docs"
|
|
41
43
|
Requires-Dist: sphinxemoji==0.3.1 ; extra == "docs"
|
|
42
44
|
Requires-Dist: sphinx-toggleprompt==0.6.0 ; extra == "docs"
|
|
43
45
|
Requires-Dist: autodocsumm==0.2.14 ; extra == "docs"
|
|
44
|
-
Requires-Dist: beautifulsoup4==4.
|
|
46
|
+
Requires-Dist: beautifulsoup4==4.14.2 ; extra == "docs"
|
|
45
47
|
Requires-Dist: openpyxl>=3.1.5 ; extra == "docs"
|
|
46
48
|
Requires-Dist: plotly>=5.22.0 ; extra == "docs"
|
|
47
49
|
Requires-Dist: python-pptx>=0.6.23 ; extra == "docs"
|
|
48
|
-
Requires-Dist: quarto-cli==1.
|
|
50
|
+
Requires-Dist: quarto-cli==1.8.25 ; extra == "docs"
|
|
49
51
|
Requires-Dist: pdf2image==1.17.0 ; extra == "docs"
|
|
50
52
|
Requires-Dist: seaborn>=0.13.2 ; extra == "docs"
|
|
51
53
|
Requires-Dist: h5py==3.14.0 ; extra == "reader"
|
|
52
|
-
Requires-Dist: pytest==8.4.
|
|
53
|
-
Requires-Dist: pytest-cov==
|
|
54
|
-
Requires-Dist: pytest-mock==3.
|
|
55
|
-
Requires-Dist: pytest-xdist==3.
|
|
56
|
-
Requires-Dist: pyfakefs==5.9.
|
|
54
|
+
Requires-Dist: pytest==8.4.2 ; extra == "tests"
|
|
55
|
+
Requires-Dist: pytest-cov==7.0.0 ; extra == "tests"
|
|
56
|
+
Requires-Dist: pytest-mock==3.15.1 ; extra == "tests"
|
|
57
|
+
Requires-Dist: pytest-xdist==3.8.0 ; extra == "tests"
|
|
58
|
+
Requires-Dist: pyfakefs==5.9.3 ; extra == "tests"
|
|
59
|
+
Requires-Dist: panel ; extra == "ui"
|
|
60
|
+
Requires-Dist: ipywidgets ; extra == "ui-jupyter"
|
|
57
61
|
Project-URL: Documentation, https://fluent.docs.pyansys.com/
|
|
58
62
|
Project-URL: Source, https://github.com/ansys/pyfluent
|
|
59
63
|
Project-URL: Tracker, https://github.com/ansys/pyfluent/issues
|
|
60
64
|
Provides-Extra: docs
|
|
61
65
|
Provides-Extra: reader
|
|
62
66
|
Provides-Extra: tests
|
|
67
|
+
Provides-Extra: ui
|
|
68
|
+
Provides-Extra: ui-jupyter
|
|
63
69
|
|
|
64
70
|
PyFluent
|
|
65
71
|
========
|
|
@@ -77,7 +83,7 @@ PyFluent
|
|
|
77
83
|
:target: https://pypi.org/project/ansys-fluent-core
|
|
78
84
|
:alt: PyPI
|
|
79
85
|
|
|
80
|
-
.. |GH-CI| image:: https://github.com/ansys/pyfluent/actions/workflows/ci.yml/badge.svg
|
|
86
|
+
.. |GH-CI| image:: https://github.com/ansys/pyfluent/actions/workflows/ci.yml/badge.svg?branch=main
|
|
81
87
|
:target: https://github.com/ansys/pyfluent/actions/workflows/ci.yml
|
|
82
88
|
:alt: GH-CI
|
|
83
89
|
|
|
@@ -188,21 +194,22 @@ To launch Fluent from Python, use the ``launch_fluent`` function:
|
|
|
188
194
|
|
|
189
195
|
Basic usage
|
|
190
196
|
~~~~~~~~~~~
|
|
191
|
-
|
|
197
|
+
The ``solver_session`` interface provides a convenient way to launch and
|
|
198
|
+
interact with Fluent.
|
|
192
199
|
|
|
193
200
|
.. code:: python
|
|
194
201
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
solver_session.
|
|
198
|
-
|
|
202
|
+
import ansys.fluent.core as pyfluent
|
|
203
|
+
|
|
204
|
+
solver_session = pyfluent.launch_fluent()
|
|
205
|
+
|
|
206
|
+
For more information on using the ``solver_session`` interface, see the
|
|
207
|
+
`PyFluent documentation <https://fluent.docs.pyansys.com/version/stable/>`_.
|
|
199
208
|
|
|
200
|
-
|
|
209
|
+
For postprocessing and visualization, you can also install:
|
|
201
210
|
|
|
202
|
-
- `PyFluent Parametric <https://parametric.fluent.docs.pyansys.com/>`_, which provides
|
|
203
|
-
access to Fluent's parametric workflows.
|
|
204
211
|
- `PyFluent Visualization <https://visualization.fluent.docs.pyansys.com/>`_, which
|
|
205
|
-
|
|
212
|
+
enables analysis and plotting through the `pyvista <https://docs.pyvista.org/>`_
|
|
206
213
|
and `matplotlib <https://matplotlib.org/>`_ packages.
|
|
207
214
|
|
|
208
215
|
License and acknowledgments
|