diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index cb45d56c..e81643de 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -7,6 +7,7 @@ on: - "*" branches: - main + - release/* concurrency: group: ${{ github.ref }} @@ -191,15 +192,24 @@ jobs: - name: Display package file list run: ls -R - #- name: Upload to Private PyPi - # run: | - # pip install twine - # python -m twine upload --skip-existing ./**/*.whl - # python -m twine upload --skip-existing ./**/*.tar.gz - # env: - # TWINE_USERNAME: PAT - # TWINE_PASSWORD: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} - # TWINE_REPOSITORY_URL: https://pkgs.dev.azure.com/pyansys/_packaging/pyansys/pypi/upload + - name: Upload to Private PyPi + run: | + pip install twine + python -m twine upload --skip-existing ./**/*.whl + python -m twine upload --skip-existing ./**/*.tar.gz + env: + TWINE_USERNAME: PAT + TWINE_PASSWORD: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} + TWINE_REPOSITORY_URL: https://pkgs.dev.azure.com/pyansys/_packaging/pyansys/pypi/upload + + - name: Upload to Public PyPi + run: | + pip install twine + twine upload --skip-existing ./**/*.whl + python -m twine upload --skip-existing ./**/*.tar.gz + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - name: Release uses: softprops/action-gh-release@v1 diff --git a/Makefile b/Makefile index 07fefb0f..9241516e 100644 --- a/Makefile +++ b/Makefile @@ -3,9 +3,7 @@ style: @pre-commit run --all-files --show-diff-on-failure install: - @pip uninstall ansys-api-fluent -y @pip install -r requirements/requirements_build.txt - @pip install install_data/ansys_api_fluent-0.1.0-py3-none-any.whl @python -m build @pip install dist/*.whl --force-reinstall diff --git a/README.rst b/README.rst index 25c296d0..b4ce1a06 100644 --- a/README.rst +++ b/README.rst @@ -42,13 +42,25 @@ Installation The ``ansys-fluent-visualization`` package currently supports Python 3.7 through Python 3.10 on Windows and Linux. -If you want to use PyFluent visualization please install the latest from `PyFluent Visualization GitHub +If you're using Python 3.10, install the vtk package from .whl file +`here in Windows `_ or +`here in Linux `_. + +Install the latest release from `PyPI +`_ with: + +.. code:: console + + pip install ansys-fluent-visualization + +Alternatively, install the latest from `pyfluent-visualization GitHub `_ via: .. code:: console pip install git+https://github.com/pyansys/pyfluent-visualization.git + If you plan on doing local "development" of PyFluent with Git, then install with: @@ -57,7 +69,6 @@ with: git clone https://github.com/pyansys/pyfluent-visualization.git cd pyfluent-visualization pip install pip -U - pip install install_data/ansys_api_fluent-0.1.0-py3-none-any.whl # till public release pip install -e . Dependencies diff --git a/doc/source/api/visualization/matplot_windows_manager.rst b/doc/source/api/visualization/matplot_windows_manager.rst index 545c45fe..42e562f6 100644 --- a/doc/source/api/visualization/matplot_windows_manager.rst +++ b/doc/source/api/visualization/matplot_windows_manager.rst @@ -36,13 +36,13 @@ time step. monitor1.plot("window-2") #Create callback which refreshes window-1 and window-2. - def auto_refersh_plot(session_id, event_info): + def auto_refresh_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) + cb_init_id = session.events_manager.register_callback('InitializedEvent', auto_refresh_plot) + cb_data_read_id = session.events_manager.register_callback('DataReadEvent', auto_refresh_plot) + cb_time_step_ended_id = session.events_manager.register_callback('TimestepEndedEvent', auto_refresh_plot) .. autoclass:: ansys.fluent.visualization.matplotlib.matplot_windows_manager.MatplotWindowsManager diff --git a/doc/source/api/visualization/pyvista_windows_manager.rst b/doc/source/api/visualization/pyvista_windows_manager.rst index 0e3173a4..4b7e4450 100644 --- a/doc/source/api/visualization/pyvista_windows_manager.rst +++ b/doc/source/api/visualization/pyvista_windows_manager.rst @@ -29,13 +29,13 @@ will create animation. contour1.display("window-1") #Create callback which refreshes window-1. - def auto_refersh_contour(session_id, event_info): + def auto_refresh_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) + cb_init_id = session.events_manager.register_callback('InitializedEvent', auto_refresh_contour) + cb_data_read_id = session.events_manager.register_callback('DataReadEvent', auto_refresh_contour) + cb_time_step_ended_id = session.events_manager.register_callback('TimestepEndedEvent', auto_refresh_contour) #Create animation for window-1 pyvista_windows_manager.animate_windows(session.id, ["window-1"]) diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst index b2bb792e..34cd2c8d 100644 --- a/doc/source/contributing.rst +++ b/doc/source/contributing.rst @@ -22,7 +22,6 @@ development mode: git clone https://github.com/pyansys/pyfluent-visualization.git cd pyfluent-visualization pip install pip -U - pip install install_data/ansys_api_fluent-0.1.0-py3-none-any.whl # till public release pip install -e . Building Documentation diff --git a/examples/00-postprocessing/post_processing_exhaust_manifold.py b/examples/00-postprocessing/post_processing_exhaust_manifold.py index 2564f873..2a676748 100644 --- a/examples/00-postprocessing/post_processing_exhaust_manifold.py +++ b/examples/00-postprocessing/post_processing_exhaust_manifold.py @@ -29,7 +29,7 @@ ############################################################################### # First, download the case and data file and start Fluent as a service with -# Meshing mode, double precision, number of processors: 2 +# Solver mode, double precision, number of processors: 2 import_case = examples.download_file( filename="exhaust_system.cas.h5", directory="pyfluent/exhaust_system" diff --git a/install_data/ansys_api_fluent-0.1.0-py3-none-any.whl b/install_data/ansys_api_fluent-0.1.0-py3-none-any.whl deleted file mode 100644 index 319b6546..00000000 Binary files a/install_data/ansys_api_fluent-0.1.0-py3-none-any.whl and /dev/null differ diff --git a/pyproject.toml b/pyproject.toml index d581c9a5..99f90b49 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] # Check https://python-poetry.org/docs/pyproject/ for all available sections name = "ansys-fluent-visualization" -version = "0.3.dev0" +version = "0.4.0" description = "A python wrapper for ansys Fluent visualization" license = "MIT" authors = ["ANSYS, Inc. "] @@ -25,12 +25,8 @@ packages = [ [tool.poetry.dependencies] python = ">=3.7,<4.0" importlib-metadata = {version = "^4.0", python = "<3.8"} -ansys-fluent-core = { git = "https://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@github.com/pyansys/pyfluent.git", branch = "main" } -vtk = [ -{ url = "https://github.com/pyvista/pyvista-wheels/raw/main/vtk-9.1.0.dev0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" , markers = "python_version > '3.9' and sys_platform == 'linux'"}, -{ url = "https://github.com/pyvista/pyvista-wheels/raw/main/vtk-9.1.0.dev0-cp310-cp310-win_amd64.whl" , markers = "python_version > '3.9' and sys_platform != 'linux'"}, -{ version = "9.1.0", python = "<=3.9" }, -] +ansys-fluent-core = "~=0.10" +vtk = {version = "9.1.0", python = "<=3.9"} ipyvtklink = ">=0.2.2" pyvista = ">=0.33.2" pyvistaqt = ">=0.7.0" diff --git a/src/ansys/fluent/visualization/post_data_extractor.py b/src/ansys/fluent/visualization/post_data_extractor.py index 8b082b89..7373d092 100644 --- a/src/ansys/fluent/visualization/post_data_extractor.py +++ b/src/ansys/fluent/visualization/post_data_extractor.py @@ -58,8 +58,12 @@ def _fetch_mesh_data(self, obj, *args, **kwargs): field_data.add_get_surfaces_request(surface_ids, *args, **kwargs) surface_tag = 0 - surfaces_data = field_data.get_fields()[surface_tag] - obj._post_display() + try: + surfaces_data = field_data.get_fields()[surface_tag] + except: + raise RuntimeError("Error while requesting data from server.") + finally: + obj._post_display() return surfaces_data def _fetch_surface_data(self, obj, *args, **kwargs): @@ -127,12 +131,15 @@ def _fetch_contour_data(self, obj, *args, **kwargs): else 0 ) surface_tag = 0 - - scalar_field_payload_data = field_data.get_fields() - data_tag = location_tag | boundary_value_tag - scalar_field_data = scalar_field_payload_data[data_tag] - surface_data = scalar_field_payload_data[surface_tag] - obj._post_display() + try: + scalar_field_payload_data = field_data.get_fields() + data_tag = location_tag | boundary_value_tag + scalar_field_data = scalar_field_payload_data[data_tag] + surface_data = scalar_field_payload_data[surface_tag] + except: + raise RuntimeError("Error while requesting data from server.") + finally: + obj._post_display() return self._merge(surface_data, scalar_field_data) def _fetch_vector_data(self, obj, *args, **kwargs): @@ -155,8 +162,12 @@ def _fetch_vector_data(self, obj, *args, **kwargs): field_data.add_get_surfaces_request(surface_ids, *args, **kwargs) field_data.add_get_vector_fields_request(surface_ids, obj.vectors_of()) vector_field_tag = 0 - fields = field_data.get_fields()[vector_field_tag] - obj._post_display() + try: + fields = field_data.get_fields()[vector_field_tag] + except: + raise RuntimeError("Error while requesting data from server.") + finally: + obj._post_display() return fields def _merge(self, a, b): diff --git a/src/ansys/fluent/visualization/post_helper.py b/src/ansys/fluent/visualization/post_helper.py index fb20eaf6..4401dc5b 100644 --- a/src/ansys/fluent/visualization/post_helper.py +++ b/src/ansys/fluent/visualization/post_helper.py @@ -111,6 +111,13 @@ 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) diff --git a/src/ansys/fluent/visualization/post_object_defns.py b/src/ansys/fluent/visualization/post_object_defns.py index 23d3617b..9a57f100 100644 --- a/src/ansys/fluent/visualization/post_object_defns.py +++ b/src/ansys/fluent/visualization/post_object_defns.py @@ -1,6 +1,7 @@ """Module providing visualization objects definition.""" from abc import abstractmethod from typing import List, NamedTuple, Optional +import warnings from ansys.fluent.core.meta import ( Attribute, @@ -293,7 +294,7 @@ def value(self): """Iso value property setter.""" if getattr(self, "_value", None) is None: range = self.range - self._value = range[0] if range else None + self._value = (range[0] + range[1]) / 2.0 if range else None return self._value @value.setter @@ -351,6 +352,9 @@ def value(self): 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 diff --git a/src/ansys/fluent/visualization/pyvista/pyvista_windows_manager.py b/src/ansys/fluent/visualization/pyvista/pyvista_windows_manager.py index 32e2f31f..d6bf37fb 100644 --- a/src/ansys/fluent/visualization/pyvista/pyvista_windows_manager.py +++ b/src/ansys/fluent/visualization/pyvista/pyvista_windows_manager.py @@ -182,6 +182,8 @@ def _display_vector(self, obj, plotter: Union[BackgroundPlotter, pv.Plotter]): def _display_contour(self, obj, plotter: Union[BackgroundPlotter, pv.Plotter]): # contour properties field = obj.field() + field_unit = obj._api_helper.get_field_unit(field) + field = f"{field}\n[{field_unit}]" if field_unit else field range_option = obj.range.option() filled = obj.filled() contour_lines = obj.contour_lines() @@ -209,9 +211,9 @@ def _display_contour(self, obj, plotter: Union[BackgroundPlotter, pv.Plotter]): faces=surface_data["faces"], ) if node_values: - mesh.point_data[field] = surface_data[field] + mesh.point_data[field] = surface_data[obj.field()] else: - mesh.cell_data[field] = surface_data[field] + mesh.cell_data[field] = surface_data[obj.field()] if range_option == "auto-range-off": auto_range_off = obj.range.auto_range_off if auto_range_off.clip_to_range(): @@ -262,7 +264,7 @@ def _display_contour(self, obj, plotter: Union[BackgroundPlotter, pv.Plotter]): field_info = obj._api_helper.field_info() plotter.add_mesh( mesh, - clim=field_info.get_range(field, False), + clim=field_info.get_range(obj.field(), False), scalars=field, show_edges=obj.show_edges(), scalar_bar_args=scalar_bar_args, @@ -297,14 +299,14 @@ def _display_surface(self, obj, plotter: Union[BackgroundPlotter, pv.Plotter]): contour = post_session.Contours[dummy_object] contour.field = obj.definition.iso_surface.field() contour.surfaces_list = [obj._name] - contour.show_edges = True + contour.show_edges = obj.show_edges() contour.range.auto_range_on.global_range = True self._display_contour(contour, plotter) del post_session.Contours[dummy_object] else: mesh = post_session.Meshes[dummy_object] mesh.surfaces_list = [obj._name] - mesh.show_edges = True + mesh.show_edges = obj.show_edges() self._display_mesh(mesh, plotter) del post_session.Meshes[dummy_object] surface_api.delete_surface_on_server() diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 5c2f24a9..1810b719 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -2,4 +2,4 @@ def test_pkg_version(): - assert __version__ == "0.3.dev0" + assert __version__ == "0.4.0" diff --git a/tests/test_post.py b/tests/test_post.py index 67ba5b22..e3848cf4 100644 --- a/tests/test_post.py +++ b/tests/test_post.py @@ -404,7 +404,7 @@ def test_surface_object(): # Iso surface value should automatically update upon change in field. iso_surf.field = "temperature" range = field_info.get_range(iso_surf.field(), True) - assert range[0] == pytest.approx(iso_surf.iso_value()) + assert (range[0] + range[1]) / 2.0 == pytest.approx(iso_surf.iso_value()) # Setting out of range should throw exception with pytest.raises(ValueError) as value_error: @@ -416,7 +416,7 @@ def test_surface_object(): # Iso surface value should automatically update upon change in field. iso_surf.field = "pressure" range = field_info.get_range(iso_surf.field(), True) - assert range[0] == pytest.approx(iso_surf.iso_value()) + assert (range[0] + range[1]) / 2.0 == pytest.approx(iso_surf.iso_value()) # New surface should be in allowed values for graphics. cont1 = pyvista_graphics.Contours["surf-1"]