ansys-fluent-core 0.28.dev0__py3-none-any.whl → 0.28.2__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 (63) hide show
  1. ansys/fluent/core/__init__.py +15 -16
  2. ansys/fluent/core/_version.py +1 -1
  3. ansys/fluent/core/codegen/allapigen.py +0 -3
  4. ansys/fluent/core/codegen/builtin_settingsgen.py +5 -20
  5. ansys/fluent/core/codegen/print_fluent_version.py +9 -14
  6. ansys/fluent/core/codegen/walk_api.py +57 -0
  7. ansys/fluent/core/fluent_connection.py +26 -22
  8. ansys/fluent/core/generated/api_tree/api_objects.json +1 -1
  9. ansys/fluent/core/generated/datamodel_252/meshing.py +21 -0
  10. ansys/fluent/core/generated/datamodel_252/preferences.py +14 -0
  11. ansys/fluent/core/generated/fluent_version_252.py +3 -3
  12. ansys/fluent/core/generated/meshing/tui_252.py +1451 -1396
  13. ansys/fluent/core/generated/solver/settings_252.py +9300 -6625
  14. ansys/fluent/core/generated/solver/settings_252.pyi +6625 -5423
  15. ansys/fluent/core/generated/solver/tui_252.py +5898 -5057
  16. ansys/fluent/core/journaling.py +4 -4
  17. ansys/fluent/core/launcher/fluent_container.py +31 -7
  18. ansys/fluent/core/launcher/launcher.py +3 -2
  19. ansys/fluent/core/launcher/launcher_utils.py +9 -0
  20. ansys/fluent/core/launcher/process_launch_string.py +8 -6
  21. ansys/fluent/core/launcher/pyfluent_enums.py +6 -3
  22. ansys/fluent/core/launcher/server_info.py +25 -2
  23. ansys/fluent/core/launcher/slurm_launcher.py +6 -3
  24. ansys/fluent/core/launcher/standalone_launcher.py +11 -9
  25. ansys/fluent/core/post_objects/post_helper.py +16 -10
  26. ansys/fluent/core/services/__init__.py +2 -0
  27. ansys/fluent/core/services/api_upgrade.py +11 -9
  28. ansys/fluent/core/services/app_utilities.py +408 -0
  29. ansys/fluent/core/services/datamodel_se.py +172 -58
  30. ansys/fluent/core/services/datamodel_tui.py +5 -2
  31. ansys/fluent/core/services/field_data.py +1 -0
  32. ansys/fluent/core/services/reduction.py +2 -0
  33. ansys/fluent/core/services/settings.py +5 -2
  34. ansys/fluent/core/session.py +27 -4
  35. ansys/fluent/core/session_pure_meshing.py +1 -1
  36. ansys/fluent/core/session_solver.py +0 -1
  37. ansys/fluent/core/solver/__init__.py +6 -0
  38. ansys/fluent/core/solver/flobject.py +15 -27
  39. ansys/fluent/core/solver/function/reduction.py +3 -0
  40. ansys/fluent/core/solver/settings_builtin_data.py +1 -1
  41. ansys/fluent/core/streaming_services/datamodel_event_streaming.py +13 -13
  42. ansys/fluent/core/streaming_services/events_streaming.py +336 -52
  43. ansys/fluent/tests/conftest.py +30 -0
  44. ansys/fluent/tests/test_builtin_settings.py +1 -1
  45. ansys/fluent/tests/test_codegen.py +0 -410
  46. ansys/fluent/tests/test_datamodel_api.py +429 -0
  47. ansys/fluent/tests/test_datamodel_service.py +64 -64
  48. ansys/fluent/tests/test_events_manager.py +24 -6
  49. ansys/fluent/tests/test_field_data.py +32 -0
  50. ansys/fluent/tests/test_launcher.py +30 -2
  51. ansys/fluent/tests/test_mapped_api.py +766 -0
  52. ansys/fluent/tests/test_reduction.py +30 -0
  53. ansys/fluent/tests/test_session.py +16 -1
  54. ansys/fluent/tests/test_settings_api.py +21 -0
  55. ansys/fluent/tests/test_solution_variables.py +27 -0
  56. ansys/fluent/tests/util/__init__.py +36 -0
  57. {ansys_fluent_core-0.28.dev0.dist-info → ansys_fluent_core-0.28.2.dist-info}/METADATA +4 -3
  58. {ansys_fluent_core-0.28.dev0.dist-info → ansys_fluent_core-0.28.2.dist-info}/RECORD +61 -58
  59. {ansys_fluent_core-0.28.dev0.dist-info → ansys_fluent_core-0.28.2.dist-info}/WHEEL +1 -1
  60. ansys/fluent/core/codegen/settingsgen_old.py +0 -535
  61. ansys/fluent/tests/fluent/test_version/test.py +0 -2
  62. {ansys_fluent_core-0.28.dev0.dist-info → ansys_fluent_core-0.28.2.dist-info}/AUTHORS +0 -0
  63. {ansys_fluent_core-0.28.dev0.dist-info → ansys_fluent_core-0.28.2.dist-info}/LICENSE +0 -0
