From 2edcca1df563077039d8eb74d9b5aae822295caf Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Wed, 7 Dec 2022 12:48:41 +0530 Subject: [PATCH 1/3] Re-factored common post objects from viz to core repo. --- .../fluent/core/post_objects/__init__.py | 0 .../fluent/core/post_objects/post_helper.py | 149 +++++ .../post_objects/post_object_definitions.py | 632 ++++++++++++++++++ .../fluent/core/post_objects/post_objects.py | 156 +++++ 4 files changed, 937 insertions(+) create mode 100644 src/ansys/fluent/core/post_objects/__init__.py create mode 100644 src/ansys/fluent/core/post_objects/post_helper.py create mode 100644 src/ansys/fluent/core/post_objects/post_object_definitions.py create mode 100644 src/ansys/fluent/core/post_objects/post_objects.py diff --git a/src/ansys/fluent/core/post_objects/__init__.py b/src/ansys/fluent/core/post_objects/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/ansys/fluent/core/post_objects/post_helper.py b/src/ansys/fluent/core/post_objects/post_helper.py new file mode 100644 index 000000000000..0dd2e631d70e --- /dev/null +++ b/src/ansys/fluent/core/post_objects/post_helper.py @@ -0,0 +1,149 @@ +import re + + +class PostAPIHelper: + """Class providing helper API for post objects.""" + + class _SurfaceAPI: + """Class providing APIs for surface operations.""" + + def __init__(self, obj): + self.obj = obj + self._surface_name_on_server = self.surface_name_in_server(obj._name) + + @staticmethod + def surface_name_in_server(local_surface_name): + return "_dummy_surface_for_pyfluent:" + local_surface_name.lower() + + def _get_api_handle(self): + return self.obj._get_top_most_parent().session.tui.surface + + def _delete_if_exist_on_server(self): + field_info = self.obj._api_helper.field_info() + surfaces_list = list(field_info.get_surfaces_info().keys()) + if self._surface_name_on_server in surfaces_list: + self.delete_surface_on_server() + + def create_surface_on_server(self): + 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: + raise RuntimeError("Iso surface definition is incomplete.") + self._delete_if_exist_on_server() + phases = self.obj._api_helper._get_phases() + unit_quantity = self.obj._api_helper._field_unit_quantity(field) + unit_info = self.obj._api_helper._fluent_unit_info(unit_quantity) + if phases: + phases = list(filter(field.startswith, phases)) + if phases: + domain, field = ( + field[0 : len(phases[0])], + field[len(phases[0]) + 1 :], + ) + else: + domain = "mixture" + self._get_api_handle().iso_surface( + domain, + field, + self._surface_name_on_server, + (), + (), + (iso_value / unit_info[1]) - unit_info[2], + (), + ) + else: + self._get_api_handle().iso_surface( + field, + self._surface_name_on_server, + (), + (), + (iso_value / unit_info[1]) - unit_info[2], + (), + ) + 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 + self._delete_if_exist_on_server() + unit_info = self.obj._api_helper._fluent_unit_info("length") + self._get_api_handle().plane_surface( + self._surface_name_on_server, + "xy-plane" if xy_plane else "yz-plane" if yz_plane else "zx-plane", + (xy_plane.z() / unit_info[1]) - unit_info[2] + if xy_plane + else (yz_plane.x() / unit_info[1]) - unit_info[2] + if yz_plane + else (zx_plane.y() / unit_info[1]) - unit_info[2], + ) + field_info = self.obj._api_helper.field_info() + surfaces_list = list(field_info.get_surfaces_info().keys()) + if self._surface_name_on_server not in surfaces_list: + raise RuntimeError("Surface creation failed.") + + def delete_surface_on_server(self): + self._get_api_handle().delete_surface(self._surface_name_on_server) + + def __init__(self, obj): + self.obj = obj + self.field_info = lambda: obj._get_top_most_parent().session.field_info + self.field_data = lambda: obj._get_top_most_parent().session.field_data + self.monitors_manager = ( + lambda: obj._get_top_most_parent().session.monitors_manager + ) + self.id = lambda: obj._get_top_most_parent().session.id + if obj.__class__.__name__ == "Surface": + self.surface_api = PostAPIHelper._SurfaceAPI(obj) + + def remote_surface_name(self, local_surface_name): + local_surfaces_provider = ( + self.obj._get_top_most_parent()._local_surfaces_provider() + ) + if local_surface_name in list(local_surfaces_provider): + return PostAPIHelper._SurfaceAPI.surface_name_in_server(local_surface_name) + else: + return local_surface_name + + # Following functions will be deprecated in future. + def get_vector_fields(self): + scheme_eval_str = "(map car (apply append (map client-inquire-cell-vector-functions (inquire-domain-for-cell-functions))))" # noqa: E501 + return self._scheme_str_to_py_list(scheme_eval_str) + + def get_field_unit(self, field): + quantity = self._field_unit_quantity(field) + if quantity == "*null*": + return "" + scheme_eval_str = f"(units/get-pretty-wb-units-from-dimension (units/inquire-dimension '{quantity}))" # noqa: E501 + return " ".join(self._scheme_str_to_py_list(scheme_eval_str)) + + def _get_phases(self): + scheme_eval_str = "(map domain-name (get-phase-domains))" + return self._scheme_str_to_py_list(scheme_eval_str) + + def _field_unit_quantity(self, field): + scheme_eval_str = f"(cdr (assq 'units (%fill-render-info '{field})))" + return self._scheme_str_to_py_list(scheme_eval_str)[0] + + def _fluent_unit_info(self, unit_quantity): + def to_float(number): + try: + return float(number) + except ValueError: + return number + + scheme_eval_str = ( + f"(units/inquire-label-scale-offset-for-quantity '{unit_quantity})" + ) + unit_info = [ + to_float(data) for data in self._scheme_str_to_py_list(scheme_eval_str) + ] + if len(unit_info) == 2: + unit_info.insert(0, "") + return unit_info + + def _scheme_str_to_py_list(self, scheme_eval_str): + session = self.obj._get_top_most_parent().session + str = session.scheme_eval.string_eval(scheme_eval_str) + return list(filter(None, re.split(r'[\s()"\']', str))) diff --git a/src/ansys/fluent/core/post_objects/post_object_definitions.py b/src/ansys/fluent/core/post_objects/post_object_definitions.py new file mode 100644 index 000000000000..07fa46a5d822 --- /dev/null +++ b/src/ansys/fluent/core/post_objects/post_object_definitions.py @@ -0,0 +1,632 @@ +"""Module providing visualization objects definition.""" +from abc import abstractmethod +from typing import List, NamedTuple, Optional +import warnings + +from ansys.fluent.core.meta import ( + Attribute, + PyLocalNamedObjectMetaAbstract, + PyLocalObjectMeta, + PyLocalPropertyMeta, +) + + +class BasePostObjectDefn: + """Base class for visualization objects.""" + + def _pre_display(self): + local_surfaces_provider = self._get_top_most_parent()._local_surfaces_provider() + for surf_name in self.surfaces_list(): + if surf_name in list(local_surfaces_provider): + surf_obj = local_surfaces_provider[surf_name] + surf_api = surf_obj._api_helper.surface_api + surf_api.create_surface_on_server() + + def _post_display(self): + local_surfaces_provider = self._get_top_most_parent()._local_surfaces_provider() + for surf_name in self.surfaces_list(): + if surf_name in list(local_surfaces_provider): + surf_obj = local_surfaces_provider[surf_name] + surf_api = surf_obj._api_helper.surface_api + surf_api.delete_surface_on_server() + + +class GraphicsDefn(BasePostObjectDefn, metaclass=PyLocalNamedObjectMetaAbstract): + """Abstract base class for graphics objects.""" + + @abstractmethod + def display(self, plotter_id: Optional[str] = None): + """Display graphics. + + Parameters + ---------- + window_id : str, optional + Window id. If not specified unique id is used. + """ + pass + + +class PlotDefn(BasePostObjectDefn, metaclass=PyLocalNamedObjectMetaAbstract): + """Abstract base class for plot objects.""" + + @abstractmethod + def plot(self, plotter_id: Optional[str] = None): + """Draw plot. + + Parameters + ---------- + window_id : str, optional + Window id. If not specified unique id is used. + """ + pass + + +class Vector(NamedTuple): + """Class for vector definition.""" + + x: float + y: float + z: float + + +class MonitorDefn(PlotDefn): + """Monitor Definition.""" + + PLURAL = "Monitors" + + class monitor_set_name(metaclass=PyLocalPropertyMeta): + """Monitor set name.""" + + value: str + + @Attribute + def allowed_values(self): + """Monitor set allowed values.""" + return self._api_helper.monitors_manager().get_monitor_set_names() + + +class XYPlotDefn(PlotDefn): + """XYPlot Definition.""" + + PLURAL = "XYPlots" + + class node_values(metaclass=PyLocalPropertyMeta): + """Plot nodal values.""" + + value: bool = True + + class boundary_values(metaclass=PyLocalPropertyMeta): + """Plot Boundary values.""" + + value: bool = True + + class direction_vector(metaclass=PyLocalPropertyMeta): + """Direction Vector.""" + + value: Vector = [1, 0, 0] + + class y_axis_function(metaclass=PyLocalPropertyMeta): + """Y Axis Function.""" + + value: str + + @Attribute + def allowed_values(self): + """Y axis function allowed values.""" + return list(self._api_helper.field_info().get_fields_info()) + + class x_axis_function(metaclass=PyLocalPropertyMeta): + """X Axis Function.""" + + value: str = "direction-vector" + + @Attribute + def allowed_values(self): + """X axis function allowed values.""" + return ["direction-vector"] + + class surfaces_list(metaclass=PyLocalPropertyMeta): + """List of surfaces for plotting.""" + + value: List[str] + + @Attribute + def allowed_values(self): + """Surface list allowed values.""" + return list( + self._api_helper.field_info().get_surfaces_info().keys() + ) + list(self._get_top_most_parent()._local_surfaces_provider()) + + +class MeshDefn(GraphicsDefn): + """Mesh graphics definition.""" + + PLURAL = "Meshes" + + class surfaces_list(metaclass=PyLocalPropertyMeta): + """List of surfaces for mesh graphics.""" + + value: List[str] + + @Attribute + def allowed_values(self): + """Surface list allowed values.""" + return list( + (self._api_helper.field_info().get_surfaces_info().keys()) + ) + list(self._get_top_most_parent()._local_surfaces_provider()) + + class show_edges(metaclass=PyLocalPropertyMeta): + """Show edges for mesh.""" + + value: bool = False + + +class PathlinesDefn(GraphicsDefn): + """Pathlines definition.""" + + PLURAL = "Pathlines" + + class field(metaclass=PyLocalPropertyMeta): + """Pathlines field.""" + + value: str + + @Attribute + def allowed_values(self): + """Field allowed values.""" + return list(self._api_helper.field_info().get_fields_info()) + + class surfaces_list(metaclass=PyLocalPropertyMeta): + """List of surfaces for pathlines.""" + + value: List[str] + + @Attribute + def allowed_values(self): + """Surface list allowed values.""" + return list( + (self._api_helper.field_info().get_surfaces_info().keys()) + ) + list(self._get_top_most_parent()._local_surfaces_provider()) + + +class SurfaceDefn(GraphicsDefn): + """Surface graphics definition.""" + + PLURAL = "Surfaces" + + class show_edges(metaclass=PyLocalPropertyMeta): + """Show edges for surface.""" + + value: bool = True + + class definition(metaclass=PyLocalObjectMeta): + """Specify surface definition type.""" + + def _availability(self, name): + if name == "plane_surface": + return self.type() == "plane-surface" + if name == "iso_surface": + return self.type() == "iso-surface" + return True + + class type(metaclass=PyLocalPropertyMeta): + """Surface type.""" + + value: str = "iso-surface" + + @Attribute + def allowed_values(self): + """Surface type allowed values.""" + return ["plane-surface", "iso-surface"] + + class plane_surface(metaclass=PyLocalObjectMeta): + """Plane surface definition.""" + + def _availability(self, name): + if name == "xy_plane": + return self.creation_method() == "xy-plane" + if name == "yz_plane": + return self.creation_method() == "yz-plane" + if name == "zx_plane": + return self.creation_method() == "zx-plane" + return True + + class creation_method(metaclass=PyLocalPropertyMeta): + """Creation Method.""" + + value: str = "xy-plane" + + @Attribute + def allowed_values(self): + """Surface type allowed values.""" + return ["xy-plane", "yz-plane", "zx-plane"] + + class xy_plane(metaclass=PyLocalObjectMeta): + """XY Plane definition.""" + + class z(metaclass=PyLocalPropertyMeta): + """Z value.""" + + value: float = 0 + + @Attribute + def range(self): + """Z value range.""" + return self._api_helper.field_info().get_range( + "z-coordinate", True + ) + + class yz_plane(metaclass=PyLocalObjectMeta): + """YZ Plane definition.""" + + class x(metaclass=PyLocalPropertyMeta): + """X value.""" + + value: float = 0 + + @Attribute + def range(self): + """X value range.""" + return self._api_helper.field_info().get_range( + "x-coordinate", True + ) + + class zx_plane(metaclass=PyLocalObjectMeta): + """ZX Plane definition.""" + + class y(metaclass=PyLocalPropertyMeta): + """Y value.""" + + value: float = 0 + + @Attribute + def range(self): + """Y value range.""" + return self._api_helper.field_info().get_range( + "y-coordinate", True + ) + + class iso_surface(metaclass=PyLocalObjectMeta): + """Iso surface definition.""" + + class field(metaclass=PyLocalPropertyMeta): + """Iso surface field.""" + + value: str + + @Attribute + def allowed_values(self): + """Field allowed values.""" + return list(self._api_helper.field_info().get_fields_info()) + + class rendering(metaclass=PyLocalPropertyMeta): + """Iso surface rendering.""" + + value: str = "mesh" + + @Attribute + def allowed_values(self): + """Surface rendering allowed values.""" + return ["mesh", "contour"] + + class iso_value(metaclass=PyLocalPropertyMeta): + """Iso value for field.""" + + _value: float + + def _reset_on_change(self): + return [self._parent.field] + + @property + def value(self): + """Iso value property setter.""" + if getattr(self, "_value", None) is None: + range = self.range + self._value = (range[0] + range[1]) / 2.0 if range else None + return self._value + + @value.setter + def value(self, value): + self._value = value + + @Attribute + def range(self): + """Iso value range.""" + field = self._parent.field() + if field: + return self._api_helper.field_info().get_range(field, True) + + +class ContourDefn(GraphicsDefn): + """Contour graphics definition.""" + + PLURAL = "Contours" + + class field(metaclass=PyLocalPropertyMeta): + """Contour field.""" + + value: str + + @Attribute + def allowed_values(self): + """Field allowed values.""" + return list(self._api_helper.field_info().get_fields_info()) + + class surfaces_list(metaclass=PyLocalPropertyMeta): + """Contour surfaces.""" + + value: List[str] + + @Attribute + def allowed_values(self): + """Surfaces list allowed values.""" + return list( + self._api_helper.field_info().get_surfaces_info().keys() + ) + list(self._get_top_most_parent()._local_surfaces_provider()) + + class filled(metaclass=PyLocalPropertyMeta): + """Draw filled contour.""" + + value: bool = True + + class node_values(metaclass=PyLocalPropertyMeta): + """Draw nodal data.""" + + _value: bool = True + + @property + def value(self): + """Node value property setter.""" + filled = self._get_parent_by_type(ContourDefn).filled() + auto_range_off = self._get_parent_by_type(ContourDefn).range.auto_range_off + if not filled or (auto_range_off and auto_range_off.clip_to_range()): + warnings.warn( + "For unfilled and clipped contours node values are diaplyed." + ) + self._value = True + return self._value + + @value.setter + def value(self, value): + self._value = value + + class boundary_values(metaclass=PyLocalPropertyMeta): + """Draw boundary values.""" + + value: bool = False + + class contour_lines(metaclass=PyLocalPropertyMeta): + """Draw contour lines.""" + + value: bool = False + + class show_edges(metaclass=PyLocalPropertyMeta): + """Show edges.""" + + value: bool = False + + class range(metaclass=PyLocalObjectMeta): + """Range definition.""" + + def _availability(self, name): + if name == "auto_range_on": + return self.option() == "auto-range-on" + if name == "auto_range_off": + return self.option() == "auto-range-off" + return True + + class option(metaclass=PyLocalPropertyMeta): + """Range option.""" + + value: str = "auto-range-on" + + @Attribute + def allowed_values(self): + """Range option allowed values.""" + return ["auto-range-on", "auto-range-off"] + + class auto_range_on(metaclass=PyLocalObjectMeta): + """Auto range on definition.""" + + class global_range(metaclass=PyLocalPropertyMeta): + """Show global range.""" + + value: bool = False + + class auto_range_off(metaclass=PyLocalObjectMeta): + """Auto range off definition.""" + + class clip_to_range(metaclass=PyLocalPropertyMeta): + """Clip contour within range.""" + + value: bool = False + + class minimum(metaclass=PyLocalPropertyMeta): + """Range minimum.""" + + _value: float + + def _reset_on_change(self): + return [ + self._get_parent_by_type(ContourDefn).field, + self._get_parent_by_type(ContourDefn).node_values, + ] + + @property + def value(self): + """Range minimum property setter.""" + if getattr(self, "_value", None) is None: + field = self._get_parent_by_type(ContourDefn).field() + if field: + field_info = self._api_helper.field_info() + field_range = field_info.get_range( + field, + self._get_parent_by_type(ContourDefn).node_values(), + ) + self._value = field_range[0] + return self._value + + @value.setter + def value(self, value): + self._value = value + + class maximum(metaclass=PyLocalPropertyMeta): + """Range maximum.""" + + _value: float + + def _reset_on_change(self): + return [ + self._get_parent_by_type(ContourDefn).field, + self._get_parent_by_type(ContourDefn).node_values, + ] + + @property + def value(self): + """Range maximum property setter.""" + if getattr(self, "_value", None) is None: + field = self._get_parent_by_type(ContourDefn).field() + if field: + field_info = self._api_helper.field_info() + field_range = field_info.get_range( + field, + self._get_parent_by_type(ContourDefn).node_values(), + ) + self._value = field_range[1] + + return self._value + + @value.setter + def value(self, value): + self._value = value + + +class VectorDefn(GraphicsDefn): + """Vector graphics definition.""" + + PLURAL = "Vectors" + + class vectors_of(metaclass=PyLocalPropertyMeta): + """Vector type.""" + + value: str = "velocity" + + @Attribute + def allowed_values(self): + """Vectors of allowed values.""" + return list(self._api_helper.get_vector_fields()) + + class field(metaclass=PyLocalPropertyMeta): + """Vector color field.""" + + value: str + + @Attribute + def allowed_values(self): + """Field allowed values.""" + return list(self._api_helper.field_info().get_fields_info()) + + class surfaces_list(metaclass=PyLocalPropertyMeta): + """List of surfaces for vector graphics.""" + + value: List[str] + + @Attribute + def allowed_values(self): + """Surface list allowed values.""" + return list( + self._api_helper.field_info().get_surfaces_info().keys() + ) + list(self._get_top_most_parent()._local_surfaces_provider()) + + class scale(metaclass=PyLocalPropertyMeta): + """Vector scale.""" + + value: float = 1.0 + + class skip(metaclass=PyLocalPropertyMeta): + """Vector skip.""" + + value: int = 0 + + class show_edges(metaclass=PyLocalPropertyMeta): + """Show edges.""" + + value: bool = False + + class range(metaclass=PyLocalObjectMeta): + """Range definition.""" + + def _availability(self, name): + if name == "auto_range_on": + return self.option() == "auto-range-on" + if name == "auto_range_off": + return self.option() == "auto-range-off" + return True + + class option(metaclass=PyLocalPropertyMeta): + """Range option.""" + + value: str = "auto-range-on" + + @Attribute + def allowed_values(self): + """Range option allowed values.""" + return ["auto-range-on", "auto-range-off"] + + class auto_range_on(metaclass=PyLocalObjectMeta): + """Auto range on definition.""" + + class global_range(metaclass=PyLocalPropertyMeta): + """Show global range.""" + + value: bool = False + + class auto_range_off(metaclass=PyLocalObjectMeta): + """Auto range off definition.""" + + class clip_to_range(metaclass=PyLocalPropertyMeta): + """Clip vector within range.""" + + value: bool = False + + class minimum(metaclass=PyLocalPropertyMeta): + """Range minimum.""" + + _value: float + + @property + def value(self): + """Range minimum property setter.""" + if getattr(self, "_value", None) is None: + field_info = self._api_helper.field_info() + field_range = field_info.get_range( + "velocity-magnitude", + False, + ) + self._value = field_range[0] + return self._value + + @value.setter + def value(self, value): + self._value = value + + class maximum(metaclass=PyLocalPropertyMeta): + """Range maximum.""" + + _value: float + + @property + def value(self): + """Range maximum property setter.""" + if getattr(self, "_value", None) is None: + field_info = self._api_helper.field_info() + field_range = field_info.get_range( + "velocity-magnitude", + False, + ) + self._value = field_range[1] + return self._value + + @value.setter + def value(self, value): + self._value = value diff --git a/src/ansys/fluent/core/post_objects/post_objects.py b/src/ansys/fluent/core/post_objects/post_objects.py new file mode 100644 index 000000000000..4b2c1f618c55 --- /dev/null +++ b/src/ansys/fluent/core/post_objects/post_objects.py @@ -0,0 +1,156 @@ +"""Module providing visualization objects for Matplotlib.""" +import inspect +import sys + +from ansys.fluent.core.meta import PyLocalContainer + + +class Plots: + """Provides the Matplotlib ``Plots`` objects manager. + + This class provides access to ``Plots`` object containers for a given + session so that plots can be created. + + Parameters + ---------- + session : obj + Session object. + local_surfaces_provider : object, optional + Object providing local surfaces so that you can access surfaces + created in other modules, such as PyVista. The default is ``None``. + + Attributes + ---------- + XYPlots : dict + Container for XY plot objects. + MonitorPlots : dict + Container for monitor plot objects. + """ + + _sessions_state = {} + + def __init__(self, session, local_surfaces_provider=None): + """Instantiate Plots, container of plot objects. + + Parameters + ---------- + session : + Session object. + local_surfaces_provider : object, optional + Object providing local surfaces. + """ + session_state = Plots._sessions_state.get(session.id if session else 1) + if not session_state: + session_state = self.__dict__ + Plots._sessions_state[session.id if session else 1] = session_state + self.session = session + self._init_module(self, sys.modules[__name__]) + else: + self.__dict__ = session_state + self._local_surfaces_provider = lambda: local_surfaces_provider or getattr( + self, "Surfaces", [] + ) + + def _init_module(self, obj, mod): + from ansys.fluent.core.graphics.post_helper import PostAPIHelper + + for name, cls in mod.__dict__.items(): + + if cls.__class__.__name__ in ( + "PyLocalNamedObjectMetaAbstract", + ) and not inspect.isabstract(cls): + setattr( + obj, + cls.PLURAL, + PyLocalContainer(self, cls, PostAPIHelper), + ) + + +class Graphics: + """Provides the PyVista ``Graphics`` objects manager. + + This class provides access to ``Graphics`` object containers for a given + session so that graphics objects can be created. + + Parameters + ---------- + session : obj + Session object. + local_surfaces_provider : object, optional + Object providing local surfaces so that you can access surfaces + created in other modules, such as PyVista. The default is ``None``. + + 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 = {} + + def __init__(self, session, local_surfaces_provider=None): + """Instantiate the ``Graphics`` object container. + + Parameters + ---------- + session : obj + Session object. + local_surfaces_provider : object, optional + Object providing local surfaces so that you can access surfaces + created in other modules, such as PyVista. The default is ``None``. + """ + session_state = Graphics._sessions_state.get(session.id if session else 1) + if not session_state: + session_state = self.__dict__ + Graphics._sessions_state[session.id if session else 1] = session_state + self.session = session + self._init_module(self, sys.modules[__name__]) + else: + self.__dict__ = session_state + self._local_surfaces_provider = lambda: local_surfaces_provider or getattr( + self, "Surfaces", [] + ) + + def _init_module(self, obj, mod): + from ansys.fluent.core.graphics.post_helper import PostAPIHelper + + for name, cls in mod.__dict__.items(): + + if cls.__class__.__name__ in ( + "PyLocalNamedObjectMetaAbstract", + ) and not inspect.isabstract(cls): + setattr( + obj, + cls.PLURAL, + PyLocalContainer(self, cls, PostAPIHelper), + ) + + def add_outline_mesh(self): + """Add a mesh outline. + + Parameters + ---------- + None + + Returns + ------- + None + """ + meshes = getattr(self, "Meshes", None) + if meshes is not None: + outline_mesh_id = "Mesh-outline" + outline_mesh = meshes[outline_mesh_id] + outline_mesh.surfaces_list = [ + k + for k, v in outline_mesh._api_helper.field_info() + .get_surfaces_info() + .items() + if v["type"] == "zone-surf" and v["zone_type"] != "interior" + ] + return outline_mesh From 24490e8b4760ce5ea0899aa2bda8122b6429f954 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Wed, 7 Dec 2022 16:02:28 +0530 Subject: [PATCH 2/3] Renamed post_objects -> post_objects_container. --- src/ansys/fluent/core/post_objects/post_helper.py | 6 +++--- .../{post_objects.py => post_objects_container.py} | 13 ++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) rename src/ansys/fluent/core/post_objects/{post_objects.py => post_objects_container.py} (91%) diff --git a/src/ansys/fluent/core/post_objects/post_helper.py b/src/ansys/fluent/core/post_objects/post_helper.py index 0dd2e631d70e..4bfc893ae491 100644 --- a/src/ansys/fluent/core/post_objects/post_helper.py +++ b/src/ansys/fluent/core/post_objects/post_helper.py @@ -9,10 +9,10 @@ class _SurfaceAPI: def __init__(self, obj): self.obj = obj - self._surface_name_on_server = self.surface_name_in_server(obj._name) + self._surface_name_on_server = self.surface_name_on_server(obj._name) @staticmethod - def surface_name_in_server(local_surface_name): + def surface_name_on_server(local_surface_name): return "_dummy_surface_for_pyfluent:" + local_surface_name.lower() def _get_api_handle(self): @@ -102,7 +102,7 @@ def remote_surface_name(self, local_surface_name): self.obj._get_top_most_parent()._local_surfaces_provider() ) if local_surface_name in list(local_surfaces_provider): - return PostAPIHelper._SurfaceAPI.surface_name_in_server(local_surface_name) + return PostAPIHelper._SurfaceAPI.surface_name_on_server(local_surface_name) else: return local_surface_name diff --git a/src/ansys/fluent/core/post_objects/post_objects.py b/src/ansys/fluent/core/post_objects/post_objects_container.py similarity index 91% rename from src/ansys/fluent/core/post_objects/post_objects.py rename to src/ansys/fluent/core/post_objects/post_objects_container.py index 4b2c1f618c55..5c5d4515d136 100644 --- a/src/ansys/fluent/core/post_objects/post_objects.py +++ b/src/ansys/fluent/core/post_objects/post_objects_container.py @@ -1,6 +1,5 @@ """Module providing visualization objects for Matplotlib.""" import inspect -import sys from ansys.fluent.core.meta import PyLocalContainer @@ -29,7 +28,7 @@ class Plots: _sessions_state = {} - def __init__(self, session, local_surfaces_provider=None): + def __init__(self, session, module, local_surfaces_provider=None): """Instantiate Plots, container of plot objects. Parameters @@ -44,7 +43,7 @@ def __init__(self, session, local_surfaces_provider=None): session_state = self.__dict__ Plots._sessions_state[session.id if session else 1] = session_state self.session = session - self._init_module(self, sys.modules[__name__]) + self._init_module(self, module) else: self.__dict__ = session_state self._local_surfaces_provider = lambda: local_surfaces_provider or getattr( @@ -52,7 +51,7 @@ def __init__(self, session, local_surfaces_provider=None): ) def _init_module(self, obj, mod): - from ansys.fluent.core.graphics.post_helper import PostAPIHelper + from ansys.fluent.core.post_objects.post_helper import PostAPIHelper for name, cls in mod.__dict__.items(): @@ -94,7 +93,7 @@ class Graphics: _sessions_state = {} - def __init__(self, session, local_surfaces_provider=None): + def __init__(self, session, module, local_surfaces_provider=None): """Instantiate the ``Graphics`` object container. Parameters @@ -110,7 +109,7 @@ def __init__(self, session, local_surfaces_provider=None): session_state = self.__dict__ Graphics._sessions_state[session.id if session else 1] = session_state self.session = session - self._init_module(self, sys.modules[__name__]) + self._init_module(self, module) else: self.__dict__ = session_state self._local_surfaces_provider = lambda: local_surfaces_provider or getattr( @@ -118,7 +117,7 @@ def __init__(self, session, local_surfaces_provider=None): ) def _init_module(self, obj, mod): - from ansys.fluent.core.graphics.post_helper import PostAPIHelper + from ansys.fluent.core.post_objects.post_helper import PostAPIHelper for name, cls in mod.__dict__.items(): From c75852dff368d934dd6fb9f5211e36f2e510888b Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Wed, 7 Dec 2022 17:23:34 +0530 Subject: [PATCH 3/3] Re-structured --- .../post_objects/post_objects_container.py | 97 +++++++------------ 1 file changed, 34 insertions(+), 63 deletions(-) diff --git a/src/ansys/fluent/core/post_objects/post_objects_container.py b/src/ansys/fluent/core/post_objects/post_objects_container.py index 5c5d4515d136..64e19658cb8f 100644 --- a/src/ansys/fluent/core/post_objects/post_objects_container.py +++ b/src/ansys/fluent/core/post_objects/post_objects_container.py @@ -4,31 +4,8 @@ from ansys.fluent.core.meta import PyLocalContainer -class Plots: - """Provides the Matplotlib ``Plots`` objects manager. - - This class provides access to ``Plots`` object containers for a given - session so that plots can be created. - - Parameters - ---------- - session : obj - Session object. - local_surfaces_provider : object, optional - Object providing local surfaces so that you can access surfaces - created in other modules, such as PyVista. The default is ``None``. - - Attributes - ---------- - XYPlots : dict - Container for XY plot objects. - MonitorPlots : dict - Container for monitor plot objects. - """ - - _sessions_state = {} - - def __init__(self, session, module, local_surfaces_provider=None): +class Container: + def __init__(self, session, child, module, local_surfaces_provider=None): """Instantiate Plots, container of plot objects. Parameters @@ -38,10 +15,10 @@ def __init__(self, session, module, local_surfaces_provider=None): local_surfaces_provider : object, optional Object providing local surfaces. """ - session_state = Plots._sessions_state.get(session.id if session else 1) + session_state = child._sessions_state.get(session.id if session else 1) if not session_state: session_state = self.__dict__ - Plots._sessions_state[session.id if session else 1] = session_state + child._sessions_state[session.id if session else 1] = session_state self.session = session self._init_module(self, module) else: @@ -65,7 +42,35 @@ def _init_module(self, obj, mod): ) -class Graphics: +class Plots(Container): + """Provides the Matplotlib ``Plots`` objects manager. + + This class provides access to ``Plots`` object containers for a given + session so that plots can be created. + + Parameters + ---------- + session : obj + Session object. + local_surfaces_provider : object, optional + Object providing local surfaces so that you can access surfaces + created in other modules, such as PyVista. The default is ``None``. + + Attributes + ---------- + XYPlots : dict + Container for XY plot objects. + MonitorPlots : dict + Container for monitor plot objects. + """ + + _sessions_state = {} + + def __init__(self, session, module, local_surfaces_provider=None): + super().__init__(session, self.__class__, module, local_surfaces_provider) + + +class Graphics(Container): """Provides the PyVista ``Graphics`` objects manager. This class provides access to ``Graphics`` object containers for a given @@ -94,41 +99,7 @@ class Graphics: _sessions_state = {} def __init__(self, session, module, local_surfaces_provider=None): - """Instantiate the ``Graphics`` object container. - - Parameters - ---------- - session : obj - Session object. - local_surfaces_provider : object, optional - Object providing local surfaces so that you can access surfaces - created in other modules, such as PyVista. The default is ``None``. - """ - session_state = Graphics._sessions_state.get(session.id if session else 1) - if not session_state: - session_state = self.__dict__ - Graphics._sessions_state[session.id if session else 1] = session_state - self.session = session - self._init_module(self, module) - else: - self.__dict__ = session_state - self._local_surfaces_provider = lambda: local_surfaces_provider or getattr( - self, "Surfaces", [] - ) - - def _init_module(self, obj, mod): - from ansys.fluent.core.post_objects.post_helper import PostAPIHelper - - for name, cls in mod.__dict__.items(): - - if cls.__class__.__name__ in ( - "PyLocalNamedObjectMetaAbstract", - ) and not inspect.isabstract(cls): - setattr( - obj, - cls.PLURAL, - PyLocalContainer(self, cls, PostAPIHelper), - ) + super().__init__(session, self.__class__, module, local_surfaces_provider) def add_outline_mesh(self): """Add a mesh outline.