From 719573b56796d05d29f5648e80432fbf7c28b1e7 Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Wed, 20 Nov 2024 13:54:41 +0100 Subject: [PATCH 01/15] add animate_data.rst tutorial --- .../tutorials/animate/animate_data.rst | 20 +++++++++++++++++++ .../user_guide/tutorials/animate/index.rst | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 doc/source/user_guide/tutorials/animate/animate_data.rst diff --git a/doc/source/user_guide/tutorials/animate/animate_data.rst b/doc/source/user_guide/tutorials/animate/animate_data.rst new file mode 100644 index 00000000000..01bc9d64d63 --- /dev/null +++ b/doc/source/user_guide/tutorials/animate/animate_data.rst @@ -0,0 +1,20 @@ +.. _ref_tutorials_animate_data: + +============ +Animate data +============ + +.. |Field| replace:: :class:`Field` +.. |FieldsContainer| replace:: :class:`FieldsContainer` +.. |Fields| replace:: :class:`Fields` +.. |FieldsContainers| replace:: :class:`FieldsContainers` + + +This tutorial shows how to animate your results data. + +The data in DPF is stored in |Fields| or |FieldsContainers| + +Get the results file +-------------------- + + diff --git a/doc/source/user_guide/tutorials/animate/index.rst b/doc/source/user_guide/tutorials/animate/index.rst index 2bfa5b2f4e5..de075ed98ac 100644 --- a/doc/source/user_guide/tutorials/animate/index.rst +++ b/doc/source/user_guide/tutorials/animate/index.rst @@ -16,9 +16,10 @@ These tutorials demonstrate how to visualise the data in an animation. :link-type: ref :text-align: center - This tutorial + This tutorial shows how to animate your results data. .. toctree:: :maxdepth: 2 :hidden: + animate_data.rst From 6bb092a1be5c8a63d459caef73c30cdc576b3a5a Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Wed, 20 Nov 2024 17:49:13 +0100 Subject: [PATCH 02/15] completes the animate_data.rst tutorial --- .../tutorials/animate/animate_data.rst | 489 +++++++++++++++++- .../user_guide/tutorials/animate/index.rst | 5 +- 2 files changed, 490 insertions(+), 4 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_data.rst b/doc/source/user_guide/tutorials/animate/animate_data.rst index 01bc9d64d63..2afda29fb21 100644 --- a/doc/source/user_guide/tutorials/animate/animate_data.rst +++ b/doc/source/user_guide/tutorials/animate/animate_data.rst @@ -4,17 +4,500 @@ Animate data ============ +:bdg-warning:`MAPDL` :bdg-success:`LSDYNA` + .. |Field| replace:: :class:`Field` .. |FieldsContainer| replace:: :class:`FieldsContainer` .. |Fields| replace:: :class:`Fields` .. |FieldsContainers| replace:: :class:`FieldsContainers` - +.. |MeshedRegion| replace:: :class:`MeshedRegion ` +.. |TimeFreqSupport| replace:: :class:`TimeFreqSupport ` +.. |animate| replace:: :func:`animate() ` +.. |Result| replace:: :class:`Result ` +.. |Operator| replace:: :class:`Operator` This tutorial shows how to animate your results data. -The data in DPF is stored in |Fields| or |FieldsContainers| +To animate a result you need to get the data stored in a |FieldsContainer| labeled in time steps. -Get the results file +Get the result files -------------------- +Here we we will download a result file available in our `Examples` package. +For more information about how to import your result file in DPF check +the :ref:`ref_tutorials_import_data` tutorial section. + +.. tab-set:: + + .. tab-item:: MAPDL + + + .. code-block:: python + + # Import the ``ansys.dpf.core`` module, including examples files and the operators subpackage + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + # Define the result file + result_file_path_1 = examples.find_msup_transient() + # Create the model + my_model_1 = dpf.Model(data_sources=result_file_path_1) + # Get the mesh + my_meshed_region_1 = my_model_1.metadata.meshed_region + + .. tab-item:: LSDYNA + + .. code-block:: python + + # Import the ``ansys.dpf.core`` module, including examples files and the operators subpackage + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + # Define the result file + result_file_path_2 = examples.download_d3plot_beam() + # Create the DataSources object + my_data_sources_2 = dpf.DataSources() + my_data_sources_2.set_result_file_path(filepath=result_file_path_2[0], key="d3plot") + my_data_sources_2.add_file_path(filepath=result_file_path_2[3], key="actunits") + # Create the model + my_model_2 = dpf.Model(data_sources=my_data_sources_2) + +Define time and mesh scopings +----------------------------- + +Here we get all the the time steps of the |TimeFreqSupport| and all the |MeshedRegion| with results in a ``Nodal`` +location (only elemental, nodal or faces location are supported for the animation). +For more information on how to define a scoping check the ``Narrow down data`` tutorial in the :ref:`ref_tutorials_import_data` +tutorials section. + +.. tab-set:: + + .. tab-item:: MAPDL + + .. code-block:: python + + # Get all the time steps + time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies + # Get all the mesh in a nodal location + mesh_scoping_1 = dpf.Scoping(ids=my_meshed_region_1.nodes.scoping.ids, location=dpf.locations.nodal) + + .. tab-item:: LSDYNA + + .. code-block:: python + + # Get all the time steps + time_scoping_2 = my_model_2.metadata.time_freq_support.time_frequencies + +Extract the results +------------------- + +You have to extracted the results of interest. + +When you animate the data you go through the |Fields| of a |FieldsContainer| and plot contours of +the data norm or of the selected data component. This means that the geometry needs to be deformed +based on the |Fields| themselves. + +The geometry can be deformed by a |Result| object, an |Operator| (It must evaluate to a FieldsContainer +of same length as the one being animated), a |Field| or a |FieldsContainer|. + +To deform the geometry we need a result with a homogeneous unit dimension, thus, a distance unit. +Thus, to deform the mesh we need the displacement result. +For more information see: :ref:`ref_plotting_data_on_deformed_mesh` + +Here we get: + +- The displacement results and the stress result for the MAPDL result file +- The displacement results and the beam axial force result for the LSDYNA result file + +.. tab-set:: + + .. tab-item:: MAPDL + + .. code-block:: python + + # Get the displacement results + my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1, + mesh_scoping=mesh_scoping_1).eval() + # Get the stress results + my_stress_1 = my_model_1.results.stress(time_scoping=time_scoping_1, + mesh_scoping=mesh_scoping_1).eval() + + .. tab-item:: LSDYNA + + .. code-block:: python + + # Get the displacement results + my_disp_2 = my_model_2.results.displacement(time_scoping=time_scoping_2.eval() + # Get the stress results + my_beam_axial_force_2 = my_model_2.results.beam_axial_force(time_scoping=time_scoping_2).eval() + +Animate the results +------------------- + +You animate a |FieldsContainer| by using the |animate| method. + +The default behavior consists in: + +- Using a constant and uniform scale factor of 1.0 +- Showing the deformed geometry if the method was used directly with the displacement fields. +- Showing the static geometry if the method was used with other results fields. + +Animate the displacement results +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Use the |animate| method with no arguments to get the default animation to the displacement results. + +.. tab-set:: + + .. tab-item:: MAPDL + + .. code-block:: python + + # Animate the displacement results + my_disp_1.animate() + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + result_file_path_1 = examples.find_msup_transient() + my_model_1 = dpf.Model(data_sources=result_file_path_1) + my_meshed_region_1 = my_model_1.metadata.meshed_region + time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies + mesh_scoping_1 = dpf.Scoping(ids=my_meshed_region_1.nodes.scoping.ids, location=dpf.locations.nodal) + my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1, + mesh_scoping=mesh_scoping_1).eval() + my_stress_1 = my_model_1.results.stress(time_scoping=time_scoping_1, + mesh_scoping=mesh_scoping_1).eval() + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_11.gif") + + .. image:: animate_disp_11.gif + :scale: 50 % + :align: center + + .. tab-item:: LSDYNA + + .. code-block:: python + + # Animate the displacement results + my_disp_2.animate() + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + result_file_path_2 = examples.download_d3plot_beam() + my_data_sources_2 = dpf.DataSources() + my_data_sources_2.set_result_file_path(filepath=result_file_path_2[0], key="d3plot") + my_data_sources_2.add_file_path(filepath=result_file_path_2[3], key="actunits") + my_model_2 = dpf.Model(data_sources=my_data_sources_2) + time_scoping_2 = my_model_2.metadata.time_freq_support.time_frequencies + my_disp_2 = my_model_2.results.displacement(time_scoping=time_scoping_2).eval() + my_beam_axial_force_2 = my_model_2.results.beam_axial_force(time_scoping=time_scoping_2).eval() + my_disp_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_21.gif") + + .. image:: animate_disp_21.gif + :scale: 50 % + :align: center + +Animate the others results +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To animate the others results with a deformed geometry you need to use the ``deform_by`` argument. + +.. tab-set:: + + .. tab-item:: MAPDL + + .. code-block:: python + + # Animate the stress results + my_stress_1.animate(deform_by=my_disp_1) + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + my_stress_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_16.gif", + deform_by=my_disp_1) + + .. image:: animate_disp_16.gif + :scale: 50 % + :align: center + + .. tab-item:: LSDYNA + + .. code-block:: python + + # Animate the beam_axial_force results + my_beam_axial_force_2.animate(deform_by=my_disp_2) + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + my_beam_axial_force_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_26.gif", + deform_by=my_disp_2) + + .. image:: animate_disp_26.gif + :scale: 50 % + :align: center + +Exploring the |animate| method arguments +----------------------------------------- + +- You can deactivate the geometry deformation by using the argument ``deform_by=False``. + +.. tab-set:: + + .. tab-item:: MAPDL + + .. code-block:: python + + # Animate the displacement results + my_disp_1.animate(deform_by=False) + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_12.gif", + deform_by=False) + + .. image:: animate_disp_12.gif + :scale: 50 % + :align: center + + .. tab-item:: LSDYNA + + .. code-block:: python + + # Animate the displacement results + my_disp_2.animate(deform_by=False) + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + my_disp_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_22.gif", + deform_by=False) + + .. image:: animate_disp_22.gif + :scale: 50 % + :align: center + +- You can change the scale factor using: + + a) A number for a uniform constant scaling + b) A list of numbers for a varying scaling. + +.. tab-set:: + + .. tab-item:: MAPDL + + .. code-block:: python + + # Define the scale factors + uniform_scale_factor=10. + varying_scale_factor = [i for i in range(len(my_disp_1))] + # Animate the displacement results + my_disp_1.animate(scale_factor=uniform_scale_factor, + show_axes=True) + my_disp_1.animate(scale_factor=varying_scale_factor, + show_axes=True) + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + uniform_scale_factor=10. + varying_scale_factor = [i for i in range(len(my_disp_1))] + # Animate the displacement results + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_13.gif", + scale_factor=uniform_scale_factor, text="Uniform scale factor") + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_14.gif", + scale_factor=varying_scale_factor, text="Varying scale factor") + + .. image:: animate_disp_13.gif + :scale: 45 % + + .. image:: animate_disp_14.gif + :scale: 45 % + + .. tab-item:: LSDYNA + + .. code-block:: python + + # Define the scale factors + uniform_scale_factor=10. + varying_scale_factor = [i for i in range(len(my_disp_2))] + # Animate the displacement results + my_disp_2.animate(scale_factor=uniform_scale_factor) + my_disp_2.animate(scale_factor=varying_scale_factor) + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + uniform_scale_factor=10. + varying_scale_factor = [i for i in range(len(my_disp_2))] + # Animate the displacement results + my_disp_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_23.gif", + scale_factor=uniform_scale_factor, text="Uniform scale factor") + my_disp_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_24.gif", + scale_factor=varying_scale_factor, legend="Varying scale factor") + + .. image:: animate_disp_23.gif + :scale: 45 % + + .. image:: animate_disp_24.gif + :scale: 45 % + +- You can save the animation using the "save_as" argument with a target path with the desired format as extension. + (accepted extension: .gif, .avi or .mp4, see pyvista.Plotter.open_movie) + +.. tab-set:: + + .. tab-item:: MAPDL + + .. code-block:: python + + # Animate the stress results and save it + my_stress_1.animate(deform_by=my_disp_1, save_as="animate_stress.gif") + + .. tab-item:: LSDYNA + + .. code-block:: python + + # Animate the beam_axial_force results and save it + my_beam_axial_force_2.animate(deform_by=my_disp_2, save_as="animate_beam_axial_force.gif") + +- You can use additional PyVista arguments (available at: :class:`pyvista.Plotter.open_movie`), such as: + + a) Show the coordinate system axis with the "show_axes" argument; + b) Make the animation with the "off_screen" argument for batch animation creation; + c) Define a camera position to use with the "cpos" argument (it have to be in one of the three + formats explained in the following code); + d) Frames per second with the "framerate" argument; + e) Image quality with the "quality" argument. + +.. tab-set:: + + .. tab-item:: MAPDL + + .. code-block:: python + + # Camera position + # a) Iterable containing position, focal_point, and view up + my_cpo_a1 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] + # b) Iterable containing a view vector + my_cpo_b1 = [-1.0, 2.0, -5.0] + # c) A string containing the plane orthogonal to the view direction (here the 'xy' direction) + import copy + my_camera_pos_list_1 = [] + init_pos = [(1.1710286191854873, 1.1276044794551632, 1.62102216127818), + (0.05000000000000724, 0.006575860269683119, 0.4999935420927001), + (0.0, 0.0, 1.0)] + camera_pos_list.append(init_pos) + for i in range(1, len(displacement_fields)): + new_pos = copy.copy(camera_pos_list[i-1]) + new_pos[0] = (camera_pos_list[i-1][0][0], + camera_pos_list[i-1][0][1]-0.2, + camera_pos_list[i-1][0][2]) + camera_pos_list.append(new_pos) + + # Animate the displacement results + my_stress_1.animate(deform_by=my_disp_1, + show_axes=True, + framerate=4, + cpos=my_cpo_a1, + quality=8, + off_screen=True) + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + my_cpo_a1 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] + my_stress_1.animate(save_as="source/user_guide/tutorials/animate/animate_disp_17.gif", + deform_by=my_disp_1, + show_axes=True, + framerate=4, + cpos=my_cpo_a1, + quality=8, + off_screen=True) + + .. image:: animate_disp_17.gif + :scale: 50 % + :align: center + + .. tab-item:: LSDYNA + + .. code-block:: python + + # Camera position + # a) Iterable containing position, focal_point, and view up + my_cpo_a2 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] + # b) Iterable containing a view vector + my_cpo_b2 = [-1.0, 2.0, -5.0] + # c) A string containing the plane orthogonal to the view direction (here the 'xy' direction) + import copy + my_camera_pos_list_2 = [] + init_pos = [(1.1710286191854873, 1.1276044794551632, 1.62102216127818), + (0.05000000000000724, 0.006575860269683119, 0.4999935420927001), + (0.0, 0.0, 1.0)] + camera_pos_list.append(init_pos) + for i in range(1, len(displacement_fields)): + new_pos = copy.copy(camera_pos_list[i-1]) + new_pos[0] = (camera_pos_list[i-1][0][0], + camera_pos_list[i-1][0][1]-0.2, + camera_pos_list[i-1][0][2]) + camera_pos_list.append(new_pos) + + # Animate the displacement results + my_beam_axial_force_2.animate(deform_by=my_disp_2, + show_axes=True, + framerate=4, + cpos=my_cpo_a2, + quality=8, + off_screen=True) + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + my_cpo_a2 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] + my_beam_axial_force_2.animate(save_as="source/user_guide/tutorials/animate/animate_disp_27.gif", + deform_by=my_disp_2, + show_axes=True, + framerate=4, + cpos=my_cpo_a2, + quality=8, + off_screen=True) + .. image:: animate_disp_27.gif + :scale: 50 % + :align: center \ No newline at end of file diff --git a/doc/source/user_guide/tutorials/animate/index.rst b/doc/source/user_guide/tutorials/animate/index.rst index de075ed98ac..d1d5db65110 100644 --- a/doc/source/user_guide/tutorials/animate/index.rst +++ b/doc/source/user_guide/tutorials/animate/index.rst @@ -12,12 +12,15 @@ These tutorials demonstrate how to visualise the data in an animation. :margin: 2 .. grid-item-card:: Animate data - :link: ref_tutorials + :link: ref_tutorials_animate_data :link-type: ref :text-align: center This tutorial shows how to animate your results data. + +++ + :bdg-warning:`MAPDL` :bdg-success:`LSDYNA` + .. toctree:: :maxdepth: 2 :hidden: From 1ad47fe893fc1e58a0b15d5dae6ed6d7f284c5ad Mon Sep 17 00:00:00 2001 From: Luisa Felix Salles Date: Thu, 21 Nov 2024 09:09:46 +0100 Subject: [PATCH 03/15] Apply suggestions from code review Co-authored-by: Paul Profizi <100710998+PProfizi@users.noreply.github.com> --- doc/source/user_guide/tutorials/animate/animate_data.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_data.rst b/doc/source/user_guide/tutorials/animate/animate_data.rst index 2afda29fb21..e1e005b0cd1 100644 --- a/doc/source/user_guide/tutorials/animate/animate_data.rst +++ b/doc/source/user_guide/tutorials/animate/animate_data.rst @@ -16,14 +16,14 @@ Animate data .. |Result| replace:: :class:`Result ` .. |Operator| replace:: :class:`Operator` -This tutorial shows how to animate your results data. +This tutorial shows how to create 3D animations of the data. -To animate a result you need to get the data stored in a |FieldsContainer| labeled in time steps. +To animate data across time you need to get the data stored in a |FieldsContainer| labeled in time. Get the result files -------------------- -Here we we will download a result file available in our `Examples` package. +First download a result file such as one available with the `ansys.dpf.core.examples` module. For more information about how to import your result file in DPF check the :ref:`ref_tutorials_import_data` tutorial section. @@ -91,7 +91,7 @@ tutorials section. Extract the results ------------------- -You have to extracted the results of interest. +Extract the results of interest When you animate the data you go through the |Fields| of a |FieldsContainer| and plot contours of the data norm or of the selected data component. This means that the geometry needs to be deformed From 198141dc9c1e860602b1daa0ced95e5e8ecbd467 Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Thu, 21 Nov 2024 09:26:57 +0100 Subject: [PATCH 04/15] codes for just one case and erase badges --- .../tutorials/animate/animate_data.rst | 522 +++++------------- .../user_guide/tutorials/animate/index.rst | 2 - 2 files changed, 150 insertions(+), 374 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_data.rst b/doc/source/user_guide/tutorials/animate/animate_data.rst index e1e005b0cd1..aeab594fd24 100644 --- a/doc/source/user_guide/tutorials/animate/animate_data.rst +++ b/doc/source/user_guide/tutorials/animate/animate_data.rst @@ -1,15 +1,12 @@ -.. _ref_tutorials_animate_data: +.. _ref_tutorials_animate_time: -============ -Animate data -============ +====================== +Animate data over time +====================== -:bdg-warning:`MAPDL` :bdg-success:`LSDYNA` .. |Field| replace:: :class:`Field` .. |FieldsContainer| replace:: :class:`FieldsContainer` -.. |Fields| replace:: :class:`Fields` -.. |FieldsContainers| replace:: :class:`FieldsContainers` .. |MeshedRegion| replace:: :class:`MeshedRegion ` .. |TimeFreqSupport| replace:: :class:`TimeFreqSupport ` .. |animate| replace:: :func:`animate() ` @@ -27,40 +24,18 @@ First download a result file such as one available with the `ansys.dpf.core.exam For more information about how to import your result file in DPF check the :ref:`ref_tutorials_import_data` tutorial section. -.. tab-set:: +.. code-block:: python - .. tab-item:: MAPDL - - - .. code-block:: python - - # Import the ``ansys.dpf.core`` module, including examples files and the operators subpackage - from ansys.dpf import core as dpf - from ansys.dpf.core import examples - from ansys.dpf.core import operators as ops - # Define the result file - result_file_path_1 = examples.find_msup_transient() - # Create the model - my_model_1 = dpf.Model(data_sources=result_file_path_1) - # Get the mesh - my_meshed_region_1 = my_model_1.metadata.meshed_region - - .. tab-item:: LSDYNA - - .. code-block:: python - - # Import the ``ansys.dpf.core`` module, including examples files and the operators subpackage - from ansys.dpf import core as dpf - from ansys.dpf.core import examples - from ansys.dpf.core import operators as ops - # Define the result file - result_file_path_2 = examples.download_d3plot_beam() - # Create the DataSources object - my_data_sources_2 = dpf.DataSources() - my_data_sources_2.set_result_file_path(filepath=result_file_path_2[0], key="d3plot") - my_data_sources_2.add_file_path(filepath=result_file_path_2[3], key="actunits") - # Create the model - my_model_2 = dpf.Model(data_sources=my_data_sources_2) + # Import the ``ansys.dpf.core`` module, including examples files and the operators subpackage + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + # Define the result file + result_file_path_1 = examples.find_msup_transient() + # Create the model + my_model_1 = dpf.Model(data_sources=result_file_path_1) + # Get the mesh + my_meshed_region_1 = my_model_1.metadata.meshed_region Define time and mesh scopings ----------------------------- @@ -70,32 +45,23 @@ location (only elemental, nodal or faces location are supported for the animatio For more information on how to define a scoping check the ``Narrow down data`` tutorial in the :ref:`ref_tutorials_import_data` tutorials section. -.. tab-set:: - - .. tab-item:: MAPDL - .. code-block:: python +.. code-block:: python - # Get all the time steps - time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies - # Get all the mesh in a nodal location - mesh_scoping_1 = dpf.Scoping(ids=my_meshed_region_1.nodes.scoping.ids, location=dpf.locations.nodal) + # Get all the time steps + time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies + # Get all the mesh in a nodal location + mesh_scoping_1 = dpf.Scoping(ids=my_meshed_region_1.nodes.scoping.ids, location=dpf.locations.nodal) - .. tab-item:: LSDYNA - - .. code-block:: python - - # Get all the time steps - time_scoping_2 = my_model_2.metadata.time_freq_support.time_frequencies Extract the results ------------------- Extract the results of interest -When you animate the data you go through the |Fields| of a |FieldsContainer| and plot contours of +When you animate the data you go through each |Field| of a |FieldsContainer| and plot contours of the data norm or of the selected data component. This means that the geometry needs to be deformed -based on the |Fields| themselves. +based on each |Field| themselves. The geometry can be deformed by a |Result| object, an |Operator| (It must evaluate to a FieldsContainer of same length as the one being animated), a |Field| or a |FieldsContainer|. @@ -109,27 +75,14 @@ Here we get: - The displacement results and the stress result for the MAPDL result file - The displacement results and the beam axial force result for the LSDYNA result file -.. tab-set:: - - .. tab-item:: MAPDL - - .. code-block:: python - - # Get the displacement results - my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1, - mesh_scoping=mesh_scoping_1).eval() - # Get the stress results - my_stress_1 = my_model_1.results.stress(time_scoping=time_scoping_1, - mesh_scoping=mesh_scoping_1).eval() - - .. tab-item:: LSDYNA +.. code-block:: python - .. code-block:: python - - # Get the displacement results - my_disp_2 = my_model_2.results.displacement(time_scoping=time_scoping_2.eval() - # Get the stress results - my_beam_axial_force_2 = my_model_2.results.beam_axial_force(time_scoping=time_scoping_2).eval() + # Get the displacement results + my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1, + mesh_scoping=mesh_scoping_1).eval() + # Get the stress results + my_stress_1 = my_model_1.results.stress(time_scoping=time_scoping_1, + mesh_scoping=mesh_scoping_1).eval() Animate the results ------------------- @@ -147,249 +100,128 @@ Animate the displacement results Use the |animate| method with no arguments to get the default animation to the displacement results. -.. tab-set:: - - .. tab-item:: MAPDL - - .. code-block:: python - - # Animate the displacement results - my_disp_1.animate() - - .. rst-class:: sphx-glr-script-out - - .. jupyter-execute:: - :hide-code: - :hide-output: - - from ansys.dpf import core as dpf - from ansys.dpf.core import examples - from ansys.dpf.core import operators as ops - result_file_path_1 = examples.find_msup_transient() - my_model_1 = dpf.Model(data_sources=result_file_path_1) - my_meshed_region_1 = my_model_1.metadata.meshed_region - time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies - mesh_scoping_1 = dpf.Scoping(ids=my_meshed_region_1.nodes.scoping.ids, location=dpf.locations.nodal) - my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1, - mesh_scoping=mesh_scoping_1).eval() - my_stress_1 = my_model_1.results.stress(time_scoping=time_scoping_1, - mesh_scoping=mesh_scoping_1).eval() - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_11.gif") - .. image:: animate_disp_11.gif - :scale: 50 % - :align: center +.. code-block:: python - .. tab-item:: LSDYNA + # Animate the displacement results + my_disp_1.animate() - .. code-block:: python +.. rst-class:: sphx-glr-script-out - # Animate the displacement results - my_disp_2.animate() + .. jupyter-execute:: + :hide-code: + :hide-output: - .. rst-class:: sphx-glr-script-out + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + result_file_path_1 = examples.find_msup_transient() + my_model_1 = dpf.Model(data_sources=result_file_path_1) + my_meshed_region_1 = my_model_1.metadata.meshed_region + time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies + mesh_scoping_1 = dpf.Scoping(ids=my_meshed_region_1.nodes.scoping.ids, location=dpf.locations.nodal) + my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1, + mesh_scoping=mesh_scoping_1).eval() + my_stress_1 = my_model_1.results.stress(time_scoping=time_scoping_1, + mesh_scoping=mesh_scoping_1).eval() + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_11.gif") - .. jupyter-execute:: - :hide-code: - :hide-output: - - result_file_path_2 = examples.download_d3plot_beam() - my_data_sources_2 = dpf.DataSources() - my_data_sources_2.set_result_file_path(filepath=result_file_path_2[0], key="d3plot") - my_data_sources_2.add_file_path(filepath=result_file_path_2[3], key="actunits") - my_model_2 = dpf.Model(data_sources=my_data_sources_2) - time_scoping_2 = my_model_2.metadata.time_freq_support.time_frequencies - my_disp_2 = my_model_2.results.displacement(time_scoping=time_scoping_2).eval() - my_beam_axial_force_2 = my_model_2.results.beam_axial_force(time_scoping=time_scoping_2).eval() - my_disp_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_21.gif") - - .. image:: animate_disp_21.gif - :scale: 50 % - :align: center +.. image:: animate_disp_11.gif + :scale: 50 % + :align: center Animate the others results ^^^^^^^^^^^^^^^^^^^^^^^^^^ To animate the others results with a deformed geometry you need to use the ``deform_by`` argument. -.. tab-set:: - - .. tab-item:: MAPDL - - .. code-block:: python - - # Animate the stress results - my_stress_1.animate(deform_by=my_disp_1) - - .. rst-class:: sphx-glr-script-out +.. code-block:: python - .. jupyter-execute:: - :hide-code: - :hide-output: + # Animate the stress results + my_stress_1.animate(deform_by=my_disp_1) - my_stress_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_16.gif", - deform_by=my_disp_1) +.. rst-class:: sphx-glr-script-out - .. image:: animate_disp_16.gif - :scale: 50 % - :align: center + .. jupyter-execute:: + :hide-code: + :hide-output: - .. tab-item:: LSDYNA + my_stress_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_16.gif", + deform_by=my_disp_1) - .. code-block:: python +.. image:: animate_disp_16.gif + :scale: 50 % + :align: center - # Animate the beam_axial_force results - my_beam_axial_force_2.animate(deform_by=my_disp_2) - - .. rst-class:: sphx-glr-script-out - - .. jupyter-execute:: - :hide-code: - :hide-output: - - my_beam_axial_force_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_26.gif", - deform_by=my_disp_2) - - .. image:: animate_disp_26.gif - :scale: 50 % - :align: center Exploring the |animate| method arguments ----------------------------------------- - You can deactivate the geometry deformation by using the argument ``deform_by=False``. -.. tab-set:: - - .. tab-item:: MAPDL - - .. code-block:: python - - # Animate the displacement results - my_disp_1.animate(deform_by=False) - - .. rst-class:: sphx-glr-script-out - - .. jupyter-execute:: - :hide-code: - :hide-output: - - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_12.gif", - deform_by=False) - - .. image:: animate_disp_12.gif - :scale: 50 % - :align: center - - .. tab-item:: LSDYNA - - .. code-block:: python +.. code-block:: python - # Animate the displacement results - my_disp_2.animate(deform_by=False) + # Animate the displacement results + my_disp_1.animate(deform_by=False) - .. rst-class:: sphx-glr-script-out +.. rst-class:: sphx-glr-script-out - .. jupyter-execute:: - :hide-code: - :hide-output: + .. jupyter-execute:: + :hide-code: + :hide-output: - my_disp_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_22.gif", - deform_by=False) + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_12.gif", + deform_by=False) - .. image:: animate_disp_22.gif - :scale: 50 % - :align: center +.. image:: animate_disp_12.gif + :scale: 50 % + :align: center - You can change the scale factor using: a) A number for a uniform constant scaling b) A list of numbers for a varying scaling. -.. tab-set:: +.. code-block:: python - .. tab-item:: MAPDL + # Define the scale factors + uniform_scale_factor=10. + varying_scale_factor = [i for i in range(len(my_disp_1))] + # Animate the displacement results + my_disp_1.animate(scale_factor=uniform_scale_factor, + show_axes=True) + my_disp_1.animate(scale_factor=varying_scale_factor, + show_axes=True) - .. code-block:: python +.. rst-class:: sphx-glr-script-out - # Define the scale factors - uniform_scale_factor=10. - varying_scale_factor = [i for i in range(len(my_disp_1))] - # Animate the displacement results - my_disp_1.animate(scale_factor=uniform_scale_factor, - show_axes=True) - my_disp_1.animate(scale_factor=varying_scale_factor, - show_axes=True) + .. jupyter-execute:: + :hide-code: + :hide-output: - .. rst-class:: sphx-glr-script-out + uniform_scale_factor=10. + varying_scale_factor = [i for i in range(len(my_disp_1))] + # Animate the displacement results + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_13.gif", + scale_factor=uniform_scale_factor, text="Uniform scale factor") + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_14.gif", + scale_factor=varying_scale_factor, text="Varying scale factor") - .. jupyter-execute:: - :hide-code: - :hide-output: +.. image:: animate_disp_13.gif + :scale: 45 % - uniform_scale_factor=10. - varying_scale_factor = [i for i in range(len(my_disp_1))] - # Animate the displacement results - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_13.gif", - scale_factor=uniform_scale_factor, text="Uniform scale factor") - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_14.gif", - scale_factor=varying_scale_factor, text="Varying scale factor") +.. image:: animate_disp_14.gif + :scale: 45 % - .. image:: animate_disp_13.gif - :scale: 45 % - - .. image:: animate_disp_14.gif - :scale: 45 % - - .. tab-item:: LSDYNA - - .. code-block:: python - - # Define the scale factors - uniform_scale_factor=10. - varying_scale_factor = [i for i in range(len(my_disp_2))] - # Animate the displacement results - my_disp_2.animate(scale_factor=uniform_scale_factor) - my_disp_2.animate(scale_factor=varying_scale_factor) - - .. rst-class:: sphx-glr-script-out - - .. jupyter-execute:: - :hide-code: - :hide-output: - - uniform_scale_factor=10. - varying_scale_factor = [i for i in range(len(my_disp_2))] - # Animate the displacement results - my_disp_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_23.gif", - scale_factor=uniform_scale_factor, text="Uniform scale factor") - my_disp_2.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_24.gif", - scale_factor=varying_scale_factor, legend="Varying scale factor") - - .. image:: animate_disp_23.gif - :scale: 45 % - - .. image:: animate_disp_24.gif - :scale: 45 % - You can save the animation using the "save_as" argument with a target path with the desired format as extension. (accepted extension: .gif, .avi or .mp4, see pyvista.Plotter.open_movie) -.. tab-set:: - - .. tab-item:: MAPDL - - .. code-block:: python - - # Animate the stress results and save it - my_stress_1.animate(deform_by=my_disp_1, save_as="animate_stress.gif") - - .. tab-item:: LSDYNA +.. code-block:: python - .. code-block:: python + # Animate the stress results and save it + my_stress_1.animate(deform_by=my_disp_1, save_as="animate_stress.gif") - # Animate the beam_axial_force results and save it - my_beam_axial_force_2.animate(deform_by=my_disp_2, save_as="animate_beam_axial_force.gif") - You can use additional PyVista arguments (available at: :class:`pyvista.Plotter.open_movie`), such as: @@ -400,104 +232,50 @@ Exploring the |animate| method arguments d) Frames per second with the "framerate" argument; e) Image quality with the "quality" argument. -.. tab-set:: - - .. tab-item:: MAPDL - - .. code-block:: python - - # Camera position - # a) Iterable containing position, focal_point, and view up - my_cpo_a1 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] - # b) Iterable containing a view vector - my_cpo_b1 = [-1.0, 2.0, -5.0] - # c) A string containing the plane orthogonal to the view direction (here the 'xy' direction) - import copy - my_camera_pos_list_1 = [] - init_pos = [(1.1710286191854873, 1.1276044794551632, 1.62102216127818), - (0.05000000000000724, 0.006575860269683119, 0.4999935420927001), - (0.0, 0.0, 1.0)] - camera_pos_list.append(init_pos) - for i in range(1, len(displacement_fields)): - new_pos = copy.copy(camera_pos_list[i-1]) - new_pos[0] = (camera_pos_list[i-1][0][0], - camera_pos_list[i-1][0][1]-0.2, - camera_pos_list[i-1][0][2]) - camera_pos_list.append(new_pos) - - # Animate the displacement results - my_stress_1.animate(deform_by=my_disp_1, - show_axes=True, - framerate=4, - cpos=my_cpo_a1, - quality=8, - off_screen=True) - - .. rst-class:: sphx-glr-script-out - - .. jupyter-execute:: - :hide-code: - :hide-output: - - my_cpo_a1 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] - my_stress_1.animate(save_as="source/user_guide/tutorials/animate/animate_disp_17.gif", - deform_by=my_disp_1, - show_axes=True, - framerate=4, - cpos=my_cpo_a1, - quality=8, - off_screen=True) - - .. image:: animate_disp_17.gif - :scale: 50 % - :align: center - - .. tab-item:: LSDYNA - - .. code-block:: python - - # Camera position - # a) Iterable containing position, focal_point, and view up - my_cpo_a2 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] - # b) Iterable containing a view vector - my_cpo_b2 = [-1.0, 2.0, -5.0] - # c) A string containing the plane orthogonal to the view direction (here the 'xy' direction) - import copy - my_camera_pos_list_2 = [] - init_pos = [(1.1710286191854873, 1.1276044794551632, 1.62102216127818), - (0.05000000000000724, 0.006575860269683119, 0.4999935420927001), - (0.0, 0.0, 1.0)] - camera_pos_list.append(init_pos) - for i in range(1, len(displacement_fields)): - new_pos = copy.copy(camera_pos_list[i-1]) - new_pos[0] = (camera_pos_list[i-1][0][0], - camera_pos_list[i-1][0][1]-0.2, - camera_pos_list[i-1][0][2]) - camera_pos_list.append(new_pos) - - # Animate the displacement results - my_beam_axial_force_2.animate(deform_by=my_disp_2, - show_axes=True, - framerate=4, - cpos=my_cpo_a2, - quality=8, - off_screen=True) - - .. rst-class:: sphx-glr-script-out - - .. jupyter-execute:: - :hide-code: - :hide-output: - - my_cpo_a2 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] - my_beam_axial_force_2.animate(save_as="source/user_guide/tutorials/animate/animate_disp_27.gif", - deform_by=my_disp_2, - show_axes=True, - framerate=4, - cpos=my_cpo_a2, - quality=8, - off_screen=True) - - .. image:: animate_disp_27.gif - :scale: 50 % - :align: center \ No newline at end of file +.. code-block:: python + + # Camera position + # a) Iterable containing position, focal_point, and view up + my_cpo_a1 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] + # b) Iterable containing a view vector + my_cpo_b1 = [-1.0, 2.0, -5.0] + # c) A string containing the plane orthogonal to the view direction (here the 'xy' direction) + import copy + my_camera_pos_list_1 = [] + init_pos = [(1.1710286191854873, 1.1276044794551632, 1.62102216127818), + (0.05000000000000724, 0.006575860269683119, 0.4999935420927001), + (0.0, 0.0, 1.0)] + camera_pos_list.append(init_pos) + for i in range(1, len(displacement_fields)): + new_pos = copy.copy(camera_pos_list[i-1]) + new_pos[0] = (camera_pos_list[i-1][0][0], + camera_pos_list[i-1][0][1]-0.2, + camera_pos_list[i-1][0][2]) + camera_pos_list.append(new_pos) + + # Animate the displacement results + my_stress_1.animate(deform_by=my_disp_1, + show_axes=True, + framerate=4, + cpos=my_cpo_a1, + quality=8, + off_screen=True) + +.. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + my_cpo_a1 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] + my_stress_1.animate(save_as="source/user_guide/tutorials/animate/animate_disp_17.gif", + deform_by=my_disp_1, + show_axes=True, + framerate=4, + cpos=my_cpo_a1, + quality=8, + off_screen=True) + +.. image:: animate_disp_17.gif + :scale: 50 % + :align: center diff --git a/doc/source/user_guide/tutorials/animate/index.rst b/doc/source/user_guide/tutorials/animate/index.rst index d1d5db65110..86823c7f39f 100644 --- a/doc/source/user_guide/tutorials/animate/index.rst +++ b/doc/source/user_guide/tutorials/animate/index.rst @@ -18,8 +18,6 @@ These tutorials demonstrate how to visualise the data in an animation. This tutorial shows how to animate your results data. - +++ - :bdg-warning:`MAPDL` :bdg-success:`LSDYNA` .. toctree:: :maxdepth: 2 From 5bf154adc5ac569567d8b811ed09f9c857e5ee15 Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Thu, 21 Nov 2024 09:28:11 +0100 Subject: [PATCH 05/15] change tutorial name --- .../tutorials/animate/{animate_data.rst => animate_time.rst} | 0 doc/source/user_guide/tutorials/animate/index.rst | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename doc/source/user_guide/tutorials/animate/{animate_data.rst => animate_time.rst} (100%) diff --git a/doc/source/user_guide/tutorials/animate/animate_data.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst similarity index 100% rename from doc/source/user_guide/tutorials/animate/animate_data.rst rename to doc/source/user_guide/tutorials/animate/animate_time.rst diff --git a/doc/source/user_guide/tutorials/animate/index.rst b/doc/source/user_guide/tutorials/animate/index.rst index 86823c7f39f..e4bc5e06560 100644 --- a/doc/source/user_guide/tutorials/animate/index.rst +++ b/doc/source/user_guide/tutorials/animate/index.rst @@ -12,7 +12,7 @@ These tutorials demonstrate how to visualise the data in an animation. :margin: 2 .. grid-item-card:: Animate data - :link: ref_tutorials_animate_data + :link: ref_tutorials_animate_time :link-type: ref :text-align: center @@ -23,4 +23,4 @@ These tutorials demonstrate how to visualise the data in an animation. :maxdepth: 2 :hidden: - animate_data.rst + animate_time.rst From 343a5781d540f842535244499b3ce2e69c76e4ba Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Thu, 21 Nov 2024 10:28:32 +0100 Subject: [PATCH 06/15] last updates --- .../tutorials/animate/animate_time.rst | 206 ++++++++++-------- .../user_guide/tutorials/animate/index.rst | 4 +- 2 files changed, 116 insertions(+), 94 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index aeab594fd24..ff32af95845 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -9,7 +9,7 @@ Animate data over time .. |FieldsContainer| replace:: :class:`FieldsContainer` .. |MeshedRegion| replace:: :class:`MeshedRegion ` .. |TimeFreqSupport| replace:: :class:`TimeFreqSupport ` -.. |animate| replace:: :func:`animate() ` +.. |animate| replace:: :func:`FieldsContainer.animate() ` .. |Result| replace:: :class:`Result ` .. |Operator| replace:: :class:`Operator` @@ -37,145 +37,167 @@ the :ref:`ref_tutorials_import_data` tutorial section. # Get the mesh my_meshed_region_1 = my_model_1.metadata.meshed_region -Define time and mesh scopings ------------------------------ +Define time scoping +------------------- -Here we get all the the time steps of the |TimeFreqSupport| and all the |MeshedRegion| with results in a ``Nodal`` -location (only elemental, nodal or faces location are supported for the animation). -For more information on how to define a scoping check the ``Narrow down data`` tutorial in the :ref:`ref_tutorials_import_data` -tutorials section. +Here we get all the the time steps of the |TimeFreqSupport|. For more information on how to define a +scoping check the ``Narrow down data`` tutorial in the :ref:`ref_tutorials_import_data` tutorials section. .. code-block:: python # Get all the time steps time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies - # Get all the mesh in a nodal location - mesh_scoping_1 = dpf.Scoping(ids=my_meshed_region_1.nodes.scoping.ids, location=dpf.locations.nodal) - Extract the results ------------------- -Extract the results of interest +The default behavior of the |animate| consists in: + +- Using a constant and uniform scale factor of 1.0; +- Showing the deformed geometry if the method was used directly with the displacement fields; +- Showing the static geometry if the method was used with other results fields. -When you animate the data you go through each |Field| of a |FieldsContainer| and plot contours of -the data norm or of the selected data component. This means that the geometry needs to be deformed -based on each |Field| themselves. +.. note:: -The geometry can be deformed by a |Result| object, an |Operator| (It must evaluate to a FieldsContainer -of same length as the one being animated), a |Field| or a |FieldsContainer|. + This geometry behavior is due to the fact that when you animate the data you go through each |Field| + of a |FieldsContainer| and plot contours of the data norm or of the selected data component. This means + that the geometry needs to be deformed based on each |Field| themselves. Thus, we need a result with a + homogeneous unit dimension (a distance unit). Therefore, to deform the mesh we need the displacement result. + For more information see: :ref:`ref_plotting_data_on_deformed_mesh`. -To deform the geometry we need a result with a homogeneous unit dimension, thus, a distance unit. -Thus, to deform the mesh we need the displacement result. -For more information see: :ref:`ref_plotting_data_on_deformed_mesh` +Nevertheless you can customize the default behavior and animate the other results fields in a deformed geometry. -Here we get: +The geometry can be deformed by a |Result| object, an |Operator| (It must evaluate to a |FieldsContainer| +of same length as the one being animated) or a |FieldsContainer| (also of same length as the one being animated). -- The displacement results and the stress result for the MAPDL result file -- The displacement results and the beam axial force result for the LSDYNA result file +Extract the results of interest. Here we get the displacement and stress results. + +.. note:: + + Only elemental, nodal or faces location are supported for the animation. .. code-block:: python # Get the displacement results - my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1, - mesh_scoping=mesh_scoping_1).eval() + my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1).eval() + # Get the stress results - my_stress_1 = my_model_1.results.stress(time_scoping=time_scoping_1, - mesh_scoping=mesh_scoping_1).eval() + # Here we average the results to get a Nodal location + my_stress_elemental_nodal = my_model_1.results.stress(time_scoping=time_scoping_1).eval() + my_stress_1 = ops.averaging.elemental_nodal_to_nodal_fc(fields_container=my_stress_elemental_nodal).eval() Animate the results ------------------- -You animate a |FieldsContainer| by using the |animate| method. - -The default behavior consists in: - -- Using a constant and uniform scale factor of 1.0 -- Showing the deformed geometry if the method was used directly with the displacement fields. -- Showing the static geometry if the method was used with other results fields. +Animate the results with: |animate|. You can animate them in a deformed geometry +(animate the results color map and the mesh deformations) or in a static geometry (animate the results color map). Animate the displacement results ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Use the |animate| method with no arguments to get the default animation to the displacement results. +Use the |animate| with the displacement results. +.. tab-set:: -.. code-block:: python + .. tab-item:: Deformed geometry - # Animate the displacement results - my_disp_1.animate() + .. code-block:: python -.. rst-class:: sphx-glr-script-out + # Animate the displacement results in a deformed geometry + my_disp_1.animate() - .. jupyter-execute:: - :hide-code: - :hide-output: + .. rst-class:: sphx-glr-script-out - from ansys.dpf import core as dpf - from ansys.dpf.core import examples - from ansys.dpf.core import operators as ops - result_file_path_1 = examples.find_msup_transient() - my_model_1 = dpf.Model(data_sources=result_file_path_1) - my_meshed_region_1 = my_model_1.metadata.meshed_region - time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies - mesh_scoping_1 = dpf.Scoping(ids=my_meshed_region_1.nodes.scoping.ids, location=dpf.locations.nodal) - my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1, - mesh_scoping=mesh_scoping_1).eval() - my_stress_1 = my_model_1.results.stress(time_scoping=time_scoping_1, - mesh_scoping=mesh_scoping_1).eval() - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_11.gif") - -.. image:: animate_disp_11.gif - :scale: 50 % - :align: center + .. jupyter-execute:: + :hide-code: + :hide-output: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + result_file_path_1 = examples.find_msup_transient() + my_model_1 = dpf.Model(data_sources=result_file_path_1) + time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies + my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1).eval() + my_stress_elemental_nodal = my_model_1.results.stress(time_scoping=time_scoping_1).eval() + my_stress_1 = ops.averaging.elemental_nodal_to_nodal_fc(fields_container=my_stress_elemental_nodal).eval() + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_1.gif") + + .. image:: animate_disp_1.gif + :scale: 50 % + :align: center + + .. tab-item:: Static geometry + + .. code-block:: python + + # Animate the displacement results in a static geometry + # You can deactivate the geometry deformation of the displacement results by using the argument ``deform_by=False`` + my_disp_1.animate(deform_by=False) + + .. rst-class:: sphx-glr-script-out + + .. jupyter-execute:: + :hide-code: + :hide-output: + + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_2.gif", + deform_by=False) + + .. image:: animate_disp_2.gif + :scale: 50 % + :align: center Animate the others results ^^^^^^^^^^^^^^^^^^^^^^^^^^ -To animate the others results with a deformed geometry you need to use the ``deform_by`` argument. +Use the |animate| with the stress results. -.. code-block:: python +.. tab-set:: - # Animate the stress results - my_stress_1.animate(deform_by=my_disp_1) + .. tab-item:: Deformed geometry -.. rst-class:: sphx-glr-script-out + .. code-block:: python - .. jupyter-execute:: - :hide-code: - :hide-output: + # Animate the stress results in a deformed geometry + # Use the ``deform_by`` argument and give the displacement results. + my_stress_1.animate(deform_by=my_disp_1) - my_stress_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_16.gif", - deform_by=my_disp_1) + .. rst-class:: sphx-glr-script-out -.. image:: animate_disp_16.gif - :scale: 50 % - :align: center + .. jupyter-execute:: + :hide-code: + :hide-output: + my_stress_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_stress_1.gif", + deform_by=my_disp_1) -Exploring the |animate| method arguments ------------------------------------------ + .. image:: animate_stress_1.gif + :scale: 50 % + :align: center -- You can deactivate the geometry deformation by using the argument ``deform_by=False``. + .. tab-item:: Static geometry -.. code-block:: python + .. code-block:: python - # Animate the displacement results - my_disp_1.animate(deform_by=False) + # Animate the stress results in a static geometry + my_stress_1.animate(my_stress_1.animate() -.. rst-class:: sphx-glr-script-out + .. rst-class:: sphx-glr-script-out - .. jupyter-execute:: - :hide-code: - :hide-output: + .. jupyter-execute:: + :hide-code: + :hide-output: - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_12.gif", - deform_by=False) + my_stress_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_stress_2.gif") -.. image:: animate_disp_12.gif - :scale: 50 % - :align: center + .. image:: animate_stress_2.gif + :scale: 50 % + :align: center + +Exploring the |animate| method arguments +----------------------------------------- - You can change the scale factor using: @@ -202,15 +224,15 @@ Exploring the |animate| method arguments uniform_scale_factor=10. varying_scale_factor = [i for i in range(len(my_disp_1))] # Animate the displacement results - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_13.gif", + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_3.gif", scale_factor=uniform_scale_factor, text="Uniform scale factor") - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_14.gif", + my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_4.gif", scale_factor=varying_scale_factor, text="Varying scale factor") -.. image:: animate_disp_13.gif +.. image:: animate_disp_3.gif :scale: 45 % -.. image:: animate_disp_14.gif +.. image:: animate_disp_4.gif :scale: 45 % @@ -268,7 +290,7 @@ Exploring the |animate| method arguments :hide-output: my_cpo_a1 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] - my_stress_1.animate(save_as="source/user_guide/tutorials/animate/animate_disp_17.gif", + my_stress_1.animate(save_as="source/user_guide/tutorials/animate/animate_disp_5.gif", deform_by=my_disp_1, show_axes=True, framerate=4, @@ -276,6 +298,6 @@ Exploring the |animate| method arguments quality=8, off_screen=True) -.. image:: animate_disp_17.gif +.. image:: animate_disp_5.gif :scale: 50 % :align: center diff --git a/doc/source/user_guide/tutorials/animate/index.rst b/doc/source/user_guide/tutorials/animate/index.rst index e4bc5e06560..69a52f44d5a 100644 --- a/doc/source/user_guide/tutorials/animate/index.rst +++ b/doc/source/user_guide/tutorials/animate/index.rst @@ -11,12 +11,12 @@ These tutorials demonstrate how to visualise the data in an animation. :padding: 2 :margin: 2 - .. grid-item-card:: Animate data + .. grid-item-card:: Animate data over time :link: ref_tutorials_animate_time :link-type: ref :text-align: center - This tutorial shows how to animate your results data. + This tutorial shows how to animate your results data over time. .. toctree:: From 57ff22bfabf72f902601fb5a53fc587bf5310f68 Mon Sep 17 00:00:00 2001 From: PProfizi Date: Fri, 22 Nov 2024 16:39:24 +0100 Subject: [PATCH 07/15] Update animate_time.rst --- .../tutorials/animate/animate_time.rst | 390 ++++++++++-------- 1 file changed, 217 insertions(+), 173 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index ff32af95845..fd22c15c937 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -4,7 +4,7 @@ Animate data over time ====================== - +.. |Animator| replace:: :class:`Animator` .. |Field| replace:: :class:`Field` .. |FieldsContainer| replace:: :class:`FieldsContainer` .. |MeshedRegion| replace:: :class:`MeshedRegion ` @@ -12,292 +12,336 @@ Animate data over time .. |animate| replace:: :func:`FieldsContainer.animate() ` .. |Result| replace:: :class:`Result ` .. |Operator| replace:: :class:`Operator` +.. |Workflow| replace:: :class:`Workflow` +.. |Elemental| replace:: :class:`elemental` +.. |ElementalNodal| replace:: :class:`elemental_nodal` +.. |Nodal| replace:: :class:`nodal` +.. |Faces| replace:: :class:`faces` +.. |Overall| replace:: :class:`overall` +.. |open_movie| replace:: :class:`pyvista.Plotter.open_movie` + +This tutorial shows how to create 3D animations of data in time. + +:jupyter-download-script:`Download tutorial as Python script` -This tutorial shows how to create 3D animations of the data. +:jupyter-download-notebook:`Download tutorial as notebook` To animate data across time you need to get the data stored in a |FieldsContainer| labeled in time. + Get the result files -------------------- -First download a result file such as one available with the `ansys.dpf.core.examples` module. -For more information about how to import your result file in DPF check +First download a result file such as one available with the :ref:`ansys.dpf.core.examples.examples` module. +For more information about how to import your own result file in DPF check the :ref:`ref_tutorials_import_data` tutorial section. -.. code-block:: python +.. jupyter-execute:: - # Import the ``ansys.dpf.core`` module, including examples files and the operators subpackage + # Import the ``ansys.dpf.core`` module from ansys.dpf import core as dpf + # Import the examples module from ansys.dpf.core import examples + # Import the operators module from ansys.dpf.core import operators as ops # Define the result file - result_file_path_1 = examples.find_msup_transient() + result_file_path = examples.find_msup_transient() # Create the model - my_model_1 = dpf.Model(data_sources=result_file_path_1) - # Get the mesh - my_meshed_region_1 = my_model_1.metadata.meshed_region + model = dpf.Model(data_sources=result_file_path) -Define time scoping -------------------- - -Here we get all the the time steps of the |TimeFreqSupport|. For more information on how to define a -scoping check the ``Narrow down data`` tutorial in the :ref:`ref_tutorials_import_data` tutorials section. +Define a time scoping +--------------------- +To animate across time we first need to define the time steps of interest. +Here we get all the time steps available in the |TimeFreqSupport|, but you can also filter them. +For more information on how to define a scoping check the ``Narrow down data`` tutorial in the +:ref:`ref_tutorials_import_data` tutorials section. -.. code-block:: python +.. jupyter-execute:: - # Get all the time steps - time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies + # Get a scoping of all time steps available + time_scoping = model.metadata.time_freq_support.time_frequencies Extract the results ------------------- -The default behavior of the |animate| consists in: - -- Using a constant and uniform scale factor of 1.0; -- Showing the deformed geometry if the method was used directly with the displacement fields; -- Showing the static geometry if the method was used with other results fields. +Extract the results to animate. Here we get the displacement and stress results. .. note:: - This geometry behavior is due to the fact that when you animate the data you go through each |Field| - of a |FieldsContainer| and plot contours of the data norm or of the selected data component. This means - that the geometry needs to be deformed based on each |Field| themselves. Thus, we need a result with a - homogeneous unit dimension (a distance unit). Therefore, to deform the mesh we need the displacement result. - For more information see: :ref:`ref_plotting_data_on_deformed_mesh`. + Only locations |Elemental|, |Nodal| or |Faces| are supported for animations. + |Overall| and |ElementalNodal| locations are not currently supported. -Nevertheless you can customize the default behavior and animate the other results fields in a deformed geometry. -The geometry can be deformed by a |Result| object, an |Operator| (It must evaluate to a |FieldsContainer| -of same length as the one being animated) or a |FieldsContainer| (also of same length as the one being animated). +.. jupyter-execute:: -Extract the results of interest. Here we get the displacement and stress results. + # Get the displacement fields (already on nodes) at all time steps + disp_fc = model.results.displacement(time_scoping=time_scoping).eval() + print(disp_fc) -.. note:: +.. jupyter-execute:: - Only elemental, nodal or faces location are supported for the animation. + # Get the stress fields on nodes at all time steps + stress_fc = model.results.stress.on_location( + location=dpf.locations.nodal).on_time_scoping( + time_scoping=time_scoping).eval() + print(stress_fc) -.. code-block:: python +Animate the results +------------------- - # Get the displacement results - my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1).eval() +Animate the results with the |animate| method. +You can animate them on a deformed mesh (animate the color map and the mesh) +or on a static mesh (animate the color map only). - # Get the stress results - # Here we average the results to get a Nodal location - my_stress_elemental_nodal = my_model_1.results.stress(time_scoping=time_scoping_1).eval() - my_stress_1 = ops.averaging.elemental_nodal_to_nodal_fc(fields_container=my_stress_elemental_nodal).eval() +The default behavior of the |animate| method consists in: -Animate the results -------------------- +- Showing the norm of the data if multiple components are available; +- Showing data at the top layer for shells; +- Showing the deformed mesh when animating displacements; +- Showing the static mesh for other types of results; +- Using a constant and uniform scale factor of 1.0 when deforming the mesh. + +You can animate any result on a deformed geometry by also providing displacements in the `deform_by` parameter. + +The geometry can be deformed by a |Result| object, an |Operator| (It must evaluate to a |FieldsContainer| +of same length as the one being animated) or a |FieldsContainer| (also of same length as the one being animated). + +.. note:: + + The behavior of the |animate| method is defined by a |Workflow| it creates and feeds to an |Animator|. + This |Workflow| loops over a |Field| of frame indices and for each frame generates a field of contours + to render as well as a displacement field to deform the mesh with if `deform_by` is provided. + For more information on plots on deformed meshes see: :ref:`ref_plotting_data_on_deformed_mesh`. -Animate the results with: |animate|. You can animate them in a deformed geometry -(animate the results color map and the mesh deformations) or in a static geometry (animate the results color map). Animate the displacement results ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Use the |animate| with the displacement results. +Use |animate| with the displacement results. .. tab-set:: - .. tab-item:: Deformed geometry + .. tab-item:: Deformed mesh - .. code-block:: python + .. jupyter-execute:: + :hide-output: - # Animate the displacement results in a deformed geometry - my_disp_1.animate() + # Animate the displacement results in a deformed geometry + disp_fc.animate() - .. rst-class:: sphx-glr-script-out + .. jupyter-execute:: + :hide-code: + :hide-output: - .. jupyter-execute:: - :hide-code: - :hide-output: - - from ansys.dpf import core as dpf - from ansys.dpf.core import examples - from ansys.dpf.core import operators as ops - result_file_path_1 = examples.find_msup_transient() - my_model_1 = dpf.Model(data_sources=result_file_path_1) - time_scoping_1 = my_model_1.metadata.time_freq_support.time_frequencies - my_disp_1 = my_model_1.results.displacement(time_scoping=time_scoping_1).eval() - my_stress_elemental_nodal = my_model_1.results.stress(time_scoping=time_scoping_1).eval() - my_stress_1 = ops.averaging.elemental_nodal_to_nodal_fc(fields_container=my_stress_elemental_nodal).eval() - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_1.gif") + disp_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_1.gif") .. image:: animate_disp_1.gif :scale: 50 % :align: center - .. tab-item:: Static geometry - - .. code-block:: python + .. tab-item:: Static mesh - # Animate the displacement results in a static geometry - # You can deactivate the geometry deformation of the displacement results by using the argument ``deform_by=False`` - my_disp_1.animate(deform_by=False) + .. jupyter-execute:: + :hide-output: - .. rst-class:: sphx-glr-script-out + # Animate the displacement results on a static mesh using ``deform_by=False`` + disp_fc.animate(deform_by=False) - .. jupyter-execute:: - :hide-code: - :hide-output: + .. jupyter-execute:: + :hide-code: + :hide-output: - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_2.gif", - deform_by=False) + disp_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_2.gif", + deform_by=False) .. image:: animate_disp_2.gif :scale: 50 % :align: center -Animate the others results -^^^^^^^^^^^^^^^^^^^^^^^^^^ +Animate the stress +^^^^^^^^^^^^^^^^^^ -Use the |animate| with the stress results. +Use |animate| with the stress results. .. tab-set:: - .. tab-item:: Deformed geometry + .. tab-item:: Deformed mesh - .. code-block:: python + .. jupyter-execute:: + :hide-output: - # Animate the stress results in a deformed geometry + # Animate the stress results on a deformed mesh # Use the ``deform_by`` argument and give the displacement results. - my_stress_1.animate(deform_by=my_disp_1) + stress_fc.animate(deform_by=disp_fc) - .. rst-class:: sphx-glr-script-out + .. jupyter-execute:: + :hide-code: + :hide-output: - .. jupyter-execute:: - :hide-code: - :hide-output: - - my_stress_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_stress_1.gif", - deform_by=my_disp_1) + stress_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_stress_1.gif", + deform_by=disp_fc) .. image:: animate_stress_1.gif :scale: 50 % :align: center - .. tab-item:: Static geometry + .. tab-item:: Static mesh - .. code-block:: python + .. jupyter-execute:: + :hide-output: # Animate the stress results in a static geometry - my_stress_1.animate(my_stress_1.animate() - - .. rst-class:: sphx-glr-script-out + stress_fc.animate() - .. jupyter-execute:: - :hide-code: - :hide-output: + .. jupyter-execute:: + :hide-code: + :hide-output: - my_stress_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_stress_2.gif") + stress_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_stress_2.gif") .. image:: animate_stress_2.gif :scale: 50 % :align: center -Exploring the |animate| method arguments ------------------------------------------ +Change the scale factor +----------------------- -- You can change the scale factor using: +You can change the scale factor using: - a) A number for a uniform constant scaling - b) A list of numbers for a varying scaling. +a) A single number for a uniform constant scaling. -.. code-block:: python +.. jupyter-execute:: + :hide-output: - # Define the scale factors + # Define a uniform scale factor uniform_scale_factor=10. - varying_scale_factor = [i for i in range(len(my_disp_1))] - # Animate the displacement results - my_disp_1.animate(scale_factor=uniform_scale_factor, - show_axes=True) - my_disp_1.animate(scale_factor=varying_scale_factor, - show_axes=True) + # Animate the displacements + disp_fc.animate(scale_factor=uniform_scale_factor) -.. rst-class:: sphx-glr-script-out - - .. jupyter-execute:: +.. jupyter-execute:: :hide-code: :hide-output: - uniform_scale_factor=10. - varying_scale_factor = [i for i in range(len(my_disp_1))] - # Animate the displacement results - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_3.gif", + disp_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_3.gif", scale_factor=uniform_scale_factor, text="Uniform scale factor") - my_disp_1.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_4.gif", - scale_factor=varying_scale_factor, text="Varying scale factor") .. image:: animate_disp_3.gif :scale: 45 % + :align: center + +b) A list of numbers for a varying scaling (same length as the number of frames). + +.. jupyter-execute:: + :hide-output: + + # Define a varying scale factor + varying_scale_factor = [i for i in range(len(disp_fc))] + # Animate the displacements + disp_fc.animate(scale_factor=varying_scale_factor) + +.. jupyter-execute:: + :hide-code: + :hide-output: + + disp_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_4.gif", + scale_factor=varying_scale_factor, text="Varying scale factor") .. image:: animate_disp_4.gif :scale: 45 % + :align: center +Save the animation +------------------ -- You can save the animation using the "save_as" argument with a target path with the desired format as extension. - (accepted extension: .gif, .avi or .mp4, see pyvista.Plotter.open_movie) +You can save the animation using the ``save_as`` argument with a target file path with the desired format as extension. +Accepted extensions are ``.gif``, ``.avi`` or ``.mp4`` (see |open_movie|). -.. code-block:: python +.. jupyter-execute:: + :hide-output: # Animate the stress results and save it - my_stress_1.animate(deform_by=my_disp_1, save_as="animate_stress.gif") + stress_fc.animate(deform_by=disp_fc, save_as="animate_stress.gif") -- You can use additional PyVista arguments (available at: :class:`pyvista.Plotter.open_movie`), such as: +Control the camera +------------------ - a) Show the coordinate system axis with the "show_axes" argument; - b) Make the animation with the "off_screen" argument for batch animation creation; - c) Define a camera position to use with the "cpos" argument (it have to be in one of the three - formats explained in the following code); - d) Frames per second with the "framerate" argument; - e) Image quality with the "quality" argument. +Control the camera with the ``cpos`` argument. + +A camera position is a combination of position, focal point (the target), and upwards vector, +resulting in a list of format: .. code-block:: python - # Camera position - # a) Iterable containing position, focal_point, and view up - my_cpo_a1 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] - # b) Iterable containing a view vector - my_cpo_b1 = [-1.0, 2.0, -5.0] - # c) A string containing the plane orthogonal to the view direction (here the 'xy' direction) - import copy - my_camera_pos_list_1 = [] - init_pos = [(1.1710286191854873, 1.1276044794551632, 1.62102216127818), - (0.05000000000000724, 0.006575860269683119, 0.4999935420927001), - (0.0, 0.0, 1.0)] - camera_pos_list.append(init_pos) - for i in range(1, len(displacement_fields)): - new_pos = copy.copy(camera_pos_list[i-1]) - new_pos[0] = (camera_pos_list[i-1][0][0], - camera_pos_list[i-1][0][1]-0.2, - camera_pos_list[i-1][0][2]) - camera_pos_list.append(new_pos) - - # Animate the displacement results - my_stress_1.animate(deform_by=my_disp_1, - show_axes=True, - framerate=4, - cpos=my_cpo_a1, - quality=8, - off_screen=True) - -.. rst-class:: sphx-glr-script-out - - .. jupyter-execute:: - :hide-code: - :hide-output: + [[pos_x, pos_y, pos_z], [fp_x, fp_y, fp_z], [up_x, up_y, up_z]] + +The |animate| method accepts a single camera position or a list of camera positions for each frame. + +.. note:: + A tip for defining a camera position is to do a first interactive plot of the data + with argument ``return_cpos=True``, position the camera as desired in the view, and retrieve + the output of the plotting command. - my_cpo_a1 = [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] - my_stress_1.animate(save_as="source/user_guide/tutorials/animate/animate_disp_5.gif", - deform_by=my_disp_1, - show_axes=True, - framerate=4, - cpos=my_cpo_a1, - quality=8, - off_screen=True) +Fixed camera +^^^^^^^^^^^^ + +.. jupyter-execute:: + :hide-output: + + # Define the camera position + cpos = [[1.171, 1.126, 1.621], [0.05, 0.005, 0.5], [0.0, 0.0, 1.0]] + # Animate the stress with a custom fixed camera position + stress_fc.animate(cpos=cpos) + +.. jupyter-execute:: + :hide-code: + :hide-output: + + stress_fc.animate(save_as="source/user_guide/tutorials/animate/animate_disp_5.gif", + cpos=cpos, + off_screen=True) .. image:: animate_disp_5.gif :scale: 50 % :align: center + +Moving camera +^^^^^^^^^^^^^ + +.. jupyter-execute:: + :hide-output: + + # Define the list of camera positions + import copy + cpos_list = [cpos] + # Incrementally decrease the y coordinate of the camera by 0.2 for each frame + for i in range(1, len(disp_fc)): + new_pos = copy.copy(cpos_list[i-1]) + new_pos[0][1] += 0.2 + cpos_list.append(new_pos) + + # Animate the stress with a moving camera + stress_fc.animate(cpos=cpos_list) + +.. jupyter-execute:: + :hide-code: + :hide-output: + + stress_fc.animate(save_as="source/user_guide/tutorials/animate/animate_disp_6.gif", + cpos=cpos_list, + off_screen=True) + +.. image:: animate_disp_6.gif + :scale: 50 % + :align: center + +Additional options +------------------ + +You can use additional PyVista arguments of |open_movie|), such as: + +- Show or hide the coordinate system axis with ``show_axes=True`` or ``show_axes=False``; +- Render off-screen for batch animation creation with ``off_screen=True``; +- Change the frame-rate with ``framerate``; +- Change the image quality with ``quality``. From 1733ba6873da6653c308bacaf8afeb0b11091330 Mon Sep 17 00:00:00 2001 From: PProfizi Date: Fri, 22 Nov 2024 17:20:50 +0100 Subject: [PATCH 08/15] Fixing moving camera --- doc/source/user_guide/tutorials/animate/animate_time.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index fd22c15c937..07e4d3307e9 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -4,6 +4,7 @@ Animate data over time ====================== +.. |Examples| replace:: :mod:`ansys.dpf.core.examples` .. |Animator| replace:: :class:`Animator` .. |Field| replace:: :class:`Field` .. |FieldsContainer| replace:: :class:`FieldsContainer` @@ -32,7 +33,7 @@ To animate data across time you need to get the data stored in a |FieldsContaine Get the result files -------------------- -First download a result file such as one available with the :ref:`ansys.dpf.core.examples.examples` module. +First download a result file such as one available with the |Examples| module. For more information about how to import your own result file in DPF check the :ref:`ref_tutorials_import_data` tutorial section. @@ -290,7 +291,7 @@ Fixed camera :hide-output: # Define the camera position - cpos = [[1.171, 1.126, 1.621], [0.05, 0.005, 0.5], [0.0, 0.0, 1.0]] + cpos = [[0., 2.0, 0.6], [0.05, 0.005, 0.5], [0.0, 0.0, 1.0]] # Animate the stress with a custom fixed camera position stress_fc.animate(cpos=cpos) @@ -317,8 +318,8 @@ Moving camera cpos_list = [cpos] # Incrementally decrease the y coordinate of the camera by 0.2 for each frame for i in range(1, len(disp_fc)): - new_pos = copy.copy(cpos_list[i-1]) - new_pos[0][1] += 0.2 + new_pos = copy.deepcopy(cpos_list[i-1]) + new_pos[0][0] += 0.1 cpos_list.append(new_pos) # Animate the stress with a moving camera From 04d1f21e06f474d8005e5be7175e42cee350042f Mon Sep 17 00:00:00 2001 From: Paul Profizi <100710998+PProfizi@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:05:28 +0100 Subject: [PATCH 09/15] Apply suggestions from code review Co-authored-by: Luisa Felix Salles --- .../tutorials/animate/animate_time.rst | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index 07e4d3307e9..d3decee0627 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -33,7 +33,7 @@ To animate data across time you need to get the data stored in a |FieldsContaine Get the result files -------------------- -First download a result file such as one available with the |Examples| module. +First, import a result file such as one available with the |Examples| module. For more information about how to import your own result file in DPF check the :ref:`ref_tutorials_import_data` tutorial section. @@ -97,13 +97,13 @@ or on a static mesh (animate the color map only). The default behavior of the |animate| method consists in: -- Showing the norm of the data if multiple components are available; +- Showing the norm of the data components; - Showing data at the top layer for shells; - Showing the deformed mesh when animating displacements; - Showing the static mesh for other types of results; - Using a constant and uniform scale factor of 1.0 when deforming the mesh. -You can animate any result on a deformed geometry by also providing displacements in the `deform_by` parameter. +You can animate any result on a deformed geometry by providing displacement results in the `deform_by` parameter. The geometry can be deformed by a |Result| object, an |Operator| (It must evaluate to a |FieldsContainer| of same length as the one being animated) or a |FieldsContainer| (also of same length as the one being animated). @@ -210,8 +210,11 @@ Change the scale factor You can change the scale factor using: -a) A single number for a uniform constant scaling. +- A single number for a uniform constant scaling; +- A list of numbers for a varying scaling (same length as the number of frames). +Uniform constant scaling +^^^^^^^^^^^^^^^^ .. jupyter-execute:: :hide-output: @@ -231,7 +234,8 @@ a) A single number for a uniform constant scaling. :scale: 45 % :align: center -b) A list of numbers for a varying scaling (same length as the number of frames). +Varying scaling +^^^^^^^^^^ .. jupyter-execute:: :hide-output: @@ -255,8 +259,13 @@ b) A list of numbers for a varying scaling (same length as the number of frames) Save the animation ------------------ -You can save the animation using the ``save_as`` argument with a target file path with the desired format as extension. -Accepted extensions are ``.gif``, ``.avi`` or ``.mp4`` (see |open_movie|). +You can save the animation using the ``save_as`` argument with a target file path with the desired format as the extension key. +Accepted extensions are: +- ``.gif``; +- ``.avi``; +- ``.mp4`` + +For more information see |open_movie|. .. jupyter-execute:: :hide-output: @@ -270,12 +279,18 @@ Control the camera Control the camera with the ``cpos`` argument. -A camera position is a combination of position, focal point (the target), and upwards vector, -resulting in a list of format: +A camera position is a combination of: +- A position; +- A focal point (the target); +- A upwards vector. + +It results in a list of format: .. code-block:: python - [[pos_x, pos_y, pos_z], [fp_x, fp_y, fp_z], [up_x, up_y, up_z]] + camera_position= [[pos_x, pos_y, pos_z], # position + [fp_x, fp_y, fp_z], # focal point + [up_x, up_y, up_z]] # upwards vector The |animate| method accepts a single camera position or a list of camera positions for each frame. From e0a45afc39267c75c6253475d6a2441107c3971e Mon Sep 17 00:00:00 2001 From: Paul Profizi <100710998+PProfizi@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:07:51 +0100 Subject: [PATCH 10/15] Update doc/source/user_guide/tutorials/animate/animate_time.rst --- doc/source/user_guide/tutorials/animate/animate_time.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index d3decee0627..7e5c138c64a 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -111,8 +111,8 @@ of same length as the one being animated) or a |FieldsContainer| (also of same l .. note:: The behavior of the |animate| method is defined by a |Workflow| it creates and feeds to an |Animator|. - This |Workflow| loops over a |Field| of frame indices and for each frame generates a field of contours - to render as well as a displacement field to deform the mesh with if `deform_by` is provided. + This |Workflow| loops over a |Field| of frame indices and for each frame generates a field of norm contours + to render, as well as a displacement field to deform the mesh if `deform_by` is provided. For more information on plots on deformed meshes see: :ref:`ref_plotting_data_on_deformed_mesh`. From cdfb01b27fd4d8fe456b8f04e1960a87a22a7ea4 Mon Sep 17 00:00:00 2001 From: Paul Profizi <100710998+PProfizi@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:19:22 +0100 Subject: [PATCH 11/15] Apply suggestions from code review Co-authored-by: JennaPaikowsky <98607744+JennaPaikowsky@users.noreply.github.com> --- .../tutorials/animate/animate_time.rst | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index 7e5c138c64a..77dec18f7f6 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -21,20 +21,20 @@ Animate data over time .. |Overall| replace:: :class:`overall` .. |open_movie| replace:: :class:`pyvista.Plotter.open_movie` -This tutorial shows how to create 3D animations of data in time. +This tutorial demonstrates how to create 3D animations of data in time. :jupyter-download-script:`Download tutorial as Python script` :jupyter-download-notebook:`Download tutorial as notebook` -To animate data across time you need to get the data stored in a |FieldsContainer| labeled in time. +To animate data across time, you must store the data in a |FieldsContainer| labeled in time. Get the result files -------------------- -First, import a result file such as one available with the |Examples| module. -For more information about how to import your own result file in DPF check +First, import a results file. For this tutorial, you can use the one available in the |Examples| module. +For more information about how to import your own result file in DPF, see the :ref:`ref_tutorials_import_data` tutorial section. .. jupyter-execute:: @@ -53,9 +53,9 @@ the :ref:`ref_tutorials_import_data` tutorial section. Define a time scoping --------------------- -To animate across time we first need to define the time steps of interest. -Here we get all the time steps available in the |TimeFreqSupport|, but you can also filter them. -For more information on how to define a scoping check the ``Narrow down data`` tutorial in the +To animate across time, you must define the time steps you are interested in. +This tutorial retrieves all the time steps available in |TimeFreqSupport|, but you can also filter them. +For more information on how to define a scoping, see the ``Narrow down data`` tutorial in the :ref:`ref_tutorials_import_data` tutorials section. .. jupyter-execute:: @@ -66,11 +66,11 @@ For more information on how to define a scoping check the ``Narrow down data`` t Extract the results ------------------- -Extract the results to animate. Here we get the displacement and stress results. +Extract the results to animate. In this tutorial, you extract the displacement and stress results. .. note:: - Only locations |Elemental|, |Nodal| or |Faces| are supported for animations. + Only the |Elemental|, |Nodal|, or |Faces| locations are supported for animations. |Overall| and |ElementalNodal| locations are not currently supported. @@ -95,18 +95,18 @@ Animate the results with the |animate| method. You can animate them on a deformed mesh (animate the color map and the mesh) or on a static mesh (animate the color map only). -The default behavior of the |animate| method consists in: +The default behavior of the |animate| method is to: -- Showing the norm of the data components; -- Showing data at the top layer for shells; -- Showing the deformed mesh when animating displacements; -- Showing the static mesh for other types of results; -- Using a constant and uniform scale factor of 1.0 when deforming the mesh. +- Display the norm of the data components; +- Display data at the top layer for shells; +- Display the deformed mesh when animating displacements; +- Display the static mesh for other types of results; +- Use a constant and uniform scale factor of 1.0 when deforming the mesh. You can animate any result on a deformed geometry by providing displacement results in the `deform_by` parameter. The geometry can be deformed by a |Result| object, an |Operator| (It must evaluate to a |FieldsContainer| -of same length as the one being animated) or a |FieldsContainer| (also of same length as the one being animated). +of same length as the one being animated), or a |FieldsContainer| (also of same length as the one being animated). .. note:: From 899d8e2075fcbeaee4cf6f40ea05c59ea8d940f2 Mon Sep 17 00:00:00 2001 From: Paul Profizi <100710998+PProfizi@users.noreply.github.com> Date: Thu, 28 Nov 2024 15:09:03 +0100 Subject: [PATCH 12/15] Apply suggestions from code review Co-authored-by: Luisa Felix Salles --- .../tutorials/animate/animate_time.rst | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index 77dec18f7f6..a18f5df0477 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -45,7 +45,8 @@ the :ref:`ref_tutorials_import_data` tutorial section. from ansys.dpf.core import examples # Import the operators module from ansys.dpf.core import operators as ops - # Define the result file + + # Define the result file path result_file_path = examples.find_msup_transient() # Create the model model = dpf.Model(data_sources=result_file_path) @@ -61,7 +62,7 @@ For more information on how to define a scoping, see the ``Narrow down data`` tu .. jupyter-execute:: # Get a scoping of all time steps available - time_scoping = model.metadata.time_freq_support.time_frequencies + time_steps = model.metadata.time_freq_support.time_frequencies Extract the results ------------------- @@ -77,15 +78,14 @@ Extract the results to animate. In this tutorial, you extract the displacement a .. jupyter-execute:: # Get the displacement fields (already on nodes) at all time steps - disp_fc = model.results.displacement(time_scoping=time_scoping).eval() + disp_fc = model.results.displacement(time_scoping=time_steps).eval() print(disp_fc) .. jupyter-execute:: # Get the stress fields on nodes at all time steps - stress_fc = model.results.stress.on_location( - location=dpf.locations.nodal).on_time_scoping( - time_scoping=time_scoping).eval() + # Request the stress on |Nodal| location as the default |ElementalNodal| location is not supported. + stress_fc = model.results.stress.on_location(location=dpf.locations.nodal).on_time_scoping(time_scoping=time_steps).eval() print(stress_fc) Animate the results @@ -306,9 +306,9 @@ Fixed camera :hide-output: # Define the camera position - cpos = [[0., 2.0, 0.6], [0.05, 0.005, 0.5], [0.0, 0.0, 1.0]] + cam_pos = [[0., 2.0, 0.6], [0.05, 0.005, 0.5], [0.0, 0.0, 1.0]] # Animate the stress with a custom fixed camera position - stress_fc.animate(cpos=cpos) + stress_fc.animate(cpos=cam_pos) .. jupyter-execute:: :hide-code: @@ -328,10 +328,10 @@ Moving camera .. jupyter-execute:: :hide-output: - # Define the list of camera positions import copy - cpos_list = [cpos] - # Incrementally decrease the y coordinate of the camera by 0.2 for each frame + # Define the list of camera positions + cpos_list = [cam_pos] + # Incrementally increase the x coordinate of the camera by 0.1 for each frame for i in range(1, len(disp_fc)): new_pos = copy.deepcopy(cpos_list[i-1]) new_pos[0][0] += 0.1 From cd719b59aa400b7b992bec39a5f6005dc64bc429 Mon Sep 17 00:00:00 2001 From: Paul Profizi <100710998+PProfizi@users.noreply.github.com> Date: Thu, 28 Nov 2024 15:22:36 +0100 Subject: [PATCH 13/15] Apply suggestions from code review --- doc/source/user_guide/tutorials/animate/animate_time.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index a18f5df0477..ebc0e6f4b80 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -27,7 +27,7 @@ This tutorial demonstrates how to create 3D animations of data in time. :jupyter-download-notebook:`Download tutorial as notebook` -To animate data across time, you must store the data in a |FieldsContainer| labeled in time. +To animate data across time, you must store the data in a |FieldsContainer| with a ``time`` label. Get the result files From 18fa9dc4a475bf8922ae062c61b62064da1bc9df Mon Sep 17 00:00:00 2001 From: Luisa Felix Salles Date: Thu, 28 Nov 2024 15:35:49 +0100 Subject: [PATCH 14/15] Update doc/source/user_guide/tutorials/animate/animate_time.rst --- doc/source/user_guide/tutorials/animate/animate_time.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index ebc0e6f4b80..09a5013d2de 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -23,9 +23,7 @@ Animate data over time This tutorial demonstrates how to create 3D animations of data in time. -:jupyter-download-script:`Download tutorial as Python script` - -:jupyter-download-notebook:`Download tutorial as notebook` +:jupyter-download-script:`Download tutorial as Python script` :jupyter-download-notebook:`Download tutorial as Jupyter notebook` To animate data across time, you must store the data in a |FieldsContainer| with a ``time`` label. From d99c2edba4ea6adf3d368a48b435033ba45ef4a0 Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Fri, 29 Nov 2024 18:01:53 +0100 Subject: [PATCH 15/15] updates --- .../user_guide/tutorials/animate/animate_time.rst | 12 ++++++------ doc/source/user_guide/tutorials/animate/index.rst | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/source/user_guide/tutorials/animate/animate_time.rst b/doc/source/user_guide/tutorials/animate/animate_time.rst index 09a5013d2de..39feabeb534 100644 --- a/doc/source/user_guide/tutorials/animate/animate_time.rst +++ b/doc/source/user_guide/tutorials/animate/animate_time.rst @@ -83,7 +83,7 @@ Extract the results to animate. In this tutorial, you extract the displacement a # Get the stress fields on nodes at all time steps # Request the stress on |Nodal| location as the default |ElementalNodal| location is not supported. - stress_fc = model.results.stress.on_location(location=dpf.locations.nodal).on_time_scoping(time_scoping=time_steps).eval() + stress_fc = model.results.stress.on_location(location=dpf.locations.nodal).on_time_scoping(time_scoping=time_steps).eval() print(stress_fc) Animate the results @@ -212,7 +212,7 @@ You can change the scale factor using: - A list of numbers for a varying scaling (same length as the number of frames). Uniform constant scaling -^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^ .. jupyter-execute:: :hide-output: @@ -233,7 +233,7 @@ Uniform constant scaling :align: center Varying scaling -^^^^^^^^^^ +^^^^^^^^^^^^^^^ .. jupyter-execute:: :hide-output: @@ -287,8 +287,8 @@ It results in a list of format: .. code-block:: python camera_position= [[pos_x, pos_y, pos_z], # position - [fp_x, fp_y, fp_z], # focal point - [up_x, up_y, up_z]] # upwards vector + [fp_x, fp_y, fp_z], # focal point + [up_x, up_y, up_z]] # upwards vector The |animate| method accepts a single camera position or a list of camera positions for each frame. @@ -313,7 +313,7 @@ Fixed camera :hide-output: stress_fc.animate(save_as="source/user_guide/tutorials/animate/animate_disp_5.gif", - cpos=cpos, + cpos=cam_pos, off_screen=True) .. image:: animate_disp_5.gif diff --git a/doc/source/user_guide/tutorials/animate/index.rst b/doc/source/user_guide/tutorials/animate/index.rst index 45820480852..6f360c42162 100644 --- a/doc/source/user_guide/tutorials/animate/index.rst +++ b/doc/source/user_guide/tutorials/animate/index.rst @@ -4,7 +4,7 @@ Animate ======= -These tutorials demonstrate how to visualise the data in an animation. +These tutorials demonstrate how to visualize the data as an animation. .. grid:: 1 1 3 3 :gutter: 2