@@ -1,5 +1,6 @@
1
1
  """Module for events management."""
2
2
 
3
+ from dataclasses import dataclass, field, fields
3
4
  from enum import Enum
4
5
  from functools import partial
5
6
  import inspect
@@ -7,11 +8,41 @@ import logging
7
8
  from typing import Callable, Generic, Literal, Type, TypeVar
8
9
  import warnings
9
10
 
11
+ from google.protobuf.json_format import MessageToDict
12
+
10
13
  from ansys.api.fluent.v0 import events_pb2 as EventsProtoModule
11
14
  from ansys.fluent.core.exceptions import InvalidArgument
12
15
  from ansys.fluent.core.streaming_services.streaming import StreamingService
13
16
  from ansys.fluent.core.warnings import PyFluentDeprecationWarning
14
17
 
18
+ __all__ = [
19
+ "EventsManager",
20
+ "Event",
21
+ "SolverEvent",
22
+ "MeshingEvent",
23
+ "TimestepStartedEventInfo",
24
+ "TimestepEndedEventInfo",
25
+ "IterationEndedEventInfo",
26
+ "CalculationsStartedEventInfo",
27
+ "CalculationsEndedEventInfo",
28
+ "CalculationsPausedEventInfo",
29
+ "CalculationsResumedEventInfo",
30
+ "AboutToLoadCaseEventInfo",
31
+ "CaseLoadedEventInfo",
32
+ "AboutToLoadDataEventInfo",
33
+ "DataLoadedEventInfo",
34
+ "AboutToInitializeSolutionEventInfo",
35
+ "SolutionInitializedEventInfo",
36
+ "ReportDefinitionUpdatedEventInfo",
37
+ "ReportPlotSetUpdatedEventInfo",
38
+ "ResidualPlotUpdatedEventInfo",
39
+ "SettingsClearedEventInfo",
40
+ "SolutionPausedEventInfo",
41
+ "ProgressUpdatedEventInfo",
42
+ "SolverTimeEstimateUpdatedEventInfo",
43
+ "FatalErrorEventInfo",
44
+ ]
45
+
15
46
  network_logger = logging.getLogger("pyfluent.networking")
16
47
 
17
48
 
@@ -70,6 +101,269 @@ class MeshingEvent(Enum):
70
101
  return _missing_for_events(cls, value)
71
102
 
72
103
 
