From 517dc1acdc533990887c7d1ced6f61e59dc3d2ac Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Thu, 19 Sep 2024 11:17:45 +0200 Subject: [PATCH 1/8] update the requirements for the documentation build --- requirements/requirements_docs.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements/requirements_docs.txt b/requirements/requirements_docs.txt index 3829e8cb2f..df5b2a087a 100644 --- a/requirements/requirements_docs.txt +++ b/requirements/requirements_docs.txt @@ -1,4 +1,4 @@ -ansys_sphinx_theme==0.16.5 +ansys-sphinx-theme[autoapi]==1.0.8 enum-tools[sphinx]==0.12.0 graphviz==0.20.1 imageio==2.35.1 @@ -13,5 +13,5 @@ sphinx-copybutton==0.5.2 sphinx-gallery==0.17.0 sphinx-notfound-page==1.0.4 sphinx-reredirects==0.1.3 -sphinx_design==0.6.0 +sphinx_design==0.6.1 sphinxcontrib-napoleon==0.7 From 617e55ba3bb161131440977a30db869f3e8d726b Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Thu, 19 Sep 2024 11:22:56 +0200 Subject: [PATCH 2/8] adapt logo for dark and light modes --- doc/source/conf.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 4042e35481..0fe332b909 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -7,7 +7,7 @@ import pyvista from ansys.dpf.core import __version__, server, server_factory from ansys.dpf.core.examples import get_example_required_minimum_dpf_version -from ansys_sphinx_theme import pyansys_logo_black, ansys_favicon, get_version_match +from ansys_sphinx_theme import ansys_favicon, get_version_match, pyansys_logo_light_mode, pyansys_logo_dark_mode # Manage errors pyvista.set_error_output_file("errors.txt") @@ -76,6 +76,7 @@ extensions = [ "enum_tools.autoenum", "nbsphinx", + "sphinx.ext.autosummary", "sphinx.ext.autosectionlabel", "sphinx.ext.autodoc", "sphinx.ext.graphviz", @@ -193,7 +194,6 @@ def reset_servers(gallery_conf, fname, when): # -- Options for HTML output ------------------------------------------------- html_short_title = html_title = "PyDPF-Core" html_theme = "ansys_sphinx_theme" -html_logo = pyansys_logo_black html_favicon = ansys_favicon html_theme_options = { "github_url": "https://github.com/ansys/pydpf-core", @@ -202,6 +202,10 @@ def reset_servers(gallery_conf, fname, when): "additional_breadcrumbs": [ ("PyAnsys", "https://docs.pyansys.com/"), ], + "logo": { + "image_dark": pyansys_logo_dark_mode, + "image_light": pyansys_logo_light_mode, + }, "switcher": { "json_url": f"https://{cname}/versions.json", "version_match": get_version_match(__version__), From cc32eae0bcfa9773ba6917a0662c7740abc5df56 Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Thu, 19 Sep 2024 11:25:11 +0200 Subject: [PATCH 3/8] add a substitution text (about the accepted solvers apps in DPF) to be used on the doc --- doc/source/substitution_solvers.rst | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 doc/source/substitution_solvers.rst diff --git a/doc/source/substitution_solvers.rst b/doc/source/substitution_solvers.rst new file mode 100644 index 0000000000..73d7dd0389 --- /dev/null +++ b/doc/source/substitution_solvers.rst @@ -0,0 +1,53 @@ +.. _ref_substitution_solvers: + +.. Information about the interactions between apps and DPF + +.. Files formats + +.. MAPDL +.. |MAPDL_files| replace:: .rst, .mode, .rfrq, .rdsp + +.. LSDYNA +.. |LS-DYNA_files| replace:: .d3plot, .binout + +.. Fluent +.. |Fluent_files1| replace:: **CFF restart files** : .cas.h5, dat.h5 +.. |Fluent_files2| replace:: **Project files** : .flprj + +.. CFX +.. |CFX_files1| replace:: **CFF files** : .cas.cff.res, dat.cff.res +.. |CFX_files2| replace:: **Project files** : .flprj + + +.. Server version + +.. MAPDL +.. |MAPDL_version| replace:: **1.0** and later (*Ansys 2021 R1*) + +.. LSDYNA +.. |LS-DYNA_version| replace:: **4.0** and later (*Ansys 2022 R2*) + +.. Fluent +.. |Fluent_version| replace:: **7.0** and later (*Ansys 2024 R1 pre0*) + +.. CFX +.. |CFX_version| replace:: **7.0** and later (*Ansys 2024 R1 pre0*) + +.. DPF examples + +.. MAPDL +.. |MAPDL_example| replace:: :ref:`ref_basic_example` + +.. LSDYNA +.. |LS-DYNA_example| replace:: :ref:`examples_lsdyna` + +.. Fluent +.. |Fluent_example1| replace:: :ref:`ref_fluids_model` +.. |Fluent_example2| replace:: :ref:`ref_fluids_mesh` +.. |Fluent_example3| replace:: :ref:`ref_fluids_results` + +.. CFX +.. |CFX_example1| replace:: :ref:`examples_cfx` +.. |CFX_example2| replace:: :ref:`ref_fluids_model` +.. |CFX_example3| replace:: :ref:`ref_fluids_mesh` +.. |CFX_example4| replace:: :ref:`ref_fluids_results` From 98b2b266cf6fac93c695310b90f094b2b900d7ff Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Thu, 19 Sep 2024 11:26:59 +0200 Subject: [PATCH 4/8] move the concepts section into the user guide section --- doc/source/index.rst | 1 - doc/source/{ => user_guide}/concepts/concepts.rst | 0 doc/source/{ => user_guide}/concepts/index.rst | 0 doc/source/{ => user_guide}/concepts/stepbystep.rst | 0 doc/source/{ => user_guide}/concepts/waysofusing.rst | 0 5 files changed, 1 deletion(-) rename doc/source/{ => user_guide}/concepts/concepts.rst (100%) rename doc/source/{ => user_guide}/concepts/index.rst (100%) rename doc/source/{ => user_guide}/concepts/stepbystep.rst (100%) rename doc/source/{ => user_guide}/concepts/waysofusing.rst (100%) diff --git a/doc/source/index.rst b/doc/source/index.rst index bef595d83d..fda0a3a1de 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -193,5 +193,4 @@ To reach the project support team, email `pyansys.core@ansys.com Date: Thu, 19 Sep 2024 16:53:40 +0200 Subject: [PATCH 5/8] add a new extension "sphinx_exec_code" --- doc/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/conf.py b/doc/source/conf.py index 0fe332b909..12e3047461 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -88,6 +88,7 @@ "sphinx_design", "sphinx_gallery.gen_gallery", 'sphinx_reredirects', + "sphinx_exec_code", ] redirects = { From 2d4f56583d72e4746e476e46a387980d5f8a86b6 Mon Sep 17 00:00:00 2001 From: Luisa Felix Salles Date: Tue, 24 Sep 2024 15:27:47 +0200 Subject: [PATCH 6/8] Changes in the user guide layout (#1763) * add concepts intro in the user guide index page * add tutorials concept (from the main entities documents) * organise and adapt the how-to section * organise and adapt the troubleshooting section * organise and adapt the troubleshooting section and final sidebar * changes in the troubleshooting index page * changes in the how to index page * changes in the concepts index page * changes in the layout of the index pages * Apply suggestions from code review Co-authored-by: Paul Profizi <100710998+PProfizi@users.noreply.github.com> * corrections after first revision * Apply suggestions from code review Co-authored-by: Paul Profizi <100710998+PProfizi@users.noreply.github.com> * Add sphinx-exec-code to doc requirements * corrections files path * Apply suggestions from code review Co-authored-by: Paul Profizi <100710998+PProfizi@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Paul Profizi <100710998+PProfizi@users.noreply.github.com> --------- Co-authored-by: Paul Profizi <100710998+PProfizi@users.noreply.github.com> --- doc/source/user_guide/concepts/concepts.rst | 8 +- doc/source/user_guide/concepts/index.rst | 32 ++----- doc/source/user_guide/concepts/stepbystep.rst | 18 ++-- .../user_guide/concepts/waysofusing.rst | 6 +- .../create_sites_for_python_operators.ps1 | 0 .../create_sites_for_python_operators.sh | 0 .../{ => how-to}/custom_operator_example.py | 0 .../{ => how-to}/custom_operators.rst | 8 +- .../{ => how-to}/custom_operators_deps.rst | 4 +- .../user_guide/{ => how-to}/custom_plugin.xml | 0 doc/source/user_guide/how-to/index.rst | 39 ++++++++ .../install_ansys_dpf_core_in_ansys.ps1 | 0 .../install_ansys_dpf_core_in_ansys.sh | 0 .../{ => how-to}/server_context.rst | 0 .../user_guide/{ => how-to}/server_types.rst | 0 .../uninstall_ansys_dpf_core_in_ansys.ps1 | 0 .../uninstall_ansys_dpf_core_in_ansys.sh | 0 .../user_guide/{ => how-to}/xmlfiles.rst | 0 doc/source/user_guide/how_to.rst | 73 -------------- doc/source/user_guide/index.rst | 49 ++++++++-- doc/source/user_guide/main_entities.rst | 43 --------- .../user_guide/troubleshooting/index.rst | 39 ++++++++ .../{ => troubleshooting}/troubleshooting.rst | 21 +++- .../{ => tutorials}/fields_container.rst | 0 doc/source/user_guide/tutorials/index.rst | 96 +++++++++++++++++++ .../user_guide/{ => tutorials}/model.rst | 2 +- .../user_guide/{ => tutorials}/operators.rst | 0 .../user_guide/{ => tutorials}/plotting.rst | 0 .../02-python_operators_with_dependencies.py | 6 +- requirements/requirements_docs.txt | 1 + 30 files changed, 270 insertions(+), 175 deletions(-) rename doc/source/user_guide/{ => how-to}/create_sites_for_python_operators.ps1 (100%) rename doc/source/user_guide/{ => how-to}/create_sites_for_python_operators.sh (100%) rename doc/source/user_guide/{ => how-to}/custom_operator_example.py (100%) rename doc/source/user_guide/{ => how-to}/custom_operators.rst (97%) rename doc/source/user_guide/{ => how-to}/custom_operators_deps.rst (94%) rename doc/source/user_guide/{ => how-to}/custom_plugin.xml (100%) create mode 100644 doc/source/user_guide/how-to/index.rst rename doc/source/user_guide/{ => how-to}/install_ansys_dpf_core_in_ansys.ps1 (100%) rename doc/source/user_guide/{ => how-to}/install_ansys_dpf_core_in_ansys.sh (100%) rename doc/source/user_guide/{ => how-to}/server_context.rst (100%) rename doc/source/user_guide/{ => how-to}/server_types.rst (100%) rename doc/source/user_guide/{ => how-to}/uninstall_ansys_dpf_core_in_ansys.ps1 (100%) rename doc/source/user_guide/{ => how-to}/uninstall_ansys_dpf_core_in_ansys.sh (100%) rename doc/source/user_guide/{ => how-to}/xmlfiles.rst (100%) delete mode 100644 doc/source/user_guide/how_to.rst delete mode 100644 doc/source/user_guide/main_entities.rst create mode 100644 doc/source/user_guide/troubleshooting/index.rst rename doc/source/user_guide/{ => troubleshooting}/troubleshooting.rst (94%) rename doc/source/user_guide/{ => tutorials}/fields_container.rst (100%) create mode 100644 doc/source/user_guide/tutorials/index.rst rename doc/source/user_guide/{ => tutorials}/model.rst (99%) rename doc/source/user_guide/{ => tutorials}/operators.rst (100%) rename doc/source/user_guide/{ => tutorials}/plotting.rst (100%) diff --git a/doc/source/user_guide/concepts/concepts.rst b/doc/source/user_guide/concepts/concepts.rst index f7bba20fc9..c2b9bb3ac2 100644 --- a/doc/source/user_guide/concepts/concepts.rst +++ b/doc/source/user_guide/concepts/concepts.rst @@ -67,7 +67,7 @@ Concept summary --------------- This image summarizes the preceding concepts: -.. image:: ../images/drawings/field-breakdown.png +.. image:: ../../images/drawings/field-breakdown.png Operators @@ -79,7 +79,7 @@ You use :ref:`ref_dpf_operators_reference` to create, transform, and stream the - The input and output pins, like those in an integrated circuit in electronics, submit data to the operator and output the computed result from the operator. -.. image:: ../images/drawings/OperatorPins.png +.. image:: ../../images/drawings/OperatorPins.png Workflows --------- @@ -90,10 +90,10 @@ to operators, which computes requested outputs. Think of a workflow as a black box in which some operators are chained, computing the information for which the workflow is made: -.. image:: ../images/drawings/Workflow1.png +.. image:: ../../images/drawings/Workflow1.png The following image shows operators that have been chained together to create a total deformation workflow. You can use this workflow in any simulation workflow with any data sources as inputs. -.. image:: ../images/drawings/Workflow2.png +.. image:: ../../images/drawings/Workflow2.png diff --git a/doc/source/user_guide/concepts/index.rst b/doc/source/user_guide/concepts/index.rst index ebaaf9257a..92bd2d63ad 100644 --- a/doc/source/user_guide/concepts/index.rst +++ b/doc/source/user_guide/concepts/index.rst @@ -1,44 +1,28 @@ -.. _ref_concepts: +.. _ref_concepts_index: -======== Concepts -======== +-------- -This section provides in-depth descriptions and explanations of DPF concepts, including terminology. +.. grid:: 3 + :gutter: 2 -DPF concepts -~~~~~~~~~~~~ - -.. toctree:: - :hidden: - - concepts.rst - waysofusing.rst - stepbystep.rst - - -.. card-carousel:: 2 - - .. card:: Concepts and terminology + .. grid-item-card:: Concepts and terminology :link: user_guide_concepts :link-type: ref - :width: 25% :text-align: center .. image:: ../images/drawings/book-logo.png - .. card:: Ways of using DPF + .. grid-item-card:: Ways of using DPF :link: user_guide_waysofusing :link-type: ref - :width: 25% :text-align: center .. image:: ../images/drawings/using-dpf.png - .. card:: Using DPF: Step by step + .. grid-item-card:: Using DPF: Step by step :link: user_guide_stepbystep :link-type: ref - :width: 25% :text-align: center - .. image:: ../images/drawings/checklist.png + .. image:: ../images/drawings/checklist.png \ No newline at end of file diff --git a/doc/source/user_guide/concepts/stepbystep.rst b/doc/source/user_guide/concepts/stepbystep.rst index 1c72c53db8..55b9caad74 100644 --- a/doc/source/user_guide/concepts/stepbystep.rst +++ b/doc/source/user_guide/concepts/stepbystep.rst @@ -53,11 +53,11 @@ Define fields A **field** is a container of simulation data. In numerical simulations, result data is defined by values associated with entities: -.. image:: ../images/drawings/values-entities.png +.. image:: ../../images/drawings/values-entities.png Therefore, a field of data might look something like this: -.. image:: ../images/drawings/field.png +.. image:: ../../images/drawings/field.png This code shows how to define a field from scratch: @@ -83,7 +83,7 @@ be a set of mesh IDs, geometric entity IDs, time domain, or frequency domain. You specify the set of entities by defining a range of IDs: -.. image:: ../images/drawings/scoping-eg.png +.. image:: ../../images/drawings/scoping-eg.png You must define a scoping prior to its use in the transformation data workflow. @@ -109,13 +109,13 @@ A **field container** holds a set of fields. It is used mainly for transient, harmonic, modal, or multi-step analyses. This image explains its structure: -.. image:: ../images/drawings/field-con-overview.png +.. image:: ../../images/drawings/field-con-overview.png A field container is a vector of fields. Fields are ordered with labels and IDs. Most commonly, a field container is scoped on the time label, and the IDs are the time or frequency sets: -.. image:: ../images/drawings/field-con.png +.. image:: ../../images/drawings/field-con.png You can define a field container in multiple ways: @@ -162,14 +162,14 @@ An operator takes input from a field, field container, or scoping using an input pin. Based on what it is designed to do, the operator computes an output that it passes to a field or field container using an output pin. -.. image:: ../images/drawings/circuit.png +.. image:: ../../images/drawings/circuit.png Comprehensive information on operators is available in :ref:`ref_dpf_operators_reference`. In the **Available Operators** area for either the **Entry** or **Premium** operators, you can either type a keyword in the **Search** option or browse by operator categories: -.. image:: ../images/drawings/help-operators.png +.. image:: ../../images/drawings/help-operators.png The page for each operator describes how the operator transforms data, indicates input and output data, and provides usage examples. @@ -185,7 +185,7 @@ Defining an operator consists of three steps: This image shows how the page for an operator provides a usage example for each available language (IronPython, CPython, and C++). -.. image:: ../images/drawings/operator-def.png +.. image:: ../../images/drawings/operator-def.png This code shows how to define an operator from a model: @@ -210,7 +210,7 @@ the input to another operator. This image shows how you would get the norm of a resulting vector from the dot product of two vectors: -.. image:: ../images/drawings/connect-operators.png +.. image:: ../../images/drawings/connect-operators.png This code shows how to define a generic workflow that computes the minimum of displacement by chaining the ``U`` and ``min_max_fc`` operators: diff --git a/doc/source/user_guide/concepts/waysofusing.rst b/doc/source/user_guide/concepts/waysofusing.rst index 25077c38da..4887669f38 100644 --- a/doc/source/user_guide/concepts/waysofusing.rst +++ b/doc/source/user_guide/concepts/waysofusing.rst @@ -29,7 +29,7 @@ enabled using the DPF Server application. These capabilities can be accessed through client APIs, as shown here: -.. image:: ../images/drawings/apis_2.png +.. image:: ../../images/drawings/apis_2.png 1. DPF server application can be accessed using Ansys Inc product, or DPF Server package (see :ref:`ref_dpf_server`) available on the Customer portal. @@ -71,7 +71,7 @@ files. You can use it to generate TH-plots, screenshots, and animations or to create custom result plots using the `numpy `_ and `matplotlib `_ packages. -.. image:: ../images/drawings/dpf-reports.png +.. image:: ../../images/drawings/dpf-reports.png Mechanical ~~~~~~~~~~ @@ -79,4 +79,4 @@ Mechanical Use it to perform custom postprocessing and visualization of results directly within the Mechanical application. -.. image:: ../images/drawings/dpf-mech.png \ No newline at end of file +.. image:: ../../images/drawings/dpf-mech.png \ No newline at end of file diff --git a/doc/source/user_guide/create_sites_for_python_operators.ps1 b/doc/source/user_guide/how-to/create_sites_for_python_operators.ps1 similarity index 100% rename from doc/source/user_guide/create_sites_for_python_operators.ps1 rename to doc/source/user_guide/how-to/create_sites_for_python_operators.ps1 diff --git a/doc/source/user_guide/create_sites_for_python_operators.sh b/doc/source/user_guide/how-to/create_sites_for_python_operators.sh similarity index 100% rename from doc/source/user_guide/create_sites_for_python_operators.sh rename to doc/source/user_guide/how-to/create_sites_for_python_operators.sh diff --git a/doc/source/user_guide/custom_operator_example.py b/doc/source/user_guide/how-to/custom_operator_example.py similarity index 100% rename from doc/source/user_guide/custom_operator_example.py rename to doc/source/user_guide/how-to/custom_operator_example.py diff --git a/doc/source/user_guide/custom_operators.rst b/doc/source/user_guide/how-to/custom_operators.rst similarity index 97% rename from doc/source/user_guide/custom_operators.rst rename to doc/source/user_guide/how-to/custom_operators.rst index 1e211bd5b0..3f521303b1 100644 --- a/doc/source/user_guide/custom_operators.rst +++ b/doc/source/user_guide/how-to/custom_operators.rst @@ -34,8 +34,8 @@ installer's Python interpreter. #. Download the script for you operating system: - - For Windows, download this :download:`PowerShell script `. - - For Linux, download this :download:`Shell script ` + - For Windows, download this :download:`PowerShell script `. + - For Linux, download this :download:`Shell script ` #. Run the downloaded script for installing with optional arguments: @@ -48,8 +48,8 @@ If you ever want to uninstall the ``ansys-dpf-core`` module from the Ansys insta #. Download the script for your operating system: - - For Windows, download this :download:`PowerShell script `. - - For Linux, download this :download:`Shell script `. + - For Windows, download this :download:`PowerShell script `. + - For Linux, download this :download:`Shell script `. 3. Run the downloaded script for uninstalling with the optional argument: diff --git a/doc/source/user_guide/custom_operators_deps.rst b/doc/source/user_guide/how-to/custom_operators_deps.rst similarity index 94% rename from doc/source/user_guide/custom_operators_deps.rst rename to doc/source/user_guide/how-to/custom_operators_deps.rst index 754b587947..9ee680ba8f 100644 --- a/doc/source/user_guide/custom_operators_deps.rst +++ b/doc/source/user_guide/how-to/custom_operators_deps.rst @@ -23,8 +23,8 @@ For this approach, do the following: #. Download the script for your operating system: - - For Windows, download this :download:`PowerShell script `. - - For Linux, download this :download:`Shell script `. + - For Windows, download this :download:`PowerShell script `. + - For Linux, download this :download:`Shell script `. 3. Run the downloaded script with the mandatory arguments: diff --git a/doc/source/user_guide/custom_plugin.xml b/doc/source/user_guide/how-to/custom_plugin.xml similarity index 100% rename from doc/source/user_guide/custom_plugin.xml rename to doc/source/user_guide/how-to/custom_plugin.xml diff --git a/doc/source/user_guide/how-to/index.rst b/doc/source/user_guide/how-to/index.rst new file mode 100644 index 0000000000..821a728ae1 --- /dev/null +++ b/doc/source/user_guide/how-to/index.rst @@ -0,0 +1,39 @@ +.. _ref_how_to: + +Enriching DPF capabilities +---------------------------------------- + +.. grid:: 3 + :gutter: 2 + + .. grid-item-card:: Create custom operators and plugins + :link: user_guide_custom_operators + :link-type: ref + :text-align: center + + .. image:: ../images/drawings/plugin-logo.png + :width: 50% + + + .. grid-item-card:: Switch between local and remote server + :link: user_guide_server_types + :link-type: ref + :text-align: center + + .. image:: ../images/drawings/remote_machines.png + + + .. grid-item-card:: Access Entry and Premium capabilities + :link: user_guide_server_context + :link-type: ref + :text-align: center + + .. image:: ../images/drawings/entry_premium.png + + + .. grid-item-card:: Configure DPF plugins load + :link: user_guide_xmlfiles + :link-type: ref + :text-align: center + + .. image:: ../images/drawings/xml.png \ No newline at end of file diff --git a/doc/source/user_guide/install_ansys_dpf_core_in_ansys.ps1 b/doc/source/user_guide/how-to/install_ansys_dpf_core_in_ansys.ps1 similarity index 100% rename from doc/source/user_guide/install_ansys_dpf_core_in_ansys.ps1 rename to doc/source/user_guide/how-to/install_ansys_dpf_core_in_ansys.ps1 diff --git a/doc/source/user_guide/install_ansys_dpf_core_in_ansys.sh b/doc/source/user_guide/how-to/install_ansys_dpf_core_in_ansys.sh similarity index 100% rename from doc/source/user_guide/install_ansys_dpf_core_in_ansys.sh rename to doc/source/user_guide/how-to/install_ansys_dpf_core_in_ansys.sh diff --git a/doc/source/user_guide/server_context.rst b/doc/source/user_guide/how-to/server_context.rst similarity index 100% rename from doc/source/user_guide/server_context.rst rename to doc/source/user_guide/how-to/server_context.rst diff --git a/doc/source/user_guide/server_types.rst b/doc/source/user_guide/how-to/server_types.rst similarity index 100% rename from doc/source/user_guide/server_types.rst rename to doc/source/user_guide/how-to/server_types.rst diff --git a/doc/source/user_guide/uninstall_ansys_dpf_core_in_ansys.ps1 b/doc/source/user_guide/how-to/uninstall_ansys_dpf_core_in_ansys.ps1 similarity index 100% rename from doc/source/user_guide/uninstall_ansys_dpf_core_in_ansys.ps1 rename to doc/source/user_guide/how-to/uninstall_ansys_dpf_core_in_ansys.ps1 diff --git a/doc/source/user_guide/uninstall_ansys_dpf_core_in_ansys.sh b/doc/source/user_guide/how-to/uninstall_ansys_dpf_core_in_ansys.sh similarity index 100% rename from doc/source/user_guide/uninstall_ansys_dpf_core_in_ansys.sh rename to doc/source/user_guide/how-to/uninstall_ansys_dpf_core_in_ansys.sh diff --git a/doc/source/user_guide/xmlfiles.rst b/doc/source/user_guide/how-to/xmlfiles.rst similarity index 100% rename from doc/source/user_guide/xmlfiles.rst rename to doc/source/user_guide/how-to/xmlfiles.rst diff --git a/doc/source/user_guide/how_to.rst b/doc/source/user_guide/how_to.rst deleted file mode 100644 index 8d4247b932..0000000000 --- a/doc/source/user_guide/how_to.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. _ref_how_to: - -How-tos -~~~~~~~ - -.. toctree:: - :hidden: - - plotting.rst - custom_operators.rst - dpf_server.rst - server_types.rst - server_context.rst - xmlfiles.rst - - -.. card-carousel:: 2 - - .. card:: Plot - :link: user_guide_plotting - :link-type: ref - :width: 25% - :text-align: center - - .. image:: ../images/plotting/pontoon.png - .. image:: ../images/plotting/pontoon_strain.png - - - .. card:: Create custom operators - :link: user_guide_custom_operators - :link-type: ref - :width: 25% - :text-align: center - - .. image:: ../images/drawings/plugin-logo.png - :width: 50% - - - .. card:: Use DPF Server package - :link: ref_dpf_server - :link-type: ref - :width: 25% - :text-align: center - - .. image:: ../images/drawings/dpf_server_client.png - - -.. card-carousel:: 2 - - .. card:: Switch between local and remote server - :link: user_guide_server_types - :link-type: ref - :width: 25% - :text-align: center - - .. image:: ../images/drawings/remote_machines.png - - .. card:: Access Entry and Premium capabilities - :link: user_guide_server_context - :link-type: ref - :width: 25% - :text-align: center - - .. image:: ../images/drawings/entry_premium.png - - - .. card:: Use DPF XML Files - :link: user_guide_xmlfiles - :link-type: ref - :width: 25% - :text-align: center - - .. image:: ../images/drawings/xml.png \ No newline at end of file diff --git a/doc/source/user_guide/index.rst b/doc/source/user_guide/index.rst index 65b8cf0a28..2095c6699c 100644 --- a/doc/source/user_guide/index.rst +++ b/doc/source/user_guide/index.rst @@ -11,18 +11,55 @@ computation, customization, and remote postprocessing accessible in Python. The goals of this section are to: - Describe the most-used DPF entities and how they can help you to access and modify solver data. - - Provide simple how-tos for tackling the most common use cases. + - Provide simple tutorials for tackling the most common use cases. + - Explain how to customize DPF behavior. + - Present some systematic approaches to determine the cause of a malfunction or failure when using DPF. +.. include:: + concepts/index.rst + +.. include:: + tutorials/index.rst .. include:: - main_entities.rst + how-to/index.rst .. include:: - how_to.rst + troubleshooting/index.rst + + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Concepts + concepts/concepts.rst + concepts/waysofusing.rst + concepts/stepbystep.rst -Troubleshooting -~~~~~~~~~~~~~~~ +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Tutorials + + tutorials/model.rst + tutorials/operators.rst + tutorials/fields_container.rst + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Accessing and enriching DPF capabilities + + how-to/plotting.rst + how-to/custom_operators.rst + how-to/server_context.rst + how-to/server_types.rst + how-to/xmlfiles.rst .. toctree:: - troubleshooting + :maxdepth: 1 + :hidden: + :caption: Troubleshooting + + troubleshooting/troubleshooting.rst diff --git a/doc/source/user_guide/main_entities.rst b/doc/source/user_guide/main_entities.rst deleted file mode 100644 index b98991d0f0..0000000000 --- a/doc/source/user_guide/main_entities.rst +++ /dev/null @@ -1,43 +0,0 @@ -.. _ref_main_entities: - -DPF most-used entities -~~~~~~~~~~~~~~~~~~~~~~ - -.. toctree:: - :hidden: - - model - operators - fields_container - -.. card-carousel:: 2 - - .. card:: DPF model - :link: user_guide_model - :link-type: ref - :width: 25% - :text-align: center - - .. image:: ../images/drawings/model.png - - .. card:: Fields container and fields - :link: ref_user_guide_fields_container - :link-type: ref - :width: 25% - :text-align: center - - .. image:: ../images/drawings/field.png - - .. card:: Operators - :link: ref_user_guide_operators - :link-type: ref - :width: 25% - :text-align: center - - .. image:: ../images/drawings/small_operator.svg - - - - - - diff --git a/doc/source/user_guide/troubleshooting/index.rst b/doc/source/user_guide/troubleshooting/index.rst new file mode 100644 index 0000000000..ee6250df72 --- /dev/null +++ b/doc/source/user_guide/troubleshooting/index.rst @@ -0,0 +1,39 @@ +.. _ref_troubleshooting_index: + +Troubleshooting +--------------- + +.. grid:: 3 + :gutter: 2 + + .. grid-item-card:: Server issues + :link: ref_server_issues + :link-type: ref + :text-align: center + + Start the DPF server + + Connect to the DPF server + + Import the pydpf-core package + + .. grid-item-card:: Model issues + :link: ref_model_issues + :link-type: ref + :text-align: center + + Invalid UTF-8 error + + .. grid-item-card:: Plotting issues + :link: ref_plotting_issues + :link-type: ref + :text-align: center + + .. grid-item-card:: Performance issues + :link: ref_performance_issues + :link-type: ref + :text-align: center + + Get and set a field's data + + Autocompletion in notebooks \ No newline at end of file diff --git a/doc/source/user_guide/troubleshooting.rst b/doc/source/user_guide/troubleshooting/troubleshooting.rst similarity index 94% rename from doc/source/user_guide/troubleshooting.rst rename to doc/source/user_guide/troubleshooting/troubleshooting.rst index 86fc50f5c2..8b2edc150d 100644 --- a/doc/source/user_guide/troubleshooting.rst +++ b/doc/source/user_guide/troubleshooting/troubleshooting.rst @@ -3,11 +3,15 @@ =============== Troubleshooting =============== + This page explains how to resolve the most common issues encountered when using PyDPF-Core. It also includes suggestions for improving scripts. +.. _ref_server_issues: + +============== Server issues -------------- +============== Start the DPF server ~~~~~~~~~~~~~~~~~~~~~ @@ -38,8 +42,11 @@ If an error lists missing modules, see :ref:`ref_compatibility`. For ``PyDPF-Core``<0.10.0, the `ansys.grpc.dpf `_ module should always be synchronized with its server version. +.. _ref_model_issues: + +============ Model issues ------------- +============ Invalid UTF-8 error ~~~~~~~~~~~~~~~~~~~ @@ -66,8 +73,11 @@ Then, with result files reproducing this issue, you can prevent the warning from However, the preceding code disables the reading and generation of the available results for the model. Any static results that are available for the model are used instead. +.. _ref_plotting_issues: + +=============== Plotting issues ---------------- +=============== When trying to plot a result with DPF, the following error might be raised: @@ -84,8 +94,11 @@ In that case, simply install `PyVista `_` with this comman Another option is to install PyVista along with PyDPF-Core. For more information, see :ref:`Install with plotting capabilities` +.. _ref_performance_issues: + +================== Performance issues ------------------- +================== Get and set a field's data ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/user_guide/fields_container.rst b/doc/source/user_guide/tutorials/fields_container.rst similarity index 100% rename from doc/source/user_guide/fields_container.rst rename to doc/source/user_guide/tutorials/fields_container.rst diff --git a/doc/source/user_guide/tutorials/index.rst b/doc/source/user_guide/tutorials/index.rst new file mode 100644 index 0000000000..5e3d5f9fc5 --- /dev/null +++ b/doc/source/user_guide/tutorials/index.rst @@ -0,0 +1,96 @@ +.. _ref_tutorials_index: + +Tutorials +--------- + + +The following tutorials show in details how to use basic features of PyDPF-Core +for each usage main step. + +:bdg-dark-line:`Define simulation data` :octicon:`arrow-right;1em` :bdg-dark-line:`Store input data in DPF` :octicon:`arrow-right;1em` :bdg-dark-line:`Transform available data` :octicon:`arrow-right;1em` :bdg-dark-line:`Extract data` + +**Define input data** + + +.. grid:: 3 + + .. grid-item-card:: Data Sources + :link: ref_tutorials_model + :link-type: ref + :text-align: center + + .. grid-item-card:: DPF model + :link: ref_tutorials_model + :link-type: ref + :text-align: center + +**Load data** + + +.. grid:: 3 + + .. grid-item-card:: Data arrays + :link: ref_tutorials_model + :link-type: ref + :text-align: center + + Fields + + PropertyField + + StringField + + CustomTypeField + + .. grid-item-card:: Data maps + :link: ref_tutorials_model + :link-type: ref + :text-align: center + + GenericDataContainer + + DataTree + + .. grid-item-card:: Collections + :link: ref_tutorials_model + :link-type: ref + :text-align: center + + LabelSpace + + FieldsContainer + + MeshContainer + +**Transform data** + + +.. grid:: 3 + + .. grid-item-card:: Process creation + :link: ref_tutorials_model + :link-type: ref + :text-align: center + + Operators + + Workflow + + .. grid-item-card:: Results visualization + :link: ref_tutorials_model + :link-type: ref + :text-align: center + + Plotter + + Animator + +**Export data** + + +.. grid:: 3 + + .. grid-item-card:: Serialization + :link: ref_tutorials_model + :link-type: ref + :text-align: center \ No newline at end of file diff --git a/doc/source/user_guide/model.rst b/doc/source/user_guide/tutorials/model.rst similarity index 99% rename from doc/source/user_guide/model.rst rename to doc/source/user_guide/tutorials/model.rst index bd3f773a04..f7f5b539fb 100644 --- a/doc/source/user_guide/model.rst +++ b/doc/source/user_guide/tutorials/model.rst @@ -1,4 +1,4 @@ -.. _user_guide_model: +.. _ref_tutorials_model: ========= DPF model diff --git a/doc/source/user_guide/operators.rst b/doc/source/user_guide/tutorials/operators.rst similarity index 100% rename from doc/source/user_guide/operators.rst rename to doc/source/user_guide/tutorials/operators.rst diff --git a/doc/source/user_guide/plotting.rst b/doc/source/user_guide/tutorials/plotting.rst similarity index 100% rename from doc/source/user_guide/plotting.rst rename to doc/source/user_guide/tutorials/plotting.rst diff --git a/examples/08-python-operators/02-python_operators_with_dependencies.py b/examples/08-python-operators/02-python_operators_with_dependencies.py index f88d9e4a80..da55847e4d 100644 --- a/examples/08-python-operators/02-python_operators_with_dependencies.py +++ b/examples/08-python-operators/02-python_operators_with_dependencies.py @@ -123,9 +123,9 @@ # Download the script for your operating system. # # - For Windows, download this -# :download:`PowerShell script `. +# :download:`PowerShell script `. # - For Linux, download this -# :download:`Shell script `. +# :download:`Shell script `. # # Run the downloaded script with the mandatory arguments: # @@ -157,6 +157,7 @@ "doc", "source", "user_guide", + "how-to", "create_sites_for_python_operators.ps1", ) args = [ @@ -189,6 +190,7 @@ "doc", "source", "user_guide", + "how-to", "create_sites_for_python_operators.sh", ) run_cmd = f"{cmd_file}" diff --git a/requirements/requirements_docs.txt b/requirements/requirements_docs.txt index df5b2a087a..3b8158ba8a 100644 --- a/requirements/requirements_docs.txt +++ b/requirements/requirements_docs.txt @@ -10,6 +10,7 @@ pyvista==0.44.1 sphinx==7.1.0 sphinx-autobuild==2024.2.4 sphinx-copybutton==0.5.2 +sphinx-exec-code==0.12 sphinx-gallery==0.17.0 sphinx-notfound-page==1.0.4 sphinx-reredirects==0.1.3 From 9dfd6f4bad6c92a9e9a208a06e84d1c6604926c9 Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Thu, 26 Sep 2024 14:38:49 +0200 Subject: [PATCH 7/8] adaptation of the fields tutorial (field and fields containers main entities) --- doc/source/user_guide/index.rst | 2 +- doc/source/user_guide/tutorials/fields.rst | 943 ++++++++++++++++++ .../user_guide/tutorials/fields_container.rst | 579 ----------- doc/source/user_guide/tutorials/index.rst | 2 +- 4 files changed, 945 insertions(+), 581 deletions(-) create mode 100644 doc/source/user_guide/tutorials/fields.rst delete mode 100644 doc/source/user_guide/tutorials/fields_container.rst diff --git a/doc/source/user_guide/index.rst b/doc/source/user_guide/index.rst index 2095c6699c..66b5b5dc9e 100644 --- a/doc/source/user_guide/index.rst +++ b/doc/source/user_guide/index.rst @@ -44,7 +44,7 @@ The goals of this section are to: tutorials/model.rst tutorials/operators.rst - tutorials/fields_container.rst + tutorials/fields.rst .. toctree:: :maxdepth: 2 diff --git a/doc/source/user_guide/tutorials/fields.rst b/doc/source/user_guide/tutorials/fields.rst new file mode 100644 index 0000000000..7231d54c0e --- /dev/null +++ b/doc/source/user_guide/tutorials/fields.rst @@ -0,0 +1,943 @@ +.. _ref_tutorials_fields: + +.. |Field| replace:: :class:`Field `: +.. |PropertyField| replace:: :class:`PropertyField `: +.. |StringField| replace:: :class:`StringField `: +.. |CustomTypeField| replace:: :class:`CustomTypeField ` + +=========== +Data Arrays +=========== + +When DPF employ operators to manipulate the data, it uses data containers to +store and return it. Therefore, it is important to be aware of how the data is +structured in those containers. + +The data containers can be: + + - **Raw data storage structures**: Data arrays (a ``Field`` for example) + or Data Maps (a ``DataTree`` for example) + - **Collections**: a group of same labeled objects from one DPF raw data storage + structure (a ``FieldsContainer`` for example, that is a group of ``Fields`` + with the same label) + +This tutorial presents how some DPF data arrays are defined and manipulated. The main difference between +them is the data type they contain: + + - |Field| : float; + - |StringField|: string. + - |PropertyField|: int; + - |CustomTypeField|: custom type (numpy.dtype) + +Therefore, the first one is typically found when manipulating the results. The two following are +typically found when analysing the mesh and its properties. + + Their data is always associated to: + + - A ``location``: What typology of the finite element method was used to give + the results. There are different spatial ``locations`` that can be found + at: :class:`locations ` but the most used + are : ``Nodal``, ``Elemental`` and ``Elemental Nodal``. + + - The ``support``: The simulation basis functions are integrated over a calculus + domain, the support of the analysis. This domain is a physical component, + usually represented by: a mesh, geometrical component, time or frequency values. + +When defining an operator, you must narrow down which parts of the initial data +are relevant for the goals of the analysis. Thus, you must define the data container +scoping. + +A field is also defined by its dimensionality, it can for example, describe +a displacement vector or norm, stresses and strains tensors, stresses and strains +equivalent, min max over time of any result... The data is stored as a vector of +double values and each elementary entity has a number of components (thanks to the +dimensionality, a displacement will have 3 components, a symmetrical stress matrix 6...). + +Define the studied results +-------------------------- + +In this tutorial we are going to use the result file from a transient analysis for the +|Field| and a fluid analysis for the |PropertyField| and |StringField|. + +Create the ``model`` object. The :class:`Model ` +class helps to organize access methods for the result by keeping track of the +operators and data sources used by the result file. + +.. tab-set:: + + .. tab-item:: Field + + .. code-block:: python + + # Import the DPF-Core module as ``dpf`` + from ansys.dpf import core as dpf + # Import the included examples file. + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_transient_result()) + my_model = dpf.Model(data_sources=my_data_sources) + print(my_model) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_transient_result()) + my_model = dpf.Model(data_sources=my_data_sources) + print(my_model) + + .. tab-item:: StringField + + .. code-block:: python + + # Import the DPF-Core module as ``dpf`` + from ansys.dpf import core as dpf + # Import the included examples file. + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + print(my_model_2) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + print(my_model_2) + + .. tab-item:: PropertyField + + .. code-block:: python + + # Import the DPF-Core module as ``dpf`` + from ansys.dpf import core as dpf + # Import the included examples file. + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + print(my_model_2) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + print(my_model_2) + +Scoping +------- + +To begin the workflow set up, you need to establish the ``scoping``, that is +a spatial and/or temporal subset of the simulation data. + +The field’s scoping also defines how the data is ordered, for example: the first +ID in the scoping identifies to which entity the first data entity belongs. + +The following explanations concern only the |Field| manipulation. Since the |StringField| +and |PropertyField| are mostly an informational tool, you can only extract and visualize +the analysis scoping. + +If the scoping is not specified the operators will only use the final result data. +For example, we can see in our model that the displacement results are available +with a time support. + +.. code-block:: python + + # create the displacement operator + my_disp = my_model.results.displacement() + # Print the evaluated results output + print(my_disp.eval()) + +.. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp = my_model.results.displacement() + print(my_disp.eval()) + + +To define the scope we have to make two considerations: the location and the +support of interest: + + 1) The location: which component will be enumerated (list of nodes for example) + 2) The support: the list is relative about which domain (list of nodes of a given + meshed region) + +Therefore, we have two main supports to scope in: time and mesh domains. You specify +the set of components by defining a range of IDs: + +.. image:: ../../images/drawings/scoping-eg.png + +Creating a scoping object +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``Scoping`` object can be created by the :class:`Scoping ` +class or with a scoping factory: + +**Time scoping** + +.. code-block:: python + + # 1) Using the Scoping class + my_time_scoping = dpf.Scoping(ids=[14, 15, 16, 17], location=dpf.locations.time_freq) + + # 2) Using the time_freq_scoping_factory class + # a. Define a time list that targets the times ids 14, 15, 16, 17 + my_time_list = [14, 15, 16, 17] + # b. Create the time scoping object + my_time_scoping = dpf.time_freq_scoping_factory.scoping_by_sets(cumulative_sets=my_time_list) + +**Mesh scoping** + +.. code-block:: python + + # 1) Using the Scoping class in a nodal location + my_mesh_scoping = dpf.Scoping(ids=[103, 204, 334, 1802], location=dpf.locations.nodal) + + # 2) Using the mesh_scoping_factory class + # a. Define a nodes list that targets the nodes with the ids 103, 204, 334, 1802 + my_nodes_ids = [103, 204, 334, 1802] + # b. Create the mesh scoping object + my_mesh_scoping = dpf.mesh_scoping_factory.nodal_scoping(node_ids=my_nodes_ids) + +Using the scoping object +~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``Scoping`` object can be assign to an operator by using ``Model`` helpers or +directly in the operator indentation if it assumes a scoping as an argument: + +**Time scoping** + +.. code-block:: python + + # 3) Using the on_time_scoping() helper + my_disp = my_model.results.displacement.on_time_scoping(time_scoping=[14, 15, 16, 17]) + # or + my_disp = my_model.results.displacement.on_time_scoping(time_scoping=my_time_scoping) + + # 4) Directly with the operator indentation + my_disp = my_model.results.displacement(time_scoping= my_time_scoping) + +**Mesh scoping** + +.. code-block:: python + + # 3) Using the on_time_scoping() helper + my_disp = my_model.results.displacement.on_mesh_scoping(mesh_scoping=[103, 204, 334, 1802]) + # or + my_disp = my_model.results.displacement.on_mesh_scoping(mesh_scoping=my_mesh_scoping) + + # 4) Directly with the operator indentation + my_disp = my_model.results.displacement(mesh_scoping=my_mesh_scoping) + +The final operator with those scopes would look like: + +.. code-block:: python + + # Time scoping targets the times ids 14, 15, 16, 17 + # Mesh scoping targets the nodes with the ids 103, 204, 334, 1802 + my_disp = my_model.results.displacement(time_scoping=my_time_scoping, mesh_scoping=my_mesh_scoping) + print(my_disp) + +.. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_mesh_scoping = dpf.Scoping(ids=[103, 204, 334, 1802], location=dpf.locations.nodal) + my_disp = my_model.results.displacement(time_scoping=[14, 15, 16, 17], mesh_scoping=my_mesh_scoping) + print(my_disp) + +Other scope helpers are available at: :class:`Result `. + +Specific examples about how to implement some scopings can be found at: + + - :mod:'Scope results over time domain ' + - :mod:'Scope results over space domain ' + +Fields +------ + +Each part of this subsection explain how to explore the data in the studied data arrays. + +Defining a field +~~~~~~~~~~~~~~~~ + +A |Field|, |StringField| or |PropertyField| can be created directly by instantiating an object +of their classes or they can be evaluated data from an operator. In particular, a +|Field| can also be created with the functions in the :mod:`fields_factory ` +module: + +**Class object instance** + +.. tab-set:: + + .. tab-item:: Field + + .. code-block:: python + + # Create the Field object with 2 entities + num_entities = 2 + my_field = dpf.Field(nentities=num_entities) + # By default, the field contains 3d vectors + # So with 2 entities we need 6 data values + my_field.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] + # Assign a location + my_field.location = dpf.locations.nodal + # Define the scoping + my_field.scoping.ids = range(num_entities) + # Define the units (only for the Field object) + my_field.unit = "m" + + print(my_field) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + num_entities = 2 + my_field = dpf.Field(nentities=num_entities) + my_field.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] + my_field.location = dpf.locations.nodal + my_field.scoping.ids = range(num_entities) + my_field.unit = "m" + print(my_field) + + .. tab-item:: StringField + + .. code-block:: python + + # Create the Field object with 2 entities + num_entities = 2 + my_StringField = dpf.StringField(nentities=num_entities) + # By default, the field contains 3d vectors + # So with 2 entities we need 6 data values + my_StringField.data = ["string_1", "string_2"] + # Assign a location + my_StringField.location = dpf.locations.nodal + # Define the scoping + my_StringField.scoping.ids = range(num_entities) + + print(my_field) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + num_entities = 2 + my_StringField = dpf.StringField(nentities=num_entities) + my_StringField.data = ["string_1", "string_2"] + my_StringField.location = dpf.locations.nodal + my_StringField.scoping.ids = range(num_entities) + print(my_StringField) + + .. tab-item:: PropertyField + + .. code-block:: python + + # Create the Field object with 2 entities + num_entities = 2 + my_PropertyField = dpf.PropertyField(nentities=num_entities) + # By default, the field contains 3d vectors + # So with 2 entities we need 6 data values + my_PropertyField.data = [12, 25] + # Assign a location + my_PropertyField.location = dpf.locations.nodal + # Define the scoping + my_PropertyField.scoping.ids = range(num_entities) + + print(my_PropertyField) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + num_entities = 2 + my_PropertyField = dpf.PropertyField(nentities=num_entities) + my_PropertyField.data = [12, 25] + my_PropertyField.location = dpf.locations.nodal + my_PropertyField.scoping.ids = range(num_entities) + print(my_PropertyField) + + +**2) Evaluated data** + +.. tab-set:: + + .. tab-item:: Field + + .. code-block:: python + + # Create the displacement operator + # Here we use [0] because the displacement operator gives an FieldsContainer as an output + my_disp_field = my_model.results.displacement.eval()[0] + # Print the evaluated results output + print(my_disp_field) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp = my_model.results.displacement() + print(my_disp.eval()) + + .. tab-item:: StringField + + .. code-block:: python + + # Usually the StringField can be found at the mesh_info + # Get the mesh_info by tht models metadata + my_mesh_info = my_model_2.metadata.mesh_info + print(my_mesh_info) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + my_mesh_info = my_model_2.metadata.mesh_info + print(my_mesh_info) + + .. code-block:: python + + # We can get the face_zone_names property for example + my_string_field = my_mesh_info.get_property(property_name="face_zone_names") + print(my_string_field) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + my_mesh_info = my_model_2.metadata.mesh_info + my_string_field = my_mesh_info.get_property(property_name="face_zone_names") + print(my_string_field) + + .. tab-item:: PropertyField + + .. code-block:: python + + # Usually the StringField can be found at the mesh_info + # Get the mesh_info by tht models metadata + my_mesh_info = my_model_2.metadata.mesh_info + print(my_mesh_info) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + my_mesh_info = my_model_2.metadata.mesh_info + print(my_mesh_info) + + .. code-block:: python + + # We can get the body_face_topology property for example + my_property_field = my_mesh_info.get_property(property_name="body_face_topology") + print(my_property_field) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + my_mesh_info = my_model_2.metadata.mesh_info + my_property_field = my_mesh_info.get_property(property_name="body_face_topology") + print(my_property_field) + +**3) With the fields_factory module** + +.. code-block:: python + + # Define a field with entities that are scalar. + my_field = dpf.fields_factory.create_scalar_field(num_entities=2) + # This is a “reserve” mechanism, at the beginning you have 0 entities. + # This means that you need to append data to grow the size of your field. + # Gives 2 vectors in the same id + my_field.append(data=[1.0, 2.0, 3.0, 4.0, 5.0, 6.0], scopingid=0) + + # Gives 2 vectors in different ids + my_field.append(data=[1.0, 2.0, 3.0], scopingid=1) + my_field.append(data=[4.0, 5.0, 6.0], scopingid=2) + + print(my_field) + +.. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + my_field = dpf.fields_factory.create_scalar_field(num_entities=2) + my_field.append(data=[1.0, 2.0, 3.0, 4.0, 5.0, 6.0], scopingid=0) + my_field.append(data=[1.0, 2.0, 3.0], scopingid=1) + my_field.append(data=[ 4.0, 5.0, 6.0], scopingid=2) + print(my_field) + +Accessing fields metadata +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A field contains the metadata for the result it is associated with. The metadata +includes the location, the scoping, the shape of the data stored, number of components, +and units of the data. + +.. tab-set:: + + .. tab-item:: Field + + .. code-block:: python + + # Location of the fields data + my_location = my_disp_field.location + print("location", '\n', my_location,'\n') + + # Fields scoping + my_scoping = my_disp_field.scoping # Location entities type and number + print("scoping", '\n',my_scoping, '\n') + + my_scoping_ids = my_disp_field.scoping.ids # Available ids of locations components + print("scoping.ids", '\n', my_scoping_ids, '\n') + + # Elementary data count + # Number of the location entities (how many data vectors we have) + my_elementary_data_count = my_disp_field.elementary_data_count + print("elementary_data_count", '\n', my_elementary_data_count, '\n') + + # Components count + # Vectors dimension, here we have a displacement so we expect to have 3 components (X, Y and Z) + my_components_count = my_disp_field.component_count + print("component_count", '\n', my_component_count, '\n') + + # Size + # Length of the data entire vector (equal to the number of elementary data times the number of components.) + my_field_size = my_disp_field.size + print("size", '\n', my_field_size, '\n') + + # Fields shape + # Gives a tuple with the elementary data count and the components count + my_shape = my_disp_field.shape + print("shape", '\n', my_shape, '\n') + + # Units + my_units = my_disp_field.unit + print("unit", '\n', my_unit, '\n') + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + my_location = my_disp_field.location + print("location", '\n', my_location,'\n') + my_scoping = my_disp_field.scoping + print("scoping", '\n',my_scoping, '\n') + print('\n', "We have a location entity of type 'Nodal' (consistent with the output of the `location` helper) and + 3820 nodes", '\n') + my_scoping_ids = my_disp_field.scoping.ids + print("scoping.ids", '\n', my_scoping_ids, '\n') + my_components_count = my_disp_field.component_count + print("component_count", '\n', my_component_count, '\n') + my_elementary_data_count = my_disp_field.elementary_data_count + print("elementary_data_count", '\n', my_elementary_data_count, '\n') + my_shape = my_disp_field.shape + print("shape", '\n', my_shape, '\n') + print('\n', "We have a Field with 3820 data vectors (consistent with the number of nodes) and each vector has + 3 components (consistent with a displacement vector dimension)", '\n') + my_units = my_disp_field.unit + print("unit", '\n', my_unit, '\n') + + .. tab-item:: StringField + + .. code-block:: python + + # Location of the fields data + my_location = my_string_field.location + print("location", '\n', my_location,'\n') + + # StringFields scoping + my_scoping = my_string_field.scoping # Location entities type and number + print("scoping", '\n',my_scoping, '\n') + + my_scoping_ids = my_string_field.scoping.ids # Available ids of locations components + print("scoping.ids", '\n', my_scoping_ids, '\n') + + # Elementary data count + # Number of the location entities (how many data vectors we have) + my_elementary_data_count = my_string_field.elementary_data_count + print("elementary_data_count", '\n', my_elementary_data_count, '\n') + + # Components count + # Data dimension, here we expect one name by zone + my_components_count = my_string_field.component_count + print("component_count", '\n', my_component_count, '\n') + + # Size + # Length of the data entire array (equal to the number of elementary data times the number of components.) + my_field_size = my_string_field.size + print("size", '\n', my_field_size, '\n') + + # Fields shape + # Gives a tuple with the elementary data count and the components count + my_shape = my_string_field.shape + print("shape", '\n', my_shape, '\n') + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + my_mesh_info = my_model_2.metadata.mesh_info + my_string_field = my_mesh_info.get_property(property_name="face_zone_names") + my_location = my_string_field.location + print("location", '\n', my_location,'\n') + my_scoping = my_string_field.scoping + print("scoping", '\n',my_scoping, '\n') + print('\n', "We have a location entity of type 'Zone' (consistent with the output of the `location` helper) and + 24 zones", '\n') + my_scoping_ids = my_string_field.scoping.ids + print("scoping.ids", '\n', my_scoping_ids, '\n') + my_components_count = my_string_field.component_count + print("component_count", '\n', my_component_count, '\n') + my_elementary_data_count = my_string_field.elementary_data_count + print("elementary_data_count", '\n', my_elementary_data_count, '\n') + my_shape = my_string_field.shape + print("shape", '\n', my_shape, '\n') + print('\n', "We have a StringField with 24 names (consistent with the number of zones) and + each zone has one name) + + .. tab-item:: PropertyField + + .. code-block:: python + + # Location of the fields data + my_location = my_property_field.location + print("location", '\n', my_location,'\n') + + # Fields scoping + my_scoping = my_property_field.scoping # Location entities type and number + print("scoping", '\n',my_scoping, '\n') + + my_scoping_ids = my_property_field.scoping.ids # Available ids of locations components + print("scoping.ids", '\n', my_scoping_ids, '\n') + + # Elementary data count + # Number of the location entities (how many data vectors we have) + my_elementary_data_count = my_property_field.elementary_data_count + print("elementary_data_count", '\n', my_elementary_data_count, '\n') + + # Components count + # Data dimension, we expect to have one id by face that makes part of a body + my_components_count = my_property_field.component_count + print("component_count", '\n', my_component_count, '\n') + + # Size + # Length of the data entire array (equal to the number of elementary data times the number of components.) + my_field_size = my_property_field.size + print("size", '\n', my_field_size, '\n') + + # Fields shape + # Gives a tuple with the elementary data count and the components count + my_shape = my_property_field.shape + print("shape", '\n', my_shape, '\n') + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + my_mesh_info = my_model_2.metadata.mesh_info + my_property_field = my_mesh_info.get_property(property_name="body_face_topology") + my_location = my_property_field.location + print("location", '\n', my_location,'\n') + my_scoping = my_property_field.scoping + print("scoping", '\n',my_scoping, '\n') + print('\n', "We have a location entity of type 'Body' (consistent with the output of the `location` helper) and + 2 bodies", '\n') + my_scoping_ids = my_property_field.scoping.ids + print("scoping.ids", '\n', my_scoping_ids, '\n') + my_components_count = my_property_field.component_count + print("component_count", '\n', my_component_count, '\n') + my_elementary_data_count = my_property_field.elementary_data_count + print("elementary_data_count", '\n', my_elementary_data_count, '\n') + my_shape = my_property_field.shape + print("shape", '\n', my_shape, '\n') + print('\n', "We have a Field with 24 face ids (consistent with the number of faces) and each face has one + id, '\n') + +Accessing fields data +~~~~~~~~~~~~~~~~~~~~~ + +When DPF-Core returns the |Field| class object, +what Python actually has is a client-side representation of the field, +not the entirety of the field itself. This means that all the data of +the field is stored within the DPF service. This is important because +when building your postprocessing workflows, the most efficient way of +interacting with result data is to minimize the exchange of data between +Python and DPF, either by using operators or by accessing only the data +that is needed. + +**1) Helpers** + +The field's ``data`` is ordered with respect to its ``scoping ids`` (as shown above). +To access the entire data in the field as an array (``numpy`` array``): + +.. tab-set:: + + .. tab-item:: Field + + .. code-block:: python + + my_data_array = my_disp_field.data + print(my_data_array) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + my_data_array = my_disp_field.data + print(my_data_array) + + Note that this array is a genuine, local, numpy array (overloaded by the DPFArray). + + .. code-block:: python + + print(type(my_data_array)) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + my_data_array = my_disp_field.data + print(type(my_data_array)) + + .. tab-item:: StringField + + .. code-block:: python + + my_data_array = my_string_field.data + print(my_data_array) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + my_mesh_info = my_model_2.metadata.mesh_info + my_string_field = my_mesh_info.get_property(property_name="face_zone_names") + my_data_array = my_disp_field.data + print(my_data_array) + + .. tab-item:: PropertyField + + .. code-block:: python + + my_data_array = my_property_field.data + print(my_data_array) + + .. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_data_sources = dpf.DataSources(result_path=examples.download_fluent_axial_comp()["flprj"]) + my_model_2 = dpf.Model(data_sources=my_data_sources) + my_mesh_info = my_model_2.metadata.mesh_info + my_property_field = my_mesh_info.get_property(property_name="body_face_topology") + my_data_array = my_property_field.data + print(my_data_array) + +**2) Functions** + +If you need to access an individual node or element, request it +using either the :func:`get_entity_data()` or +:func:`get_entity_data_by_id()` methods: + +.. code-block:: python + + # Get the data from the third element in the field + my_disp_field.get_entity_data(index=3) + +.. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + print(my_disp_field.get_entity_data(index=3)) + +.. code-block:: python + + # Get the data from the element with id 533 + my_disp_field.get_entity_data_by_id(id=533) + +.. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + print(my_disp_field.get_entity_data(id=533)) + +Note that this would correspond to an index of 2 within the +field. Be aware that scoping IDs are not sequential. You would +get the index of element 2 in the field with: + +.. code-block:: python + + # Get index of the element with id 533 + my_disp_field.scoping.index(id=533) + +.. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + print(my_disp_field.scoping.index(id=533)) + +While these methods are acceptable when requesting data for a few elements +or nodes, they should not be used when looping over the entire array. For efficiency, +a field's data can be recovered locally before sending a large number of requests: + +.. code-block:: python + + # Create a deep copy of the field that can be accessed and modified locally. + with my_disp_field.as_local_field() as f: + for i in range(1,100): + f.get_entity_data_by_id(i) + +Operate on field data +~~~~~~~~~~~~~~~~~~~~~ + +Oftentimes, you do not need to directly act on the data of an array within +Python. For example, if you want to know the maximum of the data, you can +use the ``array.max()`` method to compute the maximum of the array with the +``numpy`` package. + +However, this requires sending the entire array to Python and then computing +the maximum there. + +Rather than copying the array over and computing the maximum in Python, you can +instead compute the maximum directly from the field itself. + +Here we the ``min_max`` operator (through a fields helper) to compute +the maximum of the displacement field and return a field with only the max values: + +.. code-block:: python + + # Returns the maximum value for each component + # So with displacement results we expect having a field with : + # - 3 elementary data (one for each dimension) + # - 1 component (each entity will have a value for one dimension (X, Y or Z)) + my_max = my_disp_field.max() + print(my_max) + +.. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + print(my_disp_field.max()) + +You can for example get the element or node ID of the maximum value. + +.. code-block:: python + + my_disp_field.max() + print(my_disp_field.scoping.ids) + +.. rst-class:: sphx-glr-script-out + + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + my_disp_field.max() + print(my_disp_field.scoping.ids) \ No newline at end of file diff --git a/doc/source/user_guide/tutorials/fields_container.rst b/doc/source/user_guide/tutorials/fields_container.rst deleted file mode 100644 index b5f8fba8b4..0000000000 --- a/doc/source/user_guide/tutorials/fields_container.rst +++ /dev/null @@ -1,579 +0,0 @@ -.. _ref_user_guide_fields_container: - -=========================== -Fields container and fields -=========================== -While DPF uses operators to load and operate on data, it uses field containers -and fields to store and return data. In other words, operators are like verbs, -acting on the data, while field containers and fields are like nouns, objects -that hold data. - -Access a fields container or field ------------------------------------ -The outputs from operators can be either a -:class:`ansys.dpf.core.fields_container.FieldsContainer` or -:class:`ansys.dpf.core.field.Field` class. - -A fields container is the DPF equivalent of a list of fields. It holds a -vector of fields. - -This example uses the ``elastic_strain`` operator to access a fields container: - -.. code-block:: - - from ansys.dpf import core as dpf - from ansys.dpf.core import examples - model = dpf.Model(examples.find_msup_transient()) - epel = model.results.elastic_strain.on_all_time_freqs - fields = epel.eval() - print(fields) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPF elastic_strain(s)Fields Container - with 20 field(s) - defined on labels: time - - with: - - field 0 {time: 1} with ElementalNodal location, 6 components and 40 entities. - - field 1 {time: 2} with ElementalNodal location, 6 components and 40 entities. - - field 2 {time: 3} with ElementalNodal location, 6 components and 40 entities. - - field 3 {time: 4} with ElementalNodal location, 6 components and 40 entities. - - field 4 {time: 5} with ElementalNodal location, 6 components and 40 entities. - - field 5 {time: 6} with ElementalNodal location, 6 components and 40 entities. - - field 6 {time: 7} with ElementalNodal location, 6 components and 40 entities. - - field 7 {time: 8} with ElementalNodal location, 6 components and 40 entities. - - field 8 {time: 9} with ElementalNodal location, 6 components and 40 entities. - - field 9 {time: 10} with ElementalNodal location, 6 components and 40 entities. - - field 10 {time: 11} with ElementalNodal location, 6 components and 40 entities. - - field 11 {time: 12} with ElementalNodal location, 6 components and 40 entities. - - field 12 {time: 13} with ElementalNodal location, 6 components and 40 entities. - - field 13 {time: 14} with ElementalNodal location, 6 components and 40 entities. - - field 14 {time: 15} with ElementalNodal location, 6 components and 40 entities. - - field 15 {time: 16} with ElementalNodal location, 6 components and 40 entities. - - field 16 {time: 17} with ElementalNodal location, 6 components and 40 entities. - - field 17 {time: 18} with ElementalNodal location, 6 components and 40 entities. - - field 18 {time: 19} with ElementalNodal location, 6 components and 40 entities. - - field 19 {time: 20} with ElementalNodal location, 6 components and 40 entities. - - -Access fields within a fields container ---------------------------------------- -Many methods are available for accessing a field in a fields -container. The preceding results contain a transient -result, which means that the fields container has one field -by time set. - -Access the field: - -.. code-block:: - - len(fields) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - 20 - -Access the field based on its index: - -.. code-block:: - - field_first_time = fields[0] - field_last_time = fields[19] - -Access the field based on its time set ID: - -.. code-block:: - - field = fields.get_field_by_time_id(1) - -To access fields for more complex requests, you can use the -``get_field()`` method with the ID of the requested field: - -.. code-block:: - - field = fields.get_field({'time': 1}) - print(field) - -.. rst-class:: sphx-glr-script-out - - - .. code-block:: none - - DPF elastic_strain_0.01s Field - Location: ElementalNodal - Unit: - 40 entities - Data: 6 components and 320 elementary data - Elemental - IDs data () - ------------ ---------- - 21 -5.0964e-07 -5.8226e-07 1.8660e-06 8.3252e-09 -3.3062e-09 -7.7246e-08 - -5.7021e-07 -5.7104e-07 1.8996e-06 -9.9354e-10 -3.4486e-08 -7.4886e-08 - -6.0495e-07 -6.0408e-07 2.0172e-06 4.9817e-09 -5.5109e-09 -2.1038e-08 - ... - 22 -5.0964e-07 -5.8226e-07 1.8660e-06 -8.3252e-09 -3.3062e-09 7.7246e-08 - -5.6697e-07 -6.1112e-07 1.9950e-06 4.0239e-09 1.0457e-09 1.9740e-08 - -6.0495e-07 -6.0408e-07 2.0172e-06 -4.9817e-09 -5.5109e-09 2.1038e-08 - ... - 23 -3.7887e-07 -4.8075e-07 1.4980e-06 9.6495e-09 -1.1785e-08 -1.6389e-07 - -4.6401e-07 -4.6508e-07 1.5451e-06 1.6581e-09 -7.7990e-08 -1.5638e-07 - -5.7202e-07 -5.7104e-07 1.9081e-06 4.9200e-09 -3.3430e-08 -8.2869e-08 - ... - ... - - -Here is a more real-word example: - -.. code-block:: - - model = dpf.Model(examples.download_all_kinds_of_complexity()) - epel = model.results.elastic_strain.on_all_time_freqs.split_by_shape - fields = epel.eval() - field = fields.get_field({'time': 1, 'elshape':0}) - print(field) - - field = fields.get_field({'time': 1, 'elshape':1}) - print(field) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPF elastic_strain_1.s_elshape:0 Field - Location: ElementalNodal - Unit: - 203 entities - Data: 6 components and 2436 elementary data - Elemental - IDs data () - ------------ ---------- - 10791 9.961283e-05 -1.557876e-05 -6.798322e-05 4.423883e-20 7.823432e-21 4.348549e-06 - 9.532236e-05 -1.426944e-05 -6.635107e-05 4.234001e-20 1.050099e-20 1.901931e-05 - 8.607592e-05 -3.046389e-05 -2.422499e-05 3.823384e-20 1.776519e-20 1.917663e-05 - ... - 10790 9.829979e-05 -8.944115e-06 -8.014052e-05 -5.813971e-21 3.947791e-20 2.315096e-05 - 9.230295e-05 -1.569666e-05 -6.043398e-05 -6.588927e-21 3.371362e-20 2.682668e-05 - 1.068346e-04 -1.988030e-05 -6.647159e-05 -6.227784e-21 3.825956e-20 2.475124e-05 - ... - 10785 8.480231e-05 -1.470483e-05 -5.494706e-05 2.105046e-21 3.093755e-20 -9.940667e-06 - 7.555470e-05 -2.958404e-05 -1.549013e-05 2.273083e-21 2.002334e-20 -1.064724e-05 - 7.552039e-05 -2.970292e-05 -1.521445e-05 4.916594e-21 1.996089e-20 -2.255241e-05 - ... - ... - DPF elastic_strain_1.s_elshape:1 Field - Location: ElementalNodal - Unit: - 9052 entities - Data: 6 components and 37580 elementary data - Elemental - IDs data () - ------------ ---------- - 1 -2.365747e-04 8.205943e-04 -2.195325e-04 4.799285e-04 2.372855e-04 -8.473678e-06 - -5.085632e-04 1.070203e-03 -2.770476e-04 -2.848311e-04 3.473931e-04 4.251066e-06 - -4.331823e-04 9.600782e-04 -4.320994e-04 -3.780877e-04 -3.978023e-04 -2.898742e-06 - ... - 8 -2.388557e-04 8.369775e-04 -2.127467e-04 4.718478e-04 1.823031e-04 -5.630592e-06 - -2.600095e-04 7.688167e-04 -1.320574e-04 5.460561e-04 8.167552e-05 -7.558865e-06 - -5.470272e-04 9.995268e-04 -1.715976e-04 -3.155533e-04 1.211339e-04 -1.600466e-06 - ... - 15 -2.588085e-04 7.750597e-04 -1.346239e-04 5.428307e-04 6.121315e-05 -6.311711e-06 - -2.671824e-04 7.798763e-04 -1.107667e-04 5.587949e-04 -2.850134e-05 1.501269e-06 - -5.611221e-04 1.008660e-03 -1.391484e-04 -3.172989e-04 -2.487912e-05 1.011503e-07 - ... - ... - - - -The following example references the available time frequency support to determine which -time complex IDs are available in the fields container: - -.. code-block:: - - model = dpf.Model(examples.find_msup_transient()) - epel = model.results.elastic_strain.on_all_time_freqs - fields = epel.eval() - print(fields.time_freq_support) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPF Time/Freq Support: - Number of sets: 20 - Cumulative Time (s) LoadStep Substep - 1 0.010000 1 1 - 2 0.020000 1 2 - 3 0.030000 1 3 - 4 0.040000 1 4 - 5 0.050000 1 5 - 6 0.060000 1 6 - 7 0.070000 1 7 - 8 0.080000 1 8 - 9 0.090000 1 9 - 10 0.100000 1 10 - 11 0.110000 1 11 - 12 0.120000 1 12 - 13 0.130000 1 13 - 14 0.140000 1 14 - 15 0.150000 1 15 - 16 0.160000 1 16 - 17 0.170000 1 17 - 18 0.180000 1 18 - 19 0.190000 1 19 - 20 0.200000 1 20 - -Note that the time set IDs used are one-based. When indexing from Pythonic -indexing with ``fields[0]``, you can use zero-based indexing. When using -the ``get_fields()`` method to access results, you should base the request on -time-scoping set IDs. - -Field data ----------- -The :class:`ansys.dpf.core.field.Field` class is the fundamental unit of data within DPF. -It contains the actual data and its metadata, which is results data defined by values -associated with entities (scoping). These entities are a subset of a model (support). - -In DPF, field data is always associated with its scoping and support, making the field -a self-describing piece of data. A field is also defined by other attributes, including -dimensionality, unit, and location. - -.. figure:: ../images/drawings/field.png - :scale: 30% - - -You can get an overview of a field's metadata by printing the field: - -.. code-block:: - - field = fields[0] - print(field) - - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPF elastic_strain_0.01s Field - Location: ElementalNodal - Unit: - 40 entities - Data: 6 components and 320 elementary data - Elemental - IDs data () - ------------ ---------- - 21 -5.096470e-07 -5.822648e-07 1.866023e-06 8.325266e-09 -3.306256e-09 -7.724631e-08 - -5.702127e-07 -5.710485e-07 1.899680e-06 -9.935434e-10 -3.448644e-08 -7.488671e-08 - -6.049504e-07 -6.040822e-07 2.017216e-06 4.981728e-09 -5.510947e-09 -2.103890e-08 - ... - 22 -5.096470e-07 -5.822648e-07 1.866023e-06 -8.325266e-09 -3.306259e-09 7.724629e-08 - -5.669729e-07 -6.111289e-07 1.995080e-06 4.023948e-09 1.045763e-09 1.974096e-08 - -6.049504e-07 -6.040822e-07 2.017216e-06 -4.981728e-09 -5.510943e-09 2.103889e-08 - ... - 23 -3.788760e-07 -4.807594e-07 1.498000e-06 9.649583e-09 -1.178512e-08 -1.638991e-07 - -4.640120e-07 -4.650817e-07 1.545128e-06 1.658194e-09 -7.799093e-08 -1.563803e-07 - -5.720271e-07 -5.710485e-07 1.908120e-06 4.920075e-09 -3.343032e-08 -8.286970e-08 - ... - ... - - -The next section provides an overview of the metadata associated with the field itself. - - -Field metadata --------------- -A field contains the metadata for the result it is associated with. The metadata -includes the location (such as ``Elemental``, ``Nodal``, or -``ElementalNodal``) and the IDs associated with the location. - -The field's scoping defines the order of the data, for example: the first ID in the -``scoping`` identifies to which entity the first ``entity data`` in the data vector belongs. - -To access the scoping of the field, use the ``scoping`` attribute: - -.. code-block:: python - - print(field.scoping) - print('field.scoping.ids:', field.scoping.ids) - print('field.location:', field.location) - - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPF scoping: - with Elemental location and 40 entities - - field.scoping.ids: [21, - 22, - 23, - 24, - 25, - 26, - ... - ] - - field.location:'ElementalNodal' - - -- The ``Elemental`` location denotes one value of data (multiplied by the number - of components) per element. -- The ``Nodal`` location is one value per node. -- The ``ElementalNodal`` location is one value per node per element. For example, - strain is an ``ElementalNodal`` value because strain is evaluated at each node - for each element. - -The field also contains metadata, including the shape of -the data stored, location of the field, number of components, and -units of the data: - - -.. code-block:: python - - stress = model.results.stress - field = stress.eval()[0] - - # Units of the field describing volume - field.unit - - #Location of the field (Elemental, ElementalNodal, or Nodal) - field.location - - # Number of components associated with the field. It's expected to - # be a single dimension because there can only be one volume per - # element. - field.component_count - - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - 'Pa' - 'ElementalNodal' - 6 - - -Access field data ------------------ -When DPF-Core returns the :class:`ansys.dpf.core.field.Field` class, -what Python actually has is a client-side representation of the field, -not the entirety of the field itself. This means that all the data of -the field is stored within the DPF service. This is important because -when building your postprocessing workflows, the most efficient way of -interacting with result data is to minimize the exchange of data between -Python and DPF, either by using operators or by accessing only the data -that is needed. - -The field's ``data`` is ordered with respect to its ``scoping ids`` (see above). -To access the entire array of data as a ``numpy`` array: - -.. code-block:: python - - array = field.data - print(array) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPFArray([[ 4.01372930e+04, 3.85071930e+02, -1.40019130e+07, - 7.48472351e+02, -2.60259531e+04, -2.62856938e+05], - [-1.19228638e+03, -6.18210815e+02, -1.39912700e+07, - 2.61468994e+03, -1.31871719e+05, -2.59527125e+05], - [ 9.02558960e+02, 5.63793152e+02, -1.17102740e+07, - -8.99381836e+02, -1.21302727e+05, -2.45666328e+05], - ..., - [-3.99694531e+04, 1.44622528e+02, 9.62343100e+06, - -7.09812073e+02, -2.26106621e+04, -2.23155891e+05], - [-4.31104401e+02, -2.67612732e+02, 9.60954800e+06, - 1.93208755e+02, -1.11580734e+05, -2.24406062e+05], - [ 5.56899536e+02, 3.88515320e+02, 1.17119880e+07, - -1.68983887e+03, -1.21768023e+05, -2.41346125e+05]]) - -This array has 6 components by elementary data (symmetrical tensor XX,YY,ZZ,XY,YZ,XZ). -Note that this array is a genuine, local, numpy array (overloaded by the DPFArray). - -.. code-block:: python - - print(type(array)) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - - -If you need to access an individual node or element, request it -using either the ``get_entity_data()`` or ``get_entity_data_by_id()`` method: - -Get the data from the first element in the field. - -.. code-block:: python - - field.get_entity_data(0) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPFArray([[ 4.01372930e+04, 3.85071930e+02, -1.40019130e+07, - 7.48472351e+02, -2.60259531e+04, -2.62856938e+05], - [-1.19228638e+03, -6.18210815e+02, -1.39912700e+07, - 2.61468994e+03, -1.31871719e+05, -2.59527125e+05], - [ 9.02558960e+02, 5.63793152e+02, -1.17102740e+07, - -8.99381836e+02, -1.21302727e+05, -2.45666328e+05], - [ 3.97351055e+04, -2.43928162e+02, -1.17250040e+07, - 6.08324829e+02, -2.46618770e+04, -2.43019891e+05], - [-4.01372930e+04, -3.85071625e+02, 1.40019130e+07, - 7.48472534e+02, -2.60259531e+04, 2.62856938e+05], - [ 1.19228601e+03, 6.18211121e+02, 1.39912700e+07, - 2.61468970e+03, -1.31871719e+05, 2.59527125e+05], - [-9.02558777e+02, -5.63793701e+02, 1.17102740e+07, - -8.99382568e+02, -1.21302727e+05, 2.45666328e+05], - [-3.97351016e+04, 2.43927902e+02, 1.17250040e+07, - 6.08326172e+02, -2.46618770e+04, 2.43019891e+05]]) - -Get the data for the element with ID 10. - -.. code-block:: python - - field.get_entity_data_by_id(10) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPFArray([[ 4.99232031e+04, 1.93570602e+02, -3.08514075e+06, - -5.48255615e+02, -1.37476562e+04, 1.34827719e+05], - [ 5.23090469e+04, -1.87847885e+02, -1.98004588e+06, - -1.12942969e+03, -1.11147285e+04, 1.09223398e+05], - [-4.90510511e+00, -1.16425255e+02, -1.96296662e+06, - -5.48878540e+02, -5.48524844e+04, 1.09255164e+05], - [ 2.63994884e+01, 1.50431015e+02, -3.06906050e+06, - -1.17046680e+03, -6.76924219e+04, 1.34773391e+05], - [-4.99232031e+04, -1.93571167e+02, 3.08514075e+06, - -5.48256836e+02, -1.37476562e+04, -1.34827719e+05], - [-5.23090469e+04, 1.87848083e+02, 1.98004588e+06, - -1.12943201e+03, -1.11147295e+04, -1.09223398e+05], - [ 4.90471840e+00, 1.16423714e+02, 1.96296662e+06, - -5.48877380e+02, -5.48524844e+04, -1.09255164e+05], - [-2.63994102e+01, -1.50429443e+02, 3.06906050e+06, - -1.17046619e+03, -6.76924219e+04, -1.34773391e+05]]) - -Note that this would correspond to an index of 29 within the -field. Be aware that scoping IDs are not sequential. You would -get the index of element 29 in the field with: - -.. code-block:: python - - field.scoping.ids.index(10) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - 29 - -Here the data for the element with ID 10 is made of 8 symmetrical tensors. -The elastic strain has one tensor value by node by element (ElementalNodal location) - -To get the displacement on node 3, you would use: - -.. code-block:: python - - disp = model.results.displacement.eval()[0] - disp.get_entity_data_by_id(3) - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPFArray([[8.06571808e-14, 4.03580652e-04, 2.61804706e-05]]) - -One 3D vector (X,Y,Z) displacement - -While these methods are acceptable when requesting data for a few elements -or nodes, they should not be used when looping over the entire array. For efficiency, -a field's data can be recovered locally before sending a large number of requests: - -.. code-block:: python - - with field.as_local_field() as f: - for i in range(1,100): - f.get_entity_data_by_id(i) - - -Operate on field data ---------------------- -Oftentimes, you do not need to directly act on the data of an array within -Python. For example, if you want to know the maximum of the data, you can -use the ``array.max()`` method to compute the maximum of the array with the -``numpy`` package. However, this requires sending the entire array to Python -and then computing the maximum there. Rather than copying the array over and -computing the maximum in Python, you can instead compute the maximum directly -from the field itself. - -This example uses the ``min_max`` operator to compute the maximum of -the field while returning the field: - -Compute the maximum of the field within DPF and return the result -in a numpy array - -.. code-block:: python - - max_field = field.max() - max_field.data - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPFArray([22083762. , 22406040. , 52603044. , 1623704.25, 2443320.75, - 5014283.5 ]) - -Get the element or node ID of the maximum value. - - -.. code-block:: python - - max_field.scoping.ids - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - DPFArray([39, 39, 39, 40, 39, 39]) - - -This example uses the ``elemental_mean`` operator to compute the -average of a field: - -.. code-block:: python - - from ansys.dpf.core import operators as ops - avg_op = ops.averaging.elemental_mean(field) - avg_field = avg_op.outputs.field() - print(avg_field.get_entity_data(0)) - print(avg_field.location) - - -.. rst-class:: sphx-glr-script-out - - .. code-block:: none - - [[ 4.65393066e-04 -2.47955322e-05 0.00000000e+00 7.68026390e+02 - -7.59655688e+04 0.00000000e+00]] - Elemental - -For comprehensive information on chaining operators, see :ref:`ref_user_guide_operators`. - -API reference -------------- -For more information, see :ref:`ref_fields_container` and -:ref:`ref_field` in the **API reference**. diff --git a/doc/source/user_guide/tutorials/index.rst b/doc/source/user_guide/tutorials/index.rst index 5e3d5f9fc5..6ca3e35ec5 100644 --- a/doc/source/user_guide/tutorials/index.rst +++ b/doc/source/user_guide/tutorials/index.rst @@ -30,7 +30,7 @@ for each usage main step. .. grid:: 3 .. grid-item-card:: Data arrays - :link: ref_tutorials_model + :link: ref_tutorials_fields :link-type: ref :text-align: center From 61712c8381fde9b8a2d1a75f9aaa181f99586edb Mon Sep 17 00:00:00 2001 From: luisaFelixSalles Date: Fri, 27 Sep 2024 14:39:40 +0200 Subject: [PATCH 8/8] adaptation of the fields tutorial (field and fields containers main entities) --- doc/source/user_guide/tutorials/fields.rst | 159 ++++++++++----------- doc/source/user_guide/tutorials/index.rst | 2 +- 2 files changed, 75 insertions(+), 86 deletions(-) diff --git a/doc/source/user_guide/tutorials/fields.rst b/doc/source/user_guide/tutorials/fields.rst index 7231d54c0e..1bb2bd4944 100644 --- a/doc/source/user_guide/tutorials/fields.rst +++ b/doc/source/user_guide/tutorials/fields.rst @@ -1,25 +1,22 @@ -.. _ref_tutorials_fields: - -.. |Field| replace:: :class:`Field `: -.. |PropertyField| replace:: :class:`PropertyField `: -.. |StringField| replace:: :class:`StringField `: -.. |CustomTypeField| replace:: :class:`CustomTypeField ` +.. _ref_tutorials_data_arrays: =========== Data Arrays =========== +.. |Field| replace:: :class:`Field ` +.. |PropertyField| replace:: :class:`PropertyField ` +.. |StringField| replace:: :class:`StringField ` +.. |CustomTypeField| replace:: :class:`CustomTypeField ` + When DPF employ operators to manipulate the data, it uses data containers to store and return it. Therefore, it is important to be aware of how the data is structured in those containers. The data containers can be: - - **Raw data storage structures**: Data arrays (a ``Field`` for example) - or Data Maps (a ``DataTree`` for example) - - **Collections**: a group of same labeled objects from one DPF raw data storage - structure (a ``FieldsContainer`` for example, that is a group of ``Fields`` - with the same label) + - **Raw data storage structures**: Data arrays (a ``Field`` for example) or Data Maps (a ``DataTree`` for example) + - **Collections**: a group of same labeled objects from one DPF raw data storage structure (a ``FieldsContainer`` for example, that is a group of ``Fields`` with the same label) This tutorial presents how some DPF data arrays are defined and manipulated. The main difference between them is the data type they contain: @@ -32,16 +29,11 @@ them is the data type they contain: Therefore, the first one is typically found when manipulating the results. The two following are typically found when analysing the mesh and its properties. - Their data is always associated to: +Their data is always associated to: - - A ``location``: What typology of the finite element method was used to give - the results. There are different spatial ``locations`` that can be found - at: :class:`locations ` but the most used - are : ``Nodal``, ``Elemental`` and ``Elemental Nodal``. + - A ``location``: What typology of the finite element method was used to give the results. There are different spatial ``locations`` that can be found at: :class:`locations ` but the most used are : ``Nodal``, ``Elemental`` and ``Elemental Nodal``. - - The ``support``: The simulation basis functions are integrated over a calculus - domain, the support of the analysis. This domain is a physical component, - usually represented by: a mesh, geometrical component, time or frequency values. + - The ``support``: The simulation basis functions are integrated over a calculus domain, the support of the analysis. This domain is a physical component, usually represented by: a mesh, geometrical component, time or frequency values. When defining an operator, you must narrow down which parts of the initial data are relevant for the goals of the analysis. Thus, you must define the data container @@ -174,8 +166,7 @@ To define the scope we have to make two considerations: the location and the support of interest: 1) The location: which component will be enumerated (list of nodes for example) - 2) The support: the list is relative about which domain (list of nodes of a given - meshed region) + 2) The support: the list is relative about which domain (list of nodes of a given, meshed region) Therefore, we have two main supports to scope in: time and mesh domains. You specify the set of components by defining a range of IDs: @@ -251,7 +242,7 @@ The final operator with those scopes would look like: # Time scoping targets the times ids 14, 15, 16, 17 # Mesh scoping targets the nodes with the ids 103, 204, 334, 1802 my_disp = my_model.results.displacement(time_scoping=my_time_scoping, mesh_scoping=my_mesh_scoping) - print(my_disp) + print(my_disp.eval()) .. rst-class:: sphx-glr-script-out @@ -263,14 +254,14 @@ The final operator with those scopes would look like: my_model = dpf.Model(examples.download_transient_result()) my_mesh_scoping = dpf.Scoping(ids=[103, 204, 334, 1802], location=dpf.locations.nodal) my_disp = my_model.results.displacement(time_scoping=[14, 15, 16, 17], mesh_scoping=my_mesh_scoping) - print(my_disp) + print(my_disp.eval()) Other scope helpers are available at: :class:`Result `. Specific examples about how to implement some scopings can be found at: - - :mod:'Scope results over time domain ' - - :mod:'Scope results over space domain ' + - :mod:`Scope results over time domain ` + - :mod:`Scope results over space domain ` Fields ------ @@ -362,10 +353,10 @@ module: # By default, the field contains 3d vectors # So with 2 entities we need 6 data values my_PropertyField.data = [12, 25] - # Assign a location - my_PropertyField.location = dpf.locations.nodal # Define the scoping my_PropertyField.scoping.ids = range(num_entities) + # Assign a location + my_PropertyField.location = dpf.locations.nodal print(my_PropertyField) @@ -378,8 +369,8 @@ module: num_entities = 2 my_PropertyField = dpf.PropertyField(nentities=num_entities) my_PropertyField.data = [12, 25] - my_PropertyField.location = dpf.locations.nodal my_PropertyField.scoping.ids = range(num_entities) + my_PropertyField.location = dpf.locations.nodal print(my_PropertyField) @@ -549,7 +540,7 @@ and units of the data. # Components count # Vectors dimension, here we have a displacement so we expect to have 3 components (X, Y and Z) my_components_count = my_disp_field.component_count - print("component_count", '\n', my_component_count, '\n') + print("components_count", '\n', my_components_count, '\n') # Size # Length of the data entire vector (equal to the number of elementary data times the number of components.) @@ -562,7 +553,7 @@ and units of the data. print("shape", '\n', my_shape, '\n') # Units - my_units = my_disp_field.unit + my_unit = my_disp_field.unit print("unit", '\n', my_unit, '\n') .. rst-class:: sphx-glr-script-out @@ -578,19 +569,17 @@ and units of the data. print("location", '\n', my_location,'\n') my_scoping = my_disp_field.scoping print("scoping", '\n',my_scoping, '\n') - print('\n', "We have a location entity of type 'Nodal' (consistent with the output of the `location` helper) and - 3820 nodes", '\n') + print("We have a location entity of type 'Nodal' (consistent with the output of the `location` helper) and 3820 nodes", '\n') my_scoping_ids = my_disp_field.scoping.ids print("scoping.ids", '\n', my_scoping_ids, '\n') my_components_count = my_disp_field.component_count - print("component_count", '\n', my_component_count, '\n') + print("components_count", '\n', my_components_count, '\n') my_elementary_data_count = my_disp_field.elementary_data_count print("elementary_data_count", '\n', my_elementary_data_count, '\n') my_shape = my_disp_field.shape print("shape", '\n', my_shape, '\n') - print('\n', "We have a Field with 3820 data vectors (consistent with the number of nodes) and each vector has - 3 components (consistent with a displacement vector dimension)", '\n') - my_units = my_disp_field.unit + print("We have a Field with 3820 data vectors (consistent with the number of nodes) and each vector has 3 components (consistent with a displacement vector dimension)", '\n') + my_unit = my_disp_field.unit print("unit", '\n', my_unit, '\n') .. tab-item:: StringField @@ -616,7 +605,7 @@ and units of the data. # Components count # Data dimension, here we expect one name by zone my_components_count = my_string_field.component_count - print("component_count", '\n', my_component_count, '\n') + print("components_count", '\n', my_components_count, '\n') # Size # Length of the data entire array (equal to the number of elementary data times the number of components.) @@ -643,18 +632,16 @@ and units of the data. print("location", '\n', my_location,'\n') my_scoping = my_string_field.scoping print("scoping", '\n',my_scoping, '\n') - print('\n', "We have a location entity of type 'Zone' (consistent with the output of the `location` helper) and - 24 zones", '\n') + print("We have a location entity of type 'Zone' (consistent with the output of the `location` helper) and 24 zones", '\n') my_scoping_ids = my_string_field.scoping.ids print("scoping.ids", '\n', my_scoping_ids, '\n') my_components_count = my_string_field.component_count - print("component_count", '\n', my_component_count, '\n') + print("components_count", '\n', my_components_count, '\n') my_elementary_data_count = my_string_field.elementary_data_count print("elementary_data_count", '\n', my_elementary_data_count, '\n') my_shape = my_string_field.shape print("shape", '\n', my_shape, '\n') - print('\n', "We have a StringField with 24 names (consistent with the number of zones) and - each zone has one name) + print("We have a StringField with 24 names (consistent with the number of zones) and each zone has one name", '\n') .. tab-item:: PropertyField @@ -679,7 +666,7 @@ and units of the data. # Components count # Data dimension, we expect to have one id by face that makes part of a body my_components_count = my_property_field.component_count - print("component_count", '\n', my_component_count, '\n') + print("components_count", '\n', my_component_count, '\n') # Size # Length of the data entire array (equal to the number of elementary data times the number of components.) @@ -706,18 +693,16 @@ and units of the data. print("location", '\n', my_location,'\n') my_scoping = my_property_field.scoping print("scoping", '\n',my_scoping, '\n') - print('\n', "We have a location entity of type 'Body' (consistent with the output of the `location` helper) and - 2 bodies", '\n') + print("We have a location entity of type 'Body' (consistent with the output of the `location` helper) and 2 bodies", '\n') my_scoping_ids = my_property_field.scoping.ids print("scoping.ids", '\n', my_scoping_ids, '\n') my_components_count = my_property_field.component_count - print("component_count", '\n', my_component_count, '\n') + print("components_count", '\n', my_components_count, '\n') my_elementary_data_count = my_property_field.elementary_data_count print("elementary_data_count", '\n', my_elementary_data_count, '\n') my_shape = my_property_field.shape print("shape", '\n', my_shape, '\n') - print('\n', "We have a Field with 24 face ids (consistent with the number of faces) and each face has one - id, '\n') + print("We have a Field with 24 face ids (consistent with the number of faces) and each face has one id", '\n') Accessing fields data ~~~~~~~~~~~~~~~~~~~~~ @@ -793,7 +778,7 @@ To access the entire data in the field as an array (``numpy`` array``): my_model_2 = dpf.Model(data_sources=my_data_sources) my_mesh_info = my_model_2.metadata.mesh_info my_string_field = my_mesh_info.get_property(property_name="face_zone_names") - my_data_array = my_disp_field.data + my_data_array = my_string_field.data print(my_data_array) .. tab-item:: PropertyField @@ -823,57 +808,61 @@ If you need to access an individual node or element, request it using either the :func:`get_entity_data()` or :func:`get_entity_data_by_id()` methods: -.. code-block:: python +.. tab-set:: - # Get the data from the third element in the field - my_disp_field.get_entity_data(index=3) + .. tab-item:: Field -.. rst-class:: sphx-glr-script-out + .. code-block:: python - .. exec_code:: - :hide_code: + # Get the data from the third element in the field + my_disp_field.get_entity_data(index=3) - from ansys.dpf import core as dpf - from ansys.dpf.core import examples - my_model = dpf.Model(examples.download_transient_result()) - my_disp_field = my_model.results.displacement.eval()[0] - print(my_disp_field.get_entity_data(index=3)) + .. rst-class:: sphx-glr-script-out -.. code-block:: python + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + print(my_disp_field.get_entity_data(index=3)) - # Get the data from the element with id 533 - my_disp_field.get_entity_data_by_id(id=533) + .. code-block:: python -.. rst-class:: sphx-glr-script-out + # Get the data from the element with id 533 + my_disp_field.get_entity_data_by_id(id=533) - .. exec_code:: - :hide_code: + .. rst-class:: sphx-glr-script-out - from ansys.dpf import core as dpf - from ansys.dpf.core import examples - my_model = dpf.Model(examples.download_transient_result()) - my_disp_field = my_model.results.displacement.eval()[0] - print(my_disp_field.get_entity_data(id=533)) + .. exec_code:: + :hide_code: -Note that this would correspond to an index of 2 within the -field. Be aware that scoping IDs are not sequential. You would -get the index of element 2 in the field with: + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + print(my_disp_field.get_entity_data_by_id(id=533)) -.. code-block:: python + Note that this would correspond to an index of 2 within the + field. Be aware that scoping IDs are not sequential. You would + get the index of element 2 in the field with: - # Get index of the element with id 533 - my_disp_field.scoping.index(id=533) + .. code-block:: python -.. rst-class:: sphx-glr-script-out + # Get index of the element with id 533 + my_disp_field.scoping.index(id=533) - .. exec_code:: - :hide_code: + .. rst-class:: sphx-glr-script-out - from ansys.dpf import core as dpf - from ansys.dpf.core import examples - my_model = dpf.Model(examples.download_transient_result()) - my_disp_field = my_model.results.displacement.eval()[0] - print(my_disp_field.scoping.index(id=533)) + .. exec_code:: + :hide_code: + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + my_model = dpf.Model(examples.download_transient_result()) + my_disp_field = my_model.results.displacement.eval()[0] + print(my_disp_field.scoping.index(id=533)) While these methods are acceptable when requesting data for a few elements or nodes, they should not be used when looping over the entire array. For efficiency, diff --git a/doc/source/user_guide/tutorials/index.rst b/doc/source/user_guide/tutorials/index.rst index 6ca3e35ec5..46a527b46b 100644 --- a/doc/source/user_guide/tutorials/index.rst +++ b/doc/source/user_guide/tutorials/index.rst @@ -30,7 +30,7 @@ for each usage main step. .. grid:: 3 .. grid-item-card:: Data arrays - :link: ref_tutorials_fields + :link: ref_tutorials_data_arrays :link-type: ref :text-align: center