Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: event streaming callback #3546

Merged
merged 4 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 1 addition & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,22 +115,6 @@ jobs:
restore-keys: |
Python-${{ runner.os }}-${{ matrix.python-version }}
- name: Install Quarto
uses: quarto-dev/quarto-actions/setup@v2
with:
tinytex: true

- name: Check Quarto Version
shell: bash
run: |
quarto --version
- name: "Install Poppler for PDF to PNG conversion"
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y poppler-utils
- name: Install pyfluent
run: make install

Expand Down Expand Up @@ -197,6 +181,7 @@ jobs:
make build-doc-source
env:
FLUENT_IMAGE_TAG: ${{ env.DOC_DEPLOYMENT_IMAGE_TAG }}
PYFLUENT_DOC_SKIP_CHEATSHEET: 1

- name: Zip HTML Documentation before upload
run: |
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/doc-build-dev-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ jobs:
sudo apt update
sudo apt-get install pandoc libegl1 make xvfb libfontconfig1 libxrender1 libxkbcommon-x11-0 -y
- name: Install Quarto
uses: quarto-dev/quarto-actions/setup@v2
with:
tinytex: true

- name: Check Quarto Version
shell: bash
run: |
quarto --version
- name: "Install Poppler for PDF to PNG conversion"
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y poppler-utils
- name: Install pyfluent
run: make install

Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/doc-build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ jobs:
sudo apt update
sudo apt-get install pandoc libegl1 make xvfb libfontconfig1 libxrender1 libxkbcommon-x11-0 -y
- name: Install Quarto
uses: quarto-dev/quarto-actions/setup@v2
with:
tinytex: true

- name: Check Quarto Version
shell: bash
run: |
quarto --version
- name: "Install Poppler for PDF to PNG conversion"
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y poppler-utils
- name: Install pyfluent
run: make install

Expand Down
13 changes: 6 additions & 7 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@

toggleprompt_offset_right = 35

skip_examples = int(os.getenv("PYFLUENT_SKIP_EXAMPLES_DOC", 0))
if skip_examples:
pass
else:
if os.getenv("PYFLUENT_DOC_SKIP_EXAMPLES") != "1":
mkundu1 marked this conversation as resolved.
Show resolved Hide resolved
extensions.append("sphinx_gallery.gen_gallery")

typehints_document_rtype = False
Expand Down Expand Up @@ -197,13 +194,15 @@ def _stop_fluent_container(gallery_conf, fname):
"navbar_end": ["version-switcher", "theme-switcher", "navbar-icon-links"],
"navigation_depth": -1,
"collapse_navigation": True,
"cheatsheet": {
}

if os.getenv("PYFLUENT_DOC_SKIP_CHEATSHEET") != "1":
html_theme_options["cheatsheet"] = {
"file": "cheatsheet/cheat_sheet.qmd",
"pages": ["index", "getting_started/index", "user_guide/index"],
"title": "PyFluent cheat sheet",
"version": __version__,
},
}
}

# -- Options for HTMLHelp output ---------------------------------------------

Expand Down
6 changes: 4 additions & 2 deletions doc/source/contributing/environment_variables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Following is a list of environment variables that can be set to control various
- Specifies the path inside the container where the host path is mounted while starting a Fluent container in :func:`launch_fluent() <ansys.fluent.core.launcher.launcher.launch_fluent>`.
* - PYFLUENT_FLUENT_DEBUG
- Starts Fluent in debug mode while launching Fluent in :func:`launch_fluent() <ansys.fluent.core.launcher.launcher.launch_fluent>`.
* - PYFLUENT_DOC_SKIP_CHEATSHEET:
- Skips the generation of cheatsheet.
* - PYFLUENT_DOC_SKIP_EXAMPLES
- Skips the generation of examples documentation.
* - PYFLUENT_FLUENT_IP
- Specifies the IP address of the Fluent server in :func:`connect_to_fluent() <ansys.fluent.core.launcher.launcher.connect_to_fluent>`.
* - PYFLUENT_FLUENT_PORT
Expand All @@ -47,8 +51,6 @@ Following is a list of environment variables that can be set to control various
- Shows the Fluent GUI while launching Fluent in :func:`launch_fluent() <ansys.fluent.core.launcher.launcher.launch_fluent>`.
* - PYFLUENT_SKIP_API_UPGRADE_ADVICE
- Disables printing of TUI to settings API upgrade advice.
* - PYFLUENT_SKIP_EXAMPLES_DOC
- Skips the generation of examples documentation.
* - PYFLUENT_TIMEOUT_FORCE_EXIT
- Enables force exit while exiting a Fluent session and specifies the timeout in seconds.
* - PYFLUENT_WATCHDOG_DEBUG
Expand Down
21 changes: 14 additions & 7 deletions doc/source/user_guide/events.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,27 @@ The following code triggers a callback at the end of every iteration.