104
+ class EventInfoBase:
105
+ """Base class for event information classes."""
106
+
107
+ derived_classes = {}
108
+
109
+ def __init_subclass__(cls, event, **kwargs):
110
+ super().__init_subclass__(**kwargs)
111
+ cls.derived_classes[event] = cls
112
+
113
+ def __post_init__(self):
114
+ for f in fields(self):
115
+ # Cast to the correct type
116
+ setattr(self, f.name, f.type(getattr(self, f.name)))
117
+
118
+ def __getattr__(self, name):
119
+ for f in fields(self):
120
+ if f.metadata.get("deprecated_name") == name:
121
+ warnings.warn(
122
+ f"'{name}' is deprecated. Use '{f.name}' instead.",
123
+ PyFluentDeprecationWarning,
124
+ )
125
+ return getattr(self, f.name)
126
+ return self.__getattribute__(name)
127
+
128
+
129
+ @dataclass
130
+ class TimestepStartedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_STARTED):
131
+ """Information about the event triggered when a timestep is started.
132
+
133
+ Attributes
134
+ ----------
135
+ index : int
136
+ Timestep index.
137
+ size : float
138
+ Timestep size.
139
+ """
140
+
141
+ index: int
142
+ size: float
143
+
144
+
145
+ @dataclass
146
+ class TimestepEndedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_ENDED):
147
+ """Information about the event triggered when a timestep is ended.
148
+
149
+ Attributes
150
+ ----------
151
+ index : int
152
+ Timestep index.
153
+ size : float
154
+ Timestep size.
155
+ """
156
+
157
+ index: int
158
+ size: float
159
+
160
+
161
+ @dataclass
162
+ class IterationEndedEventInfo(EventInfoBase, event=SolverEvent.ITERATION_ENDED):
163
+ """Information about the event triggered when an iteration is ended.
164
+
165
+ Attributes
166
+ ----------
167
+ index : int
168
+ Iteration index.
169
+ """
170
+
171
+ index: int
172
+
173
+
174
+ class CalculationsStartedEventInfo(
175
+ EventInfoBase, event=SolverEvent.CALCULATIONS_STARTED
176
+ ):
177
+ """Information about the event triggered when calculations are started."""
178
+
179
+
180
+ class CalculationsEndedEventInfo(EventInfoBase, event=SolverEvent.CALCULATIONS_ENDED):
181
+ """Information about the event triggered when calculations are ended."""
182
+
183
+
184
+ class CalculationsPausedEventInfo(EventInfoBase, event=SolverEvent.CALCULATIONS_PAUSED):
185
+ """Information about the event triggered when calculations are paused."""
186
+
187
+
188
+ class CalculationsResumedEventInfo(
189
+ EventInfoBase, event=SolverEvent.CALCULATIONS_RESUMED
190
+ ):
191
+ """Information about the event triggered when calculations are resumed."""
192
+
193
+
194
+ @dataclass
195
+ class AboutToLoadCaseEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_CASE):
196
+ """Information about the event triggered just before a case file is loaded.
197
+
198
+ Attributes
199
+ ----------
200
+ case_file_name : str
201
+ Case filename.
202
+ """
203
+
204
+ case_file_name: str = field(metadata=dict(deprecated_name="casefilepath"))
205
+
206
+
207
+ @dataclass
208
+ class CaseLoadedEventInfo(EventInfoBase, event=SolverEvent.CASE_LOADED):
209
+ """Information about the event triggered after a case file is loaded.
210
+
211
+ Attributes
212
+ ----------
213
+ case_file_name : str
214
+ Case filename.
215
+ """
216
+
217
+ case_file_name: str = field(metadata=dict(deprecated_name="casefilepath"))
218
+
219
+
220
+ @dataclass
221
+ class AboutToLoadDataEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_DATA):
222
+ """Information about the event triggered just before a data file is loaded.
223
+
224
+ Attributes
225
+ ----------
226
+ data_file_name : str
227
+ Data filename.
228
+ """
229
+
230
+ data_file_name: str = field(metadata=dict(deprecated_name="datafilepath"))
231
+
232
+
233
+ @dataclass
234
+ class DataLoadedEventInfo(EventInfoBase, event=SolverEvent.DATA_LOADED):
235
+ """Information about the event triggered after a data file is loaded.
236
+
237
+ Attributes
238
+ ----------
239
+ data_file_name : str
240
+ Data filename.
241
+ """
242
+
243
+ data_file_name: str = field(metadata=dict(deprecated_name="datafilepath"))
244
+
245
+
246
+ class AboutToInitializeSolutionEventInfo(
247
+ EventInfoBase, event=SolverEvent.ABOUT_TO_INITIALIZE_SOLUTION
248
+ ):
249
+ """Information about the event triggered just before solution is initialized."""
250
+
251
+
252
+ class SolutionInitializedEventInfo(
253
+ EventInfoBase, event=SolverEvent.SOLUTION_INITIALIZED
254
+ ):
255
+ """Information about the event triggered after solution is initialized."""
256
+
257
+
258
+ @dataclass
259
+ class ReportDefinitionUpdatedEventInfo(
260
+ EventInfoBase, event=SolverEvent.REPORT_DEFINITION_UPDATED
261
+ ):
262
+ """Information about the event triggered when a report definition is updated.
263
+
264
+ Attributes
265
+ ----------
266
+ report_name : str
267
+ Report name.
268
+ """
269
+
270
+ report_name: str = field(metadata=dict(deprecated_name="reportdefinitionname"))
271
+
272
+
273
+ @dataclass
274
+ class ReportPlotSetUpdatedEventInfo(
275
+ EventInfoBase, event=SolverEvent.REPORT_PLOT_SET_UPDATED
276
+ ):
277
+ """Information about the event triggered when a report plot set is updated.
278
+
279
+ Attributes
280
+ ----------
281
+ plot_set_name : str
282
+ Plot set name.
283
+ """
284
+
285
+ plot_set_name: str = field(metadata=dict(deprecated_name="plotsetname"))
286
+
287
+
288
+ class ResidualPlotUpdatedEventInfo(
289
+ EventInfoBase, event=SolverEvent.RESIDUAL_PLOT_UPDATED
290
+ ):
291
+ """Information about the event triggered when residual plots are updated."""
292
+
293
+
294
+ class SettingsClearedEventInfo(EventInfoBase, event=SolverEvent.SETTINGS_CLEARED):
295
+ """Information about the event triggered when settings are cleared."""
296
+
297
+
298
+ @dataclass
299
+ class SolutionPausedEventInfo(EventInfoBase, event=SolverEvent.SOLUTION_PAUSED):
300
+ """Information about the event triggered when solution is paused.
301
+
302
+ Attributes
303
+ ----------
304
+ level : str
305
+ Level of the pause event.
306
+ index : int
307
+ Index of the pause event.
308
+ """
309
+
310
+ level: str
311
+ index: int
312
+
313
+
314
+ @dataclass
315
+ class ProgressUpdatedEventInfo(EventInfoBase, event=SolverEvent.PROGRESS_UPDATED):
316
+ """Information about the event triggered when progress is updated.
317
+
318
+ Attributes
319
+ ----------
320
+ message : str
321
+ Progress message.
322
+ percentage : int
323
+ Progress percentage.
324
+ """
325
+
326
+ message: str
327
+ percentage: int = field(metadata=dict(deprecated_name="percentComplete"))
328
+
329
+
330
+ @dataclass
331
+ class SolverTimeEstimateUpdatedEventInfo(
332
+ EventInfoBase, event=SolverEvent.SOLVER_TIME_ESTIMATE_UPDATED
333
+ ):
334
+ """Information about the event triggered when solver time estimate is updated.
335
+
336
+ Attributes
337
+ ----------
338
+ hours : float
339
+ Hours of solver time estimate.
340
+ minutes : float
341
+ Minutes of solver time estimate.
342
+ seconds : float
343
+ Seconds of solver time estimate.
344
+ """
345
+
346
+ hours: float
347
+ minutes: float
348
+ seconds: float
349
+
350
+
351
+ @dataclass
352
+ class FatalErrorEventInfo(EventInfoBase, event=SolverEvent.FATAL_ERROR):
353
+ """Information about the event triggered when a fatal error occurs.
354
+
355
+ Attributes
356
+ ----------
357
+ message : str
358
+ Error message.
359
+ error_code : int
360
+ Error code.
361
+ """
362
+
363
+ message: str
364
+ error_code: int = field(metadata=dict(deprecated_name="errorCode"))
365
+
366
+
73
367
  TEvent = TypeVar("TEvent")
