ansys-fluent-core 0.32.2__py3-none-any.whl → 0.33.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (78) hide show
  1. ansys/fluent/core/__init__.py +11 -4
  2. ansys/fluent/core/codegen/builtin_settingsgen.py +16 -8
  3. ansys/fluent/core/codegen/datamodelgen.py +2 -2
  4. ansys/fluent/core/codegen/print_fluent_version.py +4 -4
  5. ansys/fluent/core/codegen/settingsgen.py +1 -2
  6. ansys/fluent/core/exceptions.py +0 -1
  7. ansys/fluent/core/file_session.py +9 -9
  8. ansys/fluent/core/filereader/case_file.py +2 -2
  9. ansys/fluent/core/fluent_connection.py +5 -5
  10. ansys/fluent/core/generated/api_tree/api_objects.json +1 -1
  11. ansys/fluent/core/generated/datamodel_231/flicing.py +55 -55
  12. ansys/fluent/core/generated/datamodel_231/meshing.py +171 -171
  13. ansys/fluent/core/generated/datamodel_232/flicing.py +30 -30
  14. ansys/fluent/core/generated/datamodel_232/meshing.py +218 -218
  15. ansys/fluent/core/generated/datamodel_241/flicing.py +45 -45
  16. ansys/fluent/core/generated/datamodel_241/meshing.py +295 -295
  17. ansys/fluent/core/generated/datamodel_242/flicing.py +40 -40
  18. ansys/fluent/core/generated/datamodel_242/meshing.py +299 -299
  19. ansys/fluent/core/generated/datamodel_242/part_management.py +3 -3
  20. ansys/fluent/core/generated/datamodel_251/flicing.py +45 -45
  21. ansys/fluent/core/generated/datamodel_251/meshing.py +294 -294
  22. ansys/fluent/core/generated/datamodel_251/part_management.py +6 -6
  23. ansys/fluent/core/generated/datamodel_252/flicing.py +50 -50
  24. ansys/fluent/core/generated/datamodel_252/meshing.py +431 -431
  25. ansys/fluent/core/generated/datamodel_252/part_management.py +5 -5
  26. ansys/fluent/core/generated/datamodel_261/flicing.py +55 -55
  27. ansys/fluent/core/generated/datamodel_261/meshing.py +447 -441
  28. ansys/fluent/core/generated/datamodel_261/part_management.py +5 -5
  29. ansys/fluent/core/generated/datamodel_261/solver_workflow.py +7 -0
  30. ansys/fluent/core/generated/fluent_version_261.py +3 -3
  31. ansys/fluent/core/generated/solver/settings_252.py +55 -55
  32. ansys/fluent/core/generated/solver/settings_261.py +2134 -3644
  33. ansys/fluent/core/generated/solver/settings_261.pyi +3391 -6013
  34. ansys/fluent/core/generated/solver/settings_builtin.py +57 -1
  35. ansys/fluent/core/generated/solver/settings_builtin.pyi +79 -0
  36. ansys/fluent/core/generated/solver/tui_261.py +78 -228
  37. ansys/fluent/core/launcher/container_launcher.py +7 -9
  38. ansys/fluent/core/launcher/fluent_container.py +106 -75
  39. ansys/fluent/core/launcher/launch_options.py +22 -1
  40. ansys/fluent/core/launcher/launcher.py +5 -4
  41. ansys/fluent/core/pyfluent_warnings.py +13 -0
  42. ansys/fluent/core/search.py +170 -83
  43. ansys/fluent/core/services/app_utilities.py +52 -32
  44. ansys/fluent/core/services/datamodel_se.py +6 -3
  45. ansys/fluent/core/services/scheme_eval.py +2 -0
  46. ansys/fluent/core/services/solution_variables.py +64 -49
  47. ansys/fluent/core/session.py +36 -30
  48. ansys/fluent/core/session_base_meshing.py +2 -24
  49. ansys/fluent/core/session_shared.py +5 -2
  50. ansys/fluent/core/session_solver.py +15 -9
  51. ansys/fluent/core/solver/__init__.py +1 -1
  52. ansys/fluent/core/solver/flobject.py +55 -38
  53. ansys/fluent/core/solver/settings_builtin_bases.py +14 -7
  54. ansys/fluent/core/solver/settings_builtin_data.py +121 -540
  55. ansys/fluent/core/utils/context_managers.py +0 -17
  56. ansys/fluent/core/utils/fluent_version.py +173 -0
  57. {ansys_fluent_core-0.32.2.dist-info → ansys_fluent_core-0.33.0.dist-info}/METADATA +9 -9
  58. {ansys_fluent_core-0.32.2.dist-info → ansys_fluent_core-0.33.0.dist-info}/RECORD +60 -78
  59. {ansys_fluent_core-0.32.2.dist-info → ansys_fluent_core-0.33.0.dist-info}/WHEEL +1 -1
  60. ansys/fluent/core/generated/datamodel_222/meshing.py +0 -6332
  61. ansys/fluent/core/generated/datamodel_222/part_management.py +0 -2072
  62. ansys/fluent/core/generated/datamodel_222/pm_file_management.py +0 -290
  63. ansys/fluent/core/generated/datamodel_222/preferences.py +0 -2449
  64. ansys/fluent/core/generated/datamodel_222/workflow.py +0 -651
  65. ansys/fluent/core/generated/fluent_version_222.py +0 -5
  66. ansys/fluent/core/generated/meshing/tui_222.py +0 -9649
  67. ansys/fluent/core/generated/solver/settings_222.py +0 -29473
  68. ansys/fluent/core/generated/solver/settings_222.pyi +0 -19590
  69. ansys/fluent/core/generated/solver/tui_222.py +0 -43451
  70. ansys/fluent/core/post_objects/__init__.py +0 -21
  71. ansys/fluent/core/post_objects/check_in_notebook.py +0 -35
  72. ansys/fluent/core/post_objects/meta.py +0 -926
  73. ansys/fluent/core/post_objects/post_helper.py +0 -178
  74. ansys/fluent/core/post_objects/post_object_definitions.py +0 -693
  75. ansys/fluent/core/post_objects/post_objects_container.py +0 -248
  76. ansys/fluent/core/post_objects/singleton_meta.py +0 -42
  77. ansys/fluent/core/post_objects/timing_decorator.py +0 -38
  78. {ansys_fluent_core-0.32.2.dist-info → ansys_fluent_core-0.33.0.dist-info/licenses}/LICENSE +0 -0
