diff --git a/doc/source/_ext/autodocclass.py b/doc/source/_ext/autodocclass.py new file mode 100644 index 00000000..f7c5f876 --- /dev/null +++ b/doc/source/_ext/autodocclass.py @@ -0,0 +1,221 @@ +from enum import IntEnum +from typing import Any, Optional + +from docutils.statemachine import StringList +from sphinx.application import Sphinx +from sphinx.ext.autodoc import ClassDocumenter, bool_option + + +class PostDocumenter(ClassDocumenter): + objtype = "postdoc" + directivetype = ClassDocumenter.objtype + priority = 10 + ClassDocumenter.priority + option_spec = dict(ClassDocumenter.option_spec) + option_spec["hex"] = bool_option + + @classmethod + def can_document_member( + cls, member: Any, membername: str, isattr: bool, parent: Any + ) -> bool: + try: + return issubclass(member, IntEnum) + except TypeError: + return False + + def add_directive_header(self, sig: str) -> None: + self.add_line(f".. _post_{self.object.__name__}:", self.get_sourcename()) + self.add_line(" ", self.get_sourcename()) + super().add_directive_header(sig) + self.add_line(" ", self.get_sourcename()) + + def add_content( + self, more_content: Optional[StringList], no_docstring: bool = False + ) -> None: + + super().add_content(more_content, no_docstring) + + source_name = self.get_sourcename() + object = self.object + self.add_line("", source_name) + + data_dicts = {} + + def _update(clss, obj_name, parent_name=None, parent_path=None): + if not data_dicts.get(obj_name): + data_dicts[obj_name] = {} + data_dicts[obj_name]["parent"] = parent_name + data_dicts[obj_name]["path"] = ( + parent_path + "_" + obj_name if parent_path else obj_name + ) + data_dicts[obj_name]["obj"] = clss + data_dicts[obj_name]["attr"] = {"Member": "Summary"} + data_dicts[obj_name]["cmd"] = {"Command": "Summary"} + data_dicts[obj_name]["include"] = {"Parent": "Summary"} + dic = data_dicts[obj_name] + if parent_path: + dic["include"][ + f":ref:`{parent_name} `" + ] = f"{parent_name}'s child" + + for the_member_name in dir(clss): + if the_member_name.startswith("_"): + continue + cls = getattr(clss, the_member_name) + the_member_value = cls.__doc__.split("\n")[0] + if cls.__class__.__name__ in ( + "PyLocalPropertyMeta", + "PyLocalObjectMeta", + ): + if cls.__class__.__name__ == "PyLocalObjectMeta": + dic["attr"][ + f":ref:`{the_member_name} `" # noqa: E501 + ] = the_member_value + else: + dic["attr"][the_member_name] = the_member_value + attrs = getattr(cls, "attributes", None) + if attrs: + for attr in attrs: + dic["attr"][ + f"{the_member_name}.{attr}" + ] = f"``{the_member_name}`` {' '.join(attr.split('_'))}." # noqa: E501 + + elif callable(cls): + dic["cmd"][the_member_name] = the_member_value + + for name in dir(clss): + cls = getattr(clss, name) + if cls.__class__.__name__ in ("PyLocalObjectMeta",): + _update(cls, name, obj_name, data_dicts[obj_name]["path"]) + for base_class in clss.__bases__: + _update(base_class, obj_name, parent_name) + + _update(object, object.__name__) + key_max = 0 + val_max = 0 + for obj_name, obj_dic in data_dicts.items(): + o = obj_dic["obj"] + parent = obj_dic["parent"] + for item in ["attr", "cmd", "include"]: + dic = obj_dic[item] + if len(dic) > 1: + key_max = max(key_max, len(max(dic.keys(), key=len))) + val_max = max(val_max, len(max(dic.values(), key=len))) + + for obj_name, obj_dic in data_dicts.items(): + o = obj_dic["obj"] + parent = obj_dic["parent"] + dic = obj_dic["attr"] + if len(dic) > 1: + col_gap = 3 + total = key_max + val_max + col_gap + # Top border + if o != object: + self.add_line(f".. _post_{obj_dic['path']}:", source_name) + self.add_line("", source_name) + self.add_line( + f".. rubric:: {o.__module__}.{o.__qualname__}", source_name + ) + self.add_line("", source_name) + # self.add_line( + # f".. autoclass:: {o.__module__}.{o.__qualname__}", source_name + # ) + self.add_line(f".. rubric:: Attributes", source_name) + self.add_line("", source_name) + self.add_line(f'{"="*key_max}{" "*col_gap}{"="*val_max}', source_name) + header = True + for key, value in dic.items(): + if header: + # Write header and border + self.add_line( + f'{key}{" "*(total-len(key)-len(value))}{value}', + source_name, + ) + self.add_line( + f'{"="*key_max}{" "*col_gap}{"="*val_max}', source_name + ) + header = False + else: + # actual data + self.add_line( + f'{key}{" "*(total-len(key)-len(value))}{value}', + source_name, + ) + # Bottom border + self.add_line(f'{"="*key_max}{" "*col_gap}{"="*val_max}', source_name) + self.add_line("", source_name) + + dic = obj_dic["cmd"] + if "update" in dic: + del dic["update"] + if len(dic) > 1: + col_gap = 3 + total = key_max + val_max + col_gap + + self.add_line(f".. rubric:: Commands", source_name) + self.add_line("", source_name) + self.add_line(f'{"="*key_max}{" "*col_gap}{"="*val_max}', source_name) + header = True + for key, value in dic.items(): + if header: + # Write header and border + self.add_line( + f'{key}{" "*(total-len(key)-len(value))}{value}', + source_name, + ) + self.add_line( + f'{"="*key_max}{" "*col_gap}{"="*val_max}', source_name + ) + header = False + else: + # actual data + self.add_line( + f'{key}{" "*(total-len(key)-len(value))}{value}', + source_name, + ) + # Bottom border + self.add_line("", source_name) + self.add_line(f'{"="*key_max}{" "*col_gap}{"="*val_max}', source_name) + self.add_line("", source_name) + self.add_line("", source_name) + + if parent: + dic = obj_dic["include"] + col_gap = 3 + total = key_max + val_max + col_gap + + self.add_line(f".. rubric:: Included in", source_name) + self.add_line(" ", source_name) + self.add_line(f'{"="*key_max}{" "*col_gap}{"="*val_max}', source_name) + self.add_line(" ", source_name) + header = True + for key, value in dic.items(): + if header: + # Write header and border + self.add_line( + f'{key}{" "*(total-len(key)-len(value))}{value}', + source_name, + ) + self.add_line( + f'{"="*key_max}{" "*col_gap}{"="*val_max}', source_name + ) + header = False + else: + # actual data + self.add_line( + f'{key}{" "*(total-len(key)-len(value))}{value}', + source_name, + ) + # Bottom border + self.add_line("", source_name) + self.add_line(f'{"="*key_max}{" "*col_gap}{"="*val_max}', source_name) + self.add_line("", source_name) + self.add_line("", source_name) + + +def setup(app: Sphinx) -> None: + app.setup_extension("sphinx.ext.autodoc") # Require autodoc extension + app.add_autodocumenter(PostDocumenter) + return { + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/doc/source/_templates/custom-class.rst b/doc/source/_templates/custom-class.rst new file mode 100644 index 00000000..f7ee0002 --- /dev/null +++ b/doc/source/_templates/custom-class.rst @@ -0,0 +1,31 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :members: + :inherited-members: + + .. {% block methods %} + .. .. automethod:: __init__ + + .. {% if methods %} + .. .. rubric:: {{ _('Methods') }} + + .. .. autosummary:: + .. {% for item in methods %} + .. ~{{ name }}.{{ item }} + .. {%- endfor %} + .. {% endif %} + .. {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/doc/source/_templates/custom-module.rst b/doc/source/_templates/custom-module.rst new file mode 100644 index 00000000..00e98caa --- /dev/null +++ b/doc/source/_templates/custom-module.rst @@ -0,0 +1,65 @@ +{{ name | escape | underline}} + +.. automodule:: {{ fullname }} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Module Attributes') }} + + .. autosummary:: + :toctree: + {% for item in attributes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block functions %} + {% if functions %} + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + :toctree: + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block classes %} + {% if classes %} + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + :toctree: + :template: custom-class.rst + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block exceptions %} + {% if exceptions %} + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + +{% block modules %} +{% if modules %} +.. rubric:: Modules + +.. autosummary:: + :toctree: + :template: custom-module.rst + :recursive: +{% for item in modules %} + {{ item }} +{%- endfor %} +{% endif %} +{% endblock %} diff --git a/doc/source/api/visualization/contour.rst b/doc/source/api/visualization/contour.rst new file mode 100644 index 00000000..a271ad0c --- /dev/null +++ b/doc/source/api/visualization/contour.rst @@ -0,0 +1,6 @@ +.. _ref_contour: + +Contour +======= + +.. autopostdoc:: ansys.fluent.visualization.pyvista.pyvista_objects.Contour diff --git a/doc/source/api/visualization/graphics.rst b/doc/source/api/visualization/graphics.rst new file mode 100644 index 00000000..86ce985b --- /dev/null +++ b/doc/source/api/visualization/graphics.rst @@ -0,0 +1,31 @@ +.. _ref_graphics: + +Graphics +======== + +.. autopostdoc:: ansys.fluent.visualization.pyvista.pyvista_objects.Graphics + +In the following example, a Graphics object is instantiated with a Fluent session as its context. The Graphics object is used to create mesh, contour, vector and surface objects. + +.. code-block:: python + + from ansys.fluent.visualization.pyvista import Graphics + graphics_session = Graphics(session) + + #Create object + mesh1 = graphics_session.Meshes["mesh-1"] + contour1 = graphics_session.Contours["contour-1"] + vector1 = graphics_session.Vectors["vector-1"] + surface1 = graphics_session.Surfaces["surface-1"] + + #Delete object + del graphics_session.Contours["contour-1"] + +.. toctree:: + :maxdepth: 2 + :hidden: + + mesh + surface + contour + vector \ No newline at end of file diff --git a/doc/source/api/visualization/index.rst b/doc/source/api/visualization/index.rst index b7bf2f1a..509e3115 100644 --- a/doc/source/api/visualization/index.rst +++ b/doc/source/api/visualization/index.rst @@ -1,10 +1,10 @@ -.. _ref_postprocessing: +.. _ref_visualization: -Postprocessing -============== +Visualization +============= -Post processing Fluent results can be done with either Fluent in-built post -processing capabilities or with the PyVista/MatplotLib integration. +Post-processing of Fluent results can be done with either Fluent in-built +post-processing capabilities or with the PyVista/MatplotLib integration. Fluent ------ @@ -116,4 +116,4 @@ environment and data is plotted in MatplotLib. :maxdepth: 2 :hidden: - pyvista_objects + post_objects diff --git a/doc/source/api/visualization/matplot_windows_manager.rst b/doc/source/api/visualization/matplot_windows_manager.rst new file mode 100644 index 00000000..545c45fe --- /dev/null +++ b/doc/source/api/visualization/matplot_windows_manager.rst @@ -0,0 +1,49 @@ +.. _ref_matplot_windows_manager: + +Matplot Windows Manager +======================= + +This class manages `MatplotLib` windows and provides methods to directly interact with them. +By registering these methods to EventsManager, plots can be updated during run +time. + +The following example will update `window-1` and `window-2` during solution initialization and +whenever data is read. Also during calculation it will update both windows at end of every +time step. + +.. code-block:: python + + from ansys.fluent.visualization.matplotlib import Plots + from ansys.fluent.visualization.matplotlib import matplot_windows_manager + + plots_session = Plots(session) + + #Create xy plot. + plot1 = plots_session.XYPlots["plot-1"] + plot1.surfaces_list = ['symmetry'] + plot1.y_axis_function = "temperature" + + + #Plot xy plot on window-1. + plot1.plot("window-1") + + #Create monitor plot. + monitor1 = plots_session.Monitors["monitor-1"] + monitor1.monitor_set_name = "residual" + + + #Plot monitor on window-2. + monitor1.plot("window-2") + + #Create callback which refreshes window-1 and window-2. + def auto_refersh_plot(session_id, event_info): + matplot_windows_manager.refresh_windows(session_id, ["window-1", "window-2"]) + + #Register this callback with server events. + cb_init_id = session.events_manager.register_callback('InitializedEvent', auto_refersh_plot) + cb_data_read_id = session.events_manager.register_callback('DataReadEvent', auto_refersh_plot) + cb_time_step_ended_id = session.events_manager.register_callback('TimestepEndedEvent', auto_refersh_plot) + + +.. autoclass:: ansys.fluent.visualization.matplotlib.matplot_windows_manager.MatplotWindowsManager + :members: \ No newline at end of file diff --git a/doc/source/api/visualization/mesh.rst b/doc/source/api/visualization/mesh.rst new file mode 100644 index 00000000..aa665ba0 --- /dev/null +++ b/doc/source/api/visualization/mesh.rst @@ -0,0 +1,8 @@ +.. _ref_mesh: + +Mesh +==== + +.. autopostdoc:: ansys.fluent.visualization.pyvista.pyvista_objects.Mesh + + diff --git a/doc/source/api/visualization/monitorplot.rst b/doc/source/api/visualization/monitorplot.rst new file mode 100644 index 00000000..525f3dbc --- /dev/null +++ b/doc/source/api/visualization/monitorplot.rst @@ -0,0 +1,8 @@ +.. _ref_monitorplot: + +MonitorPlot +=========== + +.. autopostdoc:: ansys.fluent.visualization.matplotlib.matplot_objects.MonitorPlot + + diff --git a/doc/source/api/visualization/plots.rst b/doc/source/api/visualization/plots.rst new file mode 100644 index 00000000..984abdbf --- /dev/null +++ b/doc/source/api/visualization/plots.rst @@ -0,0 +1,45 @@ +.. _ref_plots: + +Plots +===== +.. autoclass:: ansys.fluent.visualization.matplotlib.matplot_objects.Plots + + +In the following example, a Plots object is instantiated with a Fluent session as its context. The Plots object is used to create and display a xy and monitor plots. + +.. code-block:: python + + from ansys.fluent.visualization.matplotlib import Plots + + plots_session = Plots(session) + plot1 = plots_session.XYPlots["plot-1"] + plot1.surfaces_list = ['symmetry', 'wall'] + plot1.y_axis_function = "temperature" + plot1.plot("window-0") + + + #To plot data on local surface created in pyVista + + from ansys.fluent.visualization.pyvista import Graphics + pyvista_surface_provider = Graphics(session).Surfaces + plots_session = Plots(session, pyvista_surface_provider) + plot2 = plots_session.XYPlots["plot-2"] + plot2.surfaces_list = ['iso-surface-1'] + plot2.y_axis_function = "temperature" + plot2.plot("window-0") + + + #To plot monitors + + monitor1=plots_session.Monitors["monitor-1"] + monitor1.monitor_set_name = "residual" + monitor1.plot("window-0") + +.. toctree:: + :maxdepth: 2 + :hidden: + + xyplot + monitorplot + + diff --git a/doc/source/api/visualization/post_objects.rst b/doc/source/api/visualization/post_objects.rst new file mode 100644 index 00000000..2d99b94a --- /dev/null +++ b/doc/source/api/visualization/post_objects.rst @@ -0,0 +1,15 @@ +.. _ref_post_objects: + +.. toctree:: + :maxdepth: 2 + :hidden: + + graphics + plots + pyvista_windows_manager + matplot_windows_manager + + + + + diff --git a/doc/source/api/visualization/pyvista_objects.rst b/doc/source/api/visualization/pyvista_objects.rst deleted file mode 100644 index ff645a9a..00000000 --- a/doc/source/api/visualization/pyvista_objects.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _ref_post_pyvista_graphics: - -Graphics -======== -.. currentmodule:: ansys.fluent.visualization.pyvista.pyvista_objects - -.. autosummary:: - :toctree: _autosummary - - Graphics - Mesh - Surface - Contour \ No newline at end of file diff --git a/doc/source/api/visualization/pyvista_windows_manager.rst b/doc/source/api/visualization/pyvista_windows_manager.rst new file mode 100644 index 00000000..0e3173a4 --- /dev/null +++ b/doc/source/api/visualization/pyvista_windows_manager.rst @@ -0,0 +1,45 @@ +.. _ref_pyvista_windows_manager: + +PyVista Windows Manager +======================= + +This class manages `PyVista` windows and provides methods to directly interact with them. +By registering these methods to EventsManager, graphics can be updated during run +time and animations can be created. + +The following example will update `window-1` during solution initialization and whenever data +is read. Also during calculation it will update `window-1` at end of every time step and +will create animation. + +`Important`:Animation will be saved whenever window is closed. + +.. code-block:: python + + from ansys.fluent.visualization.pyvista import Graphics + from ansys.fluent.visualization.pyvista import pyvista_windows_manager + + graphics_session = Graphics(session) + + #Create contour. + contour1 = graphics_session.Contours["contour-1"] + contour1.field = "velocity-magnitude" + contour1.surfaces_list = ['symmetry'] + + #Display contour on window-1. + contour1.display("window-1") + + #Create callback which refreshes window-1. + def auto_refersh_contour(session_id, event_info): + pyvista_windows_manager.refresh_windows(session_id, ["window-1"]) + + #Register this callback with server events. + cb_init_id = session.events_manager.register_callback('InitializedEvent', auto_refersh_contour) + cb_data_read_id = session.events_manager.register_callback('DataReadEvent', auto_refersh_contour) + cb_time_step_ended_id = session.events_manager.register_callback('TimestepEndedEvent', auto_refersh_contour) + + #Create animation for window-1 + pyvista_windows_manager.animate_windows(session.id, ["window-1"]) + + +.. autoclass:: ansys.fluent.visualization.pyvista.pyvista_windows_manager.PyVistaWindowsManager + :members: \ No newline at end of file diff --git a/doc/source/api/visualization/surface.rst b/doc/source/api/visualization/surface.rst new file mode 100644 index 00000000..e95edcaf --- /dev/null +++ b/doc/source/api/visualization/surface.rst @@ -0,0 +1,9 @@ +.. _ref_surface: + + +Surface +======= + +.. autopostdoc:: ansys.fluent.visualization.pyvista.pyvista_objects.Surface + + diff --git a/doc/source/api/visualization/vector.rst b/doc/source/api/visualization/vector.rst new file mode 100644 index 00000000..42eb09ef --- /dev/null +++ b/doc/source/api/visualization/vector.rst @@ -0,0 +1,6 @@ +.. _ref_vector: + +Vector +====== + +.. autopostdoc:: ansys.fluent.visualization.pyvista.pyvista_objects.Vector \ No newline at end of file diff --git a/doc/source/api/visualization/xyplot.rst b/doc/source/api/visualization/xyplot.rst new file mode 100644 index 00000000..e98a77b5 --- /dev/null +++ b/doc/source/api/visualization/xyplot.rst @@ -0,0 +1,11 @@ +.. _ref_xyplot: + +XYPlot +====== + +.. autopostdoc:: ansys.fluent.visualization.matplotlib.matplot_objects.XYPlot + + + + + diff --git a/doc/source/conf.py b/doc/source/conf.py index 428c7ab9..e9994a9b 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -3,6 +3,7 @@ import os import platform import subprocess +import sys import ansys.fluent.core as pyfluent from ansys_sphinx_theme import ansys_favicon, pyansys_logo_black @@ -54,6 +55,7 @@ "sphinx_copybutton", "sphinx_gallery.gen_gallery", "sphinxemoji.sphinxemoji", + "autodocclass", ] # Intersphinx mapping @@ -254,3 +256,4 @@ def _stop_fluent_container(gallery_conf, fname): # A list of files that should not be packed into the epub file. epub_exclude_files = ["search.html"] +sys.path.append(os.path.abspath("./_ext")) diff --git a/doc/source/index.rst b/doc/source/index.rst index c2881f69..451edd2a 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -52,7 +52,7 @@ Features The package, ``ansys-fluent-visualization``, provides features such as: - Script post processing using Fluent's in-built post processing capabilities. - See the :ref:`ref_postprocessing` module for more information. + See the :ref:`ref_visualization` module for more information. - Plotting of Fluent geometry and meshes using `PyVista `_ from within a Python script or an interactive `Jupyter notebook `_. diff --git a/examples/00-postprocessing/post_processing_exhaust_manifold.py b/examples/00-postprocessing/post_processing_exhaust_manifold.py index a5e9b67a..600ec210 100644 --- a/examples/00-postprocessing/post_processing_exhaust_manifold.py +++ b/examples/00-postprocessing/post_processing_exhaust_manifold.py @@ -79,12 +79,39 @@ mesh1.show_edges = False mesh1.display("window-2") +############################################################################### +# Create plane-surface XY plane + +surf_xy_plane = graphics.Surfaces["xy-plane"] +surf_xy_plane.definition.type = "plane-surface" +plane_surface_xy = surf_xy_plane.definition.plane_surface +plane_surface_xy.z = -0.0441921 +surf_xy_plane.display("window-3") + +############################################################################### +# Create plane-surface YZ plane + +surf_yz_plane = graphics.Surfaces["yz-plane"] +surf_yz_plane.definition.type = "plane-surface" +plane_surface_yz = surf_yz_plane.definition.plane_surface +plane_surface_yz.x = -0.174628 +surf_yz_plane.display("window-4") + +############################################################################### +# Create plane-surface ZX plane + +surf_zx_plane = graphics.Surfaces["zx-plane"] +surf_zx_plane.definition.type = "plane-surface" +plane_surface_zx = surf_zx_plane.definition.plane_surface +plane_surface_zx.y = -0.0627297 +surf_zx_plane.display("window-5") + ############################################################################### # Create iso-surface on the outlet plane surf_outlet_plane = graphics.Surfaces["outlet-plane"] -surf_outlet_plane.surface.type = "iso-surface" -iso_surf1 = surf_outlet_plane.surface.iso_surface +surf_outlet_plane.definition.type = "iso-surface" +iso_surf1 = surf_outlet_plane.definition.iso_surface iso_surf1.field = "y-coordinate" iso_surf1.iso_value = -0.125017 surf_outlet_plane.display("window-3") @@ -93,8 +120,8 @@ # Create iso-surface on the mid-plane surf_mid_plane_x = graphics.Surfaces["mid-plane-x"] -surf_mid_plane_x.surface.type = "iso-surface" -iso_surf2 = surf_mid_plane_x.surface.iso_surface +surf_mid_plane_x.definition.type = "iso-surface" +iso_surf2 = surf_mid_plane_x.definition.iso_surface iso_surf2.field = "x-coordinate" iso_surf2.iso_value = -0.174 surf_mid_plane_x.display("window-4") @@ -103,8 +130,8 @@ # Create iso-surface using the velocity magnitude surf_vel_contour = graphics.Surfaces["surf-vel-contour"] -surf_vel_contour.surface.type = "iso-surface" -iso_surf3 = surf_vel_contour.surface.iso_surface +surf_vel_contour.definition.type = "iso-surface" +iso_surf3 = surf_vel_contour.definition.iso_surface iso_surf3.field = "velocity-magnitude" iso_surf3.rendering = "contour" iso_surf3.iso_value = 0.0 @@ -174,7 +201,6 @@ session.solver.tui.solve.initialize.hyb_initialization() session.solver.tui.solve.set.number_of_iterations(50) session.solver.tui.solve.iterate() -session.monitors_manager.get_monitor_set_names() matplotlib_plots1 = Plots(session) mass_bal_rplot = matplotlib_plots1.Monitors["mass-bal-rplot"] mass_bal_rplot.monitor_set_name = "mass-bal-rplot" diff --git a/src/ansys/fluent/visualization/matplotlib/matplot_objects.py b/src/ansys/fluent/visualization/matplotlib/matplot_objects.py index 3bd67a34..13b7c51c 100644 --- a/src/ansys/fluent/visualization/matplotlib/matplot_objects.py +++ b/src/ansys/fluent/visualization/matplotlib/matplot_objects.py @@ -12,7 +12,20 @@ class Plots: - """Plot objects provider.""" + """Matplotlib Plot objects manager. + + It provides access to plot object containers for a given session, + from which plot objects can be created. + It takes session object as argument. Additionally local surface provider + can also be passed to access surfaces created in other modules e.g. pyVista. + + Attributes + ---------- + XYPlots : dict + Container for xyplot objects. + MonitorPlots : dict + Container for monitor plot objects. + """ _sessions_state = {} @@ -54,7 +67,18 @@ def _init_module(self, obj, mod): class XYPlot(XYPlotDefn): - """XY Plot.""" + """XY Plot. + + .. code-block:: python + + from ansys.fluent.visualization.matplotlib import Plots + + matplotlib_plots = Plots(session) + plot1 = matplotlib_plots.XYPlots["plot-1"] + plot1.surfaces_list = ['symmetry', 'wall'] + plot1.y_axis_function = "temperature" + plot1.plot("window-0") + """ def plot(self, window_id: Optional[str] = None): """Draw XYPlot. @@ -68,7 +92,17 @@ def plot(self, window_id: Optional[str] = None): class MonitorPlot(MonitorDefn): - """Monitor Plot.""" + """Monitor Plot. + + .. code-block:: python + + from ansys.fluent.visualization.matplotlib import Plots + + matplotlib_plots = Plots(session) + plot1 = matplotlib_plots.Monitors["plot-1"] + plot1.monitor_set_name = 'residuals' + plot1.plot("window-0") + """ def plot(self, window_id: Optional[str] = None): """Draw Monitor Plot. diff --git a/src/ansys/fluent/visualization/post_data_extractor.py b/src/ansys/fluent/visualization/post_data_extractor.py index fc0a43f8..8b082b89 100644 --- a/src/ansys/fluent/visualization/post_data_extractor.py +++ b/src/ansys/fluent/visualization/post_data_extractor.py @@ -68,11 +68,11 @@ def _fetch_surface_data(self, obj, *args, **kwargs): dummy_object = "dummy_object" post_session = obj._get_top_most_parent() if ( - obj.surface.type() == "iso-surface" - and obj.surface.iso_surface.rendering() == "contour" + obj.definition.type() == "iso-surface" + and obj.definition.iso_surface.rendering() == "contour" ): contour = post_session.Contours[dummy_object] - contour.field = obj.surface.iso_surface.field() + contour.field = obj.definition.iso_surface.field() contour.surfaces_list = [obj._name] contour.show_edges = True contour.range.auto_range_on.global_range = True diff --git a/src/ansys/fluent/visualization/post_helper.py b/src/ansys/fluent/visualization/post_helper.py index e1f0df79..fb20eaf6 100644 --- a/src/ansys/fluent/visualization/post_helper.py +++ b/src/ansys/fluent/visualization/post_helper.py @@ -25,8 +25,8 @@ def _delete_if_exist_on_server(self): self.delete_surface_on_server() def create_surface_on_server(self): - if self.obj.surface.type() == "iso-surface": - iso_surface = self.obj.surface.iso_surface + if self.obj.definition.type() == "iso-surface": + iso_surface = self.obj.definition.iso_surface field = iso_surface.field() iso_value = iso_surface.iso_value() if not field: @@ -62,8 +62,8 @@ def create_surface_on_server(self): (iso_value / unit_info[1]) - unit_info[2], (), ) - elif self.obj.surface.type() == "plane-surface": - plane_surface = self.obj.surface.plane_surface + elif self.obj.definition.type() == "plane-surface": + plane_surface = self.obj.definition.plane_surface xy_plane = plane_surface.xy_plane yz_plane = plane_surface.yz_plane zx_plane = plane_surface.zx_plane diff --git a/src/ansys/fluent/visualization/post_object_defns.py b/src/ansys/fluent/visualization/post_object_defns.py index 2a3864bb..23d3617b 100644 --- a/src/ansys/fluent/visualization/post_object_defns.py +++ b/src/ansys/fluent/visualization/post_object_defns.py @@ -90,12 +90,12 @@ class XYPlotDefn(PlotDefn): PLURAL = "XYPlots" class node_values(metaclass=PyLocalPropertyMeta): - """Show nodal data.""" + """Plot nodal values.""" value: bool = True class boundary_values(metaclass=PyLocalPropertyMeta): - """Show Boundary values.""" + """Plot Boundary values.""" value: bool = True @@ -122,7 +122,7 @@ class x_axis_function(metaclass=PyLocalPropertyMeta): @Attribute def allowed_values(self): """X axis function allowed values.""" - return ["direction-vector", "curve-length"] + return ["direction-vector"] class surfaces_list(metaclass=PyLocalPropertyMeta): """List of surfaces for plotting.""" @@ -138,7 +138,7 @@ def allowed_values(self): class MeshDefn(GraphicsDefn): - """Mesh graphics.""" + """Mesh graphics definition.""" PLURAL = "Meshes" @@ -161,7 +161,7 @@ class show_edges(metaclass=PyLocalPropertyMeta): class SurfaceDefn(GraphicsDefn): - """Surface graphics.""" + """Surface graphics definition.""" PLURAL = "Surfaces" @@ -170,8 +170,8 @@ class show_edges(metaclass=PyLocalPropertyMeta): value: bool = True - class surface(metaclass=PyLocalObjectMeta): - """Specify surface type.""" + class definition(metaclass=PyLocalObjectMeta): + """Specify surface definition type.""" def _availability(self, name): if name == "plane_surface": @@ -191,7 +191,7 @@ def allowed_values(self): return ["plane-surface", "iso-surface"] class plane_surface(metaclass=PyLocalObjectMeta): - """Plane surface data.""" + """Plane surface definition.""" def _availability(self, name): if name == "xy_plane": @@ -213,7 +213,7 @@ def allowed_values(self): return ["xy-plane", "yz-plane", "zx-plane"] class xy_plane(metaclass=PyLocalObjectMeta): - """XY Plane.""" + """XY Plane definition.""" class z(metaclass=PyLocalPropertyMeta): """Z value.""" @@ -228,7 +228,7 @@ def range(self): ) class yz_plane(metaclass=PyLocalObjectMeta): - """YZ Plane.""" + """YZ Plane definition.""" class x(metaclass=PyLocalPropertyMeta): """X value.""" @@ -243,7 +243,7 @@ def range(self): ) class zx_plane(metaclass=PyLocalObjectMeta): - """ZX Plane.""" + """ZX Plane definition.""" class y(metaclass=PyLocalPropertyMeta): """Y value.""" @@ -258,7 +258,7 @@ def range(self): ) class iso_surface(metaclass=PyLocalObjectMeta): - """Iso surface data.""" + """Iso surface definition.""" class field(metaclass=PyLocalPropertyMeta): """Iso surface field.""" @@ -281,7 +281,7 @@ def allowed_values(self): return ["mesh", "contour"] class iso_value(metaclass=PyLocalPropertyMeta): - """Iso surface field iso value.""" + """Iso value for field.""" _value: float @@ -309,7 +309,7 @@ def range(self): class ContourDefn(GraphicsDefn): - """Contour graphics.""" + """Contour graphics definition.""" PLURAL = "Contours" @@ -336,12 +336,12 @@ def allowed_values(self): ) + list(self._get_top_most_parent()._local_surfaces_provider()) class filled(metaclass=PyLocalPropertyMeta): - """Show filled contour.""" + """Draw filled contour.""" value: bool = True class node_values(metaclass=PyLocalPropertyMeta): - """Show nodal data.""" + """Draw nodal data.""" _value: bool = True @@ -359,12 +359,12 @@ def value(self, value): self._value = value class boundary_values(metaclass=PyLocalPropertyMeta): - """Show boundary values.""" + """Draw boundary values.""" value: bool = False class contour_lines(metaclass=PyLocalPropertyMeta): - """Show contour lines.""" + """Draw contour lines.""" value: bool = False @@ -374,7 +374,7 @@ class show_edges(metaclass=PyLocalPropertyMeta): value: bool = False class range(metaclass=PyLocalObjectMeta): - """Specify range options.""" + """Range definition.""" def _availability(self, name): if name == "auto_range_on": @@ -394,7 +394,7 @@ def allowed_values(self): return ["auto-range-on", "auto-range-off"] class auto_range_on(metaclass=PyLocalObjectMeta): - """Specify auto range on.""" + """Auto range on definition.""" class global_range(metaclass=PyLocalPropertyMeta): """Show global range.""" @@ -402,7 +402,7 @@ class global_range(metaclass=PyLocalPropertyMeta): value: bool = False class auto_range_off(metaclass=PyLocalObjectMeta): - """Specify auto range off.""" + """Auto range off definition.""" class clip_to_range(metaclass=PyLocalPropertyMeta): """Clip contour within range.""" @@ -470,7 +470,7 @@ def value(self, value): class VectorDefn(GraphicsDefn): - """Vector graphics.""" + """Vector graphics definition.""" PLURAL = "Vectors" @@ -512,7 +512,7 @@ class show_edges(metaclass=PyLocalPropertyMeta): value: bool = False class range(metaclass=PyLocalObjectMeta): - """Specify range options.""" + """Range definition.""" def _availability(self, name): if name == "auto_range_on": @@ -532,7 +532,7 @@ def allowed_values(self): return ["auto-range-on", "auto-range-off"] class auto_range_on(metaclass=PyLocalObjectMeta): - """Specify auto range on.""" + """Auto range on definition.""" class global_range(metaclass=PyLocalPropertyMeta): """Show global range.""" @@ -540,7 +540,7 @@ class global_range(metaclass=PyLocalPropertyMeta): value: bool = False class auto_range_off(metaclass=PyLocalObjectMeta): - """Specify auto range off.""" + """Auto range off definition.""" class clip_to_range(metaclass=PyLocalPropertyMeta): """Clip vector within range.""" diff --git a/src/ansys/fluent/visualization/pyvista/pyvista_objects.py b/src/ansys/fluent/visualization/pyvista/pyvista_objects.py index c52ea7bf..b4caccaf 100644 --- a/src/ansys/fluent/visualization/pyvista/pyvista_objects.py +++ b/src/ansys/fluent/visualization/pyvista/pyvista_objects.py @@ -18,7 +18,24 @@ class Graphics: - """Graphics objects provider.""" + """PyVista Graphics objects manager. + + It provides access to graphics object containers for a given session, + from which grpahics objects can be created. + It takes session object as argument. Additionally local surface provider + can also be passed to access surfaces created in other modules. + + Attributes + ---------- + Meshes : dict + Container for mesh objects. + Surfaces : dict + Container for surface objects. + Contours : dict + Container for contour objects. + Vectors : dict + Container for vector objects. + """ _sessions_state = {} @@ -84,7 +101,18 @@ def add_outline_mesh(self): class Mesh(MeshDefn): - """Mesh graphics.""" + """Mesh graphics. + + .. code-block:: python + + from ansys.fluent.visualization.pyvista import Graphics + + graphics_session = Graphics(session) + mesh1 = graphics_session.Meshes["mesh-1"] + mesh1.show_edges = True + mesh1.surfaces_list = ['wall'] + mesh1.display("window-0") + """ def display(self, window_id: Optional[str] = None): """Display mesh graphics. @@ -98,7 +126,20 @@ def display(self, window_id: Optional[str] = None): class Surface(SurfaceDefn): - """Surface graphics.""" + """Surface graphics. + + .. code-block:: python + + from ansys.fluent.visualization.pyvista import Graphics + + graphics_session = Graphics(session) + surface1 = graphics_session.Surfaces["surface-1"] + surface1.definition.type = "iso-surface" + surface1.definition.iso_surface.field= "velocity-magnitude" + surface1.definition.iso_surface.rendering= "contour" + surface1.definition.iso_surface.iso_value = 0.0 + surface1.display("window-0") + """ def display(self, window_id: Optional[str] = None): """Display surface graphics. @@ -112,7 +153,18 @@ def display(self, window_id: Optional[str] = None): class Contour(ContourDefn): - """Contour graphics.""" + """Contour graphics. + + .. code-block:: python + + from ansys.fluent.visualization.pyvista import Graphics + + graphics_session = Graphics(session) + contour1 = graphics_session.Contours["contour-1"] + contour1.field = "velocity-magnitude" + contour1.surfaces_list = ['wall'] + contour1.display("window-0") + """ def display(self, window_id: Optional[str] = None): """Display contour graphics. @@ -126,7 +178,19 @@ def display(self, window_id: Optional[str] = None): class Vector(VectorDefn): - """Vector graphics.""" + """Vector graphics. + + .. code-block:: python + + from ansys.fluent.visualization.pyvista import Graphics + + graphics_session = Graphics(session) + vector1 = graphics_session.Vectors["vector-1"] + vector1.surfaces_list = ['symmetry'] + vector1.scale = 4.0 + vector1.skip = 4 + vector1.display("window-0") + """ def display(self, window_id: Optional[str] = None): """Display vector graphics. diff --git a/src/ansys/fluent/visualization/pyvista/pyvista_windows_manager.py b/src/ansys/fluent/visualization/pyvista/pyvista_windows_manager.py index 07f7cddf..32e2f31f 100644 --- a/src/ansys/fluent/visualization/pyvista/pyvista_windows_manager.py +++ b/src/ansys/fluent/visualization/pyvista/pyvista_windows_manager.py @@ -291,11 +291,11 @@ def _display_surface(self, obj, plotter: Union[BackgroundPlotter, pv.Plotter]): dummy_object = "dummy_object" post_session = obj._get_top_most_parent() if ( - obj.surface.type() == "iso-surface" - and obj.surface.iso_surface.rendering() == "contour" + obj.definition.type() == "iso-surface" + and obj.definition.iso_surface.rendering() == "contour" ): contour = post_session.Contours[dummy_object] - contour.field = obj.surface.iso_surface.field() + contour.field = obj.definition.iso_surface.field() contour.surfaces_list = [obj._name] contour.show_edges = True contour.range.auto_range_on.global_range = True diff --git a/tests/test_post.py b/tests/test_post.py index 2c87cbcf..67ba5b22 100644 --- a/tests/test_post.py +++ b/tests/test_post.py @@ -380,17 +380,17 @@ def test_surface_object(): surf1 = pyvista_graphics.Surfaces["surf-1"] field_info = surf1._api_helper.field_info() - surf1.surface.type = "iso-surface" - assert surf1.surface.plane_surface is None - surf1.surface.type = "plane-surface" - assert surf1.surface.iso_surface is None + surf1.definition.type = "iso-surface" + assert surf1.definition.plane_surface is None + surf1.definition.type = "plane-surface" + assert surf1.definition.iso_surface is None - surf1.surface.plane_surface.creation_method = "xy-plane" - assert surf1.surface.plane_surface.yz_plane is None - assert surf1.surface.plane_surface.zx_plane is None + surf1.definition.plane_surface.creation_method = "xy-plane" + assert surf1.definition.plane_surface.yz_plane is None + assert surf1.definition.plane_surface.zx_plane is None - surf1.surface.type = "iso-surface" - iso_surf = surf1.surface.iso_surface + surf1.definition.type = "iso-surface" + iso_surf = surf1.definition.iso_surface assert iso_surf.field.allowed_values == list(field_info.get_fields_info())