.. code-block:: python
>>> from ansys.fluent.core import SolverEvent
>>> from ansys.fluent.core import SolverEvent, IterationEndedEventInfo
>>>
>>> def on_iteration_ended(session, event_info):
>>> def on_iteration_ended(session, event_info: IterationEndedEventInfo):
>>> print("Iteration ended. Index = ", event_info.index)
>>>
>>> callback_id = solver.events.register_callback(SolverEvent.ITERATION_ENDED, on_iteration_ended)
>>>
The general signature of the callback function is ``cb(session, event_info, <additional arguments>)``, where ``session`` is the session instance
and ``event_info`` instance holds information about the event. The event information classes for each event are documented in the
API reference of the :obj:`~ansys.fluent.core.streaming_services.events_streaming` module. See the callback function
``on_case_loaded_with_args()`` in the below examples for an example of how to pass additional arguments to the callback
function.


Examples
--------

.. code-block:: python
>>> from ansys.fluent.core import MeshingEvent, SolverEvent
>>> from ansys.fluent.core import CaseLoadedEventInfo, DataLoadedEventInfo, SolutionInitializedEventInfo, IterationEndedEventInfo
>>> from ansys.fluent.core.utils.event_loop import execute_in_event_loop_threadsafe
>>> from ansys.fluent.visualization.matplotlib import matplot_windows_manager
>>> from ansys.fluent.visualization.pyvista import pyvista_windows_manager
Expand All @@ -48,26 +55,26 @@ Examples
>>> contour2.surfaces_list = ["symmetry"]
>>>
>>> @execute_in_event_loop_threadsafe
>>> def auto_refersh_call_back_iteration(session, event_info):
>>> def auto_refersh_call_back_iteration(session, event_info: IterationEndedEventInfo):
>>> if event_info.index % 5 == 0:
>>> pyvista_windows_manager.refresh_windows(session.id, ["contour-1", "contour-2"])
>>> matplot_windows_manager.refresh_windows("", ["residual"])
>>>
>>> callback_itr_id = solver.events.register_callback(SolverEvent.ITERATION_ENDED, auto_refersh_call_back_iteration)
>>>
>>> @execute_in_event_loop_threadsafe
>>> def initialize_call_back(session, event_info):
>>> def initialize_call_back(session, event_info: SolutionInitializedEventInfo | DataLoadedEventInfo):
>>> pyvista_windows_manager.refresh_windows(session.id, ["contour-1", "contour-2"])
>>> matplot_windows_manager.refresh_windows("", ["residual"])
>>>
>>> callback_init_id = solver.events.register_callback(SolverEvent.SOLUTION_INITIALIZED, initialize_call_back)
>>>
>>> callback_data_read_id = solver.events.register_callback(SolverEvent.DATA_LOADED, initialize_call_back)
>>>
>>> def on_case_loaded(session, event_info):
>>> def on_case_loaded(session, event_info: CaseLoadedEventInfo):
>>> print("Case loaded. Index = ", event_info.index)
>>>
>>> def on_case_loaded_with_args(x, y, session, event_info):
>>> def on_case_loaded_with_args(session, event_info: CaseLoadedEventInfo, x, y):
>>> print(f"Case loaded with {x}, {y}. Index = ", event_info.index)
>>>
>>> callback = meshing.events.register_callback(MeshingEvent.CASE_LOADED, on_case_loaded)
Expand Down
39 changes: 28 additions & 11 deletions src/ansys/fluent/core/streaming_services/events_streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from ansys.fluent.core.warnings import PyFluentDeprecationWarning