@@ -74,6 +74,7 @@ config_dict =
74
74
  import logging
75
75
  import os
76
76
  from pathlib import Path, PurePosixPath
77
+ from pprint import pformat
77
78
  import tempfile
78
79
  from typing import Any, List
79
80
 
@@ -118,6 +119,20 @@ class LicenseServerNotSpecified(KeyError):
118
119
  )
119
120
 
120
121
 
122
+ def dict_to_str(dict: dict) -> str:
123
+ """Converts the dict to string while hiding the 'environment' argument from the dictionary,
124
+ if the environment variable 'PYFLUENT_HIDE_LOG_SECRETS' is '1'.
125
+ This is useful for logging purposes, to avoid printing sensitive information such as license server details.
126
+ """
127
+
128
+ if "environment" in dict and os.getenv("PYFLUENT_HIDE_LOG_SECRETS") == "1":
129
+ modified_dict = dict.copy()
130
+ modified_dict.pop("environment")
131
+ return pformat(modified_dict)
132
+ else:
133
+ return pformat(dict)
134
+
135
+
121
136
  @all_deprecators(
122
137
  deprecate_arg_mappings=[
123
138
  {
@@ -158,9 +173,12 @@ def configure_container_dict(
158
173
  args : List[str]
159
174
  List of Fluent launch arguments.
160
175
  mount_source : str | Path, optional
161
- Existing path in the host operating system that will be mounted to ``mount_target``.
176
+ Path on the host system to mount into the container. This directory will serve as the working directory
177
+ for the Fluent process inside the container. If not specified, PyFluent's current working directory will
178
+ be used.
162
179
  mount_target : str | Path, optional
163
- Path inside the container where ``mount_source`` will be mounted to.
180
+ Path inside the container where ``mount_source`` will be mounted. This will be the working directory path
181
+ visible to the Fluent process running inside the container.
164
182
  timeout : int, optional
165
183
  Time limit for the Fluent container to start, in seconds. By default, 30 seconds.
166
184
  port : int, optional
@@ -213,17 +231,15 @@ def configure_container_dict(
213
231
  See also :func:`start_fluent_container`.
214
232
  """
215
233
 
216
- if (
217
- container_dict
218
- and "environment" in container_dict
219
- and os.getenv("PYFLUENT_HIDE_LOG_SECRETS") == "1"
220
- ):
221
- container_dict_h = container_dict.copy()
222
- container_dict_h.pop("environment")
223
- logger.debug(f"container_dict before processing: {container_dict_h}")
224
- del container_dict_h
225
- else:
226
- logger.debug(f"container_dict before processing: {container_dict}")
234
+ logger.debug(f"container_dict before processing:\n{dict_to_str(container_dict)}")
235
+
236
+ # Starting with 'mount_source' because it is not tied to the 'working_dir'.
237
+ # The intended 'mount_source' logic is as follows, if it is not directly specified:
238
+ # 1. If 'file_transfer_service' is provided, use its 'mount_source'.
239
+ # 2. Try to use the environment variable 'PYFLUENT_CONTAINER_MOUNT_SOURCE', if it is set.
240
+ # 3. Use the value from 'pyfluent.CONTAINER_MOUNT_SOURCE', if it is set.
241
+ # 4. If 'volumes' is specified in 'container_dict', try to infer the value from it.
242
+ # 5. Finally, use the current working directory, which is always available.
227
243
 
228
244
  if not mount_source:
229
245
  if file_transfer_service:
@@ -231,53 +247,69 @@ def configure_container_dict(
231
247
  else:
232
248
  mount_source = os.getenv(
233
249
  "PYFLUENT_CONTAINER_MOUNT_SOURCE",
234
- pyfluent.CONTAINER_MOUNT_SOURCE or os.getcwd(),
250
+ pyfluent.CONTAINER_MOUNT_SOURCE,
235
251
  )
236
252
 
237
- elif "volumes" in container_dict:
238
- logger.warning(
239
- "'volumes' keyword specified in 'container_dict', but "
240
- "it is going to be overwritten by specified 'mount_source'."
241
- )
242
- container_dict.pop("volumes")
253
+ if "volumes" in container_dict:
254
+ if len(container_dict["volumes"]) != 1:
255
+ logger.warning(
256
+ "Multiple volumes being mounted in the Docker container, "
257
+ "Assuming the first mount is the working directory for Fluent."
258
+ )
259
+ volumes_string = container_dict["volumes"][0]
260
+ if mount_source:
261
+ logger.warning(
262
+ "'volumes' keyword specified in 'container_dict', but "
263
+ "it is going to be overwritten by specified 'mount_source'."
264
+ )
265
+ else:
266
+ mount_source = volumes_string.split(":")[0]
267
+ logger.debug(f"mount_source: {mount_source}")
268
+ inferred_mount_target = volumes_string.split(":")[1]
269
+ logger.debug(f"inferred_mount_target: {inferred_mount_target}")
270
+
271
+ if not mount_source:
272
+ logger.debug("No container 'mount_source' specified, using default value.")
273
+ mount_source = os.getcwd()
243
274
 
244
- if not os.path.exists(mount_source):
245
- os.makedirs(mount_source)
275
+ # The intended 'mount_target' logic is as follows, if it is not directly specified:
276
+ # 1. If 'working_dir' is specified in 'container_dict', use it as 'mount_target'.
277
+ # 2. Use the environment variable 'PYFLUENT_CONTAINER_MOUNT_TARGET', if it is set.
278
+ # 3. Try to infer the value from the 'volumes' keyword in 'container_dict', if available.
279
+ # 4. Finally, use the value from 'pyfluent.CONTAINER_MOUNT_TARGET', which is always set.
246
280
 
247
281
  if not mount_target:
248
- mount_target = os.getenv(
249
- "PYFLUENT_CONTAINER_MOUNT_TARGET", pyfluent.CONTAINER_MOUNT_TARGET
250
- )
251
- elif "volumes" in container_dict:
252
- logger.warning(
253
- "'volumes' keyword specified in 'container_dict', but "
254
- "it is going to be overwritten by specified 'mount_target'."
255
- )
256
- container_dict.pop("volumes")
282
+ if "working_dir" in container_dict:
283
+ mount_target = container_dict["working_dir"]
284
+ else:
285
+ mount_target = os.getenv("PYFLUENT_CONTAINER_MOUNT_TARGET")
286
+
287
+ if "working_dir" in container_dict and mount_target:
288
+ # working_dir will be set later to the final value of mount_target
289
+ container_dict.pop("working_dir")
290
+
291
+ if not mount_target and "volumes" in container_dict:
292
+ mount_target = inferred_mount_target
293
+
294
+ if not mount_target:
295
+ logger.debug("No container 'mount_target' specified, using default value.")
296
+ mount_target = pyfluent.CONTAINER_MOUNT_TARGET
257
297
 
258
298
  if "volumes" not in container_dict:
259
299
  container_dict.update(volumes=[f"{mount_source}:{mount_target}"])
260
300
  else:
261
- logger.debug(f"container_dict['volumes']: {container_dict['volumes']}")
262
- if len(container_dict["volumes"]) != 1:
263
- logger.warning(
264
- "Multiple volumes being mounted in the Docker container, "
265
- "using the first mount as the working directory for Fluent."
266
- )
267
- volumes_string = container_dict["volumes"][0]
268
- mount_target = ""
269
- for c in reversed(volumes_string):
270
- if c == ":":
271
- break
272
- else:
273
- mount_target += c
274
- mount_target = mount_target[::-1]
275
- mount_source = volumes_string.replace(":" + mount_target, "")
276
- logger.debug(f"mount_source: {mount_source}")
277
- logger.debug(f"mount_target: {mount_target}")
301
+ container_dict["volumes"][0] = f"{mount_source}:{mount_target}"
302
+
278
303
  logger.warning(
279
- f"Starting Fluent container mounted to {mount_source}, with this path available as {mount_target} for the Fluent session running inside the container."
304
+ f"Configuring Fluent container to mount to {mount_source}, "
305
+ f"with this path available as {mount_target} for the Fluent session running inside the container."
280
306
  )
307
+
308
+ if "working_dir" not in container_dict:
309
+ container_dict.update(
310
+ working_dir=mount_target,
311
+ )
312
+
281
313
  port_mapping = {port: port} if port else {}
282
314
  if not port_mapping and "ports" in container_dict:
283
315
  # take the specified 'port', OR the first port value from the specified 'ports', for Fluent to use
@@ -315,11 +347,7 @@ def configure_container_dict(
315
347
  labels={"test_name": test_name},
316
348
  )
317
349
 
318
- if "working_dir" not in container_dict:
319
- container_dict.update(
320
- working_dir=mount_target,
321
- )
322
-
350
+ # Find the server info file name from the command line arguments
323
351
  if "command" in container_dict:
324
352
  for v in container_dict["command"]:
325
353
  if v.startswith("-sifile="):
@@ -343,6 +371,20 @@ def configure_container_dict(
343
371
  os.close(fd)
344
372
  container_server_info_file = PurePosixPath(mount_target) / Path(sifile).name
345
373
 
374
+ logger.debug(
375
+ f"Using server info file '{container_server_info_file}' for Fluent container."
376
+ )
377
+
378
+ # If the 'command' had already been specified in the 'container_dict',
379
+ # maintain other 'command' arguments but update the '-sifile' argument,
380
+ # as the 'mount_target' or 'working_dir' may have changed.
381
+ if "command" in container_dict:
382
+ for i, item in enumerate(container_dict["command"]):
383
+ if item.startswith("-sifile="):
384
+ container_dict["command"][i] = f"-sifile={container_server_info_file}"
385
+ else:
386
+ container_dict["command"] = args + [f"-sifile={container_server_info_file}"]
387
+
346
388
  if not fluent_image:
347
389
  if not image_tag:
348
390
  image_tag = os.getenv(
@@ -384,16 +426,13 @@ def configure_container_dict(
384
426
  container_dict["environment"] = {}
385
427
  container_dict["environment"]["FLUENT_LAUNCHED_FROM_PYFLUENT"] = "1"
386
428
 
387
- fluent_commands = [f"-sifile={container_server_info_file}"] + args
388
-
389
- container_dict_default = {}
390
- container_dict_default.update(
391
- command=fluent_commands,
429
+ container_dict_base = {}
430
+ container_dict_base.update(
392
431
  detach=True,
393
432
  auto_remove=True,
394
433
  )
395
434
 
396
- for k, v in container_dict_default.items():
435
+ for k, v in container_dict_base.items():
397
436
  if k not in container_dict:
398
437
  container_dict[k] = v
399
438
 
@@ -404,6 +443,13 @@ def configure_container_dict(
404
443
  container_dict["mount_source"] = mount_source
405
444
  container_dict["mount_target"] = mount_target
406
445
 
446
+ logger.debug(
447
+ f"Fluent container timeout: {timeout}, container_grpc_port: {container_grpc_port}, "
448
+ f"host_server_info_file: '{host_server_info_file}', "
449
+ f"remove_server_info_file: {remove_server_info_file}"
450
+ )
451
+ logger.debug(f"container_dict after processing:\n{dict_to_str(container_dict)}")
452
+
407
453
  return (
408
454
  container_dict,
409
455
  timeout,
@@ -458,21 +504,6 @@ def start_fluent_container(
458
504
  remove_server_info_file,
459
505
  ) = container_vars
460
506
 
461
- if os.getenv("PYFLUENT_HIDE_LOG_SECRETS") != "1":
462
- logger.debug(f"container_vars: {container_vars}")
463
- else:
464
- config_dict_h = config_dict.copy()
465
- config_dict_h.pop("environment")
466
- container_vars_tmp = (
467
- config_dict_h,
468
- timeout,
469
- port,
470
- host_server_info_file,
471
- remove_server_info_file,
472
- )
473
- logger.debug(f"container_vars: {container_vars_tmp}")
474
- del container_vars_tmp
475
-
476
507
  try:
477
508
  if is_compose():
478
509
  config_dict["fluent_port"] = port
@@ -24,11 +24,13 @@
24
24
 
25
25
  from enum import Enum
26
26
  import os
27
+ import warnings
27
28
 
28
29
  from ansys.fluent.core.exceptions import DisallowedValuesError
29
30
  from ansys.fluent.core.fluent_connection import FluentConnection
30
31
  import ansys.fluent.core.launcher.error_handler as exceptions
31
32
  from ansys.fluent.core.launcher.launcher_utils import is_windows
33
+ from ansys.fluent.core.pyfluent_warnings import PyFluentUserWarning
32
34
  from ansys.fluent.core.session_meshing import Meshing
33
35
  from ansys.fluent.core.session_pure_meshing import PureMeshing
34
36
  from ansys.fluent.core.session_solver import Solver
@@ -280,11 +282,22 @@ def _get_fluent_launch_mode(start_container, container_dict, scheduler_options):
280
282
  return fluent_launch_mode
281
283
 
282
284
 
285
+ def _should_add_driver_null(ui_mode: UIMode | None = None) -> bool:
286
+ return ui_mode not in {UIMode.GUI, UIMode.HIDDEN_GUI}
287
+
288
+
283
289
  def _get_graphics_driver(
284
290
  graphics_driver: (
285
291
  FluentWindowsGraphicsDriver | FluentLinuxGraphicsDriver | str | None
286
292
  ) = None,
293
+ ui_mode: UIMode | None = None,
287
294
  ):
295
+ ui_mode_ = UIMode(ui_mode)
296
+ if graphics_driver is not None and ui_mode_ not in {UIMode.GUI, UIMode.HIDDEN_GUI}:
297
+ warnings.warn(
298
+ "User-specified value for graphics driver is ignored while launching Fluent without GUI or without graphics.",
299
+ PyFluentUserWarning,
300
+ )
288
301
  if isinstance(
289
302
  graphics_driver, (FluentWindowsGraphicsDriver, FluentLinuxGraphicsDriver)
290
303
  ):
@@ -294,6 +307,12 @@ def _get_graphics_driver(
294
307
  if is_windows()
295
308
  else FluentLinuxGraphicsDriver(graphics_driver)
296
309
  )
310
+ if _should_add_driver_null(ui_mode_):
311
+ return (
312
+ FluentWindowsGraphicsDriver.NULL
313
+ if is_windows()
314
+ else FluentLinuxGraphicsDriver.NULL
315
+ )
297
316
  return graphics_driver
298
317
 
299
318
 
@@ -361,7 +380,9 @@ def _validate_gpu(gpu: bool | list, dimension: int):
361
380
 
362
381
  def _get_argvals_and_session(argvals):
363
382
  _validate_gpu(argvals["gpu"], argvals["dimension"])
364
- argvals["graphics_driver"] = _get_graphics_driver(argvals["graphics_driver"])
383
+ argvals["graphics_driver"] = _get_graphics_driver(
384
+ argvals["graphics_driver"], argvals["ui_mode"]
385
+ )
365
386
  argvals["mode"] = FluentMode(argvals["mode"])
366
387
  del argvals["self"]
367
388
  new_session = argvals["mode"].get_fluent_value()
@@ -263,10 +263,11 @@ def launch_fluent(
263
263
  made by the user in the current Fluent solver session have been applied in the background Fluent
264
264
  solver session. This is all orchestrated by PyFluent and requires no special usage.
265
265
  This parameter is used only when ``case_file_name`` is provided. The default is ``False``.
266
- mode : str, optional
267
- Launch mode of Fluent to point to a specific session type.
268
- The default value is ``None``. Options are ``"meshing"``,
269
- ``"pure-meshing"`` and ``"solver"``.
266
+ mode : FluentMode or str or None, optional
267
+ Launch mode of Fluent to point to a specific session type. Can be a
268
+ ``FluentMode`` enum member or a string. The default value is ``None``.
269
+ Valid string options include ``"meshing"``, ``"pure-meshing"``, and
270
+ ``"solver"``.
270
271
  py : bool, optional
271
272
  If True, Fluent will run in Python mode. Default is None.
272
273
  gpu : bool or list, optional
@@ -38,6 +38,19 @@ class PyFluentUserWarning(UserWarning):
38
38
  pass
39
39
 
40
40
 
41
+ def warning_for_fluent_dev_version(version):
42
+ """Provides warning if Fluent develop branch is used."""
43
+ from ansys.fluent.core import FLUENT_RELEASE_VERSION, FluentVersion
44
+
45
+ if FluentVersion(version) > FluentVersion(FLUENT_RELEASE_VERSION):
46
+ warnings.warn(
47
+ "⚠️ Warning: You are using PyFluent with an unreleased or development version of Fluent.\n"
48
+ "Compatibility is not guaranteed, and unexpected behavior may occur. Please use a released "
49
+ "version of Fluent that is officially supported by this version of PyFluent.",
50
+ PyFluentUserWarning,
51
+ )
52
+
53
+
41
54
  class WarningControl:
42
55
  """Class to control warnings in PyFluent."""
43
56