74
368
 
75
369
 
@@ -100,6 +394,17 @@ class EventsManager(Generic[TEvent]):
100
394
  self._session = session
101
395
  self._sync_event_ids = {}
102
396
 
397
+ def _construct_event_info(
398
+ self, response: EventsProtoModule.BeginStreamingResponse, event: TEvent
399
+ ):
400
+ event_info_msg = getattr(response, event.value.lower())
401
+ # Note: MessageToDict's parameter names are different in different protobuf versions
402
+ event_info_dict = MessageToDict(event_info_msg, True)
403
+ solver_event = SolverEvent(event.value)
404
+ event_info_cls = EventInfoBase.derived_classes.get(solver_event)
405
+ # Key names can be different, but their order is the same
406
+ return event_info_cls(*event_info_dict.values())
407
+
103
408
  def _process_streaming(
104
409
  self, service, id, stream_begin_method, started_evt, *args, **kwargs
105
410
  ):
@@ -129,30 +434,33 @@ class EventsManager(Generic[TEvent]):
129
434
  for callback in callbacks_map.values():
130
435
  callback(
131
436
  session=self._session,
132
- event_info=getattr(response, event_name.value.lower()),
437
+ event_info=self._construct_event_info(response, event_name),
133
438
  )
134
439
  except StopIteration:
135
440
  break
136
441
 
137
442
  @staticmethod
138
443
  def _make_callback_to_call(callback: Callable, args, kwargs):
139
- old_style = "session_id" in inspect.signature(callback).parameters
140
- if old_style:
444
+ params = inspect.signature(callback).parameters
445
+ if "session_id" in params:
141
446
  warnings.warn(
142
447
  "Update event callback function signatures"
143
448
  " substituting 'session' for 'session_id'.",
144
449
  PyFluentDeprecationWarning,
145
450
  )
146
- fn = partial(callback, *args, **kwargs)
147
- return (
148
- (
149
- lambda session, event_info: fn(
150
- session_id=session.id, event_info=event_info
151
- )
451
+ return lambda session, event_info: callback(
452
+ *args, session_id=session.id, event_info=event_info, **kwargs
453
+ )
454
+ else:
455
+ positional_args = [
456
+ p
457
+ for p in params
458
+ if p not in kwargs and p not in ("session", "event_info")
459
+ ]
460
+ kwargs.update(dict(zip(positional_args, args)))
461
+ return lambda session, event_info: callback(
462
+ session=session, event_info=event_info, **kwargs
152
463
  )
153
- if old_style
154
- else fn
155
- )
156
464
 
157
465
  def register_callback(
158
466
  self,
@@ -229,8 +537,8 @@ class EventsManager(Generic[TEvent]):
229
537
  del callbacks_map[callback_id]
230
538
  sync_event_id = self._sync_event_ids.pop(callback_id, None)
231
539
  if sync_event_id:
232
- self._session.scheme_eval.scheme_eval(
233
- f"(cancel-solution-monitor 'pyfluent-{sync_event_id})"
540
+ self._session._app_utilities.unregister_pause_on_solution_events(
541
+ registration_id=sync_event_id
234
542
  )
235
543
 
236
544
  def start(self, *args, **kwargs) -> None:
@@ -247,44 +555,20 @@ class EventsManager(Generic[TEvent]):
247
555
  callback_id: str,
248
556
  callback: Callable,
249
557
  ) -> tuple[Literal[SolverEvent.SOLUTION_PAUSED], Callable]:
250
- unique_id = self._session.scheme_eval.scheme_eval(
251
- f"""
252
- (let
253
- ((ids
254
- (let loop ((i 1))
255
- (define next-id (string->symbol (format #f "pyfluent-~d" i)))
256
- (if (check-monitor-existence next-id)
257
- (loop (1+ i))
258
- (list i next-id)
259
- )
260
- )
261
- ))
262
- (register-solution-monitor
263
- (cadr ids)
264
- (lambda (niter time)
265
- (if (integer? niter)
266
- (begin
267
- (events/transmit 'auto-pause (cons (car ids) niter))
268
- (grpcserver/auto-pause (is-server-running?) (cadr ids))
269
- )
270
- )
271
- ()
272
- )
273
- {'#t' if event_type == SolverEvent.TIMESTEP_ENDED else '#f'}
274
- )
275
- (car ids)
276
- )
277
- """
558
+ unique_id: int = self._session._app_utilities.register_pause_on_solution_events(
559
+ solution_event=event_type
278
560
  )
279
561
 
280
- def on_pause(session, event_info: EventsProtoModule.AutoPauseEvent):
281
- if unique_id == event_info.level:
282
- event_info_cls = (
283
- EventsProtoModule.TimestepEndedEvent
284
- if event_type == SolverEvent.TIMESTEP_ENDED
285
- else EventsProtoModule.IterationEndedEvent
286
- )
287
- event_info = event_info_cls(index=event_info.index)
562
+ def on_pause(session, event_info: SolutionPausedEventInfo):
563
+ if unique_id == int(event_info.level):
564
+ if event_type == SolverEvent.ITERATION_ENDED:
565
+ event_info = IterationEndedEventInfo(index=event_info.index)
566
+ else:
567
+ event_info = TimestepEndedEventInfo(
568
+ # TODO: Timestep size is currently not available
569
+ index=event_info.index,
570
+ size=0,
571
+ )
288
572
  try:
289
573
  callback(session, event_info)
290
574
  except Exception as e:
@@ -293,8 +577,8 @@ class EventsManager(Generic[TEvent]):
293
577
  exc_info=True,
294
578
  )
295
579
  finally:
296
- session.scheme_eval.scheme_eval(
297
- f"(grpcserver/auto-resume (is-server-running?) 'pyfluent-{unique_id})"
580
+ session._app_utilities.resume_on_solution_event(
581
+ registration_id=unique_id
298
582
  )
299
583
 
300
584
  self._sync_event_ids[callback_id] = unique_id
@@ -16,6 +16,8 @@ from ansys.fluent.core.examples.downloads import download_file
16
16
  from ansys.fluent.core.utils.file_transfer_service import RemoteFileTransferStrategy
17
17
  from ansys.fluent.core.utils.fluent_version import FluentVersion
18
18
 
19
+ sys.path.append(Path(__file__).parent / "util")
20
+
19
21
 
20
22
  def pytest_addoption(parser):
21
23
  parser.addoption(
@@ -281,6 +283,13 @@ def new_solver_session():
281
283
  solver.exit()
282
284
 
283
285
 
286
+ @pytest.fixture
287
+ def new_solver_session_t4():
288
+ solver = create_session(processor_count=4)
289
+ yield solver
290
+ solver.exit()
291
+
292
+
284
293
  @pytest.fixture
285
294
  def new_solver_session_sp():
286
295
  solver = create_session(precision="single")
@@ -327,6 +336,14 @@ def mixing_elbow_settings_session(new_solver_session):
327
336
  return solver
328
337
 
329
338
 
339
+ @pytest.fixture
340
+ def mixing_elbow_case_session_t4(new_solver_session_t4):
341
+ solver = new_solver_session_t4
342
+ case_name = download_file("mixing_elbow.cas.h5", "pyfluent/mixing_elbow")
343
+ solver.settings.file.read(file_type="case", file_name=case_name)
344
+ return solver
345
+
346
+
330
347
  @pytest.fixture
331
348
  def mixing_elbow_case_data_session(new_solver_session):
332
349
  solver = new_solver_session
@@ -383,3 +400,16 @@ def periodic_rot_settings_session(new_solver_session):
383
400
  @pytest.fixture
384
401
  def disable_datamodel_cache(monkeypatch: pytest.MonkeyPatch):
385
402
  monkeypatch.setattr(pyfluent, "DATAMODEL_USE_STATE_CACHE", False)
403
+
404
+
405
+ @pytest.fixture(params=["old", "new"])
406
+ def datamodel_api_version_all(request, monkeypatch: pytest.MonkeyPatch) -> None:
407
+ if request.param == "new":
408
+ monkeypatch.setenv("REMOTING_NEW_DM_API", "1")
409
+ monkeypatch.setenv("REMOTING_MAPPED_NEW_DM_API", "1")
410
+
411
+
412
+ @pytest.fixture
413
+ def datamodel_api_version_new(monkeypatch: pytest.MonkeyPatch) -> None:
414
+ monkeypatch.setenv("REMOTING_NEW_DM_API", "1")
415
+ monkeypatch.setenv("REMOTING_MAPPED_NEW_DM_API", "1")
@@ -4,7 +4,7 @@ import tempfile
4
4
  import pytest
5
5
 
6
6
  try:
7
- from ansys.fluent.core import (
7
+ from ansys.fluent.core.solver import (
8
8
  Ablation,
9
9
  Battery,
10
10
  BoundaryCondition,