__all__ = [
"EventsManager",
"Event",
"SolverEvent",
"MeshingEvent",
Expand Down Expand Up @@ -128,6 +129,7 @@ def __getattr__(self, name):
@dataclass
class TimestepStartedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_STARTED):
"""Information about the event triggered when a timestep is started.
Attributes
----------
index : int
Expand All @@ -143,6 +145,7 @@ class TimestepStartedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_STARTED
@dataclass
class TimestepEndedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_ENDED):
"""Information about the event triggered when a timestep is ended.
Attributes
----------
index : int
Expand All @@ -158,6 +161,7 @@ class TimestepEndedEventInfo(EventInfoBase, event=SolverEvent.TIMESTEP_ENDED):
@dataclass
class IterationEndedEventInfo(EventInfoBase, event=SolverEvent.ITERATION_ENDED):
"""Information about the event triggered when an iteration is ended.
Attributes
----------
index : int
Expand Down Expand Up @@ -190,6 +194,7 @@ class CalculationsResumedEventInfo(
@dataclass
class AboutToLoadCaseEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_CASE):
"""Information about the event triggered just before a case file is loaded.
Attributes
----------
case_file_name : str
Expand All @@ -202,6 +207,7 @@ class AboutToLoadCaseEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_CA
@dataclass
class CaseLoadedEventInfo(EventInfoBase, event=SolverEvent.CASE_LOADED):
"""Information about the event triggered after a case file is loaded.
Attributes
----------
case_file_name : str
Expand All @@ -214,6 +220,7 @@ class CaseLoadedEventInfo(EventInfoBase, event=SolverEvent.CASE_LOADED):
@dataclass
class AboutToLoadDataEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_DATA):
"""Information about the event triggered just before a data file is loaded.
Attributes
----------
data_file_name : str
Expand All @@ -226,6 +233,7 @@ class AboutToLoadDataEventInfo(EventInfoBase, event=SolverEvent.ABOUT_TO_LOAD_DA
@dataclass
class DataLoadedEventInfo(EventInfoBase, event=SolverEvent.DATA_LOADED):
"""Information about the event triggered after a data file is loaded.
Attributes
----------
data_file_name : str
Expand All @@ -252,6 +260,7 @@ class ReportDefinitionUpdatedEventInfo(
EventInfoBase, event=SolverEvent.REPORT_DEFINITION_UPDATED
):
"""Information about the event triggered when a report definition is updated.
Attributes
----------
report_name : str
Expand All @@ -266,6 +275,7 @@ class ReportPlotSetUpdatedEventInfo(
EventInfoBase, event=SolverEvent.REPORT_PLOT_SET_UPDATED
):
"""Information about the event triggered when a report plot set is updated.
Attributes
----------
plot_set_name : str
Expand All @@ -288,6 +298,7 @@ class SettingsClearedEventInfo(EventInfoBase, event=SolverEvent.SETTINGS_CLEARED
@dataclass
class SolutionPausedEventInfo(EventInfoBase, event=SolverEvent.SOLUTION_PAUSED):
"""Information about the event triggered when solution is paused.
Attributes
----------
level : str
Expand All @@ -303,6 +314,7 @@ class SolutionPausedEventInfo(EventInfoBase, event=SolverEvent.SOLUTION_PAUSED):
@dataclass
class ProgressUpdatedEventInfo(EventInfoBase, event=SolverEvent.PROGRESS_UPDATED):
"""Information about the event triggered when progress is updated.
Attributes
----------
message : str
Expand All @@ -320,6 +332,7 @@ class SolverTimeEstimateUpdatedEventInfo(
EventInfoBase, event=SolverEvent.SOLVER_TIME_ESTIMATE_UPDATED
):
"""Information about the event triggered when solver time estimate is updated.
Attributes
----------
hours : float
Expand All @@ -338,6 +351,7 @@ class SolverTimeEstimateUpdatedEventInfo(
@dataclass
class FatalErrorEventInfo(EventInfoBase, event=SolverEvent.FATAL_ERROR):
"""Information about the event triggered when a fatal error occurs.
Attributes
----------
message : str
Expand Down Expand Up @@ -428,23 +442,26 @@ def _process_streaming(

@staticmethod
def _make_callback_to_call(callback: Callable, args, kwargs):
old_style = "session_id" in inspect.signature(callback).parameters
if old_style:
params = inspect.signature(callback).parameters
if "session_id" in params:
warnings.warn(
"Update event callback function signatures"
" substituting 'session' for 'session_id'.",
PyFluentDeprecationWarning,
)
fn = partial(callback, *args, **kwargs)
return (
(
lambda session, event_info: fn(
session_id=session.id, event_info=event_info
)
return lambda session, event_info: callback(
*args, session_id=session.id, event_info=event_info, **kwargs
)
else:
positional_args = [
p
for p in params
if p not in kwargs and p not in ("session", "event_info")
]
kwargs.update(dict(zip(positional_args, args)))
return lambda session, event_info: callback(
session=session, event_info=event_info, **kwargs
)
if old_style
else fn
)

def register_callback(
self,
Expand Down
13 changes: 12 additions & 1 deletion tests/test_events_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ def on_case_loaded(session, event_info):

on_case_loaded.loaded = False

def on_case_loaded_with_args(x, y, session, event_info):
def on_case_loaded_with_args_optional_first(x, y, session, event_info):
on_case_loaded_with_args_optional_first.state = dict(x=x, y=y)

on_case_loaded_with_args_optional_first.state = None

def on_case_loaded_with_args(session, event_info, x, y):
on_case_loaded_with_args.state = dict(x=x, y=y)

on_case_loaded_with_args.state = None
Expand All @@ -43,6 +48,10 @@ def on_case_loaded_with_args(x, y, session, event_info):

solver.events.register_callback(SolverEvent.CASE_LOADED, on_case_loaded)

solver.events.register_callback(
SolverEvent.CASE_LOADED, on_case_loaded_with_args_optional_first, 12, y=42
)

solver.events.register_callback(
SolverEvent.CASE_LOADED, on_case_loaded_with_args, 12, y=42
)
Expand All @@ -54,6 +63,7 @@ def on_case_loaded_with_args(x, y, session, event_info):
assert not on_case_loaded_old.loaded
assert not on_case_loaded.loaded
assert not on_case_loaded_old_with_args.state
assert not on_case_loaded_with_args_optional_first.state
assert not on_case_loaded_with_args.state

try:
Expand All @@ -64,6 +74,7 @@ def on_case_loaded_with_args(x, y, session, event_info):
assert on_case_loaded_old.loaded
assert on_case_loaded.loaded
assert on_case_loaded_old_with_args.state == dict(x=12, y=42)
assert on_case_loaded_with_args_optional_first.state == dict(x=12, y=42)
assert on_case_loaded_with_args.state == dict(x=12, y=42)


Expand Down
Loading