diff --git a/.ci/build_doc.bat b/.ci/build_doc.bat index 149a9890d0..a8067ca9c0 100644 --- a/.ci/build_doc.bat +++ b/.ci/build_doc.bat @@ -1,5 +1,5 @@ set SPHINX_APIDOC_OPTIONS=inherited-members -call sphinx-apidoc -o ../docs/source/api ../src/ansys ../src/ansys/dpf/core/log.py ^ +call sphinx-apidoc -o ../doc/source/api ../src/ansys ../src/ansys/dpf/core/log.py ^ ../src/ansys/dpf/core/help.py ../src/ansys/dpf/core/mapping_types.py ../src/ansys/dpf/core/ipconfig.py ^ ../src/ansys/dpf/core/field_base.py ../src/ansys/dpf/core/cache.py ../src/ansys/dpf/core/misc.py ^ ../src/ansys/dpf/core/check_version.py ../src/ansys/dpf/core/operators/build.py ../src/ansys/dpf/core/operators/specification.py ^ @@ -8,7 +8,7 @@ call sphinx-apidoc -o ../docs/source/api ../src/ansys ../src/ansys/dpf/core/log. ../src/ansys/dpf/core/property_fields_container.py ^ -f --implicit-namespaces --separate --no-headings pushd . -cd ../docs/ +cd ../doc/ call make clean call make html -v -v -v -P diff --git a/.ci/build_operators_doc.py b/.ci/build_operators_doc.py index a031f071f8..f36feff989 100644 --- a/.ci/build_operators_doc.py +++ b/.ci/build_operators_doc.py @@ -7,5 +7,5 @@ # Generate entry documentation print("Generating operator documentation") print(f"Current context: {SERVER_CONTEXT}") -dpf.operators.utility.html_doc(r"../docs/source/_static/dpf_operators.html").eval() +dpf.operators.utility.html_doc(r"../doc/source/_static/dpf_operators.html").eval() print("Done.\n") diff --git a/.flake8 b/.flake8 index 17e85525f0..c5c5daf0b1 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -exclude = venv, src/ansys/dpf/core/operators, __init__.py, docs/build, .venv, src/ansys/dpf/gate, src/ansys/dpf/gatebin, src/ansys/grpc/dpf +exclude = venv, src/ansys/dpf/core/operators, __init__.py, doc/build, .venv, src/ansys/dpf/gate, src/ansys/dpf/gatebin, src/ansys/grpc/dpf select = W191, W391, E115, E117, E122, E124, E125, E301, W291, W293, E225, E231, E303, E501, F401, F403 per-file-ignores = __init__.py:F401,F403 diff --git a/.github/labeler.yml b/.github/labeler.yml index f1cd367cb2..b59e934d8c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,5 +1,5 @@ documentation: -- docs/source/**/* +- doc/source/**/* - examples/**/* maintenance: - .flake8 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 704654c2ef..164138f32b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -52,7 +52,6 @@ jobs: uses: ansys/actions/doc-style@v5.0 with: token: ${{ secrets.GITHUB_TOKEN }} - vale-config: "docs/.vale.ini" docs: name: "Documentation" @@ -140,12 +139,12 @@ jobs: shell: cmd working-directory: .ci run: | - build_doc.bat > ..\docs\log.txt && type ..\docs\log.txt 2>&1 + build_doc.bat > ..\doc\log.txt && type ..\doc\log.txt 2>&1 timeout-minutes: 60 - name: "Check for success" shell: bash - working-directory: docs + working-directory: doc run: | case `grep -F "build succeeded" log.txt >/dev/null; echo $?` in 0) @@ -175,13 +174,13 @@ jobs: uses: actions/upload-artifact@v3 with: name: doc-${{env.PACKAGE_NAME}}-log - path: docs/*.txt + path: doc/*.txt if: always() - name: "Zip HTML Documentation" shell: pwsh run: | - Compress-Archive -Path docs/build/html/* -Destination HTML-doc-${{env.PACKAGE_NAME}}.zip + Compress-Archive -Path doc/build/html/* -Destination HTML-doc-${{env.PACKAGE_NAME}}.zip if: always() - name: "Upload HTML Documentation" diff --git a/.github/workflows/update_operators.yml b/.github/workflows/update_operators.yml index b8537d5f2f..859833a298 100644 --- a/.github/workflows/update_operators.yml +++ b/.github/workflows/update_operators.yml @@ -136,7 +136,7 @@ jobs: src/ansys/dpf/gatebin/* src/ansys/grpc/* src/ansys/dpf/core/operators/* - docs/source/_static/dpf_operators.html + doc/source/_static/dpf_operators.html commit-message: update generated code title: Update generated code for DPF ${{ github.event.inputs.ANSYS_VERSION || '242' }}${{ github.event.inputs.standalone_branch_suffix || '' }} on ${{ github.ref_name }} body: An update of generated code has been triggered either manually or by an update in the dpf-standalone repository. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cad541b0d1..d00a4c315e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,10 +1,10 @@ exclude: | (?x)^( - docs/source/| + doc/source/| src/ansys/dpf/core/operators/| examples_notebooks/| src/ansys/dpf/core/__init__.py| - docs/styles/| + doc/styles/| src/ansys/dpf/gate/| src/ansys/dpf/gatebin/| src/ansys/grpc/dpf/| diff --git a/Makefile b/Makefile index c7b2d164f4..9b6a574724 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Simple makefile to simplify repetitive build env management tasks under posix CODESPELL_DIRS ?= ./ -CODESPELL_SKIP ?= "*.pyc,*.txt,*.gif,*.png,*.jpg,*.js,*.html,*.doctree,*.ttf,*.woff,*.woff2,*.eot,*.mp4,*.inv,*.pickle,*.ipynb,flycheck*,./.git/*,./.hypothesis/*,*.yml,./docs/build/*,./docs/images/*,./dist/*,*~,.hypothesis*,./docs/source/examples/*,*cover,*.dat,*.mac,\#*,build,./ansys/dpf/core/raw_operators.py,./run_client.bat,./docker/v211" +CODESPELL_SKIP ?= "*.pyc,*.txt,*.gif,*.png,*.jpg,*.js,*.html,*.doctree,*.ttf,*.woff,*.woff2,*.eot,*.mp4,*.inv,*.pickle,*.ipynb,flycheck*,./.git/*,./.hypothesis/*,*.yml,./doc/build/*,./doc/images/*,./dist/*,*~,.hypothesis*,./doc/source/examples/*,*cover,*.dat,*.mac,\#*,build,./ansys/dpf/core/raw_operators.py,./run_client.bat,./docker/v211" CODESPELL_IGNORE ?= "ignore_words.txt" all: doctest diff --git a/codecov.yml b/codecov.yml index d8a9d1785e..a76be46360 100644 --- a/codecov.yml +++ b/codecov.yml @@ -15,7 +15,7 @@ coverage: if_no_uploads: error ignore: - "examples" # ignore folder and all its contents - - "docs" # ignore folder and all its contents + - "doc" # ignore folder and all its contents - "docker" # ignore folder and all its contents - "tests" # ignore folder and all its contents - "src/ansys/dpf/core/operators" # ignore folder and all its contents diff --git a/docs/.vale.ini b/doc/.vale.ini similarity index 96% rename from docs/.vale.ini rename to doc/.vale.ini index f2510e048b..79dfe17ca3 100644 --- a/docs/.vale.ini +++ b/doc/.vale.ini @@ -1,43 +1,43 @@ -# Core settings -# ============= - -# Location of our `styles` -StylesPath = "styles" - -# The options are `suggestion`, `warning`, or `error` (defaults to “warning”). -MinAlertLevel = warning - -# By default, `code` and `tt` are ignored. -IgnoredScopes = code, tt - -# By default, `script`, `style`, `pre`, and `figure` are ignored. -SkippedScopes = script, style, pre, figure - -# WordTemplate specifies what Vale will consider to be an individual word. -WordTemplate = \b(?:%s)\b - -# List of Packages to be used for our guidelines -Packages = Google - -# Define the Ansys vocabulary -Vocab = ANSYS - -[*.{md,rst}] - -# Apply the following styles -BasedOnStyles = Vale, Google - -# Removing Google-specific rule - Not applicable under some circumstances -Google.WordList = NO -Google.Colons = NO -Google.Headings = NO - -[formats] -# Format associations appear under -# the optional "formats" section. - -[*] -# Format-specific settings appear -# under a user-provided "glob" -# pattern. +# Core settings +# ============= + +# Location of our `styles` +StylesPath = "styles" + +# The options are `suggestion`, `warning`, or `error` (defaults to “warning”). +MinAlertLevel = warning + +# By default, `code` and `tt` are ignored. +IgnoredScopes = code, tt + +# By default, `script`, `style`, `pre`, and `figure` are ignored. +SkippedScopes = script, style, pre, figure + +# WordTemplate specifies what Vale will consider to be an individual word. +WordTemplate = \b(?:%s)\b + +# List of Packages to be used for our guidelines +Packages = Google + +# Define the Ansys vocabulary +Vocab = ANSYS + +[*.{md,rst}] + +# Apply the following styles +BasedOnStyles = Vale, Google + +# Removing Google-specific rule - Not applicable under some circumstances +Google.WordList = NO +Google.Colons = NO +Google.Headings = NO + +[formats] +# Format associations appear under +# the optional "formats" section. + +[*] +# Format-specific settings appear +# under a user-provided "glob" +# pattern. TokenIgnores = (:class:\x60.*\x60|:meth:\x60.*\x60|:py:class:\x60.*\x60|:py:meth:\x60.*\x60) \ No newline at end of file diff --git a/docs/make.bat b/doc/make.bat similarity index 96% rename from docs/make.bat rename to doc/make.bat index f925a5d265..6f2dec1e0c 100644 --- a/docs/make.bat +++ b/doc/make.bat @@ -1,72 +1,72 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -if "%1" == "" goto help -if "%1" == "clean" goto clean - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:clean -echo.Cleaning files form previous build... -IF EXIST "build" ( - rmdir "build" /s /q -) -IF EXIST "source\images\auto-generated" ( - rmdir "source\images\auto-generated" /s /q -) -IF EXIST "source\examples\07-python-operators\plugins" ( - robocopy "source\examples\07-python-operators\plugins" "source\_temp\plugins" /E >nul 2>&1 -) -IF EXIST "source\examples\04-advanced\02-volume_averaged_stress" ( - robocopy "source\examples\04-advanced\02-volume_averaged_stress" "source\_temp\04_advanced" /E >nul 2>&1 -) -IF EXIST "source\examples\12-fluids\02-fluids_results" ( - robocopy "source\examples\12-fluids\02-fluids_results" "source\_temp\12_fluids" /E >nul 2>&1 -) -IF EXIST "source\examples" ( - rmdir "source\examples" /s /q -) -IF EXIST "source\_temp\plugins" ( - robocopy "source\_temp\plugins" "source\examples\07-python-operators\plugins" /E >nul 2>&1 -) -IF EXIST "source\_temp\04_advanced" ( - robocopy "source\_temp\04_advanced" "source\examples\04-advanced\02-volume_averaged_stress" /E >nul 2>&1 -) -IF EXIST "source\_temp\12_fluids" ( - robocopy "source\_temp\12_fluids" "source\examples\12-fluids\02-fluids_results" /E >nul 2>&1 -) -IF EXIST "source\_temp" ( - rmdir "source\_temp" /s /q -) - -echo.Done. -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help +if "%1" == "clean" goto clean + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:clean +echo.Cleaning files form previous build... +IF EXIST "build" ( + rmdir "build" /s /q +) +IF EXIST "source\images\auto-generated" ( + rmdir "source\images\auto-generated" /s /q +) +IF EXIST "source\examples\07-python-operators\plugins" ( + robocopy "source\examples\07-python-operators\plugins" "source\_temp\plugins" /E >nul 2>&1 +) +IF EXIST "source\examples\04-advanced\02-volume_averaged_stress" ( + robocopy "source\examples\04-advanced\02-volume_averaged_stress" "source\_temp\04_advanced" /E >nul 2>&1 +) +IF EXIST "source\examples\12-fluids\02-fluids_results" ( + robocopy "source\examples\12-fluids\02-fluids_results" "source\_temp\12_fluids" /E >nul 2>&1 +) +IF EXIST "source\examples" ( + rmdir "source\examples" /s /q +) +IF EXIST "source\_temp\plugins" ( + robocopy "source\_temp\plugins" "source\examples\07-python-operators\plugins" /E >nul 2>&1 +) +IF EXIST "source\_temp\04_advanced" ( + robocopy "source\_temp\04_advanced" "source\examples\04-advanced\02-volume_averaged_stress" /E >nul 2>&1 +) +IF EXIST "source\_temp\12_fluids" ( + robocopy "source\_temp\12_fluids" "source\examples\12-fluids\02-fluids_results" /E >nul 2>&1 +) +IF EXIST "source\_temp" ( + rmdir "source\_temp" /s /q +) + +echo.Done. +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/_static/custom.css b/doc/source/_static/custom.css similarity index 100% rename from docs/source/_static/custom.css rename to doc/source/_static/custom.css diff --git a/docs/source/_static/dpf_operators.html b/doc/source/_static/dpf_operators.html similarity index 100% rename from docs/source/_static/dpf_operators.html rename to doc/source/_static/dpf_operators.html diff --git a/docs/source/_static/simple_example.rst b/doc/source/_static/simple_example.rst similarity index 100% rename from docs/source/_static/simple_example.rst rename to doc/source/_static/simple_example.rst diff --git a/docs/source/api/index.rst b/doc/source/api/index.rst similarity index 100% rename from docs/source/api/index.rst rename to doc/source/api/index.rst diff --git a/docs/source/concepts/concepts.rst b/doc/source/concepts/concepts.rst similarity index 100% rename from docs/source/concepts/concepts.rst rename to doc/source/concepts/concepts.rst diff --git a/docs/source/concepts/index.rst b/doc/source/concepts/index.rst similarity index 100% rename from docs/source/concepts/index.rst rename to doc/source/concepts/index.rst diff --git a/docs/source/concepts/stepbystep.rst b/doc/source/concepts/stepbystep.rst similarity index 100% rename from docs/source/concepts/stepbystep.rst rename to doc/source/concepts/stepbystep.rst diff --git a/docs/source/concepts/waysofusing.rst b/doc/source/concepts/waysofusing.rst similarity index 100% rename from docs/source/concepts/waysofusing.rst rename to doc/source/concepts/waysofusing.rst diff --git a/docs/source/conf.py b/doc/source/conf.py similarity index 100% rename from docs/source/conf.py rename to doc/source/conf.py diff --git a/docs/source/contributing.rst b/doc/source/contributing.rst similarity index 100% rename from docs/source/contributing.rst rename to doc/source/contributing.rst diff --git a/doc/source/examples/00-basic/00-basic_example.ipynb b/doc/source/examples/00-basic/00-basic_example.ipynb new file mode 100644 index 0000000000..ee3bea08c6 --- /dev/null +++ b/doc/source/examples/00-basic/00-basic_example.ipynb @@ -0,0 +1,155 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Basic DPF-Core usage {#ref_basic_example}\r\n\r\nThis example shows how to open a result file and do some basic\r\npostprocessing.\r\n\r\nIf you have Ansys 2021 R1 or higher installed, starting DPF is quite\r\neasy as DPF-Core takes care of launching all the services that are\r\nrequired for postprocessing Ansys files.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# First, import the DPF-Core module as ``dpf`` and import the included examples file.\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, open an example and print out the `model` object. The\r\n`Model `{.interpreted-text role=\"class\"}\r\nclass helps to organize access methods for the result by keeping track\r\nof the operators and data sources used by the result file.\r\n\r\nPrinting the model displays:\r\n\r\n- Analysis type\r\n- Available results\r\n- Size of the mesh\r\n- Number of results\r\n\r\nAlso, note that the first time you create a DPF object, Python\r\nautomatically attempts to start the server in the background. If you\r\nwant to connect to an existing server (either local or remote), use\r\n`ansys.dpf.core.connect_to_server`{.interpreted-text role=\"func\"}.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.find_simple_bar())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Model metadata\r\n\r\nSpecific metadata can be extracted from the model by referencing the\r\nmodel\\'s `metadata` property. For example, to print only the\r\n`result_info`:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "metadata = model.metadata\nprint(metadata.result_info)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the mesh region:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(metadata.meshed_region)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the time or frequency of the results:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(metadata.time_freq_support)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extract displacement results\r\n\r\nAll results of the model can be accessed through the `results` property,\r\nwhich returns the `ansys.dpf.core.results.Results`{.interpreted-text\r\nrole=\"class\"} class. This class contains the DPF result operators\r\navailable to a specific result file, which are listed when printing the\r\nobject with `print(results)`.\r\n\r\nHere, the `'U'` operator is connected with `data_sources`, which takes\r\nplace automatically when running `results.displacement()`. By default,\r\nthe `'U'` operator is connected to the first result set, which for this\r\nstatic result is the only result.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "results = model.results\ndisplacements = results.displacement()\nfields = displacements.outputs.fields_container()\n\n# Finally, extract the data of the displacement field:\ndisp = fields[0].data\ndisp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model.metadata.meshed_region.plot(fields)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/00-basic_example.py b/doc/source/examples/00-basic/00-basic_example.py new file mode 100644 index 0000000000..76869f38f9 --- /dev/null +++ b/doc/source/examples/00-basic/00-basic_example.py @@ -0,0 +1,84 @@ +# noqa: D400 +""" +.. _ref_basic_example: + +Basic DPF-Core usage +~~~~~~~~~~~~~~~~~~~~ + +This example shows how to open a result file and do some +basic postprocessing. + +If you have Ansys 2021 R1 or higher installed, starting DPF is quite easy +as DPF-Core takes care of launching all the services that +are required for postprocessing Ansys files. + +""" + +# First, import the DPF-Core module as ``dpf`` and import the included examples file. +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# Next, open an example and print out 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. +# +# Printing the model displays: +# +# - Analysis type +# - Available results +# - Size of the mesh +# - Number of results +# +# Also, note that the first time you create a DPF object, Python +# automatically attempts to start the server in the background. If you +# want to connect to an existing server (either local or remote), use +# :func:`ansys.dpf.core.connect_to_server`. + +model = dpf.Model(examples.find_simple_bar()) +print(model) + +############################################################################### +# Model metadata +# ~~~~~~~~~~~~~~ +# Specific metadata can be extracted from the model by referencing the +# model's ``metadata`` property. For example, to print only the +# ``result_info``: + +metadata = model.metadata +print(metadata.result_info) + +############################################################################### +# Print the mesh region: + +print(metadata.meshed_region) + +############################################################################### +# Print the time or frequency of the results: + +print(metadata.time_freq_support) + +############################################################################### +# Extract displacement results +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# All results of the model can be accessed through the ``results`` +# property, which returns the :class:`ansys.dpf.core.results.Results` +# class. This class contains the DPF result operators available to a +# specific result file, which are listed when printing the object with +# ``print(results)``. +# +# Here, the ``'U'`` operator is connected with ``data_sources``, which +# takes place automatically when running ``results.displacement()``. +# By default, the ``'U'`` operator is connected to the first result set, +# which for this static result is the only result. +results = model.results +displacements = results.displacement() +fields = displacements.outputs.fields_container() + +# Finally, extract the data of the displacement field: +disp = fields[0].data +disp + +############################################################################### +model.metadata.meshed_region.plot(fields) diff --git a/doc/source/examples/00-basic/00-basic_example.py.md5 b/doc/source/examples/00-basic/00-basic_example.py.md5 new file mode 100644 index 0000000000..7032bfa628 --- /dev/null +++ b/doc/source/examples/00-basic/00-basic_example.py.md5 @@ -0,0 +1 @@ +4ef93cbbe1649a2eaf5d90d7c61e67d5 \ No newline at end of file diff --git a/doc/source/examples/00-basic/00-basic_example.rst b/doc/source/examples/00-basic/00-basic_example.rst new file mode 100644 index 0000000000..9b67616199 --- /dev/null +++ b/doc/source/examples/00-basic/00-basic_example.rst @@ -0,0 +1,306 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\00-basic_example.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_00-basic_example.py: + + +.. _ref_basic_example: + +Basic DPF-Core usage +~~~~~~~~~~~~~~~~~~~~ + +This example shows how to open a result file and do some +basic postprocessing. + +If you have Ansys 2021 R1 or higher installed, starting DPF is quite easy +as DPF-Core takes care of launching all the services that +are required for postprocessing Ansys files. + +.. GENERATED FROM PYTHON SOURCE LINES 16-21 + +.. code-block:: default + + + # First, import the DPF-Core module as ``dpf`` and import the included examples file. + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-38 + +Next, open an example and print out 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. + +Printing the model displays: + +- Analysis type +- Available results +- Size of the mesh +- Number of results + +Also, note that the first time you create a DPF object, Python +automatically attempts to start the server in the background. If you +want to connect to an existing server (either local or remote), use +:func:`ansys.dpf.core.connect_to_server`. + +.. GENERATED FROM PYTHON SOURCE LINES 38-42 + +.. code-block:: default + + + model = dpf.Model(examples.find_simple_bar()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - element_nodal_forces: ElementalNodal Element nodal Forces + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 3751 nodes + 3000 elements + Unit: m + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1 + Cumulative Time (s) LoadStep Substep + 1 1,000000 1 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 43-48 + +Model metadata +~~~~~~~~~~~~~~ +Specific metadata can be extracted from the model by referencing the +model's ``metadata`` property. For example, to print only the +``result_info``: + +.. GENERATED FROM PYTHON SOURCE LINES 48-52 + +.. code-block:: default + + + metadata = model.metadata + print(metadata.result_info) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - element_nodal_forces: ElementalNodal Element nodal Forces + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 53-54 + +Print the mesh region: + +.. GENERATED FROM PYTHON SOURCE LINES 54-57 + +.. code-block:: default + + + print(metadata.meshed_region) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Meshed Region: + 3751 nodes + 3000 elements + Unit: m + With solid (3D) elements + + + + +.. GENERATED FROM PYTHON SOURCE LINES 58-59 + +Print the time or frequency of the results: + +.. GENERATED FROM PYTHON SOURCE LINES 59-62 + +.. code-block:: default + + + print(metadata.time_freq_support) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Time/Freq Support: + Number of sets: 1 + Cumulative Time (s) LoadStep Substep + 1 1,000000 1 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 63-75 + +Extract displacement results +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +All results of the model can be accessed through the ``results`` +property, which returns the :class:`ansys.dpf.core.results.Results` +class. This class contains the DPF result operators available to a +specific result file, which are listed when printing the object with +``print(results)``. + +Here, the ``'U'`` operator is connected with ``data_sources``, which +takes place automatically when running ``results.displacement()``. +By default, the ``'U'`` operator is connected to the first result set, +which for this static result is the only result. + +.. GENERATED FROM PYTHON SOURCE LINES 75-83 + +.. code-block:: default + + results = model.results + displacements = results.displacement() + fields = displacements.outputs.fields_container() + + # Finally, extract the data of the displacement field: + disp = fields[0].data + disp + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + DPFArray([[-1.22753781e-08, -1.20861254e-06, -5.02681396e-06], + [-9.46666013e-09, -1.19379712e-06, -4.64249826e-06], + [-1.22188426e-08, -1.19494216e-06, -4.63117832e-06], + ..., + [-1.35911608e-08, 1.52559428e-06, -4.29246409e-06], + [-1.91212290e-08, 1.52577102e-06, -4.28782940e-06], + [-2.69632909e-08, 1.52485289e-06, -4.27831232e-06]]) + + + +.. GENERATED FROM PYTHON SOURCE LINES 84-85 + +.. code-block:: default + + model.metadata.meshed_region.plot(fields) + + + +.. image-sg:: /examples/00-basic/images/sphx_glr_00-basic_example_001.png + :alt: 00 basic example + :srcset: /examples/00-basic/images/sphx_glr_00-basic_example_001.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 8.994 seconds) + + +.. _sphx_glr_download_examples_00-basic_00-basic_example.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 00-basic_example.py <00-basic_example.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 00-basic_example.ipynb <00-basic_example.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/00-basic_example_codeobj.pickle b/doc/source/examples/00-basic/00-basic_example_codeobj.pickle new file mode 100644 index 0000000000..9b6037052d Binary files /dev/null and b/doc/source/examples/00-basic/00-basic_example_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/01-basic_operators.ipynb b/doc/source/examples/00-basic/01-basic_operators.ipynb new file mode 100644 index 0000000000..fb7e1f3ef1 --- /dev/null +++ b/doc/source/examples/00-basic/01-basic_operators.ipynb @@ -0,0 +1,223 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Operators overview {#ref_basic_operators_example}\r\n\r\nIn DPF, operators provide the primary method for interacting with and\r\nextracting results. Within DPF-Core, operators are directly exposed with\r\nthe `Operators` class as well as wrapped within several other\r\nconvenience classes.\r\n\r\nFor a list of all operators, see\r\n`ref_dpf_operators_reference`{.interpreted-text role=\"ref\"}.\r\n\r\nThis example demonstrates how to work directly with operators and\r\ncompares this method to a wrapped approach.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import the necessary modules\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a model object to establish a connection with an example result\r\nfile:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.find_static_rst())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, create a raw displacement operator `\"U\"`. Each operator contains\r\n`input` and `output` pins that can be connected to various sources to\r\ninclude other operators. This allows operators to be \\\"chained\\\" to\r\nallow for highly efficient operations.\r\n\r\nTo print out the available inputs and outputs of the displacement\r\noperator:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp_op = dpf.Operator(\"U\")\nprint(disp_op.inputs)\nprint(disp_op.outputs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compute the maximum normalized displacement\r\n\r\nThis example demonstrate how to chain various operators. It connects the\r\ninput of the operator to the data sources contained within the `model`\r\nobject and then the maximum of the norm of the operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Connect to the data sources of the model.\ndisp_op.inputs.data_sources.connect(model.metadata.data_sources)\n\n# Create a fields container norm operator and connect it to the\n# displacement operator to chain the operators.\nnorm_op = dpf.Operator(\"norm_fc\")\nnorm_op.inputs.connect(disp_op.outputs)\n\n# Create a fields container min/max operator and connect it to the\n# output of the norm operator.\nmm_op = dpf.Operator(\"min_max_fc\")\nmm_op.inputs.connect(norm_op.outputs)\n\n# Finally, get the value of the maximum displacement.\nfield_max = mm_op.outputs.field_max()\nprint(field_max)\nprint(field_max.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Wrapped operators\r\n\r\nThe `model.results` property contains all the wrapped operators\r\navailable for a given result. This is provided out of convenience\r\nbecause all operators may not be available for a given result.\r\nConsequently, it is much easier to reference available operators by\r\nfirst running:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(model.results)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the displacement operator directly from the `results` property:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp_op = model.results.displacement()\n\n# Out of convenience, the ``operators`` module contains available operators.\n# These operators can be chained to create a workflow in one line.\nfrom ansys.dpf.core import operators\n\nmm_op = operators.min_max.min_max_fc(operators.math.norm_fc(disp_op))\n\n# Finally, get the value of the maximum displacement.\nfield_max = mm_op.outputs.field_max()\nprint(field_max)\nprint(field_max.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the displacement:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(model.metadata.meshed_region.plot(disp_op.outputs.fields_container()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Scripting operator syntax\r\n\r\nBecause DPF provides a scripting syntax, knowing an operator\\'s \\\"string\r\nname\\\" is not mandatory. While this example is similar to the above\r\nscript, it uses the DPF scripting syntax.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instead of using a `model` class instance, use a `DdataSources` object\r\ndirectly. The `DataSources` constructor input is a path.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "ds = dpf.DataSources(examples.find_static_rst())\nprint(examples.find_static_rst())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instantiate the operators and connect them:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp_op = dpf.operators.result.displacement()\ndisp_op.inputs.data_sources.connect(ds)\nnorm_op = dpf.operators.math.norm_fc()\nnorm_op.inputs.connect(disp_op.outputs)\nmm_op = dpf.operators.min_max.min_max_fc()\nmm_op.inputs.connect(norm_op.outputs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the output and print the result data:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field_max = mm_op.outputs.field_max()\nprint(field_max.data)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/01-basic_operators.py b/doc/source/examples/00-basic/01-basic_operators.py new file mode 100644 index 0000000000..c4d6b787f2 --- /dev/null +++ b/doc/source/examples/00-basic/01-basic_operators.py @@ -0,0 +1,123 @@ +# noqa: D400 +""" +.. _ref_basic_operators_example: + +Operators overview +~~~~~~~~~~~~~~~~~~ + +In DPF, operators provide the primary method for interacting with and extracting +results. Within DPF-Core, operators are directly exposed with +the ``Operators`` class as well as wrapped within several other +convenience classes. + +For a list of all operators, see :ref:`ref_dpf_operators_reference`. + +This example demonstrates how to work directly with operators and +compares this method to a wrapped approach. + +""" + +# Import the necessary modules +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# Create a model object to establish a connection with an +# example result file: +model = dpf.Model(examples.find_static_rst()) +print(model) + +############################################################################### +# Next, create a raw displacement operator ``"U"``. Each operator +# contains ``input`` and ``output`` pins that can be connected to +# various sources to include other operators. This allows operators +# to be "chained" to allow for highly efficient operations. +# +# To print out the available inputs and outputs of the +# displacement operator: +disp_op = dpf.Operator("U") +print(disp_op.inputs) +print(disp_op.outputs) + +############################################################################### +# Compute the maximum normalized displacement +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This example demonstrate how to chain various operators. It connects the input +# of the operator to the data sources contained within the ``model`` object and +# then the maximum of the norm of the operator. + +# Connect to the data sources of the model. +disp_op.inputs.data_sources.connect(model.metadata.data_sources) + +# Create a fields container norm operator and connect it to the +# displacement operator to chain the operators. +norm_op = dpf.Operator("norm_fc") +norm_op.inputs.connect(disp_op.outputs) + +# Create a fields container min/max operator and connect it to the +# output of the norm operator. +mm_op = dpf.Operator("min_max_fc") +mm_op.inputs.connect(norm_op.outputs) + +# Finally, get the value of the maximum displacement. +field_max = mm_op.outputs.field_max() +print(field_max) +print(field_max.data) + +############################################################################### +# Wrapped operators +# ~~~~~~~~~~~~~~~~~ +# The ``model.results`` property contains all the wrapped operators +# available for a given result. This is provided out of convenience +# because all operators may not be available for a given result. Consequently, +# it is much easier to reference available operators by first running: +print(model.results) + +############################################################################### +# Create the displacement operator directly from the ``results`` property: +disp_op = model.results.displacement() + +# Out of convenience, the ``operators`` module contains available operators. +# These operators can be chained to create a workflow in one line. +from ansys.dpf.core import operators + +mm_op = operators.min_max.min_max_fc(operators.math.norm_fc(disp_op)) + +# Finally, get the value of the maximum displacement. +field_max = mm_op.outputs.field_max() +print(field_max) +print(field_max.data) + +############################################################################### +# Plot the displacement: +print(model.metadata.meshed_region.plot(disp_op.outputs.fields_container())) + +############################################################################### +# Scripting operator syntax +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Because DPF provides a scripting syntax, knowing +# an operator's "string name" is not mandatory. +# While this example is similar to the above script, it uses the DPF +# scripting syntax. + +############################################################################### +# Instead of using a ``model`` class instance, use a +# ``DdataSources`` object directly. The ``DataSources`` constructor input is a path. +ds = dpf.DataSources(examples.find_static_rst()) +print(examples.find_static_rst()) + +############################################################################### +# Instantiate the operators and connect them: + +disp_op = dpf.operators.result.displacement() +disp_op.inputs.data_sources.connect(ds) +norm_op = dpf.operators.math.norm_fc() +norm_op.inputs.connect(disp_op.outputs) +mm_op = dpf.operators.min_max.min_max_fc() +mm_op.inputs.connect(norm_op.outputs) + +############################################################################### +# Get the output and print the result data: + +field_max = mm_op.outputs.field_max() +print(field_max.data) diff --git a/doc/source/examples/00-basic/01-basic_operators.py.md5 b/doc/source/examples/00-basic/01-basic_operators.py.md5 new file mode 100644 index 0000000000..86d2e5754c --- /dev/null +++ b/doc/source/examples/00-basic/01-basic_operators.py.md5 @@ -0,0 +1 @@ +414065cfb723445d6ca6a2a1a6aab685 \ No newline at end of file diff --git a/doc/source/examples/00-basic/01-basic_operators.rst b/doc/source/examples/00-basic/01-basic_operators.rst new file mode 100644 index 0000000000..4c296b8dc1 --- /dev/null +++ b/doc/source/examples/00-basic/01-basic_operators.rst @@ -0,0 +1,463 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\01-basic_operators.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_01-basic_operators.py: + + +.. _ref_basic_operators_example: + +Operators overview +~~~~~~~~~~~~~~~~~~ + +In DPF, operators provide the primary method for interacting with and extracting +results. Within DPF-Core, operators are directly exposed with +the ``Operators`` class as well as wrapped within several other +convenience classes. + +For a list of all operators, see :ref:`ref_dpf_operators_reference`. + +This example demonstrates how to work directly with operators and +compares this method to a wrapped approach. + +.. GENERATED FROM PYTHON SOURCE LINES 19-24 + +.. code-block:: default + + + # Import the necessary modules + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 25-27 + +Create a model object to establish a connection with an +example result file: + +.. GENERATED FROM PYTHON SOURCE LINES 27-30 + +.. code-block:: default + + model = dpf.Model(examples.find_static_rst()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 81 nodes + 8 elements + Unit: m + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1 + Cumulative Time (s) LoadStep Substep + 1 1,000000 1 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 31-38 + +Next, create a raw displacement operator ``"U"``. Each operator +contains ``input`` and ``output`` pins that can be connected to +various sources to include other operators. This allows operators +to be "chained" to allow for highly efficient operations. + +To print out the available inputs and outputs of the +displacement operator: + +.. GENERATED FROM PYTHON SOURCE LINES 38-42 + +.. code-block:: default + + disp_op = dpf.Operator("U") + print(disp_op.inputs) + print(disp_op.outputs) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Available inputs: + - time_scoping : Scoping, int, list, float, Field, optional + Time/freq values (use doubles or field), time/freq set ids (use ints + or scoping) or time/freq step ids (use scoping with timefreq_steps + location) required in output. to specify time/freq values at specific + load steps, put a field (and not a list) in input with a scoping + located on "timefreq_steps". linear time freq intrapolation is + performed if the values are not in the result files and the data at + the max time or freq is taken when time/freqs are higher than + available time/freqs in result files. + + - mesh_scoping : ScopingsContainer, Scoping, optional + Nodes or elements scoping required in output. the output fields will + be scoped on these node or element ids. to figure out the ordering of + the fields data, look at their scoping ids as they might not be + ordered as the input scoping was. the scoping's location indicates + whether nodes or elements are asked for. using scopings container + allows you to split the result fields container into domains + + - fields_container : FieldsContainer, optional + Fields container already allocated modified inplace + + - streams_container : StreamsContainer, optional + Result file container allowed to be kept open to cache data + + - data_sources : DataSources + Result file path container, used if no streams are set + + - bool_rotate_to_global : bool, optional + If true the field is rotated to global coordinate system (default + true) + + - mesh : MeshedRegion, MeshesContainer, optional + Prevents from reading the mesh in the result files + + - read_cyclic : Enum Dataprocessing::Ecyclicreading, int, optional + If 0 cyclic symmetry is ignored, if 1 cyclic sector is read, if 2 + cyclic expansion is done, if 3 cyclic expansion is done and stages are + merged (default is 1) + + + Available outputs: + - fields_container + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 43-48 + +Compute the maximum normalized displacement +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example demonstrate how to chain various operators. It connects the input +of the operator to the data sources contained within the ``model`` object and +then the maximum of the norm of the operator. + +.. GENERATED FROM PYTHON SOURCE LINES 48-67 + +.. code-block:: default + + + # Connect to the data sources of the model. + disp_op.inputs.data_sources.connect(model.metadata.data_sources) + + # Create a fields container norm operator and connect it to the + # displacement operator to chain the operators. + norm_op = dpf.Operator("norm_fc") + norm_op.inputs.connect(disp_op.outputs) + + # Create a fields container min/max operator and connect it to the + # output of the norm operator. + mm_op = dpf.Operator("min_max_fc") + mm_op.inputs.connect(norm_op.outputs) + + # Finally, get the value of the maximum displacement. + field_max = mm_op.outputs.field_max() + print(field_max) + print(field_max.data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF displacement_1,s Field + Location: Nodal + Unit: m + 1 entities + Data: 1 components and 1 elementary data + + IDs data(m) + ------------ ---------- + 0 1.481537e-08 + + + + [1.48153706e-08] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 68-74 + +Wrapped operators +~~~~~~~~~~~~~~~~~ +The ``model.results`` property contains all the wrapped operators +available for a given result. This is provided out of convenience +because all operators may not be available for a given result. Consequently, +it is much easier to reference available operators by first running: + +.. GENERATED FROM PYTHON SOURCE LINES 74-76 + +.. code-block:: default + + print(model.results) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 77-78 + +Create the displacement operator directly from the ``results`` property: + +.. GENERATED FROM PYTHON SOURCE LINES 78-91 + +.. code-block:: default + + disp_op = model.results.displacement() + + # Out of convenience, the ``operators`` module contains available operators. + # These operators can be chained to create a workflow in one line. + from ansys.dpf.core import operators + + mm_op = operators.min_max.min_max_fc(operators.math.norm_fc(disp_op)) + + # Finally, get the value of the maximum displacement. + field_max = mm_op.outputs.field_max() + print(field_max) + print(field_max.data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF displacement_1,s Field + Location: Nodal + Unit: m + 1 entities + Data: 1 components and 1 elementary data + + IDs data(m) + ------------ ---------- + 0 1.481537e-08 + + + + [1.48153706e-08] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 92-93 + +Plot the displacement: + +.. GENERATED FROM PYTHON SOURCE LINES 93-95 + +.. code-block:: default + + print(model.metadata.meshed_region.plot(disp_op.outputs.fields_container())) + + + + +.. image-sg:: /examples/00-basic/images/sphx_glr_01-basic_operators_001.png + :alt: 01 basic operators + :srcset: /examples/00-basic/images/sphx_glr_01-basic_operators_001.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + None + + + + +.. GENERATED FROM PYTHON SOURCE LINES 96-102 + +Scripting operator syntax +~~~~~~~~~~~~~~~~~~~~~~~~~~ +Because DPF provides a scripting syntax, knowing +an operator's "string name" is not mandatory. +While this example is similar to the above script, it uses the DPF +scripting syntax. + +.. GENERATED FROM PYTHON SOURCE LINES 104-106 + +Instead of using a ``model`` class instance, use a +``DdataSources`` object directly. The ``DataSources`` constructor input is a path. + +.. GENERATED FROM PYTHON SOURCE LINES 106-109 + +.. code-block:: default + + ds = dpf.DataSources(examples.find_static_rst()) + print(examples.find_static_rst()) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + D:\ANSYSDev\Sandbox\pydpf-core\src\ansys\dpf\core\examples\result_files\static.rst + + + + +.. GENERATED FROM PYTHON SOURCE LINES 110-111 + +Instantiate the operators and connect them: + +.. GENERATED FROM PYTHON SOURCE LINES 111-119 + +.. code-block:: default + + + disp_op = dpf.operators.result.displacement() + disp_op.inputs.data_sources.connect(ds) + norm_op = dpf.operators.math.norm_fc() + norm_op.inputs.connect(disp_op.outputs) + mm_op = dpf.operators.min_max.min_max_fc() + mm_op.inputs.connect(norm_op.outputs) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 120-121 + +Get the output and print the result data: + +.. GENERATED FROM PYTHON SOURCE LINES 121-124 + +.. code-block:: default + + + field_max = mm_op.outputs.field_max() + print(field_max.data) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [1.48153706e-08] + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.630 seconds) + + +.. _sphx_glr_download_examples_00-basic_01-basic_operators.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 01-basic_operators.py <01-basic_operators.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 01-basic_operators.ipynb <01-basic_operators.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/01-basic_operators_codeobj.pickle b/doc/source/examples/00-basic/01-basic_operators_codeobj.pickle new file mode 100644 index 0000000000..92781850b7 Binary files /dev/null and b/doc/source/examples/00-basic/01-basic_operators_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/02-basic_field_containers.ipynb b/doc/source/examples/00-basic/02-basic_field_containers.ipynb new file mode 100644 index 0000000000..9c0e84ebdc --- /dev/null +++ b/doc/source/examples/00-basic/02-basic_field_containers.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Field and field containers overview {#ref_basic_field_example}\r\n\r\nIn DPF, the field is the main simulation data container. During a\r\nnumerical simulation, the result data is defined by values associated to\r\nentities (scoping). These entities are a subset of a model (support).\r\n\r\nBecause the field data is always associated to its scoping and support,\r\nthe field is a self-describing piece of data. A field is also defined by\r\nits parameters, such as dimensionality, unit, and location. For example,\r\na field can describe any of the following:\r\n\r\n- Displacement vector\r\n- Norm, stress, or strain tensor\r\n- Stress or strain equivalent\r\n- Minimum or maximum over time of any result.\r\n\r\nA field can be defined on a complete model or on only certain entities\r\nof the model based on its scoping. The data is stored as a vector of\r\ndouble values, and each elementary entity has a number of components.\r\nFor example, a displacement has three components, and a symmetrical\r\nstress matrix has six components.\r\n\r\nIn DPF, a fields container is simply a collection of fields that can be\r\nindexed, just like a Python list. Operators applied to a fields\r\ncontainer have each individual field operated on. Fields containers are\r\noutputs from operators.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# First, import necessary modules\nimport numpy as np\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a model object to establish a connection with an example result\r\nfile and then extract:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.find_static_rst())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the displacement operator directly from the `results` property\r\nand extract the displacement fields container:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp_op = model.results.displacement()\nfields = disp_op.outputs.fields_container()\nprint(fields)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A field can be extracted from a fields container by simply indexing the\r\nrequested field:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field = fields[0]\nprint(field)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extract data from a field\r\n\r\nYou can extract all the data from a given field using the `data`\r\nproperty. This returns a `numpy` array.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(field.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While it might seem preferable to work entirely within `numpy`, DPF runs\r\noutside of Python and potentially even on a remote machine. Therefore,\r\nthe transfer of unnecessary data between the DPF instance and the Python\r\nclient leads to inefficient operations on large models. Instead, you\r\nshould use DPF operators to assemble the necessary data before recalling\r\nthe data from DPF.\r\n\r\nFor example, if you want the maximum displacement for a given result,\r\nuse the min/max operator:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "min_max_op = dpf.operators.min_max.min_max(field)\nprint(min_max_op.outputs.field_max().data)\n\n# Out of conveience, you can simply take the max of the field with:\nprint(field.max().data)\n\n# The above yields a result identical to:\nprint(np.max(field.data, axis=0))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the numpy array does not retain any information about the\r\nfield it describes. Using the DPF `max` operator of the field does\r\nretain this information.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "max_field = field.max()\nprint(max_field)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/02-basic_field_containers.py b/doc/source/examples/00-basic/02-basic_field_containers.py new file mode 100644 index 0000000000..b3d9383d17 --- /dev/null +++ b/doc/source/examples/00-basic/02-basic_field_containers.py @@ -0,0 +1,93 @@ +# noqa: D400 +""" +.. _ref_basic_field_example: + +Field and field containers overview +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In DPF, the field is the main simulation data container. During a numerical +simulation, the result data is defined by values associated to entities +(scoping). These entities are a subset of a model (support). + +Because the field data is always associated to its scoping and support, +the field is a self-describing piece of data. A field is also +defined by its parameters, such as dimensionality, unit, and location. +For example, a field can describe any of the following: + +- Displacement vector +- Norm, stress, or strain tensor +- Stress or strain equivalent +- Minimum or maximum over time of any result. + +A field can be defined on a complete model or on only certain entities +of the model based on its scoping. The data is stored as a vector of +double values, and each elementary entity has a number of components. +For example, a displacement has three components, and a symmetrical +stress matrix has six components. + +In DPF, a fields container is simply a collection of fields that can be +indexed, just like a Python list. Operators applied to a fields +container have each individual field operated on. Fields +containers are outputs from operators. + +""" + +# First, import necessary modules +import numpy as np + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# Create a model object to establish a connection with an +# example result file and then extract: +model = dpf.Model(examples.find_static_rst()) +print(model) + +############################################################################### +# Create the displacement operator directly from the ``results`` +# property and extract the displacement fields container: +disp_op = model.results.displacement() +fields = disp_op.outputs.fields_container() +print(fields) + +############################################################################### +# A field can be extracted from a fields container by simply indexing +# the requested field: +field = fields[0] +print(field) + +############################################################################### +# Extract data from a field +# ~~~~~~~~~~~~~~~~~~~~~~~~~ +# You can extract all the data from a given field using the ``data`` +# property. This returns a ``numpy`` array. + +print(field.data) + +############################################################################### +# While it might seem preferable to work entirely within ``numpy``, +# DPF runs outside of Python and potentially even on a +# remote machine. Therefore, the transfer of unnecessary data between +# the DPF instance and the Python client leads to inefficient +# operations on large models. Instead, you should use DPF operators to +# assemble the necessary data before recalling the data from DPF. +# +# For example, if you want the maximum displacement for a given +# result, use the min/max operator: +# +min_max_op = dpf.operators.min_max.min_max(field) +print(min_max_op.outputs.field_max().data) + +# Out of conveience, you can simply take the max of the field with: +print(field.max().data) + +# The above yields a result identical to: +print(np.max(field.data, axis=0)) + +############################################################################### +# Note that the numpy array does not retain any information about the +# field it describes. Using the DPF ``max`` operator of the field does +# retain this information. +max_field = field.max() +print(max_field) diff --git a/doc/source/examples/00-basic/02-basic_field_containers.py.md5 b/doc/source/examples/00-basic/02-basic_field_containers.py.md5 new file mode 100644 index 0000000000..a9ffa62016 --- /dev/null +++ b/doc/source/examples/00-basic/02-basic_field_containers.py.md5 @@ -0,0 +1 @@ +45cd2518abd948973dcf1b4d13520a06 \ No newline at end of file diff --git a/doc/source/examples/00-basic/02-basic_field_containers.rst b/doc/source/examples/00-basic/02-basic_field_containers.rst new file mode 100644 index 0000000000..6a884770b0 --- /dev/null +++ b/doc/source/examples/00-basic/02-basic_field_containers.rst @@ -0,0 +1,412 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\02-basic_field_containers.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_02-basic_field_containers.py: + + +.. _ref_basic_field_example: + +Field and field containers overview +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In DPF, the field is the main simulation data container. During a numerical +simulation, the result data is defined by values associated to entities +(scoping). These entities are a subset of a model (support). + +Because the field data is always associated to its scoping and support, +the field is a self-describing piece of data. A field is also +defined by its parameters, such as dimensionality, unit, and location. +For example, a field can describe any of the following: + +- Displacement vector +- Norm, stress, or strain tensor +- Stress or strain equivalent +- Minimum or maximum over time of any result. + +A field can be defined on a complete model or on only certain entities +of the model based on its scoping. The data is stored as a vector of +double values, and each elementary entity has a number of components. +For example, a displacement has three components, and a symmetrical +stress matrix has six components. + +In DPF, a fields container is simply a collection of fields that can be +indexed, just like a Python list. Operators applied to a fields +container have each individual field operated on. Fields +containers are outputs from operators. + +.. GENERATED FROM PYTHON SOURCE LINES 34-41 + +.. code-block:: default + + + # First, import necessary modules + import numpy as np + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 42-44 + +Create a model object to establish a connection with an +example result file and then extract: + +.. GENERATED FROM PYTHON SOURCE LINES 44-47 + +.. code-block:: default + + model = dpf.Model(examples.find_static_rst()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 81 nodes + 8 elements + Unit: m + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1 + Cumulative Time (s) LoadStep Substep + 1 1,000000 1 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-50 + +Create the displacement operator directly from the ``results`` +property and extract the displacement fields container: + +.. GENERATED FROM PYTHON SOURCE LINES 50-54 + +.. code-block:: default + + disp_op = model.results.displacement() + fields = disp_op.outputs.fields_container() + print(fields) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF displacement(s)Fields Container + with 1 field(s) + defined on labels: time + + with: + - field 0 {time: 1} with Nodal location, 3 components and 81 entities. + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 55-57 + +A field can be extracted from a fields container by simply indexing +the requested field: + +.. GENERATED FROM PYTHON SOURCE LINES 57-60 + +.. code-block:: default + + field = fields[0] + print(field) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF displacement_1,s Field + Location: Nodal + Unit: m + 81 entities + Data: 3 components and 81 elementary data + + Nodal + IDs data(m) + ------------ ---------- + 1 -3.319046e-22 -6.935660e-09 -3.286174e-22 + + 26 2.230265e-09 -7.142140e-09 -2.920779e-22 + + 14 0.000000e+00 0.000000e+00 0.000000e+00 + + ... + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 61-65 + +Extract data from a field +~~~~~~~~~~~~~~~~~~~~~~~~~ +You can extract all the data from a given field using the ``data`` +property. This returns a ``numpy`` array. + +.. GENERATED FROM PYTHON SOURCE LINES 65-68 + +.. code-block:: default + + + print(field.data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [[-3.31904602e-22 -6.93565975e-09 -3.28617350e-22] + [ 2.23026491e-09 -7.14214033e-09 -2.92077883e-22] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-3.01173895e-22 -7.14214033e-09 -2.23026491e-09] + [ 2.09077164e-09 -7.33058082e-09 -2.09077164e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 1.06212713e-09 -6.89858785e-09 -3.77906905e-22] + [ 1.89019831e-09 -3.34398104e-09 1.43440783e-23] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-2.71912713e-23 -2.92690969e-09 -2.33676924e-23] + [ 1.01364486e-09 -7.10540890e-09 -2.14726184e-09] + [ 1.89155604e-09 -3.73823999e-09 -1.89155604e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 7.64096553e-24 -3.34398104e-09 -1.89019831e-09] + [-3.81104389e-22 -6.89858785e-09 -1.06212713e-09] + [ 2.14726184e-09 -7.10540890e-09 -1.01364486e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-9.53485079e-23 -7.14214033e-09 2.23026491e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 2.09077164e-09 -7.33058082e-09 2.09077164e-09] + [ 1.18477336e-22 -3.34398104e-09 1.89019831e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 1.89155604e-09 -3.73823999e-09 1.89155604e-09] + [ 1.01364486e-09 -7.10540890e-09 2.14726184e-09] + [-2.61320844e-22 -6.89858785e-09 1.06212713e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [ 2.14726184e-09 -7.10540890e-09 1.01364486e-09] + [-1.54190337e-21 -1.42766633e-08 -1.53720678e-21] + [ 2.25103522e-09 -1.43688328e-08 -1.55960665e-21] + [-1.55180700e-21 -1.43688328e-08 -2.25103522e-09] + [ 2.25860708e-09 -1.44669483e-08 -2.25860708e-09] + [-1.02704768e-21 -1.05919802e-08 -1.01743770e-21] + [ 1.16452955e-09 -1.44002311e-08 -1.52834607e-21] + [ 2.29356739e-09 -1.07400000e-08 -1.07537743e-21] + [-1.08050063e-21 -1.07400000e-08 -2.29356739e-09] + [ 1.16046741e-09 -1.44722939e-08 -2.25762828e-09] + [ 2.26430754e-09 -1.08989140e-08 -2.26430754e-09] + [-1.50544246e-21 -1.44002311e-08 -1.16452955e-09] + [ 2.25762828e-09 -1.44722939e-08 -1.16046741e-09] + [ 2.25860708e-09 -1.44669483e-08 2.25860708e-09] + [-1.24684037e-21 -1.43688328e-08 2.25103522e-09] + [ 2.26430754e-09 -1.08989140e-08 2.26430754e-09] + [ 1.16046741e-09 -1.44722939e-08 2.25762828e-09] + [-8.03413897e-22 -1.07400000e-08 2.29356739e-09] + [ 2.25762828e-09 -1.44722939e-08 1.16046741e-09] + [-1.35051199e-21 -1.44002311e-08 1.16452955e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-2.23026491e-09 -7.14214033e-09 -9.66448574e-23] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-2.09077164e-09 -7.33058082e-09 -2.09077164e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-1.89019831e-09 -3.34398104e-09 1.19096032e-22] + [-1.06212713e-09 -6.89858785e-09 -2.59300974e-22] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-1.89155604e-09 -3.73823999e-09 -1.89155604e-09] + [-1.01364486e-09 -7.10540890e-09 -2.14726184e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-2.14726184e-09 -7.10540890e-09 -1.01364486e-09] + [-2.09077164e-09 -7.33058082e-09 2.09077164e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-1.01364486e-09 -7.10540890e-09 2.14726184e-09] + [-1.89155604e-09 -3.73823999e-09 1.89155604e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-2.14726184e-09 -7.10540890e-09 1.01364486e-09] + [ 0.00000000e+00 0.00000000e+00 0.00000000e+00] + [-2.25103522e-09 -1.43688328e-08 -1.20291800e-21] + [-2.25860708e-09 -1.44669483e-08 -2.25860708e-09] + [-2.29356739e-09 -1.07400000e-08 -7.91446544e-22] + [-1.16452955e-09 -1.44002311e-08 -1.32988359e-21] + [-2.26430754e-09 -1.08989140e-08 -2.26430754e-09] + [-1.16046741e-09 -1.44722939e-08 -2.25762828e-09] + [-2.25762828e-09 -1.44722939e-08 -1.16046741e-09] + [-2.25860708e-09 -1.44669483e-08 2.25860708e-09] + [-1.16046741e-09 -1.44722939e-08 2.25762828e-09] + [-2.26430754e-09 -1.08989140e-08 2.26430754e-09] + [-2.25762828e-09 -1.44722939e-08 1.16046741e-09]] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 69-79 + +While it might seem preferable to work entirely within ``numpy``, +DPF runs outside of Python and potentially even on a +remote machine. Therefore, the transfer of unnecessary data between +the DPF instance and the Python client leads to inefficient +operations on large models. Instead, you should use DPF operators to +assemble the necessary data before recalling the data from DPF. + +For example, if you want the maximum displacement for a given +result, use the min/max operator: + + +.. GENERATED FROM PYTHON SOURCE LINES 79-88 + +.. code-block:: default + + min_max_op = dpf.operators.min_max.min_max(field) + print(min_max_op.outputs.field_max().data) + + # Out of conveience, you can simply take the max of the field with: + print(field.max().data) + + # The above yields a result identical to: + print(np.max(field.data, axis=0)) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [2.29356739e-09 0.00000000e+00 2.29356739e-09] + [2.29356739e-09 0.00000000e+00 2.29356739e-09] + [2.29356739e-09 0.00000000e+00 2.29356739e-09] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 89-92 + +Note that the numpy array does not retain any information about the +field it describes. Using the DPF ``max`` operator of the field does +retain this information. + +.. GENERATED FROM PYTHON SOURCE LINES 92-94 + +.. code-block:: default + + max_field = field.max() + print(max_field) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF displacement_1,s Field + Location: Nodal + Unit: m + 3 entities + Data: 1 components and 3 elementary data + + IDs data(m) + ------------ ---------- + 75 2.293567e-09 + + 59 0.000000e+00 + + 40 2.293567e-09 + + + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.050 seconds) + + +.. _sphx_glr_download_examples_00-basic_02-basic_field_containers.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 02-basic_field_containers.py <02-basic_field_containers.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 02-basic_field_containers.ipynb <02-basic_field_containers.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/02-basic_field_containers_codeobj.pickle b/doc/source/examples/00-basic/02-basic_field_containers_codeobj.pickle new file mode 100644 index 0000000000..e2afc1ca2e Binary files /dev/null and b/doc/source/examples/00-basic/02-basic_field_containers_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/03-create_entities.ipynb b/doc/source/examples/00-basic/03-create_entities.ipynb new file mode 100644 index 0000000000..424b136928 --- /dev/null +++ b/doc/source/examples/00-basic/03-create_entities.ipynb @@ -0,0 +1,216 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create your own entities using DPF operators {#ref_create_entities_example}\r\n\r\nYou can create your field, fields container, or meshed region to use DPF\r\noperators with your own data. The ability to use scripting to create any\r\nDPF entity means that you are not dependent on result files and can\r\nconnect the DPF environment with any Python tool.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import necessary modules\nimport numpy as np\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a parallel piped mesh made of linear hexa:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "length = 0.1\nwidth = 0.05\ndepth = 0.1\nnum_nodes_in_length = 10\nnum_nodes_in_width = 5\nnum_nodes_in_depth = 10\nmesh = dpf.MeshedRegion()\n\n\ndef search_sequence_numpy(arr, seq):\n \"\"\"Find a sequence in an array and return its index.\"\"\"\n indexes = np.where(np.isclose(arr, seq[0]))\n for index in np.nditer(indexes[0]):\n if index % 3 == 0:\n if np.allclose(arr[index + 1], seq[1]) and np.allclose(arr[index + 2], seq[2]):\n return index\n return -1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add nodes:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "n_id = 1\nfor i, x in enumerate(\n [float(i) * length / float(num_nodes_in_length) for i in range(0, num_nodes_in_length)]\n):\n for j, y in enumerate(\n [float(i) * width / float(num_nodes_in_width) for i in range(0, num_nodes_in_width)]\n ):\n for k, z in enumerate(\n [float(i) * depth / float(num_nodes_in_depth) for i in range(0, num_nodes_in_depth)]\n ):\n mesh.nodes.add_node(n_id, [x, y, z])\n n_id += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the nodes\\' coordinates field:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "coordinates = mesh.nodes.coordinates_field" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set the mesh unit:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh.unit = \"mm\"\n\ncoordinates_data = coordinates.data\nflat_coordinates_data = coordinates_data.reshape(coordinates_data.size)\ncoordinates_scoping = coordinates.scoping" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add solid elements (linear hexa with eight nodes):\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "e_id = 1\nfor i, x in enumerate(\n [float(i) * length / float(num_nodes_in_length) for i in range(num_nodes_in_length - 1)]\n):\n for j, y in enumerate(\n [float(i) * width / float(num_nodes_in_width) for i in range(num_nodes_in_width - 1)]\n ):\n for k, z in enumerate(\n [float(i) * depth / float(num_nodes_in_depth) for i in range(num_nodes_in_depth - 1)]\n ):\n coord1 = np.array([x, y, z])\n connectivity = []\n for xx in [x, x + length / float(num_nodes_in_length)]:\n for yy in [y, y + width / float(num_nodes_in_width)]:\n for zz in [z, z + depth / float(num_nodes_in_depth)]:\n data_index = search_sequence_numpy(flat_coordinates_data, [xx, yy, zz])\n scoping_index = int(data_index / 3) # 3components\n connectivity.append(scoping_index)\n # rearrange connectivity\n tmp = connectivity[2]\n connectivity[2] = connectivity[3]\n connectivity[3] = tmp\n tmp = connectivity[6]\n connectivity[6] = connectivity[7]\n connectivity[7] = tmp\n mesh.elements.add_solid_element(e_id, connectivity)\n e_id += 1\nmesh.plot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create displacement fields over time with three time sets. For the first\r\ntime set, the displacement on each node is the value of its x, y, and z\r\ncoordinates. For the second time set, the displacement on each node is\r\ntwo times the value of its x, y, and z coordinates. For the third time\r\nset, the displacement on each node is three times the value of its x, y,\r\nand z coordinates.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "num_nodes = mesh.nodes.n_nodes\ntime1_array = coordinates_data\ntime2_array = 2.0 * coordinates_data\ntime3_array = 3.0 * coordinates_data\n\ntime1_field = dpf.fields_factory.create_3d_vector_field(num_nodes)\ntime2_field = dpf.fields_factory.create_3d_vector_field(num_nodes)\ntime3_field = dpf.fields_factory.create_3d_vector_field(num_nodes)\n\ntime1_field.scoping = coordinates.scoping\ntime2_field.scoping = coordinates.scoping\ntime3_field.scoping = coordinates.scoping\n\ntime1_field.data = time1_array\ntime2_field.data = time2_array\ntime3_field.data = time3_array\n\ntime1_field.unit = mesh.unit\ntime2_field.unit = mesh.unit\ntime3_field.unit = mesh.unit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create results over times in a fields container with its time frequency\r\nsupport:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "fc = dpf.fields_container_factory.over_time_freq_fields_container(\n {0.1: time1_field, 0.2: time2_field, 0.3: time3_field}, \"s\"\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check that the time frequency support has been built:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(fc.time_freq_support)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the norm over time of the fields container:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "norm = ops.math.norm_fc(fc)\nfc_norm = norm.outputs.fields_container()\nmesh.plot(fc_norm.get_field_by_time_complex_ids(1))\nmesh.plot(fc_norm.get_field_by_time_complex_ids(2))\nmesh.plot(fc_norm.get_field_by_time_complex_ids(3))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/03-create_entities.py b/doc/source/examples/00-basic/03-create_entities.py new file mode 100644 index 0000000000..eff9d2db11 --- /dev/null +++ b/doc/source/examples/00-basic/03-create_entities.py @@ -0,0 +1,145 @@ +# noqa: D400 +""" +.. _ref_create_entities_example: + +Create your own entities using DPF operators +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can create your field, fields container, or meshed region to use DPF operators +with your own data. The ability to use scripting to create any DPF entity means +that you are not dependent on result files and can connect the DPF environment +with any Python tool. + +""" + +# Import necessary modules +import numpy as np + +from ansys.dpf import core as dpf +from ansys.dpf.core import operators as ops + +############################################################################### +# Create a parallel piped mesh made of linear hexa: +length = 0.1 +width = 0.05 +depth = 0.1 +num_nodes_in_length = 10 +num_nodes_in_width = 5 +num_nodes_in_depth = 10 +mesh = dpf.MeshedRegion() + + +def search_sequence_numpy(arr, seq): + """Find a sequence in an array and return its index.""" + indexes = np.where(np.isclose(arr, seq[0])) + for index in np.nditer(indexes[0]): + if index % 3 == 0: + if np.allclose(arr[index + 1], seq[1]) and np.allclose(arr[index + 2], seq[2]): + return index + return -1 + + +############################################################################### +# Add nodes: +n_id = 1 +for i, x in enumerate( + [float(i) * length / float(num_nodes_in_length) for i in range(0, num_nodes_in_length)] +): + for j, y in enumerate( + [float(i) * width / float(num_nodes_in_width) for i in range(0, num_nodes_in_width)] + ): + for k, z in enumerate( + [float(i) * depth / float(num_nodes_in_depth) for i in range(0, num_nodes_in_depth)] + ): + mesh.nodes.add_node(n_id, [x, y, z]) + n_id += 1 + +############################################################################### +# Get the nodes' coordinates field: +coordinates = mesh.nodes.coordinates_field + +############################################################################### +# Set the mesh unit: +mesh.unit = "mm" + +coordinates_data = coordinates.data +flat_coordinates_data = coordinates_data.reshape(coordinates_data.size) +coordinates_scoping = coordinates.scoping + +############################################################################### +# Add solid elements (linear hexa with eight nodes): +e_id = 1 +for i, x in enumerate( + [float(i) * length / float(num_nodes_in_length) for i in range(num_nodes_in_length - 1)] +): + for j, y in enumerate( + [float(i) * width / float(num_nodes_in_width) for i in range(num_nodes_in_width - 1)] + ): + for k, z in enumerate( + [float(i) * depth / float(num_nodes_in_depth) for i in range(num_nodes_in_depth - 1)] + ): + coord1 = np.array([x, y, z]) + connectivity = [] + for xx in [x, x + length / float(num_nodes_in_length)]: + for yy in [y, y + width / float(num_nodes_in_width)]: + for zz in [z, z + depth / float(num_nodes_in_depth)]: + data_index = search_sequence_numpy(flat_coordinates_data, [xx, yy, zz]) + scoping_index = int(data_index / 3) # 3components + connectivity.append(scoping_index) + # rearrange connectivity + tmp = connectivity[2] + connectivity[2] = connectivity[3] + connectivity[3] = tmp + tmp = connectivity[6] + connectivity[6] = connectivity[7] + connectivity[7] = tmp + mesh.elements.add_solid_element(e_id, connectivity) + e_id += 1 +mesh.plot() + +############################################################################### +# Create displacement fields over time with three time sets. +# For the first time set, the displacement on each node is the +# value of its x, y, and z coordinates. +# For the second time set, the displacement on each node is two +# times the value of its x, y, and z coordinates. +# For the third time set, the displacement on each node is three +# times the value of its x, y, and z coordinates. +num_nodes = mesh.nodes.n_nodes +time1_array = coordinates_data +time2_array = 2.0 * coordinates_data +time3_array = 3.0 * coordinates_data + +time1_field = dpf.fields_factory.create_3d_vector_field(num_nodes) +time2_field = dpf.fields_factory.create_3d_vector_field(num_nodes) +time3_field = dpf.fields_factory.create_3d_vector_field(num_nodes) + +time1_field.scoping = coordinates.scoping +time2_field.scoping = coordinates.scoping +time3_field.scoping = coordinates.scoping + +time1_field.data = time1_array +time2_field.data = time2_array +time3_field.data = time3_array + +time1_field.unit = mesh.unit +time2_field.unit = mesh.unit +time3_field.unit = mesh.unit + +############################################################################### +# Create results over times in a fields container with its time frequency support: +fc = dpf.fields_container_factory.over_time_freq_fields_container( + {0.1: time1_field, 0.2: time2_field, 0.3: time3_field}, "s" +) + +############################################################################### +# Check that the time frequency support has been built: +print(fc.time_freq_support) + +############################################################################### +# Plot the norm over time of the fields container: +norm = ops.math.norm_fc(fc) +fc_norm = norm.outputs.fields_container() +mesh.plot(fc_norm.get_field_by_time_complex_ids(1)) +mesh.plot(fc_norm.get_field_by_time_complex_ids(2)) +mesh.plot(fc_norm.get_field_by_time_complex_ids(3)) diff --git a/doc/source/examples/00-basic/03-create_entities.py.md5 b/doc/source/examples/00-basic/03-create_entities.py.md5 new file mode 100644 index 0000000000..0e49688787 --- /dev/null +++ b/doc/source/examples/00-basic/03-create_entities.py.md5 @@ -0,0 +1 @@ +1d195a252f1497c3c382f592b061d7ce \ No newline at end of file diff --git a/doc/source/examples/00-basic/03-create_entities.rst b/doc/source/examples/00-basic/03-create_entities.rst new file mode 100644 index 0000000000..13900c6b1c --- /dev/null +++ b/doc/source/examples/00-basic/03-create_entities.rst @@ -0,0 +1,358 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\03-create_entities.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_03-create_entities.py: + + +.. _ref_create_entities_example: + +Create your own entities using DPF operators +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can create your field, fields container, or meshed region to use DPF operators +with your own data. The ability to use scripting to create any DPF entity means +that you are not dependent on result files and can connect the DPF environment +with any Python tool. + +.. GENERATED FROM PYTHON SOURCE LINES 14-21 + +.. code-block:: default + + + # Import necessary modules + import numpy as np + + from ansys.dpf import core as dpf + from ansys.dpf.core import operators as ops + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-23 + +Create a parallel piped mesh made of linear hexa: + +.. GENERATED FROM PYTHON SOURCE LINES 23-42 + +.. code-block:: default + + length = 0.1 + width = 0.05 + depth = 0.1 + num_nodes_in_length = 10 + num_nodes_in_width = 5 + num_nodes_in_depth = 10 + mesh = dpf.MeshedRegion() + + + def search_sequence_numpy(arr, seq): + """Find a sequence in an array and return its index.""" + indexes = np.where(np.isclose(arr, seq[0])) + for index in np.nditer(indexes[0]): + if index % 3 == 0: + if np.allclose(arr[index + 1], seq[1]) and np.allclose(arr[index + 2], seq[2]): + return index + return -1 + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 43-44 + +Add nodes: + +.. GENERATED FROM PYTHON SOURCE LINES 44-57 + +.. code-block:: default + + n_id = 1 + for i, x in enumerate( + [float(i) * length / float(num_nodes_in_length) for i in range(0, num_nodes_in_length)] + ): + for j, y in enumerate( + [float(i) * width / float(num_nodes_in_width) for i in range(0, num_nodes_in_width)] + ): + for k, z in enumerate( + [float(i) * depth / float(num_nodes_in_depth) for i in range(0, num_nodes_in_depth)] + ): + mesh.nodes.add_node(n_id, [x, y, z]) + n_id += 1 + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 58-59 + +Get the nodes' coordinates field: + +.. GENERATED FROM PYTHON SOURCE LINES 59-61 + +.. code-block:: default + + coordinates = mesh.nodes.coordinates_field + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 62-63 + +Set the mesh unit: + +.. GENERATED FROM PYTHON SOURCE LINES 63-69 + +.. code-block:: default + + mesh.unit = "mm" + + coordinates_data = coordinates.data + flat_coordinates_data = coordinates_data.reshape(coordinates_data.size) + coordinates_scoping = coordinates.scoping + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 70-71 + +Add solid elements (linear hexa with eight nodes): + +.. GENERATED FROM PYTHON SOURCE LINES 71-100 + +.. code-block:: default + + e_id = 1 + for i, x in enumerate( + [float(i) * length / float(num_nodes_in_length) for i in range(num_nodes_in_length - 1)] + ): + for j, y in enumerate( + [float(i) * width / float(num_nodes_in_width) for i in range(num_nodes_in_width - 1)] + ): + for k, z in enumerate( + [float(i) * depth / float(num_nodes_in_depth) for i in range(num_nodes_in_depth - 1)] + ): + coord1 = np.array([x, y, z]) + connectivity = [] + for xx in [x, x + length / float(num_nodes_in_length)]: + for yy in [y, y + width / float(num_nodes_in_width)]: + for zz in [z, z + depth / float(num_nodes_in_depth)]: + data_index = search_sequence_numpy(flat_coordinates_data, [xx, yy, zz]) + scoping_index = int(data_index / 3) # 3components + connectivity.append(scoping_index) + # rearrange connectivity + tmp = connectivity[2] + connectivity[2] = connectivity[3] + connectivity[3] = tmp + tmp = connectivity[6] + connectivity[6] = connectivity[7] + connectivity[7] = tmp + mesh.elements.add_solid_element(e_id, connectivity) + e_id += 1 + mesh.plot() + + + + +.. image-sg:: /examples/00-basic/images/sphx_glr_03-create_entities_001.png + :alt: 03 create entities + :srcset: /examples/00-basic/images/sphx_glr_03-create_entities_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 101-108 + +Create displacement fields over time with three time sets. +For the first time set, the displacement on each node is the +value of its x, y, and z coordinates. +For the second time set, the displacement on each node is two +times the value of its x, y, and z coordinates. +For the third time set, the displacement on each node is three +times the value of its x, y, and z coordinates. + +.. GENERATED FROM PYTHON SOURCE LINES 108-129 + +.. code-block:: default + + num_nodes = mesh.nodes.n_nodes + time1_array = coordinates_data + time2_array = 2.0 * coordinates_data + time3_array = 3.0 * coordinates_data + + time1_field = dpf.fields_factory.create_3d_vector_field(num_nodes) + time2_field = dpf.fields_factory.create_3d_vector_field(num_nodes) + time3_field = dpf.fields_factory.create_3d_vector_field(num_nodes) + + time1_field.scoping = coordinates.scoping + time2_field.scoping = coordinates.scoping + time3_field.scoping = coordinates.scoping + + time1_field.data = time1_array + time2_field.data = time2_array + time3_field.data = time3_array + + time1_field.unit = mesh.unit + time2_field.unit = mesh.unit + time3_field.unit = mesh.unit + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 130-131 + +Create results over times in a fields container with its time frequency support: + +.. GENERATED FROM PYTHON SOURCE LINES 131-135 + +.. code-block:: default + + fc = dpf.fields_container_factory.over_time_freq_fields_container( + {0.1: time1_field, 0.2: time2_field, 0.3: time3_field}, "s" + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 136-137 + +Check that the time frequency support has been built: + +.. GENERATED FROM PYTHON SOURCE LINES 137-139 + +.. code-block:: default + + print(fc.time_freq_support) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Time/Freq Support: + Number of sets: 3 + Cumulative Time (s) LoadStep Substep + 1 0,100000 1 1 + 2 0,200000 1 2 + 3 0,300000 1 3 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 140-141 + +Plot the norm over time of the fields container: + +.. GENERATED FROM PYTHON SOURCE LINES 141-146 + +.. code-block:: default + + norm = ops.math.norm_fc(fc) + fc_norm = norm.outputs.fields_container() + mesh.plot(fc_norm.get_field_by_time_complex_ids(1)) + mesh.plot(fc_norm.get_field_by_time_complex_ids(2)) + mesh.plot(fc_norm.get_field_by_time_complex_ids(3)) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_03-create_entities_002.png + :alt: 03 create entities + :srcset: /examples/00-basic/images/sphx_glr_03-create_entities_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_03-create_entities_003.png + :alt: 03 create entities + :srcset: /examples/00-basic/images/sphx_glr_03-create_entities_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_03-create_entities_004.png + :alt: 03 create entities + :srcset: /examples/00-basic/images/sphx_glr_03-create_entities_004.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 5.766 seconds) + + +.. _sphx_glr_download_examples_00-basic_03-create_entities.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 03-create_entities.py <03-create_entities.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 03-create_entities.ipynb <03-create_entities.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/03-create_entities_codeobj.pickle b/doc/source/examples/00-basic/03-create_entities_codeobj.pickle new file mode 100644 index 0000000000..022beb1c09 Binary files /dev/null and b/doc/source/examples/00-basic/03-create_entities_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/05-use_local_data.ipynb b/doc/source/examples/00-basic/05-use_local_data.ipynb new file mode 100644 index 0000000000..c3b1d8f759 --- /dev/null +++ b/doc/source/examples/00-basic/05-use_local_data.ipynb @@ -0,0 +1,172 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Bring a field\\'s data locally to improve performance {#ref_use_local_data_example}\r\n\r\nReducing the number of calls to the server is key to improving\r\nperformance. Using the `as_local_field` option brings the data from the\r\nserver to your local machine where you can work on it. When finished,\r\nyou send the updated data back to the server in one transaction.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import necessary modules\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a model object to establish a connection with an example result\r\nfile and then extract:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.download_multi_stage_cyclic_result())\nprint(model)\nmesh = model.metadata.meshed_region" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create the workflow\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute the stress principal invariants:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "stress_op = ops.result.stress(data_sources=model.metadata.data_sources)\nstress_op.inputs.requested_location.connect(dpf.locations.nodal)\nstress_op.inputs.mesh_scoping.connect(mesh.nodes.scoping)\n\nprincipal_op = ops.invariant.principal_invariants_fc(stress_op)\nprincipal_stress_1 = principal_op.outputs.fields_eig_1()[0]\nprincipal_stress_2 = principal_op.outputs.fields_eig_2()[0]\nprincipal_stress_3 = principal_op.outputs.fields_eig_3()[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Manipulate data locally\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This example goes over the fields, keeping the largest invariant value\r\nby node if the averaged value of invariants is large enough. Exploring\r\ndata allows you to customize it to meet your needs.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "node_scoping_ids = principal_stress_1.scoping.ids\nthreshold = 300000.0\n\nfield_to_keep = dpf.fields_factory.create_scalar_field(\n len(node_scoping_ids), location=dpf.locations.nodal\n)\n\nwith field_to_keep.as_local_field() as f:\n with principal_stress_1.as_local_field() as s1:\n with principal_stress_2.as_local_field() as s2:\n with principal_stress_3.as_local_field() as s3:\n for i, id in enumerate(node_scoping_ids):\n d1 = abs(s1.get_entity_data_by_id(id))\n d2 = abs(s2.get_entity_data_by_id(id))\n d3 = abs(s3.get_entity_data_by_id(id))\n if (d1 + d2 + d3) / 3.0 > threshold:\n d = max(d1, d2, d3)\n f.append(d, id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot result field\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the result field on the skin mesh:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh.plot(field_to_keep)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot initial invariants\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the initial invariants:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh.plot(principal_stress_1)\nmesh.plot(principal_stress_2)\nmesh.plot(principal_stress_3)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/05-use_local_data.py b/doc/source/examples/00-basic/05-use_local_data.py new file mode 100644 index 0000000000..1deb68e51d --- /dev/null +++ b/doc/source/examples/00-basic/05-use_local_data.py @@ -0,0 +1,91 @@ +""" +.. _ref_use_local_data_example: + +Bring a field's data locally to improve performance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Reducing the number of calls to the server is key to improving +performance. Using the ``as_local_field`` option brings the data +from the server to your local machine where you can work on it. +When finished, you send the updated data back to the server +in one transaction. + +""" + +# Import necessary modules +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + + +############################################################################### +# Create a model object to establish a connection with an +# example result file and then extract: +model = dpf.Model(examples.download_multi_stage_cyclic_result()) +print(model) +mesh = model.metadata.meshed_region + +############################################################################### +# Create the workflow +# ~~~~~~~~~~~~~~~~~~~~ + +############################################################################### +# Compute the stress principal invariants: +stress_op = ops.result.stress(data_sources=model.metadata.data_sources) +stress_op.inputs.requested_location.connect(dpf.locations.nodal) +stress_op.inputs.mesh_scoping.connect(mesh.nodes.scoping) + +principal_op = ops.invariant.principal_invariants_fc(stress_op) +principal_stress_1 = principal_op.outputs.fields_eig_1()[0] +principal_stress_2 = principal_op.outputs.fields_eig_2()[0] +principal_stress_3 = principal_op.outputs.fields_eig_3()[0] + +############################################################################### +# Manipulate data locally +# ~~~~~~~~~~~~~~~~~~~~~~~ + + +############################################################################### +# This example goes over the fields, keeping the largest invariant value +# by node if the averaged value of invariants is large enough. +# Exploring data allows you to customize it to meet your needs. + +node_scoping_ids = principal_stress_1.scoping.ids +threshold = 300000.0 + +field_to_keep = dpf.fields_factory.create_scalar_field( + len(node_scoping_ids), location=dpf.locations.nodal +) + +with field_to_keep.as_local_field() as f: + with principal_stress_1.as_local_field() as s1: + with principal_stress_2.as_local_field() as s2: + with principal_stress_3.as_local_field() as s3: + for i, id in enumerate(node_scoping_ids): + d1 = abs(s1.get_entity_data_by_id(id)) + d2 = abs(s2.get_entity_data_by_id(id)) + d3 = abs(s3.get_entity_data_by_id(id)) + if (d1 + d2 + d3) / 3.0 > threshold: + d = max(d1, d2, d3) + f.append(d, id) + +############################################################################### +# Plot result field +# ~~~~~~~~~~~~~~~~~ + + +############################################################################### +# Plot the result field on the skin mesh: +mesh.plot(field_to_keep) + +############################################################################### +# Plot initial invariants +# ~~~~~~~~~~~~~~~~~~~~~~~ + + +############################################################################### +# Plot the initial invariants: + +mesh.plot(principal_stress_1) +mesh.plot(principal_stress_2) +mesh.plot(principal_stress_3) diff --git a/doc/source/examples/00-basic/05-use_local_data.py.md5 b/doc/source/examples/00-basic/05-use_local_data.py.md5 new file mode 100644 index 0000000000..f663a461cd --- /dev/null +++ b/doc/source/examples/00-basic/05-use_local_data.py.md5 @@ -0,0 +1 @@ +2d79e58b668eb7c227fdbac817c6b5cd \ No newline at end of file diff --git a/doc/source/examples/00-basic/05-use_local_data.rst b/doc/source/examples/00-basic/05-use_local_data.rst new file mode 100644 index 0000000000..f993cca62b --- /dev/null +++ b/doc/source/examples/00-basic/05-use_local_data.rst @@ -0,0 +1,275 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\05-use_local_data.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_05-use_local_data.py: + + +.. _ref_use_local_data_example: + +Bring a field's data locally to improve performance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Reducing the number of calls to the server is key to improving +performance. Using the ``as_local_field`` option brings the data +from the server to your local machine where you can work on it. +When finished, you send the updated data back to the server +in one transaction. + +.. GENERATED FROM PYTHON SOURCE LINES 14-21 + +.. code-block:: default + + + # Import necessary modules + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-24 + +Create a model object to establish a connection with an +example result file and then extract: + +.. GENERATED FROM PYTHON SOURCE LINES 24-28 + +.. code-block:: default + + model = dpf.Model(examples.download_multi_stage_cyclic_result()) + print(model) + mesh = model.metadata.meshed_region + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Modal analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - stress: ElementalNodal Stress + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 3595 nodes + 1557 elements + Unit: m + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 6 + Cumulative Frequency (Hz) LoadStep Substep Harmonic index + 1 188,385357 1 1 0,000000 + 2 325,126418 1 2 0,000000 + 3 595,320548 1 3 0,000000 + 4 638,189511 1 4 0,000000 + 5 775,669703 1 5 0,000000 + 6 928,278013 1 6 0,000000 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 29-31 + +Create the workflow +~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 33-34 + +Compute the stress principal invariants: + +.. GENERATED FROM PYTHON SOURCE LINES 34-43 + +.. code-block:: default + + stress_op = ops.result.stress(data_sources=model.metadata.data_sources) + stress_op.inputs.requested_location.connect(dpf.locations.nodal) + stress_op.inputs.mesh_scoping.connect(mesh.nodes.scoping) + + principal_op = ops.invariant.principal_invariants_fc(stress_op) + principal_stress_1 = principal_op.outputs.fields_eig_1()[0] + principal_stress_2 = principal_op.outputs.fields_eig_2()[0] + principal_stress_3 = principal_op.outputs.fields_eig_3()[0] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 44-46 + +Manipulate data locally +~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 49-52 + +This example goes over the fields, keeping the largest invariant value +by node if the averaged value of invariants is large enough. +Exploring data allows you to customize it to meet your needs. + +.. GENERATED FROM PYTHON SOURCE LINES 52-72 + +.. code-block:: default + + + node_scoping_ids = principal_stress_1.scoping.ids + threshold = 300000.0 + + field_to_keep = dpf.fields_factory.create_scalar_field( + len(node_scoping_ids), location=dpf.locations.nodal + ) + + with field_to_keep.as_local_field() as f: + with principal_stress_1.as_local_field() as s1: + with principal_stress_2.as_local_field() as s2: + with principal_stress_3.as_local_field() as s3: + for i, id in enumerate(node_scoping_ids): + d1 = abs(s1.get_entity_data_by_id(id)) + d2 = abs(s2.get_entity_data_by_id(id)) + d3 = abs(s3.get_entity_data_by_id(id)) + if (d1 + d2 + d3) / 3.0 > threshold: + d = max(d1, d2, d3) + f.append(d, id) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 73-75 + +Plot result field +~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 78-79 + +Plot the result field on the skin mesh: + +.. GENERATED FROM PYTHON SOURCE LINES 79-81 + +.. code-block:: default + + mesh.plot(field_to_keep) + + + + +.. image-sg:: /examples/00-basic/images/sphx_glr_05-use_local_data_001.png + :alt: 05 use local data + :srcset: /examples/00-basic/images/sphx_glr_05-use_local_data_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 82-84 + +Plot initial invariants +~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 87-88 + +Plot the initial invariants: + +.. GENERATED FROM PYTHON SOURCE LINES 88-92 + +.. code-block:: default + + + mesh.plot(principal_stress_1) + mesh.plot(principal_stress_2) + mesh.plot(principal_stress_3) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_05-use_local_data_002.png + :alt: 05 use local data + :srcset: /examples/00-basic/images/sphx_glr_05-use_local_data_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_05-use_local_data_003.png + :alt: 05 use local data + :srcset: /examples/00-basic/images/sphx_glr_05-use_local_data_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_05-use_local_data_004.png + :alt: 05 use local data + :srcset: /examples/00-basic/images/sphx_glr_05-use_local_data_004.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 2.743 seconds) + + +.. _sphx_glr_download_examples_00-basic_05-use_local_data.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 05-use_local_data.py <05-use_local_data.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 05-use_local_data.ipynb <05-use_local_data.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/05-use_local_data_codeobj.pickle b/doc/source/examples/00-basic/05-use_local_data_codeobj.pickle new file mode 100644 index 0000000000..e8339c48da Binary files /dev/null and b/doc/source/examples/00-basic/05-use_local_data_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/07-use_result_helpers.ipynb b/doc/source/examples/00-basic/07-use_result_helpers.ipynb new file mode 100644 index 0000000000..33de1d8cc4 --- /dev/null +++ b/doc/source/examples/00-basic/07-use_result_helpers.ipynb @@ -0,0 +1,151 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use result helpers to load custom data {#ref_use_result_helpers}\r\n\r\nThe `Result `{.interpreted-text\r\nrole=\"class\"} class, which is an instance created by the\r\n`Model `{.interpreted-text role=\"class\"},\r\ngives access to helpers for requesting results on specific mesh and time\r\nscopings. With these helpers, working on a custom spatial and temporal\r\nsubset of the model is straightforward.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import necessary modules\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a model object to establish a connection with an example result\r\nfile:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.download_multi_stage_cyclic_result())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Visualize specific mode shapes\r\n\r\nChoose the modes to visualize:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "modes = [1, 5, 6]\n\ndisp = model.results.displacement.on_time_scoping(modes)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Choose a spatial subset\r\n\r\nWork on only a named selection (or component).\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the available named selection:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(model.metadata.available_named_selections)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify to the result that you want to work on a specific named\r\nselection:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp.on_named_selection(\"_STAG1_BASE_NOD\")\nop = disp()\nop.inputs.read_cyclic(2) # expand cyclic\nresults = op.outputs.fields_container()\n\n# plot\nfor mode in modes:\n results[0].meshed_region.plot(results.get_fields_by_time_complex_ids(mode, 0)[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify to the result that you want to work on specific nodes:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement.on_time_scoping(modes)\ndisp.on_mesh_scoping(list(range(1, 200)))\nop = disp()\nop.inputs.read_cyclic(2) # expand cyclic\nresults = op.outputs.fields_container()\n\n# plot\nfor mode in modes:\n results[0].meshed_region.plot(results.get_fields_by_time_complex_ids(mode, 0)[0])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/07-use_result_helpers.py b/doc/source/examples/00-basic/07-use_result_helpers.py new file mode 100644 index 0000000000..2c9ae8e138 --- /dev/null +++ b/doc/source/examples/00-basic/07-use_result_helpers.py @@ -0,0 +1,63 @@ +# noqa: D400 +""" +.. _ref_use_result_helpers: + +Use result helpers to load custom data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :class:`Result ` class, which is an instance +created by the :class:`Model `, gives +access to helpers for requesting results on specific mesh and time scopings. +With these helpers, working on a custom spatial and temporal subset of the +model is straightforward. + +""" + +# Import necessary modules +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# Create a model object to establish a connection with an example result file: +model = dpf.Model(examples.download_multi_stage_cyclic_result()) +print(model) + +############################################################################### +# Visualize specific mode shapes +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Choose the modes to visualize: +modes = [1, 5, 6] + +disp = model.results.displacement.on_time_scoping(modes) + +############################################################################### +# Choose a spatial subset +# ~~~~~~~~~~~~~~~~~~~~~~~ +# Work on only a named selection (or component). + +############################################################################### +# Print the available named selection: +print(model.metadata.available_named_selections) + +############################################################################### +# Specify to the result that you want to work on a specific named selection: +disp.on_named_selection("_STAG1_BASE_NOD") +op = disp() +op.inputs.read_cyclic(2) # expand cyclic +results = op.outputs.fields_container() + +# plot +for mode in modes: + results[0].meshed_region.plot(results.get_fields_by_time_complex_ids(mode, 0)[0]) + +############################################################################### +# Specify to the result that you want to work on specific nodes: +disp = model.results.displacement.on_time_scoping(modes) +disp.on_mesh_scoping(list(range(1, 200))) +op = disp() +op.inputs.read_cyclic(2) # expand cyclic +results = op.outputs.fields_container() + +# plot +for mode in modes: + results[0].meshed_region.plot(results.get_fields_by_time_complex_ids(mode, 0)[0]) diff --git a/doc/source/examples/00-basic/07-use_result_helpers.py.md5 b/doc/source/examples/00-basic/07-use_result_helpers.py.md5 new file mode 100644 index 0000000000..e41259c641 --- /dev/null +++ b/doc/source/examples/00-basic/07-use_result_helpers.py.md5 @@ -0,0 +1 @@ +239355011b96a44daca1a5ebb8707b1e \ No newline at end of file diff --git a/doc/source/examples/00-basic/07-use_result_helpers.rst b/doc/source/examples/00-basic/07-use_result_helpers.rst new file mode 100644 index 0000000000..c3b0abe603 --- /dev/null +++ b/doc/source/examples/00-basic/07-use_result_helpers.rst @@ -0,0 +1,271 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\07-use_result_helpers.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_07-use_result_helpers.py: + + +.. _ref_use_result_helpers: + +Use result helpers to load custom data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :class:`Result ` class, which is an instance +created by the :class:`Model `, gives +access to helpers for requesting results on specific mesh and time scopings. +With these helpers, working on a custom spatial and temporal subset of the +model is straightforward. + +.. GENERATED FROM PYTHON SOURCE LINES 15-20 + +.. code-block:: default + + + # Import necessary modules + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 21-22 + +Create a model object to establish a connection with an example result file: + +.. GENERATED FROM PYTHON SOURCE LINES 22-25 + +.. code-block:: default + + model = dpf.Model(examples.download_multi_stage_cyclic_result()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Modal analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - stress: ElementalNodal Stress + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 3595 nodes + 1557 elements + Unit: m + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 6 + Cumulative Frequency (Hz) LoadStep Substep Harmonic index + 1 188,385357 1 1 0,000000 + 2 325,126418 1 2 0,000000 + 3 595,320548 1 3 0,000000 + 4 638,189511 1 4 0,000000 + 5 775,669703 1 5 0,000000 + 6 928,278013 1 6 0,000000 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 26-29 + +Visualize specific mode shapes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Choose the modes to visualize: + +.. GENERATED FROM PYTHON SOURCE LINES 29-33 + +.. code-block:: default + + modes = [1, 5, 6] + + disp = model.results.displacement.on_time_scoping(modes) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 34-37 + +Choose a spatial subset +~~~~~~~~~~~~~~~~~~~~~~~ +Work on only a named selection (or component). + +.. GENERATED FROM PYTHON SOURCE LINES 39-40 + +Print the available named selection: + +.. GENERATED FROM PYTHON SOURCE LINES 40-42 + +.. code-block:: default + + print(model.metadata.available_named_selections) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ['BC', 'ELM', 'STAG1', 'STAG1HIGH', 'STAG1LOW', 'STAG2', 'STAG2HIGH', 'STAG2LOW', '_BC_NOD', '_FIXEDSU', '_INTF_ELM', '_INTF_NOD', '_NOD', '_STAG1_BASE_ELM', '_STAG1_BASE_NOD', '_STAG1_CYCHIGH_NOD', '_STAG1_CYCLOW_NOD', '_STAG2_BASE_ELM', '_STAG2_BASE_NOD', '_STAG2_CYCHIGH_NOD', '_STAG2_CYCLOW_NOD'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 43-44 + +Specify to the result that you want to work on a specific named selection: + +.. GENERATED FROM PYTHON SOURCE LINES 44-53 + +.. code-block:: default + + disp.on_named_selection("_STAG1_BASE_NOD") + op = disp() + op.inputs.read_cyclic(2) # expand cyclic + results = op.outputs.fields_container() + + # plot + for mode in modes: + results[0].meshed_region.plot(results.get_fields_by_time_complex_ids(mode, 0)[0]) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_07-use_result_helpers_001.png + :alt: 07 use result helpers + :srcset: /examples/00-basic/images/sphx_glr_07-use_result_helpers_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_07-use_result_helpers_002.png + :alt: 07 use result helpers + :srcset: /examples/00-basic/images/sphx_glr_07-use_result_helpers_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_07-use_result_helpers_003.png + :alt: 07 use result helpers + :srcset: /examples/00-basic/images/sphx_glr_07-use_result_helpers_003.png + :class: sphx-glr-multi-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 54-55 + +Specify to the result that you want to work on specific nodes: + +.. GENERATED FROM PYTHON SOURCE LINES 55-64 + +.. code-block:: default + + disp = model.results.displacement.on_time_scoping(modes) + disp.on_mesh_scoping(list(range(1, 200))) + op = disp() + op.inputs.read_cyclic(2) # expand cyclic + results = op.outputs.fields_container() + + # plot + for mode in modes: + results[0].meshed_region.plot(results.get_fields_by_time_complex_ids(mode, 0)[0]) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_07-use_result_helpers_004.png + :alt: 07 use result helpers + :srcset: /examples/00-basic/images/sphx_glr_07-use_result_helpers_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_07-use_result_helpers_005.png + :alt: 07 use result helpers + :srcset: /examples/00-basic/images/sphx_glr_07-use_result_helpers_005.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_07-use_result_helpers_006.png + :alt: 07 use result helpers + :srcset: /examples/00-basic/images/sphx_glr_07-use_result_helpers_006.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 3.915 seconds) + + +.. _sphx_glr_download_examples_00-basic_07-use_result_helpers.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 07-use_result_helpers.py <07-use_result_helpers.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 07-use_result_helpers.ipynb <07-use_result_helpers.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/07-use_result_helpers_codeobj.pickle b/doc/source/examples/00-basic/07-use_result_helpers_codeobj.pickle new file mode 100644 index 0000000000..0ed774073d Binary files /dev/null and b/doc/source/examples/00-basic/07-use_result_helpers_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/08-results_over_time_subset.ipynb b/doc/source/examples/00-basic/08-results_over_time_subset.ipynb new file mode 100644 index 0000000000..ed96c65564 --- /dev/null +++ b/doc/source/examples/00-basic/08-results_over_time_subset.ipynb @@ -0,0 +1,198 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Scope results over custom time domains {#ref_results_over_time}\r\n\r\nThe `Result `{.interpreted-text\r\nrole=\"class\"} class, which are instances created by the\r\n`Model `{.interpreted-text role=\"class\"},\r\ngive access to helpers for requesting results on specific mesh and time\r\nscopings. With these helpers, working on a temporal subset of the model\r\nis straightforward. In this example, different ways to choose the\r\ntemporal subset to evaluate a result are exposed. This example can be\r\nextended to frequency subsets.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import necessary modules\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a model object to establish a connection with an example result\r\nfile:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.download_transient_result())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Request specific time sets\r\n\r\nIf specific time sets are of interest, looking into the\r\n`TimeFreqSupport` and connect a given `time_scoping` accordingly to the\r\ncumulative indexes can be useful.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(model.metadata.time_freq_support)\n\ntime_sets = [1, 3, 10]\ndisp = model.results.displacement.on_time_scoping(time_sets).eval()\n\nprint(disp)\n\n# Or using a scoping\ntime_sets_scoping = dpf.time_freq_scoping_factory.scoping_by_sets([1, 3, 10])\ndisp = model.results.displacement.on_time_scoping(time_sets_scoping).eval()\n\nprint(disp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp_op = model.results.displacement()\ndisp_op.inputs.time_scoping(time_sets)\ndisp = disp_op.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement(time_scoping=time_sets_scoping).eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Request specific time steps\r\n\r\nIf specific time steps or load steps are of interest, looking into the\r\n`TimeFreqSupport` and connect a given `time_scoping` located on steps\r\ncan be done.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "time_steps_scoping = dpf.time_freq_scoping_factory.scoping_by_load_step(1)\ndisp = model.results.displacement.on_time_scoping(time_steps_scoping).eval()\n\nprint(disp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp_op = model.results.displacement()\ndisp_op.inputs.time_scoping(time_steps_scoping)\ndisp = disp_op.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using helpers\r\n\r\nEvaluate at all times.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement.on_all_time_freqs().eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Evaluate at first and last times\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement.on_first_time_freq().eval()\nprint(disp)\ndisp = model.results.displacement.on_last_time_freq().eval()\nprint(disp)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/08-results_over_time_subset.py b/doc/source/examples/00-basic/08-results_over_time_subset.py new file mode 100644 index 0000000000..13008e9a74 --- /dev/null +++ b/doc/source/examples/00-basic/08-results_over_time_subset.py @@ -0,0 +1,83 @@ +# noqa: D400 +""" +.. _ref_results_over_time: + +Scope results over custom time domains +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :class:`Result ` class, which are instances +created by the :class:`Model `, give +access to helpers for requesting results on specific mesh and time scopings. +With these helpers, working on a temporal subset of the +model is straightforward. In this example, different ways to choose the temporal subset to +evaluate a result are exposed. This example can be extended to frequency subsets. + +""" + +# Import necessary modules +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# Create a model object to establish a connection with an example result file: +model = dpf.Model(examples.download_transient_result()) +print(model) + +############################################################################### +# Request specific time sets +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# If specific time sets are of interest, looking into the ``TimeFreqSupport`` +# and connect a given ``time_scoping`` accordingly to the cumulative indexes can be useful. + +print(model.metadata.time_freq_support) + +time_sets = [1, 3, 10] +disp = model.results.displacement.on_time_scoping(time_sets).eval() + +print(disp) + +# Or using a scoping +time_sets_scoping = dpf.time_freq_scoping_factory.scoping_by_sets([1, 3, 10]) +disp = model.results.displacement.on_time_scoping(time_sets_scoping).eval() + +print(disp) + +############################################################################### +# Equivalent to: +disp_op = model.results.displacement() +disp_op.inputs.time_scoping(time_sets) +disp = disp_op.outputs.fields_container() + +############################################################################### +# Equivalent to: +disp = model.results.displacement(time_scoping=time_sets_scoping).eval() + +############################################################################### +# Request specific time steps +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# If specific time steps or load steps are of interest, looking into the +# ``TimeFreqSupport`` and connect a given ``time_scoping`` located on steps can be done. +time_steps_scoping = dpf.time_freq_scoping_factory.scoping_by_load_step(1) +disp = model.results.displacement.on_time_scoping(time_steps_scoping).eval() + +print(disp) + +############################################################################### +# Equivalent to: +disp_op = model.results.displacement() +disp_op.inputs.time_scoping(time_steps_scoping) +disp = disp_op.outputs.fields_container() + +############################################################################### +# Using helpers +# ~~~~~~~~~~~~~ +# Evaluate at all times. + +disp = model.results.displacement.on_all_time_freqs().eval() + +############################################################################### +# Evaluate at first and last times +disp = model.results.displacement.on_first_time_freq().eval() +print(disp) +disp = model.results.displacement.on_last_time_freq().eval() +print(disp) diff --git a/doc/source/examples/00-basic/08-results_over_time_subset.py.md5 b/doc/source/examples/00-basic/08-results_over_time_subset.py.md5 new file mode 100644 index 0000000000..81b1f8b87c --- /dev/null +++ b/doc/source/examples/00-basic/08-results_over_time_subset.py.md5 @@ -0,0 +1 @@ +602e29e6e61b0a7414c4ac2f0e037681 \ No newline at end of file diff --git a/doc/source/examples/00-basic/08-results_over_time_subset.rst b/doc/source/examples/00-basic/08-results_over_time_subset.rst new file mode 100644 index 0000000000..ab422a72e5 --- /dev/null +++ b/doc/source/examples/00-basic/08-results_over_time_subset.rst @@ -0,0 +1,443 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\08-results_over_time_subset.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_08-results_over_time_subset.py: + + +.. _ref_results_over_time: + +Scope results over custom time domains +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :class:`Result ` class, which are instances +created by the :class:`Model `, give +access to helpers for requesting results on specific mesh and time scopings. +With these helpers, working on a temporal subset of the +model is straightforward. In this example, different ways to choose the temporal subset to +evaluate a result are exposed. This example can be extended to frequency subsets. + +.. GENERATED FROM PYTHON SOURCE LINES 16-21 + +.. code-block:: default + + + # Import necessary modules + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-23 + +Create a model object to establish a connection with an example result file: + +.. GENERATED FROM PYTHON SOURCE LINES 23-26 + +.. code-block:: default + + model = dpf.Model(examples.download_transient_result()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - element_nodal_forces: ElementalNodal Element nodal Forces + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - thermal_strain: ElementalNodal Thermal Strains + - thermal_strains_eqv: ElementalNodal Thermal Strains eqv + - swelling_strains: ElementalNodal Swelling Strains + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 3820 nodes + 789 elements + Unit: m + With solid (3D) elements, shell (2D) elements, shell (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 35 + Cumulative Time (s) LoadStep Substep + 1 0,000000 1 1 + 2 0,019975 1 2 + 3 0,039975 1 3 + 4 0,059975 1 4 + 5 0,079975 1 5 + 6 0,099975 1 6 + 7 0,119975 1 7 + 8 0,139975 1 8 + 9 0,159975 1 9 + 10 0,179975 1 10 + 11 0,199975 1 11 + 12 0,218975 1 12 + 13 0,238975 1 13 + 14 0,258975 1 14 + 15 0,278975 1 15 + 16 0,298975 1 16 + 17 0,318975 1 17 + 18 0,338975 1 18 + 19 0,358975 1 19 + 20 0,378975 1 20 + 21 0,398975 1 21 + 22 0,417975 1 22 + 23 0,437975 1 23 + 24 0,457975 1 24 + 25 0,477975 1 25 + 26 0,497975 1 26 + 27 0,517975 1 27 + 28 0,537550 1 28 + 29 0,557253 1 29 + 30 0,577118 1 30 + 31 0,597021 1 31 + 32 0,616946 1 32 + 33 0,636833 1 33 + 34 0,656735 1 34 + 35 0,676628 1 35 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 27-31 + +Request specific time sets +~~~~~~~~~~~~~~~~~~~~~~~~~~ +If specific time sets are of interest, looking into the ``TimeFreqSupport`` +and connect a given ``time_scoping`` accordingly to the cumulative indexes can be useful. + +.. GENERATED FROM PYTHON SOURCE LINES 31-45 + +.. code-block:: default + + + print(model.metadata.time_freq_support) + + time_sets = [1, 3, 10] + disp = model.results.displacement.on_time_scoping(time_sets).eval() + + print(disp) + + # Or using a scoping + time_sets_scoping = dpf.time_freq_scoping_factory.scoping_by_sets([1, 3, 10]) + disp = model.results.displacement.on_time_scoping(time_sets_scoping).eval() + + print(disp) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Time/Freq Support: + Number of sets: 35 + Cumulative Time (s) LoadStep Substep + 1 0,000000 1 1 + 2 0,019975 1 2 + 3 0,039975 1 3 + 4 0,059975 1 4 + 5 0,079975 1 5 + 6 0,099975 1 6 + 7 0,119975 1 7 + 8 0,139975 1 8 + 9 0,159975 1 9 + 10 0,179975 1 10 + 11 0,199975 1 11 + 12 0,218975 1 12 + 13 0,238975 1 13 + 14 0,258975 1 14 + 15 0,278975 1 15 + 16 0,298975 1 16 + 17 0,318975 1 17 + 18 0,338975 1 18 + 19 0,358975 1 19 + 20 0,378975 1 20 + 21 0,398975 1 21 + 22 0,417975 1 22 + 23 0,437975 1 23 + 24 0,457975 1 24 + 25 0,477975 1 25 + 26 0,497975 1 26 + 27 0,517975 1 27 + 28 0,537550 1 28 + 29 0,557253 1 29 + 30 0,577118 1 30 + 31 0,597021 1 31 + 32 0,616946 1 32 + 33 0,636833 1 33 + 34 0,656735 1 34 + 35 0,676628 1 35 + + DPF displacement(s)Fields Container + with 3 field(s) + defined on labels: time + + with: + - field 0 {time: 1} with Nodal location, 3 components and 3820 entities. + - field 1 {time: 3} with Nodal location, 3 components and 3820 entities. + - field 2 {time: 10} with Nodal location, 3 components and 3820 entities. + + DPF displacement(s)Fields Container + with 3 field(s) + defined on labels: time + + with: + - field 0 {time: 1} with Nodal location, 3 components and 3820 entities. + - field 1 {time: 3} with Nodal location, 3 components and 3820 entities. + - field 2 {time: 10} with Nodal location, 3 components and 3820 entities. + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 46-47 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 47-51 + +.. code-block:: default + + disp_op = model.results.displacement() + disp_op.inputs.time_scoping(time_sets) + disp = disp_op.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 52-53 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 53-55 + +.. code-block:: default + + disp = model.results.displacement(time_scoping=time_sets_scoping).eval() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 56-60 + +Request specific time steps +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If specific time steps or load steps are of interest, looking into the +``TimeFreqSupport`` and connect a given ``time_scoping`` located on steps can be done. + +.. GENERATED FROM PYTHON SOURCE LINES 60-65 + +.. code-block:: default + + time_steps_scoping = dpf.time_freq_scoping_factory.scoping_by_load_step(1) + disp = model.results.displacement.on_time_scoping(time_steps_scoping).eval() + + print(disp) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF displacement(s)Fields Container + with 35 field(s) + defined on labels: time + + with: + - field 0 {time: 1} with Nodal location, 3 components and 3820 entities. + - field 1 {time: 2} with Nodal location, 3 components and 3820 entities. + - field 2 {time: 3} with Nodal location, 3 components and 3820 entities. + - field 3 {time: 4} with Nodal location, 3 components and 3820 entities. + - field 4 {time: 5} with Nodal location, 3 components and 3820 entities. + - field 5 {time: 6} with Nodal location, 3 components and 3820 entities. + - field 6 {time: 7} with Nodal location, 3 components and 3820 entities. + - field 7 {time: 8} with Nodal location, 3 components and 3820 entities. + - field 8 {time: 9} with Nodal location, 3 components and 3820 entities. + - field 9 {time: 10} with Nodal location, 3 components and 3820 entities. + - field 10 {time: 11} with Nodal location, 3 components and 3820 entities. + - field 11 {time: 12} with Nodal location, 3 components and 3820 entities. + - field 12 {time: 13} with Nodal location, 3 components and 3820 entities. + - field 13 {time: 14} with Nodal location, 3 components and 3820 entities. + - field 14 {time: 15} with Nodal location, 3 components and 3820 entities. + - field 15 {time: 16} with Nodal location, 3 components and 3820 entities. + - field 16 {time: 17} with Nodal location, 3 components and 3820 entities. + - field 17 {time: 18} with Nodal location, 3 components and 3820 entities. + - field 18 {time: 19} with Nodal location, 3 components and 3820 entities. + - field 19 {time: 20} with Nodal location, 3 components and 3820 entities. + - field 20 {time: 21} with Nodal location, 3 components and 3820 entities. + - field 21 {time: 22} with Nodal location, 3 components and 3820 entities. + - field 22 {time: 23} with Nodal location, 3 components and 3820 entities. + - field 23 {time: 24} with Nodal location, 3 components and 3820 entities. + - field 24 {time: 25} with Nodal location, 3 components and 3820 entities. + - field 25 {time: 26} with Nodal location, 3 components and 3820 entities. + - field 26 {time: 27} with Nodal location, 3 components and 3820 entities. + - field 27 {time: 28} with Nodal location, 3 components and 3820 entities. + - field 28 {time: 29} with Nodal location, 3 components and 3820 entities. + - field 29 {time: 30} with Nodal location, 3 components and 3820 entities. + - field 30 {time: 31} with Nodal location, 3 components and 3820 entities. + - field 31 {time: 32} with Nodal location, 3 components and 3820 entities. + - field 32 {time: 33} with Nodal location, 3 components and 3820 entities. + - field 33 {time: 34} with Nodal location, 3 components and 3820 entities. + - field 34 {time: 35} with Nodal location, 3 components and 3820 entities. + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 66-67 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 67-71 + +.. code-block:: default + + disp_op = model.results.displacement() + disp_op.inputs.time_scoping(time_steps_scoping) + disp = disp_op.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 72-75 + +Using helpers +~~~~~~~~~~~~~ +Evaluate at all times. + +.. GENERATED FROM PYTHON SOURCE LINES 75-78 + +.. code-block:: default + + + disp = model.results.displacement.on_all_time_freqs().eval() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 79-80 + +Evaluate at first and last times + +.. GENERATED FROM PYTHON SOURCE LINES 80-84 + +.. code-block:: default + + disp = model.results.displacement.on_first_time_freq().eval() + print(disp) + disp = model.results.displacement.on_last_time_freq().eval() + print(disp) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF displacement(s)Fields Container + with 1 field(s) + defined on labels: time + + with: + - field 0 {time: 1} with Nodal location, 3 components and 3820 entities. + + DPF displacement(s)Fields Container + with 1 field(s) + defined on labels: time + + with: + - field 0 {time: 35} with Nodal location, 3 components and 3820 entities. + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.163 seconds) + + +.. _sphx_glr_download_examples_00-basic_08-results_over_time_subset.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 08-results_over_time_subset.py <08-results_over_time_subset.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 08-results_over_time_subset.ipynb <08-results_over_time_subset.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/08-results_over_time_subset_codeobj.pickle b/doc/source/examples/00-basic/08-results_over_time_subset_codeobj.pickle new file mode 100644 index 0000000000..6c50506c79 Binary files /dev/null and b/doc/source/examples/00-basic/08-results_over_time_subset_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/09-results_over_space_subset.ipynb b/doc/source/examples/00-basic/09-results_over_space_subset.ipynb new file mode 100644 index 0000000000..f1a7f35fcd --- /dev/null +++ b/doc/source/examples/00-basic/09-results_over_space_subset.ipynb @@ -0,0 +1,371 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Scope results over custom space domains {#ref_results_over_space}\r\n\r\nThe `Result `{.interpreted-text\r\nrole=\"class\"} class, which are instances created by the\r\n`Model `{.interpreted-text role=\"class\"},\r\ngive access to helpers for requesting results on specific mesh and time\r\nscopings. With these helpers, working on a spatial subset of the model\r\nis straightforward. In this example, different ways to choose the\r\nspatial subset to evaluate a result are exposed\r\n\r\nImport necessary modules:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a model object to establish a connection with an example result\r\nfile:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.download_all_kinds_of_complexity())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Choose specific nodes\r\n\r\nIf some nodes or elements are specifically of interest, a nodal\r\n`mesh_scoping` can be connected.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "nodes_scoping = dpf.mesh_scoping_factory.nodal_scoping(range(400, 500))\nprint(nodes_scoping)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "nodes_scoping = dpf.Scoping(ids=range(400, 500), location=dpf.locations.nodal)\nprint(nodes_scoping)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement.on_mesh_scoping(nodes_scoping).eval()\n\nmodel.metadata.meshed_region.plot(disp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp_op = model.results.displacement()\ndisp_op.inputs.mesh_scoping(nodes_scoping)\ndisp = disp_op.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement(mesh_scoping=nodes_scoping).eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Choose specific elements\r\n\r\nIf some elements are specifically of interest, an elemental\r\n`mesh_scoping` can be connected.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "elements_scoping = dpf.mesh_scoping_factory.elemental_scoping(range(500, 5000))\nprint(elements_scoping)\n\n# or\nelements_scoping = dpf.Scoping(ids=range(500, 5000), location=dpf.locations.elemental)\nprint(elements_scoping)\n\nvolume = model.results.elemental_volume.on_mesh_scoping(elements_scoping).eval()\n\nmodel.metadata.meshed_region.plot(volume)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "volume_op = model.results.elemental_volume()\nvolume_op.inputs.mesh_scoping(elements_scoping)\nvolume = volume_op.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "volume = model.results.elemental_volume(mesh_scoping=elements_scoping).eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Choose specific named selections\r\n\r\nNamed selections (also known as components) can be selected to create a\r\nspatial domain for a result. A `mesh_scoping` can be created with a\r\nnamed selection. To know the available named selections in the result\r\nfile, use:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(model.metadata.available_named_selections)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the `mesh_scoping` of a named selection:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh_scoping = model.metadata.named_selection(\"_CM82\")\nprint(mesh_scoping)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Connect this `mesh_scoping` to the result provider\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "volume = model.results.elemental_volume(mesh_scoping=mesh_scoping).eval()\nmodel.metadata.meshed_region.plot(volume)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "volume = model.results.elemental_volume.on_named_selection(\"_CM82\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "ns_provider = dpf.operators.scoping.on_named_selection(\n requested_location=dpf.locations.elemental,\n named_selection_name=\"_CM82\",\n data_sources=model,\n)\nvolume = model.results.elemental_volume(mesh_scoping=ns_provider).eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Split results depending on spatial properties\r\n\r\nFor many applications, it can be useful to request results on different\r\nsubsets of the model. The `ScopingsContainer` entity contains different\r\n`Scopings` and can be connected to any result provider to get results\r\nsplit with the same partition as the input `ScopingsContainer`. For\r\nexample, some application require to get results split by body, by\r\nmaterial, by element types. It might also be necessary to get results by\r\nelement shape types, such as shell, solid, or beam, to average data\r\nproperly. Customers might also require split by entirely custom spatial\r\ndomains.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Split results by element shapes\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "stress = model.results.stress.split_by_shape.on_location(dpf.locations.nodal).eval()\nprint(stress)\n\nshell_stresses = stress.shell_fields()\nmodel.metadata.meshed_region.plot(shell_stresses[0])\n\nsolid_stresses = stress.solid_fields()\nmodel.metadata.meshed_region.plot(solid_stresses[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Split results by bodies\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "stress = model.results.stress.split_by_body.on_location(dpf.locations.nodal).eval()\nprint(stress)\n\nfor body_id in stress.get_mat_scoping().ids:\n fields = stress.get_fields_by_mat_id(body_id)\n for field in fields:\n if field.elementary_data_count > 0:\n model.metadata.meshed_region.plot(field)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a custom spatial split\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "scopings_container = dpf.ScopingsContainer()\nscopings_container.add_label(\"custom_split\")\nscopings_container.add_scoping(\n {\"custom_split\": 1},\n dpf.Scoping(ids=range(100, 500), location=dpf.locations.elemental),\n)\nscopings_container.add_scoping(\n {\"custom_split\": 2},\n dpf.Scoping(ids=range(500, 5000), location=dpf.locations.elemental),\n)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "elemental_stress = model.results.stress.on_location(dpf.locations.elemental)(\n mesh_scoping=scopings_container\n).eval()\nprint(elemental_stress)\n\nfor field in elemental_stress:\n model.metadata.meshed_region.plot(field)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/09-results_over_space_subset.py b/doc/source/examples/00-basic/09-results_over_space_subset.py new file mode 100644 index 0000000000..21f57e7843 --- /dev/null +++ b/doc/source/examples/00-basic/09-results_over_space_subset.py @@ -0,0 +1,172 @@ +# noqa: D400 +""" +.. _ref_results_over_space: + +Scope results over custom space domains +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :class:`Result ` class, which are instances +created by the :class:`Model `, give +access to helpers for requesting results on specific mesh and time scopings. +With these helpers, working on a spatial subset of the model is straightforward. +In this example, different ways to choose the spatial subset to +evaluate a result are exposed + +Import necessary modules: +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# Create a model object to establish a connection with an example result file: +model = dpf.Model(examples.download_all_kinds_of_complexity()) +print(model) + +############################################################################### +# Choose specific nodes +# ~~~~~~~~~~~~~~~~~~~~~ +# If some nodes or elements are specifically of interest, a nodal ``mesh_scoping`` +# can be connected. + +nodes_scoping = dpf.mesh_scoping_factory.nodal_scoping(range(400, 500)) +print(nodes_scoping) + +############################################################################### +# or +nodes_scoping = dpf.Scoping(ids=range(400, 500), location=dpf.locations.nodal) +print(nodes_scoping) + +############################################################################### + +disp = model.results.displacement.on_mesh_scoping(nodes_scoping).eval() + +model.metadata.meshed_region.plot(disp) + +############################################################################### +# Equivalent to: +disp_op = model.results.displacement() +disp_op.inputs.mesh_scoping(nodes_scoping) +disp = disp_op.outputs.fields_container() + +############################################################################### +# Equivalent to: +disp = model.results.displacement(mesh_scoping=nodes_scoping).eval() + +############################################################################### +# Choose specific elements +# ~~~~~~~~~~~~~~~~~~~~~~~~ +# If some elements are specifically of interest, an elemental ``mesh_scoping`` +# can be connected. + +elements_scoping = dpf.mesh_scoping_factory.elemental_scoping(range(500, 5000)) +print(elements_scoping) + +# or +elements_scoping = dpf.Scoping(ids=range(500, 5000), location=dpf.locations.elemental) +print(elements_scoping) + +volume = model.results.elemental_volume.on_mesh_scoping(elements_scoping).eval() + +model.metadata.meshed_region.plot(volume) + +############################################################################### +# Equivalent to: +volume_op = model.results.elemental_volume() +volume_op.inputs.mesh_scoping(elements_scoping) +volume = volume_op.outputs.fields_container() + +############################################################################### +# Equivalent to: +volume = model.results.elemental_volume(mesh_scoping=elements_scoping).eval() + +############################################################################### +# Choose specific named selections +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Named selections (also known as components) can be selected to create +# a spatial domain for a result. A ``mesh_scoping`` can be created with a +# named selection. +# To know the available named selections in the result file, use: + +print(model.metadata.available_named_selections) + +############################################################################### +# Get the ``mesh_scoping`` of a named selection: + +mesh_scoping = model.metadata.named_selection("_CM82") +print(mesh_scoping) + +############################################################################### +# Connect this ``mesh_scoping`` to the result provider +volume = model.results.elemental_volume(mesh_scoping=mesh_scoping).eval() +model.metadata.meshed_region.plot(volume) + +############################################################################### +# Equivalent to: +volume = model.results.elemental_volume.on_named_selection("_CM82") + +############################################################################### +# Equivalent to: +ns_provider = dpf.operators.scoping.on_named_selection( + requested_location=dpf.locations.elemental, + named_selection_name="_CM82", + data_sources=model, +) +volume = model.results.elemental_volume(mesh_scoping=ns_provider).eval() + +############################################################################### +# Split results depending on spatial properties +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# For many applications, it can be useful to request results on different subsets +# of the model. The ``ScopingsContainer`` entity contains different ``Scopings`` +# and can be connected to any result provider to get results split with the +# same partition as the input ``ScopingsContainer``. +# For example, some application require to get results split by body, by material, +# by element types. It might also be necessary to get results by element shape +# types, such as shell, solid, or beam, to average data properly. +# Customers might also require split by entirely custom spatial domains. + + +############################################################################### +# Split results by element shapes +stress = model.results.stress.split_by_shape.on_location(dpf.locations.nodal).eval() +print(stress) + +shell_stresses = stress.shell_fields() +model.metadata.meshed_region.plot(shell_stresses[0]) + +solid_stresses = stress.solid_fields() +model.metadata.meshed_region.plot(solid_stresses[0]) + +############################################################################### +# Split results by bodies +stress = model.results.stress.split_by_body.on_location(dpf.locations.nodal).eval() +print(stress) + +for body_id in stress.get_mat_scoping().ids: + fields = stress.get_fields_by_mat_id(body_id) + for field in fields: + if field.elementary_data_count > 0: + model.metadata.meshed_region.plot(field) + +############################################################################### +# Create a custom spatial split +scopings_container = dpf.ScopingsContainer() +scopings_container.add_label("custom_split") +scopings_container.add_scoping( + {"custom_split": 1}, + dpf.Scoping(ids=range(100, 500), location=dpf.locations.elemental), +) +scopings_container.add_scoping( + {"custom_split": 2}, + dpf.Scoping(ids=range(500, 5000), location=dpf.locations.elemental), +) + +############################################################################### +elemental_stress = model.results.stress.on_location(dpf.locations.elemental)( + mesh_scoping=scopings_container +).eval() +print(elemental_stress) + +for field in elemental_stress: + model.metadata.meshed_region.plot(field) diff --git a/doc/source/examples/00-basic/09-results_over_space_subset.py.md5 b/doc/source/examples/00-basic/09-results_over_space_subset.py.md5 new file mode 100644 index 0000000000..b552fd3624 --- /dev/null +++ b/doc/source/examples/00-basic/09-results_over_space_subset.py.md5 @@ -0,0 +1 @@ +da013e133886431628c86d351b14e1f9 \ No newline at end of file diff --git a/doc/source/examples/00-basic/09-results_over_space_subset.rst b/doc/source/examples/00-basic/09-results_over_space_subset.rst new file mode 100644 index 0000000000..8449769574 --- /dev/null +++ b/doc/source/examples/00-basic/09-results_over_space_subset.rst @@ -0,0 +1,662 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\09-results_over_space_subset.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_09-results_over_space_subset.py: + + +.. _ref_results_over_space: + +Scope results over custom space domains +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :class:`Result ` class, which are instances +created by the :class:`Model `, give +access to helpers for requesting results on specific mesh and time scopings. +With these helpers, working on a spatial subset of the model is straightforward. +In this example, different ways to choose the spatial subset to +evaluate a result are exposed + +Import necessary modules: + +.. GENERATED FROM PYTHON SOURCE LINES 17-21 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-23 + +Create a model object to establish a connection with an example result file: + +.. GENERATED FROM PYTHON SOURCE LINES 23-26 + +.. code-block:: default + + model = dpf.Model(examples.download_all_kinds_of_complexity()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - element_nodal_forces: ElementalNodal Element nodal Forces + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - thermal_strain: ElementalNodal Thermal Strains + - thermal_strains_eqv: ElementalNodal Thermal Strains eqv + - swelling_strains: ElementalNodal Swelling Strains + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + - contact_status: ElementalNodal Contact Status + - contact_penetration: ElementalNodal Contact Penetration + - contact_pressure: ElementalNodal Contact Pressure + - contact_friction_stress: ElementalNodal Contact Friction Stress + - contact_total_stress: ElementalNodal Contact Total Stress + - contact_sliding_distance: ElementalNodal Contact Sliding Distance + - contact_gap_distance: ElementalNodal Contact Gap Distance + - total_heat_flux_at_contact_surface: ElementalNodal Total heat flux at contact surface + - contact_status_changes: ElementalNodal Contact status changes + - fluid_penetration_pressure: ElementalNodal Fluid Penetration Pressure + ------------------------------ + DPF Meshed Region: + 15129 nodes + 10292 elements + Unit: m + With solid (3D) elements, shell (2D) elements, shell (3D) elements, beam (1D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1 + Cumulative Time (s) LoadStep Substep + 1 1,000000 1 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 27-31 + +Choose specific nodes +~~~~~~~~~~~~~~~~~~~~~ +If some nodes or elements are specifically of interest, a nodal ``mesh_scoping`` +can be connected. + +.. GENERATED FROM PYTHON SOURCE LINES 31-35 + +.. code-block:: default + + + nodes_scoping = dpf.mesh_scoping_factory.nodal_scoping(range(400, 500)) + print(nodes_scoping) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Scoping: + with Nodal location and 100 entities + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 36-37 + +or + +.. GENERATED FROM PYTHON SOURCE LINES 37-40 + +.. code-block:: default + + nodes_scoping = dpf.Scoping(ids=range(400, 500), location=dpf.locations.nodal) + print(nodes_scoping) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Scoping: + with Nodal location and 100 entities + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 41-46 + +.. code-block:: default + + + disp = model.results.displacement.on_mesh_scoping(nodes_scoping).eval() + + model.metadata.meshed_region.plot(disp) + + + + +.. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_001.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 47-48 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 48-52 + +.. code-block:: default + + disp_op = model.results.displacement() + disp_op.inputs.mesh_scoping(nodes_scoping) + disp = disp_op.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 53-54 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 54-56 + +.. code-block:: default + + disp = model.results.displacement(mesh_scoping=nodes_scoping).eval() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 57-61 + +Choose specific elements +~~~~~~~~~~~~~~~~~~~~~~~~ +If some elements are specifically of interest, an elemental ``mesh_scoping`` +can be connected. + +.. GENERATED FROM PYTHON SOURCE LINES 61-73 + +.. code-block:: default + + + elements_scoping = dpf.mesh_scoping_factory.elemental_scoping(range(500, 5000)) + print(elements_scoping) + + # or + elements_scoping = dpf.Scoping(ids=range(500, 5000), location=dpf.locations.elemental) + print(elements_scoping) + + volume = model.results.elemental_volume.on_mesh_scoping(elements_scoping).eval() + + model.metadata.meshed_region.plot(volume) + + + + +.. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_002.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_002.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Scoping: + with Elemental location and 4500 entities + + DPF Scoping: + with Elemental location and 4500 entities + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 74-75 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 75-79 + +.. code-block:: default + + volume_op = model.results.elemental_volume() + volume_op.inputs.mesh_scoping(elements_scoping) + volume = volume_op.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 80-81 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 81-83 + +.. code-block:: default + + volume = model.results.elemental_volume(mesh_scoping=elements_scoping).eval() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 84-90 + +Choose specific named selections +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Named selections (also known as components) can be selected to create +a spatial domain for a result. A ``mesh_scoping`` can be created with a +named selection. +To know the available named selections in the result file, use: + +.. GENERATED FROM PYTHON SOURCE LINES 90-93 + +.. code-block:: default + + + print(model.metadata.available_named_selections) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ['_CM82', '_CM86UX_XP', '_DISPNONZEROUX', '_DISPZEROUZ', '_ELMISC', '_FIXEDSU'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 94-95 + +Get the ``mesh_scoping`` of a named selection: + +.. GENERATED FROM PYTHON SOURCE LINES 95-99 + +.. code-block:: default + + + mesh_scoping = model.metadata.named_selection("_CM82") + print(mesh_scoping) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Scoping: + with Elemental location and 8709 entities + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 100-101 + +Connect this ``mesh_scoping`` to the result provider + +.. GENERATED FROM PYTHON SOURCE LINES 101-104 + +.. code-block:: default + + volume = model.results.elemental_volume(mesh_scoping=mesh_scoping).eval() + model.metadata.meshed_region.plot(volume) + + + + +.. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_003.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_003.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 105-106 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 106-108 + +.. code-block:: default + + volume = model.results.elemental_volume.on_named_selection("_CM82") + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 109-110 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 110-117 + +.. code-block:: default + + ns_provider = dpf.operators.scoping.on_named_selection( + requested_location=dpf.locations.elemental, + named_selection_name="_CM82", + data_sources=model, + ) + volume = model.results.elemental_volume(mesh_scoping=ns_provider).eval() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 118-128 + +Split results depending on spatial properties +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +For many applications, it can be useful to request results on different subsets +of the model. The ``ScopingsContainer`` entity contains different ``Scopings`` +and can be connected to any result provider to get results split with the +same partition as the input ``ScopingsContainer``. +For example, some application require to get results split by body, by material, +by element types. It might also be necessary to get results by element shape +types, such as shell, solid, or beam, to average data properly. +Customers might also require split by entirely custom spatial domains. + +.. GENERATED FROM PYTHON SOURCE LINES 131-132 + +Split results by element shapes + +.. GENERATED FROM PYTHON SOURCE LINES 132-141 + +.. code-block:: default + + stress = model.results.stress.split_by_shape.on_location(dpf.locations.nodal).eval() + print(stress) + + shell_stresses = stress.shell_fields() + model.metadata.meshed_region.plot(shell_stresses[0]) + + solid_stresses = stress.solid_fields() + model.metadata.meshed_region.plot(solid_stresses[0]) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_004.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_005.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_005.png + :class: sphx-glr-multi-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF stress(s)Fields Container + with 4 field(s) + defined on labels: elshape time + + with: + - field 0 {elshape: 0, time: 1} with Nodal location, 6 components and 240 entities. + - field 1 {elshape: 1, time: 1} with Nodal location, 6 components and 14826 entities. + - field 2 {elshape: 2, time: 1} with Nodal location, 6 components and 0 entities. + - field 3 {elshape: 3, time: 1} with Nodal location, 6 components and 0 entities. + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 142-143 + +Split results by bodies + +.. GENERATED FROM PYTHON SOURCE LINES 143-152 + +.. code-block:: default + + stress = model.results.stress.split_by_body.on_location(dpf.locations.nodal).eval() + print(stress) + + for body_id in stress.get_mat_scoping().ids: + fields = stress.get_fields_by_mat_id(body_id) + for field in fields: + if field.elementary_data_count > 0: + model.metadata.meshed_region.plot(field) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_006.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_006.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_007.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_007.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_008.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_008.png + :class: sphx-glr-multi-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF stress(s)Fields Container + with 3 field(s) + defined on labels: elshape mat time + + with: + - field 0 {elshape: 2, mat: 1, time: 1} with Nodal location, 6 components and 1856 entities. + - field 1 {elshape: 1, mat: 1, time: 1} with Nodal location, 6 components and 240 entities. + - field 2 {elshape: 2, mat: 2, time: 1} with Nodal location, 6 components and 12970 entities. + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 153-154 + +Create a custom spatial split + +.. GENERATED FROM PYTHON SOURCE LINES 154-165 + +.. code-block:: default + + scopings_container = dpf.ScopingsContainer() + scopings_container.add_label("custom_split") + scopings_container.add_scoping( + {"custom_split": 1}, + dpf.Scoping(ids=range(100, 500), location=dpf.locations.elemental), + ) + scopings_container.add_scoping( + {"custom_split": 2}, + dpf.Scoping(ids=range(500, 5000), location=dpf.locations.elemental), + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 166-173 + +.. code-block:: default + + elemental_stress = model.results.stress.on_location(dpf.locations.elemental)( + mesh_scoping=scopings_container + ).eval() + print(elemental_stress) + + for field in elemental_stress: + model.metadata.meshed_region.plot(field) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_009.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_009.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_010.png + :alt: 09 results over space subset + :srcset: /examples/00-basic/images/sphx_glr_09-results_over_space_subset_010.png + :class: sphx-glr-multi-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF stress(s)Fields Container + with 2 field(s) + defined on labels: custom_split time + + with: + - field 0 {custom_split: 1, time: 1} with Elemental location, 6 components and 400 entities. + - field 1 {custom_split: 2, time: 1} with Elemental location, 6 components and 4500 entities. + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 6.446 seconds) + + +.. _sphx_glr_download_examples_00-basic_09-results_over_space_subset.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 09-results_over_space_subset.py <09-results_over_space_subset.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 09-results_over_space_subset.ipynb <09-results_over_space_subset.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/09-results_over_space_subset_codeobj.pickle b/doc/source/examples/00-basic/09-results_over_space_subset_codeobj.pickle new file mode 100644 index 0000000000..91ed313bae Binary files /dev/null and b/doc/source/examples/00-basic/09-results_over_space_subset_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/10-math_operations.ipynb b/doc/source/examples/00-basic/10-math_operations.ipynb new file mode 100644 index 0000000000..8b26673f50 --- /dev/null +++ b/doc/source/examples/00-basic/10-math_operations.ipynb @@ -0,0 +1,288 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Mathematical Operations {#ref_math_operators_example}\r\n\r\nDPF provides operators for implementing mathematical operations, ranging\r\nfrom addition and multiplication to FFT and QR solving.\r\n\r\nFor a complete list, see `ref_dpf_operators_reference`{.interpreted-text\r\nrole=\"ref\"}, under the math section.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import the necessary modules\nimport ansys.dpf.core as dpf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Addition\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Initialize Fields\nnum_entities = 2\nfield1 = dpf.Field(nentities=2)\nfield2 = dpf.Field(nentities=2)\n\n# By default, Fields contain 3d vectors.\n# So with three entities we need nine values.\nfield1.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]\nfield2.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]\n\nfield1.scoping.ids = range(num_entities)\nfield2.scoping.ids = range(num_entities)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Once the fields are ready, we can instantiate an operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "add_op = dpf.operators.math.add(field1, field2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we use eval() to compute and retrieve the result.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field3 = add_op.eval()\n\n# = [[2. 4. 6.] [8. 10. 12.]]\nprint(field3.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Dot product\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "dot_op = dpf.operators.math.generalized_inner_product(field1, field2)\n\n# (1. * 1.) + (2. * 2.) + (3. * 3.) = 14.\n# (4. * 4.) + (5. * 5.) + (6. * 6.) = 77.\nfield3 = dot_op.eval()\nprint(field3.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Power\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field = dpf.Field(nentities=1)\nfield1.data = [1.0, 2.0, 3.0]\nfield1.scoping.ids = [1]\n\npow_op = dpf.operators.math.pow(field1, 3.0)\n\n# [1. 8. 27.]\nfield3 = pow_op.eval()\nprint(field3.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# L2 norm\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field1.data = [16.0, -8.0, 2.0]\nnorm_op = dpf.operators.math.norm(field1)\n\n# [ 18. ]\nfield3 = norm_op.eval()\nprint(field3.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Accumulate\r\n\r\nFirst we define fields. By default, fields represent 3D vectors so one\r\nelementary data is a 3D vector. The optional ponderation field is a\r\nfield which takes one value per entity, so we need to change its\r\ndimensionality (1D).\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "num_entities = 3\ninput_field = dpf.Field(nentities=num_entities)\nponderation_field = dpf.Field(num_entities)\nponderation_field.dimensionality = dpf.Dimensionality([1])\n\ninput_field.scoping.ids = range(num_entities)\nponderation_field.scoping.ids = range(num_entities)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Fill fields with data. Add nine values because there are three entities.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "input_field.data = [-2.0, 2.0, 4.0, -5.0, 0.5, 1.0, 7.0, 3.0, -3.0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Three weights, one per entity.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "ponderation_field.data = [0.5, 2.0, 0.5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Retrieve the result.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "acc = dpf.operators.math.accumulate(fieldA=input_field, ponderation=ponderation_field)\noutput_field = acc.outputs.field()\n\n# (-2.0 * 0.5) + (-5.0 * 2.0) + (7.0 * 0.5) = -7.5\n# (2.0 * 0.5) + (0.5 * 2.0) + (3.0 * 0.5) = 3.5\n# (4.0 * 0.5) + (1.0 * 2.0) + (-3.0 * 0.5) = 2.5\nprint(output_field.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# With scoping\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field1.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]\nfield2.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to provide information about the scoping. DPF needs to\r\nknow the IDs of the data we just provided, so that it can apply an\r\noperator on a subset of the original data.\r\n\r\nBy providing these integers we only select the data with an ID in\r\ncommon. Here we are selecting the third elementary data of the first\r\nfield, and the first elementary data of the second field, Other\r\nelementary data is not taken into account when using an operator that\r\nneeds two operands.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field1.scoping.ids = [1, 2, 3]\nfield2.scoping.ids = [3, 4, 5]\n\nadd_op = dpf.operators.math.add(field1, field2)\nfield3 = add_op.eval()\n\n# Only the third entity was changed\n# because it is the only operator where two operands were provided.\nprint(field3.data)\n# [[8. 10. 12.]]\nprint(field3.get_entity_data_by_id(3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dot product\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "dot_op = dpf.operators.math.generalized_inner_product(field1, field2)\n\n# We obtain zeros for IDs where there could not be two operands.\n# (7. * 1.) + (8. * 2.) + (9. * 3.) = 50.\n# [0. 0. 50. 0. 0.]\nfield3 = dot_op.eval()\nprint(field3.data)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/10-math_operations.py b/doc/source/examples/00-basic/10-math_operations.py new file mode 100644 index 0000000000..81d355d6e3 --- /dev/null +++ b/doc/source/examples/00-basic/10-math_operations.py @@ -0,0 +1,150 @@ +# noqa: D400 +""" +.. _ref_math_operators_example: + +Mathematical Operations +~~~~~~~~~~~~~~~~~~~~~~~ + +DPF provides operators for implementing mathematical operations, +ranging from addition and multiplication to FFT and QR solving. + +For a complete list, see :ref:`ref_dpf_operators_reference`, under the math section. + +""" + +# Import the necessary modules +import ansys.dpf.core as dpf + +############################################################################### +# Addition +# ~~~~~~~~ + +# Initialize Fields +num_entities = 2 +field1 = dpf.Field(nentities=2) +field2 = dpf.Field(nentities=2) + +# By default, Fields contain 3d vectors. +# So with three entities we need nine values. +field1.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] +field2.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] + +field1.scoping.ids = range(num_entities) +field2.scoping.ids = range(num_entities) +############################################################################### +# Once the fields are ready, we can instantiate an operator. +add_op = dpf.operators.math.add(field1, field2) + +############################################################################### +# Finally, we use eval() to compute and retrieve the result. +field3 = add_op.eval() + +# = [[2. 4. 6.] [8. 10. 12.]] +print(field3.data) + +############################################################################### +# Dot product +# ~~~~~~~~~~~ +dot_op = dpf.operators.math.generalized_inner_product(field1, field2) + +# (1. * 1.) + (2. * 2.) + (3. * 3.) = 14. +# (4. * 4.) + (5. * 5.) + (6. * 6.) = 77. +field3 = dot_op.eval() +print(field3.data) + + +############################################################################### +# Power +# ~~~~~ +field = dpf.Field(nentities=1) +field1.data = [1.0, 2.0, 3.0] +field1.scoping.ids = [1] + +pow_op = dpf.operators.math.pow(field1, 3.0) + +# [1. 8. 27.] +field3 = pow_op.eval() +print(field3.data) + + +############################################################################### +# L2 norm +# ~~~~~~~ +field1.data = [16.0, -8.0, 2.0] +norm_op = dpf.operators.math.norm(field1) + +# [ 18. ] +field3 = norm_op.eval() +print(field3.data) + + +############################################################################### +# Accumulate +# ~~~~~~~~~~ +# First we define fields. By default, fields represent 3D vectors +# so one elementary data is a 3D vector. +# The optional ponderation field is a field which takes one value per entity, +# so we need to change its dimensionality (1D). +num_entities = 3 +input_field = dpf.Field(nentities=num_entities) +ponderation_field = dpf.Field(num_entities) +ponderation_field.dimensionality = dpf.Dimensionality([1]) + +input_field.scoping.ids = range(num_entities) +ponderation_field.scoping.ids = range(num_entities) + +############################################################################### +# Fill fields with data. +# Add nine values because there are three entities. +input_field.data = [-2.0, 2.0, 4.0, -5.0, 0.5, 1.0, 7.0, 3.0, -3.0] +############################################################################### +# Three weights, one per entity. +ponderation_field.data = [0.5, 2.0, 0.5] + +############################################################################### +# Retrieve the result. +acc = dpf.operators.math.accumulate(fieldA=input_field, ponderation=ponderation_field) +output_field = acc.outputs.field() + +# (-2.0 * 0.5) + (-5.0 * 2.0) + (7.0 * 0.5) = -7.5 +# (2.0 * 0.5) + (0.5 * 2.0) + (3.0 * 0.5) = 3.5 +# (4.0 * 0.5) + (1.0 * 2.0) + (-3.0 * 0.5) = 2.5 +print(output_field.data) + +############################################################################### +# With scoping +# ~~~~~~~~~~~~ +field1.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] +field2.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] + +############################################################################### +# Next, we need to provide information about the scoping. +# DPF needs to know the IDs of the data we just provided, +# so that it can apply an operator on a subset of the original data. +# +# By providing these integers we only select the data with an ID in common. +# Here we are selecting the third elementary data of the first field, +# and the first elementary data of the second field, +# Other elementary data is not taken into account when using an operator that needs two operands. +field1.scoping.ids = [1, 2, 3] +field2.scoping.ids = [3, 4, 5] + +add_op = dpf.operators.math.add(field1, field2) +field3 = add_op.eval() + +# Only the third entity was changed +# because it is the only operator where two operands were provided. +print(field3.data) +# [[8. 10. 12.]] +print(field3.get_entity_data_by_id(3)) + +############################################################################### +# Dot product + +dot_op = dpf.operators.math.generalized_inner_product(field1, field2) + +# We obtain zeros for IDs where there could not be two operands. +# (7. * 1.) + (8. * 2.) + (9. * 3.) = 50. +# [0. 0. 50. 0. 0.] +field3 = dot_op.eval() +print(field3.data) diff --git a/doc/source/examples/00-basic/10-math_operations.py.md5 b/doc/source/examples/00-basic/10-math_operations.py.md5 new file mode 100644 index 0000000000..f3692cb55a --- /dev/null +++ b/doc/source/examples/00-basic/10-math_operations.py.md5 @@ -0,0 +1 @@ +4680485a20c9a5ce36b37a19a540f15f \ No newline at end of file diff --git a/doc/source/examples/00-basic/10-math_operations.rst b/doc/source/examples/00-basic/10-math_operations.rst new file mode 100644 index 0000000000..30e67826fb --- /dev/null +++ b/doc/source/examples/00-basic/10-math_operations.rst @@ -0,0 +1,422 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\10-math_operations.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_10-math_operations.py: + + +.. _ref_math_operators_example: + +Mathematical Operations +~~~~~~~~~~~~~~~~~~~~~~~ + +DPF provides operators for implementing mathematical operations, +ranging from addition and multiplication to FFT and QR solving. + +For a complete list, see :ref:`ref_dpf_operators_reference`, under the math section. + +.. GENERATED FROM PYTHON SOURCE LINES 14-18 + +.. code-block:: default + + + # Import the necessary modules + import ansys.dpf.core as dpf + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 19-21 + +Addition +~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 21-34 + +.. code-block:: default + + + # Initialize Fields + num_entities = 2 + field1 = dpf.Field(nentities=2) + field2 = dpf.Field(nentities=2) + + # By default, Fields contain 3d vectors. + # So with three entities we need nine values. + field1.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] + field2.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] + + field1.scoping.ids = range(num_entities) + field2.scoping.ids = range(num_entities) + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 35-36 + +Once the fields are ready, we can instantiate an operator. + +.. GENERATED FROM PYTHON SOURCE LINES 36-38 + +.. code-block:: default + + add_op = dpf.operators.math.add(field1, field2) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 39-40 + +Finally, we use eval() to compute and retrieve the result. + +.. GENERATED FROM PYTHON SOURCE LINES 40-45 + +.. code-block:: default + + field3 = add_op.eval() + + # = [[2. 4. 6.] [8. 10. 12.]] + print(field3.data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [[ 2. 4. 6.] + [ 8. 10. 12.]] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 46-48 + +Dot product +~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 48-56 + +.. code-block:: default + + dot_op = dpf.operators.math.generalized_inner_product(field1, field2) + + # (1. * 1.) + (2. * 2.) + (3. * 3.) = 14. + # (4. * 4.) + (5. * 5.) + (6. * 6.) = 77. + field3 = dot_op.eval() + print(field3.data) + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [14. 77.] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 57-59 + +Power +~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 59-70 + +.. code-block:: default + + field = dpf.Field(nentities=1) + field1.data = [1.0, 2.0, 3.0] + field1.scoping.ids = [1] + + pow_op = dpf.operators.math.pow(field1, 3.0) + + # [1. 8. 27.] + field3 = pow_op.eval() + print(field3.data) + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [[ 1. 8. 27.]] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 71-73 + +L2 norm +~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 73-81 + +.. code-block:: default + + field1.data = [16.0, -8.0, 2.0] + norm_op = dpf.operators.math.norm(field1) + + # [ 18. ] + field3 = norm_op.eval() + print(field3.data) + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [18.] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 82-88 + +Accumulate +~~~~~~~~~~ +First we define fields. By default, fields represent 3D vectors +so one elementary data is a 3D vector. +The optional ponderation field is a field which takes one value per entity, +so we need to change its dimensionality (1D). + +.. GENERATED FROM PYTHON SOURCE LINES 88-96 + +.. code-block:: default + + num_entities = 3 + input_field = dpf.Field(nentities=num_entities) + ponderation_field = dpf.Field(num_entities) + ponderation_field.dimensionality = dpf.Dimensionality([1]) + + input_field.scoping.ids = range(num_entities) + ponderation_field.scoping.ids = range(num_entities) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 97-99 + +Fill fields with data. +Add nine values because there are three entities. + +.. GENERATED FROM PYTHON SOURCE LINES 99-100 + +.. code-block:: default + + input_field.data = [-2.0, 2.0, 4.0, -5.0, 0.5, 1.0, 7.0, 3.0, -3.0] + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 101-102 + +Three weights, one per entity. + +.. GENERATED FROM PYTHON SOURCE LINES 102-104 + +.. code-block:: default + + ponderation_field.data = [0.5, 2.0, 0.5] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 105-106 + +Retrieve the result. + +.. GENERATED FROM PYTHON SOURCE LINES 106-114 + +.. code-block:: default + + acc = dpf.operators.math.accumulate(fieldA=input_field, ponderation=ponderation_field) + output_field = acc.outputs.field() + + # (-2.0 * 0.5) + (-5.0 * 2.0) + (7.0 * 0.5) = -7.5 + # (2.0 * 0.5) + (0.5 * 2.0) + (3.0 * 0.5) = 3.5 + # (4.0 * 0.5) + (1.0 * 2.0) + (-3.0 * 0.5) = 2.5 + print(output_field.data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [[-7.5 3.5 2.5]] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 115-117 + +With scoping +~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 117-120 + +.. code-block:: default + + field1.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] + field2.data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 121-129 + +Next, we need to provide information about the scoping. +DPF needs to know the IDs of the data we just provided, +so that it can apply an operator on a subset of the original data. + +By providing these integers we only select the data with an ID in common. +Here we are selecting the third elementary data of the first field, +and the first elementary data of the second field, +Other elementary data is not taken into account when using an operator that needs two operands. + +.. GENERATED FROM PYTHON SOURCE LINES 129-141 + +.. code-block:: default + + field1.scoping.ids = [1, 2, 3] + field2.scoping.ids = [3, 4, 5] + + add_op = dpf.operators.math.add(field1, field2) + field3 = add_op.eval() + + # Only the third entity was changed + # because it is the only operator where two operands were provided. + print(field3.data) + # [[8. 10. 12.]] + print(field3.get_entity_data_by_id(3)) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [[ 1. 2. 3.] + [ 4. 5. 6.] + [ 8. 10. 12.] + [ 4. 5. 6.] + [ 7. 8. 9.]] + [[ 8. 10. 12.]] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 142-143 + +Dot product + +.. GENERATED FROM PYTHON SOURCE LINES 143-151 + +.. code-block:: default + + + dot_op = dpf.operators.math.generalized_inner_product(field1, field2) + + # We obtain zeros for IDs where there could not be two operands. + # (7. * 1.) + (8. * 2.) + (9. * 3.) = 50. + # [0. 0. 50. 0. 0.] + field3 = dot_op.eval() + print(field3.data) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [ 0. 0. 50. 0. 0.] + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.041 seconds) + + +.. _sphx_glr_download_examples_00-basic_10-math_operations.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 10-math_operations.py <10-math_operations.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 10-math_operations.ipynb <10-math_operations.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/10-math_operations_codeobj.pickle b/doc/source/examples/00-basic/10-math_operations_codeobj.pickle new file mode 100644 index 0000000000..7d57613bc2 Binary files /dev/null and b/doc/source/examples/00-basic/10-math_operations_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/11-server_types.ipynb b/doc/source/examples/00-basic/11-server_types.ipynb new file mode 100644 index 0000000000..3b966912d2 --- /dev/null +++ b/doc/source/examples/00-basic/11-server_types.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Communicate in process or via gRPC {#ref_server_types_example}\r\n\r\nStarting with Ansys 2022 R2, PyDPF can communicate either via In Process\r\nor via gRPC with DPF C++ core server (`Ans.Dpf.Grpc.exe`). To choose\r\nwhich type of `ansys.dpf.core.server_types.BaseServer`{.interpreted-text\r\nrole=\"class\"} (object defining the type of communication and the server\r\ninstance to communicate with) to use, a\r\n`ansys.dpf.core.server_factory.ServerConfig`{.interpreted-text\r\nrole=\"class\"} class should be used. Until Ansys 2022R1, only gRPC\r\ncommunication using python module `ansys.grpc.dpf` is supported (now\r\ncalled `ansys.dpf.core.server_types.LegacyGrpcServer`{.interpreted-text\r\nrole=\"class\"}), starting with Ansys 2022 R2, three types of servers are\r\nsupported:\r\n\r\n- `ansys.dpf.core.server_types.InProcessServer`{.interpreted-text\r\n role=\"class\"} loading DPF in process. Cannot run on Docker.\r\n- `ansys.dpf.core.server_types.GrpcServer`{.interpreted-text\r\n role=\"class\"} using gRPC communication through the DPF gRPC CLayer\r\n `Ans.Dpf.GrpcClient`.\r\n- `ansys.dpf.core.server_types.LegacyGrpcServer`{.interpreted-text\r\n role=\"class\"} using gRPC communication through the Python module\r\n `ansys.grpc.dpf`.\r\n\r\nTo change the default type of server\\'s configuration used by DPF\r\nchange:\r\n\r\n- the global variable `SERVER_CONFIGURATION` at the beginning of the\r\n python script.\r\n- the environment variable `DPF_SERVER_TYPE` before running the python\r\n executable, see\r\n `ansys.dpf.core.server_factory.ServerConfig`{.interpreted-text\r\n role=\"class\"} for more information.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\nfrom ansys.dpf import core as dpf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Start servers with custom server configuration\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "in_process_config = dpf.AvailableServerConfigs.InProcessServer\ngrpc_config = dpf.AvailableServerConfigs.GrpcServer\nlegacy_grpc_config = dpf.AvailableServerConfigs.LegacyGrpcServer\n\nif \"DPF_DOCKER\" not in os.environ.keys():\n in_process_server = dpf.start_local_server(config=in_process_config)\ngrpc_server = dpf.start_local_server(config=grpc_config)\nlegacy_grpc_server = dpf.start_local_server(config=legacy_grpc_config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Equivalent to:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "in_process_config = dpf.ServerConfig(protocol=None, legacy=False)\ngrpc_config = dpf.ServerConfig(\n protocol=dpf.server_factory.CommunicationProtocols.gRPC, legacy=False\n)\nlegacy_grpc_config = dpf.ServerConfig(\n protocol=dpf.server_factory.CommunicationProtocols.gRPC, legacy=True\n)\n\nif \"DPF_DOCKER\" not in os.environ.keys():\n in_process_server = dpf.start_local_server(config=in_process_config, as_global=False)\ngrpc_server = dpf.start_local_server(config=grpc_config, as_global=False)\nlegacy_grpc_server = dpf.start_local_server(config=legacy_grpc_config, as_global=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create data on different servers\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "if \"DPF_DOCKER\" not in os.environ.keys():\n in_process_field = dpf.fields_factory.create_scalar_field(2, server=in_process_server)\n in_process_field.append([1.0], 1)\n in_process_field.append([2.0], 2)\ngrpc_field = dpf.fields_factory.create_scalar_field(2, server=grpc_server)\ngrpc_field.append([1.0], 1)\ngrpc_field.append([2.0], 2)\nlegacy_grpc_field = dpf.fields_factory.create_scalar_field(2, server=legacy_grpc_server)\nlegacy_grpc_field.append([1.0], 1)\nlegacy_grpc_field.append([2.0], 2)\n\nif \"DPF_DOCKER\" not in os.environ.keys():\n print(in_process_field, type(in_process_field._server), in_process_field._server)\nprint(grpc_field, type(grpc_field._server), grpc_field._server)\nprint(legacy_grpc_field, type(legacy_grpc_field._server), legacy_grpc_field._server)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Choose default configuration\r\n\r\nOnce a default configuration is chosen, a server of the chosen type is\r\nautomatically started when a DPF object is created:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "initial_config = dpf.SERVER_CONFIGURATION\n\ndpf.SERVER_CONFIGURATION = dpf.AvailableServerConfigs.GrpcServer\ngrpc_field = dpf.fields_factory.create_scalar_field(2)\ngrpc_field.append([1.0], 1)\ngrpc_field.append([2.0], 2)\nprint(grpc_field, type(grpc_field._server), grpc_field._server)\n\n# Go back to default config:\ndpf.SERVER_CONFIGURATION = initial_config" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/11-server_types.py b/doc/source/examples/00-basic/11-server_types.py new file mode 100644 index 0000000000..d9bedbb2de --- /dev/null +++ b/doc/source/examples/00-basic/11-server_types.py @@ -0,0 +1,100 @@ +# noqa: D400 +""" +.. _ref_server_types_example: + +Communicate in process or via gRPC +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Starting with Ansys 2022 R2, PyDPF can communicate either via In Process or via gRPC +with DPF C++ core server (``Ans.Dpf.Grpc.exe``). To choose which type of +:class:`ansys.dpf.core.server_types.BaseServer` (object defining the type of communication +and the server instance to communicate with) to use, a +:class:`ansys.dpf.core.server_factory.ServerConfig` class should be used. +Until Ansys 2022R1, only gRPC communication using python module ``ansys.grpc.dpf`` is supported +(now called :class:`ansys.dpf.core.server_types.LegacyGrpcServer`), starting with Ansys 2022 R2, +three types of servers are supported: + +- :class:`ansys.dpf.core.server_types.InProcessServer` loading DPF in process. Cannot run on Docker. + +- :class:`ansys.dpf.core.server_types.GrpcServer` using gRPC communication through the DPF + gRPC CLayer ``Ans.Dpf.GrpcClient``. + +- :class:`ansys.dpf.core.server_types.LegacyGrpcServer` using gRPC communication through the + Python module ``ansys.grpc.dpf``. + +To change the default type of server's configuration used by DPF change: + +- the global variable ``SERVER_CONFIGURATION`` at the beginning of the python script. +- the environment variable ``DPF_SERVER_TYPE`` before running the python executable, see + :class:`ansys.dpf.core.server_factory.ServerConfig` for more information. + +""" + +import os +from ansys.dpf import core as dpf + +############################################################################### +# Start servers with custom server configuration +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +in_process_config = dpf.AvailableServerConfigs.InProcessServer +grpc_config = dpf.AvailableServerConfigs.GrpcServer +legacy_grpc_config = dpf.AvailableServerConfigs.LegacyGrpcServer + +if "DPF_DOCKER" not in os.environ.keys(): + in_process_server = dpf.start_local_server(config=in_process_config) +grpc_server = dpf.start_local_server(config=grpc_config) +legacy_grpc_server = dpf.start_local_server(config=legacy_grpc_config) + +############################################################################### +# Equivalent to: + +in_process_config = dpf.ServerConfig(protocol=None, legacy=False) +grpc_config = dpf.ServerConfig( + protocol=dpf.server_factory.CommunicationProtocols.gRPC, legacy=False +) +legacy_grpc_config = dpf.ServerConfig( + protocol=dpf.server_factory.CommunicationProtocols.gRPC, legacy=True +) + +if "DPF_DOCKER" not in os.environ.keys(): + in_process_server = dpf.start_local_server(config=in_process_config, as_global=False) +grpc_server = dpf.start_local_server(config=grpc_config, as_global=False) +legacy_grpc_server = dpf.start_local_server(config=legacy_grpc_config, as_global=False) + +############################################################################### +# Create data on different servers +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if "DPF_DOCKER" not in os.environ.keys(): + in_process_field = dpf.fields_factory.create_scalar_field(2, server=in_process_server) + in_process_field.append([1.0], 1) + in_process_field.append([2.0], 2) +grpc_field = dpf.fields_factory.create_scalar_field(2, server=grpc_server) +grpc_field.append([1.0], 1) +grpc_field.append([2.0], 2) +legacy_grpc_field = dpf.fields_factory.create_scalar_field(2, server=legacy_grpc_server) +legacy_grpc_field.append([1.0], 1) +legacy_grpc_field.append([2.0], 2) + +if "DPF_DOCKER" not in os.environ.keys(): + print(in_process_field, type(in_process_field._server), in_process_field._server) +print(grpc_field, type(grpc_field._server), grpc_field._server) +print(legacy_grpc_field, type(legacy_grpc_field._server), legacy_grpc_field._server) + +############################################################################### +# Choose default configuration +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Once a default configuration is chosen, a server of the chosen type is +# automatically started when a DPF object is created: + +initial_config = dpf.SERVER_CONFIGURATION + +dpf.SERVER_CONFIGURATION = dpf.AvailableServerConfigs.GrpcServer +grpc_field = dpf.fields_factory.create_scalar_field(2) +grpc_field.append([1.0], 1) +grpc_field.append([2.0], 2) +print(grpc_field, type(grpc_field._server), grpc_field._server) + +# Go back to default config: +dpf.SERVER_CONFIGURATION = initial_config diff --git a/doc/source/examples/00-basic/11-server_types.py.md5 b/doc/source/examples/00-basic/11-server_types.py.md5 new file mode 100644 index 0000000000..950e0562a3 --- /dev/null +++ b/doc/source/examples/00-basic/11-server_types.py.md5 @@ -0,0 +1 @@ +2c6fe55526d9a33386b8338a3afdf64e \ No newline at end of file diff --git a/doc/source/examples/00-basic/11-server_types.rst b/doc/source/examples/00-basic/11-server_types.rst new file mode 100644 index 0000000000..68251dc9f6 --- /dev/null +++ b/doc/source/examples/00-basic/11-server_types.rst @@ -0,0 +1,273 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\11-server_types.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_11-server_types.py: + + +.. _ref_server_types_example: + +Communicate in process or via gRPC +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Starting with Ansys 2022 R2, PyDPF can communicate either via In Process or via gRPC +with DPF C++ core server (``Ans.Dpf.Grpc.exe``). To choose which type of +:class:`ansys.dpf.core.server_types.BaseServer` (object defining the type of communication +and the server instance to communicate with) to use, a +:class:`ansys.dpf.core.server_factory.ServerConfig` class should be used. +Until Ansys 2022R1, only gRPC communication using python module ``ansys.grpc.dpf`` is supported +(now called :class:`ansys.dpf.core.server_types.LegacyGrpcServer`), starting with Ansys 2022 R2, +three types of servers are supported: + +- :class:`ansys.dpf.core.server_types.InProcessServer` loading DPF in process. Cannot run on Docker. + +- :class:`ansys.dpf.core.server_types.GrpcServer` using gRPC communication through the DPF + gRPC CLayer ``Ans.Dpf.GrpcClient``. + +- :class:`ansys.dpf.core.server_types.LegacyGrpcServer` using gRPC communication through the + Python module ``ansys.grpc.dpf``. + +To change the default type of server's configuration used by DPF change: + +- the global variable ``SERVER_CONFIGURATION`` at the beginning of the python script. +- the environment variable ``DPF_SERVER_TYPE`` before running the python executable, see + :class:`ansys.dpf.core.server_factory.ServerConfig` for more information. + +.. GENERATED FROM PYTHON SOURCE LINES 32-36 + +.. code-block:: default + + + import os + from ansys.dpf import core as dpf + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 37-39 + +Start servers with custom server configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 39-49 + +.. code-block:: default + + + in_process_config = dpf.AvailableServerConfigs.InProcessServer + grpc_config = dpf.AvailableServerConfigs.GrpcServer + legacy_grpc_config = dpf.AvailableServerConfigs.LegacyGrpcServer + + if "DPF_DOCKER" not in os.environ.keys(): + in_process_server = dpf.start_local_server(config=in_process_config) + grpc_server = dpf.start_local_server(config=grpc_config) + legacy_grpc_server = dpf.start_local_server(config=legacy_grpc_config) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 50-51 + +Equivalent to: + +.. GENERATED FROM PYTHON SOURCE LINES 51-65 + +.. code-block:: default + + + in_process_config = dpf.ServerConfig(protocol=None, legacy=False) + grpc_config = dpf.ServerConfig( + protocol=dpf.server_factory.CommunicationProtocols.gRPC, legacy=False + ) + legacy_grpc_config = dpf.ServerConfig( + protocol=dpf.server_factory.CommunicationProtocols.gRPC, legacy=True + ) + + if "DPF_DOCKER" not in os.environ.keys(): + in_process_server = dpf.start_local_server(config=in_process_config, as_global=False) + grpc_server = dpf.start_local_server(config=grpc_config, as_global=False) + legacy_grpc_server = dpf.start_local_server(config=legacy_grpc_config, as_global=False) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 66-68 + +Create data on different servers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 68-85 + +.. code-block:: default + + + if "DPF_DOCKER" not in os.environ.keys(): + in_process_field = dpf.fields_factory.create_scalar_field(2, server=in_process_server) + in_process_field.append([1.0], 1) + in_process_field.append([2.0], 2) + grpc_field = dpf.fields_factory.create_scalar_field(2, server=grpc_server) + grpc_field.append([1.0], 1) + grpc_field.append([2.0], 2) + legacy_grpc_field = dpf.fields_factory.create_scalar_field(2, server=legacy_grpc_server) + legacy_grpc_field.append([1.0], 1) + legacy_grpc_field.append([2.0], 2) + + if "DPF_DOCKER" not in os.environ.keys(): + print(in_process_field, type(in_process_field._server), in_process_field._server) + print(grpc_field, type(grpc_field._server), grpc_field._server) + print(legacy_grpc_field, type(legacy_grpc_field._server), legacy_grpc_field._server) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Field + Location: Nodal + Unit: + 2 entities + Data: 1 components and 2 elementary data + + IDs data + ------------ ---------- + 1 1.000000e+00 + + 2 2.000000e+00 + + + DPF Server: {'server_ip': '', 'server_port': None, 'server_process_id': 11720, 'server_version': '8.0', 'os': 'nt'} + DPF Field + Location: Nodal + Unit: + 2 entities + Data: 1 components and 2 elementary data + + IDs data + ------------ ---------- + 1 1.000000e+00 + + 2 2.000000e+00 + + + DPF Server: {'server_ip': '127.0.0.1', 'server_port': 50057, 'server_process_id': 45016, 'server_version': '8.0', 'os': 'nt'} + DPF Field + Location: Nodal + Unit: + 2 entities + Data: 1 components and 2 elementary data + + IDs data + ------------ ---------- + 1 1.000000e+00 + + 2 2.000000e+00 + + + DPF Server: {'server_ip': '127.0.0.1', 'server_port': 50055, 'server_process_id': 23760, 'server_version': '8.0', 'os': 'nt'} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 86-90 + +Choose default configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once a default configuration is chosen, a server of the chosen type is +automatically started when a DPF object is created: + +.. GENERATED FROM PYTHON SOURCE LINES 90-101 + +.. code-block:: default + + + initial_config = dpf.SERVER_CONFIGURATION + + dpf.SERVER_CONFIGURATION = dpf.AvailableServerConfigs.GrpcServer + grpc_field = dpf.fields_factory.create_scalar_field(2) + grpc_field.append([1.0], 1) + grpc_field.append([2.0], 2) + print(grpc_field, type(grpc_field._server), grpc_field._server) + + # Go back to default config: + dpf.SERVER_CONFIGURATION = initial_config + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Field + Location: Nodal + Unit: + 2 entities + Data: 1 components and 2 elementary data + + IDs data + ------------ ---------- + 1 1.000000e+00 + + 2 2.000000e+00 + + + DPF Server: {'server_ip': '127.0.0.1', 'server_port': 50056, 'server_process_id': 31364, 'server_version': '8.0', 'os': 'nt'} + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 6.058 seconds) + + +.. _sphx_glr_download_examples_00-basic_11-server_types.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 11-server_types.py <11-server_types.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 11-server_types.ipynb <11-server_types.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/11-server_types_codeobj.pickle b/doc/source/examples/00-basic/11-server_types_codeobj.pickle new file mode 100644 index 0000000000..1324895536 Binary files /dev/null and b/doc/source/examples/00-basic/11-server_types_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/12-get_material_properties.ipynb b/doc/source/examples/00-basic/12-get_material_properties.ipynb new file mode 100644 index 0000000000..1d54dae103 --- /dev/null +++ b/doc/source/examples/00-basic/12-get_material_properties.ipynb @@ -0,0 +1,216 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get material properties from the result file {#ref_get_material_properties}\r\n\r\nMaterial properties are assigned to each element in APDL and by default\r\nthey are written out in the APDL result file. This example shows how you\r\ncan extract material properties of each element using PyDPF-Core.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import necessary modules\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a model object to establish a connection with an example result\r\nfile.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.find_simple_bar())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the\r\n`meshed_region `{.interpreted-text\r\nrole=\"class\"} from model\\'s metadata.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh = model.metadata.meshed_region\nprint(mesh)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "See available properties in the `meshed_region\r\n`{.interpreted-text\r\nrole=\"class\"}.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(mesh.available_property_fields)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get all material properties.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mats = mesh.property_field(\"mat\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the DPF operator `mapdl_material_properties\r\n`{.interpreted-text\r\nrole=\"class\"} to extract data for the \\# materials - [mats]{.title-ref}.\r\nFor the input `properties_name`, you need the correct material property\r\nstring. To see which strings are supported, you can print the operator\r\nhelp.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mat_prop = model.operator(\"mapdl_material_properties\")\nmat_prop.inputs.materials.connect(mats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the input pin `properties_name`, you need the correct material\r\nproperty string. To see which strings are supported, you can print the\r\noperator help.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(mat_prop)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To extract the Young\\'s modulus for element ID `1`, first we need to get\r\nthe mat_id for EID `1`.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mat_id = mats.get_entity_data_by_id(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And then use the mat_id get the material property.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mat_prop.inputs.properties_name.connect(\"EX\")\nmat_field = mat_prop.outputs.properties_value.get_data()[0]\nprint(mat_field.get_entity_data_by_id(mat_id[0]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Extract Poisson\\'s ratio for element ID `1`.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mat_prop.inputs.properties_name.connect(\"NUXY\")\nmat_field = mat_prop.outputs.properties_value.get_data()[0]\nprint(mat_field.get_entity_data_by_id(mat_id[0]))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/00-basic/12-get_material_properties.py b/doc/source/examples/00-basic/12-get_material_properties.py new file mode 100644 index 0000000000..da1d224070 --- /dev/null +++ b/doc/source/examples/00-basic/12-get_material_properties.py @@ -0,0 +1,66 @@ +""" +.. _ref_get_material_properties: + +Get material properties from the result file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Material properties are assigned to each element in APDL and by default they +are written out in the APDL result file. This example shows how you can extract +material properties of each element using PyDPF-Core. + +""" + +# Import necessary modules +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# Create a model object to establish a connection with an example result file. +model = dpf.Model(examples.find_simple_bar()) + +############################################################################### +# Get the :class:`meshed_region ` +# from model's metadata. +mesh = model.metadata.meshed_region +print(mesh) + +############################################################################### +# See available properties in the :class:`meshed_region +# `. +print(mesh.available_property_fields) + +############################################################################### +# Get all material properties. +mats = mesh.property_field("mat") + +############################################################################### +# Use the DPF operator :class:`mapdl_material_properties +# ` +# to extract data for the # materials - `mats`. For the input +# ``properties_name``, you need the correct material property string. To see +# which strings are supported, you can print the operator help. +mat_prop = model.operator("mapdl_material_properties") +mat_prop.inputs.materials.connect(mats) + +############################################################################### +# For the input pin ``properties_name``, you need the correct +# material property string. To see which strings are supported, you can +# print the operator help. +print(mat_prop) + +############################################################################### +# To extract the Young's modulus for element ID ``1``, first we need to get the +# mat_id for EID ``1``. +mat_id = mats.get_entity_data_by_id(1) + +############################################################################### +# And then use the mat_id get the material property. +mat_prop.inputs.properties_name.connect("EX") +mat_field = mat_prop.outputs.properties_value.get_data()[0] +print(mat_field.get_entity_data_by_id(mat_id[0])) + +############################################################################### +# Extract Poisson's ratio for element ID ``1``. +mat_prop.inputs.properties_name.connect("NUXY") +mat_field = mat_prop.outputs.properties_value.get_data()[0] +print(mat_field.get_entity_data_by_id(mat_id[0])) diff --git a/doc/source/examples/00-basic/12-get_material_properties.py.md5 b/doc/source/examples/00-basic/12-get_material_properties.py.md5 new file mode 100644 index 0000000000..703eedde9e --- /dev/null +++ b/doc/source/examples/00-basic/12-get_material_properties.py.md5 @@ -0,0 +1 @@ +396c4848632190dfc7e582b5ca60ea2a \ No newline at end of file diff --git a/doc/source/examples/00-basic/12-get_material_properties.rst b/doc/source/examples/00-basic/12-get_material_properties.rst new file mode 100644 index 0000000000..76ee3d63da --- /dev/null +++ b/doc/source/examples/00-basic/12-get_material_properties.rst @@ -0,0 +1,282 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\00-basic\12-get_material_properties.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_00-basic_12-get_material_properties.py: + + +.. _ref_get_material_properties: + +Get material properties from the result file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Material properties are assigned to each element in APDL and by default they +are written out in the APDL result file. This example shows how you can extract +material properties of each element using PyDPF-Core. + +.. GENERATED FROM PYTHON SOURCE LINES 12-17 + +.. code-block:: default + + + # Import necessary modules + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 18-19 + +Create a model object to establish a connection with an example result file. + +.. GENERATED FROM PYTHON SOURCE LINES 19-21 + +.. code-block:: default + + model = dpf.Model(examples.find_simple_bar()) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-24 + +Get the :class:`meshed_region ` +from model's metadata. + +.. GENERATED FROM PYTHON SOURCE LINES 24-27 + +.. code-block:: default + + mesh = model.metadata.meshed_region + print(mesh) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Meshed Region: + 3751 nodes + 3000 elements + Unit: m + With solid (3D) elements + + + + +.. GENERATED FROM PYTHON SOURCE LINES 28-30 + +See available properties in the :class:`meshed_region +`. + +.. GENERATED FROM PYTHON SOURCE LINES 30-32 + +.. code-block:: default + + print(mesh.available_property_fields) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ['connectivity', 'elprops', 'eltype', 'apdl_element_type', 'section', 'mat'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 33-34 + +Get all material properties. + +.. GENERATED FROM PYTHON SOURCE LINES 34-36 + +.. code-block:: default + + mats = mesh.property_field("mat") + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 37-42 + +Use the DPF operator :class:`mapdl_material_properties +` +to extract data for the # materials - `mats`. For the input +``properties_name``, you need the correct material property string. To see +which strings are supported, you can print the operator help. + +.. GENERATED FROM PYTHON SOURCE LINES 42-45 + +.. code-block:: default + + mat_prop = model.operator("mapdl_material_properties") + mat_prop.inputs.materials.connect(mats) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 46-49 + +For the input pin ``properties_name``, you need the correct +material property string. To see which strings are supported, you can +print the operator help. + +.. GENERATED FROM PYTHON SOURCE LINES 49-51 + +.. code-block:: default + + print(mat_prop) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF mapdl_material_properties Operator: + Read the values of the properties of a material for a given materials property field (property field that contains materials information for each element of a mesh).It returns a fields container containing a field for each material property, with only one value per material. The following keys can be used: Young's modulus (keys: EX, EY, EZ), Poisson's ratio (keys: NUXY, NUYZ, NUXZ), Shear Modulus (keys: GXY, GYZ, GXZ), Coefficient of Thermal Expansion (keys: ALPX, ALPY, ALPZ), Volumic Mass (key: DENS), second Lame's coefficient (key: MU), Damping coefficient (key: DAMP), thermal Conductivity (keys: KXX, KYY, KZZ), Resistivity (keys: RSVX, RSVY, RSVZ), Specific heat in constant volume (key: C), Film coefficient (key: HF), Viscosity (key: VISC), Emissivity (key: EMIS). + Inputs: + properties_name [string, vector] + materials [property_field]: Property field that contains a material id per element. + streams_container [streams_container] + data_sources [data_sources] + Outputs: + properties_value [fields_container] + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 52-54 + +To extract the Young's modulus for element ID ``1``, first we need to get the +mat_id for EID ``1``. + +.. GENERATED FROM PYTHON SOURCE LINES 54-56 + +.. code-block:: default + + mat_id = mats.get_entity_data_by_id(1) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 57-58 + +And then use the mat_id get the material property. + +.. GENERATED FROM PYTHON SOURCE LINES 58-62 + +.. code-block:: default + + mat_prop.inputs.properties_name.connect("EX") + mat_field = mat_prop.outputs.properties_value.get_data()[0] + print(mat_field.get_entity_data_by_id(mat_id[0])) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [2.e+11] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 63-64 + +Extract Poisson's ratio for element ID ``1``. + +.. GENERATED FROM PYTHON SOURCE LINES 64-67 + +.. code-block:: default + + mat_prop.inputs.properties_name.connect("NUXY") + mat_field = mat_prop.outputs.properties_value.get_data()[0] + print(mat_field.get_entity_data_by_id(mat_id[0])) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [0.3] + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.029 seconds) + + +.. _sphx_glr_download_examples_00-basic_12-get_material_properties.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 12-get_material_properties.py <12-get_material_properties.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 12-get_material_properties.ipynb <12-get_material_properties.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/00-basic/12-get_material_properties_codeobj.pickle b/doc/source/examples/00-basic/12-get_material_properties_codeobj.pickle new file mode 100644 index 0000000000..48da1a4efb Binary files /dev/null and b/doc/source/examples/00-basic/12-get_material_properties_codeobj.pickle differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_00-basic_example_001.png b/doc/source/examples/00-basic/images/sphx_glr_00-basic_example_001.png new file mode 100644 index 0000000000..c2fb4bb3ae Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_00-basic_example_001.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_01-basic_operators_001.png b/doc/source/examples/00-basic/images/sphx_glr_01-basic_operators_001.png new file mode 100644 index 0000000000..4e097154bb Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_01-basic_operators_001.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_001.png b/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_001.png new file mode 100644 index 0000000000..b6d46f29a1 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_001.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_002.png b/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_002.png new file mode 100644 index 0000000000..73318dd4f7 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_002.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_003.png b/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_003.png new file mode 100644 index 0000000000..3fa15c18a6 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_003.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_004.png b/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_004.png new file mode 100644 index 0000000000..1da178683b Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_03-create_entities_004.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_001.png b/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_001.png new file mode 100644 index 0000000000..cdaf267bd6 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_001.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_002.png b/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_002.png new file mode 100644 index 0000000000..f93f0e1f7e Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_002.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_003.png b/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_003.png new file mode 100644 index 0000000000..154b630bcc Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_003.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_004.png b/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_004.png new file mode 100644 index 0000000000..6131517bf0 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_05-use_local_data_004.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_001.png b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_001.png new file mode 100644 index 0000000000..02ecd0e753 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_001.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_002.png b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_002.png new file mode 100644 index 0000000000..abd5f071fa Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_002.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_003.png b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_003.png new file mode 100644 index 0000000000..40c293dcba Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_003.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_004.png b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_004.png new file mode 100644 index 0000000000..c7ebbbbb17 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_004.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_005.png b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_005.png new file mode 100644 index 0000000000..f31e102bcc Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_005.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_006.png b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_006.png new file mode 100644 index 0000000000..b983eb8a36 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_07-use_result_helpers_006.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_001.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_001.png new file mode 100644 index 0000000000..02d1658f5e Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_001.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_002.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_002.png new file mode 100644 index 0000000000..2db22408db Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_002.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_003.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_003.png new file mode 100644 index 0000000000..ed41aaf13a Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_003.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_004.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_004.png new file mode 100644 index 0000000000..eab7c06ee7 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_004.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_005.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_005.png new file mode 100644 index 0000000000..b7a1739bdb Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_005.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_006.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_006.png new file mode 100644 index 0000000000..1d0ecb15b9 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_006.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_007.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_007.png new file mode 100644 index 0000000000..eab7c06ee7 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_007.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_008.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_008.png new file mode 100644 index 0000000000..0b32b5a170 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_008.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_009.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_009.png new file mode 100644 index 0000000000..f00e1a8481 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_009.png differ diff --git a/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_010.png b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_010.png new file mode 100644 index 0000000000..599d7f1661 Binary files /dev/null and b/doc/source/examples/00-basic/images/sphx_glr_09-results_over_space_subset_010.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_00-basic_example_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_00-basic_example_thumb.png new file mode 100644 index 0000000000..c651bfd4dd Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_00-basic_example_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_01-basic_operators_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_01-basic_operators_thumb.png new file mode 100644 index 0000000000..8ab433adb2 Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_01-basic_operators_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_02-basic_field_containers_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_02-basic_field_containers_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_02-basic_field_containers_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_03-create_entities_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_03-create_entities_thumb.png new file mode 100644 index 0000000000..54662dfe40 Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_03-create_entities_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_05-use_local_data_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_05-use_local_data_thumb.png new file mode 100644 index 0000000000..4e83f5d5b9 Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_05-use_local_data_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_07-use_result_helpers_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_07-use_result_helpers_thumb.png new file mode 100644 index 0000000000..1f112e14b6 Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_07-use_result_helpers_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_08-results_over_time_subset_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_08-results_over_time_subset_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_08-results_over_time_subset_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_09-results_over_space_subset_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_09-results_over_space_subset_thumb.png new file mode 100644 index 0000000000..08c1dbc66d Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_09-results_over_space_subset_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_10-math_operations_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_10-math_operations_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_10-math_operations_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_11-server_types_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_11-server_types_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_11-server_types_thumb.png differ diff --git a/doc/source/examples/00-basic/images/thumb/sphx_glr_12-get_material_properties_thumb.png b/doc/source/examples/00-basic/images/thumb/sphx_glr_12-get_material_properties_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/00-basic/images/thumb/sphx_glr_12-get_material_properties_thumb.png differ diff --git a/doc/source/examples/00-basic/index.rst b/doc/source/examples/00-basic/index.rst new file mode 100644 index 0000000000..aeec4a781d --- /dev/null +++ b/doc/source/examples/00-basic/index.rst @@ -0,0 +1,224 @@ + + +.. _sphx_glr_examples_00-basic: + +.. _basic-gallery: + +Basic DPF examples +================== +These examples explain the basic concepts of DPF. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_00-basic_example_thumb.png + :alt: Basic DPF-Core usage + + :ref:`sphx_glr_examples_00-basic_00-basic_example.py` + +.. raw:: html + +
Basic DPF-Core usage
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_01-basic_operators_thumb.png + :alt: Operators overview + + :ref:`sphx_glr_examples_00-basic_01-basic_operators.py` + +.. raw:: html + +
Operators overview
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_02-basic_field_containers_thumb.png + :alt: Field and field containers overview + + :ref:`sphx_glr_examples_00-basic_02-basic_field_containers.py` + +.. raw:: html + +
Field and field containers overview
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_03-create_entities_thumb.png + :alt: Create your own entities using DPF operators + + :ref:`sphx_glr_examples_00-basic_03-create_entities.py` + +.. raw:: html + +
Create your own entities using DPF operators
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_05-use_local_data_thumb.png + :alt: Bring a field's data locally to improve performance + + :ref:`sphx_glr_examples_00-basic_05-use_local_data.py` + +.. raw:: html + +
Bring a field's data locally to improve performance
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_07-use_result_helpers_thumb.png + :alt: Use result helpers to load custom data + + :ref:`sphx_glr_examples_00-basic_07-use_result_helpers.py` + +.. raw:: html + +
Use result helpers to load custom data
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_08-results_over_time_subset_thumb.png + :alt: Scope results over custom time domains + + :ref:`sphx_glr_examples_00-basic_08-results_over_time_subset.py` + +.. raw:: html + +
Scope results over custom time domains
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_09-results_over_space_subset_thumb.png + :alt: Scope results over custom space domains + + :ref:`sphx_glr_examples_00-basic_09-results_over_space_subset.py` + +.. raw:: html + +
Scope results over custom space domains
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_10-math_operations_thumb.png + :alt: Mathematical Operations + + :ref:`sphx_glr_examples_00-basic_10-math_operations.py` + +.. raw:: html + +
Mathematical Operations
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_11-server_types_thumb.png + :alt: Communicate in process or via gRPC + + :ref:`sphx_glr_examples_00-basic_11-server_types.py` + +.. raw:: html + +
Communicate in process or via gRPC
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_12-get_material_properties_thumb.png + :alt: Get material properties from the result file + + :ref:`sphx_glr_examples_00-basic_12-get_material_properties.py` + +.. raw:: html + +
Get material properties from the result file
+
+ + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /examples/00-basic/00-basic_example + /examples/00-basic/01-basic_operators + /examples/00-basic/02-basic_field_containers + /examples/00-basic/03-create_entities + /examples/00-basic/05-use_local_data + /examples/00-basic/07-use_result_helpers + /examples/00-basic/08-results_over_time_subset + /examples/00-basic/09-results_over_space_subset + /examples/00-basic/10-math_operations + /examples/00-basic/11-server_types + /examples/00-basic/12-get_material_properties + diff --git a/doc/source/examples/00-basic/sg_execution_times.rst b/doc/source/examples/00-basic/sg_execution_times.rst new file mode 100644 index 0000000000..bd4f8d7365 --- /dev/null +++ b/doc/source/examples/00-basic/sg_execution_times.rst @@ -0,0 +1,32 @@ + +:orphan: + +.. _sphx_glr_examples_00-basic_sg_execution_times: + +Computation times +================= +**00:06.088** total execution time for **examples_00-basic** files: + ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_11-server_types.py` (``11-server_types.py``) | 00:06.058 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_12-get_material_properties.py` (``12-get_material_properties.py``) | 00:00.029 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_00-basic_example.py` (``00-basic_example.py``) | 00:00.000 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_01-basic_operators.py` (``01-basic_operators.py``) | 00:00.000 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_02-basic_field_containers.py` (``02-basic_field_containers.py``) | 00:00.000 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_03-create_entities.py` (``03-create_entities.py``) | 00:00.000 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_05-use_local_data.py` (``05-use_local_data.py``) | 00:00.000 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_07-use_result_helpers.py` (``07-use_result_helpers.py``) | 00:00.000 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_08-results_over_time_subset.py` (``08-results_over_time_subset.py``) | 00:00.000 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_09-results_over_space_subset.py` (``09-results_over_space_subset.py``) | 00:00.000 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_00-basic_10-math_operations.py` (``10-math_operations.py``) | 00:00.000 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ diff --git a/doc/source/examples/01-transient_analyses/00-basic_transient.ipynb b/doc/source/examples/01-transient_analyses/00-basic_transient.ipynb new file mode 100644 index 0000000000..6a9e7afc5a --- /dev/null +++ b/doc/source/examples/01-transient_analyses/00-basic_transient.ipynb @@ -0,0 +1,234 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Transient analysis result example {#ref_basic_transient}\r\n\r\nThis example shows how to postprocess a transient result and visualize\r\nthe outputs.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import the necessary modules\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Download the transient result example. This example is not included in\r\nDPF-Core by default to speed up the installation. Downloading this\r\nexample should take only a few seconds.\r\n\r\nNext, create the model and display the state of the result. This\r\ntransient result file contains several individual results, each at a\r\ndifferent timestamp.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "transient = examples.download_transient_result()\nmodel = dpf.Model(transient)\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the timestamps for each substep as a numpy array:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "tf = model.metadata.time_freq_support\nprint(tf.time_frequencies.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Obtain minimum and maximum displacements for all results\r\n\r\nCreate a displacement operator and set its time scoping request to the\r\nentire time frequency support:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement()\ntimeids = range(1, tf.n_sets + 1) # Must use 1-based indexing.\ndisp.inputs.time_scoping(timeids)\n\n# Chain the displacement operator with ``norm`` and ``min_max`` operators.\nmin_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp))\n\nmin_disp = min_max_op.outputs.field_min()\nmax_disp = min_max_op.outputs.field_max()\nprint(max_disp.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the minimum and maximum displacements over time:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "tdata = tf.time_frequencies.data\nplt.plot(tdata, max_disp.data, \"r\", label=\"Max\")\nplt.plot(tdata, min_disp.data, \"b\", label=\"Min\")\nplt.xlabel(\"Time (s)\")\nplt.ylabel(\"Displacement (m)\")\nplt.legend()\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the minimum and maximum displacements over time for the X\r\ncomponent.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp_z = disp.Z()\ndisp_z.inputs.time_scoping(timeids)\nmin_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_z))\n\nmin_disp_z = min_max_op.outputs.field_min()\nmax_disp_z = min_max_op.outputs.field_max()\n\ntdata = tf.time_frequencies.data\nplt.plot(tdata, max_disp_z.data, \"r\", label=\"Max\")\nplt.plot(tdata, min_disp_z.data, \"b\", label=\"Min\")\nplt.xlabel(\"Time (s)\")\nplt.ylabel(\"X Displacement (m)\")\nplt.legend()\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Postprocessing stress\r\n\r\nCreate an equivalent (von Mises) stress operator and set its time\r\nscoping to the entire time frequency support:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Component stress operator (stress)\nstress = model.results.stress()\n\n# Equivalent stress operator\neqv = stress.eqv()\neqv.inputs.time_scoping(timeids)\n\n# Connect to the min_max operator and return the minimum and maximum\n# fields.\nmin_max_eqv = ops.min_max.min_max_fc(eqv)\neqv_min = min_max_eqv.outputs.field_min()\neqv_max = min_max_eqv.outputs.field_max()\n\nprint(eqv_min)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the maximum stress over time:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.plot(tdata, eqv_min.data, \"b\", label=\"Minimum\")\nplt.plot(tdata, eqv_max.data, \"r\", label=\"Maximum\")\nplt.xlabel(\"Time (s)\")\nplt.ylabel(\"Equivalent Stress (Pa)\")\nplt.legend()\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Scoping and stress field coordinates\r\n\r\nThe scoping of the stress field can be used to extract the coordinates\r\nused for each result:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Extract a single field from the equivalent stress operator.\nfield = eqv.outputs.fields_container()[28]\n\n# Print the first node IDs from the field.\nprint(field.scoping.ids[:10])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, these node IDs are not in order. Additionally, there may\r\nbe fewer entries in the field than nodes in the model. For example,\r\nstresses are not computed at mid-side nodes.\r\n\r\nTo extract the coordinates for these node IDs, load the mesh from the\r\nmodel and then extract a coordinate for each node index.\r\n\r\nHere is an inefficient way of getting the coordinates as each individual\r\nrequest must be sent to the DPF service:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Load the mesh from the model.\nmeshed_region = model.metadata.meshed_region\n\n# Print the first 10 coordinates for the field.\nnode_ids = field.scoping.ids\nfor node_id in node_ids[:10]:\n # Fetch each individual node by node ID.\n node_coord = meshed_region.nodes.node_by_id(node_id).coordinates\n print(f\"Node ID {node_id} : %8.5f, %8.5f, %8.5f\" % tuple(node_coord))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Rather than individually querying for each node coordinate of the field,\r\nyou can use the\r\n`map_scoping `{.interpreted-text\r\nrole=\"func\"} to remap the field data to match the order of the nodes in\r\nthe meshed region.\r\n\r\nObtain the indices needed to get the data from `field.data` to match the\r\norder of nodes in the mesh:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "nodes = meshed_region.nodes\nind, mask = nodes.map_scoping(field.scoping)\n\n# Show that the order of the remapped node scoping matches the field scoping.\nprint(\"Scoping matches:\", np.allclose(np.array(nodes.scoping.ids)[ind], field.scoping.ids))\n\n# Now plot the von Mises stress relative to the Z coordinates.\nz_coord = nodes.coordinates_field.data[ind, 2]\n\nplt.plot(z_coord, field.data, \".\")\nplt.xlabel(\"Z Coordinate (m)\")\nplt.ylabel(\"Equivalent Stress (Pa)\")\nplt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/01-transient_analyses/00-basic_transient.py b/doc/source/examples/01-transient_analyses/00-basic_transient.py new file mode 100644 index 0000000000..c1fc3e5e4a --- /dev/null +++ b/doc/source/examples/01-transient_analyses/00-basic_transient.py @@ -0,0 +1,166 @@ +# noqa: D400 +""" +.. _ref_basic_transient: + +Transient analysis result example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to postprocess a transient result and +visualize the outputs. + +""" +# Import the necessary modules +import matplotlib.pyplot as plt +import numpy as np + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + +############################################################################### +# Download the transient result example. This example is +# not included in DPF-Core by default to speed up the installation. +# Downloading this example should take only a few seconds. +# +# Next, create the model and display the state of the result. This transient +# result file contains several individual results, each at a different timestamp. + +transient = examples.download_transient_result() +model = dpf.Model(transient) +print(model) + +############################################################################### +# Get the timestamps for each substep as a numpy array: +tf = model.metadata.time_freq_support +print(tf.time_frequencies.data) + +############################################################################### +# Obtain minimum and maximum displacements for all results +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a displacement operator and set its time scoping request to +# the entire time frequency support: +disp = model.results.displacement() +timeids = range(1, tf.n_sets + 1) # Must use 1-based indexing. +disp.inputs.time_scoping(timeids) + +# Chain the displacement operator with ``norm`` and ``min_max`` operators. +min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp)) + +min_disp = min_max_op.outputs.field_min() +max_disp = min_max_op.outputs.field_max() +print(max_disp.data) + +############################################################################### +# Plot the minimum and maximum displacements over time: + +tdata = tf.time_frequencies.data +plt.plot(tdata, max_disp.data, "r", label="Max") +plt.plot(tdata, min_disp.data, "b", label="Min") +plt.xlabel("Time (s)") +plt.ylabel("Displacement (m)") +plt.legend() +plt.show() + +############################################################################### +# Plot the minimum and maximum displacements over time for the X +# component. +disp_z = disp.Z() +disp_z.inputs.time_scoping(timeids) +min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_z)) + +min_disp_z = min_max_op.outputs.field_min() +max_disp_z = min_max_op.outputs.field_max() + +tdata = tf.time_frequencies.data +plt.plot(tdata, max_disp_z.data, "r", label="Max") +plt.plot(tdata, min_disp_z.data, "b", label="Min") +plt.xlabel("Time (s)") +plt.ylabel("X Displacement (m)") +plt.legend() +plt.show() + +############################################################################### +# Postprocessing stress +# ~~~~~~~~~~~~~~~~~~~~~ +# Create an equivalent (von Mises) stress operator and set its time +# scoping to the entire time frequency support: + +# Component stress operator (stress) +stress = model.results.stress() + +# Equivalent stress operator +eqv = stress.eqv() +eqv.inputs.time_scoping(timeids) + +# Connect to the min_max operator and return the minimum and maximum +# fields. +min_max_eqv = ops.min_max.min_max_fc(eqv) +eqv_min = min_max_eqv.outputs.field_min() +eqv_max = min_max_eqv.outputs.field_max() + +print(eqv_min) + +############################################################################### +# Plot the maximum stress over time: + +plt.plot(tdata, eqv_min.data, "b", label="Minimum") +plt.plot(tdata, eqv_max.data, "r", label="Maximum") +plt.xlabel("Time (s)") +plt.ylabel("Equivalent Stress (Pa)") +plt.legend() +plt.show() + +############################################################################### +# Scoping and stress field coordinates +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The scoping of the stress field can be used to extract the +# coordinates used for each result: + +# Extract a single field from the equivalent stress operator. +field = eqv.outputs.fields_container()[28] + +# Print the first node IDs from the field. +print(field.scoping.ids[:10]) + +################################################################################ +# As you can see, these node IDs are not in order. Additionally, +# there may be fewer entries in the field than nodes in the model. For +# example, stresses are not computed at mid-side nodes. +# +# To extract the coordinates for these node IDs, load the mesh from +# the model and then extract a coordinate for each node index. +# +# Here is an inefficient way of getting the coordinates as each +# individual request must be sent to the DPF service: + +# Load the mesh from the model. +meshed_region = model.metadata.meshed_region + +# Print the first 10 coordinates for the field. +node_ids = field.scoping.ids +for node_id in node_ids[:10]: + # Fetch each individual node by node ID. + node_coord = meshed_region.nodes.node_by_id(node_id).coordinates + print(f"Node ID {node_id} : %8.5f, %8.5f, %8.5f" % tuple(node_coord)) + +############################################################################### +# Rather than individually querying for each node coordinate of the +# field, you can use the :func:`map_scoping ` +# to remap the field data to match the order of the nodes in the meshed region. +# +# Obtain the indices needed to get the data from ``field.data`` to match +# the order of nodes in the mesh: + +nodes = meshed_region.nodes +ind, mask = nodes.map_scoping(field.scoping) + +# Show that the order of the remapped node scoping matches the field scoping. +print("Scoping matches:", np.allclose(np.array(nodes.scoping.ids)[ind], field.scoping.ids)) + +# Now plot the von Mises stress relative to the Z coordinates. +z_coord = nodes.coordinates_field.data[ind, 2] + +plt.plot(z_coord, field.data, ".") +plt.xlabel("Z Coordinate (m)") +plt.ylabel("Equivalent Stress (Pa)") +plt.show() diff --git a/doc/source/examples/01-transient_analyses/00-basic_transient.py.md5 b/doc/source/examples/01-transient_analyses/00-basic_transient.py.md5 new file mode 100644 index 0000000000..d25dd9f8ba --- /dev/null +++ b/doc/source/examples/01-transient_analyses/00-basic_transient.py.md5 @@ -0,0 +1 @@ +47877ed6b17508275c65cbca0abe4743 \ No newline at end of file diff --git a/doc/source/examples/01-transient_analyses/00-basic_transient.rst b/doc/source/examples/01-transient_analyses/00-basic_transient.rst new file mode 100644 index 0000000000..38715e8162 --- /dev/null +++ b/doc/source/examples/01-transient_analyses/00-basic_transient.rst @@ -0,0 +1,516 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\01-transient_analyses\00-basic_transient.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_01-transient_analyses_00-basic_transient.py: + + +.. _ref_basic_transient: + +Transient analysis result example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to postprocess a transient result and +visualize the outputs. + +.. GENERATED FROM PYTHON SOURCE LINES 12-20 + +.. code-block:: default + + # Import the necessary modules + import matplotlib.pyplot as plt + import numpy as np + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 21-27 + +Download the transient result example. This example is +not included in DPF-Core by default to speed up the installation. +Downloading this example should take only a few seconds. + +Next, create the model and display the state of the result. This transient +result file contains several individual results, each at a different timestamp. + +.. GENERATED FROM PYTHON SOURCE LINES 27-32 + +.. code-block:: default + + + transient = examples.download_transient_result() + model = dpf.Model(transient) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - element_nodal_forces: ElementalNodal Element nodal Forces + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - thermal_strain: ElementalNodal Thermal Strains + - thermal_strains_eqv: ElementalNodal Thermal Strains eqv + - swelling_strains: ElementalNodal Swelling Strains + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 3820 nodes + 789 elements + Unit: m + With solid (3D) elements, shell (2D) elements, shell (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 35 + Cumulative Time (s) LoadStep Substep + 1 0,000000 1 1 + 2 0,019975 1 2 + 3 0,039975 1 3 + 4 0,059975 1 4 + 5 0,079975 1 5 + 6 0,099975 1 6 + 7 0,119975 1 7 + 8 0,139975 1 8 + 9 0,159975 1 9 + 10 0,179975 1 10 + 11 0,199975 1 11 + 12 0,218975 1 12 + 13 0,238975 1 13 + 14 0,258975 1 14 + 15 0,278975 1 15 + 16 0,298975 1 16 + 17 0,318975 1 17 + 18 0,338975 1 18 + 19 0,358975 1 19 + 20 0,378975 1 20 + 21 0,398975 1 21 + 22 0,417975 1 22 + 23 0,437975 1 23 + 24 0,457975 1 24 + 25 0,477975 1 25 + 26 0,497975 1 26 + 27 0,517975 1 27 + 28 0,537550 1 28 + 29 0,557253 1 29 + 30 0,577118 1 30 + 31 0,597021 1 31 + 32 0,616946 1 32 + 33 0,636833 1 33 + 34 0,656735 1 34 + 35 0,676628 1 35 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 33-34 + +Get the timestamps for each substep as a numpy array: + +.. GENERATED FROM PYTHON SOURCE LINES 34-37 + +.. code-block:: default + + tf = model.metadata.time_freq_support + print(tf.time_frequencies.data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [0. 0.019975 0.039975 0.059975 0.079975 0.099975 + 0.119975 0.139975 0.159975 0.179975 0.199975 0.218975 + 0.238975 0.258975 0.278975 0.298975 0.318975 0.338975 + 0.358975 0.378975 0.398975 0.417975 0.437975 0.457975 + 0.477975 0.497975 0.517975 0.53754972 0.55725277 0.57711786 + 0.59702054 0.61694639 0.63683347 0.65673452 0.67662783] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 38-42 + +Obtain minimum and maximum displacements for all results +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create a displacement operator and set its time scoping request to +the entire time frequency support: + +.. GENERATED FROM PYTHON SOURCE LINES 42-53 + +.. code-block:: default + + disp = model.results.displacement() + timeids = range(1, tf.n_sets + 1) # Must use 1-based indexing. + disp.inputs.time_scoping(timeids) + + # Chain the displacement operator with ``norm`` and ``min_max`` operators. + min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp)) + + min_disp = min_max_op.outputs.field_min() + max_disp = min_max_op.outputs.field_max() + print(max_disp.data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [0. 0.00062674 0.0025094 0.00564185 0.00999992 0.01552154 + 0.02207871 0.02944459 0.03725894 0.04499722 0.05195353 0.05703912 + 0.05982844 0.05897617 0.05358419 0.04310436 0.02759782 0.00798431 + 0.0137951 0.03478255 0.05130461 0.05942392 0.05715204 0.04272116 + 0.01787116 0.01244994 0.04062977 0.05913066 0.06042056 0.0418829 + 0.01201879 0.03526532 0.05950852 0.06077103 0.03733769] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 54-55 + +Plot the minimum and maximum displacements over time: + +.. GENERATED FROM PYTHON SOURCE LINES 55-64 + +.. code-block:: default + + + tdata = tf.time_frequencies.data + plt.plot(tdata, max_disp.data, "r", label="Max") + plt.plot(tdata, min_disp.data, "b", label="Min") + plt.xlabel("Time (s)") + plt.ylabel("Displacement (m)") + plt.legend() + plt.show() + + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_001.png + :alt: 00 basic transient + :srcset: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 65-67 + +Plot the minimum and maximum displacements over time for the X +component. + +.. GENERATED FROM PYTHON SOURCE LINES 67-82 + +.. code-block:: default + + disp_z = disp.Z() + disp_z.inputs.time_scoping(timeids) + min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_z)) + + min_disp_z = min_max_op.outputs.field_min() + max_disp_z = min_max_op.outputs.field_max() + + tdata = tf.time_frequencies.data + plt.plot(tdata, max_disp_z.data, "r", label="Max") + plt.plot(tdata, min_disp_z.data, "b", label="Min") + plt.xlabel("Time (s)") + plt.ylabel("X Displacement (m)") + plt.legend() + plt.show() + + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_002.png + :alt: 00 basic transient + :srcset: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_002.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 83-87 + +Postprocessing stress +~~~~~~~~~~~~~~~~~~~~~ +Create an equivalent (von Mises) stress operator and set its time +scoping to the entire time frequency support: + +.. GENERATED FROM PYTHON SOURCE LINES 87-103 + +.. code-block:: default + + + # Component stress operator (stress) + stress = model.results.stress() + + # Equivalent stress operator + eqv = stress.eqv() + eqv.inputs.time_scoping(timeids) + + # Connect to the min_max operator and return the minimum and maximum + # fields. + min_max_eqv = ops.min_max.min_max_fc(eqv) + eqv_min = min_max_eqv.outputs.field_min() + eqv_max = min_max_eqv.outputs.field_max() + + print(eqv_min) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF stress_0,s_eqv Field + Location: Nodal + Unit: Pa + 35 entities + Data: 1 components and 35 elementary data + + IDs data(Pa) + ------------ ---------- + 0 0.000000e+00 + + 1 6.215362e+02 + + 2 1.017913e+03 + + ... + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 104-105 + +Plot the maximum stress over time: + +.. GENERATED FROM PYTHON SOURCE LINES 105-113 + +.. code-block:: default + + + plt.plot(tdata, eqv_min.data, "b", label="Minimum") + plt.plot(tdata, eqv_max.data, "r", label="Maximum") + plt.xlabel("Time (s)") + plt.ylabel("Equivalent Stress (Pa)") + plt.legend() + plt.show() + + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_003.png + :alt: 00 basic transient + :srcset: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_003.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 114-118 + +Scoping and stress field coordinates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The scoping of the stress field can be used to extract the +coordinates used for each result: + +.. GENERATED FROM PYTHON SOURCE LINES 118-125 + +.. code-block:: default + + + # Extract a single field from the equivalent stress operator. + field = eqv.outputs.fields_container()[28] + + # Print the first node IDs from the field. + print(field.scoping.ids[:10]) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [508 509 909 910 524 525 534 533 513 908] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 126-135 + +As you can see, these node IDs are not in order. Additionally, +there may be fewer entries in the field than nodes in the model. For +example, stresses are not computed at mid-side nodes. + +To extract the coordinates for these node IDs, load the mesh from +the model and then extract a coordinate for each node index. + +Here is an inefficient way of getting the coordinates as each +individual request must be sent to the DPF service: + +.. GENERATED FROM PYTHON SOURCE LINES 135-146 + +.. code-block:: default + + + # Load the mesh from the model. + meshed_region = model.metadata.meshed_region + + # Print the first 10 coordinates for the field. + node_ids = field.scoping.ids + for node_id in node_ids[:10]: + # Fetch each individual node by node ID. + node_coord = meshed_region.nodes.node_by_id(node_id).coordinates + print(f"Node ID {node_id} : %8.5f, %8.5f, %8.5f" % tuple(node_coord)) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Node ID 508 : -0.01251, 0.01403, 0.02310 + Node ID 509 : -0.01378, 0.00218, 0.02310 + Node ID 909 : -0.03000, 0.00000, 0.02310 + Node ID 910 : -0.02121, 0.02121, 0.02310 + Node ID 524 : -0.01251, 0.01403, 0.00000 + Node ID 525 : -0.01378, 0.00218, 0.00000 + Node ID 534 : -0.03000, 0.00000, 0.00000 + Node ID 533 : -0.02121, 0.02121, 0.00000 + Node ID 513 : -0.00891, -0.00952, 0.02310 + Node ID 908 : -0.02121, -0.02121, 0.02310 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 147-153 + +Rather than individually querying for each node coordinate of the +field, you can use the :func:`map_scoping ` +to remap the field data to match the order of the nodes in the meshed region. + +Obtain the indices needed to get the data from ``field.data`` to match +the order of nodes in the mesh: + +.. GENERATED FROM PYTHON SOURCE LINES 153-167 + +.. code-block:: default + + + nodes = meshed_region.nodes + ind, mask = nodes.map_scoping(field.scoping) + + # Show that the order of the remapped node scoping matches the field scoping. + print("Scoping matches:", np.allclose(np.array(nodes.scoping.ids)[ind], field.scoping.ids)) + + # Now plot the von Mises stress relative to the Z coordinates. + z_coord = nodes.coordinates_field.data[ind, 2] + + plt.plot(z_coord, field.data, ".") + plt.xlabel("Z Coordinate (m)") + plt.ylabel("Equivalent Stress (Pa)") + plt.show() + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_004.png + :alt: 00 basic transient + :srcset: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_004.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Scoping matches: True + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.703 seconds) + + +.. _sphx_glr_download_examples_01-transient_analyses_00-basic_transient.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 00-basic_transient.py <00-basic_transient.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 00-basic_transient.ipynb <00-basic_transient.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/01-transient_analyses/00-basic_transient_codeobj.pickle b/doc/source/examples/01-transient_analyses/00-basic_transient_codeobj.pickle new file mode 100644 index 0000000000..1c8afd4964 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/00-basic_transient_codeobj.pickle differ diff --git a/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.ipynb b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.ipynb new file mode 100644 index 0000000000..71774cfee4 --- /dev/null +++ b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Choose a time scoping for a transient analysis {#ref_transient_easy_time_scoping}\r\n\r\nThis example shows how to use a model\\'s result to choose a time\r\nscoping.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the model and display the state of the result. This transient\r\nresult file contains several individual results, each at a different\r\ntimes.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "transient = examples.find_msup_transient()\nmodel = dpf.Model(transient)\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Obtain minimum and maximum displacements at all times\r\n\r\nCreate a displacement operator and set its time scoping request to the\r\nentire time frequency support:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement\ndisp_op = disp.on_all_time_freqs()\n\n# Chain the displacement operator with norm and min_max operators.\nmin_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_op))\n\nmin_disp = min_max_op.outputs.field_min()\nmax_disp = min_max_op.outputs.field_max()\nprint(max_disp.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the minimum and maximum displacements over time:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "tdata = model.metadata.time_freq_support.time_frequencies.data\nplt.plot(tdata, max_disp.data, \"r\", label=\"Max\")\nplt.plot(tdata, min_disp.data, \"b\", label=\"Min\")\nplt.xlabel(\"Time (s)\")\nplt.ylabel(\"Displacement (m)\")\nplt.legend()\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use time extrapolation\r\n\r\nA local maximum can be seen on the plot between 0.05 and 0.075 seconds.\r\nDisplacement is evaluated every 0.0005 seconds in this range to draw a\r\nnicer plot on this range.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "offset = 0.0005\ntime_scoping = [0.05 + offset * i for i in range(0, int((0.08 - 0.05) / offset))]\nprint(time_scoping)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a displacement operator and set its time scoping request:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement\ndisp_op = disp.on_time_scoping(time_scoping)()\n\n# Chain the displacement operator with norm and min_max operators.\nmin_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_op))\n\nmin_disp = min_max_op.outputs.field_min()\nmax_disp = min_max_op.outputs.field_max()\nprint(max_disp.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the minimum and maximum displacements over time:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.plot(time_scoping, max_disp.data, \"rx\", label=\"Max\")\nplt.xlabel(\"Time (s)\")\nplt.ylabel(\"Displacement (m)\")\nplt.legend()\nplt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.py b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.py new file mode 100644 index 0000000000..71ad0c9603 --- /dev/null +++ b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.py @@ -0,0 +1,81 @@ +# noqa: D400 +""" +.. _ref_transient_easy_time_scoping: + +Choose a time scoping for a transient analysis +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to use a model's result to choose a time scoping. + +""" +import matplotlib.pyplot as plt + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + +############################################################################### +# Create the model and display the state of the result. This transient result +# file contains several individual results, each at a different times. + +transient = examples.find_msup_transient() +model = dpf.Model(transient) +print(model) + +############################################################################### +# Obtain minimum and maximum displacements at all times +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a displacement operator and set its time scoping request to +# the entire time frequency support: +disp = model.results.displacement +disp_op = disp.on_all_time_freqs() + +# Chain the displacement operator with norm and min_max operators. +min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_op)) + +min_disp = min_max_op.outputs.field_min() +max_disp = min_max_op.outputs.field_max() +print(max_disp.data) + +############################################################################### +# Plot the minimum and maximum displacements over time: + +tdata = model.metadata.time_freq_support.time_frequencies.data +plt.plot(tdata, max_disp.data, "r", label="Max") +plt.plot(tdata, min_disp.data, "b", label="Min") +plt.xlabel("Time (s)") +plt.ylabel("Displacement (m)") +plt.legend() +plt.show() + +############################################################################### +# Use time extrapolation +# ~~~~~~~~~~~~~~~~~~~~~~~ +# A local maximum can be seen on the plot between 0.05 and 0.075 seconds. +# Displacement is evaluated every 0.0005 seconds in this range +# to draw a nicer plot on this range. + +offset = 0.0005 +time_scoping = [0.05 + offset * i for i in range(0, int((0.08 - 0.05) / offset))] +print(time_scoping) + +############################################################################### +# Create a displacement operator and set its time scoping request: +disp = model.results.displacement +disp_op = disp.on_time_scoping(time_scoping)() + +# Chain the displacement operator with norm and min_max operators. +min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_op)) + +min_disp = min_max_op.outputs.field_min() +max_disp = min_max_op.outputs.field_max() +print(max_disp.data) + +############################################################################### +# Plot the minimum and maximum displacements over time: + +plt.plot(time_scoping, max_disp.data, "rx", label="Max") +plt.xlabel("Time (s)") +plt.ylabel("Displacement (m)") +plt.legend() +plt.show() diff --git a/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.py.md5 b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.py.md5 new file mode 100644 index 0000000000..be2356338c --- /dev/null +++ b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.py.md5 @@ -0,0 +1 @@ +219cc3c5220798f5e74d5b81e0c2efe3 \ No newline at end of file diff --git a/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.rst b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.rst new file mode 100644 index 0000000000..8d0bb99fbc --- /dev/null +++ b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping.rst @@ -0,0 +1,309 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\01-transient_analyses\01-transient_easy_time_scoping.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_01-transient_analyses_01-transient_easy_time_scoping.py: + + +.. _ref_transient_easy_time_scoping: + +Choose a time scoping for a transient analysis +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to use a model's result to choose a time scoping. + +.. GENERATED FROM PYTHON SOURCE LINES 11-17 + +.. code-block:: default + + import matplotlib.pyplot as plt + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 18-20 + +Create the model and display the state of the result. This transient result +file contains several individual results, each at a different times. + +.. GENERATED FROM PYTHON SOURCE LINES 20-25 + +.. code-block:: default + + + transient = examples.find_msup_transient() + model = dpf.Model(transient) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Transient analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - velocity: Nodal Velocity + - acceleration: Nodal Acceleration + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + ------------------------------ + DPF Meshed Region: + 393 nodes + 40 elements + Unit: m + With solid (3D) elements + ------------------------------ + 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 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 26-30 + +Obtain minimum and maximum displacements at all times +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create a displacement operator and set its time scoping request to +the entire time frequency support: + +.. GENERATED FROM PYTHON SOURCE LINES 30-40 + +.. code-block:: default + + disp = model.results.displacement + disp_op = disp.on_all_time_freqs() + + # Chain the displacement operator with norm and min_max operators. + min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_op)) + + min_disp = min_max_op.outputs.field_min() + max_disp = min_max_op.outputs.field_max() + print(max_disp.data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [0.00031517 0.00163154 0.00409388 0.00693318 0.00939617 0.01105343 + 0.01135235 0.01016139 0.00796552 0.00521109 0.00250834 0.00070916 + 0.00019964 0.00098568 0.0030466 0.00581779 0.00846792 0.01049698 + 0.0113754 0.01074555] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 41-42 + +Plot the minimum and maximum displacements over time: + +.. GENERATED FROM PYTHON SOURCE LINES 42-51 + +.. code-block:: default + + + tdata = model.metadata.time_freq_support.time_frequencies.data + plt.plot(tdata, max_disp.data, "r", label="Max") + plt.plot(tdata, min_disp.data, "b", label="Min") + plt.xlabel("Time (s)") + plt.ylabel("Displacement (m)") + plt.legend() + plt.show() + + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_001.png + :alt: 01 transient easy time scoping + :srcset: /examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 52-57 + +Use time extrapolation +~~~~~~~~~~~~~~~~~~~~~~~ +A local maximum can be seen on the plot between 0.05 and 0.075 seconds. +Displacement is evaluated every 0.0005 seconds in this range +to draw a nicer plot on this range. + +.. GENERATED FROM PYTHON SOURCE LINES 57-62 + +.. code-block:: default + + + offset = 0.0005 + time_scoping = [0.05 + offset * i for i in range(0, int((0.08 - 0.05) / offset))] + print(time_scoping) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [0.05, 0.0505, 0.051000000000000004, 0.051500000000000004, 0.052000000000000005, 0.052500000000000005, 0.053000000000000005, 0.053500000000000006, 0.054000000000000006, 0.05450000000000001, 0.055, 0.0555, 0.056, 0.0565, 0.057, 0.0575, 0.058, 0.0585, 0.059000000000000004, 0.059500000000000004, 0.060000000000000005, 0.060500000000000005, 0.061, 0.0615, 0.062, 0.0625, 0.063, 0.0635, 0.064, 0.0645, 0.065, 0.0655, 0.066, 0.0665, 0.067, 0.0675, 0.068, 0.0685, 0.069, 0.0695, 0.07, 0.07050000000000001, 0.07100000000000001, 0.07150000000000001, 0.07200000000000001, 0.07250000000000001, 0.07300000000000001, 0.07350000000000001, 0.07400000000000001, 0.07450000000000001, 0.07500000000000001, 0.07550000000000001, 0.07600000000000001, 0.0765, 0.077, 0.0775, 0.078, 0.0785, 0.079, 0.0795] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 63-64 + +Create a displacement operator and set its time scoping request: + +.. GENERATED FROM PYTHON SOURCE LINES 64-74 + +.. code-block:: default + + disp = model.results.displacement + disp_op = disp.on_time_scoping(time_scoping)() + + # Chain the displacement operator with norm and min_max operators. + min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_op)) + + min_disp = min_max_op.outputs.field_min() + max_disp = min_max_op.outputs.field_max() + print(max_disp.data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [0.00939617 0.00947903 0.0095619 0.00964476 0.00972762 0.00981049 + 0.00989335 0.00997621 0.01005908 0.01014194 0.0102248 0.01030766 + 0.01039053 0.01047339 0.01055625 0.01063912 0.01072198 0.01080484 + 0.01088771 0.01097057 0.01105343 0.01106838 0.01108332 0.01109827 + 0.01111322 0.01112816 0.01114311 0.01115805 0.011173 0.01118794 + 0.01120289 0.01121784 0.01123278 0.01124773 0.01126267 0.01127762 + 0.01129256 0.01130751 0.01132245 0.0113374 0.01135235 0.0112928 + 0.01123325 0.0111737 0.01111415 0.01105461 0.01099506 0.01093551 + 0.01087596 0.01081642 0.01075687 0.01069732 0.01063777 0.01057822 + 0.01051868 0.01045913 0.01039958 0.01034003 0.01028049 0.01022094] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 75-76 + +Plot the minimum and maximum displacements over time: + +.. GENERATED FROM PYTHON SOURCE LINES 76-82 + +.. code-block:: default + + + plt.plot(time_scoping, max_disp.data, "rx", label="Max") + plt.xlabel("Time (s)") + plt.ylabel("Displacement (m)") + plt.legend() + plt.show() + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_002.png + :alt: 01 transient easy time scoping + :srcset: /examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_002.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.268 seconds) + + +.. _sphx_glr_download_examples_01-transient_analyses_01-transient_easy_time_scoping.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 01-transient_easy_time_scoping.py <01-transient_easy_time_scoping.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 01-transient_easy_time_scoping.ipynb <01-transient_easy_time_scoping.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping_codeobj.pickle b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping_codeobj.pickle new file mode 100644 index 0000000000..c7a599a0e2 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/01-transient_easy_time_scoping_codeobj.pickle differ diff --git a/doc/source/examples/01-transient_analyses/02-lsdyna_operators.ipynb b/doc/source/examples/01-transient_analyses/02-lsdyna_operators.ipynb new file mode 100644 index 0000000000..fd439aeeb0 --- /dev/null +++ b/doc/source/examples/01-transient_analyses/02-lsdyna_operators.ipynb @@ -0,0 +1,252 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Results extraction and analysis from LS-DYNA sources {#lsdyna_operators}\r\n\r\nThis example provides an overview of the LS-DYNA results providers.\r\n\r\n::: note\r\n::: title\r\nNote\r\n:::\r\n\r\nThis example requires DPF 6.1 (ansys-dpf-server-2023-2-pre0) or above.\r\nFor more information, see `ref_compatibility`{.interpreted-text\r\nrole=\"ref\"}.\r\n:::\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# d3plot file results extraction\r\n\r\nCreate the model and print its contents. This LS-DYNA d3plot file\r\ncontains several individual results, each at different times. The d3plot\r\nfile does not contain information related to Units. In this case, as the\r\nsimulation was run through Mechanical, a file.actunits file is produced.\r\nIf this file is supplemented in the data_sources, the units will be\r\ncorrectly fetched for all resuls in the file as well as for the mesh.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "d3plot = examples.download_d3plot_beam()\nds = dpf.DataSources()\nds.set_result_file_path(d3plot[0], \"d3plot\")\nds.add_file_path(d3plot[3], \"actunits\")\nmodel = dpf.Model(ds)\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The model has solid (3D) elements and beam (1D) elements. Some of the\r\nresults only apply to one type of elements (such as the stress tensor\r\nfor solids, or the axial force for beams, for example).\r\n\r\nLet\\'s extract beam axial force for the last time step and plot it,\r\ndeforming the mesh according to the displacement field at the same time\r\nstep.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "N = model.results.beam_axial_force(time_scoping=[12]).eval()\nu = model.results.displacement(time_scoping=[12]).eval()\n\nsargs = dict(title=\"N\", fmt=\"%.2e\", title_font_size=30, label_font_size=20)\nN[0].plot(deform_by=u[0], scalar_bar_args=sargs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The axial force has only been computed for the beam elements (the bottom\r\nframe), whereas the top sphere, which is comprised by solid elements,\r\nhas only been deformed by the displacement field.\r\n\r\nPyDPF also allows you to animate the results in a FieldsContainer. Thus,\r\nif all time steps are extracted, an animation can be produced.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "N_all = model.results.beam_axial_force.on_all_time_freqs.eval()\nu_all = model.results.displacement.on_all_time_freqs.eval()\nN_all.animate(deform_by=u_all, save_as=\"falling_ball.gif\", scalar_bar_args=sargs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Some of the results are marked as global. They are not scoped over any\r\nmesh entity, but are global variables of the model.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "K = model.results.global_kinetic_energy().eval()\nprint(K)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Energy plots over time (the sphere was released with some initial\r\nvelocity).\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "U = model.results.global_internal_energy().eval()\nH = model.results.global_total_energy().eval()\n\nplt.plot(K.time_freq_support.time_frequencies.data, K[0].data, label=\"Kinetic\")\nplt.plot(U.time_freq_support.time_frequencies.data, U[0].data, label=\"Internal\")\nplt.plot(H.time_freq_support.time_frequencies.data, H[0].data, label=\"Total\")\nplt.xlabel(\"Time ({:s})\".format(K.time_freq_support.time_frequencies.unit))\nplt.ylabel(\"Energies ({:s})\".format(K[0].unit))\nplt.legend()\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# binout file results extraction\r\n\r\nCreate the model and dprint its contents. This LS-DYNA binout file\r\ncontains several branches (glstat, matsum and rcforc).\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "binout = examples.download_binout_matsum()\nds = dpf.DataSources()\nds.set_result_file_path(binout, \"binout\")\nmodel = dpf.Model(ds)\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case, the Unit System is not attached to the data_source, but it\r\ncan be directly assigned to the results. As we are employing the\r\ndpf.Model API, we only need to assign the Unit System once (the Model\r\nwill assign it for the rest of the results).\r\n\r\nResults from the matsum branch of the binout file are a FieldsContainer\r\non a LabelSpace comprised by part IDs. Extract part kinetic energy for\r\nall parts:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "PKE_op = model.results.part_kinetic_energy()\nPKE_op.inputs.unit_system.connect(dpf.unit_systems.solver_mks)\nPKE = PKE_op.eval()\nprint(PKE)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Extract part internal energy for only a selected number of parts.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "part_sco = dpf.Scoping(ids=[50, 1522], location=\"part\")\nPIE_op = model.results.part_internal_energy()\nPIE_op.inputs.entity_scoping.connect(part_sco)\nPIE = PIE_op.eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot part kinetic and internal energy for a selection of parts. In this\r\ncase, the TimeFreqSupport of the matsum branch does not have all the\r\ntime steps in the binout file. Thus, a rescoping operation is needed:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "rescope_op = dpf.operators.scoping.rescope()\nrescope_op.inputs.fields.connect(PKE.time_freq_support.time_frequencies)\nrescope_op.inputs.mesh_scoping.connect(PKE[0].scoping)\nt_field = rescope_op.outputs.fields_as_field()\nt_vals = t_field.data\n\nplt.plot(t_vals, PKE.get_field({\"part\": 50}).data, label=\"Kinetic, Part 50\")\nplt.plot(t_vals, PKE.get_field({\"part\": 1522}).data, label=\"Kinetic, Part 1522\")\nplt.plot(t_vals, PIE.get_field({\"part\": 50}).data, label=\"Internal, Part 50\")\nplt.plot(t_vals, PIE.get_field({\"part\": 1522}).data, label=\"Internal, Part 1522\")\nplt.xlabel(\"Time ({:s})\".format(t_field.unit))\nplt.ylabel(\"Energy ({:s})\".format(PIE.get_field({\"part\": 50}).unit))\nplt.legend()\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, results from the rcforc branch of the binout file are a\r\nFieldsContainer on a LabelSpace comprised by interface IDs. Extract\r\ninterface contact force for only one interface.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "interface_sco = dpf.Scoping(ids=[19], location=\"interface\")\nFC_op = model.results.interface_contact_force()\nFC_op.inputs.entity_scoping.connect(interface_sco)\nFC = FC_op.eval()\nprint(FC)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to interface, the FieldsContainer is scoped on idtype (0 for\r\nthe master side of the interface, 1 for the slave). Contact force is a\r\nvector, and the three components are available.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "rescope_op = dpf.operators.scoping.rescope()\nrescope_op.inputs.fields.connect(FC.time_freq_support.time_frequencies)\nrescope_op.inputs.mesh_scoping.connect(FC[0].scoping)\nt_field = rescope_op.outputs.fields_as_field()\nt_vals = t_field.data\n\nFX = FC.select_component(0)\nFY = FC.select_component(1)\nFZ = FC.select_component(2)\n\nplt.plot(t_vals, FX.get_field({\"interface\": 19, \"idtype\": 0}).data, label=\"FX, slave\")\nplt.plot(t_vals, FX.get_field({\"interface\": 19, \"idtype\": 1}).data, label=\"FX, master\")\nplt.plot(t_vals, FY.get_field({\"interface\": 19, \"idtype\": 0}).data, label=\"FY, slave\")\nplt.plot(t_vals, FY.get_field({\"interface\": 19, \"idtype\": 1}).data, label=\"FY, master\")\nplt.plot(t_vals, FZ.get_field({\"interface\": 19, \"idtype\": 0}).data, label=\"FZ, slave\")\nplt.plot(t_vals, FZ.get_field({\"interface\": 19, \"idtype\": 1}).data, label=\"FZ, master\")\nplt.xlabel(\"Time ({:s})\".format(t_field.unit))\nplt.xlim([0, 10])\nplt.ylabel(\"Contact Force ({:s})\".format(FX.get_field({\"interface\": 19, \"idtype\": 0}).unit))\nplt.legend()\nplt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/01-transient_analyses/02-lsdyna_operators.py b/doc/source/examples/01-transient_analyses/02-lsdyna_operators.py new file mode 100644 index 0000000000..972f83ce88 --- /dev/null +++ b/doc/source/examples/01-transient_analyses/02-lsdyna_operators.py @@ -0,0 +1,174 @@ +# noqa: D400 +""" +.. _lsdyna_operators: + +Results extraction and analysis from LS-DYNA sources +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example provides an overview of the LS-DYNA results providers. + +.. note:: + This example requires DPF 6.1 (ansys-dpf-server-2023-2-pre0) or above. + For more information, see :ref:`ref_compatibility`. + +""" + +import matplotlib.pyplot as plt +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# d3plot file results extraction +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create the model and print its contents. This LS-DYNA d3plot file contains +# several individual results, each at different times. The d3plot file does not +# contain information related to Units. In this case, as the simulation was run +# through Mechanical, a file.actunits file is produced. If this file is +# supplemented in the data_sources, the units will be correctly fetched for all +# resuls in the file as well as for the mesh. + +d3plot = examples.download_d3plot_beam() +ds = dpf.DataSources() +ds.set_result_file_path(d3plot[0], "d3plot") +ds.add_file_path(d3plot[3], "actunits") +model = dpf.Model(ds) +print(model) + +############################################################################### +# The model has solid (3D) elements and beam (1D) elements. Some of the results +# only apply to one type of elements (such as the stress tensor for solids, or +# the axial force for beams, for example). +# +# Let's extract beam axial force for the last time step and plot it, deforming +# the mesh according to the displacement field at the same time step. + +N = model.results.beam_axial_force(time_scoping=[12]).eval() +u = model.results.displacement(time_scoping=[12]).eval() + +sargs = dict(title="N", fmt="%.2e", title_font_size=30, label_font_size=20) +N[0].plot(deform_by=u[0], scalar_bar_args=sargs) + +############################################################################### +# The axial force has only been computed for the beam elements (the bottom +# frame), whereas the top sphere, which is comprised by solid elements, has +# only been deformed by the displacement field. +# +# PyDPF also allows you to animate the results in a FieldsContainer. Thus, if +# all time steps are extracted, an animation can be produced. + +N_all = model.results.beam_axial_force.on_all_time_freqs.eval() +u_all = model.results.displacement.on_all_time_freqs.eval() +N_all.animate(deform_by=u_all, save_as="falling_ball.gif", scalar_bar_args=sargs) + +############################################################################### +# Some of the results are marked as global. They are not scoped over any mesh +# entity, but are global variables of the model. + +K = model.results.global_kinetic_energy().eval() +print(K) + +############################################################################### +# Energy plots over time (the sphere was released with some initial velocity). + +U = model.results.global_internal_energy().eval() +H = model.results.global_total_energy().eval() + +plt.plot(K.time_freq_support.time_frequencies.data, K[0].data, label="Kinetic") +plt.plot(U.time_freq_support.time_frequencies.data, U[0].data, label="Internal") +plt.plot(H.time_freq_support.time_frequencies.data, H[0].data, label="Total") +plt.xlabel("Time ({:s})".format(K.time_freq_support.time_frequencies.unit)) +plt.ylabel("Energies ({:s})".format(K[0].unit)) +plt.legend() +plt.show() + +############################################################################### +# binout file results extraction +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create the model and dprint its contents. This LS-DYNA binout file contains +# several branches (glstat, matsum and rcforc). + +binout = examples.download_binout_matsum() +ds = dpf.DataSources() +ds.set_result_file_path(binout, "binout") +model = dpf.Model(ds) +print(model) + +############################################################################### +# In this case, the Unit System is not attached to the data_source, but it can +# be directly assigned to the results. As we are employing the dpf.Model API, we +# only need to assign the Unit System once (the Model will assign it for the +# rest of the results). +# +# Results from the matsum branch of the binout file are a FieldsContainer on a +# LabelSpace comprised by part IDs. Extract part kinetic energy for all parts: + +PKE_op = model.results.part_kinetic_energy() +PKE_op.inputs.unit_system.connect(dpf.unit_systems.solver_mks) +PKE = PKE_op.eval() +print(PKE) + +############################################################################### +# Extract part internal energy for only a selected number of parts. + +part_sco = dpf.Scoping(ids=[50, 1522], location="part") +PIE_op = model.results.part_internal_energy() +PIE_op.inputs.entity_scoping.connect(part_sco) +PIE = PIE_op.eval() + +############################################################################### +# Plot part kinetic and internal energy for a selection of parts. In this case, +# the TimeFreqSupport of the matsum branch does not have all the time steps in +# the binout file. Thus, a rescoping operation is needed: + +rescope_op = dpf.operators.scoping.rescope() +rescope_op.inputs.fields.connect(PKE.time_freq_support.time_frequencies) +rescope_op.inputs.mesh_scoping.connect(PKE[0].scoping) +t_field = rescope_op.outputs.fields_as_field() +t_vals = t_field.data + +plt.plot(t_vals, PKE.get_field({"part": 50}).data, label="Kinetic, Part 50") +plt.plot(t_vals, PKE.get_field({"part": 1522}).data, label="Kinetic, Part 1522") +plt.plot(t_vals, PIE.get_field({"part": 50}).data, label="Internal, Part 50") +plt.plot(t_vals, PIE.get_field({"part": 1522}).data, label="Internal, Part 1522") +plt.xlabel("Time ({:s})".format(t_field.unit)) +plt.ylabel("Energy ({:s})".format(PIE.get_field({"part": 50}).unit)) +plt.legend() +plt.show() + +############################################################################### +# Similarly, results from the rcforc branch of the binout file are a +# FieldsContainer on a LabelSpace comprised by interface IDs. Extract interface +# contact force for only one interface. + +interface_sco = dpf.Scoping(ids=[19], location="interface") +FC_op = model.results.interface_contact_force() +FC_op.inputs.entity_scoping.connect(interface_sco) +FC = FC_op.eval() +print(FC) + +############################################################################### +# In addition to interface, the FieldsContainer is scoped on idtype (0 for the +# master side of the interface, 1 for the slave). Contact force is a vector, and +# the three components are available. + +rescope_op = dpf.operators.scoping.rescope() +rescope_op.inputs.fields.connect(FC.time_freq_support.time_frequencies) +rescope_op.inputs.mesh_scoping.connect(FC[0].scoping) +t_field = rescope_op.outputs.fields_as_field() +t_vals = t_field.data + +FX = FC.select_component(0) +FY = FC.select_component(1) +FZ = FC.select_component(2) + +plt.plot(t_vals, FX.get_field({"interface": 19, "idtype": 0}).data, label="FX, slave") +plt.plot(t_vals, FX.get_field({"interface": 19, "idtype": 1}).data, label="FX, master") +plt.plot(t_vals, FY.get_field({"interface": 19, "idtype": 0}).data, label="FY, slave") +plt.plot(t_vals, FY.get_field({"interface": 19, "idtype": 1}).data, label="FY, master") +plt.plot(t_vals, FZ.get_field({"interface": 19, "idtype": 0}).data, label="FZ, slave") +plt.plot(t_vals, FZ.get_field({"interface": 19, "idtype": 1}).data, label="FZ, master") +plt.xlabel("Time ({:s})".format(t_field.unit)) +plt.xlim([0, 10]) +plt.ylabel("Contact Force ({:s})".format(FX.get_field({"interface": 19, "idtype": 0}).unit)) +plt.legend() +plt.show() diff --git a/doc/source/examples/01-transient_analyses/02-lsdyna_operators.py.md5 b/doc/source/examples/01-transient_analyses/02-lsdyna_operators.py.md5 new file mode 100644 index 0000000000..16a3f40628 --- /dev/null +++ b/doc/source/examples/01-transient_analyses/02-lsdyna_operators.py.md5 @@ -0,0 +1 @@ +49070db627ea8bf8df05e842db81e822 \ No newline at end of file diff --git a/doc/source/examples/01-transient_analyses/02-lsdyna_operators.rst b/doc/source/examples/01-transient_analyses/02-lsdyna_operators.rst new file mode 100644 index 0000000000..a01e4eced2 --- /dev/null +++ b/doc/source/examples/01-transient_analyses/02-lsdyna_operators.rst @@ -0,0 +1,1677 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\01-transient_analyses\02-lsdyna_operators.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_01-transient_analyses_02-lsdyna_operators.py: + + +.. _lsdyna_operators: + +Results extraction and analysis from LS-DYNA sources +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example provides an overview of the LS-DYNA results providers. + +.. note:: + This example requires DPF 6.1 (ansys-dpf-server-2023-2-pre0) or above. + For more information, see :ref:`ref_compatibility`. + +.. GENERATED FROM PYTHON SOURCE LINES 15-20 + +.. code-block:: default + + + import matplotlib.pyplot as plt + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 21-29 + +d3plot file results extraction +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create the model and print its contents. This LS-DYNA d3plot file contains +several individual results, each at different times. The d3plot file does not +contain information related to Units. In this case, as the simulation was run +through Mechanical, a file.actunits file is produced. If this file is +supplemented in the data_sources, the units will be correctly fetched for all +resuls in the file as well as for the mesh. + +.. GENERATED FROM PYTHON SOURCE LINES 29-37 + +.. code-block:: default + + + d3plot = examples.download_d3plot_beam() + ds = dpf.DataSources() + ds.set_result_file_path(d3plot[0], "d3plot") + ds.add_file_path(d3plot[3], "actunits") + model = dpf.Model(ds) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Unknown analysis + Unit system: NMM: mm, ton, N, s, mV, mA, degC + Physics Type: Unknown + Available results: + - global_kinetic_energy: TimeFreq_steps Global Kinetic Energy + - global_internal_energy: TimeFreq_steps Global Internal Energy + - global_total_energy: TimeFreq_steps Global Total Energy + - global_velocity: TimeFreq_steps Global Velocity + - initial_coordinates: Nodal Initial Coordinates + - coordinates: Nodal Coordinates + - velocity: Nodal Velocity + - acceleration: Nodal Acceleration + - stress: Elemental Stress + - stress_von_mises: Elemental Stress Von Mises + - plastic_strain_eqv: Elemental Plastic Strain Eqv + - total_strain: Elemental Total Strain + - beam_axial_force: Elemental Beam Axial Force + - beam_s_shear_force: Elemental Beam S Shear Force + - beam_t_shear_force: Elemental Beam T Shear Force + - beam_s_bending_moment: Elemental Beam S Bending Moment + - beam_t_bending_moment: Elemental Beam T Bending Moment + - beam_torsional_moment: Elemental Beam Torsional Moment + - beam_axial_stress: Elemental Beam Axial Stress + - beam_rs_shear_stress: Elemental Beam Rs Shear Stress + - beam_tr_shear_stress: Elemental Beam Tr Shear Stress + - beam_axial_plastic_strain: Elemental Beam Axial Plastic Strain + - beam_axial_total_strain: Elemental Beam Axial Total Strain + - history_variablesihv__[1__10]: Elemental History Variables(ihv: [1, 10]) + - displacement: Nodal Displacement + ------------------------------ + DPF Meshed Region: + 1940 nodes + 2056 elements + Unit: mm + With solid (3D) elements, beam (1D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 12 + Cumulative Time (s) LoadStep Substep + 1 0,000000 1 1 + 2 0,997460 2 1 + 3 1,997818 3 1 + 4 2,998237 4 1 + 5 3,998657 5 1 + 6 4,999076 6 1 + 7 5,999496 7 1 + 8 6,999915 8 1 + 9 7,997509 9 1 + 10 8,997929 10 1 + 11 9,998348 11 1 + 12 10,001174 12 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 38-44 + +The model has solid (3D) elements and beam (1D) elements. Some of the results +only apply to one type of elements (such as the stress tensor for solids, or +the axial force for beams, for example). + +Let's extract beam axial force for the last time step and plot it, deforming +the mesh according to the displacement field at the same time step. + +.. GENERATED FROM PYTHON SOURCE LINES 44-51 + +.. code-block:: default + + + N = model.results.beam_axial_force(time_scoping=[12]).eval() + u = model.results.displacement(time_scoping=[12]).eval() + + sargs = dict(title="N", fmt="%.2e", title_font_size=30, label_font_size=20) + N[0].plot(deform_by=u[0], scalar_bar_args=sargs) + + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_001.png + :alt: 02 lsdyna operators + :srcset: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 52-58 + +The axial force has only been computed for the beam elements (the bottom +frame), whereas the top sphere, which is comprised by solid elements, has +only been deformed by the displacement field. + +PyDPF also allows you to animate the results in a FieldsContainer. Thus, if +all time steps are extracted, an animation can be produced. + +.. GENERATED FROM PYTHON SOURCE LINES 58-63 + +.. code-block:: default + + + N_all = model.results.beam_axial_force.on_all_time_freqs.eval() + u_all = model.results.displacement.on_all_time_freqs.eval() + N_all.animate(deform_by=u_all, save_as="falling_ball.gif", scalar_bar_args=sargs) + + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_002.gif + :alt: 02 lsdyna operators + :srcset: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_002.gif + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 64-66 + +Some of the results are marked as global. They are not scoped over any mesh +entity, but are global variables of the model. + +.. GENERATED FROM PYTHON SOURCE LINES 66-70 + +.. code-block:: default + + + K = model.results.global_kinetic_energy().eval() + print(K) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Fields Container + with 1 field(s) + defined on labels: + + with: + - field 0 {} with TimeFreq_steps location, 1 components and 12 entities. + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 71-72 + +Energy plots over time (the sphere was released with some initial velocity). + +.. GENERATED FROM PYTHON SOURCE LINES 72-84 + +.. code-block:: default + + + U = model.results.global_internal_energy().eval() + H = model.results.global_total_energy().eval() + + plt.plot(K.time_freq_support.time_frequencies.data, K[0].data, label="Kinetic") + plt.plot(U.time_freq_support.time_frequencies.data, U[0].data, label="Internal") + plt.plot(H.time_freq_support.time_frequencies.data, H[0].data, label="Total") + plt.xlabel("Time ({:s})".format(K.time_freq_support.time_frequencies.unit)) + plt.ylabel("Energies ({:s})".format(K[0].unit)) + plt.legend() + plt.show() + + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_003.png + :alt: 02 lsdyna operators + :srcset: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_003.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-89 + +binout file results extraction +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create the model and dprint its contents. This LS-DYNA binout file contains +several branches (glstat, matsum and rcforc). + +.. GENERATED FROM PYTHON SOURCE LINES 89-96 + +.. code-block:: default + + + binout = examples.download_binout_matsum() + ds = dpf.DataSources() + ds.set_result_file_path(binout, "binout") + model = dpf.Model(ds) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Unknown analysis + Unit system: Undefined + Physics Type: Unknown + Available results: + - displacement: Nodal Displacement + - global_time_step: TimeFreq_steps Global Time Step + - global_kinetic_energy: TimeFreq_steps Global Kinetic Energy + - global_internal_energy: TimeFreq_steps Global Internal Energy + - global_spring_damper_energy: TimeFreq_steps Global Spring Damper Energy + - global_joint_internal_energy: TimeFreq_steps Global Joint Internal Energy + - global_system_damping_energy: TimeFreq_steps Global System Damping Energy + - global_sliding_interface_energy: TimeFreq_steps Global Sliding Interface Energy + - global_external_work: TimeFreq_steps Global External Work + - global_eroded_kinetic_energy: TimeFreq_steps Global Eroded Kinetic Energy + - global_eroded_internal_energy: TimeFreq_steps Global Eroded Internal Energy + - global_total_energy: TimeFreq_steps Global Total Energy + - global_energy_ratio: TimeFreq_steps Global Energy Ratio + - global_energy_ratio_wo_eroded: TimeFreq_steps Global Energy Ratio Wo Eroded + - global_velocity: TimeFreq_steps Global Velocity + - global_added_mass: TimeFreq_steps Global Added Mass + - global_added_mass_percentage: TimeFreq_steps Global Added Mass Percentage + - part_internal_energy: TimeFreq_steps Part Internal Energy + - part_kinetic_energy: TimeFreq_steps Part Kinetic Energy + - part_eroded_internal_energy: TimeFreq_steps Part Eroded Internal Energy + - part_eroded_kinetic_energy: TimeFreq_steps Part Eroded Kinetic Energy + - part_added_mass: TimeFreq_steps Part Added Mass + - part_momentum: TimeFreq_steps Part Momentum + - part_rigid_body_velocity: TimeFreq_steps Part Rigid Body Velocity + - interface_contact_mass: TimeFreq_steps Interface Contact Mass + - interface_contact_force: TimeFreq_steps Interface Contact Force + ------------------------------ + DPF Meshed Region: + 1 nodes + Unit: + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1010 + Cumulative Frequency () LoadStep Substep + 1 0,000000 1 1 + 2 0,097868 2 1 + 3 0,195737 3 1 + 4 0,293605 4 1 + 5 0,391474 5 1 + 6 0,498239 6 1 + 7 0,596107 7 1 + 8 0,693976 8 1 + 9 0,791844 9 1 + 10 0,898610 10 1 + 11 0,996478 11 1 + 12 1,094346 12 1 + 13 1,192215 13 1 + 14 1,298980 14 1 + 15 1,396849 15 1 + 16 1,494717 16 1 + 17 1,592585 17 1 + 18 1,699351 18 1 + 19 1,797219 19 1 + 20 1,895088 20 1 + 21 1,992956 21 1 + 22 2,099721 22 1 + 23 2,197590 23 1 + 24 2,295462 24 1 + 25 2,393364 25 1 + 26 2,491304 26 1 + 27 2,598073 27 1 + 28 2,696023 28 1 + 29 2,794000 29 1 + 30 2,891951 30 1 + 31 2,998879 31 1 + 32 3,096866 32 1 + 33 3,194883 33 1 + 34 3,292901 34 1 + 35 3,399788 35 1 + 36 3,497805 36 1 + 37 3,595823 37 1 + 38 3,693840 38 1 + 39 3,791857 39 1 + 40 3,898755 40 1 + 41 3,996773 41 1 + 42 4,094749 42 1 + 43 4,192767 43 1 + 44 4,299624 44 1 + 45 4,397628 45 1 + 46 4,495646 46 1 + 47 4,593663 47 1 + 48 4,691681 48 1 + 49 4,798609 49 1 + 50 4,896627 50 1 + 51 4,994594 51 1 + 52 5,092611 52 1 + 53 5,199547 53 1 + 54 5,297572 54 1 + 55 5,395590 55 1 + 56 5,493581 56 1 + 57 5,591599 57 1 + 58 5,698528 58 1 + 59 5,796547 59 1 + 60 5,894565 60 1 + 61 5,992583 61 1 + 62 6,099511 62 1 + 63 6,197529 63 1 + 64 6,295547 64 1 + 65 6,393566 65 1 + 66 6,491584 66 1 + 67 6,598444 67 1 + 68 6,696421 68 1 + 69 6,794439 69 1 + 70 6,892458 70 1 + 71 6,999387 71 1 + 72 7,097407 72 1 + 73 7,195426 73 1 + 74 7,293445 74 1 + 75 7,391466 75 1 + 76 7,498406 76 1 + 77 7,596435 77 1 + 78 7,694464 78 1 + 79 7,792492 79 1 + 80 7,899434 80 1 + 81 7,997462 81 1 + 82 8,095469 82 1 + 83 8,193441 83 1 + 84 8,291460 84 1 + 85 8,398328 85 1 + 86 8,496346 86 1 + 87 8,594317 87 1 + 88 8,692324 88 1 + 89 8,799255 89 1 + 90 8,897273 90 1 + 91 8,995292 91 1 + 92 9,093309 92 1 + 93 9,191328 93 1 + 94 9,298257 94 1 + 95 9,396275 95 1 + 96 9,494293 96 1 + 97 9,592311 97 1 + 98 9,699240 98 1 + 99 9,797258 99 1 + 100 9,895276 100 1 + 101 9,993294 101 1 + 102 10,091312 102 1 + 103 10,198241 103 1 + 104 10,296259 104 1 + 105 10,394279 105 1 + 106 10,492304 106 1 + 107 10,599245 107 1 + 108 10,697274 108 1 + 109 10,795304 109 1 + 110 10,893333 110 1 + 111 10,991363 111 1 + 112 11,098304 112 1 + 113 11,196333 113 1 + 114 11,294362 114 1 + 115 11,392391 115 1 + 116 11,499333 116 1 + 117 11,597363 117 1 + 118 11,695392 118 1 + 119 11,793422 119 1 + 120 11,891449 120 1 + 121 11,998384 121 1 + 122 12,096347 122 1 + 123 12,194366 123 1 + 124 12,292382 124 1 + 125 12,399310 125 1 + 126 12,497328 126 1 + 127 12,595345 127 1 + 128 12,693352 128 1 + 129 12,791368 129 1 + 130 12,898229 130 1 + 131 12,996218 131 1 + 132 13,094235 132 1 + 133 13,192252 133 1 + 134 13,299180 134 1 + 135 13,397198 135 1 + 136 13,495215 136 1 + 137 13,593246 137 1 + 138 13,691278 138 1 + 139 13,798222 139 1 + 140 13,896254 140 1 + 141 13,994215 141 1 + 142 14,092141 142 1 + 143 14,198971 143 1 + 144 14,296902 144 1 + 145 14,394816 145 1 + 146 14,492726 146 1 + 147 14,599604 147 1 + 148 14,697553 148 1 + 149 14,795456 149 1 + 150 14,893403 150 1 + 151 14,991365 151 1 + 152 15,098253 152 1 + 153 15,196204 153 1 + 154 15,294127 154 1 + 155 15,392003 155 1 + 156 15,498770 156 1 + 157 15,596642 157 1 + 158 15,694518 158 1 + 159 15,792427 159 1 + 160 15,899206 160 1 + 161 15,997162 161 1 + 162 16,095060 162 1 + 163 16,192940 163 1 + 164 16,299715 164 1 + 165 16,397587 165 1 + 166 16,495459 166 1 + 167 16,593330 167 1 + 168 16,691200 168 1 + 169 16,797968 169 1 + 170 16,895941 170 1 + 171 16,993937 171 1 + 172 17,091888 172 1 + 173 17,198776 173 1 + 174 17,296793 174 1 + 175 17,394678 175 1 + 176 17,492554 176 1 + 177 17,599354 177 1 + 178 17,697252 178 1 + 179 17,795135 179 1 + 180 17,893005 180 1 + 181 17,999775 181 1 + 182 18,097645 182 1 + 183 18,195517 183 1 + 184 18,293386 184 1 + 185 18,391256 185 1 + 186 18,498024 186 1 + 187 18,595894 187 1 + 188 18,693762 188 1 + 189 18,791632 189 1 + 190 18,898399 190 1 + 191 18,996269 191 1 + 192 19,094139 192 1 + 193 19,192009 193 1 + 194 19,298775 194 1 + 195 19,396645 195 1 + 196 19,494514 196 1 + 197 19,592386 197 1 + 198 19,699152 198 1 + 199 19,797024 199 1 + 200 19,894894 200 1 + 201 19,992764 201 1 + 202 20,099531 202 1 + 203 20,197401 203 1 + 204 20,295271 204 1 + 205 20,393141 205 1 + 206 20,499907 206 1 + 207 20,597776 207 1 + 208 20,695646 208 1 + 209 20,793518 209 1 + 210 20,891388 210 1 + 211 20,998158 211 1 + 212 21,096027 212 1 + 213 21,193899 213 1 + 214 21,291771 214 1 + 215 21,398764 215 1 + 216 21,498735 216 1 + 217 21,599386 217 1 + 218 21,698536 218 1 + 219 21,798298 219 1 + 220 21,898647 220 1 + 221 21,999575 221 1 + 222 22,098860 222 1 + 223 22,198702 223 1 + 224 22,299099 224 1 + 225 22,400043 225 1 + 226 22,499275 226 1 + 227 22,599031 227 1 + 228 22,699329 228 1 + 229 22,797865 229 1 + 230 22,899208 230 1 + 231 22,998747 231 1 + 232 23,098791 232 1 + 233 23,199358 233 1 + 234 23,298098 234 1 + 235 23,399715 235 1 + 236 23,499483 236 1 + 237 23,599775 237 1 + 238 23,698185 238 1 + 239 23,799513 239 1 + 240 23,898933 240 1 + 241 23,998865 241 1 + 242 24,099319 242 1 + 243 24,197836 243 1 + 244 24,299360 244 1 + 245 24,398956 245 1 + 246 24,499113 246 1 + 247 24,599850 247 1 + 248 24,698679 248 1 + 249 24,798164 249 1 + 250 24,898348 250 1 + 251 24,999241 251 1 + 252 25,098253 252 1 + 253 25,198011 253 1 + 254 25,298561 254 1 + 255 25,399933 255 1 + 256 25,499472 256 1 + 257 25,599909 257 1 + 258 25,698580 258 1 + 259 25,798267 259 1 + 260 25,899038 260 1 + 261 25,998114 261 1 + 262 26,098392 262 1 + 263 26,199966 263 1 + 264 26,299913 264 1 + 265 26,398115 265 1 + 266 26,497496 266 1 + 267 26,598053 267 1 + 268 26,699776 268 1 + 269 26,799532 269 1 + 270 26,897236 270 1 + 271 26,999231 271 1 + 272 27,099184 272 1 + 273 27,197046 273 1 + 274 27,299398 274 1 + 275 27,399677 275 1 + 276 27,497784 276 1 + 277 27,597071 277 1 + 278 27,697582 278 1 + 279 27,799368 279 1 + 280 27,898903 280 1 + 281 27,999710 281 1 + 282 28,098152 282 1 + 283 28,197824 283 1 + 284 28,298733 284 1 + 285 28,397083 285 1 + 286 28,496624 286 1 + 287 28,597397 287 1 + 288 28,699442 288 1 + 289 28,798777 289 1 + 290 28,899324 290 1 + 291 28,997013 291 1 + 292 29,100006 292 1 + 293 29,195889 293 1 + 294 29,297098 294 1 + 295 29,399496 295 1 + 296 29,498739 296 1 + 297 29,599081 297 1 + 298 29,696087 298 1 + 299 29,798573 299 1 + 300 29,897617 300 1 + 301 29,997641 301 1 + 302 30,098639 302 1 + 303 30,195957 303 1 + 304 30,298866 304 1 + 305 30,398010 305 1 + 306 30,498035 306 1 + 307 30,598740 307 1 + 308 30,697105 308 1 + 309 30,796635 309 1 + 310 30,896976 310 1 + 311 30,996698 311 1 + 312 31,095596 312 1 + 313 31,197756 313 1 + 314 31,298031 314 1 + 315 31,395048 315 1 + 316 31,497917 316 1 + 317 31,596348 317 1 + 318 31,695446 318 1 + 319 31,795191 319 1 + 320 31,895548 320 1 + 321 31,996508 321 1 + 322 32,098083 322 1 + 323 32,194904 323 1 + 324 32,297726 324 1 + 325 32,395702 325 1 + 326 32,499683 326 1 + 327 32,598660 327 1 + 328 32,698044 328 1 + 329 32,797794 329 1 + 330 32,897907 330 1 + 331 32,998405 331 1 + 332 33,099312 332 1 + 333 33,195011 333 1 + 334 33,296768 334 1 + 335 33,398956 335 1 + 336 33,495861 336 1 + 337 33,598877 337 1 + 338 33,696568 338 1 + 339 33,794651 339 1 + 340 33,898952 340 1 + 341 33,997894 341 1 + 342 34,097282 342 1 + 343 34,197136 343 1 + 344 34,297470 344 1 + 345 34,398304 345 1 + 346 34,499653 346 1 + 347 34,595516 347 1 + 348 34,697891 348 1 + 349 34,794743 349 1 + 350 34,898186 350 1 + 351 34,996063 351 1 + 352 35,094463 352 1 + 353 35,199596 353 1 + 354 35,299114 354 1 + 355 35,399197 355 1 + 356 35,499851 356 1 + 357 35,594730 357 1 + 358 35,695652 358 1 + 359 35,799515 359 1 + 360 35,899506 360 1 + 361 35,995525 361 1 + 362 36,098106 362 1 + 363 36,195683 363 1 + 364 36,297588 364 1 + 365 36,397541 365 1 + 366 36,496498 366 1 + 367 36,598366 367 1 + 368 36,698254 368 1 + 369 36,799324 369 1 + 370 36,898586 370 1 + 371 36,997723 371 1 + 372 37,098717 372 1 + 373 37,198433 373 1 + 374 37,299068 374 1 + 375 37,397396 375 1 + 376 37,498909 376 1 + 377 37,597363 377 1 + 378 37,698647 378 1 + 379 37,799484 379 1 + 380 37,899643 380 1 + 381 37,998882 381 1 + 382 38,096966 382 1 + 383 38,197273 383 1 + 384 38,299793 384 1 + 385 38,396961 385 1 + 386 38,499851 386 1 + 387 38,596916 387 1 + 388 38,699688 388 1 + 389 38,796211 389 1 + 390 38,898472 390 1 + 391 38,998302 391 1 + 392 39,099781 392 1 + 393 39,198582 393 1 + 394 39,298496 394 1 + 395 39,395855 395 1 + 396 39,499107 396 1 + 397 39,599281 397 1 + 398 39,696175 398 1 + 399 39,798985 399 1 + 400 39,898350 400 1 + 401 39,998882 401 1 + 402 40,095692 402 1 + 403 40,198425 403 1 + 404 40,297260 404 1 + 405 40,396984 405 1 + 406 40,497517 406 1 + 407 40,598789 407 1 + 408 40,695621 408 1 + 409 40,798138 409 1 + 410 40,896027 410 1 + 411 40,999531 411 1 + 412 41,098259 412 1 + 413 41,197323 413 1 + 414 41,296677 414 1 + 415 41,396275 415 1 + 416 41,496067 416 1 + 417 41,596027 417 1 + 418 41,696152 418 1 + 419 41,796444 419 1 + 420 41,896938 420 1 + 421 41,997654 421 1 + 422 42,097473 422 1 + 423 42,198185 423 1 + 424 42,298985 424 1 + 425 42,399212 425 1 + 426 42,496552 426 1 + 427 42,595505 427 1 + 428 42,699448 428 1 + 429 42,797859 429 1 + 430 42,894871 430 1 + 431 42,998627 431 1 + 432 43,097332 432 1 + 433 43,196476 433 1 + 434 43,296085 434 1 + 435 43,396194 435 1 + 436 43,496834 436 1 + 437 43,598022 437 1 + 438 43,699772 438 1 + 439 43,796383 439 1 + 440 43,899239 440 1 + 441 43,996918 441 1 + 442 44,095146 442 1 + 443 44,199768 443 1 + 444 44,299168 444 1 + 445 44,399162 445 1 + 446 44,499771 446 1 + 447 44,595058 447 1 + 448 44,696953 448 1 + 449 44,799515 449 1 + 450 44,896626 450 1 + 451 44,994236 451 1 + 452 45,095139 452 1 + 453 45,196796 453 1 + 454 45,298306 454 1 + 455 45,398643 455 1 + 456 45,496727 456 1 + 457 45,599728 457 1 + 458 45,696220 458 1 + 459 45,798355 459 1 + 460 45,894894 460 1 + 461 45,995911 461 1 + 462 46,095600 462 1 + 463 46,199570 463 1 + 464 46,294743 464 1 + 465 46,397125 465 1 + 466 46,499519 466 1 + 467 46,595528 467 1 + 468 46,697941 468 1 + 469 46,793964 469 1 + 470 46,898586 470 1 + 471 46,999065 471 1 + 472 47,098663 472 1 + 473 47,199722 473 1 + 474 47,299709 474 1 + 475 47,398182 475 1 + 476 47,497311 476 1 + 477 47,599579 477 1 + 478 47,699291 478 1 + 479 47,798820 479 1 + 480 47,897900 480 1 + 481 47,999321 481 1 + 482 48,096905 482 1 + 483 48,199684 483 1 + 484 48,298237 484 1 + 485 48,398777 485 1 + 486 48,498035 486 1 + 487 48,599335 487 1 + 488 48,699295 488 1 + 489 48,797794 489 1 + 490 48,898296 490 1 + 491 48,997124 491 1 + 492 49,097820 492 1 + 493 49,196495 493 1 + 494 49,296780 494 1 + 495 49,398594 495 1 + 496 49,497856 496 1 + 497 49,598370 497 1 + 498 49,695961 498 1 + 499 49,798687 499 1 + 500 49,898251 500 1 + 501 49,998661 501 1 + 502 50,095600 502 1 + 503 50,197403 503 1 + 504 50,299770 504 1 + 505 50,398323 505 1 + 506 50,497257 506 1 + 507 50,596539 507 1 + 508 50,696148 508 1 + 509 50,796036 509 1 + 510 50,896156 510 1 + 511 50,996483 511 1 + 512 51,097012 512 1 + 513 51,197742 513 1 + 514 51,298710 514 1 + 515 51,395569 515 1 + 516 51,497196 516 1 + 517 51,599281 517 1 + 518 51,697464 518 1 + 519 51,796288 519 1 + 520 51,895859 520 1 + 521 51,996254 521 1 + 522 52,097549 522 1 + 523 52,195145 523 1 + 524 52,298397 524 1 + 525 52,397980 525 1 + 526 52,498501 526 1 + 527 52,599464 527 1 + 528 52,695415 528 1 + 529 52,795685 529 1 + 530 52,899094 530 1 + 531 52,997910 531 1 + 532 53,097610 532 1 + 533 53,197834 533 1 + 534 53,298611 534 1 + 535 53,395298 535 1 + 536 53,497799 536 1 + 537 53,596516 537 1 + 538 53,696472 538 1 + 539 53,797825 539 1 + 540 53,895523 540 1 + 541 53,994690 541 1 + 542 53,999950 542 1 + 543 54,095367 543 1 + 544 54,197590 544 1 + 545 54,295849 545 1 + 546 54,395443 546 1 + 547 54,496315 547 1 + 548 54,598404 548 1 + 549 54,695896 549 1 + 550 54,794392 550 1 + 551 54,899723 551 1 + 552 54,994213 552 1 + 553 55,099247 553 1 + 554 55,196472 554 1 + 555 55,299496 555 1 + 556 55,399052 556 1 + 557 55,495045 557 1 + 558 55,598309 558 1 + 559 55,697903 559 1 + 560 55,799137 560 1 + 561 55,897148 561 1 + 562 55,997131 562 1 + 563 56,099277 563 1 + 564 56,198238 564 1 + 565 56,299503 565 1 + 566 56,397381 566 1 + 567 56,497566 567 1 + 568 56,594013 568 1 + 569 56,698742 569 1 + 570 56,797749 570 1 + 571 56,896503 571 1 + 572 56,995148 572 1 + 573 57,093777 573 1 + 574 57,198627 574 1 + 575 57,297436 575 1 + 576 57,396423 576 1 + 577 57,495628 577 1 + 578 57,595066 578 1 + 579 57,694752 579 1 + 580 57,794678 580 1 + 581 57,894829 581 1 + 582 57,995201 582 1 + 583 58,095810 583 1 + 584 58,196674 584 1 + 585 58,297829 585 1 + 586 58,399292 586 1 + 587 58,497662 587 1 + 588 58,596508 588 1 + 589 58,693451 589 1 + 590 58,792042 590 1 + 591 58,893253 591 1 + 592 58,993610 592 1 + 593 59,097088 593 1 + 594 59,195107 594 1 + 595 59,294846 595 1 + 596 59,398270 596 1 + 597 59,496750 597 1 + 598 59,595139 598 1 + 599 59,698166 599 1 + 600 59,798031 600 1 + 601 59,898396 601 1 + 602 59,996727 602 1 + 603 60,099335 603 1 + 604 60,198711 604 1 + 605 60,297974 605 1 + 606 60,396893 606 1 + 607 60,499100 607 1 + 608 60,595608 608 1 + 609 60,698551 609 1 + 610 60,799133 610 1 + 611 60,899158 611 1 + 612 60,998318 612 1 + 613 61,098686 613 1 + 614 61,195549 614 1 + 615 61,295708 615 1 + 616 61,399109 616 1 + 617 61,498520 617 1 + 618 61,598572 618 1 + 619 61,699268 619 1 + 620 61,798626 620 1 + 621 61,898388 621 1 + 622 61,996387 622 1 + 623 62,097511 623 1 + 624 62,196812 624 1 + 625 62,296928 625 1 + 626 62,397636 626 1 + 627 62,498623 627 1 + 628 62,598114 628 1 + 629 62,698845 629 1 + 630 62,797821 630 1 + 631 62,897034 631 1 + 632 62,997009 632 1 + 633 63,099350 633 1 + 634 63,197098 634 1 + 635 63,297955 635 1 + 636 63,397018 636 1 + 637 63,497719 637 1 + 638 63,597069 638 1 + 639 63,698181 639 1 + 640 63,797832 640 1 + 641 63,899082 641 1 + 642 63,998466 642 1 + 643 64,099220 643 1 + 644 64,198006 644 1 + 645 64,298363 645 1 + 646 64,396996 646 1 + 647 64,497734 647 1 + 648 64,597267 648 1 + 649 64,699341 649 1 + 650 64,797836 650 1 + 651 64,895775 651 1 + 652 64,999107 652 1 + 653 65,096153 653 1 + 654 65,194511 654 1 + 655 65,294067 655 1 + 656 65,394691 656 1 + 657 65,496292 657 1 + 658 65,598442 658 1 + 659 65,695824 659 1 + 660 65,797157 660 1 + 661 65,896500 661 1 + 662 65,998512 662 1 + 663 66,095955 663 1 + 664 66,196014 664 1 + 665 66,297638 665 1 + 666 66,398659 666 1 + 667 66,497978 667 1 + 668 66,596672 668 1 + 669 66,696022 669 1 + 670 66,797050 670 1 + 671 66,897072 671 1 + 672 66,996864 672 1 + 673 67,096977 673 1 + 674 67,197739 674 1 + 675 67,299347 675 1 + 676 67,398209 676 1 + 677 67,498039 677 1 + 678 67,599007 678 1 + 679 67,697502 679 1 + 680 67,797569 680 1 + 681 67,895668 681 1 + 682 67,996025 682 1 + 683 68,098991 683 1 + 684 68,195976 684 1 + 685 68,299057 685 1 + 686 68,399063 686 1 + 687 68,495331 687 1 + 688 68,596405 688 1 + 689 68,697884 689 1 + 690 68,795311 690 1 + 691 68,897575 691 1 + 692 68,995827 692 1 + 693 69,099022 693 1 + 694 69,194160 694 1 + 695 69,295479 695 1 + 696 69,396385 696 1 + 697 69,495796 697 1 + 698 69,598282 698 1 + 699 69,695694 699 1 + 700 69,799469 700 1 + 701 69,898781 701 1 + 702 69,996033 702 1 + 703 69,999756 703 1 + 704 70,096512 704 1 + 705 70,197105 705 1 + 706 70,297966 706 1 + 707 70,399284 707 1 + 708 70,497482 708 1 + 709 70,596344 709 1 + 710 70,695747 710 1 + 711 70,799263 711 1 + 712 70,899025 712 1 + 713 70,999016 713 1 + 714 71,095772 714 1 + 715 71,197426 715 1 + 716 71,296288 716 1 + 717 71,396271 717 1 + 718 71,497467 718 1 + 719 71,595886 719 1 + 720 71,695580 720 1 + 721 71,796181 721 1 + 722 71,897385 722 1 + 723 71,999176 723 1 + 724 72,097397 724 1 + 725 72,196312 725 1 + 726 72,295929 726 1 + 727 72,396133 727 1 + 728 72,496887 728 1 + 729 72,598228 729 1 + 730 72,695869 730 1 + 731 72,798912 731 1 + 732 72,898674 732 1 + 733 72,997437 733 1 + 734 73,095413 734 1 + 735 73,196739 735 1 + 736 73,298820 736 1 + 737 73,398743 737 1 + 738 73,496010 738 1 + 739 73,598969 739 1 + 740 73,698006 740 1 + 741 73,798454 741 1 + 742 73,898056 742 1 + 743 73,997803 743 1 + 744 74,098282 744 1 + 745 74,196243 745 1 + 746 74,298874 746 1 + 747 74,399155 747 1 + 748 74,497017 748 1 + 749 74,596191 749 1 + 750 74,696945 750 1 + 751 74,795631 751 1 + 752 74,895981 752 1 + 753 74,997833 753 1 + 754 75,097069 754 1 + 755 75,197525 755 1 + 756 75,299156 756 1 + 757 75,397606 757 1 + 758 75,496498 758 1 + 759 75,595306 759 1 + 760 75,698036 760 1 + 761 75,796631 761 1 + 762 75,899315 762 1 + 763 75,998055 763 1 + 764 76,097130 764 1 + 765 76,196556 765 1 + 766 76,296249 766 1 + 767 76,396255 767 1 + 768 76,496902 768 1 + 769 76,598694 769 1 + 770 76,697784 770 1 + 771 76,798668 771 1 + 772 76,896393 772 1 + 773 76,998802 773 1 + 774 77,095863 774 1 + 775 77,195580 775 1 + 776 77,297424 776 1 + 777 77,396805 777 1 + 778 77,497551 778 1 + 779 77,595688 779 1 + 780 77,699280 780 1 + 781 77,797119 781 1 + 782 77,897072 782 1 + 783 77,995789 783 1 + 784 77,999428 784 1 + 785 78,097328 785 1 + 786 78,198364 786 1 + 787 78,299225 787 1 + 788 78,396614 788 1 + 789 78,498070 789 1 + 790 78,596519 790 1 + 791 78,699333 791 1 + 792 78,799156 792 1 + 793 78,895920 793 1 + 794 78,997055 794 1 + 795 79,098854 795 1 + 796 79,197380 796 1 + 797 79,296219 797 1 + 798 79,399139 798 1 + 799 79,498566 799 1 + 800 79,598297 800 1 + 801 79,698227 801 1 + 802 79,798187 802 1 + 803 79,897949 803 1 + 804 79,997330 804 1 + 805 80,096260 805 1 + 806 80,198669 806 1 + 807 80,297554 807 1 + 808 80,397369 808 1 + 809 80,498566 809 1 + 810 80,597290 810 1 + 811 80,697189 811 1 + 812 80,797874 812 1 + 813 80,898842 813 1 + 814 80,995499 814 1 + 815 80,999519 815 1 + 816 81,095490 816 1 + 817 81,198395 817 1 + 818 81,295998 818 1 + 819 81,395844 819 1 + 820 81,497581 820 1 + 821 81,597313 821 1 + 822 81,698814 822 1 + 823 81,798645 823 1 + 824 81,897079 824 1 + 825 81,997871 825 1 + 826 82,097832 826 1 + 827 82,197243 827 1 + 828 82,296303 828 1 + 829 82,398483 829 1 + 830 82,497002 830 1 + 831 82,598633 831 1 + 832 82,696518 832 1 + 833 82,797386 833 1 + 834 82,897896 834 1 + 835 82,998161 835 1 + 836 83,098282 836 1 + 837 83,198311 837 1 + 838 83,298271 838 1 + 839 83,398163 839 1 + 840 83,497871 840 1 + 841 83,597122 841 1 + 842 83,698853 842 1 + 843 83,796303 843 1 + 844 83,899185 844 1 + 845 83,998177 845 1 + 846 84,097023 846 1 + 847 84,196312 847 1 + 848 84,296509 848 1 + 849 84,397743 849 1 + 850 84,496628 850 1 + 851 84,596344 851 1 + 852 84,696762 852 1 + 853 84,797684 853 1 + 854 84,898834 854 1 + 855 84,996559 855 1 + 856 84,999931 856 1 + 857 85,097366 857 1 + 858 85,197601 858 1 + 859 85,296936 859 1 + 860 85,398407 860 1 + 861 85,498558 861 1 + 862 85,597412 862 1 + 863 85,698296 863 1 + 864 85,798248 864 1 + 865 85,897491 865 1 + 866 85,999207 866 1 + 867 86,097252 867 1 + 868 86,197800 868 1 + 869 86,297852 869 1 + 870 86,397476 870 1 + 871 86,496696 871 1 + 872 86,598503 872 1 + 873 86,696907 873 1 + 874 86,797882 874 1 + 875 86,898445 875 1 + 876 86,998558 876 1 + 877 87,098228 877 1 + 878 87,197449 878 1 + 879 87,299103 879 1 + 880 87,397354 880 1 + 881 87,498009 881 1 + 882 87,598175 882 1 + 883 87,697823 883 1 + 884 87,796829 884 1 + 885 87,897827 885 1 + 886 87,997841 886 1 + 887 88,096748 887 1 + 888 88,197258 888 1 + 889 88,296837 889 1 + 890 88,398468 890 1 + 891 88,497032 891 1 + 892 88,598061 892 1 + 893 88,698975 893 1 + 894 88,797234 894 1 + 895 88,898125 895 1 + 896 88,998909 896 1 + 897 89,096809 897 1 + 898 89,196999 898 1 + 899 89,296768 899 1 + 900 89,398796 900 1 + 901 89,497932 901 1 + 902 89,596710 902 1 + 903 89,697548 903 1 + 904 89,797577 904 1 + 905 89,899040 905 1 + 906 89,999130 906 1 + 907 90,097702 907 1 + 908 90,197128 908 1 + 909 90,297394 909 1 + 910 90,398682 910 1 + 911 90,498909 911 1 + 912 90,598305 912 1 + 913 90,696991 913 1 + 914 90,797256 914 1 + 915 90,898933 915 1 + 916 90,997368 916 1 + 917 90,999596 917 1 + 918 91,099159 918 1 + 919 91,197655 919 1 + 920 91,297287 920 1 + 921 91,398048 921 1 + 922 91,497818 922 1 + 923 91,598694 923 1 + 924 91,698486 924 1 + 925 91,799164 925 1 + 926 91,898529 926 1 + 927 91,994476 927 1 + 928 91,999649 928 1 + 929 92,093620 929 1 + 930 92,194557 930 1 + 931 92,295479 931 1 + 932 92,396393 932 1 + 933 92,497284 933 1 + 934 92,598167 934 1 + 935 92,699028 935 1 + 936 92,793571 936 1 + 937 92,894409 937 1 + 938 92,995239 938 1 + 939 93,096054 939 1 + 940 93,196861 940 1 + 941 93,297661 941 1 + 942 93,398453 942 1 + 943 93,492920 943 1 + 944 93,593674 944 1 + 945 93,694130 945 1 + 946 93,798470 946 1 + 947 93,894218 947 1 + 948 93,993454 948 1 + 949 93,999214 949 1 + 950 94,095642 950 1 + 951 94,194656 951 1 + 952 94,295464 952 1 + 953 94,397217 953 1 + 954 94,499069 954 1 + 955 94,595764 955 1 + 956 94,695816 956 1 + 957 94,796463 957 1 + 958 94,897522 958 1 + 959 94,998192 959 1 + 960 95,097672 960 1 + 961 95,195129 961 1 + 962 95,295425 962 1 + 963 95,398483 963 1 + 964 95,498398 964 1 + 965 95,594734 965 1 + 966 95,693306 966 1 + 967 95,794113 967 1 + 968 95,896873 968 1 + 969 95,994904 969 1 + 970 96,094551 970 1 + 971 96,195740 971 1 + 972 96,298393 972 1 + 973 96,395454 973 1 + 974 96,493706 974 1 + 975 96,593170 975 1 + 976 96,693840 976 1 + 977 96,795700 977 1 + 978 96,898735 978 1 + 979 96,995483 979 1 + 980 97,098320 980 1 + 981 97,197815 981 1 + 982 97,295593 982 1 + 983 97,391281 983 1 + 984 97,493439 984 1 + 985 97,596687 985 1 + 986 97,691605 986 1 + 987 97,797691 987 1 + 988 97,898926 988 1 + 989 97,993690 989 1 + 990 98,094635 990 1 + 991 98,195473 991 1 + 992 98,296059 992 1 + 993 98,396629 993 1 + 994 98,497223 994 1 + 995 98,597824 995 1 + 996 98,698425 996 1 + 997 98,799034 997 1 + 998 98,893364 998 1 + 999 98,993980 999 1 + 1000 99,094604 1000 1 + 1001 99,195229 1001 1 + 1002 99,295860 1002 1 + 1003 99,396500 1003 1 + 1004 99,497131 1004 1 + 1005 99,597763 1005 1 + 1006 99,698402 1006 1 + 1007 99,799042 1007 1 + 1008 99,893394 1008 1 + 1009 99,993752 1009 1 + 1010 99,999969 1010 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 97-104 + +In this case, the Unit System is not attached to the data_source, but it can +be directly assigned to the results. As we are employing the dpf.Model API, we +only need to assign the Unit System once (the Model will assign it for the +rest of the results). + +Results from the matsum branch of the binout file are a FieldsContainer on a +LabelSpace comprised by part IDs. Extract part kinetic energy for all parts: + +.. GENERATED FROM PYTHON SOURCE LINES 104-110 + +.. code-block:: default + + + PKE_op = model.results.part_kinetic_energy() + PKE_op.inputs.unit_system.connect(dpf.unit_systems.solver_mks) + PKE = PKE_op.eval() + print(PKE) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Fields Container + with 129 field(s) + defined on labels: part + + with: + - field 0 {part: 1} with TimeFreq_steps location, 1 components and 101 entities. + - field 1 {part: 2} with TimeFreq_steps location, 1 components and 101 entities. + - field 2 {part: 3} with TimeFreq_steps location, 1 components and 101 entities. + - field 3 {part: 4} with TimeFreq_steps location, 1 components and 101 entities. + - field 4 {part: 5} with TimeFreq_steps location, 1 components and 101 entities. + - field 5 {part: 6} with TimeFreq_steps location, 1 components and 101 entities. + - field 6 {part: 7} with TimeFreq_steps location, 1 components and 101 entities. + - field 7 {part: 8} with TimeFreq_steps location, 1 components and 101 entities. + - field 8 {part: 9} with TimeFreq_steps location, 1 components and 101 entities. + - field 9 {part: 10} with TimeFreq_steps location, 1 components and 101 entities. + - field 10 {part: 11} with TimeFreq_steps location, 1 components and 101 entities. + - field 11 {part: 12} with TimeFreq_steps location, 1 components and 101 entities. + - field 12 {part: 13} with TimeFreq_steps location, 1 components and 101 entities. + - field 13 {part: 14} with TimeFreq_steps location, 1 components and 101 entities. + - field 14 {part: 15} with TimeFreq_steps location, 1 components and 101 entities. + - field 15 {part: 16} with TimeFreq_steps location, 1 components and 101 entities. + - field 16 {part: 17} with TimeFreq_steps location, 1 components and 101 entities. + - field 17 {part: 18} with TimeFreq_steps location, 1 components and 101 entities. + - field 18 {part: 19} with TimeFreq_steps location, 1 components and 101 entities. + - field 19 {part: 20} with TimeFreq_steps location, 1 components and 101 entities. + - field 20 {part: 21} with TimeFreq_steps location, 1 components and 101 entities. + - field 21 {part: 22} with TimeFreq_steps location, 1 components and 101 entities. + - field 22 {part: 23} with TimeFreq_steps location, 1 components and 101 entities. + - field 23 {part: 24} with TimeFreq_steps location, 1 components and 101 entities. + - field 24 {part: 25} with TimeFreq_steps location, 1 components and 101 entities. + - field 25 {part: 26} with TimeFreq_steps location, 1 components and 101 entities. + - field 26 {part: 27} with TimeFreq_steps location, 1 components and 101 entities. + - field 27 {part: 28} with TimeFreq_steps location, 1 components and 101 entities. + - field 28 {part: 29} with TimeFreq_steps location, 1 components and 101 entities. + - field 29 {part: 30} with TimeFreq_steps location, 1 components and 101 entities. + - field 30 {part: 31} with TimeFreq_steps location, 1 components and 101 entities. + - field 31 {part: 32} with TimeFreq_steps location, 1 components and 101 entities. + - field 32 {part: 33} with TimeFreq_steps location, 1 components and 101 entities. + - field 33 {part: 34} with TimeFreq_steps location, 1 components and 101 entities. + - field 34 {part: 35} with TimeFreq_steps location, 1 components and 101 entities. + - field 35 {part: 36} with TimeFreq_steps location, 1 components and 101 entities. + - field 36 {part: 37} with TimeFreq_steps location, 1 components and 101 entities. + - field 37 {part: 38} with TimeFreq_steps location, 1 components and 101 entities. + - field 38 {part: 39} with TimeFreq_steps location, 1 components and 101 entities. + - field 39 {part: 40} with TimeFreq_steps location, 1 components and 101 entities. + - field 40 {part: 41} with TimeFreq_steps location, 1 components and 101 entities. + - field 41 {part: 42} with TimeFreq_steps location, 1 components and 101 entities. + - field 42 {part: 43} with TimeFreq_steps location, 1 components and 101 entities. + - field 43 {part: 44} with TimeFreq_steps location, 1 components and 101 entities. + - field 44 {part: 45} with TimeFreq_steps location, 1 components and 101 entities. + - field 45 {part: 46} with TimeFreq_steps location, 1 components and 101 entities. + - field 46 {part: 47} with TimeFreq_steps location, 1 components and 101 entities. + - field 47 {part: 48} with TimeFreq_steps location, 1 components and 101 entities. + - field 48 {part: 49} with TimeFreq_steps location, 1 components and 101 entities. + - field 49 {part: 50} with TimeFreq_steps location, 1 components and 101 entities. + - field 50 {part: 51} with TimeFreq_steps location, 1 components and 101 entities. + - field 51 {part: 52} with TimeFreq_steps location, 1 components and 101 entities. + - field 52 {part: 53} with TimeFreq_steps location, 1 components and 101 entities. + - field 53 {part: 54} with TimeFreq_steps location, 1 components and 101 entities. + - field 54 {part: 55} with TimeFreq_steps location, 1 components and 101 entities. + - field 55 {part: 56} with TimeFreq_steps location, 1 components and 101 entities. + - field 56 {part: 57} with TimeFreq_steps location, 1 components and 101 entities. + - field 57 {part: 58} with TimeFreq_steps location, 1 components and 101 entities. + - field 58 {part: 59} with TimeFreq_steps location, 1 components and 101 entities. + - field 59 {part: 60} with TimeFreq_steps location, 1 components and 101 entities. + - field 60 {part: 61} with TimeFreq_steps location, 1 components and 101 entities. + - field 61 {part: 62} with TimeFreq_steps location, 1 components and 101 entities. + - field 62 {part: 63} with TimeFreq_steps location, 1 components and 101 entities. + - field 63 {part: 64} with TimeFreq_steps location, 1 components and 101 entities. + - field 64 {part: 65} with TimeFreq_steps location, 1 components and 101 entities. + - field 65 {part: 66} with TimeFreq_steps location, 1 components and 101 entities. + - field 66 {part: 67} with TimeFreq_steps location, 1 components and 101 entities. + - field 67 {part: 68} with TimeFreq_steps location, 1 components and 101 entities. + - field 68 {part: 69} with TimeFreq_steps location, 1 components and 101 entities. + - field 69 {part: 70} with TimeFreq_steps location, 1 components and 101 entities. + - field 70 {part: 71} with TimeFreq_steps location, 1 components and 101 entities. + - field 71 {part: 72} with TimeFreq_steps location, 1 components and 101 entities. + - field 72 {part: 73} with TimeFreq_steps location, 1 components and 101 entities. + - field 73 {part: 74} with TimeFreq_steps location, 1 components and 101 entities. + - field 74 {part: 75} with TimeFreq_steps location, 1 components and 101 entities. + - field 75 {part: 76} with TimeFreq_steps location, 1 components and 101 entities. + - field 76 {part: 77} with TimeFreq_steps location, 1 components and 101 entities. + - field 77 {part: 78} with TimeFreq_steps location, 1 components and 101 entities. + - field 78 {part: 79} with TimeFreq_steps location, 1 components and 101 entities. + - field 79 {part: 80} with TimeFreq_steps location, 1 components and 101 entities. + - field 80 {part: 81} with TimeFreq_steps location, 1 components and 101 entities. + - field 81 {part: 82} with TimeFreq_steps location, 1 components and 101 entities. + - field 82 {part: 83} with TimeFreq_steps location, 1 components and 101 entities. + - field 83 {part: 84} with TimeFreq_steps location, 1 components and 101 entities. + - field 84 {part: 85} with TimeFreq_steps location, 1 components and 101 entities. + - field 85 {part: 86} with TimeFreq_steps location, 1 components and 101 entities. + - field 86 {part: 87} with TimeFreq_steps location, 1 components and 101 entities. + - field 87 {part: 88} with TimeFreq_steps location, 1 components and 101 entities. + - field 88 {part: 89} with TimeFreq_steps location, 1 components and 101 entities. + - field 89 {part: 90} with TimeFreq_steps location, 1 components and 101 entities. + - field 90 {part: 91} with TimeFreq_steps location, 1 components and 101 entities. + - field 91 {part: 92} with TimeFreq_steps location, 1 components and 101 entities. + - field 92 {part: 93} with TimeFreq_steps location, 1 components and 101 entities. + - field 93 {part: 301} with TimeFreq_steps location, 1 components and 101 entities. + - field 94 {part: 303} with TimeFreq_steps location, 1 components and 101 entities. + - field 95 {part: 304} with TimeFreq_steps location, 1 components and 101 entities. + - field 96 {part: 305} with TimeFreq_steps location, 1 components and 101 entities. + - field 97 {part: 306} with TimeFreq_steps location, 1 components and 101 entities. + - field 98 {part: 307} with TimeFreq_steps location, 1 components and 101 entities. + - field 99 {part: 308} with TimeFreq_steps location, 1 components and 101 entities. + - field 100 {part: 309} with TimeFreq_steps location, 1 components and 101 entities. + - field 101 {part: 310} with TimeFreq_steps location, 1 components and 101 entities. + - field 102 {part: 311} with TimeFreq_steps location, 1 components and 101 entities. + - field 103 {part: 312} with TimeFreq_steps location, 1 components and 101 entities. + - field 104 {part: 718} with TimeFreq_steps location, 1 components and 101 entities. + - field 105 {part: 1500} with TimeFreq_steps location, 1 components and 101 entities. + - field 106 {part: 1501} with TimeFreq_steps location, 1 components and 101 entities. + - field 107 {part: 1502} with TimeFreq_steps location, 1 components and 101 entities. + - field 108 {part: 1503} with TimeFreq_steps location, 1 components and 101 entities. + - field 109 {part: 1504} with TimeFreq_steps location, 1 components and 101 entities. + - field 110 {part: 1505} with TimeFreq_steps location, 1 components and 101 entities. + - field 111 {part: 1506} with TimeFreq_steps location, 1 components and 101 entities. + - field 112 {part: 1507} with TimeFreq_steps location, 1 components and 101 entities. + - field 113 {part: 1508} with TimeFreq_steps location, 1 components and 101 entities. + - field 114 {part: 1509} with TimeFreq_steps location, 1 components and 101 entities. + - field 115 {part: 1510} with TimeFreq_steps location, 1 components and 101 entities. + - field 116 {part: 1511} with TimeFreq_steps location, 1 components and 101 entities. + - field 117 {part: 1512} with TimeFreq_steps location, 1 components and 101 entities. + - field 118 {part: 1513} with TimeFreq_steps location, 1 components and 101 entities. + - field 119 {part: 1514} with TimeFreq_steps location, 1 components and 101 entities. + - field 120 {part: 1515} with TimeFreq_steps location, 1 components and 101 entities. + - field 121 {part: 1516} with TimeFreq_steps location, 1 components and 101 entities. + - field 122 {part: 1517} with TimeFreq_steps location, 1 components and 101 entities. + - field 123 {part: 1518} with TimeFreq_steps location, 1 components and 101 entities. + - field 124 {part: 1519} with TimeFreq_steps location, 1 components and 101 entities. + - field 125 {part: 1520} with TimeFreq_steps location, 1 components and 101 entities. + - field 126 {part: 1521} with TimeFreq_steps location, 1 components and 101 entities. + - field 127 {part: 1522} with TimeFreq_steps location, 1 components and 101 entities. + - field 128 {part: 1523} with TimeFreq_steps location, 1 components and 101 entities. + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 111-112 + +Extract part internal energy for only a selected number of parts. + +.. GENERATED FROM PYTHON SOURCE LINES 112-118 + +.. code-block:: default + + + part_sco = dpf.Scoping(ids=[50, 1522], location="part") + PIE_op = model.results.part_internal_energy() + PIE_op.inputs.entity_scoping.connect(part_sco) + PIE = PIE_op.eval() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 119-122 + +Plot part kinetic and internal energy for a selection of parts. In this case, +the TimeFreqSupport of the matsum branch does not have all the time steps in +the binout file. Thus, a rescoping operation is needed: + +.. GENERATED FROM PYTHON SOURCE LINES 122-138 + +.. code-block:: default + + + rescope_op = dpf.operators.scoping.rescope() + rescope_op.inputs.fields.connect(PKE.time_freq_support.time_frequencies) + rescope_op.inputs.mesh_scoping.connect(PKE[0].scoping) + t_field = rescope_op.outputs.fields_as_field() + t_vals = t_field.data + + plt.plot(t_vals, PKE.get_field({"part": 50}).data, label="Kinetic, Part 50") + plt.plot(t_vals, PKE.get_field({"part": 1522}).data, label="Kinetic, Part 1522") + plt.plot(t_vals, PIE.get_field({"part": 50}).data, label="Internal, Part 50") + plt.plot(t_vals, PIE.get_field({"part": 1522}).data, label="Internal, Part 1522") + plt.xlabel("Time ({:s})".format(t_field.unit)) + plt.ylabel("Energy ({:s})".format(PIE.get_field({"part": 50}).unit)) + plt.legend() + plt.show() + + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_004.png + :alt: 02 lsdyna operators + :srcset: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_004.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 139-142 + +Similarly, results from the rcforc branch of the binout file are a +FieldsContainer on a LabelSpace comprised by interface IDs. Extract interface +contact force for only one interface. + +.. GENERATED FROM PYTHON SOURCE LINES 142-149 + +.. code-block:: default + + + interface_sco = dpf.Scoping(ids=[19], location="interface") + FC_op = model.results.interface_contact_force() + FC_op.inputs.entity_scoping.connect(interface_sco) + FC = FC_op.eval() + print(FC) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Fields Container + with 2 field(s) + defined on labels: idtype interface + + with: + - field 0 {interface: 19, idtype: 0} with TimeFreq_steps location, 3 components and 1001 entities. + - field 1 {interface: 19, idtype: 1} with TimeFreq_steps location, 3 components and 1001 entities. + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 150-153 + +In addition to interface, the FieldsContainer is scoped on idtype (0 for the +master side of the interface, 1 for the slave). Contact force is a vector, and +the three components are available. + +.. GENERATED FROM PYTHON SOURCE LINES 153-175 + +.. code-block:: default + + + rescope_op = dpf.operators.scoping.rescope() + rescope_op.inputs.fields.connect(FC.time_freq_support.time_frequencies) + rescope_op.inputs.mesh_scoping.connect(FC[0].scoping) + t_field = rescope_op.outputs.fields_as_field() + t_vals = t_field.data + + FX = FC.select_component(0) + FY = FC.select_component(1) + FZ = FC.select_component(2) + + plt.plot(t_vals, FX.get_field({"interface": 19, "idtype": 0}).data, label="FX, slave") + plt.plot(t_vals, FX.get_field({"interface": 19, "idtype": 1}).data, label="FX, master") + plt.plot(t_vals, FY.get_field({"interface": 19, "idtype": 0}).data, label="FY, slave") + plt.plot(t_vals, FY.get_field({"interface": 19, "idtype": 1}).data, label="FY, master") + plt.plot(t_vals, FZ.get_field({"interface": 19, "idtype": 0}).data, label="FZ, slave") + plt.plot(t_vals, FZ.get_field({"interface": 19, "idtype": 1}).data, label="FZ, master") + plt.xlabel("Time ({:s})".format(t_field.unit)) + plt.xlim([0, 10]) + plt.ylabel("Contact Force ({:s})".format(FX.get_field({"interface": 19, "idtype": 0}).unit)) + plt.legend() + plt.show() + + + +.. image-sg:: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_005.png + :alt: 02 lsdyna operators + :srcset: /examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_005.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 9.193 seconds) + + +.. _sphx_glr_download_examples_01-transient_analyses_02-lsdyna_operators.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 02-lsdyna_operators.py <02-lsdyna_operators.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 02-lsdyna_operators.ipynb <02-lsdyna_operators.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/01-transient_analyses/02-lsdyna_operators_codeobj.pickle b/doc/source/examples/01-transient_analyses/02-lsdyna_operators_codeobj.pickle new file mode 100644 index 0000000000..d183756ca1 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/02-lsdyna_operators_codeobj.pickle differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_001.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_001.png new file mode 100644 index 0000000000..9a5cfd9f65 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_001.png differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_002.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_002.png new file mode 100644 index 0000000000..7f3b6835a0 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_002.png differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_003.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_003.png new file mode 100644 index 0000000000..474936a023 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_003.png differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_004.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_004.png new file mode 100644 index 0000000000..f5e902259f Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_00-basic_transient_004.png differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_001.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_001.png new file mode 100644 index 0000000000..0deedc5d8e Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_001.png differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_002.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_002.png new file mode 100644 index 0000000000..e90df3984d Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_01-transient_easy_time_scoping_002.png differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_001.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_001.png new file mode 100644 index 0000000000..ab0fcfedb4 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_001.png differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_002.gif b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_002.gif new file mode 100644 index 0000000000..64ee1beeb4 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_002.gif differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_003.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_003.png new file mode 100644 index 0000000000..fd06de055a Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_003.png differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_004.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_004.png new file mode 100644 index 0000000000..e85def0bdf Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_004.png differ diff --git a/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_005.png b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_005.png new file mode 100644 index 0000000000..f178118414 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/sphx_glr_02-lsdyna_operators_005.png differ diff --git a/doc/source/examples/01-transient_analyses/images/thumb/sphx_glr_00-basic_transient_thumb.png b/doc/source/examples/01-transient_analyses/images/thumb/sphx_glr_00-basic_transient_thumb.png new file mode 100644 index 0000000000..d87a61f622 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/thumb/sphx_glr_00-basic_transient_thumb.png differ diff --git a/doc/source/examples/01-transient_analyses/images/thumb/sphx_glr_01-transient_easy_time_scoping_thumb.png b/doc/source/examples/01-transient_analyses/images/thumb/sphx_glr_01-transient_easy_time_scoping_thumb.png new file mode 100644 index 0000000000..394b20c972 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/thumb/sphx_glr_01-transient_easy_time_scoping_thumb.png differ diff --git a/doc/source/examples/01-transient_analyses/images/thumb/sphx_glr_02-lsdyna_operators_thumb.png b/doc/source/examples/01-transient_analyses/images/thumb/sphx_glr_02-lsdyna_operators_thumb.png new file mode 100644 index 0000000000..0cd9f67217 Binary files /dev/null and b/doc/source/examples/01-transient_analyses/images/thumb/sphx_glr_02-lsdyna_operators_thumb.png differ diff --git a/doc/source/examples/01-transient_analyses/index.rst b/doc/source/examples/01-transient_analyses/index.rst new file mode 100644 index 0000000000..f8009f1753 --- /dev/null +++ b/doc/source/examples/01-transient_analyses/index.rst @@ -0,0 +1,81 @@ + + +.. _sphx_glr_examples_01-transient_analyses: + +.. _static_transient_examples: + +Transient analysis examples +=========================== +These examples show how to use DPF to extract and plot displacements, +stresses, and strains for a transient result. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/01-transient_analyses/images/thumb/sphx_glr_00-basic_transient_thumb.png + :alt: Transient analysis result example + + :ref:`sphx_glr_examples_01-transient_analyses_00-basic_transient.py` + +.. raw:: html + +
Transient analysis result example
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/01-transient_analyses/images/thumb/sphx_glr_01-transient_easy_time_scoping_thumb.png + :alt: Choose a time scoping for a transient analysis + + :ref:`sphx_glr_examples_01-transient_analyses_01-transient_easy_time_scoping.py` + +.. raw:: html + +
Choose a time scoping for a transient analysis
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/01-transient_analyses/images/thumb/sphx_glr_02-lsdyna_operators_thumb.png + :alt: Results extraction and analysis from LS-DYNA sources + + :ref:`sphx_glr_examples_01-transient_analyses_02-lsdyna_operators.py` + +.. raw:: html + +
Results extraction and analysis from LS-DYNA sources
+
+ + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /examples/01-transient_analyses/00-basic_transient + /examples/01-transient_analyses/01-transient_easy_time_scoping + /examples/01-transient_analyses/02-lsdyna_operators + diff --git a/doc/source/examples/01-transient_analyses/sg_execution_times.rst b/doc/source/examples/01-transient_analyses/sg_execution_times.rst new file mode 100644 index 0000000000..1bf27357e1 --- /dev/null +++ b/doc/source/examples/01-transient_analyses/sg_execution_times.rst @@ -0,0 +1,16 @@ + +:orphan: + +.. _sphx_glr_examples_01-transient_analyses_sg_execution_times: + +Computation times +================= +**00:10.165** total execution time for **examples_01-transient_analyses** files: + ++--------------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_01-transient_analyses_02-lsdyna_operators.py` (``02-lsdyna_operators.py``) | 00:09.193 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_01-transient_analyses_00-basic_transient.py` (``00-basic_transient.py``) | 00:00.703 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_01-transient_analyses_01-transient_easy_time_scoping.py` (``01-transient_easy_time_scoping.py``) | 00:00.268 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------------+-----------+--------+ diff --git a/doc/source/examples/02-modal_analyses/00-compare_modes.ipynb b/doc/source/examples/02-modal_analyses/00-compare_modes.ipynb new file mode 100644 index 0000000000..5395158f77 --- /dev/null +++ b/doc/source/examples/02-modal_analyses/00-compare_modes.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use Result Helpers to compare mode shapes for solids and then shells {#ref_compare_modes}\r\n\r\nThe `Result `{.interpreted-text\r\nrole=\"class\"} class which instances are created by the\r\n`Model `{.interpreted-text role=\"class\"}\r\ngives access to helpers to request results on specific mesh and time\r\nscopings. With those helpers, working on a custom spatial and temporal\r\nsubset of the model is straightforward.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, create a model object to establish a connection with an example\r\nresult file\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.download_all_kinds_of_complexity_modal())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Visualize specific mode shapes\r\n\r\nChoose the modes to visualize\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "modes = [1, 5, 10, 15]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Choose to split the displacement on solid/shell/beam to only focus on\r\nshell elements\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement\nfor mode in modes:\n fc = disp.on_time_scoping(mode).split_by_shape.eval()\n model.metadata.meshed_region.plot(fc.shell_field())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Choose to split the displacement on solid/shell/beam to only focus on\r\nsolid elements\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement\nfor mode in modes:\n fc = disp.on_time_scoping(mode).split_by_shape.eval()\n model.metadata.meshed_region.plot(fc.solid_field())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/02-modal_analyses/00-compare_modes.py b/doc/source/examples/02-modal_analyses/00-compare_modes.py new file mode 100644 index 0000000000..0a1c86e555 --- /dev/null +++ b/doc/source/examples/02-modal_analyses/00-compare_modes.py @@ -0,0 +1,44 @@ +# noqa: D400 +""" +.. _ref_compare_modes: + +Use Result Helpers to compare mode shapes for solids and then shells +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :class:`Result ` class which instances +are created by the :class:`Model ` gives access to +helpers to request results on specific mesh and time scopings. +With those helpers, working on a custom spatial and temporal subset of the +model is straightforward. +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# First, create a model object to establish a connection with an +# example result file +model = dpf.Model(examples.download_all_kinds_of_complexity_modal()) +print(model) + +############################################################################### +# Visualize specific mode shapes +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Choose the modes to visualize +modes = [1, 5, 10, 15] + +############################################################################### +# Choose to split the displacement on solid/shell/beam to only focus on shell +# elements +disp = model.results.displacement +for mode in modes: + fc = disp.on_time_scoping(mode).split_by_shape.eval() + model.metadata.meshed_region.plot(fc.shell_field()) + +############################################################################### +# Choose to split the displacement on solid/shell/beam to only focus on solid +# elements +disp = model.results.displacement +for mode in modes: + fc = disp.on_time_scoping(mode).split_by_shape.eval() + model.metadata.meshed_region.plot(fc.solid_field()) diff --git a/doc/source/examples/02-modal_analyses/00-compare_modes.py.md5 b/doc/source/examples/02-modal_analyses/00-compare_modes.py.md5 new file mode 100644 index 0000000000..e0c74b67ea --- /dev/null +++ b/doc/source/examples/02-modal_analyses/00-compare_modes.py.md5 @@ -0,0 +1 @@ +a121c6967e7fc49afe2a8450e11b1f13 \ No newline at end of file diff --git a/doc/source/examples/02-modal_analyses/00-compare_modes.rst b/doc/source/examples/02-modal_analyses/00-compare_modes.rst new file mode 100644 index 0000000000..4beca2e30c --- /dev/null +++ b/doc/source/examples/02-modal_analyses/00-compare_modes.rst @@ -0,0 +1,295 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\02-modal_analyses\00-compare_modes.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_02-modal_analyses_00-compare_modes.py: + + +.. _ref_compare_modes: + +Use Result Helpers to compare mode shapes for solids and then shells +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :class:`Result ` class which instances +are created by the :class:`Model ` gives access to +helpers to request results on specific mesh and time scopings. +With those helpers, working on a custom spatial and temporal subset of the +model is straightforward. + +.. GENERATED FROM PYTHON SOURCE LINES 14-18 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 19-21 + +First, create a model object to establish a connection with an +example result file + +.. GENERATED FROM PYTHON SOURCE LINES 21-24 + +.. code-block:: default + + model = dpf.Model(examples.download_all_kinds_of_complexity_modal()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Modal analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - element_nodal_forces: ElementalNodal Element nodal Forces + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 2388 nodes + 1824 elements + Unit: m + With solid (3D) elements, shell (2D) elements, shell (3D) elements, beam (1D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 45 + Cumulative Frequency (Hz) LoadStep Substep + 1 4800,665229 1 1 + 2 6472,119402 1 2 + 3 10094,813112 1 3 + 4 15408,070193 1 4 + 5 19935,616102 1 5 + 6 30659,224027 1 6 + 7 33485,028985 1 7 + 8 40514,020302 1 8 + 9 41144,836724 1 9 + 10 41696,364343 1 10 + 11 42568,142453 1 11 + 12 48803,935725 1 12 + 13 51557,014600 1 13 + 14 54829,807966 1 14 + 15 55121,065060 1 15 + 16 55481,661956 1 16 + 17 55779,054274 1 17 + 18 56346,453210 1 18 + 19 56598,396154 1 19 + 20 57504,056787 1 20 + 21 57768,209089 1 21 + 22 60135,893137 1 22 + 23 62336,016111 1 23 + 24 62809,029190 1 24 + 25 64186,171203 1 25 + 26 64911,479227 1 26 + 27 66488,724651 1 27 + 28 66728,182829 1 28 + 29 67521,333063 1 29 + 30 68699,230845 1 30 + 31 70108,268581 1 31 + 32 71432,124756 1 32 + 33 71784,765113 1 33 + 34 73189,275762 1 34 + 35 74862,553459 1 35 + 36 75051,318416 1 36 + 37 76335,025905 1 37 + 38 76631,728520 1 38 + 39 76956,786796 1 39 + 40 77754,144888 1 40 + 41 78460,122703 1 41 + 42 78721,878185 1 42 + 43 79330,520798 1 43 + 44 80301,992725 1 44 + 45 80835,840814 1 45 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 25-28 + +Visualize specific mode shapes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Choose the modes to visualize + +.. GENERATED FROM PYTHON SOURCE LINES 28-30 + +.. code-block:: default + + modes = [1, 5, 10, 15] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 31-33 + +Choose to split the displacement on solid/shell/beam to only focus on shell +elements + +.. GENERATED FROM PYTHON SOURCE LINES 33-38 + +.. code-block:: default + + disp = model.results.displacement + for mode in modes: + fc = disp.on_time_scoping(mode).split_by_shape.eval() + model.metadata.meshed_region.plot(fc.shell_field()) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_001.png + :alt: 00 compare modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_002.png + :alt: 00 compare modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_003.png + :alt: 00 compare modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_004.png + :alt: 00 compare modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_004.png + :class: sphx-glr-multi-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 39-41 + +Choose to split the displacement on solid/shell/beam to only focus on solid +elements + +.. GENERATED FROM PYTHON SOURCE LINES 41-45 + +.. code-block:: default + + disp = model.results.displacement + for mode in modes: + fc = disp.on_time_scoping(mode).split_by_shape.eval() + model.metadata.meshed_region.plot(fc.solid_field()) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_005.png + :alt: 00 compare modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_005.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_006.png + :alt: 00 compare modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_006.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_007.png + :alt: 00 compare modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_007.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_008.png + :alt: 00 compare modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_00-compare_modes_008.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 5.023 seconds) + + +.. _sphx_glr_download_examples_02-modal_analyses_00-compare_modes.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 00-compare_modes.py <00-compare_modes.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 00-compare_modes.ipynb <00-compare_modes.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/02-modal_analyses/00-compare_modes_codeobj.pickle b/doc/source/examples/02-modal_analyses/00-compare_modes_codeobj.pickle new file mode 100644 index 0000000000..a7deb182fc Binary files /dev/null and b/doc/source/examples/02-modal_analyses/00-compare_modes_codeobj.pickle differ diff --git a/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.ipynb b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.ipynb new file mode 100644 index 0000000000..519d93128f --- /dev/null +++ b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.ipynb @@ -0,0 +1,108 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot and animate mode shapes with DPF {#ref_plot_and_animate_modes}\r\n\r\nThis example shows how to extract mode shapes from a modal analysis\r\nresult and how to plot and animate them.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import animation\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Retrieve mode shapes\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Load the result file as a model\nmodel = dpf.Model(examples.download_modal_frame())\nprint(model)\n\n# Extract the displacement results which define mode shapes\ndisp = model.results.displacement.on_all_time_freqs.eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot mode shapes\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Get the frequency scoping (available frequency IDs for disp)\nfreq_scoping = disp.get_time_scoping()\n# Get the frequency support (all available frequencies in the model)\nfreq_support = disp.time_freq_support\n# Get the unit from the time_freq_support\nunit = freq_support.time_frequencies.unit\n\n# For each ID in the scoping\nfor freq_set in freq_scoping:\n # Get the associated frequency in the time_freq_support\n freq = freq_support.get_frequency(cumulative_index=freq_set - 1)\n # Get the associated mode shape as a displacement field\n disp_mode = disp.get_field_by_time_complex_ids(freq_set, 0)\n # Extract the mode frequency and unit\n text = f\"{freq:.3f}{unit}\"\n # Plot the mode displacement field on the deformed mesh\n disp_mode.plot(deform_by=disp_mode, scale_factor=2.0, text=text)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Animate a mode shape\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "animation.animate_mode(disp, mode_number=1, save_as=\"tmp.gif\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.py b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.py new file mode 100644 index 0000000000..04c4e8adac --- /dev/null +++ b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.py @@ -0,0 +1,53 @@ +""" +.. _ref_plot_and_animate_modes: + +Plot and animate mode shapes with DPF +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to extract mode shapes from a modal analysis result +and how to plot and animate them. + +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import animation +from ansys.dpf.core import examples + +############################################################################### +# Retrieve mode shapes +# ~~~~~~~~~~~~~~~~~~~~ + +# Load the result file as a model +model = dpf.Model(examples.download_modal_frame()) +print(model) + +# Extract the displacement results which define mode shapes +disp = model.results.displacement.on_all_time_freqs.eval() + +############################################################################### +# Plot mode shapes +# ~~~~~~~~~~~~~~~~ + +# Get the frequency scoping (available frequency IDs for disp) +freq_scoping = disp.get_time_scoping() +# Get the frequency support (all available frequencies in the model) +freq_support = disp.time_freq_support +# Get the unit from the time_freq_support +unit = freq_support.time_frequencies.unit + +# For each ID in the scoping +for freq_set in freq_scoping: + # Get the associated frequency in the time_freq_support + freq = freq_support.get_frequency(cumulative_index=freq_set - 1) + # Get the associated mode shape as a displacement field + disp_mode = disp.get_field_by_time_complex_ids(freq_set, 0) + # Extract the mode frequency and unit + text = f"{freq:.3f}{unit}" + # Plot the mode displacement field on the deformed mesh + disp_mode.plot(deform_by=disp_mode, scale_factor=2.0, text=text) + +############################################################################### +# Animate a mode shape +# ~~~~~~~~~~~~~~~~~~~~ + +animation.animate_mode(disp, mode_number=1, save_as="tmp.gif") diff --git a/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.py.md5 b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.py.md5 new file mode 100644 index 0000000000..e4aaae9346 --- /dev/null +++ b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.py.md5 @@ -0,0 +1 @@ +01118fb173f42036ba613936d9a14d91 \ No newline at end of file diff --git a/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.rst b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.rst new file mode 100644 index 0000000000..6e0365c6f9 --- /dev/null +++ b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes.rst @@ -0,0 +1,230 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\02-modal_analyses\01-plot_and_animate_modes.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_02-modal_analyses_01-plot_and_animate_modes.py: + + +.. _ref_plot_and_animate_modes: + +Plot and animate mode shapes with DPF +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to extract mode shapes from a modal analysis result +and how to plot and animate them. + +.. GENERATED FROM PYTHON SOURCE LINES 11-16 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import animation + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 17-19 + +Retrieve mode shapes +~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 19-27 + +.. code-block:: default + + + # Load the result file as a model + model = dpf.Model(examples.download_modal_frame()) + print(model) + + # Extract the displacement results which define mode shapes + disp = model.results.displacement.on_all_time_freqs.eval() + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Modal analysis + Unit system: NMM: mm, ton, N, s, mV, mA, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - stress: ElementalNodal Stress + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + ------------------------------ + DPF Meshed Region: + 5886 nodes + 2842 elements + Unit: mm + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 6 + Cumulative Frequency (Hz) LoadStep Substep + 1 253,615690 1 1 + 2 317,918491 1 2 + 3 329,825709 1 3 + 4 575,619678 1 4 + 5 621,973976 1 5 + 6 667,364882 1 6 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 28-30 + +Plot mode shapes +~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 30-49 + +.. code-block:: default + + + # Get the frequency scoping (available frequency IDs for disp) + freq_scoping = disp.get_time_scoping() + # Get the frequency support (all available frequencies in the model) + freq_support = disp.time_freq_support + # Get the unit from the time_freq_support + unit = freq_support.time_frequencies.unit + + # For each ID in the scoping + for freq_set in freq_scoping: + # Get the associated frequency in the time_freq_support + freq = freq_support.get_frequency(cumulative_index=freq_set - 1) + # Get the associated mode shape as a displacement field + disp_mode = disp.get_field_by_time_complex_ids(freq_set, 0) + # Extract the mode frequency and unit + text = f"{freq:.3f}{unit}" + # Plot the mode displacement field on the deformed mesh + disp_mode.plot(deform_by=disp_mode, scale_factor=2.0, text=text) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_001.png + :alt: 01 plot and animate modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_002.png + :alt: 01 plot and animate modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_003.png + :alt: 01 plot and animate modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_004.png + :alt: 01 plot and animate modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_005.png + :alt: 01 plot and animate modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_005.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_006.png + :alt: 01 plot and animate modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_006.png + :class: sphx-glr-multi-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 50-52 + +Animate a mode shape +~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 52-54 + +.. code-block:: default + + + animation.animate_mode(disp, mode_number=1, save_as="tmp.gif") + + + +.. image-sg:: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_007.gif + :alt: 01 plot and animate modes + :srcset: /examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_007.gif + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 19.542 seconds) + + +.. _sphx_glr_download_examples_02-modal_analyses_01-plot_and_animate_modes.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 01-plot_and_animate_modes.py <01-plot_and_animate_modes.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 01-plot_and_animate_modes.ipynb <01-plot_and_animate_modes.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes_codeobj.pickle b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes_codeobj.pickle new file mode 100644 index 0000000000..a7e6be8dc7 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/01-plot_and_animate_modes_codeobj.pickle differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_001.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_001.png new file mode 100644 index 0000000000..86900c3e02 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_001.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_002.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_002.png new file mode 100644 index 0000000000..4e9e89d3fe Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_002.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_003.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_003.png new file mode 100644 index 0000000000..59d6897985 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_003.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_004.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_004.png new file mode 100644 index 0000000000..f541949554 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_004.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_005.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_005.png new file mode 100644 index 0000000000..370e5c20bd Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_005.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_006.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_006.png new file mode 100644 index 0000000000..4822cdd61e Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_006.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_007.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_007.png new file mode 100644 index 0000000000..f206788e1a Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_007.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_008.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_008.png new file mode 100644 index 0000000000..875dbefc73 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_00-compare_modes_008.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_001.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_001.png new file mode 100644 index 0000000000..cebaf56fd2 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_001.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_002.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_002.png new file mode 100644 index 0000000000..64f112171b Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_002.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_003.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_003.png new file mode 100644 index 0000000000..3a554e7383 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_003.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_004.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_004.png new file mode 100644 index 0000000000..1942bdc3a6 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_004.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_005.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_005.png new file mode 100644 index 0000000000..f1920bc9e0 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_005.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_006.png b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_006.png new file mode 100644 index 0000000000..a0f901a60c Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_006.png differ diff --git a/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_007.gif b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_007.gif new file mode 100644 index 0000000000..dfb978149a Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/sphx_glr_01-plot_and_animate_modes_007.gif differ diff --git a/doc/source/examples/02-modal_analyses/images/thumb/sphx_glr_00-compare_modes_thumb.png b/doc/source/examples/02-modal_analyses/images/thumb/sphx_glr_00-compare_modes_thumb.png new file mode 100644 index 0000000000..eb9f48c67b Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/thumb/sphx_glr_00-compare_modes_thumb.png differ diff --git a/doc/source/examples/02-modal_analyses/images/thumb/sphx_glr_01-plot_and_animate_modes_thumb.png b/doc/source/examples/02-modal_analyses/images/thumb/sphx_glr_01-plot_and_animate_modes_thumb.png new file mode 100644 index 0000000000..2e56939646 Binary files /dev/null and b/doc/source/examples/02-modal_analyses/images/thumb/sphx_glr_01-plot_and_animate_modes_thumb.png differ diff --git a/doc/source/examples/02-modal_analyses/index.rst b/doc/source/examples/02-modal_analyses/index.rst new file mode 100644 index 0000000000..09e1cd4203 --- /dev/null +++ b/doc/source/examples/02-modal_analyses/index.rst @@ -0,0 +1,63 @@ + + +.. _sphx_glr_examples_02-modal_analyses: + +.. _modal_examples: + +Modal analysis examples +======================= +These examples show how to use DPF to extract and manipulate +results from modal analyses. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/02-modal_analyses/images/thumb/sphx_glr_00-compare_modes_thumb.png + :alt: Use Result Helpers to compare mode shapes for solids and then shells + + :ref:`sphx_glr_examples_02-modal_analyses_00-compare_modes.py` + +.. raw:: html + +
Use Result Helpers to compare mode shapes for solids and then shells
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/02-modal_analyses/images/thumb/sphx_glr_01-plot_and_animate_modes_thumb.png + :alt: Plot and animate mode shapes with DPF + + :ref:`sphx_glr_examples_02-modal_analyses_01-plot_and_animate_modes.py` + +.. raw:: html + +
Plot and animate mode shapes with DPF
+
+ + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /examples/02-modal_analyses/00-compare_modes + /examples/02-modal_analyses/01-plot_and_animate_modes + diff --git a/doc/source/examples/02-modal_analyses/sg_execution_times.rst b/doc/source/examples/02-modal_analyses/sg_execution_times.rst new file mode 100644 index 0000000000..e7291e187b --- /dev/null +++ b/doc/source/examples/02-modal_analyses/sg_execution_times.rst @@ -0,0 +1,14 @@ + +:orphan: + +.. _sphx_glr_examples_02-modal_analyses_sg_execution_times: + +Computation times +================= +**00:24.564** total execution time for **examples_02-modal_analyses** files: + ++------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_02-modal_analyses_01-plot_and_animate_modes.py` (``01-plot_and_animate_modes.py``) | 00:19.542 | 0.0 MB | ++------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_02-modal_analyses_00-compare_modes.py` (``00-compare_modes.py``) | 00:05.023 | 0.0 MB | ++------------------------------------------------------------------------------------------------------------+-----------+--------+ diff --git a/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.ipynb b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.ipynb new file mode 100644 index 0000000000..106774931d --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Multi-harmonic response example {#ref_basic_harmonic}\r\n\r\nThis example shows how to compute a multi-harmonic response using `fft`\r\ntransformations.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as pyplot\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Begin by downloading the example harmonic result. This result is not\r\nincluded in the core module by default to speed up the install. Download\r\nshould only take a few seconds.\r\n\r\nNext, create the model and display the state of the result. This\r\nharmonic result file contains several RPMs, and each RPM has several\r\nfrequencies.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# The size of this file is 66 MB. Downloading it might take some time.\nharmonic = examples.download_multi_harmonic_result()\nmodel = dpf.Model(harmonic)\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read the analysis domain support\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "tf = model.metadata.time_freq_support\nprint(\"Number of solution sets\", tf.n_sets)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compute multi-harmonic response\r\n\r\nThis example computes the Rz multi-harmonic responses based on selected\r\nnodes and a set of EOs (engine orders).\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create a total displacement operator and set its time scoping to\n# the entire time frequency support and its nodes scoping to user-defined nodes.\ndisp_op = ops.result.raw_displacement(data_sources=model)\ntime_ids = list(range(1, model.metadata.time_freq_support.n_sets + 1))\n\n# Define nodal scoping\nnodes = dpf.Scoping()\nnodes.ids = [2, 18]\n\n# Connect the frequencies and the nodes scopings to the result\n# provider operator.\ndisp_op.inputs.mesh_scoping.connect(nodes)\ndisp_op.inputs.time_scoping.connect(time_ids)\n\n# Extract the Rz component using the component selector operator.\ncomp = dpf.Operator(\"component_selector_fc\")\ncomp.inputs.connect(disp_op.outputs)\ncomp.inputs.component_number.connect(5)\n\n# Compute the multi-harmonic response based on Rz and a set of RPMs.\nrpms = dpf.Scoping()\nrpms.ids = [1, 2, 3]\n\nfft = ops.math.fft_multi_harmonic_minmax()\n\nfft.inputs.connect(comp.outputs)\nfft.inputs.rpm_scoping.connect(rpms)\n\nfields = fft.outputs.field_max()\nlen(fields) # one multi-harmonic field response per node\n\nfield1 = fields[0]\nfield2 = fields[1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the minimum and maximum displacements over time.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pyplot.plot(field1.data, \"r\", label=\"Field 1\")\npyplot.plot(field2.data, \"b\", label=\"Field 2\")\npyplot.xlabel(\"Frequency (Hz)\")\npyplot.ylabel(\"Displacement (m)\")\npyplot.legend()\npyplot.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.py b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.py new file mode 100644 index 0000000000..0118b326bd --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.py @@ -0,0 +1,85 @@ +""" +.. _ref_basic_harmonic: + +Multi-harmonic response example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to compute a multi-harmonic response +using ``fft`` transformations. + +""" +import matplotlib.pyplot as pyplot + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + + +############################################################################### +# Begin by downloading the example harmonic result. This result is +# not included in the core module by default to speed up the install. +# Download should only take a few seconds. +# +# Next, create the model and display the state of the result. +# This harmonic result file contains several RPMs, and +# each RPM has several frequencies. + +# The size of this file is 66 MB. Downloading it might take some time. +harmonic = examples.download_multi_harmonic_result() +model = dpf.Model(harmonic) +print(model) + +############################################################################### +# Read the analysis domain support +tf = model.metadata.time_freq_support +print("Number of solution sets", tf.n_sets) + +############################################################################### +# Compute multi-harmonic response +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This example computes the Rz multi-harmonic responses based on +# selected nodes and a set of EOs (engine orders). + +# Create a total displacement operator and set its time scoping to +# the entire time frequency support and its nodes scoping to user-defined nodes. +disp_op = ops.result.raw_displacement(data_sources=model) +time_ids = list(range(1, model.metadata.time_freq_support.n_sets + 1)) + +# Define nodal scoping +nodes = dpf.Scoping() +nodes.ids = [2, 18] + +# Connect the frequencies and the nodes scopings to the result +# provider operator. +disp_op.inputs.mesh_scoping.connect(nodes) +disp_op.inputs.time_scoping.connect(time_ids) + +# Extract the Rz component using the component selector operator. +comp = dpf.Operator("component_selector_fc") +comp.inputs.connect(disp_op.outputs) +comp.inputs.component_number.connect(5) + +# Compute the multi-harmonic response based on Rz and a set of RPMs. +rpms = dpf.Scoping() +rpms.ids = [1, 2, 3] + +fft = ops.math.fft_multi_harmonic_minmax() + +fft.inputs.connect(comp.outputs) +fft.inputs.rpm_scoping.connect(rpms) + +fields = fft.outputs.field_max() +len(fields) # one multi-harmonic field response per node + +field1 = fields[0] +field2 = fields[1] + +############################################################################### +# Plot the minimum and maximum displacements over time. + +pyplot.plot(field1.data, "r", label="Field 1") +pyplot.plot(field2.data, "b", label="Field 2") +pyplot.xlabel("Frequency (Hz)") +pyplot.ylabel("Displacement (m)") +pyplot.legend() +pyplot.show() diff --git a/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.py.md5 b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.py.md5 new file mode 100644 index 0000000000..4581b9bbe4 --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.py.md5 @@ -0,0 +1 @@ +a75ca5e5ddc2a72e7fe441a996435407 \ No newline at end of file diff --git a/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.rst b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.rst new file mode 100644 index 0000000000..05231fe7cb --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic.rst @@ -0,0 +1,1230 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\03-harmonic_analyses\00-multi_harmonic.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_03-harmonic_analyses_00-multi_harmonic.py: + + +.. _ref_basic_harmonic: + +Multi-harmonic response example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to compute a multi-harmonic response +using ``fft`` transformations. + +.. GENERATED FROM PYTHON SOURCE LINES 11-18 + +.. code-block:: default + + import matplotlib.pyplot as pyplot + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 19-26 + +Begin by downloading the example harmonic result. This result is +not included in the core module by default to speed up the install. +Download should only take a few seconds. + +Next, create the model and display the state of the result. +This harmonic result file contains several RPMs, and +each RPM has several frequencies. + +.. GENERATED FROM PYTHON SOURCE LINES 26-32 + +.. code-block:: default + + + # The size of this file is 66 MB. Downloading it might take some time. + harmonic = examples.download_multi_harmonic_result() + model = dpf.Model(harmonic) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Harmonic analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 88 nodes + 33 elements + Unit: m + With beam (1D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1000 + With complex values + + Cumulative Frequency (Hz) LoadStep Substep RPM + 1 1,000000 1 1 100,000000 + 2 2,000000 1 2 100,000000 + 3 3,000000 1 3 100,000000 + 4 4,000000 1 4 100,000000 + 5 5,000000 1 5 100,000000 + 6 6,000000 1 6 100,000000 + 7 7,000000 1 7 100,000000 + 8 8,000000 1 8 100,000000 + 9 9,000000 1 9 100,000000 + 10 10,000000 1 10 100,000000 + 11 11,000000 1 11 100,000000 + 12 12,000000 1 12 100,000000 + 13 13,000000 1 13 100,000000 + 14 14,000000 1 14 100,000000 + 15 15,000000 1 15 100,000000 + 16 16,000000 1 16 100,000000 + 17 17,000000 1 17 100,000000 + 18 18,000000 1 18 100,000000 + 19 19,000000 1 19 100,000000 + 20 20,000000 1 20 100,000000 + 21 21,000000 1 21 100,000000 + 22 22,000000 1 22 100,000000 + 23 23,000000 1 23 100,000000 + 24 24,000000 1 24 100,000000 + 25 25,000000 1 25 100,000000 + 26 26,000000 1 26 100,000000 + 27 27,000000 1 27 100,000000 + 28 28,000000 1 28 100,000000 + 29 29,000000 1 29 100,000000 + 30 30,000000 1 30 100,000000 + 31 31,000000 1 31 100,000000 + 32 32,000000 1 32 100,000000 + 33 33,000000 1 33 100,000000 + 34 34,000000 1 34 100,000000 + 35 35,000000 1 35 100,000000 + 36 36,000000 1 36 100,000000 + 37 37,000000 1 37 100,000000 + 38 38,000000 1 38 100,000000 + 39 39,000000 1 39 100,000000 + 40 40,000000 1 40 100,000000 + 41 41,000000 1 41 100,000000 + 42 42,000000 1 42 100,000000 + 43 43,000000 1 43 100,000000 + 44 44,000000 1 44 100,000000 + 45 45,000000 1 45 100,000000 + 46 46,000000 1 46 100,000000 + 47 47,000000 1 47 100,000000 + 48 48,000000 1 48 100,000000 + 49 49,000000 1 49 100,000000 + 50 50,000000 1 50 100,000000 + 51 51,000000 1 51 100,000000 + 52 52,000000 1 52 100,000000 + 53 53,000000 1 53 100,000000 + 54 54,000000 1 54 100,000000 + 55 55,000000 1 55 100,000000 + 56 56,000000 1 56 100,000000 + 57 57,000000 1 57 100,000000 + 58 58,000000 1 58 100,000000 + 59 59,000000 1 59 100,000000 + 60 60,000000 1 60 100,000000 + 61 61,000000 1 61 100,000000 + 62 62,000000 1 62 100,000000 + 63 63,000000 1 63 100,000000 + 64 64,000000 1 64 100,000000 + 65 65,000000 1 65 100,000000 + 66 66,000000 1 66 100,000000 + 67 67,000000 1 67 100,000000 + 68 68,000000 1 68 100,000000 + 69 69,000000 1 69 100,000000 + 70 70,000000 1 70 100,000000 + 71 71,000000 1 71 100,000000 + 72 72,000000 1 72 100,000000 + 73 73,000000 1 73 100,000000 + 74 74,000000 1 74 100,000000 + 75 75,000000 1 75 100,000000 + 76 76,000000 1 76 100,000000 + 77 77,000000 1 77 100,000000 + 78 78,000000 1 78 100,000000 + 79 79,000000 1 79 100,000000 + 80 80,000000 1 80 100,000000 + 81 81,000000 1 81 100,000000 + 82 82,000000 1 82 100,000000 + 83 83,000000 1 83 100,000000 + 84 84,000000 1 84 100,000000 + 85 85,000000 1 85 100,000000 + 86 86,000000 1 86 100,000000 + 87 87,000000 1 87 100,000000 + 88 88,000000 1 88 100,000000 + 89 89,000000 1 89 100,000000 + 90 90,000000 1 90 100,000000 + 91 91,000000 1 91 100,000000 + 92 92,000000 1 92 100,000000 + 93 93,000000 1 93 100,000000 + 94 94,000000 1 94 100,000000 + 95 95,000000 1 95 100,000000 + 96 96,000000 1 96 100,000000 + 97 97,000000 1 97 100,000000 + 98 98,000000 1 98 100,000000 + 99 99,000000 1 99 100,000000 + 100 100,000000 1 100 100,000000 + 101 101,000000 1 101 100,000000 + 102 102,000000 1 102 100,000000 + 103 103,000000 1 103 100,000000 + 104 104,000000 1 104 100,000000 + 105 105,000000 1 105 100,000000 + 106 106,000000 1 106 100,000000 + 107 107,000000 1 107 100,000000 + 108 108,000000 1 108 100,000000 + 109 109,000000 1 109 100,000000 + 110 110,000000 1 110 100,000000 + 111 111,000000 1 111 100,000000 + 112 112,000000 1 112 100,000000 + 113 113,000000 1 113 100,000000 + 114 114,000000 1 114 100,000000 + 115 115,000000 1 115 100,000000 + 116 116,000000 1 116 100,000000 + 117 117,000000 1 117 100,000000 + 118 118,000000 1 118 100,000000 + 119 119,000000 1 119 100,000000 + 120 120,000000 1 120 100,000000 + 121 121,000000 1 121 100,000000 + 122 122,000000 1 122 100,000000 + 123 123,000000 1 123 100,000000 + 124 124,000000 1 124 100,000000 + 125 125,000000 1 125 100,000000 + 126 126,000000 1 126 100,000000 + 127 127,000000 1 127 100,000000 + 128 128,000000 1 128 100,000000 + 129 129,000000 1 129 100,000000 + 130 130,000000 1 130 100,000000 + 131 131,000000 1 131 100,000000 + 132 132,000000 1 132 100,000000 + 133 133,000000 1 133 100,000000 + 134 134,000000 1 134 100,000000 + 135 135,000000 1 135 100,000000 + 136 136,000000 1 136 100,000000 + 137 137,000000 1 137 100,000000 + 138 138,000000 1 138 100,000000 + 139 139,000000 1 139 100,000000 + 140 140,000000 1 140 100,000000 + 141 141,000000 1 141 100,000000 + 142 142,000000 1 142 100,000000 + 143 143,000000 1 143 100,000000 + 144 144,000000 1 144 100,000000 + 145 145,000000 1 145 100,000000 + 146 146,000000 1 146 100,000000 + 147 147,000000 1 147 100,000000 + 148 148,000000 1 148 100,000000 + 149 149,000000 1 149 100,000000 + 150 150,000000 1 150 100,000000 + 151 151,000000 1 151 100,000000 + 152 152,000000 1 152 100,000000 + 153 153,000000 1 153 100,000000 + 154 154,000000 1 154 100,000000 + 155 155,000000 1 155 100,000000 + 156 156,000000 1 156 100,000000 + 157 157,000000 1 157 100,000000 + 158 158,000000 1 158 100,000000 + 159 159,000000 1 159 100,000000 + 160 160,000000 1 160 100,000000 + 161 161,000000 1 161 100,000000 + 162 162,000000 1 162 100,000000 + 163 163,000000 1 163 100,000000 + 164 164,000000 1 164 100,000000 + 165 165,000000 1 165 100,000000 + 166 166,000000 1 166 100,000000 + 167 167,000000 1 167 100,000000 + 168 168,000000 1 168 100,000000 + 169 169,000000 1 169 100,000000 + 170 170,000000 1 170 100,000000 + 171 171,000000 1 171 100,000000 + 172 172,000000 1 172 100,000000 + 173 173,000000 1 173 100,000000 + 174 174,000000 1 174 100,000000 + 175 175,000000 1 175 100,000000 + 176 176,000000 1 176 100,000000 + 177 177,000000 1 177 100,000000 + 178 178,000000 1 178 100,000000 + 179 179,000000 1 179 100,000000 + 180 180,000000 1 180 100,000000 + 181 181,000000 1 181 100,000000 + 182 182,000000 1 182 100,000000 + 183 183,000000 1 183 100,000000 + 184 184,000000 1 184 100,000000 + 185 185,000000 1 185 100,000000 + 186 186,000000 1 186 100,000000 + 187 187,000000 1 187 100,000000 + 188 188,000000 1 188 100,000000 + 189 189,000000 1 189 100,000000 + 190 190,000000 1 190 100,000000 + 191 191,000000 1 191 100,000000 + 192 192,000000 1 192 100,000000 + 193 193,000000 1 193 100,000000 + 194 194,000000 1 194 100,000000 + 195 195,000000 1 195 100,000000 + 196 196,000000 1 196 100,000000 + 197 197,000000 1 197 100,000000 + 198 198,000000 1 198 100,000000 + 199 199,000000 1 199 100,000000 + 200 200,000000 1 200 100,000000 + 201 2,000000 2 1 200,000000 + 202 4,000000 2 2 200,000000 + 203 6,000000 2 3 200,000000 + 204 8,000000 2 4 200,000000 + 205 10,000000 2 5 200,000000 + 206 12,000000 2 6 200,000000 + 207 14,000000 2 7 200,000000 + 208 16,000000 2 8 200,000000 + 209 18,000000 2 9 200,000000 + 210 20,000000 2 10 200,000000 + 211 22,000000 2 11 200,000000 + 212 24,000000 2 12 200,000000 + 213 26,000000 2 13 200,000000 + 214 28,000000 2 14 200,000000 + 215 30,000000 2 15 200,000000 + 216 32,000000 2 16 200,000000 + 217 34,000000 2 17 200,000000 + 218 36,000000 2 18 200,000000 + 219 38,000000 2 19 200,000000 + 220 40,000000 2 20 200,000000 + 221 42,000000 2 21 200,000000 + 222 44,000000 2 22 200,000000 + 223 46,000000 2 23 200,000000 + 224 48,000000 2 24 200,000000 + 225 50,000000 2 25 200,000000 + 226 52,000000 2 26 200,000000 + 227 54,000000 2 27 200,000000 + 228 56,000000 2 28 200,000000 + 229 58,000000 2 29 200,000000 + 230 60,000000 2 30 200,000000 + 231 62,000000 2 31 200,000000 + 232 64,000000 2 32 200,000000 + 233 66,000000 2 33 200,000000 + 234 68,000000 2 34 200,000000 + 235 70,000000 2 35 200,000000 + 236 72,000000 2 36 200,000000 + 237 74,000000 2 37 200,000000 + 238 76,000000 2 38 200,000000 + 239 78,000000 2 39 200,000000 + 240 80,000000 2 40 200,000000 + 241 82,000000 2 41 200,000000 + 242 84,000000 2 42 200,000000 + 243 86,000000 2 43 200,000000 + 244 88,000000 2 44 200,000000 + 245 90,000000 2 45 200,000000 + 246 92,000000 2 46 200,000000 + 247 94,000000 2 47 200,000000 + 248 96,000000 2 48 200,000000 + 249 98,000000 2 49 200,000000 + 250 100,000000 2 50 200,000000 + 251 102,000000 2 51 200,000000 + 252 104,000000 2 52 200,000000 + 253 106,000000 2 53 200,000000 + 254 108,000000 2 54 200,000000 + 255 110,000000 2 55 200,000000 + 256 112,000000 2 56 200,000000 + 257 114,000000 2 57 200,000000 + 258 116,000000 2 58 200,000000 + 259 118,000000 2 59 200,000000 + 260 120,000000 2 60 200,000000 + 261 122,000000 2 61 200,000000 + 262 124,000000 2 62 200,000000 + 263 126,000000 2 63 200,000000 + 264 128,000000 2 64 200,000000 + 265 130,000000 2 65 200,000000 + 266 132,000000 2 66 200,000000 + 267 134,000000 2 67 200,000000 + 268 136,000000 2 68 200,000000 + 269 138,000000 2 69 200,000000 + 270 140,000000 2 70 200,000000 + 271 142,000000 2 71 200,000000 + 272 144,000000 2 72 200,000000 + 273 146,000000 2 73 200,000000 + 274 148,000000 2 74 200,000000 + 275 150,000000 2 75 200,000000 + 276 152,000000 2 76 200,000000 + 277 154,000000 2 77 200,000000 + 278 156,000000 2 78 200,000000 + 279 158,000000 2 79 200,000000 + 280 160,000000 2 80 200,000000 + 281 162,000000 2 81 200,000000 + 282 164,000000 2 82 200,000000 + 283 166,000000 2 83 200,000000 + 284 168,000000 2 84 200,000000 + 285 170,000000 2 85 200,000000 + 286 172,000000 2 86 200,000000 + 287 174,000000 2 87 200,000000 + 288 176,000000 2 88 200,000000 + 289 178,000000 2 89 200,000000 + 290 180,000000 2 90 200,000000 + 291 182,000000 2 91 200,000000 + 292 184,000000 2 92 200,000000 + 293 186,000000 2 93 200,000000 + 294 188,000000 2 94 200,000000 + 295 190,000000 2 95 200,000000 + 296 192,000000 2 96 200,000000 + 297 194,000000 2 97 200,000000 + 298 196,000000 2 98 200,000000 + 299 198,000000 2 99 200,000000 + 300 200,000000 2 100 200,000000 + 301 202,000000 2 101 200,000000 + 302 204,000000 2 102 200,000000 + 303 206,000000 2 103 200,000000 + 304 208,000000 2 104 200,000000 + 305 210,000000 2 105 200,000000 + 306 212,000000 2 106 200,000000 + 307 214,000000 2 107 200,000000 + 308 216,000000 2 108 200,000000 + 309 218,000000 2 109 200,000000 + 310 220,000000 2 110 200,000000 + 311 222,000000 2 111 200,000000 + 312 224,000000 2 112 200,000000 + 313 226,000000 2 113 200,000000 + 314 228,000000 2 114 200,000000 + 315 230,000000 2 115 200,000000 + 316 232,000000 2 116 200,000000 + 317 234,000000 2 117 200,000000 + 318 236,000000 2 118 200,000000 + 319 238,000000 2 119 200,000000 + 320 240,000000 2 120 200,000000 + 321 242,000000 2 121 200,000000 + 322 244,000000 2 122 200,000000 + 323 246,000000 2 123 200,000000 + 324 248,000000 2 124 200,000000 + 325 250,000000 2 125 200,000000 + 326 252,000000 2 126 200,000000 + 327 254,000000 2 127 200,000000 + 328 256,000000 2 128 200,000000 + 329 258,000000 2 129 200,000000 + 330 260,000000 2 130 200,000000 + 331 262,000000 2 131 200,000000 + 332 264,000000 2 132 200,000000 + 333 266,000000 2 133 200,000000 + 334 268,000000 2 134 200,000000 + 335 270,000000 2 135 200,000000 + 336 272,000000 2 136 200,000000 + 337 274,000000 2 137 200,000000 + 338 276,000000 2 138 200,000000 + 339 278,000000 2 139 200,000000 + 340 280,000000 2 140 200,000000 + 341 282,000000 2 141 200,000000 + 342 284,000000 2 142 200,000000 + 343 286,000000 2 143 200,000000 + 344 288,000000 2 144 200,000000 + 345 290,000000 2 145 200,000000 + 346 292,000000 2 146 200,000000 + 347 294,000000 2 147 200,000000 + 348 296,000000 2 148 200,000000 + 349 298,000000 2 149 200,000000 + 350 300,000000 2 150 200,000000 + 351 302,000000 2 151 200,000000 + 352 304,000000 2 152 200,000000 + 353 306,000000 2 153 200,000000 + 354 308,000000 2 154 200,000000 + 355 310,000000 2 155 200,000000 + 356 312,000000 2 156 200,000000 + 357 314,000000 2 157 200,000000 + 358 316,000000 2 158 200,000000 + 359 318,000000 2 159 200,000000 + 360 320,000000 2 160 200,000000 + 361 322,000000 2 161 200,000000 + 362 324,000000 2 162 200,000000 + 363 326,000000 2 163 200,000000 + 364 328,000000 2 164 200,000000 + 365 330,000000 2 165 200,000000 + 366 332,000000 2 166 200,000000 + 367 334,000000 2 167 200,000000 + 368 336,000000 2 168 200,000000 + 369 338,000000 2 169 200,000000 + 370 340,000000 2 170 200,000000 + 371 342,000000 2 171 200,000000 + 372 344,000000 2 172 200,000000 + 373 346,000000 2 173 200,000000 + 374 348,000000 2 174 200,000000 + 375 350,000000 2 175 200,000000 + 376 352,000000 2 176 200,000000 + 377 354,000000 2 177 200,000000 + 378 356,000000 2 178 200,000000 + 379 358,000000 2 179 200,000000 + 380 360,000000 2 180 200,000000 + 381 362,000000 2 181 200,000000 + 382 364,000000 2 182 200,000000 + 383 366,000000 2 183 200,000000 + 384 368,000000 2 184 200,000000 + 385 370,000000 2 185 200,000000 + 386 372,000000 2 186 200,000000 + 387 374,000000 2 187 200,000000 + 388 376,000000 2 188 200,000000 + 389 378,000000 2 189 200,000000 + 390 380,000000 2 190 200,000000 + 391 382,000000 2 191 200,000000 + 392 384,000000 2 192 200,000000 + 393 386,000000 2 193 200,000000 + 394 388,000000 2 194 200,000000 + 395 390,000000 2 195 200,000000 + 396 392,000000 2 196 200,000000 + 397 394,000000 2 197 200,000000 + 398 396,000000 2 198 200,000000 + 399 398,000000 2 199 200,000000 + 400 400,000000 2 200 200,000000 + 401 3,000000 3 1 300,000000 + 402 6,000000 3 2 300,000000 + 403 9,000000 3 3 300,000000 + 404 12,000000 3 4 300,000000 + 405 15,000000 3 5 300,000000 + 406 18,000000 3 6 300,000000 + 407 21,000000 3 7 300,000000 + 408 24,000000 3 8 300,000000 + 409 27,000000 3 9 300,000000 + 410 30,000000 3 10 300,000000 + 411 33,000000 3 11 300,000000 + 412 36,000000 3 12 300,000000 + 413 39,000000 3 13 300,000000 + 414 42,000000 3 14 300,000000 + 415 45,000000 3 15 300,000000 + 416 48,000000 3 16 300,000000 + 417 51,000000 3 17 300,000000 + 418 54,000000 3 18 300,000000 + 419 57,000000 3 19 300,000000 + 420 60,000000 3 20 300,000000 + 421 63,000000 3 21 300,000000 + 422 66,000000 3 22 300,000000 + 423 69,000000 3 23 300,000000 + 424 72,000000 3 24 300,000000 + 425 75,000000 3 25 300,000000 + 426 78,000000 3 26 300,000000 + 427 81,000000 3 27 300,000000 + 428 84,000000 3 28 300,000000 + 429 87,000000 3 29 300,000000 + 430 90,000000 3 30 300,000000 + 431 93,000000 3 31 300,000000 + 432 96,000000 3 32 300,000000 + 433 99,000000 3 33 300,000000 + 434 102,000000 3 34 300,000000 + 435 105,000000 3 35 300,000000 + 436 108,000000 3 36 300,000000 + 437 111,000000 3 37 300,000000 + 438 114,000000 3 38 300,000000 + 439 117,000000 3 39 300,000000 + 440 120,000000 3 40 300,000000 + 441 123,000000 3 41 300,000000 + 442 126,000000 3 42 300,000000 + 443 129,000000 3 43 300,000000 + 444 132,000000 3 44 300,000000 + 445 135,000000 3 45 300,000000 + 446 138,000000 3 46 300,000000 + 447 141,000000 3 47 300,000000 + 448 144,000000 3 48 300,000000 + 449 147,000000 3 49 300,000000 + 450 150,000000 3 50 300,000000 + 451 153,000000 3 51 300,000000 + 452 156,000000 3 52 300,000000 + 453 159,000000 3 53 300,000000 + 454 162,000000 3 54 300,000000 + 455 165,000000 3 55 300,000000 + 456 168,000000 3 56 300,000000 + 457 171,000000 3 57 300,000000 + 458 174,000000 3 58 300,000000 + 459 177,000000 3 59 300,000000 + 460 180,000000 3 60 300,000000 + 461 183,000000 3 61 300,000000 + 462 186,000000 3 62 300,000000 + 463 189,000000 3 63 300,000000 + 464 192,000000 3 64 300,000000 + 465 195,000000 3 65 300,000000 + 466 198,000000 3 66 300,000000 + 467 201,000000 3 67 300,000000 + 468 204,000000 3 68 300,000000 + 469 207,000000 3 69 300,000000 + 470 210,000000 3 70 300,000000 + 471 213,000000 3 71 300,000000 + 472 216,000000 3 72 300,000000 + 473 219,000000 3 73 300,000000 + 474 222,000000 3 74 300,000000 + 475 225,000000 3 75 300,000000 + 476 228,000000 3 76 300,000000 + 477 231,000000 3 77 300,000000 + 478 234,000000 3 78 300,000000 + 479 237,000000 3 79 300,000000 + 480 240,000000 3 80 300,000000 + 481 243,000000 3 81 300,000000 + 482 246,000000 3 82 300,000000 + 483 249,000000 3 83 300,000000 + 484 252,000000 3 84 300,000000 + 485 255,000000 3 85 300,000000 + 486 258,000000 3 86 300,000000 + 487 261,000000 3 87 300,000000 + 488 264,000000 3 88 300,000000 + 489 267,000000 3 89 300,000000 + 490 270,000000 3 90 300,000000 + 491 273,000000 3 91 300,000000 + 492 276,000000 3 92 300,000000 + 493 279,000000 3 93 300,000000 + 494 282,000000 3 94 300,000000 + 495 285,000000 3 95 300,000000 + 496 288,000000 3 96 300,000000 + 497 291,000000 3 97 300,000000 + 498 294,000000 3 98 300,000000 + 499 297,000000 3 99 300,000000 + 500 300,000000 3 100 300,000000 + 501 303,000000 3 101 300,000000 + 502 306,000000 3 102 300,000000 + 503 309,000000 3 103 300,000000 + 504 312,000000 3 104 300,000000 + 505 315,000000 3 105 300,000000 + 506 318,000000 3 106 300,000000 + 507 321,000000 3 107 300,000000 + 508 324,000000 3 108 300,000000 + 509 327,000000 3 109 300,000000 + 510 330,000000 3 110 300,000000 + 511 333,000000 3 111 300,000000 + 512 336,000000 3 112 300,000000 + 513 339,000000 3 113 300,000000 + 514 342,000000 3 114 300,000000 + 515 345,000000 3 115 300,000000 + 516 348,000000 3 116 300,000000 + 517 351,000000 3 117 300,000000 + 518 354,000000 3 118 300,000000 + 519 357,000000 3 119 300,000000 + 520 360,000000 3 120 300,000000 + 521 363,000000 3 121 300,000000 + 522 366,000000 3 122 300,000000 + 523 369,000000 3 123 300,000000 + 524 372,000000 3 124 300,000000 + 525 375,000000 3 125 300,000000 + 526 378,000000 3 126 300,000000 + 527 381,000000 3 127 300,000000 + 528 384,000000 3 128 300,000000 + 529 387,000000 3 129 300,000000 + 530 390,000000 3 130 300,000000 + 531 393,000000 3 131 300,000000 + 532 396,000000 3 132 300,000000 + 533 399,000000 3 133 300,000000 + 534 402,000000 3 134 300,000000 + 535 405,000000 3 135 300,000000 + 536 408,000000 3 136 300,000000 + 537 411,000000 3 137 300,000000 + 538 414,000000 3 138 300,000000 + 539 417,000000 3 139 300,000000 + 540 420,000000 3 140 300,000000 + 541 423,000000 3 141 300,000000 + 542 426,000000 3 142 300,000000 + 543 429,000000 3 143 300,000000 + 544 432,000000 3 144 300,000000 + 545 435,000000 3 145 300,000000 + 546 438,000000 3 146 300,000000 + 547 441,000000 3 147 300,000000 + 548 444,000000 3 148 300,000000 + 549 447,000000 3 149 300,000000 + 550 450,000000 3 150 300,000000 + 551 453,000000 3 151 300,000000 + 552 456,000000 3 152 300,000000 + 553 459,000000 3 153 300,000000 + 554 462,000000 3 154 300,000000 + 555 465,000000 3 155 300,000000 + 556 468,000000 3 156 300,000000 + 557 471,000000 3 157 300,000000 + 558 474,000000 3 158 300,000000 + 559 477,000000 3 159 300,000000 + 560 480,000000 3 160 300,000000 + 561 483,000000 3 161 300,000000 + 562 486,000000 3 162 300,000000 + 563 489,000000 3 163 300,000000 + 564 492,000000 3 164 300,000000 + 565 495,000000 3 165 300,000000 + 566 498,000000 3 166 300,000000 + 567 501,000000 3 167 300,000000 + 568 504,000000 3 168 300,000000 + 569 507,000000 3 169 300,000000 + 570 510,000000 3 170 300,000000 + 571 513,000000 3 171 300,000000 + 572 516,000000 3 172 300,000000 + 573 519,000000 3 173 300,000000 + 574 522,000000 3 174 300,000000 + 575 525,000000 3 175 300,000000 + 576 528,000000 3 176 300,000000 + 577 531,000000 3 177 300,000000 + 578 534,000000 3 178 300,000000 + 579 537,000000 3 179 300,000000 + 580 540,000000 3 180 300,000000 + 581 543,000000 3 181 300,000000 + 582 546,000000 3 182 300,000000 + 583 549,000000 3 183 300,000000 + 584 552,000000 3 184 300,000000 + 585 555,000000 3 185 300,000000 + 586 558,000000 3 186 300,000000 + 587 561,000000 3 187 300,000000 + 588 564,000000 3 188 300,000000 + 589 567,000000 3 189 300,000000 + 590 570,000000 3 190 300,000000 + 591 573,000000 3 191 300,000000 + 592 576,000000 3 192 300,000000 + 593 579,000000 3 193 300,000000 + 594 582,000000 3 194 300,000000 + 595 585,000000 3 195 300,000000 + 596 588,000000 3 196 300,000000 + 597 591,000000 3 197 300,000000 + 598 594,000000 3 198 300,000000 + 599 597,000000 3 199 300,000000 + 600 600,000000 3 200 300,000000 + 601 4,000000 4 1 400,000000 + 602 8,000000 4 2 400,000000 + 603 12,000000 4 3 400,000000 + 604 16,000000 4 4 400,000000 + 605 20,000000 4 5 400,000000 + 606 24,000000 4 6 400,000000 + 607 28,000000 4 7 400,000000 + 608 32,000000 4 8 400,000000 + 609 36,000000 4 9 400,000000 + 610 40,000000 4 10 400,000000 + 611 44,000000 4 11 400,000000 + 612 48,000000 4 12 400,000000 + 613 52,000000 4 13 400,000000 + 614 56,000000 4 14 400,000000 + 615 60,000000 4 15 400,000000 + 616 64,000000 4 16 400,000000 + 617 68,000000 4 17 400,000000 + 618 72,000000 4 18 400,000000 + 619 76,000000 4 19 400,000000 + 620 80,000000 4 20 400,000000 + 621 84,000000 4 21 400,000000 + 622 88,000000 4 22 400,000000 + 623 92,000000 4 23 400,000000 + 624 96,000000 4 24 400,000000 + 625 100,000000 4 25 400,000000 + 626 104,000000 4 26 400,000000 + 627 108,000000 4 27 400,000000 + 628 112,000000 4 28 400,000000 + 629 116,000000 4 29 400,000000 + 630 120,000000 4 30 400,000000 + 631 124,000000 4 31 400,000000 + 632 128,000000 4 32 400,000000 + 633 132,000000 4 33 400,000000 + 634 136,000000 4 34 400,000000 + 635 140,000000 4 35 400,000000 + 636 144,000000 4 36 400,000000 + 637 148,000000 4 37 400,000000 + 638 152,000000 4 38 400,000000 + 639 156,000000 4 39 400,000000 + 640 160,000000 4 40 400,000000 + 641 164,000000 4 41 400,000000 + 642 168,000000 4 42 400,000000 + 643 172,000000 4 43 400,000000 + 644 176,000000 4 44 400,000000 + 645 180,000000 4 45 400,000000 + 646 184,000000 4 46 400,000000 + 647 188,000000 4 47 400,000000 + 648 192,000000 4 48 400,000000 + 649 196,000000 4 49 400,000000 + 650 200,000000 4 50 400,000000 + 651 204,000000 4 51 400,000000 + 652 208,000000 4 52 400,000000 + 653 212,000000 4 53 400,000000 + 654 216,000000 4 54 400,000000 + 655 220,000000 4 55 400,000000 + 656 224,000000 4 56 400,000000 + 657 228,000000 4 57 400,000000 + 658 232,000000 4 58 400,000000 + 659 236,000000 4 59 400,000000 + 660 240,000000 4 60 400,000000 + 661 244,000000 4 61 400,000000 + 662 248,000000 4 62 400,000000 + 663 252,000000 4 63 400,000000 + 664 256,000000 4 64 400,000000 + 665 260,000000 4 65 400,000000 + 666 264,000000 4 66 400,000000 + 667 268,000000 4 67 400,000000 + 668 272,000000 4 68 400,000000 + 669 276,000000 4 69 400,000000 + 670 280,000000 4 70 400,000000 + 671 284,000000 4 71 400,000000 + 672 288,000000 4 72 400,000000 + 673 292,000000 4 73 400,000000 + 674 296,000000 4 74 400,000000 + 675 300,000000 4 75 400,000000 + 676 304,000000 4 76 400,000000 + 677 308,000000 4 77 400,000000 + 678 312,000000 4 78 400,000000 + 679 316,000000 4 79 400,000000 + 680 320,000000 4 80 400,000000 + 681 324,000000 4 81 400,000000 + 682 328,000000 4 82 400,000000 + 683 332,000000 4 83 400,000000 + 684 336,000000 4 84 400,000000 + 685 340,000000 4 85 400,000000 + 686 344,000000 4 86 400,000000 + 687 348,000000 4 87 400,000000 + 688 352,000000 4 88 400,000000 + 689 356,000000 4 89 400,000000 + 690 360,000000 4 90 400,000000 + 691 364,000000 4 91 400,000000 + 692 368,000000 4 92 400,000000 + 693 372,000000 4 93 400,000000 + 694 376,000000 4 94 400,000000 + 695 380,000000 4 95 400,000000 + 696 384,000000 4 96 400,000000 + 697 388,000000 4 97 400,000000 + 698 392,000000 4 98 400,000000 + 699 396,000000 4 99 400,000000 + 700 400,000000 4 100 400,000000 + 701 404,000000 4 101 400,000000 + 702 408,000000 4 102 400,000000 + 703 412,000000 4 103 400,000000 + 704 416,000000 4 104 400,000000 + 705 420,000000 4 105 400,000000 + 706 424,000000 4 106 400,000000 + 707 428,000000 4 107 400,000000 + 708 432,000000 4 108 400,000000 + 709 436,000000 4 109 400,000000 + 710 440,000000 4 110 400,000000 + 711 444,000000 4 111 400,000000 + 712 448,000000 4 112 400,000000 + 713 452,000000 4 113 400,000000 + 714 456,000000 4 114 400,000000 + 715 460,000000 4 115 400,000000 + 716 464,000000 4 116 400,000000 + 717 468,000000 4 117 400,000000 + 718 472,000000 4 118 400,000000 + 719 476,000000 4 119 400,000000 + 720 480,000000 4 120 400,000000 + 721 484,000000 4 121 400,000000 + 722 488,000000 4 122 400,000000 + 723 492,000000 4 123 400,000000 + 724 496,000000 4 124 400,000000 + 725 500,000000 4 125 400,000000 + 726 504,000000 4 126 400,000000 + 727 508,000000 4 127 400,000000 + 728 512,000000 4 128 400,000000 + 729 516,000000 4 129 400,000000 + 730 520,000000 4 130 400,000000 + 731 524,000000 4 131 400,000000 + 732 528,000000 4 132 400,000000 + 733 532,000000 4 133 400,000000 + 734 536,000000 4 134 400,000000 + 735 540,000000 4 135 400,000000 + 736 544,000000 4 136 400,000000 + 737 548,000000 4 137 400,000000 + 738 552,000000 4 138 400,000000 + 739 556,000000 4 139 400,000000 + 740 560,000000 4 140 400,000000 + 741 564,000000 4 141 400,000000 + 742 568,000000 4 142 400,000000 + 743 572,000000 4 143 400,000000 + 744 576,000000 4 144 400,000000 + 745 580,000000 4 145 400,000000 + 746 584,000000 4 146 400,000000 + 747 588,000000 4 147 400,000000 + 748 592,000000 4 148 400,000000 + 749 596,000000 4 149 400,000000 + 750 600,000000 4 150 400,000000 + 751 604,000000 4 151 400,000000 + 752 608,000000 4 152 400,000000 + 753 612,000000 4 153 400,000000 + 754 616,000000 4 154 400,000000 + 755 620,000000 4 155 400,000000 + 756 624,000000 4 156 400,000000 + 757 628,000000 4 157 400,000000 + 758 632,000000 4 158 400,000000 + 759 636,000000 4 159 400,000000 + 760 640,000000 4 160 400,000000 + 761 644,000000 4 161 400,000000 + 762 648,000000 4 162 400,000000 + 763 652,000000 4 163 400,000000 + 764 656,000000 4 164 400,000000 + 765 660,000000 4 165 400,000000 + 766 664,000000 4 166 400,000000 + 767 668,000000 4 167 400,000000 + 768 672,000000 4 168 400,000000 + 769 676,000000 4 169 400,000000 + 770 680,000000 4 170 400,000000 + 771 684,000000 4 171 400,000000 + 772 688,000000 4 172 400,000000 + 773 692,000000 4 173 400,000000 + 774 696,000000 4 174 400,000000 + 775 700,000000 4 175 400,000000 + 776 704,000000 4 176 400,000000 + 777 708,000000 4 177 400,000000 + 778 712,000000 4 178 400,000000 + 779 716,000000 4 179 400,000000 + 780 720,000000 4 180 400,000000 + 781 724,000000 4 181 400,000000 + 782 728,000000 4 182 400,000000 + 783 732,000000 4 183 400,000000 + 784 736,000000 4 184 400,000000 + 785 740,000000 4 185 400,000000 + 786 744,000000 4 186 400,000000 + 787 748,000000 4 187 400,000000 + 788 752,000000 4 188 400,000000 + 789 756,000000 4 189 400,000000 + 790 760,000000 4 190 400,000000 + 791 764,000000 4 191 400,000000 + 792 768,000000 4 192 400,000000 + 793 772,000000 4 193 400,000000 + 794 776,000000 4 194 400,000000 + 795 780,000000 4 195 400,000000 + 796 784,000000 4 196 400,000000 + 797 788,000000 4 197 400,000000 + 798 792,000000 4 198 400,000000 + 799 796,000000 4 199 400,000000 + 800 800,000000 4 200 400,000000 + 801 5,000000 5 1 500,000000 + 802 10,000000 5 2 500,000000 + 803 15,000000 5 3 500,000000 + 804 20,000000 5 4 500,000000 + 805 25,000000 5 5 500,000000 + 806 30,000000 5 6 500,000000 + 807 35,000000 5 7 500,000000 + 808 40,000000 5 8 500,000000 + 809 45,000000 5 9 500,000000 + 810 50,000000 5 10 500,000000 + 811 55,000000 5 11 500,000000 + 812 60,000000 5 12 500,000000 + 813 65,000000 5 13 500,000000 + 814 70,000000 5 14 500,000000 + 815 75,000000 5 15 500,000000 + 816 80,000000 5 16 500,000000 + 817 85,000000 5 17 500,000000 + 818 90,000000 5 18 500,000000 + 819 95,000000 5 19 500,000000 + 820 100,000000 5 20 500,000000 + 821 105,000000 5 21 500,000000 + 822 110,000000 5 22 500,000000 + 823 115,000000 5 23 500,000000 + 824 120,000000 5 24 500,000000 + 825 125,000000 5 25 500,000000 + 826 130,000000 5 26 500,000000 + 827 135,000000 5 27 500,000000 + 828 140,000000 5 28 500,000000 + 829 145,000000 5 29 500,000000 + 830 150,000000 5 30 500,000000 + 831 155,000000 5 31 500,000000 + 832 160,000000 5 32 500,000000 + 833 165,000000 5 33 500,000000 + 834 170,000000 5 34 500,000000 + 835 175,000000 5 35 500,000000 + 836 180,000000 5 36 500,000000 + 837 185,000000 5 37 500,000000 + 838 190,000000 5 38 500,000000 + 839 195,000000 5 39 500,000000 + 840 200,000000 5 40 500,000000 + 841 205,000000 5 41 500,000000 + 842 210,000000 5 42 500,000000 + 843 215,000000 5 43 500,000000 + 844 220,000000 5 44 500,000000 + 845 225,000000 5 45 500,000000 + 846 230,000000 5 46 500,000000 + 847 235,000000 5 47 500,000000 + 848 240,000000 5 48 500,000000 + 849 245,000000 5 49 500,000000 + 850 250,000000 5 50 500,000000 + 851 255,000000 5 51 500,000000 + 852 260,000000 5 52 500,000000 + 853 265,000000 5 53 500,000000 + 854 270,000000 5 54 500,000000 + 855 275,000000 5 55 500,000000 + 856 280,000000 5 56 500,000000 + 857 285,000000 5 57 500,000000 + 858 290,000000 5 58 500,000000 + 859 295,000000 5 59 500,000000 + 860 300,000000 5 60 500,000000 + 861 305,000000 5 61 500,000000 + 862 310,000000 5 62 500,000000 + 863 315,000000 5 63 500,000000 + 864 320,000000 5 64 500,000000 + 865 325,000000 5 65 500,000000 + 866 330,000000 5 66 500,000000 + 867 335,000000 5 67 500,000000 + 868 340,000000 5 68 500,000000 + 869 345,000000 5 69 500,000000 + 870 350,000000 5 70 500,000000 + 871 355,000000 5 71 500,000000 + 872 360,000000 5 72 500,000000 + 873 365,000000 5 73 500,000000 + 874 370,000000 5 74 500,000000 + 875 375,000000 5 75 500,000000 + 876 380,000000 5 76 500,000000 + 877 385,000000 5 77 500,000000 + 878 390,000000 5 78 500,000000 + 879 395,000000 5 79 500,000000 + 880 400,000000 5 80 500,000000 + 881 405,000000 5 81 500,000000 + 882 410,000000 5 82 500,000000 + 883 415,000000 5 83 500,000000 + 884 420,000000 5 84 500,000000 + 885 425,000000 5 85 500,000000 + 886 430,000000 5 86 500,000000 + 887 435,000000 5 87 500,000000 + 888 440,000000 5 88 500,000000 + 889 445,000000 5 89 500,000000 + 890 450,000000 5 90 500,000000 + 891 455,000000 5 91 500,000000 + 892 460,000000 5 92 500,000000 + 893 465,000000 5 93 500,000000 + 894 470,000000 5 94 500,000000 + 895 475,000000 5 95 500,000000 + 896 480,000000 5 96 500,000000 + 897 485,000000 5 97 500,000000 + 898 490,000000 5 98 500,000000 + 899 495,000000 5 99 500,000000 + 900 500,000000 5 100 500,000000 + 901 505,000000 5 101 500,000000 + 902 510,000000 5 102 500,000000 + 903 515,000000 5 103 500,000000 + 904 520,000000 5 104 500,000000 + 905 525,000000 5 105 500,000000 + 906 530,000000 5 106 500,000000 + 907 535,000000 5 107 500,000000 + 908 540,000000 5 108 500,000000 + 909 545,000000 5 109 500,000000 + 910 550,000000 5 110 500,000000 + 911 555,000000 5 111 500,000000 + 912 560,000000 5 112 500,000000 + 913 565,000000 5 113 500,000000 + 914 570,000000 5 114 500,000000 + 915 575,000000 5 115 500,000000 + 916 580,000000 5 116 500,000000 + 917 585,000000 5 117 500,000000 + 918 590,000000 5 118 500,000000 + 919 595,000000 5 119 500,000000 + 920 600,000000 5 120 500,000000 + 921 605,000000 5 121 500,000000 + 922 610,000000 5 122 500,000000 + 923 615,000000 5 123 500,000000 + 924 620,000000 5 124 500,000000 + 925 625,000000 5 125 500,000000 + 926 630,000000 5 126 500,000000 + 927 635,000000 5 127 500,000000 + 928 640,000000 5 128 500,000000 + 929 645,000000 5 129 500,000000 + 930 650,000000 5 130 500,000000 + 931 655,000000 5 131 500,000000 + 932 660,000000 5 132 500,000000 + 933 665,000000 5 133 500,000000 + 934 670,000000 5 134 500,000000 + 935 675,000000 5 135 500,000000 + 936 680,000000 5 136 500,000000 + 937 685,000000 5 137 500,000000 + 938 690,000000 5 138 500,000000 + 939 695,000000 5 139 500,000000 + 940 700,000000 5 140 500,000000 + 941 705,000000 5 141 500,000000 + 942 710,000000 5 142 500,000000 + 943 715,000000 5 143 500,000000 + 944 720,000000 5 144 500,000000 + 945 725,000000 5 145 500,000000 + 946 730,000000 5 146 500,000000 + 947 735,000000 5 147 500,000000 + 948 740,000000 5 148 500,000000 + 949 745,000000 5 149 500,000000 + 950 750,000000 5 150 500,000000 + 951 755,000000 5 151 500,000000 + 952 760,000000 5 152 500,000000 + 953 765,000000 5 153 500,000000 + 954 770,000000 5 154 500,000000 + 955 775,000000 5 155 500,000000 + 956 780,000000 5 156 500,000000 + 957 785,000000 5 157 500,000000 + 958 790,000000 5 158 500,000000 + 959 795,000000 5 159 500,000000 + 960 800,000000 5 160 500,000000 + 961 805,000000 5 161 500,000000 + 962 810,000000 5 162 500,000000 + 963 815,000000 5 163 500,000000 + 964 820,000000 5 164 500,000000 + 965 825,000000 5 165 500,000000 + 966 830,000000 5 166 500,000000 + 967 835,000000 5 167 500,000000 + 968 840,000000 5 168 500,000000 + 969 845,000000 5 169 500,000000 + 970 850,000000 5 170 500,000000 + 971 855,000000 5 171 500,000000 + 972 860,000000 5 172 500,000000 + 973 865,000000 5 173 500,000000 + 974 870,000000 5 174 500,000000 + 975 875,000000 5 175 500,000000 + 976 880,000000 5 176 500,000000 + 977 885,000000 5 177 500,000000 + 978 890,000000 5 178 500,000000 + 979 895,000000 5 179 500,000000 + 980 900,000000 5 180 500,000000 + 981 905,000000 5 181 500,000000 + 982 910,000000 5 182 500,000000 + 983 915,000000 5 183 500,000000 + 984 920,000000 5 184 500,000000 + 985 925,000000 5 185 500,000000 + 986 930,000000 5 186 500,000000 + 987 935,000000 5 187 500,000000 + 988 940,000000 5 188 500,000000 + 989 945,000000 5 189 500,000000 + 990 950,000000 5 190 500,000000 + 991 955,000000 5 191 500,000000 + 992 960,000000 5 192 500,000000 + 993 965,000000 5 193 500,000000 + 994 970,000000 5 194 500,000000 + 995 975,000000 5 195 500,000000 + 996 980,000000 5 196 500,000000 + 997 985,000000 5 197 500,000000 + 998 990,000000 5 198 500,000000 + 999 995,000000 5 199 500,000000 + 1000 1000,000000 5 200 500,000000 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 33-34 + +Read the analysis domain support + +.. GENERATED FROM PYTHON SOURCE LINES 34-37 + +.. code-block:: default + + tf = model.metadata.time_freq_support + print("Number of solution sets", tf.n_sets) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Number of solution sets 1000 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 38-42 + +Compute multi-harmonic response +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example computes the Rz multi-harmonic responses based on +selected nodes and a set of EOs (engine orders). + +.. GENERATED FROM PYTHON SOURCE LINES 42-77 + +.. code-block:: default + + + # Create a total displacement operator and set its time scoping to + # the entire time frequency support and its nodes scoping to user-defined nodes. + disp_op = ops.result.raw_displacement(data_sources=model) + time_ids = list(range(1, model.metadata.time_freq_support.n_sets + 1)) + + # Define nodal scoping + nodes = dpf.Scoping() + nodes.ids = [2, 18] + + # Connect the frequencies and the nodes scopings to the result + # provider operator. + disp_op.inputs.mesh_scoping.connect(nodes) + disp_op.inputs.time_scoping.connect(time_ids) + + # Extract the Rz component using the component selector operator. + comp = dpf.Operator("component_selector_fc") + comp.inputs.connect(disp_op.outputs) + comp.inputs.component_number.connect(5) + + # Compute the multi-harmonic response based on Rz and a set of RPMs. + rpms = dpf.Scoping() + rpms.ids = [1, 2, 3] + + fft = ops.math.fft_multi_harmonic_minmax() + + fft.inputs.connect(comp.outputs) + fft.inputs.rpm_scoping.connect(rpms) + + fields = fft.outputs.field_max() + len(fields) # one multi-harmonic field response per node + + field1 = fields[0] + field2 = fields[1] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 78-79 + +Plot the minimum and maximum displacements over time. + +.. GENERATED FROM PYTHON SOURCE LINES 79-86 + +.. code-block:: default + + + pyplot.plot(field1.data, "r", label="Field 1") + pyplot.plot(field2.data, "b", label="Field 2") + pyplot.xlabel("Frequency (Hz)") + pyplot.ylabel("Displacement (m)") + pyplot.legend() + pyplot.show() + + + +.. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_00-multi_harmonic_001.png + :alt: 00 multi harmonic + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_00-multi_harmonic_001.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 2.331 seconds) + + +.. _sphx_glr_download_examples_03-harmonic_analyses_00-multi_harmonic.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 00-multi_harmonic.py <00-multi_harmonic.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 00-multi_harmonic.ipynb <00-multi_harmonic.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/03-harmonic_analyses/00-multi_harmonic_codeobj.pickle b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic_codeobj.pickle new file mode 100644 index 0000000000..e39d81ade3 Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/00-multi_harmonic_codeobj.pickle differ diff --git a/doc/source/examples/03-harmonic_analyses/01-modal_superposition.ipynb b/doc/source/examples/03-harmonic_analyses/01-modal_superposition.ipynb new file mode 100644 index 0000000000..53d2030363 --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/01-modal_superposition.ipynb @@ -0,0 +1,90 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Expand harmonic modal superposition with DPF {#ref_msup}\r\n\r\nDifferent types of linear dynamics expansions are implemented in DPF.\r\nWith modal superposition used in harmonic analysis, modal coefficients\r\nare multiplied by mode shapes (of a previous modal analysis) to analyse\r\na structure under given boundary conditions in a range of frequencies.\r\nDoing this expansion \\\"on demand\\\" in DPF instead of in the solver\r\nreduces the size of the result files.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create data sources\r\n\r\nCreate data sources with the mode shapes and the modal response. The\r\nexpansion is recursive in DPF: first the modal response is read. Then,\r\n\\\"upstream\\\" mode shapes are found in the data sources, where they are\r\nread and expanded (mode shapes x modal response)\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "msup_files = examples.download_msup_files_to_dict()\ndata_sources = dpf.DataSources(msup_files[\"rfrq\"])\nup_stream_data_sources = dpf.DataSources(msup_files[\"mode\"])\nup_stream_data_sources.add_file_path(msup_files[\"rst\"])\n\ndata_sources.add_upstream(up_stream_data_sources)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compute displacements\r\n\r\nOnce the `add_upstream()` method puts the recursivity in the data\r\nsources, in a harmonic, transient, or modal analysis, computing\r\ndisplacements with or without expansion has the exact same syntax.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(data_sources)\ndisp = model.results.displacement.on_all_time_freqs.eval()\n\nfreq_scoping = disp.get_time_scoping()\nfor freq_set in freq_scoping:\n model.metadata.meshed_region.plot(disp.get_field_by_time_complex_ids(freq_set, 0))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/03-harmonic_analyses/01-modal_superposition.py b/doc/source/examples/03-harmonic_analyses/01-modal_superposition.py new file mode 100644 index 0000000000..e5e3c542fd --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/01-modal_superposition.py @@ -0,0 +1,47 @@ +""" +.. _ref_msup: + +Expand harmonic modal superposition with DPF +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Different types of linear dynamics expansions are implemented in DPF. +With modal superposition used in harmonic analysis, modal coefficients +are multiplied by mode shapes (of a previous modal analysis) to analyse +a structure under given boundary conditions in a range of frequencies. +Doing this expansion "on demand" in DPF instead of in the solver +reduces the size of the result files. + +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + + +############################################################################### +# Create data sources +# ~~~~~~~~~~~~~~~~~~~ +# Create data sources with the mode shapes and the modal response. +# The expansion is recursive in DPF: first the modal response is read. +# Then, "upstream" mode shapes are found in the data sources, where they +# are read and expanded (mode shapes x modal response) + +msup_files = examples.download_msup_files_to_dict() +data_sources = dpf.DataSources(msup_files["rfrq"]) +up_stream_data_sources = dpf.DataSources(msup_files["mode"]) +up_stream_data_sources.add_file_path(msup_files["rst"]) + +data_sources.add_upstream(up_stream_data_sources) + +############################################################################### +# Compute displacements +# ~~~~~~~~~~~~~~~~~~~~~ +# Once the ``add_upstream()`` method puts the recursivity in the data sources, +# in a harmonic, transient, or modal analysis, computing displacements with +# or without expansion has the exact same syntax. + +model = dpf.Model(data_sources) +disp = model.results.displacement.on_all_time_freqs.eval() + +freq_scoping = disp.get_time_scoping() +for freq_set in freq_scoping: + model.metadata.meshed_region.plot(disp.get_field_by_time_complex_ids(freq_set, 0)) diff --git a/doc/source/examples/03-harmonic_analyses/01-modal_superposition.py.md5 b/doc/source/examples/03-harmonic_analyses/01-modal_superposition.py.md5 new file mode 100644 index 0000000000..a3af0ff34e --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/01-modal_superposition.py.md5 @@ -0,0 +1 @@ +76a85dce2122be1107218fd386ec63d1 \ No newline at end of file diff --git a/doc/source/examples/03-harmonic_analyses/01-modal_superposition.rst b/doc/source/examples/03-harmonic_analyses/01-modal_superposition.rst new file mode 100644 index 0000000000..9c25cc6ae2 --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/01-modal_superposition.rst @@ -0,0 +1,202 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\03-harmonic_analyses\01-modal_superposition.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_03-harmonic_analyses_01-modal_superposition.py: + + +.. _ref_msup: + +Expand harmonic modal superposition with DPF +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Different types of linear dynamics expansions are implemented in DPF. +With modal superposition used in harmonic analysis, modal coefficients +are multiplied by mode shapes (of a previous modal analysis) to analyse +a structure under given boundary conditions in a range of frequencies. +Doing this expansion "on demand" in DPF instead of in the solver +reduces the size of the result files. + +.. GENERATED FROM PYTHON SOURCE LINES 15-20 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 21-27 + +Create data sources +~~~~~~~~~~~~~~~~~~~ +Create data sources with the mode shapes and the modal response. +The expansion is recursive in DPF: first the modal response is read. +Then, "upstream" mode shapes are found in the data sources, where they +are read and expanded (mode shapes x modal response) + +.. GENERATED FROM PYTHON SOURCE LINES 27-35 + +.. code-block:: default + + + msup_files = examples.download_msup_files_to_dict() + data_sources = dpf.DataSources(msup_files["rfrq"]) + up_stream_data_sources = dpf.DataSources(msup_files["mode"]) + up_stream_data_sources.add_file_path(msup_files["rst"]) + + data_sources.add_upstream(up_stream_data_sources) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 36-41 + +Compute displacements +~~~~~~~~~~~~~~~~~~~~~ +Once the ``add_upstream()`` method puts the recursivity in the data sources, +in a harmonic, transient, or modal analysis, computing displacements with +or without expansion has the exact same syntax. + +.. GENERATED FROM PYTHON SOURCE LINES 41-48 + +.. code-block:: default + + + model = dpf.Model(data_sources) + disp = model.results.displacement.on_all_time_freqs.eval() + + freq_scoping = disp.get_time_scoping() + for freq_set in freq_scoping: + model.metadata.meshed_region.plot(disp.get_field_by_time_complex_ids(freq_set, 0)) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_001.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_002.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_003.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_004.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_005.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_005.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_006.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_006.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_007.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_007.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_008.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_008.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_009.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_009.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_010.png + :alt: 01 modal superposition + :srcset: /examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_010.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 8.624 seconds) + + +.. _sphx_glr_download_examples_03-harmonic_analyses_01-modal_superposition.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 01-modal_superposition.py <01-modal_superposition.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 01-modal_superposition.ipynb <01-modal_superposition.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/03-harmonic_analyses/01-modal_superposition_codeobj.pickle b/doc/source/examples/03-harmonic_analyses/01-modal_superposition_codeobj.pickle new file mode 100644 index 0000000000..180366da1a Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/01-modal_superposition_codeobj.pickle differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_00-multi_harmonic_001.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_00-multi_harmonic_001.png new file mode 100644 index 0000000000..cdf7a051f9 Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_00-multi_harmonic_001.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_001.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_001.png new file mode 100644 index 0000000000..e1da2dfab6 Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_001.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_002.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_002.png new file mode 100644 index 0000000000..d5bc220c64 Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_002.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_003.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_003.png new file mode 100644 index 0000000000..a9c395b22a Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_003.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_004.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_004.png new file mode 100644 index 0000000000..d84015c904 Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_004.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_005.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_005.png new file mode 100644 index 0000000000..116ded2d46 Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_005.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_006.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_006.png new file mode 100644 index 0000000000..b351742c7a Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_006.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_007.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_007.png new file mode 100644 index 0000000000..a3fa5fe40f Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_007.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_008.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_008.png new file mode 100644 index 0000000000..7e5542343c Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_008.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_009.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_009.png new file mode 100644 index 0000000000..b77d804a80 Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_009.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_010.png b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_010.png new file mode 100644 index 0000000000..20ef6dfb68 Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/sphx_glr_01-modal_superposition_010.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/thumb/sphx_glr_00-multi_harmonic_thumb.png b/doc/source/examples/03-harmonic_analyses/images/thumb/sphx_glr_00-multi_harmonic_thumb.png new file mode 100644 index 0000000000..8a5c174448 Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/thumb/sphx_glr_00-multi_harmonic_thumb.png differ diff --git a/doc/source/examples/03-harmonic_analyses/images/thumb/sphx_glr_01-modal_superposition_thumb.png b/doc/source/examples/03-harmonic_analyses/images/thumb/sphx_glr_01-modal_superposition_thumb.png new file mode 100644 index 0000000000..401b00b55f Binary files /dev/null and b/doc/source/examples/03-harmonic_analyses/images/thumb/sphx_glr_01-modal_superposition_thumb.png differ diff --git a/doc/source/examples/03-harmonic_analyses/index.rst b/doc/source/examples/03-harmonic_analyses/index.rst new file mode 100644 index 0000000000..90cd92c1fe --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/index.rst @@ -0,0 +1,63 @@ + + +.. _sphx_glr_examples_03-harmonic_analyses: + +.. _harmonic_examples: + +Harmonic analysis examples +=========================== +These examples show how to use DPF to extract and manipulate +results from harmonic analyses. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/03-harmonic_analyses/images/thumb/sphx_glr_00-multi_harmonic_thumb.png + :alt: Multi-harmonic response example + + :ref:`sphx_glr_examples_03-harmonic_analyses_00-multi_harmonic.py` + +.. raw:: html + +
Multi-harmonic response example
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/03-harmonic_analyses/images/thumb/sphx_glr_01-modal_superposition_thumb.png + :alt: Expand harmonic modal superposition with DPF + + :ref:`sphx_glr_examples_03-harmonic_analyses_01-modal_superposition.py` + +.. raw:: html + +
Expand harmonic modal superposition with DPF
+
+ + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /examples/03-harmonic_analyses/00-multi_harmonic + /examples/03-harmonic_analyses/01-modal_superposition + diff --git a/doc/source/examples/03-harmonic_analyses/sg_execution_times.rst b/doc/source/examples/03-harmonic_analyses/sg_execution_times.rst new file mode 100644 index 0000000000..bb8b0042d6 --- /dev/null +++ b/doc/source/examples/03-harmonic_analyses/sg_execution_times.rst @@ -0,0 +1,14 @@ + +:orphan: + +.. _sphx_glr_examples_03-harmonic_analyses_sg_execution_times: + +Computation times +================= +**00:10.955** total execution time for **examples_03-harmonic_analyses** files: + ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_03-harmonic_analyses_01-modal_superposition.py` (``01-modal_superposition.py``) | 00:08.624 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_03-harmonic_analyses_00-multi_harmonic.py` (``00-multi_harmonic.py``) | 00:02.331 | 0.0 MB | ++---------------------------------------------------------------------------------------------------------+-----------+--------+ diff --git a/doc/source/examples/04-advanced/00-multistage_advanced_options.ipynb b/doc/source/examples/04-advanced/00-multistage_advanced_options.ipynb new file mode 100644 index 0000000000..6c3e715340 --- /dev/null +++ b/doc/source/examples/04-advanced/00-multistage_advanced_options.ipynb @@ -0,0 +1,180 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Multi-stage cyclic symmetry using advanced customization {#ref_multi_stage_cyclic_advanced}\r\n\r\nThis example shows how to expand on selected sectors the mesh and\r\nresults from a multi-stage cyclic analysis. It also shows how to use the\r\ncyclic support for advanced postprocessing\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the model and display the state of the result.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "cyc = examples.download_multi_stage_cyclic_result()\nmodel = dpf.Model(cyc)\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check the result info to verify that it\\'s a multi-stage model\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "result_info = model.metadata.result_info\nprint(result_info.has_cyclic)\nprint(result_info.cyclic_symmetry_type)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Go over the cyclic support\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "cyc_support = result_info.cyclic_support\nprint(\"num stages:\", cyc_support.num_stages)\nprint(\"num_sectors stage 0:\", cyc_support.num_sectors(0))\nprint(\"num_sectors stage 1:\", cyc_support.num_sectors(1))\nprint(\n \"num nodes in the first stage's base sector: \",\n len(cyc_support.base_nodes_scoping(0)),\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Expand displacement results\r\n\r\nThis example expands displacement results on chosen sectors.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create displacement cyclic operator\nUCyc = dpf.operators.result.cyclic_expanded_displacement()\nUCyc.inputs.data_sources(model.metadata.data_sources)\n# Select the sectors to expand on the first stage\nUCyc.inputs.sectors_to_expand([0, 1, 2])\n# Or select the sectors to expand stage by stage\nsectors_scopings = dpf.ScopingsContainer()\nsectors_scopings.labels = [\"stage\"]\nsectors_scopings.add_scoping({\"stage\": 0}, dpf.Scoping(ids=[0, 1, 2]))\nsectors_scopings.add_scoping({\"stage\": 1}, dpf.Scoping(ids=[0, 1, 2, 3, 4, 5, 6]))\nUCyc.inputs.sectors_to_expand(sectors_scopings)\n\n# expand the displacements and get a total deformation\nnrm = dpf.Operator(\"norm_fc\")\nnrm.inputs.connect(UCyc.outputs)\nfields = nrm.outputs.fields_container()\n\n# # get the expanded mesh\nmesh_provider = model.metadata.mesh_provider\nmesh_provider.inputs.read_cyclic(2)\nmesh = mesh_provider.outputs.mesh()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot the expanded result on the expanded mesh\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh.plot(fields)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Choose to expand only some sectors for the mesh\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "cyc_support_provider = ops.metadata.cyclic_support_provider(\n data_sources=model.metadata.data_sources\n)\ncyc_support_provider.inputs.sectors_to_expand(sectors_scopings)\nmesh_exp = ops.metadata.cyclic_mesh_expansion(cyclic_support=cyc_support_provider)\nselected_sectors_mesh = mesh_exp.outputs.meshed_region()\n\n# # plot the expanded result on the expanded mesh\nselected_sectors_mesh.plot(fields)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Check results precisely\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Print the time_freq_support to see the harmonic index\nprint(model.metadata.time_freq_support)\nprint(model.metadata.time_freq_support.get_harmonic_indices(stage_num=1).data)\n\n# Harmonic index 0 means that the results are symmetric sectors by sector\n# taking a node in the base sector of the first stage\nnode_id = cyc_support.base_nodes_scoping(0)[18]\nprint(node_id)\n\n# Check what are the expanded ids of this node\nexpanded_ids = cyc_support.expand_node_id(node_id, [0, 1, 2], 0)\nprint(expanded_ids.ids)\n\n# Verify that the displacement values are the same on all those nodes\nfor node in expanded_ids.ids:\n print(fields[0].get_entity_data_by_id(node))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/00-multistage_advanced_options.py b/doc/source/examples/04-advanced/00-multistage_advanced_options.py new file mode 100644 index 0000000000..ccc437d5ac --- /dev/null +++ b/doc/source/examples/04-advanced/00-multistage_advanced_options.py @@ -0,0 +1,103 @@ +""" +.. _ref_multi_stage_cyclic_advanced: + +Multi-stage cyclic symmetry using advanced customization +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to expand on selected sectors the mesh and results +from a multi-stage cyclic analysis. It also shows how to use the cyclic support +for advanced postprocessing +""" +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + +############################################################################### +# Create the model and display the state of the result. +cyc = examples.download_multi_stage_cyclic_result() +model = dpf.Model(cyc) +print(model) + +############################################################################### +# Check the result info to verify that it's a multi-stage model +result_info = model.metadata.result_info +print(result_info.has_cyclic) +print(result_info.cyclic_symmetry_type) + +############################################################################### +# Go over the cyclic support +cyc_support = result_info.cyclic_support +print("num stages:", cyc_support.num_stages) +print("num_sectors stage 0:", cyc_support.num_sectors(0)) +print("num_sectors stage 1:", cyc_support.num_sectors(1)) +print( + "num nodes in the first stage's base sector: ", + len(cyc_support.base_nodes_scoping(0)), +) + +############################################################################### +# Expand displacement results +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This example expands displacement results on chosen sectors. + + +# Create displacement cyclic operator +UCyc = dpf.operators.result.cyclic_expanded_displacement() +UCyc.inputs.data_sources(model.metadata.data_sources) +# Select the sectors to expand on the first stage +UCyc.inputs.sectors_to_expand([0, 1, 2]) +# Or select the sectors to expand stage by stage +sectors_scopings = dpf.ScopingsContainer() +sectors_scopings.labels = ["stage"] +sectors_scopings.add_scoping({"stage": 0}, dpf.Scoping(ids=[0, 1, 2])) +sectors_scopings.add_scoping({"stage": 1}, dpf.Scoping(ids=[0, 1, 2, 3, 4, 5, 6])) +UCyc.inputs.sectors_to_expand(sectors_scopings) + +# expand the displacements and get a total deformation +nrm = dpf.Operator("norm_fc") +nrm.inputs.connect(UCyc.outputs) +fields = nrm.outputs.fields_container() + +# # get the expanded mesh +mesh_provider = model.metadata.mesh_provider +mesh_provider.inputs.read_cyclic(2) +mesh = mesh_provider.outputs.mesh() + +############################################################################### +# Plot the expanded result on the expanded mesh +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +mesh.plot(fields) + +############################################################################### +# Choose to expand only some sectors for the mesh +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cyc_support_provider = ops.metadata.cyclic_support_provider( + data_sources=model.metadata.data_sources +) +cyc_support_provider.inputs.sectors_to_expand(sectors_scopings) +mesh_exp = ops.metadata.cyclic_mesh_expansion(cyclic_support=cyc_support_provider) +selected_sectors_mesh = mesh_exp.outputs.meshed_region() + +# # plot the expanded result on the expanded mesh +selected_sectors_mesh.plot(fields) + +############################################################################### +# Check results precisely +# ~~~~~~~~~~~~~~~~~~~~~~~ + +# Print the time_freq_support to see the harmonic index +print(model.metadata.time_freq_support) +print(model.metadata.time_freq_support.get_harmonic_indices(stage_num=1).data) + +# Harmonic index 0 means that the results are symmetric sectors by sector +# taking a node in the base sector of the first stage +node_id = cyc_support.base_nodes_scoping(0)[18] +print(node_id) + +# Check what are the expanded ids of this node +expanded_ids = cyc_support.expand_node_id(node_id, [0, 1, 2], 0) +print(expanded_ids.ids) + +# Verify that the displacement values are the same on all those nodes +for node in expanded_ids.ids: + print(fields[0].get_entity_data_by_id(node)) diff --git a/doc/source/examples/04-advanced/00-multistage_advanced_options.py.md5 b/doc/source/examples/04-advanced/00-multistage_advanced_options.py.md5 new file mode 100644 index 0000000000..0102924d0c --- /dev/null +++ b/doc/source/examples/04-advanced/00-multistage_advanced_options.py.md5 @@ -0,0 +1 @@ +ef0fb5387bc49af9f9b8ea8842b330c5 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/00-multistage_advanced_options.rst b/doc/source/examples/04-advanced/00-multistage_advanced_options.rst new file mode 100644 index 0000000000..f833616549 --- /dev/null +++ b/doc/source/examples/04-advanced/00-multistage_advanced_options.rst @@ -0,0 +1,331 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\00-multistage_advanced_options.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_00-multistage_advanced_options.py: + + +.. _ref_multi_stage_cyclic_advanced: + +Multi-stage cyclic symmetry using advanced customization +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to expand on selected sectors the mesh and results +from a multi-stage cyclic analysis. It also shows how to use the cyclic support +for advanced postprocessing + +.. GENERATED FROM PYTHON SOURCE LINES 11-15 + +.. code-block:: default + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 16-17 + +Create the model and display the state of the result. + +.. GENERATED FROM PYTHON SOURCE LINES 17-21 + +.. code-block:: default + + cyc = examples.download_multi_stage_cyclic_result() + model = dpf.Model(cyc) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Modal analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - stress: ElementalNodal Stress + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 3595 nodes + 1557 elements + Unit: m + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 6 + Cumulative Frequency (Hz) LoadStep Substep Harmonic index + 1 188,385357 1 1 0,000000 + 2 325,126418 1 2 0,000000 + 3 595,320548 1 3 0,000000 + 4 638,189511 1 4 0,000000 + 5 775,669703 1 5 0,000000 + 6 928,278013 1 6 0,000000 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-23 + +Check the result info to verify that it's a multi-stage model + +.. GENERATED FROM PYTHON SOURCE LINES 23-27 + +.. code-block:: default + + result_info = model.metadata.result_info + print(result_info.has_cyclic) + print(result_info.cyclic_symmetry_type) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + True + multi_stage + + + + +.. GENERATED FROM PYTHON SOURCE LINES 28-29 + +Go over the cyclic support + +.. GENERATED FROM PYTHON SOURCE LINES 29-38 + +.. code-block:: default + + cyc_support = result_info.cyclic_support + print("num stages:", cyc_support.num_stages) + print("num_sectors stage 0:", cyc_support.num_sectors(0)) + print("num_sectors stage 1:", cyc_support.num_sectors(1)) + print( + "num nodes in the first stage's base sector: ", + len(cyc_support.base_nodes_scoping(0)), + ) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + num stages: 2 + num_sectors stage 0: 6 + num_sectors stage 1: 12 + num nodes in the first stage's base sector: 2220 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 39-42 + +Expand displacement results +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example expands displacement results on chosen sectors. + +.. GENERATED FROM PYTHON SOURCE LINES 42-66 + +.. code-block:: default + + + + # Create displacement cyclic operator + UCyc = dpf.operators.result.cyclic_expanded_displacement() + UCyc.inputs.data_sources(model.metadata.data_sources) + # Select the sectors to expand on the first stage + UCyc.inputs.sectors_to_expand([0, 1, 2]) + # Or select the sectors to expand stage by stage + sectors_scopings = dpf.ScopingsContainer() + sectors_scopings.labels = ["stage"] + sectors_scopings.add_scoping({"stage": 0}, dpf.Scoping(ids=[0, 1, 2])) + sectors_scopings.add_scoping({"stage": 1}, dpf.Scoping(ids=[0, 1, 2, 3, 4, 5, 6])) + UCyc.inputs.sectors_to_expand(sectors_scopings) + + # expand the displacements and get a total deformation + nrm = dpf.Operator("norm_fc") + nrm.inputs.connect(UCyc.outputs) + fields = nrm.outputs.fields_container() + + # # get the expanded mesh + mesh_provider = model.metadata.mesh_provider + mesh_provider.inputs.read_cyclic(2) + mesh = mesh_provider.outputs.mesh() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 67-69 + +Plot the expanded result on the expanded mesh +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 69-71 + +.. code-block:: default + + mesh.plot(fields) + + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_001.png + :alt: 00 multistage advanced options + :srcset: /examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 72-74 + +Choose to expand only some sectors for the mesh +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 74-84 + +.. code-block:: default + + cyc_support_provider = ops.metadata.cyclic_support_provider( + data_sources=model.metadata.data_sources + ) + cyc_support_provider.inputs.sectors_to_expand(sectors_scopings) + mesh_exp = ops.metadata.cyclic_mesh_expansion(cyclic_support=cyc_support_provider) + selected_sectors_mesh = mesh_exp.outputs.meshed_region() + + # # plot the expanded result on the expanded mesh + selected_sectors_mesh.plot(fields) + + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_002.png + :alt: 00 multistage advanced options + :srcset: /examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_002.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-87 + +Check results precisely +~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 87-104 + +.. code-block:: default + + + # Print the time_freq_support to see the harmonic index + print(model.metadata.time_freq_support) + print(model.metadata.time_freq_support.get_harmonic_indices(stage_num=1).data) + + # Harmonic index 0 means that the results are symmetric sectors by sector + # taking a node in the base sector of the first stage + node_id = cyc_support.base_nodes_scoping(0)[18] + print(node_id) + + # Check what are the expanded ids of this node + expanded_ids = cyc_support.expand_node_id(node_id, [0, 1, 2], 0) + print(expanded_ids.ids) + + # Verify that the displacement values are the same on all those nodes + for node in expanded_ids.ids: + print(fields[0].get_entity_data_by_id(node)) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Time/Freq Support: + Number of sets: 6 + Cumulative Frequency (Hz) LoadStep Substep Harmonic index + 1 188,385357 1 1 0,000000 + 2 325,126418 1 2 0,000000 + 3 595,320548 1 3 0,000000 + 4 638,189511 1 4 0,000000 + 5 775,669703 1 5 0,000000 + 6 928,278013 1 6 0,000000 + + [0. 0. 0. 0. 0. 0.] + 1394 + [1394 4989 7209] + [0.07179672] + [0.07179672] + [0.07179672] + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 1.292 seconds) + + +.. _sphx_glr_download_examples_04-advanced_00-multistage_advanced_options.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 00-multistage_advanced_options.py <00-multistage_advanced_options.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 00-multistage_advanced_options.ipynb <00-multistage_advanced_options.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/00-multistage_advanced_options_codeobj.pickle b/doc/source/examples/04-advanced/00-multistage_advanced_options_codeobj.pickle new file mode 100644 index 0000000000..dbd0c84590 Binary files /dev/null and b/doc/source/examples/04-advanced/00-multistage_advanced_options_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/01-solve_harmonic_problem.ipynb b/doc/source/examples/04-advanced/01-solve_harmonic_problem.ipynb new file mode 100644 index 0000000000..089f733ba4 --- /dev/null +++ b/doc/source/examples/04-advanced/01-solve_harmonic_problem.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Solve harmonic problem (with damping) using matrix inverse {#ref_solve_modal_problem_advanced}\r\n\r\nThis example shows how to create a harmonic (over frequencies) fields\r\ncontainer for an analysis with damping. This fields container is then\r\nused to solve the problem Ma+Dv+Ku=F by inverting the matrix\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import math\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create 2D (x,y) matrix fields for inertia, damping, and stiffness.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "freq = [25, 50, 100, 200, 400]\ndim = 2 # dimension of matrix\n\nfM0 = dpf.fields_factory.create_matrix_field(1, dim, dim)\nfM0.append([0.0, 1.0, 2.0, 3.0], 1)\nfK0 = dpf.fields_factory.create_matrix_field(1, dim, dim)\nfK0.append([4.0, 8.0, 0.0, 1.0], 1)\nfC0 = dpf.fields_factory.create_matrix_field(1, dim, dim)\nfC0.append([7.0, 5.0, 9.0, 1.0], 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fields container for real and imaginary parts for each\r\nfrequency.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "reals = {}\nims = {}\nfor k, f in enumerate(freq):\n omega = 2.0 * math.pi * f\n omega2 = omega**2\n real = fK0 + fM0 * omega2\n imag = fC0 * omega\n reals[f] = real.outputs.field()\n ims[f] = imag.outputs.field()\n\ncplx_fc = dpf.fields_container_factory.over_time_freq_complex_fields_container(\n reals, ims, time_freq_unit=\"Hz\"\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use DPF operators to inverse the matrix and then compute the amplitude\r\nand the phase.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "inverse = ops.math.matrix_inverse(cplx_fc)\ncomponent = ops.logic.component_selector_fc(inverse, 0)\namp = ops.math.amplitude_fc(component)\nphase = ops.math.phase_fc(component)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the phase and amplitude and then plot it over frequencies.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "amp_over_frequency = amp.outputs.fields_container()\nphase_over_frequency = phase.outputs.fields_container()\ntime_freq_support = amp_over_frequency.time_freq_support\n\namp_array = []\nphase_array = []\nfor f in amp_over_frequency:\n amp_array.append(f.data)\n\nfor f in phase_over_frequency:\n phase_array.append(f.data * 180.0 / math.pi)\n\nimport matplotlib.pyplot as plt\n\nplt.figure()\nplt.plot(time_freq_support.time_frequencies.data, amp_array, \"r\", label=\"amplitude\")\nplt.xlabel(\"Frequency (Hz)\")\nplt.ylabel(\"Displacement ampliude (m)\")\nplt.legend()\nplt.show()\n\nplt.figure()\nplt.plot(time_freq_support.time_frequencies.data, phase_array, \"r\", label=\"phase\")\nplt.xlabel(\"Frequency (Hz)\")\nplt.ylabel(\"Displacement phase (deg)\")\nplt.legend()\nplt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/01-solve_harmonic_problem.py b/doc/source/examples/04-advanced/01-solve_harmonic_problem.py new file mode 100644 index 0000000000..cbb7eb54da --- /dev/null +++ b/doc/source/examples/04-advanced/01-solve_harmonic_problem.py @@ -0,0 +1,87 @@ +""" +.. _ref_solve_modal_problem_advanced: + +Solve harmonic problem (with damping) using matrix inverse +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to create a harmonic (over frequencies) fields +container for an analysis with damping. This fields container is then used to +solve the problem Ma+Dv+Ku=F by inverting the matrix + +""" + +import math + +from ansys.dpf import core as dpf +from ansys.dpf.core import operators as ops + + +############################################################################### +# Create 2D (x,y) matrix fields for inertia, damping, and stiffness. + +freq = [25, 50, 100, 200, 400] +dim = 2 # dimension of matrix + +fM0 = dpf.fields_factory.create_matrix_field(1, dim, dim) +fM0.append([0.0, 1.0, 2.0, 3.0], 1) +fK0 = dpf.fields_factory.create_matrix_field(1, dim, dim) +fK0.append([4.0, 8.0, 0.0, 1.0], 1) +fC0 = dpf.fields_factory.create_matrix_field(1, dim, dim) +fC0.append([7.0, 5.0, 9.0, 1.0], 1) + +############################################################################### +# Create a fields container for real and imaginary parts +# for each frequency. + +reals = {} +ims = {} +for k, f in enumerate(freq): + omega = 2.0 * math.pi * f + omega2 = omega**2 + real = fK0 + fM0 * omega2 + imag = fC0 * omega + reals[f] = real.outputs.field() + ims[f] = imag.outputs.field() + +cplx_fc = dpf.fields_container_factory.over_time_freq_complex_fields_container( + reals, ims, time_freq_unit="Hz" +) + +############################################################################### +# Use DPF operators to inverse the matrix and then compute the amplitude +# and the phase. + +inverse = ops.math.matrix_inverse(cplx_fc) +component = ops.logic.component_selector_fc(inverse, 0) +amp = ops.math.amplitude_fc(component) +phase = ops.math.phase_fc(component) + +############################################################################### +# Get the phase and amplitude and then plot it over frequencies. +amp_over_frequency = amp.outputs.fields_container() +phase_over_frequency = phase.outputs.fields_container() +time_freq_support = amp_over_frequency.time_freq_support + +amp_array = [] +phase_array = [] +for f in amp_over_frequency: + amp_array.append(f.data) + +for f in phase_over_frequency: + phase_array.append(f.data * 180.0 / math.pi) + +import matplotlib.pyplot as plt + +plt.figure() +plt.plot(time_freq_support.time_frequencies.data, amp_array, "r", label="amplitude") +plt.xlabel("Frequency (Hz)") +plt.ylabel("Displacement ampliude (m)") +plt.legend() +plt.show() + +plt.figure() +plt.plot(time_freq_support.time_frequencies.data, phase_array, "r", label="phase") +plt.xlabel("Frequency (Hz)") +plt.ylabel("Displacement phase (deg)") +plt.legend() +plt.show() diff --git a/doc/source/examples/04-advanced/01-solve_harmonic_problem.py.md5 b/doc/source/examples/04-advanced/01-solve_harmonic_problem.py.md5 new file mode 100644 index 0000000000..ed08bee10f --- /dev/null +++ b/doc/source/examples/04-advanced/01-solve_harmonic_problem.py.md5 @@ -0,0 +1 @@ +8f8f30ffe0ada6a38d33e71199a9fec9 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/01-solve_harmonic_problem.rst b/doc/source/examples/04-advanced/01-solve_harmonic_problem.rst new file mode 100644 index 0000000000..ba448b9d60 --- /dev/null +++ b/doc/source/examples/04-advanced/01-solve_harmonic_problem.rst @@ -0,0 +1,212 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\01-solve_harmonic_problem.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_01-solve_harmonic_problem.py: + + +.. _ref_solve_modal_problem_advanced: + +Solve harmonic problem (with damping) using matrix inverse +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to create a harmonic (over frequencies) fields +container for an analysis with damping. This fields container is then used to +solve the problem Ma+Dv+Ku=F by inverting the matrix + +.. GENERATED FROM PYTHON SOURCE LINES 12-19 + +.. code-block:: default + + + import math + + from ansys.dpf import core as dpf + from ansys.dpf.core import operators as ops + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 20-21 + +Create 2D (x,y) matrix fields for inertia, damping, and stiffness. + +.. GENERATED FROM PYTHON SOURCE LINES 21-32 + +.. code-block:: default + + + freq = [25, 50, 100, 200, 400] + dim = 2 # dimension of matrix + + fM0 = dpf.fields_factory.create_matrix_field(1, dim, dim) + fM0.append([0.0, 1.0, 2.0, 3.0], 1) + fK0 = dpf.fields_factory.create_matrix_field(1, dim, dim) + fK0.append([4.0, 8.0, 0.0, 1.0], 1) + fC0 = dpf.fields_factory.create_matrix_field(1, dim, dim) + fC0.append([7.0, 5.0, 9.0, 1.0], 1) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 33-35 + +Create a fields container for real and imaginary parts +for each frequency. + +.. GENERATED FROM PYTHON SOURCE LINES 35-50 + +.. code-block:: default + + + reals = {} + ims = {} + for k, f in enumerate(freq): + omega = 2.0 * math.pi * f + omega2 = omega**2 + real = fK0 + fM0 * omega2 + imag = fC0 * omega + reals[f] = real.outputs.field() + ims[f] = imag.outputs.field() + + cplx_fc = dpf.fields_container_factory.over_time_freq_complex_fields_container( + reals, ims, time_freq_unit="Hz" + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 51-53 + +Use DPF operators to inverse the matrix and then compute the amplitude +and the phase. + +.. GENERATED FROM PYTHON SOURCE LINES 53-59 + +.. code-block:: default + + + inverse = ops.math.matrix_inverse(cplx_fc) + component = ops.logic.component_selector_fc(inverse, 0) + amp = ops.math.amplitude_fc(component) + phase = ops.math.phase_fc(component) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 60-61 + +Get the phase and amplitude and then plot it over frequencies. + +.. GENERATED FROM PYTHON SOURCE LINES 61-88 + +.. code-block:: default + + amp_over_frequency = amp.outputs.fields_container() + phase_over_frequency = phase.outputs.fields_container() + time_freq_support = amp_over_frequency.time_freq_support + + amp_array = [] + phase_array = [] + for f in amp_over_frequency: + amp_array.append(f.data) + + for f in phase_over_frequency: + phase_array.append(f.data * 180.0 / math.pi) + + import matplotlib.pyplot as plt + + plt.figure() + plt.plot(time_freq_support.time_frequencies.data, amp_array, "r", label="amplitude") + plt.xlabel("Frequency (Hz)") + plt.ylabel("Displacement ampliude (m)") + plt.legend() + plt.show() + + plt.figure() + plt.plot(time_freq_support.time_frequencies.data, phase_array, "r", label="phase") + plt.xlabel("Frequency (Hz)") + plt.ylabel("Displacement phase (deg)") + plt.legend() + plt.show() + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_001.png + :alt: 01 solve harmonic problem + :srcset: /examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_002.png + :alt: 01 solve harmonic problem + :srcset: /examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_002.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.212 seconds) + + +.. _sphx_glr_download_examples_04-advanced_01-solve_harmonic_problem.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 01-solve_harmonic_problem.py <01-solve_harmonic_problem.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 01-solve_harmonic_problem.ipynb <01-solve_harmonic_problem.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/01-solve_harmonic_problem_codeobj.pickle b/doc/source/examples/04-advanced/01-solve_harmonic_problem_codeobj.pickle new file mode 100644 index 0000000000..89b5dc3317 Binary files /dev/null and b/doc/source/examples/04-advanced/01-solve_harmonic_problem_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/02-volume_averaged_stress.ipynb b/doc/source/examples/04-advanced/02-volume_averaged_stress.ipynb new file mode 100644 index 0000000000..5b1a16f0f1 --- /dev/null +++ b/doc/source/examples/04-advanced/02-volume_averaged_stress.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Average elemental stress on a given volume {#ref_volume_averaged_stress_advanced}\r\n\r\nThis example shows how to find the minimum list of surrounding elements\r\nfor a given node to get a minimum volume. For each list of elements, the\r\nelemental stress equivalent is multiplied by the volume of each element.\r\nThis result is then accumulated to divide it by the total volume.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a model targeting a given result file\r\n\r\nThe model provides easy access to the mesh and time frequency support.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.find_complex_rst())\nmesh = model.metadata.meshed_region\n\n# Volume size to check\nvolume_check = 4.0e-11\n\n# Get all node IDs in the model to find the minimum amount of\n# surrounding elements to get a minimum volume.\nnodes = mesh.nodes.scoping\nnodes_ids = nodes.ids\nnodes_ids_to_compute = []\nfor i in range(0, 400):\n nodes_ids_to_compute.append(nodes_ids[i])\nelements = mesh.elements.scoping\nelements_ids = elements.ids" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Read the volume by element\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "vol_op = ops.result.elemental_volume()\nvol_op.inputs.streams_container(model.metadata.streams_provider)\nvol_field = vol_op.outputs.fields_container()[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Find the minimum list of elements by node to get the volume check\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# get the connectivity and inverse connectivity fields\nconnectivity_field = mesh.elements.connectivities_field\nnodal_connectivity_field = mesh.nodes.nodal_connectivity_field\n\nnode_index_to_el_ids = {}\nnode_index_to_found_volume = {}\n# using the with statement with as_local_field allows to bring the server's\n# data locally and to work only on the local process before sending the data\n# updates to the server as the end of the with statement\n# the performances are a lot better using this syntax\n# fmt: off\nwith connectivity_field.as_local_field() as connectivity, \\\n nodal_connectivity_field.as_local_field() as nodal_connectivity,\\\n vol_field.as_local_field() as vol: # fmt: on\n for i, node in enumerate(nodes_ids_to_compute):\n\n current_node_indexes = [i]\n volume = 0.0\n # Loop through recursively selecting elements attached\n # to nodes until specified volume is reached\n while volume_check > volume:\n volume = 0.0\n elements_indexes = []\n\n # Get elements attached to nodes\n for current_node_index in current_node_indexes:\n elements_indexes.extend(nodal_connectivity.get_entity_data(i).flatten())\n\n current_node_indexes = []\n for index in elements_indexes:\n # Sum up the volume on those elements\n volume += vol.get_entity_data(index)[0]\n # Get all nodes of the current elements for next iteration\n current_node_indexes.extend(connectivity.get_entity_data(index))\n\n node_index_to_el_ids[i] = [elements_ids[index] for index in elements_indexes]\n node_index_to_found_volume[i] = volume" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create workflow\r\n\r\nFor each list of elements surrounding nodes:\r\n\r\n- Compute equivalent stress averaged on elements.\r\n- Apply dot product seqv.volume.\r\n- Sum up those on the list of elements.\r\n- Divide this sum by the total volume on these elements.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s = model.results.stress()\nto_elemental = ops.averaging.to_elemental_fc(s)\neqv = ops.invariant.von_mises_eqv_fc(to_elemental)\nvalues_to_sum_field = eqv.outputs.fields_container()[0]\n\n# sum up the seqv by list of elements and create a Field\nseqvsum = dpf.fields_factory.create_scalar_field(len(nodes), dpf.locations.nodal)\ndataseqvsum = []\nvolsum = dpf.fields_factory.create_scalar_field(len(nodes), dpf.locations.nodal)\ndatavolsum = []\n\nwith values_to_sum_field.as_local_field() as values_to_sum:\n with vol_field.as_local_field() as vol:\n for key in node_index_to_el_ids:\n ssum = 0.0\n for id in node_index_to_el_ids[key]:\n ssum += (\n values_to_sum.get_entity_data_by_id(id)[0] * vol.get_entity_data_by_id(id)[0]\n )\n dataseqvsum.append(ssum)\n datavolsum.append(node_index_to_found_volume[key])\n\nseqvsum.data = dataseqvsum\nseqvsum.scoping.ids = nodes_ids_to_compute\n\nvolsum.data = datavolsum\nvolsum.scoping.ids = nodes_ids_to_compute\n\n# use component wise divide to average the stress by the volume\ndivide = ops.math.component_wise_divide(seqvsum, volsum)\ndivide.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot equivalent elemental stress and volume averaged elemental equivalent stress\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh.plot(values_to_sum_field)\nmesh.plot(divide.outputs.field())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use the operator instead\r\n\r\nAn operator with the same algorithm has been implemented\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s_fc = s.outputs.fields_container()\nsingle_field_vol_fc = dpf.fields_container_factory.over_time_freq_fields_container([vol_field])\n\nsingle_field_fc = dpf.fields_container_factory.over_time_freq_fields_container(\n [values_to_sum_field]\n)\n\nop = dpf.Operator(\"volume_stress\")\nop.inputs.scoping.connect(nodes)\nop.inputs.stress_fields.connect(single_field_fc)\nop.inputs.volume_fields(single_field_vol_fc)\nop.inputs.volume(volume_check * 10.0)\n\nout = op.get_output(0, dpf.types.field)\nmesh.plot(out)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/02-volume_averaged_stress.py b/doc/source/examples/04-advanced/02-volume_averaged_stress.py new file mode 100644 index 0000000000..be293149c0 --- /dev/null +++ b/doc/source/examples/04-advanced/02-volume_averaged_stress.py @@ -0,0 +1,156 @@ +""" +.. _ref_volume_averaged_stress_advanced: + +Average elemental stress on a given volume +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to find the minimum list of surrounding +elements for a given node to get a minimum volume. +For each list of elements, the elemental stress equivalent is multiplied by the +volume of each element. This result is then accumulated to divide it by the +total volume. + +""" +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + + +############################################################################### +# Create a model targeting a given result file +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The model provides easy access to the mesh and time frequency support. + +model = dpf.Model(examples.find_complex_rst()) +mesh = model.metadata.meshed_region + +# Volume size to check +volume_check = 4.0e-11 + +# Get all node IDs in the model to find the minimum amount of +# surrounding elements to get a minimum volume. +nodes = mesh.nodes.scoping +nodes_ids = nodes.ids +nodes_ids_to_compute = [] +for i in range(0, 400): + nodes_ids_to_compute.append(nodes_ids[i]) +elements = mesh.elements.scoping +elements_ids = elements.ids + +############################################################################### +# Read the volume by element +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +vol_op = ops.result.elemental_volume() +vol_op.inputs.streams_container(model.metadata.streams_provider) +vol_field = vol_op.outputs.fields_container()[0] + +############################################################################### +# Find the minimum list of elements by node to get the volume check +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# get the connectivity and inverse connectivity fields +connectivity_field = mesh.elements.connectivities_field +nodal_connectivity_field = mesh.nodes.nodal_connectivity_field + +node_index_to_el_ids = {} +node_index_to_found_volume = {} +# using the with statement with as_local_field allows to bring the server's +# data locally and to work only on the local process before sending the data +# updates to the server as the end of the with statement +# the performances are a lot better using this syntax +# fmt: off +with connectivity_field.as_local_field() as connectivity, \ + nodal_connectivity_field.as_local_field() as nodal_connectivity,\ + vol_field.as_local_field() as vol: # fmt: on + for i, node in enumerate(nodes_ids_to_compute): + + current_node_indexes = [i] + volume = 0.0 + # Loop through recursively selecting elements attached + # to nodes until specified volume is reached + while volume_check > volume: + volume = 0.0 + elements_indexes = [] + + # Get elements attached to nodes + for current_node_index in current_node_indexes: + elements_indexes.extend(nodal_connectivity.get_entity_data(i).flatten()) + + current_node_indexes = [] + for index in elements_indexes: + # Sum up the volume on those elements + volume += vol.get_entity_data(index)[0] + # Get all nodes of the current elements for next iteration + current_node_indexes.extend(connectivity.get_entity_data(index)) + + node_index_to_el_ids[i] = [elements_ids[index] for index in elements_indexes] + node_index_to_found_volume[i] = volume + +############################################################################### +# Create workflow +# ~~~~~~~~~~~~~~~ +# For each list of elements surrounding nodes: +# +# - Compute equivalent stress averaged on elements. +# - Apply dot product seqv.volume. +# - Sum up those on the list of elements. +# - Divide this sum by the total volume on these elements. +# + +s = model.results.stress() +to_elemental = ops.averaging.to_elemental_fc(s) +eqv = ops.invariant.von_mises_eqv_fc(to_elemental) +values_to_sum_field = eqv.outputs.fields_container()[0] + +# sum up the seqv by list of elements and create a Field +seqvsum = dpf.fields_factory.create_scalar_field(len(nodes), dpf.locations.nodal) +dataseqvsum = [] +volsum = dpf.fields_factory.create_scalar_field(len(nodes), dpf.locations.nodal) +datavolsum = [] + +with values_to_sum_field.as_local_field() as values_to_sum: + with vol_field.as_local_field() as vol: + for key in node_index_to_el_ids: + ssum = 0.0 + for id in node_index_to_el_ids[key]: + ssum += ( + values_to_sum.get_entity_data_by_id(id)[0] * vol.get_entity_data_by_id(id)[0] + ) + dataseqvsum.append(ssum) + datavolsum.append(node_index_to_found_volume[key]) + +seqvsum.data = dataseqvsum +seqvsum.scoping.ids = nodes_ids_to_compute + +volsum.data = datavolsum +volsum.scoping.ids = nodes_ids_to_compute + +# use component wise divide to average the stress by the volume +divide = ops.math.component_wise_divide(seqvsum, volsum) +divide.run() + +############################################################################### +# Plot equivalent elemental stress and volume averaged elemental equivalent stress +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +mesh.plot(values_to_sum_field) +mesh.plot(divide.outputs.field()) + +############################################################################### +# Use the operator instead +# ~~~~~~~~~~~~~~~~~~~~~~~~ +# An operator with the same algorithm has been implemented +s_fc = s.outputs.fields_container() +single_field_vol_fc = dpf.fields_container_factory.over_time_freq_fields_container([vol_field]) + +single_field_fc = dpf.fields_container_factory.over_time_freq_fields_container( + [values_to_sum_field] +) + +op = dpf.Operator("volume_stress") +op.inputs.scoping.connect(nodes) +op.inputs.stress_fields.connect(single_field_fc) +op.inputs.volume_fields(single_field_vol_fc) +op.inputs.volume(volume_check * 10.0) + +out = op.get_output(0, dpf.types.field) +mesh.plot(out) diff --git a/doc/source/examples/04-advanced/02-volume_averaged_stress.py.md5 b/doc/source/examples/04-advanced/02-volume_averaged_stress.py.md5 new file mode 100644 index 0000000000..85028dc419 --- /dev/null +++ b/doc/source/examples/04-advanced/02-volume_averaged_stress.py.md5 @@ -0,0 +1 @@ +3ee77c548ffc65fa8d5528eeed8723b7 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/02-volume_averaged_stress.rst b/doc/source/examples/04-advanced/02-volume_averaged_stress.rst new file mode 100644 index 0000000000..becd431580 --- /dev/null +++ b/doc/source/examples/04-advanced/02-volume_averaged_stress.rst @@ -0,0 +1,312 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\02-volume_averaged_stress.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_02-volume_averaged_stress.py: + + +.. _ref_volume_averaged_stress_advanced: + +Average elemental stress on a given volume +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to find the minimum list of surrounding +elements for a given node to get a minimum volume. +For each list of elements, the elemental stress equivalent is multiplied by the +volume of each element. This result is then accumulated to divide it by the +total volume. + +.. GENERATED FROM PYTHON SOURCE LINES 14-19 + +.. code-block:: default + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 20-23 + +Create a model targeting a given result file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The model provides easy access to the mesh and time frequency support. + +.. GENERATED FROM PYTHON SOURCE LINES 23-40 + +.. code-block:: default + + + model = dpf.Model(examples.find_complex_rst()) + mesh = model.metadata.meshed_region + + # Volume size to check + volume_check = 4.0e-11 + + # Get all node IDs in the model to find the minimum amount of + # surrounding elements to get a minimum volume. + nodes = mesh.nodes.scoping + nodes_ids = nodes.ids + nodes_ids_to_compute = [] + for i in range(0, 400): + nodes_ids_to_compute.append(nodes_ids[i]) + elements = mesh.elements.scoping + elements_ids = elements.ids + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 41-43 + +Read the volume by element +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 43-47 + +.. code-block:: default + + vol_op = ops.result.elemental_volume() + vol_op.inputs.streams_container(model.metadata.streams_provider) + vol_field = vol_op.outputs.fields_container()[0] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-50 + +Find the minimum list of elements by node to get the volume check +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 50-89 + +.. code-block:: default + + + # get the connectivity and inverse connectivity fields + connectivity_field = mesh.elements.connectivities_field + nodal_connectivity_field = mesh.nodes.nodal_connectivity_field + + node_index_to_el_ids = {} + node_index_to_found_volume = {} + # using the with statement with as_local_field allows to bring the server's + # data locally and to work only on the local process before sending the data + # updates to the server as the end of the with statement + # the performances are a lot better using this syntax + # fmt: off + with connectivity_field.as_local_field() as connectivity, \ + nodal_connectivity_field.as_local_field() as nodal_connectivity,\ + vol_field.as_local_field() as vol: # fmt: on + for i, node in enumerate(nodes_ids_to_compute): + + current_node_indexes = [i] + volume = 0.0 + # Loop through recursively selecting elements attached + # to nodes until specified volume is reached + while volume_check > volume: + volume = 0.0 + elements_indexes = [] + + # Get elements attached to nodes + for current_node_index in current_node_indexes: + elements_indexes.extend(nodal_connectivity.get_entity_data(i).flatten()) + + current_node_indexes = [] + for index in elements_indexes: + # Sum up the volume on those elements + volume += vol.get_entity_data(index)[0] + # Get all nodes of the current elements for next iteration + current_node_indexes.extend(connectivity.get_entity_data(index)) + + node_index_to_el_ids[i] = [elements_ids[index] for index in elements_indexes] + node_index_to_found_volume[i] = volume + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 90-99 + +Create workflow +~~~~~~~~~~~~~~~ +For each list of elements surrounding nodes: + +- Compute equivalent stress averaged on elements. +- Apply dot product seqv.volume. +- Sum up those on the list of elements. +- Divide this sum by the total volume on these elements. + + +.. GENERATED FROM PYTHON SOURCE LINES 99-132 + +.. code-block:: default + + + s = model.results.stress() + to_elemental = ops.averaging.to_elemental_fc(s) + eqv = ops.invariant.von_mises_eqv_fc(to_elemental) + values_to_sum_field = eqv.outputs.fields_container()[0] + + # sum up the seqv by list of elements and create a Field + seqvsum = dpf.fields_factory.create_scalar_field(len(nodes), dpf.locations.nodal) + dataseqvsum = [] + volsum = dpf.fields_factory.create_scalar_field(len(nodes), dpf.locations.nodal) + datavolsum = [] + + with values_to_sum_field.as_local_field() as values_to_sum: + with vol_field.as_local_field() as vol: + for key in node_index_to_el_ids: + ssum = 0.0 + for id in node_index_to_el_ids[key]: + ssum += ( + values_to_sum.get_entity_data_by_id(id)[0] * vol.get_entity_data_by_id(id)[0] + ) + dataseqvsum.append(ssum) + datavolsum.append(node_index_to_found_volume[key]) + + seqvsum.data = dataseqvsum + seqvsum.scoping.ids = nodes_ids_to_compute + + volsum.data = datavolsum + volsum.scoping.ids = nodes_ids_to_compute + + # use component wise divide to average the stress by the volume + divide = ops.math.component_wise_divide(seqvsum, volsum) + divide.run() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 133-135 + +Plot equivalent elemental stress and volume averaged elemental equivalent stress +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 135-138 + +.. code-block:: default + + mesh.plot(values_to_sum_field) + mesh.plot(divide.outputs.field()) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_001.png + :alt: 02 volume averaged stress + :srcset: /examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_002.png + :alt: 02 volume averaged stress + :srcset: /examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_002.png + :class: sphx-glr-multi-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 139-142 + +Use the operator instead +~~~~~~~~~~~~~~~~~~~~~~~~ +An operator with the same algorithm has been implemented + +.. GENERATED FROM PYTHON SOURCE LINES 142-157 + +.. code-block:: default + + s_fc = s.outputs.fields_container() + single_field_vol_fc = dpf.fields_container_factory.over_time_freq_fields_container([vol_field]) + + single_field_fc = dpf.fields_container_factory.over_time_freq_fields_container( + [values_to_sum_field] + ) + + op = dpf.Operator("volume_stress") + op.inputs.scoping.connect(nodes) + op.inputs.stress_fields.connect(single_field_fc) + op.inputs.volume_fields(single_field_vol_fc) + op.inputs.volume(volume_check * 10.0) + + out = op.get_output(0, dpf.types.field) + mesh.plot(out) + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_003.png + :alt: 02 volume averaged stress + :srcset: /examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_003.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 3.061 seconds) + + +.. _sphx_glr_download_examples_04-advanced_02-volume_averaged_stress.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 02-volume_averaged_stress.py <02-volume_averaged_stress.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 02-volume_averaged_stress.ipynb <02-volume_averaged_stress.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/examples/04-advanced/02-volume_averaged_stress/sphx_glr_02-volume_averaged_stress_001.png b/doc/source/examples/04-advanced/02-volume_averaged_stress/sphx_glr_02-volume_averaged_stress_001.png similarity index 100% rename from docs/source/examples/04-advanced/02-volume_averaged_stress/sphx_glr_02-volume_averaged_stress_001.png rename to doc/source/examples/04-advanced/02-volume_averaged_stress/sphx_glr_02-volume_averaged_stress_001.png diff --git a/doc/source/examples/04-advanced/02-volume_averaged_stress_codeobj.pickle b/doc/source/examples/04-advanced/02-volume_averaged_stress_codeobj.pickle new file mode 100644 index 0000000000..32babc3dc0 Binary files /dev/null and b/doc/source/examples/04-advanced/02-volume_averaged_stress_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/03-exchange_data_between_servers.ipynb b/doc/source/examples/04-advanced/03-exchange_data_between_servers.ipynb new file mode 100644 index 0000000000..a43122b299 --- /dev/null +++ b/doc/source/examples/04-advanced/03-exchange_data_between_servers.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Exchange data between servers {#ref_exchange_data_between_servers.}\r\n\r\nIn this example, two DPF servers are started, and a workflow is created\r\nwith a part on both servers. This example shows how you can read data\r\nfrom a given machine and transform this data on another machine without\r\nany more difficulties than working on a local computer.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create two servers\r\n\r\nUse the\r\n`start_local_server() `{.interpreted-text\r\nrole=\"func\"} method to start two servers on your local machine. If you\r\nhave another server, you can use the\r\n`connect_to_server() `{.interpreted-text\r\nrole=\"func\"} method to connect to any DPF server on your network.\r\n\r\nThe `as_global` attributes allows you to choose whether a server is\r\nstored by the module and used by default. This example sets the first\r\nserver as the default.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "server1 = dpf.start_local_server(as_global=True, config=dpf.AvailableServerConfigs.GrpcServer)\nserver2 = dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer)\n\n# Check that the two servers are listening on different ports.\nprint(\n server1.port if hasattr(server1, \"port\") else \"\",\n server2.port if hasattr(server2, \"port\") else \"\",\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Send the result file\r\n\r\nThe result file is sent to the temporary directory of the first server.\r\nThis file upload is useless in this case because the two servers are\r\nlocal machines.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "file_path_in_tmp = examples.find_complex_rst(server=server1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a workflow on the first server\r\n\r\nCreate the model\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(file_path_in_tmp)\n\n# Read displacement\ndisp = model.results.displacement()\ndisp.inputs.time_scoping(len(model.metadata.time_freq_support.time_frequencies))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a workflow on the second server\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Change the Cartesian coordinates to cylindrical coordinates cs\ncoordinates = ops.geo.rotate_in_cylindrical_cs_fc(server=server2)\n\n# Create the Cartesian coordinate cs\ncs = dpf.fields_factory.create_scalar_field(12, server=server2)\ncs.data = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]\n\ncoordinates.inputs.coordinate_system(cs)\n\n# Choose the radial component to plot\ncomp = dpf.operators.logic.component_selector_fc(coordinates, 0, server=server2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pass data from one server to another\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "fc_disp = disp.outputs.fields_container()\nfc_copy = fc_disp.deep_copy(server=server2)\n\nmesh_copy = model.metadata.meshed_region.deep_copy(server=server2)\n# give a mesh to the field\nfc_copy[0].meshed_region = mesh_copy\nfc_copy[1].meshed_region = mesh_copy\n\ncoordinates.inputs.field(fc_copy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot the output\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "out = comp.outputs.fields_container()\n\n# real part\nmesh_copy.plot(out.get_field({\"complex\": 0}))\n\n# imaginary part\nmesh_copy.plot(out.get_field({\"complex\": 1}))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/03-exchange_data_between_servers.py b/doc/source/examples/04-advanced/03-exchange_data_between_servers.py new file mode 100644 index 0000000000..a9e65edb01 --- /dev/null +++ b/doc/source/examples/04-advanced/03-exchange_data_between_servers.py @@ -0,0 +1,95 @@ +# noqa: D400 +""" +.. _ref_exchange_data_between_servers.: + +Exchange data between servers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In this example, two DPF servers are started, and a workflow is created +with a part on both servers. This example shows how you can read data +from a given machine and transform this data on another machine +without any more difficulties than working on a local computer. + +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + + +############################################################################### +# Create two servers +# ~~~~~~~~~~~~~~~~~~ +# Use the :func:`start_local_server() ` +# method to start two servers on your local machine. If you have another server, +# you can use the :func:`connect_to_server() ` +# method to connect to any DPF server on your network. +# +# The ``as_global`` attributes allows you to choose whether a server is stored +# by the module and used by default. This example sets the first server as the default. +server1 = dpf.start_local_server(as_global=True, config=dpf.AvailableServerConfigs.GrpcServer) +server2 = dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer) + +# Check that the two servers are listening on different ports. +print( + server1.port if hasattr(server1, "port") else "", + server2.port if hasattr(server2, "port") else "", +) + +############################################################################### +# Send the result file +# ~~~~~~~~~~~~~~~~~~~~ +# The result file is sent to the temporary directory of the first server. +# This file upload is useless in this case because the two servers are local +# machines. +file_path_in_tmp = examples.find_complex_rst(server=server1) + +############################################################################### +# Create a workflow on the first server +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create the model +model = dpf.Model(file_path_in_tmp) + +# Read displacement +disp = model.results.displacement() +disp.inputs.time_scoping(len(model.metadata.time_freq_support.time_frequencies)) + +############################################################################### +# Create a workflow on the second server +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Change the Cartesian coordinates to cylindrical coordinates cs +coordinates = ops.geo.rotate_in_cylindrical_cs_fc(server=server2) + +# Create the Cartesian coordinate cs +cs = dpf.fields_factory.create_scalar_field(12, server=server2) +cs.data = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0] + +coordinates.inputs.coordinate_system(cs) + +# Choose the radial component to plot +comp = dpf.operators.logic.component_selector_fc(coordinates, 0, server=server2) + +############################################################################### +# Pass data from one server to another +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +fc_disp = disp.outputs.fields_container() +fc_copy = fc_disp.deep_copy(server=server2) + +mesh_copy = model.metadata.meshed_region.deep_copy(server=server2) +# give a mesh to the field +fc_copy[0].meshed_region = mesh_copy +fc_copy[1].meshed_region = mesh_copy + +coordinates.inputs.field(fc_copy) + +############################################################################### +# Plot the output +# ~~~~~~~~~~~~~~~ +out = comp.outputs.fields_container() + +# real part +mesh_copy.plot(out.get_field({"complex": 0})) + +# imaginary part +mesh_copy.plot(out.get_field({"complex": 1})) diff --git a/doc/source/examples/04-advanced/03-exchange_data_between_servers.py.md5 b/doc/source/examples/04-advanced/03-exchange_data_between_servers.py.md5 new file mode 100644 index 0000000000..7d2de30985 --- /dev/null +++ b/doc/source/examples/04-advanced/03-exchange_data_between_servers.py.md5 @@ -0,0 +1 @@ +914077021d710c1abe0ee4b5275c5e7e \ No newline at end of file diff --git a/doc/source/examples/04-advanced/03-exchange_data_between_servers.rst b/doc/source/examples/04-advanced/03-exchange_data_between_servers.rst new file mode 100644 index 0000000000..32ff530e75 --- /dev/null +++ b/doc/source/examples/04-advanced/03-exchange_data_between_servers.rst @@ -0,0 +1,251 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\03-exchange_data_between_servers.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_03-exchange_data_between_servers.py: + + +.. _ref_exchange_data_between_servers.: + +Exchange data between servers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In this example, two DPF servers are started, and a workflow is created +with a part on both servers. This example shows how you can read data +from a given machine and transform this data on another machine +without any more difficulties than working on a local computer. + +.. GENERATED FROM PYTHON SOURCE LINES 14-20 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 21-30 + +Create two servers +~~~~~~~~~~~~~~~~~~ +Use the :func:`start_local_server() ` +method to start two servers on your local machine. If you have another server, +you can use the :func:`connect_to_server() ` +method to connect to any DPF server on your network. + +The ``as_global`` attributes allows you to choose whether a server is stored +by the module and used by default. This example sets the first server as the default. + +.. GENERATED FROM PYTHON SOURCE LINES 30-39 + +.. code-block:: default + + server1 = dpf.start_local_server(as_global=True, config=dpf.AvailableServerConfigs.GrpcServer) + server2 = dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer) + + # Check that the two servers are listening on different ports. + print( + server1.port if hasattr(server1, "port") else "", + server2.port if hasattr(server2, "port") else "", + ) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + 50055 50056 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 40-45 + +Send the result file +~~~~~~~~~~~~~~~~~~~~ +The result file is sent to the temporary directory of the first server. +This file upload is useless in this case because the two servers are local +machines. + +.. GENERATED FROM PYTHON SOURCE LINES 45-47 + +.. code-block:: default + + file_path_in_tmp = examples.find_complex_rst(server=server1) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-51 + +Create a workflow on the first server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create the model + +.. GENERATED FROM PYTHON SOURCE LINES 51-57 + +.. code-block:: default + + model = dpf.Model(file_path_in_tmp) + + # Read displacement + disp = model.results.displacement() + disp.inputs.time_scoping(len(model.metadata.time_freq_support.time_frequencies)) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 58-60 + +Create a workflow on the second server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 60-73 + +.. code-block:: default + + + # Change the Cartesian coordinates to cylindrical coordinates cs + coordinates = ops.geo.rotate_in_cylindrical_cs_fc(server=server2) + + # Create the Cartesian coordinate cs + cs = dpf.fields_factory.create_scalar_field(12, server=server2) + cs.data = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0] + + coordinates.inputs.coordinate_system(cs) + + # Choose the radial component to plot + comp = dpf.operators.logic.component_selector_fc(coordinates, 0, server=server2) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 74-76 + +Pass data from one server to another +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 76-86 + +.. code-block:: default + + fc_disp = disp.outputs.fields_container() + fc_copy = fc_disp.deep_copy(server=server2) + + mesh_copy = model.metadata.meshed_region.deep_copy(server=server2) + # give a mesh to the field + fc_copy[0].meshed_region = mesh_copy + fc_copy[1].meshed_region = mesh_copy + + coordinates.inputs.field(fc_copy) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 87-89 + +Plot the output +~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 89-96 + +.. code-block:: default + + out = comp.outputs.fields_container() + + # real part + mesh_copy.plot(out.get_field({"complex": 0})) + + # imaginary part + mesh_copy.plot(out.get_field({"complex": 1})) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_001.png + :alt: 03 exchange data between servers + :srcset: /examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_002.png + :alt: 03 exchange data between servers + :srcset: /examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_002.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 4.434 seconds) + + +.. _sphx_glr_download_examples_04-advanced_03-exchange_data_between_servers.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 03-exchange_data_between_servers.py <03-exchange_data_between_servers.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 03-exchange_data_between_servers.ipynb <03-exchange_data_between_servers.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/03-exchange_data_between_servers_codeobj.pickle b/doc/source/examples/04-advanced/03-exchange_data_between_servers_codeobj.pickle new file mode 100644 index 0000000000..075df4c02c Binary files /dev/null and b/doc/source/examples/04-advanced/03-exchange_data_between_servers_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/04-extrapolation_stress_3d.ipynb b/doc/source/examples/04-advanced/04-extrapolation_stress_3d.ipynb new file mode 100644 index 0000000000..cc84229474 --- /dev/null +++ b/doc/source/examples/04-advanced/04-extrapolation_stress_3d.ipynb @@ -0,0 +1,216 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extrapolation method for stress result of a 3D element {#extrapolation_test_stress_3Delement}\r\n\r\nThis example shows how to compute the stress nodal components from\r\nGaussian points (integration points) for a 3D element using\r\nextrapolation.\r\n\r\nExtrapolate results available at Gaussian or quadrature points to nodal\r\npoints for a field or fields container. The available elements are:\r\n\r\n- Linear quadrangle\r\n- Parabolic quadrangle\r\n- Linear hexagonal\r\n- Quadratic hexagonal\r\n- Linear tetrahedral\r\n- Quadratic tetrahedral\r\n\r\nHere are the steps for extrapolation:\r\n\r\n1. Get the data source\\'s solution from the integration points. (This\r\n result file was generated with the Ansys Mechanical APDL (MAPDL)\r\n option `ERESX, NO`).\r\n2. Use the extrapolation operator to compute the nodal stress.\r\n3. Get the result for nodal stress from the data source. The analysis\r\n was computed by MAPDL.\r\n4. Compare the result for nodal stress from the data source and the\r\n nodal stress computed by the extrapolation method.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the data source\\'s analysis of integration points and analysis\r\nreference\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "datafile = examples.download_extrapolation_3d_result()\n\n# Get integration points (Gaussian points)\ndata_integration_points = datafile[\"file_integrated\"]\ndata_sources_integration_points = dpf.DataSources(data_integration_points)\n\n# Get the reference\ndataSourceref = datafile[\"file_ref\"]\ndata_sources_ref = dpf.DataSources(dataSourceref)\n\n# Get the mesh\nmodel = dpf.Model(data_integration_points)\nmesh = model.metadata.meshed_region\n\n# Operator instantiation scoping\nop_scoping = dpf.operators.scoping.split_on_property_type() # operator instantiation\nop_scoping.inputs.mesh.connect(mesh)\nop_scoping.inputs.requested_location.connect(\"Elemental\")\nmesh_scoping = op_scoping.outputs.mesh_scoping()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extrapolate from integration points for stress result\r\n\r\nThis example uses the `gauss_to_node_fc` operator to compute the nodal\r\ncomponent stress result from the stress result of integration points.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create stress operator to get stress result of integration points\nstressop = dpf.operators.result.stress()\nstressop.inputs.data_sources.connect(data_sources_integration_points)\nstress = stressop.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Nodal stress result of integration points\r\n\r\n> The MAPLD command `ERESX,NO` is used to copy directly the Gaussian\r\n> (integration) points results to the nodes, instead of the results at\r\n> nodes or elements (which are interpolation of results at a few gauss\r\n> points). The following plot shows the nodal values, which are the\r\n> averaged values of stresses at each node. The value shown at the node\r\n> is the average of the stresses from the Gaussian points of each\r\n> element that it belongs to.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Plot\nstress_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc()\nstress_nodal_op.inputs.fields_container.connect(stress)\nmesh.plot(stress_nodal_op.outputs.fields_container())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create operator `gauss_to_node_fc` and compute nodal component stress by\r\napplying the extrapolation method.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "ex_stress = dpf.operators.averaging.gauss_to_node_fc()\n# connect mesh\nex_stress.inputs.mesh.connect(mesh)\n# connect fields container stress\nex_stress.inputs.fields_container.connect(stress)\n# get output\nfex = ex_stress.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Stress result of reference Ansys Workbench\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Stress from file dataSourceref\nstressop_ref = dpf.operators.result.stress()\nstressop_ref.inputs.data_sources.connect(data_sources_ref)\nstressop_ref.inputs.mesh_scoping.connect(mesh_scoping)\nstress_ref = stressop_ref.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot\r\n\r\nShow plots of the extrapolation\\'s stress result and the reference\\'s\r\nstress result\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# extrapolation\nfex_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc()\nfex_nodal_op.inputs.fields_container.connect(fex)\nfex_nodal_fc = fex_nodal_op.eval()\nmesh.plot(fex_nodal_fc)\n\n# reference\nstress_ref_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc()\nstress_ref_nodal_op.inputs.fields_container.connect(stress_ref)\nstress_ref_nodal_fc = stress_ref_nodal_op.eval()\nmesh.plot(stress_ref_nodal_fc)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compare stress results\r\n\r\nCompare the stress result computed by extrapolation and the reference\\'s\r\nresult. Check if the two fields container are identical using the\r\n`identical_fc `{.interpreted-text\r\nrole=\"class\"} operator. The relative tolerance is set to 1.1e-6. The\r\nsmallest value that is considered during the comparison step: all the\r\n`abs(values)` in field less than 1e-2 is considered as null.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# operator AreFieldsIdentical_fc\nop = dpf.operators.logic.identical_fc()\nop.inputs.fields_containerA.connect(fex_nodal_op)\nop.inputs.fields_containerB.connect(stress_ref_nodal_op)\nop.inputs.tolerance.connect(1.1e-6)\nop.inputs.small_value.connect(0.01)\nop.outputs.boolean()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute absolute and relative errors\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "abs_error_sqr = dpf.operators.math.sqr_fc()\nabs_error = dpf.operators.math.sqrt_fc()\nerror = stress_ref_nodal_op - fex_nodal_op\nabs_error_sqr.inputs.fields_container.connect(error)\nabs_error.inputs.fields_container.connect(abs_error_sqr)\n\n\ndivide = dpf.operators.math.component_wise_divide()\ndivide.inputs.fieldA.connect(stress_ref_nodal_op - fex_nodal_op)\ndivide.inputs.fieldB.connect(stress_ref_nodal_op)\nrel_error = dpf.operators.math.scale()\nrel_error.inputs.field.connect(divide)\nrel_error.inputs.ponderation.connect(1.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot absolute and relative errors. The absolute value is the order of\r\n10, which is very small when compared to the magnitude of 1e8 of the\r\ndisplacements. This is reflected in the relative error plot, where the\r\nerrors are found to be below 1.02e-6%. The result of these plots can be\r\nused to set the tolerances for the\r\n`identical_fc `{.interpreted-text\r\nrole=\"class\"} operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh.plot(abs_error.eval(), scalar_bar_args={\"title\": \"Absolute error [mm]\"})\nmesh.plot(rel_error.eval(), scalar_bar_args={\"title\": \"Relative error [%]\"})" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/04-extrapolation_stress_3d.py b/doc/source/examples/04-advanced/04-extrapolation_stress_3d.py new file mode 100644 index 0000000000..5483b1c9fd --- /dev/null +++ b/doc/source/examples/04-advanced/04-extrapolation_stress_3d.py @@ -0,0 +1,169 @@ +# noqa: D400 +""" +.. _extrapolation_test_stress_3Delement: + +Extrapolation method for stress result of a 3D element +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to compute the stress nodal components from +Gaussian points (integration points) for a 3D element using +extrapolation. + +Extrapolate results available at Gaussian or quadrature points to nodal +points for a field or fields container. The available elements are: + +* Linear quadrangle +* Parabolic quadrangle +* Linear hexagonal +* Quadratic hexagonal +* Linear tetrahedral +* Quadratic tetrahedral + +Here are the steps for extrapolation: + +#. Get the data source's solution from the integration points. (This + result file was generated with the Ansys Mechanical APDL (MAPDL) + option ``ERESX, NO``). +#. Use the extrapolation operator to compute the nodal stress. +#. Get the result for nodal stress from the data source. + The analysis was computed by MAPDL. +#. Compare the result for nodal stress from the data source + and the nodal stress computed by the extrapolation method. + +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + + +############################################################################### +# Get the data source's analysis of integration points and analysis reference +datafile = examples.download_extrapolation_3d_result() + +# Get integration points (Gaussian points) +data_integration_points = datafile["file_integrated"] +data_sources_integration_points = dpf.DataSources(data_integration_points) + +# Get the reference +dataSourceref = datafile["file_ref"] +data_sources_ref = dpf.DataSources(dataSourceref) + +# Get the mesh +model = dpf.Model(data_integration_points) +mesh = model.metadata.meshed_region + +# Operator instantiation scoping +op_scoping = dpf.operators.scoping.split_on_property_type() # operator instantiation +op_scoping.inputs.mesh.connect(mesh) +op_scoping.inputs.requested_location.connect("Elemental") +mesh_scoping = op_scoping.outputs.mesh_scoping() + +############################################################################### +# Extrapolate from integration points for stress result +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This example uses the ``gauss_to_node_fc`` operator to compute the nodal +# component stress result from the stress result of integration points. + +# Create stress operator to get stress result of integration points +stressop = dpf.operators.result.stress() +stressop.inputs.data_sources.connect(data_sources_integration_points) +stress = stressop.outputs.fields_container() + +############################################################################### +# Nodal stress result of integration points +############################################################################### +# The MAPLD command ``ERESX,NO`` is used to copy directly the +# Gaussian (integration) points results to the nodes, instead of the +# results at nodes or elements (which are interpolation of results at a +# few gauss points). +# The following plot shows the nodal values, which are the averaged values +# of stresses at each node. The value shown at the node is the average of +# the stresses from the Gaussian points of each element that it belongs to. + +# Plot +stress_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() +stress_nodal_op.inputs.fields_container.connect(stress) +mesh.plot(stress_nodal_op.outputs.fields_container()) + +############################################################################### +# Create operator ``gauss_to_node_fc`` and compute nodal component stress +# by applying the extrapolation method. + +ex_stress = dpf.operators.averaging.gauss_to_node_fc() +# connect mesh +ex_stress.inputs.mesh.connect(mesh) +# connect fields container stress +ex_stress.inputs.fields_container.connect(stress) +# get output +fex = ex_stress.outputs.fields_container() + +############################################################################### +# Stress result of reference Ansys Workbench +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Stress from file dataSourceref +stressop_ref = dpf.operators.result.stress() +stressop_ref.inputs.data_sources.connect(data_sources_ref) +stressop_ref.inputs.mesh_scoping.connect(mesh_scoping) +stress_ref = stressop_ref.outputs.fields_container() + +############################################################################### +# Plot +# ~~~~~~~~~~ +# Show plots of the extrapolation's stress result and the reference's stress result + +# extrapolation +fex_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() +fex_nodal_op.inputs.fields_container.connect(fex) +fex_nodal_fc = fex_nodal_op.eval() +mesh.plot(fex_nodal_fc) + +# reference +stress_ref_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() +stress_ref_nodal_op.inputs.fields_container.connect(stress_ref) +stress_ref_nodal_fc = stress_ref_nodal_op.eval() +mesh.plot(stress_ref_nodal_fc) + +############################################################################### +# Compare stress results +# ~~~~~~~~~~~~~~~~~~~~~~ +# Compare the stress result computed by extrapolation and the reference's result. +# Check if the two fields container are identical using the +# :class:`identical_fc ` operator. +# The relative tolerance is set to 1.1e-6. +# The smallest value that is considered during the comparison step: all the +# ``abs(values)`` in field less than 1e-2 is considered as null. + +# operator AreFieldsIdentical_fc +op = dpf.operators.logic.identical_fc() +op.inputs.fields_containerA.connect(fex_nodal_op) +op.inputs.fields_containerB.connect(stress_ref_nodal_op) +op.inputs.tolerance.connect(1.1e-6) +op.inputs.small_value.connect(0.01) +op.outputs.boolean() + +############################################################################### +# Compute absolute and relative errors +abs_error_sqr = dpf.operators.math.sqr_fc() +abs_error = dpf.operators.math.sqrt_fc() +error = stress_ref_nodal_op - fex_nodal_op +abs_error_sqr.inputs.fields_container.connect(error) +abs_error.inputs.fields_container.connect(abs_error_sqr) + + +divide = dpf.operators.math.component_wise_divide() +divide.inputs.fieldA.connect(stress_ref_nodal_op - fex_nodal_op) +divide.inputs.fieldB.connect(stress_ref_nodal_op) +rel_error = dpf.operators.math.scale() +rel_error.inputs.field.connect(divide) +rel_error.inputs.ponderation.connect(1.0) + +############################################################################### +# Plot absolute and relative errors. +# The absolute value is the order of 10, which is very small when compared to the +# magnitude of 1e8 of the displacements. This is reflected in the relative error +# plot, where the errors are found to be below 1.02e-6%. The result of these plots +# can be used to set the tolerances for the +# :class:`identical_fc ` operator. +mesh.plot(abs_error.eval(), scalar_bar_args={"title": "Absolute error [mm]"}) +mesh.plot(rel_error.eval(), scalar_bar_args={"title": "Relative error [%]"}) diff --git a/doc/source/examples/04-advanced/04-extrapolation_stress_3d.py.md5 b/doc/source/examples/04-advanced/04-extrapolation_stress_3d.py.md5 new file mode 100644 index 0000000000..c910bf6112 --- /dev/null +++ b/doc/source/examples/04-advanced/04-extrapolation_stress_3d.py.md5 @@ -0,0 +1 @@ +31596d90adfedac48136dc444a5c8d72 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/04-extrapolation_stress_3d.rst b/doc/source/examples/04-advanced/04-extrapolation_stress_3d.rst new file mode 100644 index 0000000000..9b1529aefc --- /dev/null +++ b/doc/source/examples/04-advanced/04-extrapolation_stress_3d.rst @@ -0,0 +1,386 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\04-extrapolation_stress_3d.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_04-extrapolation_stress_3d.py: + + +.. _extrapolation_test_stress_3Delement: + +Extrapolation method for stress result of a 3D element +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to compute the stress nodal components from +Gaussian points (integration points) for a 3D element using +extrapolation. + +Extrapolate results available at Gaussian or quadrature points to nodal +points for a field or fields container. The available elements are: + +* Linear quadrangle +* Parabolic quadrangle +* Linear hexagonal +* Quadratic hexagonal +* Linear tetrahedral +* Quadratic tetrahedral + +Here are the steps for extrapolation: + +#. Get the data source's solution from the integration points. (This + result file was generated with the Ansys Mechanical APDL (MAPDL) + option ``ERESX, NO``). +#. Use the extrapolation operator to compute the nodal stress. +#. Get the result for nodal stress from the data source. + The analysis was computed by MAPDL. +#. Compare the result for nodal stress from the data source + and the nodal stress computed by the extrapolation method. + +.. GENERATED FROM PYTHON SOURCE LINES 34-39 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 40-41 + +Get the data source's analysis of integration points and analysis reference + +.. GENERATED FROM PYTHON SOURCE LINES 41-61 + +.. code-block:: default + + datafile = examples.download_extrapolation_3d_result() + + # Get integration points (Gaussian points) + data_integration_points = datafile["file_integrated"] + data_sources_integration_points = dpf.DataSources(data_integration_points) + + # Get the reference + dataSourceref = datafile["file_ref"] + data_sources_ref = dpf.DataSources(dataSourceref) + + # Get the mesh + model = dpf.Model(data_integration_points) + mesh = model.metadata.meshed_region + + # Operator instantiation scoping + op_scoping = dpf.operators.scoping.split_on_property_type() # operator instantiation + op_scoping.inputs.mesh.connect(mesh) + op_scoping.inputs.requested_location.connect("Elemental") + mesh_scoping = op_scoping.outputs.mesh_scoping() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 62-66 + +Extrapolate from integration points for stress result +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example uses the ``gauss_to_node_fc`` operator to compute the nodal +component stress result from the stress result of integration points. + +.. GENERATED FROM PYTHON SOURCE LINES 66-72 + +.. code-block:: default + + + # Create stress operator to get stress result of integration points + stressop = dpf.operators.result.stress() + stressop.inputs.data_sources.connect(data_sources_integration_points) + stress = stressop.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 73-82 + +Nodal stress result of integration points +############################################################################## + The MAPLD command ``ERESX,NO`` is used to copy directly the + Gaussian (integration) points results to the nodes, instead of the + results at nodes or elements (which are interpolation of results at a + few gauss points). + The following plot shows the nodal values, which are the averaged values + of stresses at each node. The value shown at the node is the average of + the stresses from the Gaussian points of each element that it belongs to. + +.. GENERATED FROM PYTHON SOURCE LINES 82-88 + +.. code-block:: default + + + # Plot + stress_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() + stress_nodal_op.inputs.fields_container.connect(stress) + mesh.plot(stress_nodal_op.outputs.fields_container()) + + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_001.png + :alt: 04 extrapolation stress 3d + :srcset: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 89-91 + +Create operator ``gauss_to_node_fc`` and compute nodal component stress +by applying the extrapolation method. + +.. GENERATED FROM PYTHON SOURCE LINES 91-100 + +.. code-block:: default + + + ex_stress = dpf.operators.averaging.gauss_to_node_fc() + # connect mesh + ex_stress.inputs.mesh.connect(mesh) + # connect fields container stress + ex_stress.inputs.fields_container.connect(stress) + # get output + fex = ex_stress.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 101-103 + +Stress result of reference Ansys Workbench +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 103-110 + +.. code-block:: default + + + # Stress from file dataSourceref + stressop_ref = dpf.operators.result.stress() + stressop_ref.inputs.data_sources.connect(data_sources_ref) + stressop_ref.inputs.mesh_scoping.connect(mesh_scoping) + stress_ref = stressop_ref.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 111-114 + +Plot +~~~~~~~~~~ +Show plots of the extrapolation's stress result and the reference's stress result + +.. GENERATED FROM PYTHON SOURCE LINES 114-127 + +.. code-block:: default + + + # extrapolation + fex_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() + fex_nodal_op.inputs.fields_container.connect(fex) + fex_nodal_fc = fex_nodal_op.eval() + mesh.plot(fex_nodal_fc) + + # reference + stress_ref_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() + stress_ref_nodal_op.inputs.fields_container.connect(stress_ref) + stress_ref_nodal_fc = stress_ref_nodal_op.eval() + mesh.plot(stress_ref_nodal_fc) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_002.png + :alt: 04 extrapolation stress 3d + :srcset: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_003.png + :alt: 04 extrapolation stress 3d + :srcset: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_003.png + :class: sphx-glr-multi-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 128-136 + +Compare stress results +~~~~~~~~~~~~~~~~~~~~~~ +Compare the stress result computed by extrapolation and the reference's result. +Check if the two fields container are identical using the +:class:`identical_fc ` operator. +The relative tolerance is set to 1.1e-6. +The smallest value that is considered during the comparison step: all the +``abs(values)`` in field less than 1e-2 is considered as null. + +.. GENERATED FROM PYTHON SOURCE LINES 136-145 + +.. code-block:: default + + + # operator AreFieldsIdentical_fc + op = dpf.operators.logic.identical_fc() + op.inputs.fields_containerA.connect(fex_nodal_op) + op.inputs.fields_containerB.connect(stress_ref_nodal_op) + op.inputs.tolerance.connect(1.1e-6) + op.inputs.small_value.connect(0.01) + op.outputs.boolean() + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + True + + + +.. GENERATED FROM PYTHON SOURCE LINES 146-147 + +Compute absolute and relative errors + +.. GENERATED FROM PYTHON SOURCE LINES 147-161 + +.. code-block:: default + + abs_error_sqr = dpf.operators.math.sqr_fc() + abs_error = dpf.operators.math.sqrt_fc() + error = stress_ref_nodal_op - fex_nodal_op + abs_error_sqr.inputs.fields_container.connect(error) + abs_error.inputs.fields_container.connect(abs_error_sqr) + + + divide = dpf.operators.math.component_wise_divide() + divide.inputs.fieldA.connect(stress_ref_nodal_op - fex_nodal_op) + divide.inputs.fieldB.connect(stress_ref_nodal_op) + rel_error = dpf.operators.math.scale() + rel_error.inputs.field.connect(divide) + rel_error.inputs.ponderation.connect(1.0) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 162-168 + +Plot absolute and relative errors. +The absolute value is the order of 10, which is very small when compared to the +magnitude of 1e8 of the displacements. This is reflected in the relative error +plot, where the errors are found to be below 1.02e-6%. The result of these plots +can be used to set the tolerances for the +:class:`identical_fc ` operator. + +.. GENERATED FROM PYTHON SOURCE LINES 168-170 + +.. code-block:: default + + mesh.plot(abs_error.eval(), scalar_bar_args={"title": "Absolute error [mm]"}) + mesh.plot(rel_error.eval(), scalar_bar_args={"title": "Relative error [%]"}) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_004.png + :alt: 04 extrapolation stress 3d + :srcset: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_005.png + :alt: 04 extrapolation stress 3d + :srcset: /examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_005.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 4.446 seconds) + + +.. _sphx_glr_download_examples_04-advanced_04-extrapolation_stress_3d.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 04-extrapolation_stress_3d.py <04-extrapolation_stress_3d.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 04-extrapolation_stress_3d.ipynb <04-extrapolation_stress_3d.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/04-extrapolation_stress_3d_codeobj.pickle b/doc/source/examples/04-advanced/04-extrapolation_stress_3d_codeobj.pickle new file mode 100644 index 0000000000..16eb713d44 Binary files /dev/null and b/doc/source/examples/04-advanced/04-extrapolation_stress_3d_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/05-extrapolation_strain_2d.ipynb b/doc/source/examples/04-advanced/05-extrapolation_strain_2d.ipynb new file mode 100644 index 0000000000..b5aaea864e --- /dev/null +++ b/doc/source/examples/04-advanced/05-extrapolation_strain_2d.ipynb @@ -0,0 +1,216 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extrapolation method for strain result of a 2D element {#extrapolation_test_strain_2Delement}\r\n\r\nThis example shows how to compute the stress nodal components from\r\nGaussian points (integration points) for a 2D element using\r\nextrapolation.\r\n\r\nExtrapolate results available at Gaussian or quadrature points to nodal\r\npoints for a field or fields container. The available elements are:\r\n\r\n- Linear quadrangle\r\n- Parabolic quadrangle\r\n- Linear hexagonal\r\n- Quadratic hexagonal\r\n- Linear tetrahedral\r\n- Quadratic tetrahedral\r\n\r\nHere are the steps for extrapolation:\r\n\r\n1. Get the data source\\'s solution from the integration points. (This\r\n result file was generated with the Ansys Mechanical APDL (MAPDL)\r\n option `ERESX, NO`).\r\n2. Use the extrapolation operator to compute the nodal elastic strain.\r\n3. Get the result for nodal elastic strain from the data source. The\r\n analysis was computed by MAPDL.\r\n4. Compare the result for nodal elastic strain from the data source and\r\n the nodal elastic strain computed by the extrapolation method.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the data source\\'s analyse of integration points and data source\\'s\r\nanalyse reference\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "datafile = examples.download_extrapolation_2d_result()\n\n# integration points (Gaussian points)\ndata_integration_points = datafile[\"file_integrated\"]\ndata_sources_integration_points = dpf.DataSources(data_integration_points)\n\n# reference\ndataSourceref = datafile[\"file_ref\"]\ndata_sources_ref = dpf.DataSources(dataSourceref)\n\n# get the mesh\nmodel = dpf.Model(data_integration_points)\nmesh = model.metadata.meshed_region" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extrapolate from integration points for elastic strain result\r\n\r\nThis example uses the `gauss_to_node_fc` operator to compute nodal\r\ncomponent elastic strain results from the elastic strain at the\r\nintegration points.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create elastic strain operator to get strain result of integration points\nstrainop = dpf.operators.result.elastic_strain()\nstrainop.inputs.data_sources.connect(data_sources_integration_points)\nstrain = strainop.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Nodal elastic strain result of integration points:\r\n\r\n> The command `ERESX,NO` in MAPDL is used to copy directly the Gaussian\r\n> (integration) points results to the nodes, instead of the results at\r\n> nodes or elements (which are an interpolation of results at a few\r\n> Gaussian points).\r\n>\r\n> The following plot shows the nodal values that are the averaged values\r\n> of elastic strain at each node. The value shown at the node is the\r\n> average of the elastic strains from the Gaussian points of each\r\n> element that it belongs to.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# plot\nstrain_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc()\nstrain_nodal_op.inputs.fields_container.connect(strain)\nmesh.plot(strain_nodal_op.outputs.fields_container())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the `gauss_to_node_fc` operator and compute nodal component\r\nelastic strain by applying the extrapolation method.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "ex_strain = dpf.operators.averaging.gauss_to_node_fc()\n# connect mesh\nex_strain.inputs.mesh.connect(mesh)\n# connect fields container elastic strain\nex_strain.inputs.fields_container.connect(strain)\n# get output\nfex = ex_strain.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Elastic strain result of reference Ansys Workbench\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Strain from file dataSourceref\nstrainop_ref = dpf.operators.result.elastic_strain()\nstrainop_ref.inputs.data_sources.connect(data_sources_ref)\nstrain_ref = strainop_ref.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot\r\n\r\nShow plots of extrapolation\\'s elastic strain result and reference\\'s\r\nelastic strain result\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# extrapolation\nfex_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc()\nfex_nodal_op.inputs.fields_container.connect(fex)\nmesh.plot(fex_nodal_op.outputs.fields_container())\n# reference\nstrain_ref_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc()\nstrain_ref_nodal_op.inputs.fields_container.connect(strain_ref)\nmesh.plot(strain_ref_nodal_op.outputs.fields_container())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Comparison\r\n\r\nCompare the elastic strain result computed by extrapolation and\r\nreference\\'s result. Check if the two fields containers are identical.\r\nThe relative tolerance is set to 1e-14. The smallest value that is to be\r\nconsidered during the comparison step : all the `abs(values)` in the\r\nfield less than 1e-2 are considered null.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# operator AreFieldsIdentical_fc\nop = dpf.operators.logic.identical_fc()\nop.inputs.fields_containerA.connect(fex_nodal_op)\nop.inputs.fields_containerB.connect(strain_ref_nodal_op)\nop.inputs.tolerance.connect(1.0e-14)\nop.inputs.small_value.connect(0.01)\nprint(op.outputs.boolean())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute absolute and relative errors\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "abs_error_sqr = dpf.operators.math.sqr_fc()\nabs_error = dpf.operators.math.sqrt_fc()\nerror = strain_ref_nodal_op - fex_nodal_op\nabs_error_sqr.inputs.fields_container.connect(error)\nabs_error.inputs.fields_container.connect(abs_error_sqr)\n\ndivide = dpf.operators.math.component_wise_divide()\ndivide.inputs.fieldA.connect(strain_ref_nodal_op - fex_nodal_op)\ndivide.inputs.fieldB.connect(strain_ref_nodal_op)\nrel_error = dpf.operators.math.scale()\nrel_error.inputs.field.connect(divide)\nrel_error.inputs.ponderation.connect(1.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot absolute and relative errors. The absolute value is the order of\r\n1e-13, which is very small when compared to the magnitude of 1e-5 of the\r\ndisplacements. This is reflected in the relative error plot, where the\r\nerrors are found to be below 1.1e-5%. The result of these plots can be\r\nused to set the tolerances for the\r\n`identical_fc `{.interpreted-text\r\nrole=\"class\"} operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh.plot(abs_error.eval(), scalar_bar_args={\"title\": \"Absolute error [mm]\"})\nmesh.plot(rel_error.eval(), scalar_bar_args={\"title\": \"Relative error [%]\"})" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/05-extrapolation_strain_2d.py b/doc/source/examples/04-advanced/05-extrapolation_strain_2d.py new file mode 100644 index 0000000000..a177393a3f --- /dev/null +++ b/doc/source/examples/04-advanced/05-extrapolation_strain_2d.py @@ -0,0 +1,159 @@ +# noqa: D400 +""" +.. _extrapolation_test_strain_2Delement: + +Extrapolation method for strain result of a 2D element +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to compute the stress nodal components from +Gaussian points (integration points) for a 2D element using +extrapolation. + +Extrapolate results available at Gaussian or quadrature points to nodal +points for a field or fields container. The available elements are: + +* Linear quadrangle +* Parabolic quadrangle +* Linear hexagonal +* Quadratic hexagonal +* Linear tetrahedral +* Quadratic tetrahedral + +Here are the steps for extrapolation: + +#. Get the data source's solution from the integration points. (This + result file was generated with the Ansys Mechanical APDL (MAPDL) + option ``ERESX, NO``). +#. Use the extrapolation operator to compute the nodal elastic strain. +#. Get the result for nodal elastic strain from the data source. + The analysis was computed by MAPDL. +#. Compare the result for nodal elastic strain from the data source + and the nodal elastic strain computed by the extrapolation method. + +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + + +############################################################################### +# Get the data source's analyse of integration points and data source's analyse reference +datafile = examples.download_extrapolation_2d_result() + +# integration points (Gaussian points) +data_integration_points = datafile["file_integrated"] +data_sources_integration_points = dpf.DataSources(data_integration_points) + +# reference +dataSourceref = datafile["file_ref"] +data_sources_ref = dpf.DataSources(dataSourceref) + +# get the mesh +model = dpf.Model(data_integration_points) +mesh = model.metadata.meshed_region + +############################################################################### +# Extrapolate from integration points for elastic strain result +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This example uses the ``gauss_to_node_fc`` operator to compute nodal component +# elastic strain results from the elastic strain at the integration points. + +# Create elastic strain operator to get strain result of integration points +strainop = dpf.operators.result.elastic_strain() +strainop.inputs.data_sources.connect(data_sources_integration_points) +strain = strainop.outputs.fields_container() + +############################################################################### +# Nodal elastic strain result of integration points: +############################################################################### +# The command ``ERESX,NO`` in MAPDL is used to copy directly the +# Gaussian (integration) points results to the nodes, instead of the results +# at nodes or elements (which are an interpolation of results at a few +# Gaussian points). +# +# The following plot shows the nodal values that are the averaged values +# of elastic strain at each node. The value shown at the node is the +# average of the elastic strains from the Gaussian points of each element +# that it belongs to. + +# plot +strain_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() +strain_nodal_op.inputs.fields_container.connect(strain) +mesh.plot(strain_nodal_op.outputs.fields_container()) + +############################################################################### +# Create the ``gauss_to_node_fc`` operator and compute nodal component +# elastic strain by applying the extrapolation method. + +ex_strain = dpf.operators.averaging.gauss_to_node_fc() +# connect mesh +ex_strain.inputs.mesh.connect(mesh) +# connect fields container elastic strain +ex_strain.inputs.fields_container.connect(strain) +# get output +fex = ex_strain.outputs.fields_container() + +############################################################################### +# Elastic strain result of reference Ansys Workbench +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Strain from file dataSourceref +strainop_ref = dpf.operators.result.elastic_strain() +strainop_ref.inputs.data_sources.connect(data_sources_ref) +strain_ref = strainop_ref.outputs.fields_container() + +############################################################################### +# Plot +# ~~~~ +# Show plots of extrapolation's elastic strain result and reference's elastic strain result + +# extrapolation +fex_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() +fex_nodal_op.inputs.fields_container.connect(fex) +mesh.plot(fex_nodal_op.outputs.fields_container()) +# reference +strain_ref_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() +strain_ref_nodal_op.inputs.fields_container.connect(strain_ref) +mesh.plot(strain_ref_nodal_op.outputs.fields_container()) + +############################################################################### +# Comparison +# ~~~~~~~~~~~~ +# Compare the elastic strain result computed by extrapolation and reference's result. +# Check if the two fields containers are identical. +# The relative tolerance is set to 1e-14. +# The smallest value that is to be considered during the comparison +# step : all the ``abs(values)`` in the field less than 1e-2 are considered null. + +# operator AreFieldsIdentical_fc +op = dpf.operators.logic.identical_fc() +op.inputs.fields_containerA.connect(fex_nodal_op) +op.inputs.fields_containerB.connect(strain_ref_nodal_op) +op.inputs.tolerance.connect(1.0e-14) +op.inputs.small_value.connect(0.01) +print(op.outputs.boolean()) + +############################################################################### +# Compute absolute and relative errors +abs_error_sqr = dpf.operators.math.sqr_fc() +abs_error = dpf.operators.math.sqrt_fc() +error = strain_ref_nodal_op - fex_nodal_op +abs_error_sqr.inputs.fields_container.connect(error) +abs_error.inputs.fields_container.connect(abs_error_sqr) + +divide = dpf.operators.math.component_wise_divide() +divide.inputs.fieldA.connect(strain_ref_nodal_op - fex_nodal_op) +divide.inputs.fieldB.connect(strain_ref_nodal_op) +rel_error = dpf.operators.math.scale() +rel_error.inputs.field.connect(divide) +rel_error.inputs.ponderation.connect(1.0) + +############################################################################### +# Plot absolute and relative errors. +# The absolute value is the order of 1e-13, which is very small when compared to the +# magnitude of 1e-5 of the displacements. This is reflected in the relative error +# plot, where the errors are found to be below 1.1e-5%. The result of these plots +# can be used to set the tolerances for the +# :class:`identical_fc ` operator. +mesh.plot(abs_error.eval(), scalar_bar_args={"title": "Absolute error [mm]"}) +mesh.plot(rel_error.eval(), scalar_bar_args={"title": "Relative error [%]"}) diff --git a/doc/source/examples/04-advanced/05-extrapolation_strain_2d.py.md5 b/doc/source/examples/04-advanced/05-extrapolation_strain_2d.py.md5 new file mode 100644 index 0000000000..b0f642e862 --- /dev/null +++ b/doc/source/examples/04-advanced/05-extrapolation_strain_2d.py.md5 @@ -0,0 +1 @@ +e8897cbdf77f2af47bb66423d05e14e3 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/05-extrapolation_strain_2d.rst b/doc/source/examples/04-advanced/05-extrapolation_strain_2d.rst new file mode 100644 index 0000000000..e4b7ccd975 --- /dev/null +++ b/doc/source/examples/04-advanced/05-extrapolation_strain_2d.rst @@ -0,0 +1,376 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\05-extrapolation_strain_2d.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_05-extrapolation_strain_2d.py: + + +.. _extrapolation_test_strain_2Delement: + +Extrapolation method for strain result of a 2D element +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to compute the stress nodal components from +Gaussian points (integration points) for a 2D element using +extrapolation. + +Extrapolate results available at Gaussian or quadrature points to nodal +points for a field or fields container. The available elements are: + +* Linear quadrangle +* Parabolic quadrangle +* Linear hexagonal +* Quadratic hexagonal +* Linear tetrahedral +* Quadratic tetrahedral + +Here are the steps for extrapolation: + +#. Get the data source's solution from the integration points. (This + result file was generated with the Ansys Mechanical APDL (MAPDL) + option ``ERESX, NO``). +#. Use the extrapolation operator to compute the nodal elastic strain. +#. Get the result for nodal elastic strain from the data source. + The analysis was computed by MAPDL. +#. Compare the result for nodal elastic strain from the data source + and the nodal elastic strain computed by the extrapolation method. + +.. GENERATED FROM PYTHON SOURCE LINES 34-39 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 40-41 + +Get the data source's analyse of integration points and data source's analyse reference + +.. GENERATED FROM PYTHON SOURCE LINES 41-55 + +.. code-block:: default + + datafile = examples.download_extrapolation_2d_result() + + # integration points (Gaussian points) + data_integration_points = datafile["file_integrated"] + data_sources_integration_points = dpf.DataSources(data_integration_points) + + # reference + dataSourceref = datafile["file_ref"] + data_sources_ref = dpf.DataSources(dataSourceref) + + # get the mesh + model = dpf.Model(data_integration_points) + mesh = model.metadata.meshed_region + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 56-60 + +Extrapolate from integration points for elastic strain result +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example uses the ``gauss_to_node_fc`` operator to compute nodal component +elastic strain results from the elastic strain at the integration points. + +.. GENERATED FROM PYTHON SOURCE LINES 60-66 + +.. code-block:: default + + + # Create elastic strain operator to get strain result of integration points + strainop = dpf.operators.result.elastic_strain() + strainop.inputs.data_sources.connect(data_sources_integration_points) + strain = strainop.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 67-78 + +Nodal elastic strain result of integration points: +############################################################################## + The command ``ERESX,NO`` in MAPDL is used to copy directly the + Gaussian (integration) points results to the nodes, instead of the results + at nodes or elements (which are an interpolation of results at a few + Gaussian points). + + The following plot shows the nodal values that are the averaged values + of elastic strain at each node. The value shown at the node is the + average of the elastic strains from the Gaussian points of each element + that it belongs to. + +.. GENERATED FROM PYTHON SOURCE LINES 78-84 + +.. code-block:: default + + + # plot + strain_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() + strain_nodal_op.inputs.fields_container.connect(strain) + mesh.plot(strain_nodal_op.outputs.fields_container()) + + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_001.png + :alt: 05 extrapolation strain 2d + :srcset: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-87 + +Create the ``gauss_to_node_fc`` operator and compute nodal component +elastic strain by applying the extrapolation method. + +.. GENERATED FROM PYTHON SOURCE LINES 87-96 + +.. code-block:: default + + + ex_strain = dpf.operators.averaging.gauss_to_node_fc() + # connect mesh + ex_strain.inputs.mesh.connect(mesh) + # connect fields container elastic strain + ex_strain.inputs.fields_container.connect(strain) + # get output + fex = ex_strain.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 97-99 + +Elastic strain result of reference Ansys Workbench +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 99-105 + +.. code-block:: default + + + # Strain from file dataSourceref + strainop_ref = dpf.operators.result.elastic_strain() + strainop_ref.inputs.data_sources.connect(data_sources_ref) + strain_ref = strainop_ref.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 106-109 + +Plot +~~~~ +Show plots of extrapolation's elastic strain result and reference's elastic strain result + +.. GENERATED FROM PYTHON SOURCE LINES 109-119 + +.. code-block:: default + + + # extrapolation + fex_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() + fex_nodal_op.inputs.fields_container.connect(fex) + mesh.plot(fex_nodal_op.outputs.fields_container()) + # reference + strain_ref_nodal_op = dpf.operators.averaging.elemental_nodal_to_nodal_fc() + strain_ref_nodal_op.inputs.fields_container.connect(strain_ref) + mesh.plot(strain_ref_nodal_op.outputs.fields_container()) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_002.png + :alt: 05 extrapolation strain 2d + :srcset: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_003.png + :alt: 05 extrapolation strain 2d + :srcset: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_003.png + :class: sphx-glr-multi-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 120-127 + +Comparison +~~~~~~~~~~~~ +Compare the elastic strain result computed by extrapolation and reference's result. +Check if the two fields containers are identical. +The relative tolerance is set to 1e-14. +The smallest value that is to be considered during the comparison +step : all the ``abs(values)`` in the field less than 1e-2 are considered null. + +.. GENERATED FROM PYTHON SOURCE LINES 127-136 + +.. code-block:: default + + + # operator AreFieldsIdentical_fc + op = dpf.operators.logic.identical_fc() + op.inputs.fields_containerA.connect(fex_nodal_op) + op.inputs.fields_containerB.connect(strain_ref_nodal_op) + op.inputs.tolerance.connect(1.0e-14) + op.inputs.small_value.connect(0.01) + print(op.outputs.boolean()) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + True + + + + +.. GENERATED FROM PYTHON SOURCE LINES 137-138 + +Compute absolute and relative errors + +.. GENERATED FROM PYTHON SOURCE LINES 138-151 + +.. code-block:: default + + abs_error_sqr = dpf.operators.math.sqr_fc() + abs_error = dpf.operators.math.sqrt_fc() + error = strain_ref_nodal_op - fex_nodal_op + abs_error_sqr.inputs.fields_container.connect(error) + abs_error.inputs.fields_container.connect(abs_error_sqr) + + divide = dpf.operators.math.component_wise_divide() + divide.inputs.fieldA.connect(strain_ref_nodal_op - fex_nodal_op) + divide.inputs.fieldB.connect(strain_ref_nodal_op) + rel_error = dpf.operators.math.scale() + rel_error.inputs.field.connect(divide) + rel_error.inputs.ponderation.connect(1.0) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 152-158 + +Plot absolute and relative errors. +The absolute value is the order of 1e-13, which is very small when compared to the +magnitude of 1e-5 of the displacements. This is reflected in the relative error +plot, where the errors are found to be below 1.1e-5%. The result of these plots +can be used to set the tolerances for the +:class:`identical_fc ` operator. + +.. GENERATED FROM PYTHON SOURCE LINES 158-160 + +.. code-block:: default + + mesh.plot(abs_error.eval(), scalar_bar_args={"title": "Absolute error [mm]"}) + mesh.plot(rel_error.eval(), scalar_bar_args={"title": "Relative error [%]"}) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_004.png + :alt: 05 extrapolation strain 2d + :srcset: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_005.png + :alt: 05 extrapolation strain 2d + :srcset: /examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_005.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 4.634 seconds) + + +.. _sphx_glr_download_examples_04-advanced_05-extrapolation_strain_2d.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 05-extrapolation_strain_2d.py <05-extrapolation_strain_2d.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 05-extrapolation_strain_2d.ipynb <05-extrapolation_strain_2d.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/05-extrapolation_strain_2d_codeobj.pickle b/doc/source/examples/04-advanced/05-extrapolation_strain_2d_codeobj.pickle new file mode 100644 index 0000000000..88907638c1 Binary files /dev/null and b/doc/source/examples/04-advanced/05-extrapolation_strain_2d_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/06-stress_gradient_path.ipynb b/doc/source/examples/04-advanced/06-stress_gradient_path.ipynb new file mode 100644 index 0000000000..e5ccc24921 --- /dev/null +++ b/doc/source/examples/04-advanced/06-stress_gradient_path.ipynb @@ -0,0 +1,385 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Stress gradient normal to a defined node {#stress_gradient_path}\r\n\r\nThis example shows how to plot a stress gradient normal to a selected\r\nnode. Because the example is based on creating a path along the normal,\r\nthe selected node must be on the surface of the geometry. A path is\r\ncreated of a defined length.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import the DPF-Core module as `dpf` and import the included examples\r\nfile and `DpfPlotter`.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops\nfrom ansys.dpf.core.plotter import DpfPlotter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Open an example and print out the `Model` object. The\r\n`Model `{.interpreted-text role=\"class\"}\r\nclass helps to organize access methods for the result by keeping track\r\nof the operators and data sources used by the result file.\r\n\r\nPrinting the model displays:\r\n\r\n- Analysis type\r\n- Available results\r\n- Size of the mesh\r\n- Number of results\r\n- Unit\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "path = examples.download_hemisphere()\nmodel = dpf.Model(path)\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Define the node ID normal to plot the a stress gradient\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "node_id = 1928" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the mesh unit\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "unit = model.metadata.meshed_region.unit\nprint(\"Unit: %s\" % unit)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`depth` defines the length/depth that the path penetrates to. While\r\ndefining `depth` make sure you use the correct mesh unit. `delta`\r\ndefines distance between consecutive points on the path.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "depth = 10 # in mm\ndelta = 0.1 # in mm" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the meshed region\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh = model.metadata.meshed_region" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get Equivalent stress fields container.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "stress_fc = model.results.stress().eqv().eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Define Nodal scoping. Make sure to define `\"Nodal\"` as the requested\r\nlocation, important for the\r\n`normals `{.interpreted-text\r\nrole=\"class\"} operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "nodal_scoping = dpf.Scoping(location=dpf.locations.nodal)\nnodal_scoping.ids = [node_id]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get Skin Mesh because\r\n`normals `{.interpreted-text\r\nrole=\"class\"} operator requires Shells as input.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "skin_mesh = ops.mesh.skin(mesh=mesh)\nskin_meshed_region = skin_mesh.outputs.mesh.get_data()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get normal at a node using\r\n`normals `{.interpreted-text\r\nrole=\"class\"} operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "normal = ops.geo.normals()\nnormal.inputs.mesh.connect(skin_meshed_region)\nnormal.inputs.mesh_scoping.connect(nodal_scoping)\nnormal_vec_out_field = normal.outputs.field.get_data()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The normal vector is along the surface normal. You need to invert the\r\nvector using\r\n`scale `{.interpreted-text\r\nrole=\"class\"} operator inwards in the geometry, to get the path\r\ndirection.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "normal_vec_in_field = ops.math.scale(field=normal_vec_out_field, ponderation=-1.0)\nnormal_vec_in = normal_vec_in_field.outputs.field.get_data().data[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get nodal coordinates, they serve as the first point on the line.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "node = mesh.nodes.node_by_id(node_id)\nline_fp = node.coordinates" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create 3D line equation.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "fx = lambda t: line_fp[0] + normal_vec_in[0] * t\nfy = lambda t: line_fp[1] + normal_vec_in[1] * t\nfz = lambda t: line_fp[2] + normal_vec_in[2] * t" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create coordinates using 3D line equation.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "coordinates = [[fx(t * delta), fy(t * delta), fz(t * delta)] for t in range(int(depth / delta))]\nflat_coordinates = [entry for data in coordinates for entry in data]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create field for coordinates of the path.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field_coord = dpf.fields_factory.create_3d_vector_field(len(coordinates))\nfield_coord.data = flat_coordinates\nfield_coord.scoping.ids = list(range(1, len(coordinates) + 1))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Map results on the path.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mapping_operator = ops.mapping.on_coordinates(\n fields_container=stress_fc, coordinates=field_coord, create_support=True, mesh=mesh\n)\nfields_mapped = mapping_operator.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Request the mapped field data and its mesh.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field_m = fields_mapped[0]\nmesh_m = field_m.meshed_region" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create stress vs length chart.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x_initial = 0.0\nlength = [x_initial + delta * index for index in range(len(field_m.data))]\nplt.plot(length, field_m.data, \"r\")\nplt.xlabel(\"Length (%s)\" % mesh.unit)\nplt.ylabel(\"Stress (%s)\" % field_m.unit)\nplt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a plot to add both meshes, `mesh_m` (the mapped mesh) and `mesh`\r\n(the original mesh)\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pl = DpfPlotter()\npl.add_field(field_m, mesh_m)\npl.add_mesh(mesh, style=\"surface\", show_edges=True, color=\"w\", opacity=0.3)\npl.show_figure(\n show_axes=True,\n cpos=[(62.687, 50.119, 67.247), (5.135, 6.458, -0.355), (-0.286, 0.897, -0.336)],\n)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/06-stress_gradient_path.py b/doc/source/examples/04-advanced/06-stress_gradient_path.py new file mode 100644 index 0000000000..4c04f7f400 --- /dev/null +++ b/doc/source/examples/04-advanced/06-stress_gradient_path.py @@ -0,0 +1,145 @@ +# noqa: D400 +""" +.. _stress_gradient_path: + +Stress gradient normal to a defined node +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to plot a stress gradient normal to a selected node. +Because the example is based on creating a path along the normal, the selected node +must be on the surface of the geometry. +A path is created of a defined length. + +""" + +############################################################################### +# Import the DPF-Core module as ``dpf`` and import the +# included examples file and ``DpfPlotter``. +# +import matplotlib.pyplot as plt + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops +from ansys.dpf.core.plotter import DpfPlotter + + +############################################################################### +# Open an example and print out 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. +# +# Printing the model displays: +# +# - Analysis type +# - Available results +# - Size of the mesh +# - Number of results +# - Unit +# +path = examples.download_hemisphere() +model = dpf.Model(path) +print(model) +############################################################################### +# Define the node ID normal to plot the a stress gradient +# +node_id = 1928 +############################################################################### +# Print the mesh unit +# +unit = model.metadata.meshed_region.unit +print("Unit: %s" % unit) +############################################################################### +# ``depth`` defines the length/depth that the path penetrates to. +# While defining ``depth`` make sure you use the correct mesh unit. +# ``delta`` defines distance between consecutive points on the path. +depth = 10 # in mm +delta = 0.1 # in mm +############################################################################### +# Get the meshed region +# +mesh = model.metadata.meshed_region +############################################################################### +# Get Equivalent stress fields container. +# +stress_fc = model.results.stress().eqv().eval() +############################################################################### +# Define Nodal scoping. +# Make sure to define ``"Nodal"`` as the requested location, important for the +# :class:`normals ` operator. +# +nodal_scoping = dpf.Scoping(location=dpf.locations.nodal) +nodal_scoping.ids = [node_id] +############################################################################### +# Get Skin Mesh because :class:`normals ` +# operator requires Shells as input. +# +skin_mesh = ops.mesh.skin(mesh=mesh) +skin_meshed_region = skin_mesh.outputs.mesh.get_data() +############################################################################### +# Get normal at a node using :class:`normals ` +# operator. +# +normal = ops.geo.normals() +normal.inputs.mesh.connect(skin_meshed_region) +normal.inputs.mesh_scoping.connect(nodal_scoping) +normal_vec_out_field = normal.outputs.field.get_data() +############################################################################### +# The normal vector is along the surface normal. You need to invert the vector +# using :class:`scale ` operator +# inwards in the geometry, to get the path direction. +# +normal_vec_in_field = ops.math.scale(field=normal_vec_out_field, ponderation=-1.0) +normal_vec_in = normal_vec_in_field.outputs.field.get_data().data[0] +############################################################################### +# Get nodal coordinates, they serve as the first point on the line. +# +node = mesh.nodes.node_by_id(node_id) +line_fp = node.coordinates +############################################################################### +# Create 3D line equation. +# +fx = lambda t: line_fp[0] + normal_vec_in[0] * t +fy = lambda t: line_fp[1] + normal_vec_in[1] * t +fz = lambda t: line_fp[2] + normal_vec_in[2] * t +############################################################################### +# Create coordinates using 3D line equation. +# +coordinates = [[fx(t * delta), fy(t * delta), fz(t * delta)] for t in range(int(depth / delta))] +flat_coordinates = [entry for data in coordinates for entry in data] +############################################################################### +# Create field for coordinates of the path. +# +field_coord = dpf.fields_factory.create_3d_vector_field(len(coordinates)) +field_coord.data = flat_coordinates +field_coord.scoping.ids = list(range(1, len(coordinates) + 1)) +############################################################################### +# Map results on the path. +mapping_operator = ops.mapping.on_coordinates( + fields_container=stress_fc, coordinates=field_coord, create_support=True, mesh=mesh +) +fields_mapped = mapping_operator.outputs.fields_container() +############################################################################### +# Request the mapped field data and its mesh. +field_m = fields_mapped[0] +mesh_m = field_m.meshed_region +############################################################################### +# Create stress vs length chart. +# +x_initial = 0.0 +length = [x_initial + delta * index for index in range(len(field_m.data))] +plt.plot(length, field_m.data, "r") +plt.xlabel("Length (%s)" % mesh.unit) +plt.ylabel("Stress (%s)" % field_m.unit) +plt.show() +############################################################################### +# Create a plot to add both meshes, ``mesh_m`` (the mapped mesh) and ``mesh`` +# (the original mesh) +pl = DpfPlotter() +pl.add_field(field_m, mesh_m) +pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) +pl.show_figure( + show_axes=True, + cpos=[(62.687, 50.119, 67.247), (5.135, 6.458, -0.355), (-0.286, 0.897, -0.336)], +) diff --git a/doc/source/examples/04-advanced/06-stress_gradient_path.py.md5 b/doc/source/examples/04-advanced/06-stress_gradient_path.py.md5 new file mode 100644 index 0000000000..2ff40bc3f9 --- /dev/null +++ b/doc/source/examples/04-advanced/06-stress_gradient_path.py.md5 @@ -0,0 +1 @@ +d6fef8e3c3e8be5993e0df50c8402761 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/06-stress_gradient_path.rst b/doc/source/examples/04-advanced/06-stress_gradient_path.rst new file mode 100644 index 0000000000..7ebd609e9c --- /dev/null +++ b/doc/source/examples/04-advanced/06-stress_gradient_path.rst @@ -0,0 +1,487 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\06-stress_gradient_path.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_06-stress_gradient_path.py: + + +.. _stress_gradient_path: + +Stress gradient normal to a defined node +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to plot a stress gradient normal to a selected node. +Because the example is based on creating a path along the normal, the selected node +must be on the surface of the geometry. +A path is created of a defined length. + +.. GENERATED FROM PYTHON SOURCE LINES 16-19 + +Import the DPF-Core module as ``dpf`` and import the +included examples file and ``DpfPlotter``. + + +.. GENERATED FROM PYTHON SOURCE LINES 19-27 + +.. code-block:: default + + import matplotlib.pyplot as plt + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + from ansys.dpf.core.plotter import DpfPlotter + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 28-41 + +Open an example and print out 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. + +Printing the model displays: + +- Analysis type +- Available results +- Size of the mesh +- Number of results +- Unit + + +.. GENERATED FROM PYTHON SOURCE LINES 41-44 + +.. code-block:: default + + path = examples.download_hemisphere() + model = dpf.Model(path) + print(model) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: NMM: mm, ton, N, s, mV, mA, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 10741 nodes + 3011 elements + Unit: mm + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1 + Cumulative Time (s) LoadStep Substep + 1 1,000000 1 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 45-47 + +Define the node ID normal to plot the a stress gradient + + +.. GENERATED FROM PYTHON SOURCE LINES 47-48 + +.. code-block:: default + + node_id = 1928 + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 49-51 + +Print the mesh unit + + +.. GENERATED FROM PYTHON SOURCE LINES 51-53 + +.. code-block:: default + + unit = model.metadata.meshed_region.unit + print("Unit: %s" % unit) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Unit: mm + + + + +.. GENERATED FROM PYTHON SOURCE LINES 54-57 + +``depth`` defines the length/depth that the path penetrates to. +While defining ``depth`` make sure you use the correct mesh unit. +``delta`` defines distance between consecutive points on the path. + +.. GENERATED FROM PYTHON SOURCE LINES 57-59 + +.. code-block:: default + + depth = 10 # in mm + delta = 0.1 # in mm + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 60-62 + +Get the meshed region + + +.. GENERATED FROM PYTHON SOURCE LINES 62-63 + +.. code-block:: default + + mesh = model.metadata.meshed_region + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 64-66 + +Get Equivalent stress fields container. + + +.. GENERATED FROM PYTHON SOURCE LINES 66-67 + +.. code-block:: default + + stress_fc = model.results.stress().eqv().eval() + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 68-72 + +Define Nodal scoping. +Make sure to define ``"Nodal"`` as the requested location, important for the +:class:`normals ` operator. + + +.. GENERATED FROM PYTHON SOURCE LINES 72-74 + +.. code-block:: default + + nodal_scoping = dpf.Scoping(location=dpf.locations.nodal) + nodal_scoping.ids = [node_id] + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 75-78 + +Get Skin Mesh because :class:`normals ` +operator requires Shells as input. + + +.. GENERATED FROM PYTHON SOURCE LINES 78-80 + +.. code-block:: default + + skin_mesh = ops.mesh.skin(mesh=mesh) + skin_meshed_region = skin_mesh.outputs.mesh.get_data() + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 81-84 + +Get normal at a node using :class:`normals ` +operator. + + +.. GENERATED FROM PYTHON SOURCE LINES 84-88 + +.. code-block:: default + + normal = ops.geo.normals() + normal.inputs.mesh.connect(skin_meshed_region) + normal.inputs.mesh_scoping.connect(nodal_scoping) + normal_vec_out_field = normal.outputs.field.get_data() + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 89-93 + +The normal vector is along the surface normal. You need to invert the vector +using :class:`scale ` operator +inwards in the geometry, to get the path direction. + + +.. GENERATED FROM PYTHON SOURCE LINES 93-95 + +.. code-block:: default + + normal_vec_in_field = ops.math.scale(field=normal_vec_out_field, ponderation=-1.0) + normal_vec_in = normal_vec_in_field.outputs.field.get_data().data[0] + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 96-98 + +Get nodal coordinates, they serve as the first point on the line. + + +.. GENERATED FROM PYTHON SOURCE LINES 98-100 + +.. code-block:: default + + node = mesh.nodes.node_by_id(node_id) + line_fp = node.coordinates + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 101-103 + +Create 3D line equation. + + +.. GENERATED FROM PYTHON SOURCE LINES 103-106 + +.. code-block:: default + + fx = lambda t: line_fp[0] + normal_vec_in[0] * t + fy = lambda t: line_fp[1] + normal_vec_in[1] * t + fz = lambda t: line_fp[2] + normal_vec_in[2] * t + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 107-109 + +Create coordinates using 3D line equation. + + +.. GENERATED FROM PYTHON SOURCE LINES 109-111 + +.. code-block:: default + + coordinates = [[fx(t * delta), fy(t * delta), fz(t * delta)] for t in range(int(depth / delta))] + flat_coordinates = [entry for data in coordinates for entry in data] + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 112-114 + +Create field for coordinates of the path. + + +.. GENERATED FROM PYTHON SOURCE LINES 114-117 + +.. code-block:: default + + field_coord = dpf.fields_factory.create_3d_vector_field(len(coordinates)) + field_coord.data = flat_coordinates + field_coord.scoping.ids = list(range(1, len(coordinates) + 1)) + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 118-119 + +Map results on the path. + +.. GENERATED FROM PYTHON SOURCE LINES 119-123 + +.. code-block:: default + + mapping_operator = ops.mapping.on_coordinates( + fields_container=stress_fc, coordinates=field_coord, create_support=True, mesh=mesh + ) + fields_mapped = mapping_operator.outputs.fields_container() + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 124-125 + +Request the mapped field data and its mesh. + +.. GENERATED FROM PYTHON SOURCE LINES 125-127 + +.. code-block:: default + + field_m = fields_mapped[0] + mesh_m = field_m.meshed_region + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 128-130 + +Create stress vs length chart. + + +.. GENERATED FROM PYTHON SOURCE LINES 130-136 + +.. code-block:: default + + x_initial = 0.0 + length = [x_initial + delta * index for index in range(len(field_m.data))] + plt.plot(length, field_m.data, "r") + plt.xlabel("Length (%s)" % mesh.unit) + plt.ylabel("Stress (%s)" % field_m.unit) + plt.show() + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_06-stress_gradient_path_001.png + :alt: 06 stress gradient path + :srcset: /examples/04-advanced/images/sphx_glr_06-stress_gradient_path_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 137-139 + +Create a plot to add both meshes, ``mesh_m`` (the mapped mesh) and ``mesh`` +(the original mesh) + +.. GENERATED FROM PYTHON SOURCE LINES 139-146 + +.. code-block:: default + + pl = DpfPlotter() + pl.add_field(field_m, mesh_m) + pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) + pl.show_figure( + show_axes=True, + cpos=[(62.687, 50.119, 67.247), (5.135, 6.458, -0.355), (-0.286, 0.897, -0.336)], + ) + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_06-stress_gradient_path_002.png + :alt: 06 stress gradient path + :srcset: /examples/04-advanced/images/sphx_glr_06-stress_gradient_path_002.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 1.270 seconds) + + +.. _sphx_glr_download_examples_04-advanced_06-stress_gradient_path.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 06-stress_gradient_path.py <06-stress_gradient_path.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 06-stress_gradient_path.ipynb <06-stress_gradient_path.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/06-stress_gradient_path_codeobj.pickle b/doc/source/examples/04-advanced/06-stress_gradient_path_codeobj.pickle new file mode 100644 index 0000000000..28d4327d3e Binary files /dev/null and b/doc/source/examples/04-advanced/06-stress_gradient_path_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/07-load_plugin.ipynb b/doc/source/examples/04-advanced/07-load_plugin.ipynb new file mode 100644 index 0000000000..cc8955ced2 --- /dev/null +++ b/doc/source/examples/04-advanced/07-load_plugin.ipynb @@ -0,0 +1,97 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Load plugin {#ref_load_plugin}\r\n\r\nThis example shows how to load a plugin that is not loaded\r\nautomatically.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import DPF-Core:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\n\n\nserver = dpf.global_server()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a base service for loading a plugin:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "if server.os == \"posix\":\n dpf.core.load_library(\"libAns.Dpf.Math.so\", \"math_operators\")\nelse:\n dpf.core.load_library(\"Ans.Dpf.Math.dll\", \"math_operators\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Math operators are now loaded and accessible in\r\n`ansys.dpf.core.operators`:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf.core import operators as ops\n\nmath_op = ops.math.fft_eval()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/07-load_plugin.py b/doc/source/examples/04-advanced/07-load_plugin.py new file mode 100644 index 0000000000..7f8753b6f0 --- /dev/null +++ b/doc/source/examples/04-advanced/07-load_plugin.py @@ -0,0 +1,30 @@ +""" +.. _ref_load_plugin: + +Load plugin +~~~~~~~~~~~ + +This example shows how to load a plugin that is not loaded automatically. + +""" + +############################################################################### +# Import DPF-Core: +from ansys.dpf import core as dpf + + +server = dpf.global_server() + +############################################################################### +# Create a base service for loading a plugin: +if server.os == "posix": + dpf.core.load_library("libAns.Dpf.Math.so", "math_operators") +else: + dpf.core.load_library("Ans.Dpf.Math.dll", "math_operators") + +############################################################################### +# Math operators are now loaded and accessible in ``ansys.dpf.core.operators``: + +from ansys.dpf.core import operators as ops + +math_op = ops.math.fft_eval() diff --git a/doc/source/examples/04-advanced/07-load_plugin.py.md5 b/doc/source/examples/04-advanced/07-load_plugin.py.md5 new file mode 100644 index 0000000000..393cac25d0 --- /dev/null +++ b/doc/source/examples/04-advanced/07-load_plugin.py.md5 @@ -0,0 +1 @@ +c01ec987385e260b1bd03feb8c87593c \ No newline at end of file diff --git a/doc/source/examples/04-advanced/07-load_plugin.rst b/doc/source/examples/04-advanced/07-load_plugin.rst new file mode 100644 index 0000000000..cd936cd687 --- /dev/null +++ b/doc/source/examples/04-advanced/07-load_plugin.rst @@ -0,0 +1,113 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\07-load_plugin.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_07-load_plugin.py: + + +.. _ref_load_plugin: + +Load plugin +~~~~~~~~~~~ + +This example shows how to load a plugin that is not loaded automatically. + +.. GENERATED FROM PYTHON SOURCE LINES 12-13 + +Import DPF-Core: + +.. GENERATED FROM PYTHON SOURCE LINES 13-18 + +.. code-block:: default + + from ansys.dpf import core as dpf + + + server = dpf.global_server() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 19-20 + +Create a base service for loading a plugin: + +.. GENERATED FROM PYTHON SOURCE LINES 20-25 + +.. code-block:: default + + if server.os == "posix": + dpf.core.load_library("libAns.Dpf.Math.so", "math_operators") + else: + dpf.core.load_library("Ans.Dpf.Math.dll", "math_operators") + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 26-27 + +Math operators are now loaded and accessible in ``ansys.dpf.core.operators``: + +.. GENERATED FROM PYTHON SOURCE LINES 27-31 + +.. code-block:: default + + + from ansys.dpf.core import operators as ops + + math_op = ops.math.fft_eval() + + + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.013 seconds) + + +.. _sphx_glr_download_examples_04-advanced_07-load_plugin.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 07-load_plugin.py <07-load_plugin.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 07-load_plugin.ipynb <07-load_plugin.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/07-load_plugin_codeobj.pickle b/doc/source/examples/04-advanced/07-load_plugin_codeobj.pickle new file mode 100644 index 0000000000..36f2cf6e09 Binary files /dev/null and b/doc/source/examples/04-advanced/07-load_plugin_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/10-asme_secviii_divtwo.ipynb b/doc/source/examples/04-advanced/10-asme_secviii_divtwo.ipynb new file mode 100644 index 0000000000..676c318ede --- /dev/null +++ b/doc/source/examples/04-advanced/10-asme_secviii_divtwo.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pressure vessel analysis according to an ASME standard {#ref_ASME_SecVIII_Div2}\r\n\r\nThis example demonstrates how you can use PyDPF to postprocess a\r\nMechanical model according to the ASME Section VIII Division 2 standard\r\nfor pressure vessel designs.\r\n\r\nThis example is taken from Workshop 02.1 from Ansys Mechanical Advanced\r\nTopics. Instead of using several user defined results as it is done in\r\nthe workshop, DPF is able to calculate the triaxial strain limit and\r\ncompare it with the equivalent plastic strain, as specified in Equation\r\n5.7 assuming 0 forming strain.\r\n\r\nPlease be aware that this is just an example, so it is the user\\'s duty\r\nto verify that calculation is made according to latest ASME standard.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import the result file from Workshop 02.1.\n# Because it is a elastic-plastic analysis, there are several substeps. The focus\n# here is on the latest substep (number 4)\n\nimport ansys.dpf.core as dpf\nfrom ansys.dpf.core import examples\n\npath = examples.download_example_asme_result()\nmodel = dpf.Model(path)\ndata_source = model.metadata.data_sources\n\ntime_scoping = dpf.Scoping()\ntime_scoping.location = dpf.locations.time_freq\ntime_scoping.ids = [4]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parameters input\r\n\r\nYou must go to ASME Section III Division 2 to get values for the\r\nparameters `alfasl` and `m2`. This is the code for introducing these\r\nparameters manually:\r\n\r\n- `alfasl` = input(\\\"Introduce `alfasl` parameter from ASMEn\\\")\r\n- `alfasl` = float(alfasl)\r\n- `m2` = input(\\\"Introduce `m2` parameter from ASMEn\\\")\r\n- `m2` = float(m2)\r\n\r\nFor this exercise, `alfasl` = 2.2 and `m2` = .288, which is the same as\r\nthe original.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "alfasl = 2.2\nm2 = 0.288" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Stresses and strains\r\n\r\nStresses and strains are read. To get the same results as Mechanical,\r\nread elemental nodal strains and apply von Mises invariant. This\r\noperator does not have an option for defining the effective Poisson\\'s\r\nratio. Consequently, a correction factor is applied.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "seqv_op = dpf.operators.result.stress_von_mises(\n time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal\n)\nseqv = seqv_op.outputs.fields_container()\n\ns1_op = dpf.operators.result.stress_principal_1(\n time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal\n)\ns1 = s1_op.outputs.fields_container()\n\ns2_op = dpf.operators.result.stress_principal_2(\n time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal\n)\ns2 = s2_op.outputs.fields_container()\n\ns3_op = dpf.operators.result.stress_principal_3(\n time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal\n)\ns3 = s3_op.outputs.fields_container()\n\nstrain_op = dpf.operators.result.plastic_strain(\n data_sources=data_source,\n requested_location=dpf.locations.elemental_nodal,\n time_scoping=time_scoping,\n)\npstrain = strain_op.outputs.fields_container()\n\neppleqv_op = dpf.operators.invariant.von_mises_eqv_fc(fields_container=pstrain)\neppleqv = eppleqv_op.outputs.fields_container()\n\npoisson_ratio_correction = 1.3 / 1.5\neppleqvmech_op = dpf.operators.math.scale_fc(\n fields_container=eppleqv, ponderation=poisson_ratio_correction\n)\neppleqvmech = eppleqvmech_op.outputs.fields_container()\n\n\neppleqvave_op = dpf.operators.averaging.to_nodal_fc(fields_container=eppleqvmech)\neppleqvave = eppleqvave_op.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Triaxial strain limit calculation\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# S12=S1+S2\ns12_op = dpf.operators.math.add_fc(fields_container1=s1, fields_container2=s2)\ns12 = s12_op.outputs.fields_container()\n# S123=S12+S3\ns123_op = dpf.operators.math.add_fc(fields_container1=s12, fields_container2=s3)\ns123 = s123_op.outputs.fields_container()\n# SVM_scale=SVM*3\nratio = 3.0\nseqvs_op = dpf.operators.math.scale_fc(fields_container=seqv, ponderation=ratio)\nseqvs = seqvs_op.outputs.fields_container()\n# S123/SVM*3\nsratio_op = dpf.operators.math.component_wise_divide(fieldA=s123, fieldB=seqvs)\nsratio = sratio_op.outputs.field()\n# S123/SVM*3-0.33\nsterm_op = dpf.operators.math.add_constant(field=sratio, ponderation=-1 / 3)\nsterm = sterm_op.outputs.field()\n# -alfasl/(1+m2)*stressterm\nratio2 = -alfasl / (1 + m2)\nexpt_op = dpf.operators.math.scale(field=sterm, ponderation=ratio2)\nexpt = expt_op.outputs.field()\n# exp(-alfasl/(1+m2)*stressterm)\nexp_op = dpf.operators.math.exponential(field=expt)\nexp = exp_op.outputs.field()\n# elu*exp(-alfasl/(1+m2)*stressterm)\nstrainlimit_op = dpf.operators.math.scale(field=exp, ponderation=m2)\nstrainlimit = strainlimit_op.outputs.field()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Strain limit condition (less than 1 pass the criteria)\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "strainratio = dpf.operators.math.component_wise_divide(fieldA=eppleqvave, fieldB=strainlimit)\nstrainratio = strainratio.outputs.field()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Strain limit condition is plot\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model.metadata.meshed_region.plot(strainratio)\ndpf.server.shutdown_all_session_servers()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/10-asme_secviii_divtwo.py b/doc/source/examples/04-advanced/10-asme_secviii_divtwo.py new file mode 100644 index 0000000000..79b2022b77 --- /dev/null +++ b/doc/source/examples/04-advanced/10-asme_secviii_divtwo.py @@ -0,0 +1,144 @@ +""" +.. _ref_ASME_SecVIII_Div2: + +Pressure vessel analysis according to an ASME standard +------------------------------------------------------ + +This example demonstrates how you can use PyDPF to postprocess a Mechanical +model according to the ASME Section VIII Division 2 standard for pressure +vessel designs. + +This example is taken from Workshop 02.1 from Ansys Mechanical Advanced Topics. +Instead of using several user defined results as it is done in the workshop, +DPF is able to calculate the triaxial strain limit and compare it with the +equivalent plastic strain, as specified in Equation 5.7 assuming 0 forming strain. + +Please be aware that this is just an example, so it is the user's duty to verify +that calculation is made according to latest ASME standard. +""" + +# Import the result file from Workshop 02.1. +# Because it is a elastic-plastic analysis, there are several substeps. The focus +# here is on the latest substep (number 4) + +import ansys.dpf.core as dpf +from ansys.dpf.core import examples + +path = examples.download_example_asme_result() +model = dpf.Model(path) +data_source = model.metadata.data_sources + +time_scoping = dpf.Scoping() +time_scoping.location = dpf.locations.time_freq +time_scoping.ids = [4] + + +############################################################################### +# Parameters input +# ~~~~~~~~~~~~~~~~ +# You must go to ASME Section III Division 2 to get values for the parameters +# ``alfasl`` and ``m2``. This is the code for introducing these parameters +# manually: +# +# - ``alfasl`` = input("Introduce ``alfasl`` parameter from ASME\n") +# - ``alfasl`` = float(alfasl) +# - ``m2`` = input("Introduce ``m2`` parameter from ASME\n") +# - ``m2`` = float(m2) +# +# For this exercise, ``alfasl`` = 2.2 and ``m2`` = .288, which is the same +# as the original. +# + +alfasl = 2.2 +m2 = 0.288 + +############################################################################### +# Stresses and strains +# ~~~~~~~~~~~~~~~~~~~~ +# Stresses and strains are read. To get the same results as Mechanical, read +# elemental nodal strains and apply von Mises invariant. This operator +# does not have an option for defining the effective Poisson's ratio. +# Consequently, a correction factor is applied. + +seqv_op = dpf.operators.result.stress_von_mises( + time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal +) +seqv = seqv_op.outputs.fields_container() + +s1_op = dpf.operators.result.stress_principal_1( + time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal +) +s1 = s1_op.outputs.fields_container() + +s2_op = dpf.operators.result.stress_principal_2( + time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal +) +s2 = s2_op.outputs.fields_container() + +s3_op = dpf.operators.result.stress_principal_3( + time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal +) +s3 = s3_op.outputs.fields_container() + +strain_op = dpf.operators.result.plastic_strain( + data_sources=data_source, + requested_location=dpf.locations.elemental_nodal, + time_scoping=time_scoping, +) +pstrain = strain_op.outputs.fields_container() + +eppleqv_op = dpf.operators.invariant.von_mises_eqv_fc(fields_container=pstrain) +eppleqv = eppleqv_op.outputs.fields_container() + +poisson_ratio_correction = 1.3 / 1.5 +eppleqvmech_op = dpf.operators.math.scale_fc( + fields_container=eppleqv, ponderation=poisson_ratio_correction +) +eppleqvmech = eppleqvmech_op.outputs.fields_container() + + +eppleqvave_op = dpf.operators.averaging.to_nodal_fc(fields_container=eppleqvmech) +eppleqvave = eppleqvave_op.outputs.fields_container() + +############################################################################### +# Triaxial strain limit calculation +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# S12=S1+S2 +s12_op = dpf.operators.math.add_fc(fields_container1=s1, fields_container2=s2) +s12 = s12_op.outputs.fields_container() +# S123=S12+S3 +s123_op = dpf.operators.math.add_fc(fields_container1=s12, fields_container2=s3) +s123 = s123_op.outputs.fields_container() +# SVM_scale=SVM*3 +ratio = 3.0 +seqvs_op = dpf.operators.math.scale_fc(fields_container=seqv, ponderation=ratio) +seqvs = seqvs_op.outputs.fields_container() +# S123/SVM*3 +sratio_op = dpf.operators.math.component_wise_divide(fieldA=s123, fieldB=seqvs) +sratio = sratio_op.outputs.field() +# S123/SVM*3-0.33 +sterm_op = dpf.operators.math.add_constant(field=sratio, ponderation=-1 / 3) +sterm = sterm_op.outputs.field() +# -alfasl/(1+m2)*stressterm +ratio2 = -alfasl / (1 + m2) +expt_op = dpf.operators.math.scale(field=sterm, ponderation=ratio2) +expt = expt_op.outputs.field() +# exp(-alfasl/(1+m2)*stressterm) +exp_op = dpf.operators.math.exponential(field=expt) +exp = exp_op.outputs.field() +# elu*exp(-alfasl/(1+m2)*stressterm) +strainlimit_op = dpf.operators.math.scale(field=exp, ponderation=m2) +strainlimit = strainlimit_op.outputs.field() + +############################################################################### +# Strain limit condition (less than 1 pass the criteria) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +strainratio = dpf.operators.math.component_wise_divide(fieldA=eppleqvave, fieldB=strainlimit) +strainratio = strainratio.outputs.field() + +############################################################################### +# Strain limit condition is plot +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +model.metadata.meshed_region.plot(strainratio) +dpf.server.shutdown_all_session_servers() diff --git a/doc/source/examples/04-advanced/10-asme_secviii_divtwo.py.md5 b/doc/source/examples/04-advanced/10-asme_secviii_divtwo.py.md5 new file mode 100644 index 0000000000..14952b033a --- /dev/null +++ b/doc/source/examples/04-advanced/10-asme_secviii_divtwo.py.md5 @@ -0,0 +1 @@ +ab271a1ad855d9f61d866fb296781518 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/10-asme_secviii_divtwo.rst b/doc/source/examples/04-advanced/10-asme_secviii_divtwo.rst new file mode 100644 index 0000000000..d125b6b169 --- /dev/null +++ b/doc/source/examples/04-advanced/10-asme_secviii_divtwo.rst @@ -0,0 +1,271 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\10-asme_secviii_divtwo.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_10-asme_secviii_divtwo.py: + + +.. _ref_ASME_SecVIII_Div2: + +Pressure vessel analysis according to an ASME standard +------------------------------------------------------ + +This example demonstrates how you can use PyDPF to postprocess a Mechanical +model according to the ASME Section VIII Division 2 standard for pressure +vessel designs. + +This example is taken from Workshop 02.1 from Ansys Mechanical Advanced Topics. +Instead of using several user defined results as it is done in the workshop, +DPF is able to calculate the triaxial strain limit and compare it with the +equivalent plastic strain, as specified in Equation 5.7 assuming 0 forming strain. + +Please be aware that this is just an example, so it is the user's duty to verify +that calculation is made according to latest ASME standard. + +.. GENERATED FROM PYTHON SOURCE LINES 19-36 + +.. code-block:: default + + + # Import the result file from Workshop 02.1. + # Because it is a elastic-plastic analysis, there are several substeps. The focus + # here is on the latest substep (number 4) + + import ansys.dpf.core as dpf + from ansys.dpf.core import examples + + path = examples.download_example_asme_result() + model = dpf.Model(path) + data_source = model.metadata.data_sources + + time_scoping = dpf.Scoping() + time_scoping.location = dpf.locations.time_freq + time_scoping.ids = [4] + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 37-51 + +Parameters input +~~~~~~~~~~~~~~~~ +You must go to ASME Section III Division 2 to get values for the parameters +``alfasl`` and ``m2``. This is the code for introducing these parameters +manually: + +- ``alfasl`` = input("Introduce ``alfasl`` parameter from ASME\n") +- ``alfasl`` = float(alfasl) +- ``m2`` = input("Introduce ``m2`` parameter from ASME\n") +- ``m2`` = float(m2) + +For this exercise, ``alfasl`` = 2.2 and ``m2`` = .288, which is the same +as the original. + + +.. GENERATED FROM PYTHON SOURCE LINES 51-55 + +.. code-block:: default + + + alfasl = 2.2 + m2 = 0.288 + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 56-62 + +Stresses and strains +~~~~~~~~~~~~~~~~~~~~ +Stresses and strains are read. To get the same results as Mechanical, read +elemental nodal strains and apply von Mises invariant. This operator +does not have an option for defining the effective Poisson's ratio. +Consequently, a correction factor is applied. + +.. GENERATED FROM PYTHON SOURCE LINES 62-103 + +.. code-block:: default + + + seqv_op = dpf.operators.result.stress_von_mises( + time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal + ) + seqv = seqv_op.outputs.fields_container() + + s1_op = dpf.operators.result.stress_principal_1( + time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal + ) + s1 = s1_op.outputs.fields_container() + + s2_op = dpf.operators.result.stress_principal_2( + time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal + ) + s2 = s2_op.outputs.fields_container() + + s3_op = dpf.operators.result.stress_principal_3( + time_scoping=time_scoping, data_sources=data_source, requested_location=dpf.locations.nodal + ) + s3 = s3_op.outputs.fields_container() + + strain_op = dpf.operators.result.plastic_strain( + data_sources=data_source, + requested_location=dpf.locations.elemental_nodal, + time_scoping=time_scoping, + ) + pstrain = strain_op.outputs.fields_container() + + eppleqv_op = dpf.operators.invariant.von_mises_eqv_fc(fields_container=pstrain) + eppleqv = eppleqv_op.outputs.fields_container() + + poisson_ratio_correction = 1.3 / 1.5 + eppleqvmech_op = dpf.operators.math.scale_fc( + fields_container=eppleqv, ponderation=poisson_ratio_correction + ) + eppleqvmech = eppleqvmech_op.outputs.fields_container() + + + eppleqvave_op = dpf.operators.averaging.to_nodal_fc(fields_container=eppleqvmech) + eppleqvave = eppleqvave_op.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 104-106 + +Triaxial strain limit calculation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 106-134 + +.. code-block:: default + + + # S12=S1+S2 + s12_op = dpf.operators.math.add_fc(fields_container1=s1, fields_container2=s2) + s12 = s12_op.outputs.fields_container() + # S123=S12+S3 + s123_op = dpf.operators.math.add_fc(fields_container1=s12, fields_container2=s3) + s123 = s123_op.outputs.fields_container() + # SVM_scale=SVM*3 + ratio = 3.0 + seqvs_op = dpf.operators.math.scale_fc(fields_container=seqv, ponderation=ratio) + seqvs = seqvs_op.outputs.fields_container() + # S123/SVM*3 + sratio_op = dpf.operators.math.component_wise_divide(fieldA=s123, fieldB=seqvs) + sratio = sratio_op.outputs.field() + # S123/SVM*3-0.33 + sterm_op = dpf.operators.math.add_constant(field=sratio, ponderation=-1 / 3) + sterm = sterm_op.outputs.field() + # -alfasl/(1+m2)*stressterm + ratio2 = -alfasl / (1 + m2) + expt_op = dpf.operators.math.scale(field=sterm, ponderation=ratio2) + expt = expt_op.outputs.field() + # exp(-alfasl/(1+m2)*stressterm) + exp_op = dpf.operators.math.exponential(field=expt) + exp = exp_op.outputs.field() + # elu*exp(-alfasl/(1+m2)*stressterm) + strainlimit_op = dpf.operators.math.scale(field=exp, ponderation=m2) + strainlimit = strainlimit_op.outputs.field() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 135-137 + +Strain limit condition (less than 1 pass the criteria) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 137-140 + +.. code-block:: default + + strainratio = dpf.operators.math.component_wise_divide(fieldA=eppleqvave, fieldB=strainlimit) + strainratio = strainratio.outputs.field() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 141-143 + +Strain limit condition is plot +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 143-145 + +.. code-block:: default + + model.metadata.meshed_region.plot(strainratio) + dpf.server.shutdown_all_session_servers() + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_10-asme_secviii_divtwo_001.png + :alt: 10 asme secviii divtwo + :srcset: /examples/04-advanced/images/sphx_glr_10-asme_secviii_divtwo_001.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 2.984 seconds) + + +.. _sphx_glr_download_examples_04-advanced_10-asme_secviii_divtwo.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 10-asme_secviii_divtwo.py <10-asme_secviii_divtwo.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 10-asme_secviii_divtwo.ipynb <10-asme_secviii_divtwo.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/10-asme_secviii_divtwo_codeobj.pickle b/doc/source/examples/04-advanced/10-asme_secviii_divtwo_codeobj.pickle new file mode 100644 index 0000000000..3f71f946c4 Binary files /dev/null and b/doc/source/examples/04-advanced/10-asme_secviii_divtwo_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/11-cycles_to_failure.ipynb b/doc/source/examples/04-advanced/11-cycles_to_failure.ipynb new file mode 100644 index 0000000000..30c55d047b --- /dev/null +++ b/doc/source/examples/04-advanced/11-cycles_to_failure.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Calculate the number of cycles to fatigue failure {#ref_cycles_to_failure}\r\n\r\nThis example shows how to generate and use a result file to calculate\r\nthe cycles to failure result for a simple model.\r\n\r\nMaterial data is manually imported, Structural Steel from Ansys\r\nMechanical:\r\n\r\n- Youngs Modulus (youngsSteel)\r\n- Poisson\\'s Ratio (prxySteel)\r\n- SN curve (sn_data)\r\n\r\nThe first step is to generate a simple model with high stress and save\r\nthe results .rst file locally to myDir (default is \\\"C:\\\\temp\\\"). For\r\nthis, we provide a short pyMAPDL script.\r\n\r\nThe cycles to failure result is the (interpolated) negative of the\r\nstress result. The higher the stress result, the lower the number of\r\ncycles to failure.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nimport numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first step is to generate a simple model with high stress\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# # Material parameters from Ansys Mechanical Structural Steel\nyoungsSteel = 200e9\nprxySteel = 0.3\nsn_data = np.empty((11, 2)) # initialize empty np matrix\nsn_data[:, 0] = [10, 20, 50, 100, 200, 2000, 10000, 20000, 1e5, 2e5, 1e6]\nsn_data[:, 1] = [\n 3.999e9,\n 2.8327e9,\n 1.896e9,\n 1.413e9,\n 1.069e9,\n 4.41e8,\n 2.62e8,\n 2.14e8,\n 1.38e8,\n 1.14e8,\n 8.62e7,\n]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The .rst file used is already available, but can be obtained using the\r\nshort pyMAPDL code below:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# # ### Launch pymapdl to generate rst file in myDir\n# from ansys.mapdl.core import launch_mapdl\n# import os\n#\n#\n# mapdl = launch_mapdl()\n# mapdl.prep7()\n# # Model\n# mapdl.cylind(0.5, 0, 10, 0)\n# mapdl.mp(\"EX\", 1, youngsSteel)\n# mapdl.mp(\"PRXY\", 1, prxySteel)\n# mapdl.mshape(key=1, dimension='3d')\n# mapdl.et(1, \"SOLID186\")\n# mapdl.esize(0.3)\n# mapdl.vmesh('ALL')\n#\n# # #### Boundary Conditions: fixed constraint\n# mapdl.nsel(type_='S', item='LOC', comp='Z', vmin=0)\n# mapdl.d(\"all\", \"all\")\n# mapdl.nsel(type_='S', item='LOC', comp='Z', vmin=10)\n# nnodes = mapdl.get(\"NumNodes\", \"NODE\", 0, \"COUNT\")\n# mapdl.f(node=\"ALL\", lab=\"fy\", value=-13e6 / nnodes)\n# mapdl.allsel()\n#\n# # #### Solve\n# mapdl.run(\"/SOLU\")\n# sol_output = mapdl.solve()\n# rst = os.path.join(mapdl.directory, 'file.rst')\n# mapdl.exit()\n# print('apdl model solved.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "PyDPF-Core is then used to post-process the .rst file to estimate the\r\ncycles to failure.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Comment the following line if solving the MAPDL problem first.\nrst = examples.download_cycles_to_failure()\n\n# Import the result as a DPF Model object.\nmodel = dpf.Model(rst)\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the von mises equivalent stress, requires an operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s_eqv_op = dpf.operators.result.stress_von_mises(data_sources=model)\nvm_stress_fc = s_eqv_op.eval()\nvm_stress_field = vm_stress_fc[0]\nvm_stress_field.plot(text=\"VM stress field\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use NumPy to interpolate the results.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Inverse the sn_data\nx_values = sn_data[:, 1][::-1] # the x values are the stress ranges in ascending order\ny_values = sn_data[:, 0][::-1] # y values are inverted cycles to failure\n\n# Interpolate cycles to failure for the VM values\ncycles_to_failure = np.interp(vm_stress_field.data, x_values, y_values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a cycles_to_failure DPF Field\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create an empty field\ncycles_to_failure_field = dpf.Field(\n nentities=len(vm_stress_field.scoping),\n nature=dpf.natures.scalar,\n location=dpf.locations.nodal,\n)\n# Populate the field\ncycles_to_failure_field.scoping = vm_stress_field.scoping\ncycles_to_failure_field.meshed_region = vm_stress_field.meshed_region\ncycles_to_failure_field.data = cycles_to_failure\n\n# Plot the field\nsargs = dict(title=\"cycles\", fmt=\"%.2e\")\ncycles_to_failure_field.plot(text=\"Cycles to failure\", scalar_bar_args=sargs)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/11-cycles_to_failure.py b/doc/source/examples/04-advanced/11-cycles_to_failure.py new file mode 100644 index 0000000000..5f500c8574 --- /dev/null +++ b/doc/source/examples/04-advanced/11-cycles_to_failure.py @@ -0,0 +1,137 @@ +""" +.. _ref_cycles_to_failure: + +Calculate the number of cycles to fatigue failure +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to generate and use a result file to calculate the +cycles to failure result for a simple model. + +Material data is manually imported, Structural Steel from Ansys Mechanical: + +- Youngs Modulus (youngsSteel) +- Poisson's Ratio (prxySteel) +- SN curve (sn_data) + +The first step is to generate a simple model with high stress and save the +results .rst file locally to myDir (default is "C:\\\\temp"). +For this, we provide a short pyMAPDL script. + +.. line-block:: + The second step uses PyDPF-Core to generate the cycles to failure result: + The locally saved .rst file is imported and plotted. + Then the von Mises stress is generated and plotted with DPF operators. + The NumPy python package is then used to interpolate the cycles to failure values. + The nodal von Mises equivalent stress value is used in the interpolation. + (Note that the cycles to failure data must be manipulated to use NumPy interpolation) + An empty field is then created and filled with the resulting cycles to failure values. + The cycles to failure result is finally plotted. + +The cycles to failure result is the (interpolated) negative of the stress result. +The higher the stress result, the lower the number of cycles to failure. +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +import numpy as np + +############################################################################### +# The first step is to generate a simple model with high stress + +# # Material parameters from Ansys Mechanical Structural Steel +youngsSteel = 200e9 +prxySteel = 0.3 +sn_data = np.empty((11, 2)) # initialize empty np matrix +sn_data[:, 0] = [10, 20, 50, 100, 200, 2000, 10000, 20000, 1e5, 2e5, 1e6] +sn_data[:, 1] = [ + 3.999e9, + 2.8327e9, + 1.896e9, + 1.413e9, + 1.069e9, + 4.41e8, + 2.62e8, + 2.14e8, + 1.38e8, + 1.14e8, + 8.62e7, +] + +############################################################################### +# The .rst file used is already available, but can be obtained using the short pyMAPDL code below: + +# # ### Launch pymapdl to generate rst file in myDir +# from ansys.mapdl.core import launch_mapdl +# import os +# +# +# mapdl = launch_mapdl() +# mapdl.prep7() +# # Model +# mapdl.cylind(0.5, 0, 10, 0) +# mapdl.mp("EX", 1, youngsSteel) +# mapdl.mp("PRXY", 1, prxySteel) +# mapdl.mshape(key=1, dimension='3d') +# mapdl.et(1, "SOLID186") +# mapdl.esize(0.3) +# mapdl.vmesh('ALL') +# +# # #### Boundary Conditions: fixed constraint +# mapdl.nsel(type_='S', item='LOC', comp='Z', vmin=0) +# mapdl.d("all", "all") +# mapdl.nsel(type_='S', item='LOC', comp='Z', vmin=10) +# nnodes = mapdl.get("NumNodes", "NODE", 0, "COUNT") +# mapdl.f(node="ALL", lab="fy", value=-13e6 / nnodes) +# mapdl.allsel() +# +# # #### Solve +# mapdl.run("/SOLU") +# sol_output = mapdl.solve() +# rst = os.path.join(mapdl.directory, 'file.rst') +# mapdl.exit() +# print('apdl model solved.') + +############################################################################### +# PyDPF-Core is then used to post-process the .rst file to estimate the cycles to failure. + +# Comment the following line if solving the MAPDL problem first. +rst = examples.download_cycles_to_failure() + +# Import the result as a DPF Model object. +model = dpf.Model(rst) +print(model) + +############################################################################### +# Get the von mises equivalent stress, requires an operator. +s_eqv_op = dpf.operators.result.stress_von_mises(data_sources=model) +vm_stress_fc = s_eqv_op.eval() +vm_stress_field = vm_stress_fc[0] +vm_stress_field.plot(text="VM stress field") + +############################################################################### +# Use NumPy to interpolate the results. + +# Inverse the sn_data +x_values = sn_data[:, 1][::-1] # the x values are the stress ranges in ascending order +y_values = sn_data[:, 0][::-1] # y values are inverted cycles to failure + +# Interpolate cycles to failure for the VM values +cycles_to_failure = np.interp(vm_stress_field.data, x_values, y_values) + +############################################################################### +# Generate a cycles_to_failure DPF Field + +# Create an empty field +cycles_to_failure_field = dpf.Field( + nentities=len(vm_stress_field.scoping), + nature=dpf.natures.scalar, + location=dpf.locations.nodal, +) +# Populate the field +cycles_to_failure_field.scoping = vm_stress_field.scoping +cycles_to_failure_field.meshed_region = vm_stress_field.meshed_region +cycles_to_failure_field.data = cycles_to_failure + +# Plot the field +sargs = dict(title="cycles", fmt="%.2e") +cycles_to_failure_field.plot(text="Cycles to failure", scalar_bar_args=sargs) diff --git a/doc/source/examples/04-advanced/11-cycles_to_failure.py.md5 b/doc/source/examples/04-advanced/11-cycles_to_failure.py.md5 new file mode 100644 index 0000000000..a0d7017f9c --- /dev/null +++ b/doc/source/examples/04-advanced/11-cycles_to_failure.py.md5 @@ -0,0 +1 @@ +6eb301abe84b516d39267c4133256c1f \ No newline at end of file diff --git a/doc/source/examples/04-advanced/11-cycles_to_failure.rst b/doc/source/examples/04-advanced/11-cycles_to_failure.rst new file mode 100644 index 0000000000..14ce012781 --- /dev/null +++ b/doc/source/examples/04-advanced/11-cycles_to_failure.rst @@ -0,0 +1,322 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\11-cycles_to_failure.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_11-cycles_to_failure.py: + + +.. _ref_cycles_to_failure: + +Calculate the number of cycles to fatigue failure +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to generate and use a result file to calculate the +cycles to failure result for a simple model. + +Material data is manually imported, Structural Steel from Ansys Mechanical: + +- Youngs Modulus (youngsSteel) +- Poisson's Ratio (prxySteel) +- SN curve (sn_data) + +The first step is to generate a simple model with high stress and save the +results .rst file locally to myDir (default is "C:\\temp"). +For this, we provide a short pyMAPDL script. + +.. line-block:: + The second step uses PyDPF-Core to generate the cycles to failure result: + The locally saved .rst file is imported and plotted. + Then the von Mises stress is generated and plotted with DPF operators. + The NumPy python package is then used to interpolate the cycles to failure values. + The nodal von Mises equivalent stress value is used in the interpolation. + (Note that the cycles to failure data must be manipulated to use NumPy interpolation) + An empty field is then created and filled with the resulting cycles to failure values. + The cycles to failure result is finally plotted. + +The cycles to failure result is the (interpolated) negative of the stress result. +The higher the stress result, the lower the number of cycles to failure. + +.. GENERATED FROM PYTHON SOURCE LINES 33-38 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + import numpy as np + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 39-40 + +The first step is to generate a simple model with high stress + +.. GENERATED FROM PYTHON SOURCE LINES 40-60 + +.. code-block:: default + + + # # Material parameters from Ansys Mechanical Structural Steel + youngsSteel = 200e9 + prxySteel = 0.3 + sn_data = np.empty((11, 2)) # initialize empty np matrix + sn_data[:, 0] = [10, 20, 50, 100, 200, 2000, 10000, 20000, 1e5, 2e5, 1e6] + sn_data[:, 1] = [ + 3.999e9, + 2.8327e9, + 1.896e9, + 1.413e9, + 1.069e9, + 4.41e8, + 2.62e8, + 2.14e8, + 1.38e8, + 1.14e8, + 8.62e7, + ] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 61-62 + +The .rst file used is already available, but can be obtained using the short pyMAPDL code below: + +.. GENERATED FROM PYTHON SOURCE LINES 62-94 + +.. code-block:: default + + + # # ### Launch pymapdl to generate rst file in myDir + # from ansys.mapdl.core import launch_mapdl + # import os + # + # + # mapdl = launch_mapdl() + # mapdl.prep7() + # # Model + # mapdl.cylind(0.5, 0, 10, 0) + # mapdl.mp("EX", 1, youngsSteel) + # mapdl.mp("PRXY", 1, prxySteel) + # mapdl.mshape(key=1, dimension='3d') + # mapdl.et(1, "SOLID186") + # mapdl.esize(0.3) + # mapdl.vmesh('ALL') + # + # # #### Boundary Conditions: fixed constraint + # mapdl.nsel(type_='S', item='LOC', comp='Z', vmin=0) + # mapdl.d("all", "all") + # mapdl.nsel(type_='S', item='LOC', comp='Z', vmin=10) + # nnodes = mapdl.get("NumNodes", "NODE", 0, "COUNT") + # mapdl.f(node="ALL", lab="fy", value=-13e6 / nnodes) + # mapdl.allsel() + # + # # #### Solve + # mapdl.run("/SOLU") + # sol_output = mapdl.solve() + # rst = os.path.join(mapdl.directory, 'file.rst') + # mapdl.exit() + # print('apdl model solved.') + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 95-96 + +PyDPF-Core is then used to post-process the .rst file to estimate the cycles to failure. + +.. GENERATED FROM PYTHON SOURCE LINES 96-104 + +.. code-block:: default + + + # Comment the following line if solving the MAPDL problem first. + rst = examples.download_cycles_to_failure() + + # Import the result as a DPF Model object. + model = dpf.Model(rst) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: Undefined + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - element_nodal_forces: ElementalNodal Element nodal Forces + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - thermal_strain: ElementalNodal Thermal Strains + - thermal_strains_eqv: ElementalNodal Thermal Strains eqv + - swelling_strains: ElementalNodal Swelling Strains + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 4102 nodes + 2356 elements + Unit: + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1 + Cumulative Time (s) LoadStep Substep + 1 1,000000 1 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 105-106 + +Get the von mises equivalent stress, requires an operator. + +.. GENERATED FROM PYTHON SOURCE LINES 106-111 + +.. code-block:: default + + s_eqv_op = dpf.operators.result.stress_von_mises(data_sources=model) + vm_stress_fc = s_eqv_op.eval() + vm_stress_field = vm_stress_fc[0] + vm_stress_field.plot(text="VM stress field") + + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_11-cycles_to_failure_001.png + :alt: 11 cycles to failure + :srcset: /examples/04-advanced/images/sphx_glr_11-cycles_to_failure_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 112-113 + +Use NumPy to interpolate the results. + +.. GENERATED FROM PYTHON SOURCE LINES 113-121 + +.. code-block:: default + + + # Inverse the sn_data + x_values = sn_data[:, 1][::-1] # the x values are the stress ranges in ascending order + y_values = sn_data[:, 0][::-1] # y values are inverted cycles to failure + + # Interpolate cycles to failure for the VM values + cycles_to_failure = np.interp(vm_stress_field.data, x_values, y_values) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 122-123 + +Generate a cycles_to_failure DPF Field + +.. GENERATED FROM PYTHON SOURCE LINES 123-138 + +.. code-block:: default + + + # Create an empty field + cycles_to_failure_field = dpf.Field( + nentities=len(vm_stress_field.scoping), + nature=dpf.natures.scalar, + location=dpf.locations.nodal, + ) + # Populate the field + cycles_to_failure_field.scoping = vm_stress_field.scoping + cycles_to_failure_field.meshed_region = vm_stress_field.meshed_region + cycles_to_failure_field.data = cycles_to_failure + + # Plot the field + sargs = dict(title="cycles", fmt="%.2e") + cycles_to_failure_field.plot(text="Cycles to failure", scalar_bar_args=sargs) + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_11-cycles_to_failure_002.png + :alt: 11 cycles to failure + :srcset: /examples/04-advanced/images/sphx_glr_11-cycles_to_failure_002.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 2.817 seconds) + + +.. _sphx_glr_download_examples_04-advanced_11-cycles_to_failure.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 11-cycles_to_failure.py <11-cycles_to_failure.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 11-cycles_to_failure.ipynb <11-cycles_to_failure.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/11-cycles_to_failure_codeobj.pickle b/doc/source/examples/04-advanced/11-cycles_to_failure_codeobj.pickle new file mode 100644 index 0000000000..affaa4e724 Binary files /dev/null and b/doc/source/examples/04-advanced/11-cycles_to_failure_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/12-read_distributed_files.ipynb b/doc/source/examples/04-advanced/12-read_distributed_files.ipynb new file mode 100644 index 0000000000..8dcd6fdb5e --- /dev/null +++ b/doc/source/examples/04-advanced/12-read_distributed_files.ipynb @@ -0,0 +1,108 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Read results from distributed files {#ref_distributed_files}\r\n\r\nSolvers usually solve analysis with distributed architecture. In this\r\ncase, one file is written by spatial or temporal domains. DPF is capable\r\nof reading one result in distributed files. This allows it to skip the\r\nmerging of files on the solver side, which is time-consuming and often\r\ndoubles the memory used.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create the data sources\r\n\r\nFirst create a data sources with one result file by domain\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "distributed_file_path = examples.download_distributed_files()\ndata_sources = dpf.DataSources()\ndata_sources.set_domain_result_file_path(distributed_file_path[0], 0)\ndata_sources.set_domain_result_file_path(distributed_file_path[1], 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compute displacements\r\n\r\nOnce the file architecture is put in the data sources, computing\r\ndisplacements with or without domain has the exact same syntax. DPF\r\nreads parts of the result on each domain and merges these results in the\r\noutputs fields. The output is no different than when using combined or\r\ndistributed files.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(data_sources)\ndisp = model.results.displacement.on_all_time_freqs.eval()\n\nfreq_scoping = disp.get_time_scoping()\nfor freq_set in freq_scoping:\n model.metadata.meshed_region.plot(disp.get_field_by_time_complex_ids(freq_set, 0))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compute equivalent stress\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "stress_res = model.results.stress\nstress_res.on_location(dpf.locations.nodal)\nstress = stress_res.on_all_time_freqs.eval()\n\nfreq_scoping = stress.get_time_scoping()\nfor freq_set in freq_scoping:\n model.metadata.meshed_region.plot(stress.get_field_by_time_complex_ids(freq_set, 0))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/12-read_distributed_files.py b/doc/source/examples/04-advanced/12-read_distributed_files.py new file mode 100644 index 0000000000..15dfee6b19 --- /dev/null +++ b/doc/source/examples/04-advanced/12-read_distributed_files.py @@ -0,0 +1,52 @@ +""" +.. _ref_distributed_files: + +Read results from distributed files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Solvers usually solve analysis with distributed architecture. In this +case, one file is written by spatial or temporal domains. DPF is capable +of reading one result in distributed files. This allows it to skip the +merging of files on the solver side, which is time-consuming and +often doubles the memory used. +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +############################################################################### +# Create the data sources +# ~~~~~~~~~~~~~~~~~~~~~~~ +# First create a data sources with one result file by domain + +distributed_file_path = examples.download_distributed_files() +data_sources = dpf.DataSources() +data_sources.set_domain_result_file_path(distributed_file_path[0], 0) +data_sources.set_domain_result_file_path(distributed_file_path[1], 1) + +############################################################################### +# Compute displacements +# ~~~~~~~~~~~~~~~~~~~~~ +# Once the file architecture is put in the data sources, +# computing displacements with or without domain has the exact same syntax. +# DPF reads parts of the result on each domain and merges these results in +# the outputs fields. The output is no different than when using combined +# or distributed files. + +model = dpf.Model(data_sources) +disp = model.results.displacement.on_all_time_freqs.eval() + +freq_scoping = disp.get_time_scoping() +for freq_set in freq_scoping: + model.metadata.meshed_region.plot(disp.get_field_by_time_complex_ids(freq_set, 0)) + +############################################################################### +# Compute equivalent stress +# ~~~~~~~~~~~~~~~~~~~~~~~~~ +stress_res = model.results.stress +stress_res.on_location(dpf.locations.nodal) +stress = stress_res.on_all_time_freqs.eval() + +freq_scoping = stress.get_time_scoping() +for freq_set in freq_scoping: + model.metadata.meshed_region.plot(stress.get_field_by_time_complex_ids(freq_set, 0)) diff --git a/doc/source/examples/04-advanced/12-read_distributed_files.py.md5 b/doc/source/examples/04-advanced/12-read_distributed_files.py.md5 new file mode 100644 index 0000000000..340ea1591f --- /dev/null +++ b/doc/source/examples/04-advanced/12-read_distributed_files.py.md5 @@ -0,0 +1 @@ +adf24448ef333778c830579487b90f73 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/12-read_distributed_files.rst b/doc/source/examples/04-advanced/12-read_distributed_files.rst new file mode 100644 index 0000000000..f349a6d5d5 --- /dev/null +++ b/doc/source/examples/04-advanced/12-read_distributed_files.rst @@ -0,0 +1,238 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\12-read_distributed_files.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_12-read_distributed_files.py: + + +.. _ref_distributed_files: + +Read results from distributed files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Solvers usually solve analysis with distributed architecture. In this +case, one file is written by spatial or temporal domains. DPF is capable +of reading one result in distributed files. This allows it to skip the +merging of files on the solver side, which is time-consuming and +often doubles the memory used. + +.. GENERATED FROM PYTHON SOURCE LINES 13-17 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 18-21 + +Create the data sources +~~~~~~~~~~~~~~~~~~~~~~~ +First create a data sources with one result file by domain + +.. GENERATED FROM PYTHON SOURCE LINES 21-27 + +.. code-block:: default + + + distributed_file_path = examples.download_distributed_files() + data_sources = dpf.DataSources() + data_sources.set_domain_result_file_path(distributed_file_path[0], 0) + data_sources.set_domain_result_file_path(distributed_file_path[1], 1) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 28-35 + +Compute displacements +~~~~~~~~~~~~~~~~~~~~~ +Once the file architecture is put in the data sources, +computing displacements with or without domain has the exact same syntax. +DPF reads parts of the result on each domain and merges these results in +the outputs fields. The output is no different than when using combined +or distributed files. + +.. GENERATED FROM PYTHON SOURCE LINES 35-43 + +.. code-block:: default + + + model = dpf.Model(data_sources) + disp = model.results.displacement.on_all_time_freqs.eval() + + freq_scoping = disp.get_time_scoping() + for freq_set in freq_scoping: + model.metadata.meshed_region.plot(disp.get_field_by_time_complex_ids(freq_set, 0)) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_001.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_002.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_003.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_004.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_005.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_005.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_006.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_006.png + :class: sphx-glr-multi-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 44-46 + +Compute equivalent stress +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 46-53 + +.. code-block:: default + + stress_res = model.results.stress + stress_res.on_location(dpf.locations.nodal) + stress = stress_res.on_all_time_freqs.eval() + + freq_scoping = stress.get_time_scoping() + for freq_set in freq_scoping: + model.metadata.meshed_region.plot(stress.get_field_by_time_complex_ids(freq_set, 0)) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_007.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_007.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_008.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_008.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_009.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_009.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_010.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_010.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_011.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_011.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_012.png + :alt: 12 read distributed files + :srcset: /examples/04-advanced/images/sphx_glr_12-read_distributed_files_012.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 7.173 seconds) + + +.. _sphx_glr_download_examples_04-advanced_12-read_distributed_files.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 12-read_distributed_files.py <12-read_distributed_files.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 12-read_distributed_files.ipynb <12-read_distributed_files.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/12-read_distributed_files_codeobj.pickle b/doc/source/examples/04-advanced/12-read_distributed_files_codeobj.pickle new file mode 100644 index 0000000000..5815e5cd87 Binary files /dev/null and b/doc/source/examples/04-advanced/12-read_distributed_files_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/13-manage_licensing.ipynb b/doc/source/examples/04-advanced/13-manage_licensing.ipynb new file mode 100644 index 0000000000..0165cc15c2 --- /dev/null +++ b/doc/source/examples/04-advanced/13-manage_licensing.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Manage the DPF licensing logic using the server context {#ref_manage_licensing}\r\n\r\nThis example shows how to manage the licensing logic of a DPF server\r\nusing a [ServerContext]{.title-ref}.\r\n\r\nYou can prevent DPF from checking licenses out and blocking increments\r\nby using the **Entry** context.\r\n\r\n::: warning\r\n::: title\r\nWarning\r\n:::\r\n\r\nYou cannot start a new `InProcess` server, as starting an `InProcess`\r\nserver means linking the DPF binaries to your current Python process. If\r\nyour local `InProcess` server is already set to **Premium**, you cannot\r\nset it back to **Entry**. Since `InProcess` is the default server type,\r\nput the commands to set the **Entry** server context at the start of\r\nyour script.\r\n:::\r\n\r\n::: note\r\n::: title\r\nNote\r\n:::\r\n\r\nThis example requires DPF 6.1 (Ansys 2023R2) or above. For more\r\ninformation, see `ref_compatibility`{.interpreted-text role=\"ref\"}.\r\n:::\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import necessary modules\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core.core import errors" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Start a server as Entry to prevent using licensed operators\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "server = dpf.start_local_server(\n context=dpf.AvailableServerContexts.entry,\n config=dpf.AvailableServerConfigs.GrpcServer,\n as_global=False,\n)\n# The context is shown as Entry\nprint(server.context)\n\n# A server of type InProcess being linked to the current Python process,\n# if an InProcess server already exists as Premium, you cannot set it back as Entry." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a dummy Field\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field = dpf.Field(server=server)\nfield.append([0.0, 0.0, 0.0], 1)\nprint(field)\n\n# Instantiate an Entry (not licensed) DPF operator\nop_entry = dpf.operators.math.add_constant(field=field, ponderation=2.0, server=server)\n\n# Instantiate a Premium (licensed) DPF operator\nop_premium = dpf.operators.filter.field_high_pass(field=field, threshold=0.0, server=server)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Operators with the Entry context\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Using unlicensed DPF operators is possible\nout = op_entry.eval()\nprint(out)\n\n# While using license ones is blocked, raising an error\ntry:\n op_premium.eval()\nexcept errors.DPFServerException as e:\n print(e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Operators with the Premium context\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Set the default server context as Premium for new servers\ndpf.set_default_server_context(dpf.AvailableServerContexts.premium)\n# or in our case, apply the Premium context to the current server\nserver.apply_context(dpf.AvailableServerContexts.premium)\n\n# Licensed operators can now check a license out and run\nout = op_premium.eval()\nprint(out)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When Premium, using a LicenseContextManaged allows you to control your\r\ninteraction with a license It gives direct control over when the license\r\ncheck-out and check-in occur, as well as which license increment is\r\nused, and for what maximum duration.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Use the LicenseContextManager to block a specific increment for a limited duration\nwith dpf.LicenseContextManager(increment_name=\"preppost\", license_timeout_in_seconds=1.0) as lic:\n # Instantiate the licensed operator\n out = op_premium.eval()\n print(out)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/13-manage_licensing.py b/doc/source/examples/04-advanced/13-manage_licensing.py new file mode 100644 index 0000000000..b3f3de62ab --- /dev/null +++ b/doc/source/examples/04-advanced/13-manage_licensing.py @@ -0,0 +1,87 @@ +""" +.. _ref_manage_licensing: + +Manage the DPF licensing logic using the server context +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to manage the licensing logic of a DPF server using a `ServerContext`. + +You can prevent DPF from checking licenses out and blocking increments by using the +**Entry** context. + +.. warning:: + You cannot start a new ``InProcess`` server, as starting an ``InProcess`` server means linking + the DPF binaries to your current Python process. If your local ``InProcess`` server is already + set to **Premium**, you cannot set it back to **Entry**. + Since ``InProcess`` is the default server type, put the commands to set the **Entry** server + context at the start of your script. + +.. note:: + This example requires DPF 6.1 (Ansys 2023R2) or above. + For more information, see :ref:`ref_compatibility`. + +""" +# Import necessary modules +from ansys.dpf import core as dpf +from ansys.dpf.core.core import errors + +####################################################################################### +# Start a server as Entry to prevent using licensed operators +server = dpf.start_local_server( + context=dpf.AvailableServerContexts.entry, + config=dpf.AvailableServerConfigs.GrpcServer, + as_global=False, +) +# The context is shown as Entry +print(server.context) + +# A server of type InProcess being linked to the current Python process, +# if an InProcess server already exists as Premium, you cannot set it back as Entry. + +####################################################################################### +# Create a dummy Field +field = dpf.Field(server=server) +field.append([0.0, 0.0, 0.0], 1) +print(field) + +# Instantiate an Entry (not licensed) DPF operator +op_entry = dpf.operators.math.add_constant(field=field, ponderation=2.0, server=server) + +# Instantiate a Premium (licensed) DPF operator +op_premium = dpf.operators.filter.field_high_pass(field=field, threshold=0.0, server=server) + +####################################################################################### +# Operators with the Entry context + +# Using unlicensed DPF operators is possible +out = op_entry.eval() +print(out) + +# While using license ones is blocked, raising an error +try: + op_premium.eval() +except errors.DPFServerException as e: + print(e) + +####################################################################################### +# Operators with the Premium context + +# Set the default server context as Premium for new servers +dpf.set_default_server_context(dpf.AvailableServerContexts.premium) +# or in our case, apply the Premium context to the current server +server.apply_context(dpf.AvailableServerContexts.premium) + +# Licensed operators can now check a license out and run +out = op_premium.eval() +print(out) + +################################################################################################### +# When Premium, using a LicenseContextManaged allows you to control your interaction with a license +# It gives direct control over when the license check-out and check-in occur, as well as which +# license increment is used, and for what maximum duration. + +# Use the LicenseContextManager to block a specific increment for a limited duration +with dpf.LicenseContextManager(increment_name="preppost", license_timeout_in_seconds=1.0) as lic: + # Instantiate the licensed operator + out = op_premium.eval() + print(out) diff --git a/doc/source/examples/04-advanced/13-manage_licensing.py.md5 b/doc/source/examples/04-advanced/13-manage_licensing.py.md5 new file mode 100644 index 0000000000..da3722694d --- /dev/null +++ b/doc/source/examples/04-advanced/13-manage_licensing.py.md5 @@ -0,0 +1 @@ +26dbba743dd1af214f021f62841a7a58 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/13-manage_licensing.rst b/doc/source/examples/04-advanced/13-manage_licensing.rst new file mode 100644 index 0000000000..c43dfcea70 --- /dev/null +++ b/doc/source/examples/04-advanced/13-manage_licensing.rst @@ -0,0 +1,271 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\13-manage_licensing.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_13-manage_licensing.py: + + +.. _ref_manage_licensing: + +Manage the DPF licensing logic using the server context +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to manage the licensing logic of a DPF server using a `ServerContext`. + +You can prevent DPF from checking licenses out and blocking increments by using the +**Entry** context. + +.. warning:: + You cannot start a new ``InProcess`` server, as starting an ``InProcess`` server means linking + the DPF binaries to your current Python process. If your local ``InProcess`` server is already + set to **Premium**, you cannot set it back to **Entry**. + Since ``InProcess`` is the default server type, put the commands to set the **Entry** server + context at the start of your script. + +.. note:: + This example requires DPF 6.1 (Ansys 2023R2) or above. + For more information, see :ref:`ref_compatibility`. + +.. GENERATED FROM PYTHON SOURCE LINES 24-28 + +.. code-block:: default + + # Import necessary modules + from ansys.dpf import core as dpf + from ansys.dpf.core.core import errors + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 29-30 + +Start a server as Entry to prevent using licensed operators + +.. GENERATED FROM PYTHON SOURCE LINES 30-41 + +.. code-block:: default + + server = dpf.start_local_server( + context=dpf.AvailableServerContexts.entry, + config=dpf.AvailableServerConfigs.GrpcServer, + as_global=False, + ) + # The context is shown as Entry + print(server.context) + + # A server of type InProcess being linked to the current Python process, + # if an InProcess server already exists as Premium, you cannot set it back as Entry. + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Server Context of type LicensingContextType.entry with no xml path + + + + +.. GENERATED FROM PYTHON SOURCE LINES 42-43 + +Create a dummy Field + +.. GENERATED FROM PYTHON SOURCE LINES 43-53 + +.. code-block:: default + + field = dpf.Field(server=server) + field.append([0.0, 0.0, 0.0], 1) + print(field) + + # Instantiate an Entry (not licensed) DPF operator + op_entry = dpf.operators.math.add_constant(field=field, ponderation=2.0, server=server) + + # Instantiate a Premium (licensed) DPF operator + op_premium = dpf.operators.filter.field_high_pass(field=field, threshold=0.0, server=server) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Field + Location: Nodal + Unit: + 1 entities + Data: 3 components and 1 elementary data + + IDs data + ------------ ---------- + 1 0.000000e+00 0.000000e+00 0.000000e+00 + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 54-55 + +Operators with the Entry context + +.. GENERATED FROM PYTHON SOURCE LINES 55-66 + +.. code-block:: default + + + # Using unlicensed DPF operators is possible + out = op_entry.eval() + print(out) + + # While using license ones is blocked, raising an error + try: + op_premium.eval() + except errors.DPFServerException as e: + print(e) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Field + Location: Nodal + Unit: + 1 entities + Data: 3 components and 1 elementary data + + IDs data + ------------ ---------- + 1 2.000000e+00 2.000000e+00 2.000000e+00 + + + + a data processing core error error ocurred: DPF issue due to licensing context: execution stopped. Apply Premium context to unlock this capability. + + + + +.. GENERATED FROM PYTHON SOURCE LINES 67-68 + +Operators with the Premium context + +.. GENERATED FROM PYTHON SOURCE LINES 68-78 + +.. code-block:: default + + + # Set the default server context as Premium for new servers + dpf.set_default_server_context(dpf.AvailableServerContexts.premium) + # or in our case, apply the Premium context to the current server + server.apply_context(dpf.AvailableServerContexts.premium) + + # Licensed operators can now check a license out and run + out = op_premium.eval() + print(out) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Field + Location: Nodal + Unit: + 0 entities + Data: 3 components and 0 elementary data + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 79-82 + +When Premium, using a LicenseContextManaged allows you to control your interaction with a license +It gives direct control over when the license check-out and check-in occur, as well as which +license increment is used, and for what maximum duration. + +.. GENERATED FROM PYTHON SOURCE LINES 82-88 + +.. code-block:: default + + + # Use the LicenseContextManager to block a specific increment for a limited duration + with dpf.LicenseContextManager(increment_name="preppost", license_timeout_in_seconds=1.0) as lic: + # Instantiate the licensed operator + out = op_premium.eval() + print(out) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Field + Location: Nodal + Unit: + 0 entities + Data: 3 components and 0 elementary data + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 1.840 seconds) + + +.. _sphx_glr_download_examples_04-advanced_13-manage_licensing.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 13-manage_licensing.py <13-manage_licensing.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 13-manage_licensing.ipynb <13-manage_licensing.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/13-manage_licensing_codeobj.pickle b/doc/source/examples/04-advanced/13-manage_licensing_codeobj.pickle new file mode 100644 index 0000000000..e2d03e7ac9 Binary files /dev/null and b/doc/source/examples/04-advanced/13-manage_licensing_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/14-incremental_evaluation.ipynb b/doc/source/examples/04-advanced/14-incremental_evaluation.ipynb new file mode 100644 index 0000000000..59e7bdb7ab --- /dev/null +++ b/doc/source/examples/04-advanced/14-incremental_evaluation.ipynb @@ -0,0 +1,108 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use incremental evaluation helper {#ref_incremental_evaluation}\r\n\r\nThis example shows you how to use the incremental evaluation helper.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Import necessary modules\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Retrieve an example to instantiate a DataSources object\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "path = examples.download_transient_result()\nds = dpf.DataSources(path)\n\n# From the DataSources object we can retrieve the scoping\n# In this example we want to compute the min/max for all the time sets\ntf_provider = dpf.operators.metadata.time_freq_provider(data_sources=ds)\ntf_support = tf_provider.get_output(output_type=dpf.types.time_freq_support)\nscoping = dpf.time_freq_scoping_factory.scoping_on_all_time_freqs(tf_support)\n\n# If you don't need to reuse TimeFreqSupport you could also use the DataSources\n# scoping = dpf.time_freq_scoping_factory.scoping_on_all_time_freqs(ds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Defining the workflow to exploit\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Instantiating a streams_provider is important when dealing with incremental evaluation\n# due to multiple reuses of operators\nstreams_provider = dpf.operators.metadata.streams_provider(data_sources=ds)\n\n# Defining the main workflow\nresult_op = dpf.operators.result.stress(\n data_sources=ds, time_scoping=scoping, streams_container=streams_provider\n)\nnorm_fc = dpf.operators.math.norm_fc(result_op)\nfinal_op = dpf.operators.min_max.min_max_fc_inc(norm_fc)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Obtain a new operator to retrieve outputs from\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Workflow is adapted from the first and the last operator in the current workflow\n# Scoping is important to split the workload into chunks\nnew_end_op = dpf.split_workflow_in_chunks(result_op, final_op, scoping)\n\n\n# Obtain results on the same pin numbers\nmin = new_end_op.get_output(0, dpf.types.field)\nmax = new_end_op.get_output(1, dpf.types.field)\n\n# Plot results\nimport matplotlib.pyplot as plt\n\nx = tf_support.time_frequencies.data\nplt.plot(x, min.data, \"b\", label=\"Min\")\nplt.plot(x, max.data, \"r\", label=\"Max\")\nplt.xlabel(\"Time\")\nplt.ylabel(\"Stress\")\nplt.legend()\nplt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/04-advanced/14-incremental_evaluation.py b/doc/source/examples/04-advanced/14-incremental_evaluation.py new file mode 100644 index 0000000000..60ab0a2f8a --- /dev/null +++ b/doc/source/examples/04-advanced/14-incremental_evaluation.py @@ -0,0 +1,64 @@ +""" +.. _ref_incremental_evaluation: + +Use incremental evaluation helper +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows you how to use the incremental evaluation helper. +""" + +# Import necessary modules +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + + +####################################################################################### +# Retrieve an example to instantiate a DataSources object +path = examples.download_transient_result() +ds = dpf.DataSources(path) + +# From the DataSources object we can retrieve the scoping +# In this example we want to compute the min/max for all the time sets +tf_provider = dpf.operators.metadata.time_freq_provider(data_sources=ds) +tf_support = tf_provider.get_output(output_type=dpf.types.time_freq_support) +scoping = dpf.time_freq_scoping_factory.scoping_on_all_time_freqs(tf_support) + +# If you don't need to reuse TimeFreqSupport you could also use the DataSources +# scoping = dpf.time_freq_scoping_factory.scoping_on_all_time_freqs(ds) + +####################################################################################### +# Defining the workflow to exploit + +# Instantiating a streams_provider is important when dealing with incremental evaluation +# due to multiple reuses of operators +streams_provider = dpf.operators.metadata.streams_provider(data_sources=ds) + +# Defining the main workflow +result_op = dpf.operators.result.stress( + data_sources=ds, time_scoping=scoping, streams_container=streams_provider +) +norm_fc = dpf.operators.math.norm_fc(result_op) +final_op = dpf.operators.min_max.min_max_fc_inc(norm_fc) + +####################################################################################### +# Obtain a new operator to retrieve outputs from + +# Workflow is adapted from the first and the last operator in the current workflow +# Scoping is important to split the workload into chunks +new_end_op = dpf.split_workflow_in_chunks(result_op, final_op, scoping) + + +# Obtain results on the same pin numbers +min = new_end_op.get_output(0, dpf.types.field) +max = new_end_op.get_output(1, dpf.types.field) + +# Plot results +import matplotlib.pyplot as plt + +x = tf_support.time_frequencies.data +plt.plot(x, min.data, "b", label="Min") +plt.plot(x, max.data, "r", label="Max") +plt.xlabel("Time") +plt.ylabel("Stress") +plt.legend() +plt.show() diff --git a/doc/source/examples/04-advanced/14-incremental_evaluation.py.md5 b/doc/source/examples/04-advanced/14-incremental_evaluation.py.md5 new file mode 100644 index 0000000000..ce7e07dd21 --- /dev/null +++ b/doc/source/examples/04-advanced/14-incremental_evaluation.py.md5 @@ -0,0 +1 @@ +006f4b059a74b0a9866be2e0d32d58b3 \ No newline at end of file diff --git a/doc/source/examples/04-advanced/14-incremental_evaluation.rst b/doc/source/examples/04-advanced/14-incremental_evaluation.rst new file mode 100644 index 0000000000..a42b07d519 --- /dev/null +++ b/doc/source/examples/04-advanced/14-incremental_evaluation.rst @@ -0,0 +1,172 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\04-advanced\14-incremental_evaluation.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_04-advanced_14-incremental_evaluation.py: + + +.. _ref_incremental_evaluation: + +Use incremental evaluation helper +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows you how to use the incremental evaluation helper. + +.. GENERATED FROM PYTHON SOURCE LINES 9-15 + +.. code-block:: default + + + # Import necessary modules + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 16-17 + +Retrieve an example to instantiate a DataSources object + +.. GENERATED FROM PYTHON SOURCE LINES 17-29 + +.. code-block:: default + + path = examples.download_transient_result() + ds = dpf.DataSources(path) + + # From the DataSources object we can retrieve the scoping + # In this example we want to compute the min/max for all the time sets + tf_provider = dpf.operators.metadata.time_freq_provider(data_sources=ds) + tf_support = tf_provider.get_output(output_type=dpf.types.time_freq_support) + scoping = dpf.time_freq_scoping_factory.scoping_on_all_time_freqs(tf_support) + + # If you don't need to reuse TimeFreqSupport you could also use the DataSources + # scoping = dpf.time_freq_scoping_factory.scoping_on_all_time_freqs(ds) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 30-31 + +Defining the workflow to exploit + +.. GENERATED FROM PYTHON SOURCE LINES 31-43 + +.. code-block:: default + + + # Instantiating a streams_provider is important when dealing with incremental evaluation + # due to multiple reuses of operators + streams_provider = dpf.operators.metadata.streams_provider(data_sources=ds) + + # Defining the main workflow + result_op = dpf.operators.result.stress( + data_sources=ds, time_scoping=scoping, streams_container=streams_provider + ) + norm_fc = dpf.operators.math.norm_fc(result_op) + final_op = dpf.operators.min_max.min_max_fc_inc(norm_fc) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 44-45 + +Obtain a new operator to retrieve outputs from + +.. GENERATED FROM PYTHON SOURCE LINES 45-65 + +.. code-block:: default + + + # Workflow is adapted from the first and the last operator in the current workflow + # Scoping is important to split the workload into chunks + new_end_op = dpf.split_workflow_in_chunks(result_op, final_op, scoping) + + + # Obtain results on the same pin numbers + min = new_end_op.get_output(0, dpf.types.field) + max = new_end_op.get_output(1, dpf.types.field) + + # Plot results + import matplotlib.pyplot as plt + + x = tf_support.time_frequencies.data + plt.plot(x, min.data, "b", label="Min") + plt.plot(x, max.data, "r", label="Max") + plt.xlabel("Time") + plt.ylabel("Stress") + plt.legend() + plt.show() + + + +.. image-sg:: /examples/04-advanced/images/sphx_glr_14-incremental_evaluation_001.png + :alt: 14 incremental evaluation + :srcset: /examples/04-advanced/images/sphx_glr_14-incremental_evaluation_001.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Estimating chunk_size with max_bytes: 1073741824 + Done. chunk_size set to 35 (scoping size: 35) + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.327 seconds) + + +.. _sphx_glr_download_examples_04-advanced_14-incremental_evaluation.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 14-incremental_evaluation.py <14-incremental_evaluation.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 14-incremental_evaluation.ipynb <14-incremental_evaluation.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/04-advanced/14-incremental_evaluation_codeobj.pickle b/doc/source/examples/04-advanced/14-incremental_evaluation_codeobj.pickle new file mode 100644 index 0000000000..d5b4849ef5 Binary files /dev/null and b/doc/source/examples/04-advanced/14-incremental_evaluation_codeobj.pickle differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_001.png b/doc/source/examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_001.png new file mode 100644 index 0000000000..7fa7dfb967 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_002.png b/doc/source/examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_002.png new file mode 100644 index 0000000000..3c4bc05025 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_00-multistage_advanced_options_002.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_001.png b/doc/source/examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_001.png new file mode 100644 index 0000000000..5c220a65d7 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_002.png b/doc/source/examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_002.png new file mode 100644 index 0000000000..ac5ab5a8f5 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_01-solve_harmonic_problem_002.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_001.png b/doc/source/examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_001.png new file mode 100644 index 0000000000..01e284b055 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_002.png b/doc/source/examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_002.png new file mode 100644 index 0000000000..be91a7f484 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_002.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_003.png b/doc/source/examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_003.png new file mode 100644 index 0000000000..054d468c1c Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_02-volume_averaged_stress_003.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_001.png b/doc/source/examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_001.png new file mode 100644 index 0000000000..b58a8a9a02 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_002.png b/doc/source/examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_002.png new file mode 100644 index 0000000000..75accd39f6 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_03-exchange_data_between_servers_002.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_001.png b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_001.png new file mode 100644 index 0000000000..f9ad29247c Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_002.png b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_002.png new file mode 100644 index 0000000000..60a0b71847 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_002.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_003.png b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_003.png new file mode 100644 index 0000000000..665ffe0593 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_003.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_004.png b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_004.png new file mode 100644 index 0000000000..f20fbdde87 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_004.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_005.png b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_005.png new file mode 100644 index 0000000000..9864d2910d Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_04-extrapolation_stress_3d_005.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_001.png b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_001.png new file mode 100644 index 0000000000..5482eb50a3 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_002.png b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_002.png new file mode 100644 index 0000000000..ca71dd72f0 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_002.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_003.png b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_003.png new file mode 100644 index 0000000000..84cd5e7325 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_003.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_004.png b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_004.png new file mode 100644 index 0000000000..bec2de8188 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_004.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_005.png b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_005.png new file mode 100644 index 0000000000..4d567d16e8 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_05-extrapolation_strain_2d_005.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_06-stress_gradient_path_001.png b/doc/source/examples/04-advanced/images/sphx_glr_06-stress_gradient_path_001.png new file mode 100644 index 0000000000..a9e21a24c5 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_06-stress_gradient_path_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_06-stress_gradient_path_002.png b/doc/source/examples/04-advanced/images/sphx_glr_06-stress_gradient_path_002.png new file mode 100644 index 0000000000..f75b041db9 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_06-stress_gradient_path_002.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_10-asme_secviii_divtwo_001.png b/doc/source/examples/04-advanced/images/sphx_glr_10-asme_secviii_divtwo_001.png new file mode 100644 index 0000000000..5c67cbf33c Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_10-asme_secviii_divtwo_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_11-cycles_to_failure_001.png b/doc/source/examples/04-advanced/images/sphx_glr_11-cycles_to_failure_001.png new file mode 100644 index 0000000000..4e0c35742a Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_11-cycles_to_failure_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_11-cycles_to_failure_002.png b/doc/source/examples/04-advanced/images/sphx_glr_11-cycles_to_failure_002.png new file mode 100644 index 0000000000..56d68d6134 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_11-cycles_to_failure_002.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_001.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_001.png new file mode 100644 index 0000000000..4a94977e19 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_001.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_002.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_002.png new file mode 100644 index 0000000000..9a8ed1255e Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_002.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_003.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_003.png new file mode 100644 index 0000000000..66c7f53a98 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_003.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_004.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_004.png new file mode 100644 index 0000000000..cc56d40e17 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_004.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_005.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_005.png new file mode 100644 index 0000000000..380898bd15 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_005.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_006.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_006.png new file mode 100644 index 0000000000..0f38dc0c31 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_006.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_007.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_007.png new file mode 100644 index 0000000000..4178d43f0d Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_007.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_008.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_008.png new file mode 100644 index 0000000000..615b6af3e0 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_008.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_009.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_009.png new file mode 100644 index 0000000000..4fd3f5ad81 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_009.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_010.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_010.png new file mode 100644 index 0000000000..c5309145ca Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_010.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_011.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_011.png new file mode 100644 index 0000000000..79018e1841 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_011.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_012.png b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_012.png new file mode 100644 index 0000000000..3c1b15cba6 Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_12-read_distributed_files_012.png differ diff --git a/doc/source/examples/04-advanced/images/sphx_glr_14-incremental_evaluation_001.png b/doc/source/examples/04-advanced/images/sphx_glr_14-incremental_evaluation_001.png new file mode 100644 index 0000000000..09286fa03c Binary files /dev/null and b/doc/source/examples/04-advanced/images/sphx_glr_14-incremental_evaluation_001.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_00-multistage_advanced_options_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_00-multistage_advanced_options_thumb.png new file mode 100644 index 0000000000..f250ba3e9b Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_00-multistage_advanced_options_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_01-solve_harmonic_problem_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_01-solve_harmonic_problem_thumb.png new file mode 100644 index 0000000000..7896ec55ab Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_01-solve_harmonic_problem_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_02-volume_averaged_stress_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_02-volume_averaged_stress_thumb.png new file mode 100644 index 0000000000..046f67a581 Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_02-volume_averaged_stress_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_03-exchange_data_between_servers_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_03-exchange_data_between_servers_thumb.png new file mode 100644 index 0000000000..33488811ce Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_03-exchange_data_between_servers_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_04-extrapolation_stress_3d_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_04-extrapolation_stress_3d_thumb.png new file mode 100644 index 0000000000..c31b7f29cb Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_04-extrapolation_stress_3d_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_05-extrapolation_strain_2d_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_05-extrapolation_strain_2d_thumb.png new file mode 100644 index 0000000000..57ff9b7841 Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_05-extrapolation_strain_2d_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_06-stress_gradient_path_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_06-stress_gradient_path_thumb.png new file mode 100644 index 0000000000..66f6792d8b Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_06-stress_gradient_path_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_07-load_plugin_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_07-load_plugin_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_07-load_plugin_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_10-asme_secviii_divtwo_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_10-asme_secviii_divtwo_thumb.png new file mode 100644 index 0000000000..e059805067 Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_10-asme_secviii_divtwo_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_11-cycles_to_failure_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_11-cycles_to_failure_thumb.png new file mode 100644 index 0000000000..9e8a4a05c4 Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_11-cycles_to_failure_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_12-read_distributed_files_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_12-read_distributed_files_thumb.png new file mode 100644 index 0000000000..715123e9c3 Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_12-read_distributed_files_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_13-manage_licensing_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_13-manage_licensing_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_13-manage_licensing_thumb.png differ diff --git a/doc/source/examples/04-advanced/images/thumb/sphx_glr_14-incremental_evaluation_thumb.png b/doc/source/examples/04-advanced/images/thumb/sphx_glr_14-incremental_evaluation_thumb.png new file mode 100644 index 0000000000..4f829aa49b Binary files /dev/null and b/doc/source/examples/04-advanced/images/thumb/sphx_glr_14-incremental_evaluation_thumb.png differ diff --git a/doc/source/examples/04-advanced/index.rst b/doc/source/examples/04-advanced/index.rst new file mode 100644 index 0000000000..b6292f0059 --- /dev/null +++ b/doc/source/examples/04-advanced/index.rst @@ -0,0 +1,260 @@ + + +.. _sphx_glr_examples_04-advanced: + +.. _advanced_examples: + +Advanced and miscellaneous examples +=================================== +These examples show advanced use cases to demonstrate the high level of workflow customization. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_00-multistage_advanced_options_thumb.png + :alt: Multi-stage cyclic symmetry using advanced customization + + :ref:`sphx_glr_examples_04-advanced_00-multistage_advanced_options.py` + +.. raw:: html + +
Multi-stage cyclic symmetry using advanced customization
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_01-solve_harmonic_problem_thumb.png + :alt: Solve harmonic problem (with damping) using matrix inverse + + :ref:`sphx_glr_examples_04-advanced_01-solve_harmonic_problem.py` + +.. raw:: html + +
Solve harmonic problem (with damping) using matrix inverse
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_02-volume_averaged_stress_thumb.png + :alt: Average elemental stress on a given volume + + :ref:`sphx_glr_examples_04-advanced_02-volume_averaged_stress.py` + +.. raw:: html + +
Average elemental stress on a given volume
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_03-exchange_data_between_servers_thumb.png + :alt: Exchange data between servers + + :ref:`sphx_glr_examples_04-advanced_03-exchange_data_between_servers.py` + +.. raw:: html + +
Exchange data between servers
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_04-extrapolation_stress_3d_thumb.png + :alt: Extrapolation method for stress result of a 3D element + + :ref:`sphx_glr_examples_04-advanced_04-extrapolation_stress_3d.py` + +.. raw:: html + +
Extrapolation method for stress result of a 3D element
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_05-extrapolation_strain_2d_thumb.png + :alt: Extrapolation method for strain result of a 2D element + + :ref:`sphx_glr_examples_04-advanced_05-extrapolation_strain_2d.py` + +.. raw:: html + +
Extrapolation method for strain result of a 2D element
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_06-stress_gradient_path_thumb.png + :alt: Stress gradient normal to a defined node + + :ref:`sphx_glr_examples_04-advanced_06-stress_gradient_path.py` + +.. raw:: html + +
Stress gradient normal to a defined node
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_07-load_plugin_thumb.png + :alt: Load plugin + + :ref:`sphx_glr_examples_04-advanced_07-load_plugin.py` + +.. raw:: html + +
Load plugin
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_10-asme_secviii_divtwo_thumb.png + :alt: Pressure vessel analysis according to an ASME standard + + :ref:`sphx_glr_examples_04-advanced_10-asme_secviii_divtwo.py` + +.. raw:: html + +
Pressure vessel analysis according to an ASME standard
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_11-cycles_to_failure_thumb.png + :alt: Calculate the number of cycles to fatigue failure + + :ref:`sphx_glr_examples_04-advanced_11-cycles_to_failure.py` + +.. raw:: html + +
Calculate the number of cycles to fatigue failure
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_12-read_distributed_files_thumb.png + :alt: Read results from distributed files + + :ref:`sphx_glr_examples_04-advanced_12-read_distributed_files.py` + +.. raw:: html + +
Read results from distributed files
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_13-manage_licensing_thumb.png + :alt: Manage the DPF licensing logic using the server context + + :ref:`sphx_glr_examples_04-advanced_13-manage_licensing.py` + +.. raw:: html + +
Manage the DPF licensing logic using the server context
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_14-incremental_evaluation_thumb.png + :alt: Use incremental evaluation helper + + :ref:`sphx_glr_examples_04-advanced_14-incremental_evaluation.py` + +.. raw:: html + +
Use incremental evaluation helper
+
+ + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /examples/04-advanced/00-multistage_advanced_options + /examples/04-advanced/01-solve_harmonic_problem + /examples/04-advanced/02-volume_averaged_stress + /examples/04-advanced/03-exchange_data_between_servers + /examples/04-advanced/04-extrapolation_stress_3d + /examples/04-advanced/05-extrapolation_strain_2d + /examples/04-advanced/06-stress_gradient_path + /examples/04-advanced/07-load_plugin + /examples/04-advanced/10-asme_secviii_divtwo + /examples/04-advanced/11-cycles_to_failure + /examples/04-advanced/12-read_distributed_files + /examples/04-advanced/13-manage_licensing + /examples/04-advanced/14-incremental_evaluation + diff --git a/doc/source/examples/04-advanced/sg_execution_times.rst b/doc/source/examples/04-advanced/sg_execution_times.rst new file mode 100644 index 0000000000..ae06318960 --- /dev/null +++ b/doc/source/examples/04-advanced/sg_execution_times.rst @@ -0,0 +1,36 @@ + +:orphan: + +.. _sphx_glr_examples_04-advanced_sg_execution_times: + +Computation times +================= +**00:34.504** total execution time for **examples_04-advanced** files: + ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_12-read_distributed_files.py` (``12-read_distributed_files.py``) | 00:07.173 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_05-extrapolation_strain_2d.py` (``05-extrapolation_strain_2d.py``) | 00:04.634 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_04-extrapolation_stress_3d.py` (``04-extrapolation_stress_3d.py``) | 00:04.446 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_03-exchange_data_between_servers.py` (``03-exchange_data_between_servers.py``) | 00:04.434 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_02-volume_averaged_stress.py` (``02-volume_averaged_stress.py``) | 00:03.061 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_10-asme_secviii_divtwo.py` (``10-asme_secviii_divtwo.py``) | 00:02.984 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_11-cycles_to_failure.py` (``11-cycles_to_failure.py``) | 00:02.817 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_13-manage_licensing.py` (``13-manage_licensing.py``) | 00:01.840 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_00-multistage_advanced_options.py` (``00-multistage_advanced_options.py``) | 00:01.292 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_06-stress_gradient_path.py` (``06-stress_gradient_path.py``) | 00:01.270 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_14-incremental_evaluation.py` (``14-incremental_evaluation.py``) | 00:00.327 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_01-solve_harmonic_problem.py` (``01-solve_harmonic_problem.py``) | 00:00.212 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_04-advanced_07-load_plugin.py` (``07-load_plugin.py``) | 00:00.013 | 0.0 MB | ++--------------------------------------------------------------------------------------------------------------------+-----------+--------+ diff --git a/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.ipynb b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.ipynb new file mode 100644 index 0000000000..d94afde10c --- /dev/null +++ b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.ipynb @@ -0,0 +1,223 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# HDF5 export and compare precision {#ref_basic_hdf5}\r\n\r\nThis example shows how to use HDF5 format to export and compare simple\r\nprecision versus double precision.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import the `dpf-core` module and its examples files, and then create a\r\ntemporary directory.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the model and get the stresses, displacements, and mesh.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "transient = examples.download_transient_result()\nmodel = dpf.Model(transient)\n\nstress = model.results.stress()\ndisplacement = model.results.displacement()\nmesh = model.metadata.meshed_region" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the HDF5 export operator. The HDF5 module should already be\r\nloaded.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "h5op = ops.serialization.serialize_to_hdf5()\nprint(h5op)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Connect the correct time scoping to the results operators (stress and\r\ndisplacement).\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "timeIds = list(range(1, model.metadata.time_freq_support.n_sets + 1))\n\nstress.inputs.time_scoping.connect(timeIds)\ndisplacement.inputs.time_scoping.connect(timeIds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Connect inputs of the HDF5 export operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "h5op.inputs.data1.connect(stress.outputs)\nh5op.inputs.data2.connect(displacement.outputs)\nh5op.inputs.data3.connect(mesh)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Define a temporary folder for outputs\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "tmpdir = dpf.core.make_tmp_dir_server(dpf.SERVER)\nfiles = [\n dpf.path_utilities.join(tmpdir, \"dpf_float.h5\"),\n dpf.path_utilities.join(tmpdir, \"dpf_double.h5\"),\n]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Export with simple precision.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "h5op.inputs.file_path.connect(files[0])\nh5op.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Export with double precision.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "h5op.inputs.export_floats.connect(False)\nh5op.inputs.file_path.connect(files[1])\nh5op.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Download the resulting .h5 files if necessary\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "if not dpf.SERVER.local_server:\n float_file_path = os.path.join(os.getcwd(), \"dpf_float.h5\")\n double_file_path = os.path.join(os.getcwd(), \"dpf_double.h5\")\n dpf.download_file(files[0], float_file_path)\n dpf.download_file(files[1], double_file_path)\nelse:\n float_file_path = files[0]\n double_file_path = files[1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compare simple precision versus double precision.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "float_precision = os.stat(float_file_path).st_size\ndouble_precision = os.stat(double_file_path).st_size\nprint(\n f\"size with float precision: {float_precision}\\n\"\n f\"size with double precision: {double_precision}\"\n)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.py b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.py new file mode 100644 index 0000000000..1df96bf3e3 --- /dev/null +++ b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.py @@ -0,0 +1,95 @@ +# noqa: D400 +""" +.. _ref_basic_hdf5: + +HDF5 export and compare precision +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to use HDF5 format to export and +compare simple precision versus double precision. + +""" + +############################################################################### +# Import the ``dpf-core`` module and its examples files, and then create a +# temporary directory. + +import os + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + +############################################################################### +# Create the model and get the stresses, displacements, and mesh. + +transient = examples.download_transient_result() +model = dpf.Model(transient) + +stress = model.results.stress() +displacement = model.results.displacement() +mesh = model.metadata.meshed_region + +############################################################################### +# Create the HDF5 export operator. The HDF5 module should already be loaded. + +h5op = ops.serialization.serialize_to_hdf5() +print(h5op) + +############################################################################### +# Connect the correct time scoping to the results operators (stress +# and displacement). + +timeIds = list(range(1, model.metadata.time_freq_support.n_sets + 1)) + +stress.inputs.time_scoping.connect(timeIds) +displacement.inputs.time_scoping.connect(timeIds) + +############################################################################### +# Connect inputs of the HDF5 export operator. + +h5op.inputs.data1.connect(stress.outputs) +h5op.inputs.data2.connect(displacement.outputs) +h5op.inputs.data3.connect(mesh) + +############################################################################### +# Define a temporary folder for outputs +tmpdir = dpf.core.make_tmp_dir_server(dpf.SERVER) +files = [ + dpf.path_utilities.join(tmpdir, "dpf_float.h5"), + dpf.path_utilities.join(tmpdir, "dpf_double.h5"), +] +############################################################################### +# Export with simple precision. + +h5op.inputs.file_path.connect(files[0]) +h5op.run() + +############################################################################### +# Export with double precision. + +h5op.inputs.export_floats.connect(False) +h5op.inputs.file_path.connect(files[1]) +h5op.run() + +############################################################################### +# Download the resulting .h5 files if necessary + +if not dpf.SERVER.local_server: + float_file_path = os.path.join(os.getcwd(), "dpf_float.h5") + double_file_path = os.path.join(os.getcwd(), "dpf_double.h5") + dpf.download_file(files[0], float_file_path) + dpf.download_file(files[1], double_file_path) +else: + float_file_path = files[0] + double_file_path = files[1] + + +############################################################################### +# Compare simple precision versus double precision. +float_precision = os.stat(float_file_path).st_size +double_precision = os.stat(double_file_path).st_size +print( + f"size with float precision: {float_precision}\n" + f"size with double precision: {double_precision}" +) diff --git a/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.py.md5 b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.py.md5 new file mode 100644 index 0000000000..b98cd83066 --- /dev/null +++ b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.py.md5 @@ -0,0 +1 @@ +c31b34e1962caaedaf5eee6c4225c83f \ No newline at end of file diff --git a/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.rst b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.rst new file mode 100644 index 0000000000..fa7c0cd1df --- /dev/null +++ b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison.rst @@ -0,0 +1,289 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\05-file-IO\00-hdf5_double_float_comparison.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_05-file-IO_00-hdf5_double_float_comparison.py: + + +.. _ref_basic_hdf5: + +HDF5 export and compare precision +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to use HDF5 format to export and +compare simple precision versus double precision. + +.. GENERATED FROM PYTHON SOURCE LINES 14-16 + +Import the ``dpf-core`` module and its examples files, and then create a +temporary directory. + +.. GENERATED FROM PYTHON SOURCE LINES 16-23 + +.. code-block:: default + + + import os + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 24-25 + +Create the model and get the stresses, displacements, and mesh. + +.. GENERATED FROM PYTHON SOURCE LINES 25-33 + +.. code-block:: default + + + transient = examples.download_transient_result() + model = dpf.Model(transient) + + stress = model.results.stress() + displacement = model.results.displacement() + mesh = model.metadata.meshed_region + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 34-35 + +Create the HDF5 export operator. The HDF5 module should already be loaded. + +.. GENERATED FROM PYTHON SOURCE LINES 35-39 + +.. code-block:: default + + + h5op = ops.serialization.serialize_to_hdf5() + print(h5op) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF serialize_to_hdf5 Operator: + This operator is deprecated: use 'hdf5::h5dpf::make_result_file' instead. Serialize the inputs in an hdf5 format. + Inputs: + file_path [string]: output file path with .h5 extension + export_floats (optional) [bool]: converts double to float to reduce file size (default is true) + export_flat_vectors (optional) [bool]: if true, vectors and matrices data are exported flat (x1,y1,z1,x2,y2,z2..) (default is false) + data (ellipsis) []: only the data set explicitly to export is exported + Run the operator to get its result + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 40-42 + +Connect the correct time scoping to the results operators (stress +and displacement). + +.. GENERATED FROM PYTHON SOURCE LINES 42-48 + +.. code-block:: default + + + timeIds = list(range(1, model.metadata.time_freq_support.n_sets + 1)) + + stress.inputs.time_scoping.connect(timeIds) + displacement.inputs.time_scoping.connect(timeIds) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 49-50 + +Connect inputs of the HDF5 export operator. + +.. GENERATED FROM PYTHON SOURCE LINES 50-55 + +.. code-block:: default + + + h5op.inputs.data1.connect(stress.outputs) + h5op.inputs.data2.connect(displacement.outputs) + h5op.inputs.data3.connect(mesh) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 56-57 + +Define a temporary folder for outputs + +.. GENERATED FROM PYTHON SOURCE LINES 57-62 + +.. code-block:: default + + tmpdir = dpf.core.make_tmp_dir_server(dpf.SERVER) + files = [ + dpf.path_utilities.join(tmpdir, "dpf_float.h5"), + dpf.path_utilities.join(tmpdir, "dpf_double.h5"), + ] + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 63-64 + +Export with simple precision. + +.. GENERATED FROM PYTHON SOURCE LINES 64-68 + +.. code-block:: default + + + h5op.inputs.file_path.connect(files[0]) + h5op.run() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 69-70 + +Export with double precision. + +.. GENERATED FROM PYTHON SOURCE LINES 70-75 + +.. code-block:: default + + + h5op.inputs.export_floats.connect(False) + h5op.inputs.file_path.connect(files[1]) + h5op.run() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 76-77 + +Download the resulting .h5 files if necessary + +.. GENERATED FROM PYTHON SOURCE LINES 77-88 + +.. code-block:: default + + + if not dpf.SERVER.local_server: + float_file_path = os.path.join(os.getcwd(), "dpf_float.h5") + double_file_path = os.path.join(os.getcwd(), "dpf_double.h5") + dpf.download_file(files[0], float_file_path) + dpf.download_file(files[1], double_file_path) + else: + float_file_path = files[0] + double_file_path = files[1] + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 89-90 + +Compare simple precision versus double precision. + +.. GENERATED FROM PYTHON SOURCE LINES 90-96 + +.. code-block:: default + + float_precision = os.stat(float_file_path).st_size + double_precision = os.stat(double_file_path).st_size + print( + f"size with float precision: {float_precision}\n" + f"size with double precision: {double_precision}" + ) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + size with float precision: 6703264 + size with double precision: 13112464 + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.209 seconds) + + +.. _sphx_glr_download_examples_05-file-IO_00-hdf5_double_float_comparison.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 00-hdf5_double_float_comparison.py <00-hdf5_double_float_comparison.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 00-hdf5_double_float_comparison.ipynb <00-hdf5_double_float_comparison.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison_codeobj.pickle b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison_codeobj.pickle new file mode 100644 index 0000000000..4d52d2672e Binary files /dev/null and b/doc/source/examples/05-file-IO/00-hdf5_double_float_comparison_codeobj.pickle differ diff --git a/doc/source/examples/05-file-IO/01-reduced_matrices_export.ipynb b/doc/source/examples/05-file-IO/01-reduced_matrices_export.ipynb new file mode 100644 index 0000000000..476d17a659 --- /dev/null +++ b/doc/source/examples/05-file-IO/01-reduced_matrices_export.ipynb @@ -0,0 +1,151 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get reduced matrices and make export {#ref_reduced_matrices_export}\r\n\r\nThis example shows how to get reduced matrices and export them to HDF5\r\nand CSV files.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import the `dpf-core` module and its examples files, and then create a\r\ntemporary directory.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the operator and connect data sources.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "ds = dpf.DataSources(examples.download_sub_file())\n\nmatrices_provider = ops.result.cms_matrices_provider()\nmatrices_provider.inputs.data_sources.connect(ds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get result fields container that contains the reduced matrices.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "fields = matrices_provider.outputs.fields_container()\n\nlen(fields)\n\nfields[0].data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Define a temporary folder for outputs\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "tmpdir = dpf.core.make_tmp_dir_server(dpf.SERVER)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Export the result fields container to an HDF5 file.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "h5_op = ops.serialization.serialize_to_hdf5()\nh5_op.inputs.data1.connect(matrices_provider.outputs)\nh5_op.inputs.file_path.connect(dpf.path_utilities.join(tmpdir, \"matrices.h5\"))\nh5_op.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Export the result fields container to a CSV file.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "csv_op = ops.serialization.field_to_csv()\ncsv_op.inputs.field_or_fields_container.connect(matrices_provider.outputs)\ncsv_op.inputs.file_path.connect(dpf.path_utilities.join(tmpdir, \"matrices.csv\"))\ncsv_op.run()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/05-file-IO/01-reduced_matrices_export.py b/doc/source/examples/05-file-IO/01-reduced_matrices_export.py new file mode 100644 index 0000000000..bb56862c88 --- /dev/null +++ b/doc/source/examples/05-file-IO/01-reduced_matrices_export.py @@ -0,0 +1,55 @@ +""" +.. _ref_reduced_matrices_export: + +Get reduced matrices and make export +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to get reduced matrices and +export them to HDF5 and CSV files. + +""" + +############################################################################### +# Import the ``dpf-core`` module and its examples files, and then create a +# temporary directory. + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + +############################################################################### +# Create the operator and connect data sources. + +ds = dpf.DataSources(examples.download_sub_file()) + +matrices_provider = ops.result.cms_matrices_provider() +matrices_provider.inputs.data_sources.connect(ds) + +############################################################################### +# Get result fields container that contains the reduced matrices. + +fields = matrices_provider.outputs.fields_container() + +len(fields) + +fields[0].data + +############################################################################### +# Define a temporary folder for outputs +tmpdir = dpf.core.make_tmp_dir_server(dpf.SERVER) + +############################################################################### +# Export the result fields container to an HDF5 file. + +h5_op = ops.serialization.serialize_to_hdf5() +h5_op.inputs.data1.connect(matrices_provider.outputs) +h5_op.inputs.file_path.connect(dpf.path_utilities.join(tmpdir, "matrices.h5")) +h5_op.run() + +############################################################################### +# Export the result fields container to a CSV file. + +csv_op = ops.serialization.field_to_csv() +csv_op.inputs.field_or_fields_container.connect(matrices_provider.outputs) +csv_op.inputs.file_path.connect(dpf.path_utilities.join(tmpdir, "matrices.csv")) +csv_op.run() diff --git a/doc/source/examples/05-file-IO/01-reduced_matrices_export.py.md5 b/doc/source/examples/05-file-IO/01-reduced_matrices_export.py.md5 new file mode 100644 index 0000000000..c417f0fb19 --- /dev/null +++ b/doc/source/examples/05-file-IO/01-reduced_matrices_export.py.md5 @@ -0,0 +1 @@ +48373e3513d2973b78f44fa9efcb1730 \ No newline at end of file diff --git a/doc/source/examples/05-file-IO/01-reduced_matrices_export.rst b/doc/source/examples/05-file-IO/01-reduced_matrices_export.rst new file mode 100644 index 0000000000..f161ec8b99 --- /dev/null +++ b/doc/source/examples/05-file-IO/01-reduced_matrices_export.rst @@ -0,0 +1,184 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\05-file-IO\01-reduced_matrices_export.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_05-file-IO_01-reduced_matrices_export.py: + + +.. _ref_reduced_matrices_export: + +Get reduced matrices and make export +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to get reduced matrices and +export them to HDF5 and CSV files. + +.. GENERATED FROM PYTHON SOURCE LINES 13-15 + +Import the ``dpf-core`` module and its examples files, and then create a +temporary directory. + +.. GENERATED FROM PYTHON SOURCE LINES 15-20 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 21-22 + +Create the operator and connect data sources. + +.. GENERATED FROM PYTHON SOURCE LINES 22-28 + +.. code-block:: default + + + ds = dpf.DataSources(examples.download_sub_file()) + + matrices_provider = ops.result.cms_matrices_provider() + matrices_provider.inputs.data_sources.connect(ds) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 29-30 + +Get result fields container that contains the reduced matrices. + +.. GENERATED FROM PYTHON SOURCE LINES 30-37 + +.. code-block:: default + + + fields = matrices_provider.outputs.fields_container() + + len(fields) + + fields[0].data + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + DPFArray([[ 5.53476768e+11, -2.29728435e+10, 2.29728435e+10, ..., + 0.00000000e+00, 0.00000000e+00, 2.91225427e+05]]) + + + +.. GENERATED FROM PYTHON SOURCE LINES 38-39 + +Define a temporary folder for outputs + +.. GENERATED FROM PYTHON SOURCE LINES 39-41 + +.. code-block:: default + + tmpdir = dpf.core.make_tmp_dir_server(dpf.SERVER) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 42-43 + +Export the result fields container to an HDF5 file. + +.. GENERATED FROM PYTHON SOURCE LINES 43-49 + +.. code-block:: default + + + h5_op = ops.serialization.serialize_to_hdf5() + h5_op.inputs.data1.connect(matrices_provider.outputs) + h5_op.inputs.file_path.connect(dpf.path_utilities.join(tmpdir, "matrices.h5")) + h5_op.run() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 50-51 + +Export the result fields container to a CSV file. + +.. GENERATED FROM PYTHON SOURCE LINES 51-56 + +.. code-block:: default + + + csv_op = ops.serialization.field_to_csv() + csv_op.inputs.field_or_fields_container.connect(matrices_provider.outputs) + csv_op.inputs.file_path.connect(dpf.path_utilities.join(tmpdir, "matrices.csv")) + csv_op.run() + + + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 1.292 seconds) + + +.. _sphx_glr_download_examples_05-file-IO_01-reduced_matrices_export.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 01-reduced_matrices_export.py <01-reduced_matrices_export.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 01-reduced_matrices_export.ipynb <01-reduced_matrices_export.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/05-file-IO/01-reduced_matrices_export_codeobj.pickle b/doc/source/examples/05-file-IO/01-reduced_matrices_export_codeobj.pickle new file mode 100644 index 0000000000..6b4619ced5 Binary files /dev/null and b/doc/source/examples/05-file-IO/01-reduced_matrices_export_codeobj.pickle differ diff --git a/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.ipynb b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.ipynb new file mode 100644 index 0000000000..c96812e72d --- /dev/null +++ b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.ipynb @@ -0,0 +1,266 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# HDF5 export and import operations {#ref_basic_hdf5}\r\n\r\nThis example shows you how to use the HDF5 format to export results and\r\nmeshed regions in an H5 file. It also demonstrates how to read results\r\nand meshed regions from the created H5 file.\r\n\r\nFirst, it exports all the results for all time frequencies, then it\r\nexports all the time sets for the results, per time set. Finally, it\r\nreads the results and compares them. For the example to run correctly,\r\nensure you do not have an existing H5 file.\r\n\r\n::: note\r\n::: title\r\nNote\r\n:::\r\n\r\nThis example requires DPF 7.0 (ansys-dpf-server-2024-1-pre0) or above.\r\nFor more information, see `ref_compatibility`{.interpreted-text\r\nrole=\"ref\"}.\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Import modules, instantiate model and create temporary folder\r\n\r\nImport the `dpf-core` module and its examples files.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import ansys.dpf.core as dpf\nfrom ansys.dpf.core import examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instantiate the model and the provider operators:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.download_transient_result())\nstreams_cont = model.metadata.streams_provider.outputs.streams_container\ntime_freq_op = dpf.operators.metadata.time_freq_provider(streams_container=streams_cont)\ntime_freq_support = time_freq_op.outputs.time_freq_support()\ntime_freqs = time_freq_support.time_frequencies\n\nresult_names_on_all_time_steps = []\nresult_names_time_per_time = []\n\nnum_res = len(model.results)\nnum_sets = len(time_freqs.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Define a temporary folder for outputs:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "tmpdir = dpf.core.make_tmp_dir_server(dpf.SERVER)\nfiles = [\n dpf.path_utilities.join(tmpdir, \"file_on_all_time_steps.h5\"),\n dpf.path_utilities.join(tmpdir, \"file_time_per_time.h5\"),\n]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use H5 serialization operator\r\n\r\nExport all results on all time frequencies:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "h5_serialization_op_all_times = dpf.operators.serialization.hdf5dpf_generate_result_file()\nh5_serialization_op_all_times.inputs.filename.connect(files[0])\nh5_serialization_op_all_times.inputs.mesh_provider_out.connect(model.metadata.meshed_region)\nh5_serialization_op_all_times.inputs.time_freq_support_out.connect(time_freq_support)\n\nfor i, res in enumerate(model.results):\n res_name = \"result_\" + res().name\n result_names_on_all_time_steps.append(res_name)\n h5_serialization_op_all_times.connect(2 * i + 4, res_name)\n h5_serialization_op_all_times.connect(2 * i + 5, res.on_all_time_freqs())\n\nh5_all_times_ds = h5_serialization_op_all_times.outputs.data_sources()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Export all the results, time set per time set:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "h5_serialization_op_set_per_set = dpf.operators.serialization.hdf5dpf_generate_result_file()\nh5_serialization_op_set_per_set.inputs.filename.connect(files[1])\nh5_serialization_op_set_per_set.inputs.mesh_provider_out.connect(model.metadata.meshed_region)\nh5_serialization_op_set_per_set.inputs.time_freq_support_out.connect(time_freq_support)\n\nfor j, freq in enumerate(time_freqs.data):\n for i, res in enumerate(model.results):\n res_name = \"result_\" + res().name + \"_time_\" + str(freq)\n result_names_time_per_time.append(res_name)\n h5_serialization_op_set_per_set.connect(2 * (j * num_res + i) + 4, res_name)\n h5_serialization_op_set_per_set.connect(\n 2 * (j * num_res + i) + 5, res.on_time_scoping(j + 1).eval()\n )\n\nh5_set_per_set_ds = h5_serialization_op_set_per_set.outputs.data_sources()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use H5 reading operator\r\n\r\nRead the results from all time steps files:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "h5_stream_prov_op = dpf.operators.metadata.streams_provider()\nh5_stream_prov_op.inputs.data_sources.connect(h5_all_times_ds)\nres_deser_all_times_list = []\nh5_read_op = dpf.operators.serialization.hdf5dpf_custom_read()\nh5_read_op.inputs.streams.connect(h5_stream_prov_op.outputs)\nfor i, res_name in enumerate(result_names_on_all_time_steps):\n h5_read_op.inputs.result_name.connect(res_name)\n res_deser = h5_read_op.outputs.field_or_fields_container_as_fields_container()\n res_deser_all_times_list.append(res_deser)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read the meshed region from all time steps file:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh_prov_op = dpf.operators.mesh.mesh_provider()\nmesh_prov_op.inputs.streams_container.connect(h5_stream_prov_op.outputs)\nmesh_deser_all_times = mesh_prov_op.outputs.mesh()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read the results from the time set per set file:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "h5_stream_prov_op_2 = dpf.operators.metadata.streams_provider()\nh5_stream_prov_op_2.inputs.data_sources.connect(h5_set_per_set_ds)\nres_deser_set_per_set_list = []\nh5_read_op_2 = dpf.operators.serialization.hdf5dpf_custom_read()\nh5_read_op_2.inputs.streams.connect(h5_stream_prov_op_2.outputs)\nfor i, res_name in enumerate(result_names_time_per_time):\n h5_read_op_2.inputs.result_name.connect(res_name)\n res_deser = h5_read_op_2.outputs.field_or_fields_container_as_fields_container()\n res_deser_set_per_set_list.append(res_deser)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read the meshed region from all time steps files:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh_prov_op_2 = dpf.operators.mesh.mesh_provider()\nmesh_prov_op_2.inputs.streams_container.connect(h5_stream_prov_op_2.outputs)\nmesh_deser_set_per_set = mesh_prov_op_2.outputs.mesh()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compare results\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print global data:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"Number of results is: \" + str(num_res))\nprint(\"Number of time sets is: \" + str(num_sets))\nprint(\"Results names for 'all time steps' file: \")\nprint(result_names_on_all_time_steps)\nprint(\"Results names for 'set per set' file: \")\nprint(result_names_time_per_time)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "compare first result at second time set:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "fc_all_steps_first_step_first_res = res_deser_all_times_list[0].get_field_by_time_id(2) # set 1\nmesh_deser_all_times.plot(fc_all_steps_first_step_first_res)\n\nmesh_deser_set_per_set.plot(res_deser_set_per_set_list[num_res * 1 + 0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "compare 4th result at 6 time set:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "to_nodal_op = dpf.operators.averaging.to_nodal_fc()\n\nfc_all_steps_first_step_first_res = res_deser_all_times_list[3].get_field_by_time_id(6) # set 6\nmesh_deser_all_times.plot(\n dpf.operators.averaging.to_nodal(fc_all_steps_first_step_first_res).outputs.field()\n)\n\nmesh_deser_set_per_set.plot(\n dpf.operators.averaging.to_nodal(res_deser_set_per_set_list[num_res * 5 + 3]).outputs.field()\n)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.py b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.py new file mode 100644 index 0000000000..54fc91bde8 --- /dev/null +++ b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.py @@ -0,0 +1,158 @@ +""" +.. _ref_basic_hdf5: + +HDF5 export and import operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows you how to use the HDF5 format to export results +and meshed regions in an H5 file. +It also demonstrates how to read results and meshed regions from the +created H5 file. + +First, it exports all the results for all time frequencies, +then it exports all the time sets for the results, per time set. +Finally, it reads the results and compares them. +For the example to run correctly, ensure you do not have an existing H5 file. + +.. note:: + This example requires DPF 7.0 (ansys-dpf-server-2024-1-pre0) or above. + For more information, see :ref:`ref_compatibility`. + +""" + +############################################################################### +# Import modules, instantiate model and create temporary folder +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Import the ``dpf-core`` module and its examples files. + +import ansys.dpf.core as dpf +from ansys.dpf.core import examples + +############################################################################### +# Instantiate the model and the provider operators: + +model = dpf.Model(examples.download_transient_result()) +streams_cont = model.metadata.streams_provider.outputs.streams_container +time_freq_op = dpf.operators.metadata.time_freq_provider(streams_container=streams_cont) +time_freq_support = time_freq_op.outputs.time_freq_support() +time_freqs = time_freq_support.time_frequencies + +result_names_on_all_time_steps = [] +result_names_time_per_time = [] + +num_res = len(model.results) +num_sets = len(time_freqs.data) + +############################################################################### +# Define a temporary folder for outputs: +tmpdir = dpf.core.make_tmp_dir_server(dpf.SERVER) +files = [ + dpf.path_utilities.join(tmpdir, "file_on_all_time_steps.h5"), + dpf.path_utilities.join(tmpdir, "file_time_per_time.h5"), +] + +############################################################################### +# Use H5 serialization operator +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Export all results on all time frequencies: +h5_serialization_op_all_times = dpf.operators.serialization.hdf5dpf_generate_result_file() +h5_serialization_op_all_times.inputs.filename.connect(files[0]) +h5_serialization_op_all_times.inputs.mesh_provider_out.connect(model.metadata.meshed_region) +h5_serialization_op_all_times.inputs.time_freq_support_out.connect(time_freq_support) + +for i, res in enumerate(model.results): + res_name = "result_" + res().name + result_names_on_all_time_steps.append(res_name) + h5_serialization_op_all_times.connect(2 * i + 4, res_name) + h5_serialization_op_all_times.connect(2 * i + 5, res.on_all_time_freqs()) + +h5_all_times_ds = h5_serialization_op_all_times.outputs.data_sources() + +############################################################################### +# Export all the results, time set per time set: +h5_serialization_op_set_per_set = dpf.operators.serialization.hdf5dpf_generate_result_file() +h5_serialization_op_set_per_set.inputs.filename.connect(files[1]) +h5_serialization_op_set_per_set.inputs.mesh_provider_out.connect(model.metadata.meshed_region) +h5_serialization_op_set_per_set.inputs.time_freq_support_out.connect(time_freq_support) + +for j, freq in enumerate(time_freqs.data): + for i, res in enumerate(model.results): + res_name = "result_" + res().name + "_time_" + str(freq) + result_names_time_per_time.append(res_name) + h5_serialization_op_set_per_set.connect(2 * (j * num_res + i) + 4, res_name) + h5_serialization_op_set_per_set.connect( + 2 * (j * num_res + i) + 5, res.on_time_scoping(j + 1).eval() + ) + +h5_set_per_set_ds = h5_serialization_op_set_per_set.outputs.data_sources() + +############################################################################### +# Use H5 reading operator +# ~~~~~~~~~~~~~~~~~~~~~~~ +# Read the results from all time steps files: +h5_stream_prov_op = dpf.operators.metadata.streams_provider() +h5_stream_prov_op.inputs.data_sources.connect(h5_all_times_ds) +res_deser_all_times_list = [] +h5_read_op = dpf.operators.serialization.hdf5dpf_custom_read() +h5_read_op.inputs.streams.connect(h5_stream_prov_op.outputs) +for i, res_name in enumerate(result_names_on_all_time_steps): + h5_read_op.inputs.result_name.connect(res_name) + res_deser = h5_read_op.outputs.field_or_fields_container_as_fields_container() + res_deser_all_times_list.append(res_deser) + +############################################################################### +# Read the meshed region from all time steps file: +mesh_prov_op = dpf.operators.mesh.mesh_provider() +mesh_prov_op.inputs.streams_container.connect(h5_stream_prov_op.outputs) +mesh_deser_all_times = mesh_prov_op.outputs.mesh() + +############################################################################### +# Read the results from the time set per set file: +h5_stream_prov_op_2 = dpf.operators.metadata.streams_provider() +h5_stream_prov_op_2.inputs.data_sources.connect(h5_set_per_set_ds) +res_deser_set_per_set_list = [] +h5_read_op_2 = dpf.operators.serialization.hdf5dpf_custom_read() +h5_read_op_2.inputs.streams.connect(h5_stream_prov_op_2.outputs) +for i, res_name in enumerate(result_names_time_per_time): + h5_read_op_2.inputs.result_name.connect(res_name) + res_deser = h5_read_op_2.outputs.field_or_fields_container_as_fields_container() + res_deser_set_per_set_list.append(res_deser) + +############################################################################### +# Read the meshed region from all time steps files: +mesh_prov_op_2 = dpf.operators.mesh.mesh_provider() +mesh_prov_op_2.inputs.streams_container.connect(h5_stream_prov_op_2.outputs) +mesh_deser_set_per_set = mesh_prov_op_2.outputs.mesh() + +############################################################################### +# Compare results +# ~~~~~~~~~~~~~~~ + +############################################################################### +# Print global data: +print("Number of results is: " + str(num_res)) +print("Number of time sets is: " + str(num_sets)) +print("Results names for 'all time steps' file: ") +print(result_names_on_all_time_steps) +print("Results names for 'set per set' file: ") +print(result_names_time_per_time) + +############################################################################### +# compare first result at second time set: +fc_all_steps_first_step_first_res = res_deser_all_times_list[0].get_field_by_time_id(2) # set 1 +mesh_deser_all_times.plot(fc_all_steps_first_step_first_res) + +mesh_deser_set_per_set.plot(res_deser_set_per_set_list[num_res * 1 + 0]) + +############################################################################### +# compare 4th result at 6 time set: +to_nodal_op = dpf.operators.averaging.to_nodal_fc() + +fc_all_steps_first_step_first_res = res_deser_all_times_list[3].get_field_by_time_id(6) # set 6 +mesh_deser_all_times.plot( + dpf.operators.averaging.to_nodal(fc_all_steps_first_step_first_res).outputs.field() +) + +mesh_deser_set_per_set.plot( + dpf.operators.averaging.to_nodal(res_deser_set_per_set_list[num_res * 5 + 3]).outputs.field() +) diff --git a/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.py.md5 b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.py.md5 new file mode 100644 index 0000000000..6eeffdf3bf --- /dev/null +++ b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.py.md5 @@ -0,0 +1 @@ +4e97f7f582a3901e9e400ca9a0f36fc9 \ No newline at end of file diff --git a/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.rst b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.rst new file mode 100644 index 0000000000..0dca1b5e9d --- /dev/null +++ b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read.rst @@ -0,0 +1,404 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\05-file-IO\02-hdf5_serialize_and_read.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_05-file-IO_02-hdf5_serialize_and_read.py: + + +.. _ref_basic_hdf5: + +HDF5 export and import operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows you how to use the HDF5 format to export results +and meshed regions in an H5 file. +It also demonstrates how to read results and meshed regions from the +created H5 file. + +First, it exports all the results for all time frequencies, +then it exports all the time sets for the results, per time set. +Finally, it reads the results and compares them. +For the example to run correctly, ensure you do not have an existing H5 file. + +.. note:: + This example requires DPF 7.0 (ansys-dpf-server-2024-1-pre0) or above. + For more information, see :ref:`ref_compatibility`. + +.. GENERATED FROM PYTHON SOURCE LINES 24-27 + +Import modules, instantiate model and create temporary folder +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Import the ``dpf-core`` module and its examples files. + +.. GENERATED FROM PYTHON SOURCE LINES 27-31 + +.. code-block:: default + + + import ansys.dpf.core as dpf + from ansys.dpf.core import examples + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 32-33 + +Instantiate the model and the provider operators: + +.. GENERATED FROM PYTHON SOURCE LINES 33-46 + +.. code-block:: default + + + model = dpf.Model(examples.download_transient_result()) + streams_cont = model.metadata.streams_provider.outputs.streams_container + time_freq_op = dpf.operators.metadata.time_freq_provider(streams_container=streams_cont) + time_freq_support = time_freq_op.outputs.time_freq_support() + time_freqs = time_freq_support.time_frequencies + + result_names_on_all_time_steps = [] + result_names_time_per_time = [] + + num_res = len(model.results) + num_sets = len(time_freqs.data) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 47-48 + +Define a temporary folder for outputs: + +.. GENERATED FROM PYTHON SOURCE LINES 48-54 + +.. code-block:: default + + tmpdir = dpf.core.make_tmp_dir_server(dpf.SERVER) + files = [ + dpf.path_utilities.join(tmpdir, "file_on_all_time_steps.h5"), + dpf.path_utilities.join(tmpdir, "file_time_per_time.h5"), + ] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 55-58 + +Use H5 serialization operator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Export all results on all time frequencies: + +.. GENERATED FROM PYTHON SOURCE LINES 58-71 + +.. code-block:: default + + h5_serialization_op_all_times = dpf.operators.serialization.hdf5dpf_generate_result_file() + h5_serialization_op_all_times.inputs.filename.connect(files[0]) + h5_serialization_op_all_times.inputs.mesh_provider_out.connect(model.metadata.meshed_region) + h5_serialization_op_all_times.inputs.time_freq_support_out.connect(time_freq_support) + + for i, res in enumerate(model.results): + res_name = "result_" + res().name + result_names_on_all_time_steps.append(res_name) + h5_serialization_op_all_times.connect(2 * i + 4, res_name) + h5_serialization_op_all_times.connect(2 * i + 5, res.on_all_time_freqs()) + + h5_all_times_ds = h5_serialization_op_all_times.outputs.data_sources() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 72-73 + +Export all the results, time set per time set: + +.. GENERATED FROM PYTHON SOURCE LINES 73-89 + +.. code-block:: default + + h5_serialization_op_set_per_set = dpf.operators.serialization.hdf5dpf_generate_result_file() + h5_serialization_op_set_per_set.inputs.filename.connect(files[1]) + h5_serialization_op_set_per_set.inputs.mesh_provider_out.connect(model.metadata.meshed_region) + h5_serialization_op_set_per_set.inputs.time_freq_support_out.connect(time_freq_support) + + for j, freq in enumerate(time_freqs.data): + for i, res in enumerate(model.results): + res_name = "result_" + res().name + "_time_" + str(freq) + result_names_time_per_time.append(res_name) + h5_serialization_op_set_per_set.connect(2 * (j * num_res + i) + 4, res_name) + h5_serialization_op_set_per_set.connect( + 2 * (j * num_res + i) + 5, res.on_time_scoping(j + 1).eval() + ) + + h5_set_per_set_ds = h5_serialization_op_set_per_set.outputs.data_sources() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 90-93 + +Use H5 reading operator +~~~~~~~~~~~~~~~~~~~~~~~ +Read the results from all time steps files: + +.. GENERATED FROM PYTHON SOURCE LINES 93-103 + +.. code-block:: default + + h5_stream_prov_op = dpf.operators.metadata.streams_provider() + h5_stream_prov_op.inputs.data_sources.connect(h5_all_times_ds) + res_deser_all_times_list = [] + h5_read_op = dpf.operators.serialization.hdf5dpf_custom_read() + h5_read_op.inputs.streams.connect(h5_stream_prov_op.outputs) + for i, res_name in enumerate(result_names_on_all_time_steps): + h5_read_op.inputs.result_name.connect(res_name) + res_deser = h5_read_op.outputs.field_or_fields_container_as_fields_container() + res_deser_all_times_list.append(res_deser) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 104-105 + +Read the meshed region from all time steps file: + +.. GENERATED FROM PYTHON SOURCE LINES 105-109 + +.. code-block:: default + + mesh_prov_op = dpf.operators.mesh.mesh_provider() + mesh_prov_op.inputs.streams_container.connect(h5_stream_prov_op.outputs) + mesh_deser_all_times = mesh_prov_op.outputs.mesh() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 110-111 + +Read the results from the time set per set file: + +.. GENERATED FROM PYTHON SOURCE LINES 111-121 + +.. code-block:: default + + h5_stream_prov_op_2 = dpf.operators.metadata.streams_provider() + h5_stream_prov_op_2.inputs.data_sources.connect(h5_set_per_set_ds) + res_deser_set_per_set_list = [] + h5_read_op_2 = dpf.operators.serialization.hdf5dpf_custom_read() + h5_read_op_2.inputs.streams.connect(h5_stream_prov_op_2.outputs) + for i, res_name in enumerate(result_names_time_per_time): + h5_read_op_2.inputs.result_name.connect(res_name) + res_deser = h5_read_op_2.outputs.field_or_fields_container_as_fields_container() + res_deser_set_per_set_list.append(res_deser) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 122-123 + +Read the meshed region from all time steps files: + +.. GENERATED FROM PYTHON SOURCE LINES 123-127 + +.. code-block:: default + + mesh_prov_op_2 = dpf.operators.mesh.mesh_provider() + mesh_prov_op_2.inputs.streams_container.connect(h5_stream_prov_op_2.outputs) + mesh_deser_set_per_set = mesh_prov_op_2.outputs.mesh() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 128-130 + +Compare results +~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 132-133 + +Print global data: + +.. GENERATED FROM PYTHON SOURCE LINES 133-140 + +.. code-block:: default + + print("Number of results is: " + str(num_res)) + print("Number of time sets is: " + str(num_sets)) + print("Results names for 'all time steps' file: ") + print(result_names_on_all_time_steps) + print("Results names for 'set per set' file: ") + print(result_names_time_per_time) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Number of results is: 17 + Number of time sets is: 35 + Results names for 'all time steps' file: + ['result_U', 'result_RF', 'result_ENF', 'result_S', 'result_ENG_VOL', 'result_ENG_SE', 'result_ENG_AHO', 'result_ENG_TH', 'result_ENG_KE', 'result_ENG_CO', 'result_ENG_INC', 'result_EPEL', 'result_ETH', 'result_ETH_EQV', 'result_ETH_SWL', 'result_EUL', 'result_BFE'] + Results names for 'set per set' file: + ['result_U_time_0.0', 'result_RF_time_0.0', 'result_ENF_time_0.0', 'result_S_time_0.0', 'result_ENG_VOL_time_0.0', 'result_ENG_SE_time_0.0', 'result_ENG_AHO_time_0.0', 'result_ENG_TH_time_0.0', 'result_ENG_KE_time_0.0', 'result_ENG_CO_time_0.0', 'result_ENG_INC_time_0.0', 'result_EPEL_time_0.0', 'result_ETH_time_0.0', 'result_ETH_EQV_time_0.0', 'result_ETH_SWL_time_0.0', 'result_EUL_time_0.0', 'result_BFE_time_0.0', 'result_U_time_0.019974999999999035', 'result_RF_time_0.019974999999999035', 'result_ENF_time_0.019974999999999035', 'result_S_time_0.019974999999999035', 'result_ENG_VOL_time_0.019974999999999035', 'result_ENG_SE_time_0.019974999999999035', 'result_ENG_AHO_time_0.019974999999999035', 'result_ENG_TH_time_0.019974999999999035', 'result_ENG_KE_time_0.019974999999999035', 'result_ENG_CO_time_0.019974999999999035', 'result_ENG_INC_time_0.019974999999999035', 'result_EPEL_time_0.019974999999999035', 'result_ETH_time_0.019974999999999035', 'result_ETH_EQV_time_0.019974999999999035', 'result_ETH_SWL_time_0.019974999999999035', 'result_EUL_time_0.019974999999999035', 'result_BFE_time_0.019974999999999035', 'result_U_time_0.03997499999999905', 'result_RF_time_0.03997499999999905', 'result_ENF_time_0.03997499999999905', 'result_S_time_0.03997499999999905', 'result_ENG_VOL_time_0.03997499999999905', 'result_ENG_SE_time_0.03997499999999905', 'result_ENG_AHO_time_0.03997499999999905', 'result_ENG_TH_time_0.03997499999999905', 'result_ENG_KE_time_0.03997499999999905', 'result_ENG_CO_time_0.03997499999999905', 'result_ENG_INC_time_0.03997499999999905', 'result_EPEL_time_0.03997499999999905', 'result_ETH_time_0.03997499999999905', 'result_ETH_EQV_time_0.03997499999999905', 'result_ETH_SWL_time_0.03997499999999905', 'result_EUL_time_0.03997499999999905', 'result_BFE_time_0.03997499999999905', 'result_U_time_0.05997499999999907', 'result_RF_time_0.05997499999999907', 'result_ENF_time_0.05997499999999907', 'result_S_time_0.05997499999999907', 'result_ENG_VOL_time_0.05997499999999907', 'result_ENG_SE_time_0.05997499999999907', 'result_ENG_AHO_time_0.05997499999999907', 'result_ENG_TH_time_0.05997499999999907', 'result_ENG_KE_time_0.05997499999999907', 'result_ENG_CO_time_0.05997499999999907', 'result_ENG_INC_time_0.05997499999999907', 'result_EPEL_time_0.05997499999999907', 'result_ETH_time_0.05997499999999907', 'result_ETH_EQV_time_0.05997499999999907', 'result_ETH_SWL_time_0.05997499999999907', 'result_EUL_time_0.05997499999999907', 'result_BFE_time_0.05997499999999907', 'result_U_time_0.07997499999999909', 'result_RF_time_0.07997499999999909', 'result_ENF_time_0.07997499999999909', 'result_S_time_0.07997499999999909', 'result_ENG_VOL_time_0.07997499999999909', 'result_ENG_SE_time_0.07997499999999909', 'result_ENG_AHO_time_0.07997499999999909', 'result_ENG_TH_time_0.07997499999999909', 'result_ENG_KE_time_0.07997499999999909', 'result_ENG_CO_time_0.07997499999999909', 'result_ENG_INC_time_0.07997499999999909', 'result_EPEL_time_0.07997499999999909', 'result_ETH_time_0.07997499999999909', 'result_ETH_EQV_time_0.07997499999999909', 'result_ETH_SWL_time_0.07997499999999909', 'result_EUL_time_0.07997499999999909', 'result_BFE_time_0.07997499999999909', 'result_U_time_0.0999749999999991', 'result_RF_time_0.0999749999999991', 'result_ENF_time_0.0999749999999991', 'result_S_time_0.0999749999999991', 'result_ENG_VOL_time_0.0999749999999991', 'result_ENG_SE_time_0.0999749999999991', 'result_ENG_AHO_time_0.0999749999999991', 'result_ENG_TH_time_0.0999749999999991', 'result_ENG_KE_time_0.0999749999999991', 'result_ENG_CO_time_0.0999749999999991', 'result_ENG_INC_time_0.0999749999999991', 'result_EPEL_time_0.0999749999999991', 'result_ETH_time_0.0999749999999991', 'result_ETH_EQV_time_0.0999749999999991', 'result_ETH_SWL_time_0.0999749999999991', 'result_EUL_time_0.0999749999999991', 'result_BFE_time_0.0999749999999991', 'result_U_time_0.11997499999999912', 'result_RF_time_0.11997499999999912', 'result_ENF_time_0.11997499999999912', 'result_S_time_0.11997499999999912', 'result_ENG_VOL_time_0.11997499999999912', 'result_ENG_SE_time_0.11997499999999912', 'result_ENG_AHO_time_0.11997499999999912', 'result_ENG_TH_time_0.11997499999999912', 'result_ENG_KE_time_0.11997499999999912', 'result_ENG_CO_time_0.11997499999999912', 'result_ENG_INC_time_0.11997499999999912', 'result_EPEL_time_0.11997499999999912', 'result_ETH_time_0.11997499999999912', 'result_ETH_EQV_time_0.11997499999999912', 'result_ETH_SWL_time_0.11997499999999912', 'result_EUL_time_0.11997499999999912', 'result_BFE_time_0.11997499999999912', 'result_U_time_0.13997499999999913', 'result_RF_time_0.13997499999999913', 'result_ENF_time_0.13997499999999913', 'result_S_time_0.13997499999999913', 'result_ENG_VOL_time_0.13997499999999913', 'result_ENG_SE_time_0.13997499999999913', 'result_ENG_AHO_time_0.13997499999999913', 'result_ENG_TH_time_0.13997499999999913', 'result_ENG_KE_time_0.13997499999999913', 'result_ENG_CO_time_0.13997499999999913', 'result_ENG_INC_time_0.13997499999999913', 'result_EPEL_time_0.13997499999999913', 'result_ETH_time_0.13997499999999913', 'result_ETH_EQV_time_0.13997499999999913', 'result_ETH_SWL_time_0.13997499999999913', 'result_EUL_time_0.13997499999999913', 'result_BFE_time_0.13997499999999913', 'result_U_time_0.15997499999999915', 'result_RF_time_0.15997499999999915', 'result_ENF_time_0.15997499999999915', 'result_S_time_0.15997499999999915', 'result_ENG_VOL_time_0.15997499999999915', 'result_ENG_SE_time_0.15997499999999915', 'result_ENG_AHO_time_0.15997499999999915', 'result_ENG_TH_time_0.15997499999999915', 'result_ENG_KE_time_0.15997499999999915', 'result_ENG_CO_time_0.15997499999999915', 'result_ENG_INC_time_0.15997499999999915', 'result_EPEL_time_0.15997499999999915', 'result_ETH_time_0.15997499999999915', 'result_ETH_EQV_time_0.15997499999999915', 'result_ETH_SWL_time_0.15997499999999915', 'result_EUL_time_0.15997499999999915', 'result_BFE_time_0.15997499999999915', 'result_U_time_0.17997499999999916', 'result_RF_time_0.17997499999999916', 'result_ENF_time_0.17997499999999916', 'result_S_time_0.17997499999999916', 'result_ENG_VOL_time_0.17997499999999916', 'result_ENG_SE_time_0.17997499999999916', 'result_ENG_AHO_time_0.17997499999999916', 'result_ENG_TH_time_0.17997499999999916', 'result_ENG_KE_time_0.17997499999999916', 'result_ENG_CO_time_0.17997499999999916', 'result_ENG_INC_time_0.17997499999999916', 'result_EPEL_time_0.17997499999999916', 'result_ETH_time_0.17997499999999916', 'result_ETH_EQV_time_0.17997499999999916', 'result_ETH_SWL_time_0.17997499999999916', 'result_EUL_time_0.17997499999999916', 'result_BFE_time_0.17997499999999916', 'result_U_time_0.19997499999999918', 'result_RF_time_0.19997499999999918', 'result_ENF_time_0.19997499999999918', 'result_S_time_0.19997499999999918', 'result_ENG_VOL_time_0.19997499999999918', 'result_ENG_SE_time_0.19997499999999918', 'result_ENG_AHO_time_0.19997499999999918', 'result_ENG_TH_time_0.19997499999999918', 'result_ENG_KE_time_0.19997499999999918', 'result_ENG_CO_time_0.19997499999999918', 'result_ENG_INC_time_0.19997499999999918', 'result_EPEL_time_0.19997499999999918', 'result_ETH_time_0.19997499999999918', 'result_ETH_EQV_time_0.19997499999999918', 'result_ETH_SWL_time_0.19997499999999918', 'result_EUL_time_0.19997499999999918', 'result_BFE_time_0.19997499999999918', 'result_U_time_0.2189749999999992', 'result_RF_time_0.2189749999999992', 'result_ENF_time_0.2189749999999992', 'result_S_time_0.2189749999999992', 'result_ENG_VOL_time_0.2189749999999992', 'result_ENG_SE_time_0.2189749999999992', 'result_ENG_AHO_time_0.2189749999999992', 'result_ENG_TH_time_0.2189749999999992', 'result_ENG_KE_time_0.2189749999999992', 'result_ENG_CO_time_0.2189749999999992', 'result_ENG_INC_time_0.2189749999999992', 'result_EPEL_time_0.2189749999999992', 'result_ETH_time_0.2189749999999992', 'result_ETH_EQV_time_0.2189749999999992', 'result_ETH_SWL_time_0.2189749999999992', 'result_EUL_time_0.2189749999999992', 'result_BFE_time_0.2189749999999992', 'result_U_time_0.23897499999999922', 'result_RF_time_0.23897499999999922', 'result_ENF_time_0.23897499999999922', 'result_S_time_0.23897499999999922', 'result_ENG_VOL_time_0.23897499999999922', 'result_ENG_SE_time_0.23897499999999922', 'result_ENG_AHO_time_0.23897499999999922', 'result_ENG_TH_time_0.23897499999999922', 'result_ENG_KE_time_0.23897499999999922', 'result_ENG_CO_time_0.23897499999999922', 'result_ENG_INC_time_0.23897499999999922', 'result_EPEL_time_0.23897499999999922', 'result_ETH_time_0.23897499999999922', 'result_ETH_EQV_time_0.23897499999999922', 'result_ETH_SWL_time_0.23897499999999922', 'result_EUL_time_0.23897499999999922', 'result_BFE_time_0.23897499999999922', 'result_U_time_0.25897499999999923', 'result_RF_time_0.25897499999999923', 'result_ENF_time_0.25897499999999923', 'result_S_time_0.25897499999999923', 'result_ENG_VOL_time_0.25897499999999923', 'result_ENG_SE_time_0.25897499999999923', 'result_ENG_AHO_time_0.25897499999999923', 'result_ENG_TH_time_0.25897499999999923', 'result_ENG_KE_time_0.25897499999999923', 'result_ENG_CO_time_0.25897499999999923', 'result_ENG_INC_time_0.25897499999999923', 'result_EPEL_time_0.25897499999999923', 'result_ETH_time_0.25897499999999923', 'result_ETH_EQV_time_0.25897499999999923', 'result_ETH_SWL_time_0.25897499999999923', 'result_EUL_time_0.25897499999999923', 'result_BFE_time_0.25897499999999923', 'result_U_time_0.27897499999999925', 'result_RF_time_0.27897499999999925', 'result_ENF_time_0.27897499999999925', 'result_S_time_0.27897499999999925', 'result_ENG_VOL_time_0.27897499999999925', 'result_ENG_SE_time_0.27897499999999925', 'result_ENG_AHO_time_0.27897499999999925', 'result_ENG_TH_time_0.27897499999999925', 'result_ENG_KE_time_0.27897499999999925', 'result_ENG_CO_time_0.27897499999999925', 'result_ENG_INC_time_0.27897499999999925', 'result_EPEL_time_0.27897499999999925', 'result_ETH_time_0.27897499999999925', 'result_ETH_EQV_time_0.27897499999999925', 'result_ETH_SWL_time_0.27897499999999925', 'result_EUL_time_0.27897499999999925', 'result_BFE_time_0.27897499999999925', 'result_U_time_0.29897499999999927', 'result_RF_time_0.29897499999999927', 'result_ENF_time_0.29897499999999927', 'result_S_time_0.29897499999999927', 'result_ENG_VOL_time_0.29897499999999927', 'result_ENG_SE_time_0.29897499999999927', 'result_ENG_AHO_time_0.29897499999999927', 'result_ENG_TH_time_0.29897499999999927', 'result_ENG_KE_time_0.29897499999999927', 'result_ENG_CO_time_0.29897499999999927', 'result_ENG_INC_time_0.29897499999999927', 'result_EPEL_time_0.29897499999999927', 'result_ETH_time_0.29897499999999927', 'result_ETH_EQV_time_0.29897499999999927', 'result_ETH_SWL_time_0.29897499999999927', 'result_EUL_time_0.29897499999999927', 'result_BFE_time_0.29897499999999927', 'result_U_time_0.3189749999999993', 'result_RF_time_0.3189749999999993', 'result_ENF_time_0.3189749999999993', 'result_S_time_0.3189749999999993', 'result_ENG_VOL_time_0.3189749999999993', 'result_ENG_SE_time_0.3189749999999993', 'result_ENG_AHO_time_0.3189749999999993', 'result_ENG_TH_time_0.3189749999999993', 'result_ENG_KE_time_0.3189749999999993', 'result_ENG_CO_time_0.3189749999999993', 'result_ENG_INC_time_0.3189749999999993', 'result_EPEL_time_0.3189749999999993', 'result_ETH_time_0.3189749999999993', 'result_ETH_EQV_time_0.3189749999999993', 'result_ETH_SWL_time_0.3189749999999993', 'result_EUL_time_0.3189749999999993', 'result_BFE_time_0.3189749999999993', 'result_U_time_0.3389749999999993', 'result_RF_time_0.3389749999999993', 'result_ENF_time_0.3389749999999993', 'result_S_time_0.3389749999999993', 'result_ENG_VOL_time_0.3389749999999993', 'result_ENG_SE_time_0.3389749999999993', 'result_ENG_AHO_time_0.3389749999999993', 'result_ENG_TH_time_0.3389749999999993', 'result_ENG_KE_time_0.3389749999999993', 'result_ENG_CO_time_0.3389749999999993', 'result_ENG_INC_time_0.3389749999999993', 'result_EPEL_time_0.3389749999999993', 'result_ETH_time_0.3389749999999993', 'result_ETH_EQV_time_0.3389749999999993', 'result_ETH_SWL_time_0.3389749999999993', 'result_EUL_time_0.3389749999999993', 'result_BFE_time_0.3389749999999993', 'result_U_time_0.3589749999999993', 'result_RF_time_0.3589749999999993', 'result_ENF_time_0.3589749999999993', 'result_S_time_0.3589749999999993', 'result_ENG_VOL_time_0.3589749999999993', 'result_ENG_SE_time_0.3589749999999993', 'result_ENG_AHO_time_0.3589749999999993', 'result_ENG_TH_time_0.3589749999999993', 'result_ENG_KE_time_0.3589749999999993', 'result_ENG_CO_time_0.3589749999999993', 'result_ENG_INC_time_0.3589749999999993', 'result_EPEL_time_0.3589749999999993', 'result_ETH_time_0.3589749999999993', 'result_ETH_EQV_time_0.3589749999999993', 'result_ETH_SWL_time_0.3589749999999993', 'result_EUL_time_0.3589749999999993', 'result_BFE_time_0.3589749999999993', 'result_U_time_0.37897499999999934', 'result_RF_time_0.37897499999999934', 'result_ENF_time_0.37897499999999934', 'result_S_time_0.37897499999999934', 'result_ENG_VOL_time_0.37897499999999934', 'result_ENG_SE_time_0.37897499999999934', 'result_ENG_AHO_time_0.37897499999999934', 'result_ENG_TH_time_0.37897499999999934', 'result_ENG_KE_time_0.37897499999999934', 'result_ENG_CO_time_0.37897499999999934', 'result_ENG_INC_time_0.37897499999999934', 'result_EPEL_time_0.37897499999999934', 'result_ETH_time_0.37897499999999934', 'result_ETH_EQV_time_0.37897499999999934', 'result_ETH_SWL_time_0.37897499999999934', 'result_EUL_time_0.37897499999999934', 'result_BFE_time_0.37897499999999934', 'result_U_time_0.39897499999999936', 'result_RF_time_0.39897499999999936', 'result_ENF_time_0.39897499999999936', 'result_S_time_0.39897499999999936', 'result_ENG_VOL_time_0.39897499999999936', 'result_ENG_SE_time_0.39897499999999936', 'result_ENG_AHO_time_0.39897499999999936', 'result_ENG_TH_time_0.39897499999999936', 'result_ENG_KE_time_0.39897499999999936', 'result_ENG_CO_time_0.39897499999999936', 'result_ENG_INC_time_0.39897499999999936', 'result_EPEL_time_0.39897499999999936', 'result_ETH_time_0.39897499999999936', 'result_ETH_EQV_time_0.39897499999999936', 'result_ETH_SWL_time_0.39897499999999936', 'result_EUL_time_0.39897499999999936', 'result_BFE_time_0.39897499999999936', 'result_U_time_0.4179749999999994', 'result_RF_time_0.4179749999999994', 'result_ENF_time_0.4179749999999994', 'result_S_time_0.4179749999999994', 'result_ENG_VOL_time_0.4179749999999994', 'result_ENG_SE_time_0.4179749999999994', 'result_ENG_AHO_time_0.4179749999999994', 'result_ENG_TH_time_0.4179749999999994', 'result_ENG_KE_time_0.4179749999999994', 'result_ENG_CO_time_0.4179749999999994', 'result_ENG_INC_time_0.4179749999999994', 'result_EPEL_time_0.4179749999999994', 'result_ETH_time_0.4179749999999994', 'result_ETH_EQV_time_0.4179749999999994', 'result_ETH_SWL_time_0.4179749999999994', 'result_EUL_time_0.4179749999999994', 'result_BFE_time_0.4179749999999994', 'result_U_time_0.4379749999999994', 'result_RF_time_0.4379749999999994', 'result_ENF_time_0.4379749999999994', 'result_S_time_0.4379749999999994', 'result_ENG_VOL_time_0.4379749999999994', 'result_ENG_SE_time_0.4379749999999994', 'result_ENG_AHO_time_0.4379749999999994', 'result_ENG_TH_time_0.4379749999999994', 'result_ENG_KE_time_0.4379749999999994', 'result_ENG_CO_time_0.4379749999999994', 'result_ENG_INC_time_0.4379749999999994', 'result_EPEL_time_0.4379749999999994', 'result_ETH_time_0.4379749999999994', 'result_ETH_EQV_time_0.4379749999999994', 'result_ETH_SWL_time_0.4379749999999994', 'result_EUL_time_0.4379749999999994', 'result_BFE_time_0.4379749999999994', 'result_U_time_0.4579749999999994', 'result_RF_time_0.4579749999999994', 'result_ENF_time_0.4579749999999994', 'result_S_time_0.4579749999999994', 'result_ENG_VOL_time_0.4579749999999994', 'result_ENG_SE_time_0.4579749999999994', 'result_ENG_AHO_time_0.4579749999999994', 'result_ENG_TH_time_0.4579749999999994', 'result_ENG_KE_time_0.4579749999999994', 'result_ENG_CO_time_0.4579749999999994', 'result_ENG_INC_time_0.4579749999999994', 'result_EPEL_time_0.4579749999999994', 'result_ETH_time_0.4579749999999994', 'result_ETH_EQV_time_0.4579749999999994', 'result_ETH_SWL_time_0.4579749999999994', 'result_EUL_time_0.4579749999999994', 'result_BFE_time_0.4579749999999994', 'result_U_time_0.47797499999999943', 'result_RF_time_0.47797499999999943', 'result_ENF_time_0.47797499999999943', 'result_S_time_0.47797499999999943', 'result_ENG_VOL_time_0.47797499999999943', 'result_ENG_SE_time_0.47797499999999943', 'result_ENG_AHO_time_0.47797499999999943', 'result_ENG_TH_time_0.47797499999999943', 'result_ENG_KE_time_0.47797499999999943', 'result_ENG_CO_time_0.47797499999999943', 'result_ENG_INC_time_0.47797499999999943', 'result_EPEL_time_0.47797499999999943', 'result_ETH_time_0.47797499999999943', 'result_ETH_EQV_time_0.47797499999999943', 'result_ETH_SWL_time_0.47797499999999943', 'result_EUL_time_0.47797499999999943', 'result_BFE_time_0.47797499999999943', 'result_U_time_0.49797499999999945', 'result_RF_time_0.49797499999999945', 'result_ENF_time_0.49797499999999945', 'result_S_time_0.49797499999999945', 'result_ENG_VOL_time_0.49797499999999945', 'result_ENG_SE_time_0.49797499999999945', 'result_ENG_AHO_time_0.49797499999999945', 'result_ENG_TH_time_0.49797499999999945', 'result_ENG_KE_time_0.49797499999999945', 'result_ENG_CO_time_0.49797499999999945', 'result_ENG_INC_time_0.49797499999999945', 'result_EPEL_time_0.49797499999999945', 'result_ETH_time_0.49797499999999945', 'result_ETH_EQV_time_0.49797499999999945', 'result_ETH_SWL_time_0.49797499999999945', 'result_EUL_time_0.49797499999999945', 'result_BFE_time_0.49797499999999945', 'result_U_time_0.5179749999999994', 'result_RF_time_0.5179749999999994', 'result_ENF_time_0.5179749999999994', 'result_S_time_0.5179749999999994', 'result_ENG_VOL_time_0.5179749999999994', 'result_ENG_SE_time_0.5179749999999994', 'result_ENG_AHO_time_0.5179749999999994', 'result_ENG_TH_time_0.5179749999999994', 'result_ENG_KE_time_0.5179749999999994', 'result_ENG_CO_time_0.5179749999999994', 'result_ENG_INC_time_0.5179749999999994', 'result_EPEL_time_0.5179749999999994', 'result_ETH_time_0.5179749999999994', 'result_ETH_EQV_time_0.5179749999999994', 'result_ETH_SWL_time_0.5179749999999994', 'result_EUL_time_0.5179749999999994', 'result_BFE_time_0.5179749999999994', 'result_U_time_0.5375497170781891', 'result_RF_time_0.5375497170781891', 'result_ENF_time_0.5375497170781891', 'result_S_time_0.5375497170781891', 'result_ENG_VOL_time_0.5375497170781891', 'result_ENG_SE_time_0.5375497170781891', 'result_ENG_AHO_time_0.5375497170781891', 'result_ENG_TH_time_0.5375497170781891', 'result_ENG_KE_time_0.5375497170781891', 'result_ENG_CO_time_0.5375497170781891', 'result_ENG_INC_time_0.5375497170781891', 'result_EPEL_time_0.5375497170781891', 'result_ETH_time_0.5375497170781891', 'result_ETH_EQV_time_0.5375497170781891', 'result_ETH_SWL_time_0.5375497170781891', 'result_EUL_time_0.5375497170781891', 'result_BFE_time_0.5375497170781891', 'result_U_time_0.5572527745675683', 'result_RF_time_0.5572527745675683', 'result_ENF_time_0.5572527745675683', 'result_S_time_0.5572527745675683', 'result_ENG_VOL_time_0.5572527745675683', 'result_ENG_SE_time_0.5572527745675683', 'result_ENG_AHO_time_0.5572527745675683', 'result_ENG_TH_time_0.5572527745675683', 'result_ENG_KE_time_0.5572527745675683', 'result_ENG_CO_time_0.5572527745675683', 'result_ENG_INC_time_0.5572527745675683', 'result_EPEL_time_0.5572527745675683', 'result_ETH_time_0.5572527745675683', 'result_ETH_EQV_time_0.5572527745675683', 'result_ETH_SWL_time_0.5572527745675683', 'result_EUL_time_0.5572527745675683', 'result_BFE_time_0.5572527745675683', 'result_U_time_0.5771178586948806', 'result_RF_time_0.5771178586948806', 'result_ENF_time_0.5771178586948806', 'result_S_time_0.5771178586948806', 'result_ENG_VOL_time_0.5771178586948806', 'result_ENG_SE_time_0.5771178586948806', 'result_ENG_AHO_time_0.5771178586948806', 'result_ENG_TH_time_0.5771178586948806', 'result_ENG_KE_time_0.5771178586948806', 'result_ENG_CO_time_0.5771178586948806', 'result_ENG_INC_time_0.5771178586948806', 'result_EPEL_time_0.5771178586948806', 'result_ETH_time_0.5771178586948806', 'result_ETH_EQV_time_0.5771178586948806', 'result_ETH_SWL_time_0.5771178586948806', 'result_EUL_time_0.5771178586948806', 'result_BFE_time_0.5771178586948806', 'result_U_time_0.5970205401025951', 'result_RF_time_0.5970205401025951', 'result_ENF_time_0.5970205401025951', 'result_S_time_0.5970205401025951', 'result_ENG_VOL_time_0.5970205401025951', 'result_ENG_SE_time_0.5970205401025951', 'result_ENG_AHO_time_0.5970205401025951', 'result_ENG_TH_time_0.5970205401025951', 'result_ENG_KE_time_0.5970205401025951', 'result_ENG_CO_time_0.5970205401025951', 'result_ENG_INC_time_0.5970205401025951', 'result_EPEL_time_0.5970205401025951', 'result_ETH_time_0.5970205401025951', 'result_ETH_EQV_time_0.5970205401025951', 'result_ETH_SWL_time_0.5970205401025951', 'result_EUL_time_0.5970205401025951', 'result_BFE_time_0.5970205401025951', 'result_U_time_0.6169463863439129', 'result_RF_time_0.6169463863439129', 'result_ENF_time_0.6169463863439129', 'result_S_time_0.6169463863439129', 'result_ENG_VOL_time_0.6169463863439129', 'result_ENG_SE_time_0.6169463863439129', 'result_ENG_AHO_time_0.6169463863439129', 'result_ENG_TH_time_0.6169463863439129', 'result_ENG_KE_time_0.6169463863439129', 'result_ENG_CO_time_0.6169463863439129', 'result_ENG_INC_time_0.6169463863439129', 'result_EPEL_time_0.6169463863439129', 'result_ETH_time_0.6169463863439129', 'result_ETH_EQV_time_0.6169463863439129', 'result_ETH_SWL_time_0.6169463863439129', 'result_EUL_time_0.6169463863439129', 'result_BFE_time_0.6169463863439129', 'result_U_time_0.6368334712400927', 'result_RF_time_0.6368334712400927', 'result_ENF_time_0.6368334712400927', 'result_S_time_0.6368334712400927', 'result_ENG_VOL_time_0.6368334712400927', 'result_ENG_SE_time_0.6368334712400927', 'result_ENG_AHO_time_0.6368334712400927', 'result_ENG_TH_time_0.6368334712400927', 'result_ENG_KE_time_0.6368334712400927', 'result_ENG_CO_time_0.6368334712400927', 'result_ENG_INC_time_0.6368334712400927', 'result_EPEL_time_0.6368334712400927', 'result_ETH_time_0.6368334712400927', 'result_ETH_EQV_time_0.6368334712400927', 'result_ETH_SWL_time_0.6368334712400927', 'result_EUL_time_0.6368334712400927', 'result_BFE_time_0.6368334712400927', 'result_U_time_0.6567345247543699', 'result_RF_time_0.6567345247543699', 'result_ENF_time_0.6567345247543699', 'result_S_time_0.6567345247543699', 'result_ENG_VOL_time_0.6567345247543699', 'result_ENG_SE_time_0.6567345247543699', 'result_ENG_AHO_time_0.6567345247543699', 'result_ENG_TH_time_0.6567345247543699', 'result_ENG_KE_time_0.6567345247543699', 'result_ENG_CO_time_0.6567345247543699', 'result_ENG_INC_time_0.6567345247543699', 'result_EPEL_time_0.6567345247543699', 'result_ETH_time_0.6567345247543699', 'result_ETH_EQV_time_0.6567345247543699', 'result_ETH_SWL_time_0.6567345247543699', 'result_EUL_time_0.6567345247543699', 'result_BFE_time_0.6567345247543699', 'result_U_time_0.6766278291959333', 'result_RF_time_0.6766278291959333', 'result_ENF_time_0.6766278291959333', 'result_S_time_0.6766278291959333', 'result_ENG_VOL_time_0.6766278291959333', 'result_ENG_SE_time_0.6766278291959333', 'result_ENG_AHO_time_0.6766278291959333', 'result_ENG_TH_time_0.6766278291959333', 'result_ENG_KE_time_0.6766278291959333', 'result_ENG_CO_time_0.6766278291959333', 'result_ENG_INC_time_0.6766278291959333', 'result_EPEL_time_0.6766278291959333', 'result_ETH_time_0.6766278291959333', 'result_ETH_EQV_time_0.6766278291959333', 'result_ETH_SWL_time_0.6766278291959333', 'result_EUL_time_0.6766278291959333', 'result_BFE_time_0.6766278291959333'] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 141-142 + +compare first result at second time set: + +.. GENERATED FROM PYTHON SOURCE LINES 142-147 + +.. code-block:: default + + fc_all_steps_first_step_first_res = res_deser_all_times_list[0].get_field_by_time_id(2) # set 1 + mesh_deser_all_times.plot(fc_all_steps_first_step_first_res) + + mesh_deser_set_per_set.plot(res_deser_set_per_set_list[num_res * 1 + 0]) + + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_001.png + :alt: 02 hdf5 serialize and read + :srcset: /examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_002.png + :alt: 02 hdf5 serialize and read + :srcset: /examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_002.png + :class: sphx-glr-multi-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 148-149 + +compare 4th result at 6 time set: + +.. GENERATED FROM PYTHON SOURCE LINES 149-159 + +.. code-block:: default + + to_nodal_op = dpf.operators.averaging.to_nodal_fc() + + fc_all_steps_first_step_first_res = res_deser_all_times_list[3].get_field_by_time_id(6) # set 6 + mesh_deser_all_times.plot( + dpf.operators.averaging.to_nodal(fc_all_steps_first_step_first_res).outputs.field() + ) + + mesh_deser_set_per_set.plot( + dpf.operators.averaging.to_nodal(res_deser_set_per_set_list[num_res * 5 + 3]).outputs.field() + ) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_003.png + :alt: 02 hdf5 serialize and read + :srcset: /examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_004.png + :alt: 02 hdf5 serialize and read + :srcset: /examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_004.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 9.655 seconds) + + +.. _sphx_glr_download_examples_05-file-IO_02-hdf5_serialize_and_read.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 02-hdf5_serialize_and_read.py <02-hdf5_serialize_and_read.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 02-hdf5_serialize_and_read.ipynb <02-hdf5_serialize_and_read.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read_codeobj.pickle b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read_codeobj.pickle new file mode 100644 index 0000000000..911932faad Binary files /dev/null and b/doc/source/examples/05-file-IO/02-hdf5_serialize_and_read_codeobj.pickle differ diff --git a/doc/source/examples/05-file-IO/04-basic-load-file.ipynb b/doc/source/examples/05-file-IO/04-basic-load-file.ipynb new file mode 100644 index 0000000000..53c3319b36 --- /dev/null +++ b/doc/source/examples/05-file-IO/04-basic-load-file.ipynb @@ -0,0 +1,187 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Working with a result file {#ref_basic_load_file_example}\r\n\r\nThis example shows how to write and upload files on the server machine\r\nand then download them back on the client side. The resulting fields\r\ncontainer is then exported to a CSV file.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load a model from the DPF-Core examples: `ansys.dpf.core` module.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\n\n\nmodel = dpf.Model(examples.find_simple_bar())\nmesh = model.metadata.meshed_region" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get and plot the fields container for the result\r\n\r\nGet the fields container for the result and plot it so you can compare\r\nit later:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "displacement_operator = model.results.displacement()\nfc_out = displacement_operator.outputs.fields_container()\nmesh.plot(fc_out)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Export result\r\n\r\nExport the fields container in the CSV format:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\n\ncsv_file_name = \"simple_bar_fc.csv\"\n# Define an output path for the resulting .csv file\nif not dpf.SERVER.local_server:\n # Define it server-side if using a remote server\n tmp_dir_path = dpf.core.make_tmp_dir_server(dpf.SERVER)\n server_file_path = dpf.path_utilities.join(tmp_dir_path, csv_file_name)\nelse:\n server_file_path = os.path.join(os.getcwd(), csv_file_name)\n\n# Perform the export to csv on the server side\nexport_csv_operator = dpf.operators.serialization.field_to_csv()\nexport_csv_operator.inputs.field_or_fields_container.connect(fc_out)\nexport_csv_operator.inputs.file_path.connect(server_file_path)\nexport_csv_operator.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Download CSV result file\r\n\r\nDownload the file `simple_bar_fc.csv`:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "if not dpf.SERVER.local_server:\n downloaded_client_file_path = os.path.join(os.getcwd(), \"simple_bar_fc_downloaded.csv\")\n dpf.download_file(server_file_path, downloaded_client_file_path)\nelse:\n downloaded_client_file_path = server_file_path" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Load CSV result file as operator input\r\n\r\nLoad the fields container contained in the CSV file as an operator\r\ninput:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "my_data_sources = dpf.DataSources(server_file_path)\nimport_csv_operator = dpf.operators.serialization.csv_to_field()\nimport_csv_operator.inputs.data_sources.connect(my_data_sources)\nserver_fc_out = import_csv_operator.outputs.fields_container()\nmesh.plot(server_fc_out)\n\n# Remove file to avoid polluting.\nos.remove(downloaded_client_file_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Make operations over the fields container\r\n\r\nUse this fields container to get the minimum displacement:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "min_max_op = dpf.operators.min_max.min_max_fc()\nmin_max_op.inputs.fields_container.connect(server_fc_out)\nmin_field = min_max_op.outputs.field_min()\nmin_field.data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compare the original and the new fields container\r\n\r\nSubtract the two fields and plot an error map:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "abs_error = (fc_out - server_fc_out).eval()\n\ndivide = dpf.operators.math.component_wise_divide()\ndivide.inputs.fieldA.connect(fc_out - server_fc_out)\ndivide.inputs.fieldB.connect(fc_out)\nscale = dpf.operators.math.scale()\nscale.inputs.field.connect(divide)\nscale.inputs.ponderation.connect(100.0)\nrel_error = scale.eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot both absolute and relative error fields\r\n\r\nNote that the absolute error is bigger where the displacements are\r\nbigger, at the tip of the geometry. Instead, the relative error is\r\nsimilar across the geometry since we are dividing by the displacements\r\n`fc_out`. Both plots show errors that can be understood as zero due to\r\nmachine precision (1e-12 mm for the absolute error and 1e-5% for the\r\nrelative error).\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh.plot(abs_error, scalar_bar_args={\"title\": \"Absolute error [mm]\"})\nmesh.plot(rel_error, scalar_bar_args={\"title\": \"Relative error [%]\"})" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/05-file-IO/04-basic-load-file.py b/doc/source/examples/05-file-IO/04-basic-load-file.py new file mode 100644 index 0000000000..f9aa6db143 --- /dev/null +++ b/doc/source/examples/05-file-IO/04-basic-load-file.py @@ -0,0 +1,115 @@ +# noqa: D400 +""" +.. _ref_basic_load_file_example: + +Working with a result file +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to write and upload files on the server machine and then +download them back on the client side. The resulting fields container is then +exported to a CSV file. + +""" + +############################################################################### +# Load a model from the DPF-Core examples: +# ``ansys.dpf.core`` module. + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + + +model = dpf.Model(examples.find_simple_bar()) +mesh = model.metadata.meshed_region + +############################################################################### +# Get and plot the fields container for the result +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Get the fields container for the result and plot it so you can compare it later: + +displacement_operator = model.results.displacement() +fc_out = displacement_operator.outputs.fields_container() +mesh.plot(fc_out) + +############################################################################### +# Export result +# ~~~~~~~~~~~~~ +# Export the fields container in the CSV format: + +import os + +csv_file_name = "simple_bar_fc.csv" +# Define an output path for the resulting .csv file +if not dpf.SERVER.local_server: + # Define it server-side if using a remote server + tmp_dir_path = dpf.core.make_tmp_dir_server(dpf.SERVER) + server_file_path = dpf.path_utilities.join(tmp_dir_path, csv_file_name) +else: + server_file_path = os.path.join(os.getcwd(), csv_file_name) + +# Perform the export to csv on the server side +export_csv_operator = dpf.operators.serialization.field_to_csv() +export_csv_operator.inputs.field_or_fields_container.connect(fc_out) +export_csv_operator.inputs.file_path.connect(server_file_path) +export_csv_operator.run() + +############################################################################### +# Download CSV result file +# ~~~~~~~~~~~~~~~~~~~~~~~~~ +# Download the file ``simple_bar_fc.csv``: + +if not dpf.SERVER.local_server: + downloaded_client_file_path = os.path.join(os.getcwd(), "simple_bar_fc_downloaded.csv") + dpf.download_file(server_file_path, downloaded_client_file_path) +else: + downloaded_client_file_path = server_file_path + +############################################################################### +# Load CSV result file as operator input +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Load the fields container contained in the CSV file as an operator input: + +my_data_sources = dpf.DataSources(server_file_path) +import_csv_operator = dpf.operators.serialization.csv_to_field() +import_csv_operator.inputs.data_sources.connect(my_data_sources) +server_fc_out = import_csv_operator.outputs.fields_container() +mesh.plot(server_fc_out) + +# Remove file to avoid polluting. +os.remove(downloaded_client_file_path) + +############################################################################### +# Make operations over the fields container +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Use this fields container to get the minimum displacement: + +min_max_op = dpf.operators.min_max.min_max_fc() +min_max_op.inputs.fields_container.connect(server_fc_out) +min_field = min_max_op.outputs.field_min() +min_field.data + +############################################################################### +# Compare the original and the new fields container +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Subtract the two fields and plot an error map: +abs_error = (fc_out - server_fc_out).eval() + +divide = dpf.operators.math.component_wise_divide() +divide.inputs.fieldA.connect(fc_out - server_fc_out) +divide.inputs.fieldB.connect(fc_out) +scale = dpf.operators.math.scale() +scale.inputs.field.connect(divide) +scale.inputs.ponderation.connect(100.0) +rel_error = scale.eval() + +############################################################################### +# Plot both absolute and relative error fields +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Note that the absolute error is bigger where the displacements are +# bigger, at the tip of the geometry. +# Instead, the relative error is similar across the geometry since we +# are dividing by the displacements ``fc_out``. +# Both plots show errors that can be understood as zero due to machine precision +# (1e-12 mm for the absolute error and 1e-5% for the relative error). +mesh.plot(abs_error, scalar_bar_args={"title": "Absolute error [mm]"}) +mesh.plot(rel_error, scalar_bar_args={"title": "Relative error [%]"}) diff --git a/doc/source/examples/05-file-IO/04-basic-load-file.py.md5 b/doc/source/examples/05-file-IO/04-basic-load-file.py.md5 new file mode 100644 index 0000000000..afdc15e59e --- /dev/null +++ b/doc/source/examples/05-file-IO/04-basic-load-file.py.md5 @@ -0,0 +1 @@ +337d22acefe3eaec4bbe2eadd2830049 \ No newline at end of file diff --git a/doc/source/examples/05-file-IO/04-basic-load-file.rst b/doc/source/examples/05-file-IO/04-basic-load-file.rst new file mode 100644 index 0000000000..8e5213d4fd --- /dev/null +++ b/doc/source/examples/05-file-IO/04-basic-load-file.rst @@ -0,0 +1,295 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\05-file-IO\04-basic-load-file.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_05-file-IO_04-basic-load-file.py: + + +.. _ref_basic_load_file_example: + +Working with a result file +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to write and upload files on the server machine and then +download them back on the client side. The resulting fields container is then +exported to a CSV file. + +.. GENERATED FROM PYTHON SOURCE LINES 15-17 + +Load a model from the DPF-Core examples: +``ansys.dpf.core`` module. + +.. GENERATED FROM PYTHON SOURCE LINES 17-25 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + model = dpf.Model(examples.find_simple_bar()) + mesh = model.metadata.meshed_region + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 26-29 + +Get and plot the fields container for the result +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Get the fields container for the result and plot it so you can compare it later: + +.. GENERATED FROM PYTHON SOURCE LINES 29-34 + +.. code-block:: default + + + displacement_operator = model.results.displacement() + fc_out = displacement_operator.outputs.fields_container() + mesh.plot(fc_out) + + + + +.. image-sg:: /examples/05-file-IO/images/sphx_glr_04-basic-load-file_001.png + :alt: 04 basic load file + :srcset: /examples/05-file-IO/images/sphx_glr_04-basic-load-file_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 35-38 + +Export result +~~~~~~~~~~~~~ +Export the fields container in the CSV format: + +.. GENERATED FROM PYTHON SOURCE LINES 38-56 + +.. code-block:: default + + + import os + + csv_file_name = "simple_bar_fc.csv" + # Define an output path for the resulting .csv file + if not dpf.SERVER.local_server: + # Define it server-side if using a remote server + tmp_dir_path = dpf.core.make_tmp_dir_server(dpf.SERVER) + server_file_path = dpf.path_utilities.join(tmp_dir_path, csv_file_name) + else: + server_file_path = os.path.join(os.getcwd(), csv_file_name) + + # Perform the export to csv on the server side + export_csv_operator = dpf.operators.serialization.field_to_csv() + export_csv_operator.inputs.field_or_fields_container.connect(fc_out) + export_csv_operator.inputs.file_path.connect(server_file_path) + export_csv_operator.run() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 57-60 + +Download CSV result file +~~~~~~~~~~~~~~~~~~~~~~~~~ +Download the file ``simple_bar_fc.csv``: + +.. GENERATED FROM PYTHON SOURCE LINES 60-67 + +.. code-block:: default + + + if not dpf.SERVER.local_server: + downloaded_client_file_path = os.path.join(os.getcwd(), "simple_bar_fc_downloaded.csv") + dpf.download_file(server_file_path, downloaded_client_file_path) + else: + downloaded_client_file_path = server_file_path + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 68-71 + +Load CSV result file as operator input +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Load the fields container contained in the CSV file as an operator input: + +.. GENERATED FROM PYTHON SOURCE LINES 71-81 + +.. code-block:: default + + + my_data_sources = dpf.DataSources(server_file_path) + import_csv_operator = dpf.operators.serialization.csv_to_field() + import_csv_operator.inputs.data_sources.connect(my_data_sources) + server_fc_out = import_csv_operator.outputs.fields_container() + mesh.plot(server_fc_out) + + # Remove file to avoid polluting. + os.remove(downloaded_client_file_path) + + + + +.. image-sg:: /examples/05-file-IO/images/sphx_glr_04-basic-load-file_002.png + :alt: 04 basic load file + :srcset: /examples/05-file-IO/images/sphx_glr_04-basic-load-file_002.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 82-85 + +Make operations over the fields container +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Use this fields container to get the minimum displacement: + +.. GENERATED FROM PYTHON SOURCE LINES 85-91 + +.. code-block:: default + + + min_max_op = dpf.operators.min_max.min_max_fc() + min_max_op.inputs.fields_container.connect(server_fc_out) + min_field = min_max_op.outputs.field_min() + min_field.data + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + DPFArray([[-9., 0., -9.]]) + + + +.. GENERATED FROM PYTHON SOURCE LINES 92-95 + +Compare the original and the new fields container +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Subtract the two fields and plot an error map: + +.. GENERATED FROM PYTHON SOURCE LINES 95-105 + +.. code-block:: default + + abs_error = (fc_out - server_fc_out).eval() + + divide = dpf.operators.math.component_wise_divide() + divide.inputs.fieldA.connect(fc_out - server_fc_out) + divide.inputs.fieldB.connect(fc_out) + scale = dpf.operators.math.scale() + scale.inputs.field.connect(divide) + scale.inputs.ponderation.connect(100.0) + rel_error = scale.eval() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 106-114 + +Plot both absolute and relative error fields +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Note that the absolute error is bigger where the displacements are +bigger, at the tip of the geometry. +Instead, the relative error is similar across the geometry since we +are dividing by the displacements ``fc_out``. +Both plots show errors that can be understood as zero due to machine precision +(1e-12 mm for the absolute error and 1e-5% for the relative error). + +.. GENERATED FROM PYTHON SOURCE LINES 114-116 + +.. code-block:: default + + mesh.plot(abs_error, scalar_bar_args={"title": "Absolute error [mm]"}) + mesh.plot(rel_error, scalar_bar_args={"title": "Relative error [%]"}) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/05-file-IO/images/sphx_glr_04-basic-load-file_003.png + :alt: 04 basic load file + :srcset: /examples/05-file-IO/images/sphx_glr_04-basic-load-file_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/05-file-IO/images/sphx_glr_04-basic-load-file_004.png + :alt: 04 basic load file + :srcset: /examples/05-file-IO/images/sphx_glr_04-basic-load-file_004.png + :class: sphx-glr-multi-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 3.893 seconds) + + +.. _sphx_glr_download_examples_05-file-IO_04-basic-load-file.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 04-basic-load-file.py <04-basic-load-file.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 04-basic-load-file.ipynb <04-basic-load-file.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/05-file-IO/04-basic-load-file_codeobj.pickle b/doc/source/examples/05-file-IO/04-basic-load-file_codeobj.pickle new file mode 100644 index 0000000000..278f8e692b Binary files /dev/null and b/doc/source/examples/05-file-IO/04-basic-load-file_codeobj.pickle differ diff --git a/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_001.png b/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_001.png new file mode 100644 index 0000000000..efd050b5d6 Binary files /dev/null and b/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_001.png differ diff --git a/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_002.png b/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_002.png new file mode 100644 index 0000000000..efd050b5d6 Binary files /dev/null and b/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_002.png differ diff --git a/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_003.png b/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_003.png new file mode 100644 index 0000000000..90f9406ed0 Binary files /dev/null and b/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_003.png differ diff --git a/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_004.png b/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_004.png new file mode 100644 index 0000000000..90f9406ed0 Binary files /dev/null and b/doc/source/examples/05-file-IO/images/sphx_glr_02-hdf5_serialize_and_read_004.png differ diff --git a/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_001.png b/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_001.png new file mode 100644 index 0000000000..c2fb4bb3ae Binary files /dev/null and b/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_001.png differ diff --git a/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_002.png b/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_002.png new file mode 100644 index 0000000000..71aa65d534 Binary files /dev/null and b/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_002.png differ diff --git a/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_003.png b/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_003.png new file mode 100644 index 0000000000..addf53b291 Binary files /dev/null and b/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_003.png differ diff --git a/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_004.png b/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_004.png new file mode 100644 index 0000000000..cae6890879 Binary files /dev/null and b/doc/source/examples/05-file-IO/images/sphx_glr_04-basic-load-file_004.png differ diff --git a/doc/source/examples/05-file-IO/images/thumb/sphx_glr_00-hdf5_double_float_comparison_thumb.png b/doc/source/examples/05-file-IO/images/thumb/sphx_glr_00-hdf5_double_float_comparison_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/05-file-IO/images/thumb/sphx_glr_00-hdf5_double_float_comparison_thumb.png differ diff --git a/doc/source/examples/05-file-IO/images/thumb/sphx_glr_01-reduced_matrices_export_thumb.png b/doc/source/examples/05-file-IO/images/thumb/sphx_glr_01-reduced_matrices_export_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/05-file-IO/images/thumb/sphx_glr_01-reduced_matrices_export_thumb.png differ diff --git a/doc/source/examples/05-file-IO/images/thumb/sphx_glr_02-hdf5_serialize_and_read_thumb.png b/doc/source/examples/05-file-IO/images/thumb/sphx_glr_02-hdf5_serialize_and_read_thumb.png new file mode 100644 index 0000000000..e079a20189 Binary files /dev/null and b/doc/source/examples/05-file-IO/images/thumb/sphx_glr_02-hdf5_serialize_and_read_thumb.png differ diff --git a/doc/source/examples/05-file-IO/images/thumb/sphx_glr_04-basic-load-file_thumb.png b/doc/source/examples/05-file-IO/images/thumb/sphx_glr_04-basic-load-file_thumb.png new file mode 100644 index 0000000000..c651bfd4dd Binary files /dev/null and b/doc/source/examples/05-file-IO/images/thumb/sphx_glr_04-basic-load-file_thumb.png differ diff --git a/doc/source/examples/05-file-IO/index.rst b/doc/source/examples/05-file-IO/index.rst new file mode 100644 index 0000000000..70fedc14a6 --- /dev/null +++ b/doc/source/examples/05-file-IO/index.rst @@ -0,0 +1,99 @@ + + +.. _sphx_glr_examples_05-file-IO: + +.. _file_IO: + +File manipulation and input-output examples +=========================================== +These examples show how to manipulate files, +as well as importing or exporting from or to specific formats. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/05-file-IO/images/thumb/sphx_glr_00-hdf5_double_float_comparison_thumb.png + :alt: HDF5 export and compare precision + + :ref:`sphx_glr_examples_05-file-IO_00-hdf5_double_float_comparison.py` + +.. raw:: html + +
HDF5 export and compare precision
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/05-file-IO/images/thumb/sphx_glr_01-reduced_matrices_export_thumb.png + :alt: Get reduced matrices and make export + + :ref:`sphx_glr_examples_05-file-IO_01-reduced_matrices_export.py` + +.. raw:: html + +
Get reduced matrices and make export
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/05-file-IO/images/thumb/sphx_glr_02-hdf5_serialize_and_read_thumb.png + :alt: HDF5 export and import operations + + :ref:`sphx_glr_examples_05-file-IO_02-hdf5_serialize_and_read.py` + +.. raw:: html + +
HDF5 export and import operations
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/05-file-IO/images/thumb/sphx_glr_04-basic-load-file_thumb.png + :alt: Working with a result file + + :ref:`sphx_glr_examples_05-file-IO_04-basic-load-file.py` + +.. raw:: html + +
Working with a result file
+
+ + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /examples/05-file-IO/00-hdf5_double_float_comparison + /examples/05-file-IO/01-reduced_matrices_export + /examples/05-file-IO/02-hdf5_serialize_and_read + /examples/05-file-IO/04-basic-load-file + diff --git a/doc/source/examples/05-file-IO/sg_execution_times.rst b/doc/source/examples/05-file-IO/sg_execution_times.rst new file mode 100644 index 0000000000..e8420e8aed --- /dev/null +++ b/doc/source/examples/05-file-IO/sg_execution_times.rst @@ -0,0 +1,18 @@ + +:orphan: + +.. _sphx_glr_examples_05-file-IO_sg_execution_times: + +Computation times +================= +**00:15.049** total execution time for **examples_05-file-IO** files: + ++-----------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_05-file-IO_02-hdf5_serialize_and_read.py` (``02-hdf5_serialize_and_read.py``) | 00:09.655 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_05-file-IO_04-basic-load-file.py` (``04-basic-load-file.py``) | 00:03.893 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_05-file-IO_01-reduced_matrices_export.py` (``01-reduced_matrices_export.py``) | 00:01.292 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_05-file-IO_00-hdf5_double_float_comparison.py` (``00-hdf5_double_float_comparison.py``) | 00:00.209 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------------------+-----------+--------+ diff --git a/doc/source/examples/06-plotting/00-basic_plotting.ipynb b/doc/source/examples/06-plotting/00-basic_plotting.ipynb new file mode 100644 index 0000000000..9bb163c0eb --- /dev/null +++ b/doc/source/examples/06-plotting/00-basic_plotting.ipynb @@ -0,0 +1,54 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Review of available plotting commands {#basic_plotting}\r\n\r\nThis example lists the different plotting commands available, shown with\r\nthe arguments available.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\n\n\n# Plot the bare mesh of a model\nmodel = dpf.Model(examples.find_multishells_rst())\nmodel.plot(color=\"w\", show_edges=True, title=\"Model\", text=\"Model plot\")\n# # Additional PyVista kwargs are supported, such as:\nmodel.plot(\n off_screen=True,\n notebook=False,\n screenshot=\"model_plot.png\",\n title=\"Model\",\n text=\"Model plot off\",\n)\n\n# Notes:\n# - To make screenshots, use \"screenshot\" as well as \"notebook=False\" if on a Jupyter notebook.\n# - The \"off_screen\" keyword only works when \"notebook=False\" to prevent the GUI from appearing.\n\n\n# Plot a field on its supporting mesh (field location must be Elemental or Nodal)\nstress = model.results.stress()\nstress.inputs.requested_location.connect(dpf.locations.nodal)\nfc = stress.outputs.fields_container()\nfield = fc[0]\nfield.plot(notebook=False, shell_layers=None, show_axes=True, title=\"Field\", text=\"Field plot\")\n# # Additional PyVista kwargs are supported, such as:\nfield.plot(\n off_screen=True,\n notebook=False,\n screenshot=\"field_plot.png\",\n title=\"Field\",\n text=\"Field plot off\",\n)\n#\n# # Alternatively one can plot the MeshedRegion associated to the model\nmesh = model.metadata.meshed_region\nmesh.plot(\n field_or_fields_container=None,\n shell_layers=None,\n show_axes=True,\n title=\"Mesh fc None\",\n text=\"Mesh plot\",\n)\n# Additional PyVista kwargs are supported, such as:\nmesh.plot(\n off_screen=True,\n notebook=False,\n screenshot=\"mesh_plot.png\",\n title=\"Mesh\",\n text=\"Mesh plot off\",\n)\n# A fields_container or a specific field can be given to plot on the mesh.\nmesh.plot(\n field_or_fields_container=fc,\n title=\"Mesh with fields container\",\n text=\"Mesh fc plot\",\n)\nmesh.plot(field_or_fields_container=field, title=\"Mesh with field\", text=\"Mesh field plot\")\n\n\n# ##############################################################################################\n# # This next section requires a Premium context to be active du to the ``split_mesh`` operator.\n# # Comment this last part to run the example as Entry.\n#\n# dpf.SERVER.apply_context(dpf.AvailableServerContexts.premium)\n#\n# # One can also plot a MeshesContainer. Here our mesh is split by material.\n# split_mesh_op = dpf.Operator(\"split_mesh\")\n# split_mesh_op.connect(7, mesh)\n# split_mesh_op.connect(13, \"mat\")\n# meshes_cont = split_mesh_op.get_output(0, dpf.types.meshes_container)\n# meshes_cont.plot(title='Meshes Container', text='Meshes Container plot')\n# # A fields_container can be given as input, with results on each part of our split mesh.\n# disp_op = dpf.Operator(\"U\")\n# disp_op.connect(7, meshes_cont)\n# ds = dpf.DataSources(examples.find_multishells_rst())\n# disp_op.connect(4, ds)\n# disp_fc = disp_op.outputs.fields_container()\n# meshes_cont.plot(disp_fc, title='Meshes Container disp_fc', text='Meshes Container disp_fc plot')\n# # Additional PyVista kwargs are supported, such as:\n# meshes_cont.plot(off_screen=True, notebook=False, screenshot='meshes_cont_plot.png',\n# title='Meshes Container', text='Meshes Container plot')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/06-plotting/00-basic_plotting.py b/doc/source/examples/06-plotting/00-basic_plotting.py new file mode 100644 index 0000000000..6841b4b72c --- /dev/null +++ b/doc/source/examples/06-plotting/00-basic_plotting.py @@ -0,0 +1,95 @@ +""" +.. _basic_plotting: + +Review of available plotting commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example lists the different plotting commands available, +shown with the arguments available. + +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + + +# Plot the bare mesh of a model +model = dpf.Model(examples.find_multishells_rst()) +model.plot(color="w", show_edges=True, title="Model", text="Model plot") +# # Additional PyVista kwargs are supported, such as: +model.plot( + off_screen=True, + notebook=False, + screenshot="model_plot.png", + title="Model", + text="Model plot off", +) + +# Notes: +# - To make screenshots, use "screenshot" as well as "notebook=False" if on a Jupyter notebook. +# - The "off_screen" keyword only works when "notebook=False" to prevent the GUI from appearing. + + +# Plot a field on its supporting mesh (field location must be Elemental or Nodal) +stress = model.results.stress() +stress.inputs.requested_location.connect(dpf.locations.nodal) +fc = stress.outputs.fields_container() +field = fc[0] +field.plot(notebook=False, shell_layers=None, show_axes=True, title="Field", text="Field plot") +# # Additional PyVista kwargs are supported, such as: +field.plot( + off_screen=True, + notebook=False, + screenshot="field_plot.png", + title="Field", + text="Field plot off", +) +# +# # Alternatively one can plot the MeshedRegion associated to the model +mesh = model.metadata.meshed_region +mesh.plot( + field_or_fields_container=None, + shell_layers=None, + show_axes=True, + title="Mesh fc None", + text="Mesh plot", +) +# Additional PyVista kwargs are supported, such as: +mesh.plot( + off_screen=True, + notebook=False, + screenshot="mesh_plot.png", + title="Mesh", + text="Mesh plot off", +) +# A fields_container or a specific field can be given to plot on the mesh. +mesh.plot( + field_or_fields_container=fc, + title="Mesh with fields container", + text="Mesh fc plot", +) +mesh.plot(field_or_fields_container=field, title="Mesh with field", text="Mesh field plot") + + +# ############################################################################################## +# # This next section requires a Premium context to be active du to the ``split_mesh`` operator. +# # Comment this last part to run the example as Entry. +# +# dpf.SERVER.apply_context(dpf.AvailableServerContexts.premium) +# +# # One can also plot a MeshesContainer. Here our mesh is split by material. +# split_mesh_op = dpf.Operator("split_mesh") +# split_mesh_op.connect(7, mesh) +# split_mesh_op.connect(13, "mat") +# meshes_cont = split_mesh_op.get_output(0, dpf.types.meshes_container) +# meshes_cont.plot(title='Meshes Container', text='Meshes Container plot') +# # A fields_container can be given as input, with results on each part of our split mesh. +# disp_op = dpf.Operator("U") +# disp_op.connect(7, meshes_cont) +# ds = dpf.DataSources(examples.find_multishells_rst()) +# disp_op.connect(4, ds) +# disp_fc = disp_op.outputs.fields_container() +# meshes_cont.plot(disp_fc, title='Meshes Container disp_fc', text='Meshes Container disp_fc plot') +# # Additional PyVista kwargs are supported, such as: +# meshes_cont.plot(off_screen=True, notebook=False, screenshot='meshes_cont_plot.png', +# title='Meshes Container', text='Meshes Container plot') diff --git a/doc/source/examples/06-plotting/00-basic_plotting.py.md5 b/doc/source/examples/06-plotting/00-basic_plotting.py.md5 new file mode 100644 index 0000000000..3f9ded14a7 --- /dev/null +++ b/doc/source/examples/06-plotting/00-basic_plotting.py.md5 @@ -0,0 +1 @@ +74221b673868319ceea45fe932063827 \ No newline at end of file diff --git a/doc/source/examples/06-plotting/00-basic_plotting.rst b/doc/source/examples/06-plotting/00-basic_plotting.rst new file mode 100644 index 0000000000..1bde1ba6ea --- /dev/null +++ b/doc/source/examples/06-plotting/00-basic_plotting.rst @@ -0,0 +1,223 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\06-plotting\00-basic_plotting.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_06-plotting_00-basic_plotting.py: + + +.. _basic_plotting: + +Review of available plotting commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example lists the different plotting commands available, +shown with the arguments available. + +.. GENERATED FROM PYTHON SOURCE LINES 11-96 + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_00-basic_plotting_001.png + :alt: 00 basic plotting + :srcset: /examples/06-plotting/images/sphx_glr_00-basic_plotting_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_00-basic_plotting_002.png + :alt: 00 basic plotting + :srcset: /examples/06-plotting/images/sphx_glr_00-basic_plotting_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_00-basic_plotting_003.png + :alt: 00 basic plotting + :srcset: /examples/06-plotting/images/sphx_glr_00-basic_plotting_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_00-basic_plotting_004.png + :alt: 00 basic plotting + :srcset: /examples/06-plotting/images/sphx_glr_00-basic_plotting_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_00-basic_plotting_005.png + :alt: 00 basic plotting + :srcset: /examples/06-plotting/images/sphx_glr_00-basic_plotting_005.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_00-basic_plotting_006.png + :alt: 00 basic plotting + :srcset: /examples/06-plotting/images/sphx_glr_00-basic_plotting_006.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_00-basic_plotting_007.png + :alt: 00 basic plotting + :srcset: /examples/06-plotting/images/sphx_glr_00-basic_plotting_007.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_00-basic_plotting_008.png + :alt: 00 basic plotting + :srcset: /examples/06-plotting/images/sphx_glr_00-basic_plotting_008.png + :class: sphx-glr-multi-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + D:\ANSYSDev\Sandbox\pydpf-core\src\ansys\dpf\core\plotter.py:660: UserWarning: 'notebook' is not a valid kwarg for show_figure(). Please give this argument to the init of DpfPlotter. + warnings.warn( + D:\ANSYSDev\Sandbox\pydpf-core\src\ansys\dpf\core\plotter.py:660: UserWarning: 'notebook' is not a valid kwarg for show_figure(). Please give this argument to the init of DpfPlotter. + warnings.warn( + + + + + + +| + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + # Plot the bare mesh of a model + model = dpf.Model(examples.find_multishells_rst()) + model.plot(color="w", show_edges=True, title="Model", text="Model plot") + # # Additional PyVista kwargs are supported, such as: + model.plot( + off_screen=True, + notebook=False, + screenshot="model_plot.png", + title="Model", + text="Model plot off", + ) + + # Notes: + # - To make screenshots, use "screenshot" as well as "notebook=False" if on a Jupyter notebook. + # - The "off_screen" keyword only works when "notebook=False" to prevent the GUI from appearing. + + + # Plot a field on its supporting mesh (field location must be Elemental or Nodal) + stress = model.results.stress() + stress.inputs.requested_location.connect(dpf.locations.nodal) + fc = stress.outputs.fields_container() + field = fc[0] + field.plot(notebook=False, shell_layers=None, show_axes=True, title="Field", text="Field plot") + # # Additional PyVista kwargs are supported, such as: + field.plot( + off_screen=True, + notebook=False, + screenshot="field_plot.png", + title="Field", + text="Field plot off", + ) + # + # # Alternatively one can plot the MeshedRegion associated to the model + mesh = model.metadata.meshed_region + mesh.plot( + field_or_fields_container=None, + shell_layers=None, + show_axes=True, + title="Mesh fc None", + text="Mesh plot", + ) + # Additional PyVista kwargs are supported, such as: + mesh.plot( + off_screen=True, + notebook=False, + screenshot="mesh_plot.png", + title="Mesh", + text="Mesh plot off", + ) + # A fields_container or a specific field can be given to plot on the mesh. + mesh.plot( + field_or_fields_container=fc, + title="Mesh with fields container", + text="Mesh fc plot", + ) + mesh.plot(field_or_fields_container=field, title="Mesh with field", text="Mesh field plot") + + + # ############################################################################################## + # # This next section requires a Premium context to be active du to the ``split_mesh`` operator. + # # Comment this last part to run the example as Entry. + # + # dpf.SERVER.apply_context(dpf.AvailableServerContexts.premium) + # + # # One can also plot a MeshesContainer. Here our mesh is split by material. + # split_mesh_op = dpf.Operator("split_mesh") + # split_mesh_op.connect(7, mesh) + # split_mesh_op.connect(13, "mat") + # meshes_cont = split_mesh_op.get_output(0, dpf.types.meshes_container) + # meshes_cont.plot(title='Meshes Container', text='Meshes Container plot') + # # A fields_container can be given as input, with results on each part of our split mesh. + # disp_op = dpf.Operator("U") + # disp_op.connect(7, meshes_cont) + # ds = dpf.DataSources(examples.find_multishells_rst()) + # disp_op.connect(4, ds) + # disp_fc = disp_op.outputs.fields_container() + # meshes_cont.plot(disp_fc, title='Meshes Container disp_fc', text='Meshes Container disp_fc plot') + # # Additional PyVista kwargs are supported, such as: + # meshes_cont.plot(off_screen=True, notebook=False, screenshot='meshes_cont_plot.png', + # title='Meshes Container', text='Meshes Container plot') + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 6.360 seconds) + + +.. _sphx_glr_download_examples_06-plotting_00-basic_plotting.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 00-basic_plotting.py <00-basic_plotting.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 00-basic_plotting.ipynb <00-basic_plotting.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/06-plotting/00-basic_plotting_codeobj.pickle b/doc/source/examples/06-plotting/00-basic_plotting_codeobj.pickle new file mode 100644 index 0000000000..6328dd464d Binary files /dev/null and b/doc/source/examples/06-plotting/00-basic_plotting_codeobj.pickle differ diff --git a/doc/source/examples/06-plotting/01-compare_results.ipynb b/doc/source/examples/06-plotting/01-compare_results.ipynb new file mode 100644 index 0000000000..ec39733440 --- /dev/null +++ b/doc/source/examples/06-plotting/01-compare_results.ipynb @@ -0,0 +1,90 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compare results using the plotter {#compare_results}\r\n\r\nThis example shows how to plot several mesh/result combinations on the\r\nsame plot so that you can compare results at different time steps.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core.plotter import DpfPlotter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compare two results\r\n\r\nUse the `ansys.dpf.core.plotter.DpfPlotter`{.interpreted-text\r\nrole=\"class\"} class to plot two different results over the same mesh and\r\ncompare them.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Here we create a Model and request its mesh\nmodel = dpf.Model(examples.find_msup_transient())\nmesh_set2 = model.metadata.meshed_region\n\n# Then we need to request the displacement for two different time steps\ndisplacement_operator = model.results.displacement()\ndisplacement_operator.inputs.time_scoping.connect([2, 15])\ndisplacement_set2 = displacement_operator.outputs.fields_container()[0]\ndisplacement_set15 = displacement_operator.outputs.fields_container()[1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the `ansys.dpf.core.plotter.DpfPlotter`{.interpreted-text\r\nrole=\"class\"} class to add plots for the first mesh and the first\r\nresult.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pl = DpfPlotter()\npl.add_field(displacement_set2, mesh_set2)\n\n# Create a new mesh and translate it along the x axis.\nmesh_set15 = mesh_set2.deep_copy()\noverall_field = dpf.fields_factory.create_3d_vector_field(1, dpf.locations.overall)\noverall_field.append([0.2, 0.0, 0.0], 1)\ncoordinates_to_update = mesh_set15.nodes.coordinates_field\nadd_operator = dpf.operators.math.add(coordinates_to_update, overall_field)\ncoordinates_updated = add_operator.outputs.field()\ncoordinates_to_update.data = coordinates_updated.data\n\n# Use the :class:`ansys.dpf.core.plotter.DpfPlotter` class to add plots for the\n# second mesh and the second result.\npl.add_field(displacement_set15, mesh_set15)\npl.show_figure(show_axes=True)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/06-plotting/01-compare_results.py b/doc/source/examples/06-plotting/01-compare_results.py new file mode 100644 index 0000000000..bb18041240 --- /dev/null +++ b/doc/source/examples/06-plotting/01-compare_results.py @@ -0,0 +1,50 @@ +""" +.. _compare_results: + +Compare results using the plotter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to plot several mesh/result combinations on the +same plot so that you can compare results at different time steps. + +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core.plotter import DpfPlotter + +############################################################################### +# Compare two results +# ~~~~~~~~~~~~~~~~~~~ +# Use the :class:`ansys.dpf.core.plotter.DpfPlotter` class to plot two different +# results over the same mesh and compare them. + +# Here we create a Model and request its mesh +model = dpf.Model(examples.find_msup_transient()) +mesh_set2 = model.metadata.meshed_region + +# Then we need to request the displacement for two different time steps +displacement_operator = model.results.displacement() +displacement_operator.inputs.time_scoping.connect([2, 15]) +displacement_set2 = displacement_operator.outputs.fields_container()[0] +displacement_set15 = displacement_operator.outputs.fields_container()[1] + +############################################################################### +# Use the :class:`ansys.dpf.core.plotter.DpfPlotter` class to add plots for the +# first mesh and the first result. +pl = DpfPlotter() +pl.add_field(displacement_set2, mesh_set2) + +# Create a new mesh and translate it along the x axis. +mesh_set15 = mesh_set2.deep_copy() +overall_field = dpf.fields_factory.create_3d_vector_field(1, dpf.locations.overall) +overall_field.append([0.2, 0.0, 0.0], 1) +coordinates_to_update = mesh_set15.nodes.coordinates_field +add_operator = dpf.operators.math.add(coordinates_to_update, overall_field) +coordinates_updated = add_operator.outputs.field() +coordinates_to_update.data = coordinates_updated.data + +# Use the :class:`ansys.dpf.core.plotter.DpfPlotter` class to add plots for the +# second mesh and the second result. +pl.add_field(displacement_set15, mesh_set15) +pl.show_figure(show_axes=True) diff --git a/doc/source/examples/06-plotting/01-compare_results.py.md5 b/doc/source/examples/06-plotting/01-compare_results.py.md5 new file mode 100644 index 0000000000..66fa2febff --- /dev/null +++ b/doc/source/examples/06-plotting/01-compare_results.py.md5 @@ -0,0 +1 @@ +a73c80b51db59441f8810baae5250c40 \ No newline at end of file diff --git a/doc/source/examples/06-plotting/01-compare_results.rst b/doc/source/examples/06-plotting/01-compare_results.rst new file mode 100644 index 0000000000..5d486ee166 --- /dev/null +++ b/doc/source/examples/06-plotting/01-compare_results.rst @@ -0,0 +1,137 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\06-plotting\01-compare_results.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_06-plotting_01-compare_results.py: + + +.. _compare_results: + +Compare results using the plotter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to plot several mesh/result combinations on the +same plot so that you can compare results at different time steps. + +.. GENERATED FROM PYTHON SOURCE LINES 11-16 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core.plotter import DpfPlotter + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 17-21 + +Compare two results +~~~~~~~~~~~~~~~~~~~ +Use the :class:`ansys.dpf.core.plotter.DpfPlotter` class to plot two different +results over the same mesh and compare them. + +.. GENERATED FROM PYTHON SOURCE LINES 21-32 + +.. code-block:: default + + + # Here we create a Model and request its mesh + model = dpf.Model(examples.find_msup_transient()) + mesh_set2 = model.metadata.meshed_region + + # Then we need to request the displacement for two different time steps + displacement_operator = model.results.displacement() + displacement_operator.inputs.time_scoping.connect([2, 15]) + displacement_set2 = displacement_operator.outputs.fields_container()[0] + displacement_set15 = displacement_operator.outputs.fields_container()[1] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 33-35 + +Use the :class:`ansys.dpf.core.plotter.DpfPlotter` class to add plots for the +first mesh and the first result. + +.. GENERATED FROM PYTHON SOURCE LINES 35-51 + +.. code-block:: default + + pl = DpfPlotter() + pl.add_field(displacement_set2, mesh_set2) + + # Create a new mesh and translate it along the x axis. + mesh_set15 = mesh_set2.deep_copy() + overall_field = dpf.fields_factory.create_3d_vector_field(1, dpf.locations.overall) + overall_field.append([0.2, 0.0, 0.0], 1) + coordinates_to_update = mesh_set15.nodes.coordinates_field + add_operator = dpf.operators.math.add(coordinates_to_update, overall_field) + coordinates_updated = add_operator.outputs.field() + coordinates_to_update.data = coordinates_updated.data + + # Use the :class:`ansys.dpf.core.plotter.DpfPlotter` class to add plots for the + # second mesh and the second result. + pl.add_field(displacement_set15, mesh_set15) + pl.show_figure(show_axes=True) + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_01-compare_results_001.png + :alt: 01 compare results + :srcset: /examples/06-plotting/images/sphx_glr_01-compare_results_001.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.579 seconds) + + +.. _sphx_glr_download_examples_06-plotting_01-compare_results.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 01-compare_results.py <01-compare_results.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 01-compare_results.ipynb <01-compare_results.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/06-plotting/01-compare_results_codeobj.pickle b/doc/source/examples/06-plotting/01-compare_results_codeobj.pickle new file mode 100644 index 0000000000..120c32a7e3 Binary files /dev/null and b/doc/source/examples/06-plotting/01-compare_results_codeobj.pickle differ diff --git a/doc/source/examples/06-plotting/02-solution_combination.ipynb b/doc/source/examples/06-plotting/02-solution_combination.ipynb new file mode 100644 index 0000000000..735e004702 --- /dev/null +++ b/doc/source/examples/06-plotting/02-solution_combination.ipynb @@ -0,0 +1,205 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Load case combination for principal stress {#solution_combination}\r\n\r\nThis example shows how to get a principal stress load case combination\r\nusing DPF And highlight min/max values in the plot.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import the `ansys.dpf.core` module, included examples file, and the\r\n`DpfPlotter` module.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core.plotter import DpfPlotter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Open an example and print the `Model` object. The\r\n`Model `{.interpreted-text role=\"class\"}\r\nclass helps to organize access methods for the result by keeping track\r\nof the operators and data sources used by the result file.\r\n\r\nPrinting the model displays this metadata:\r\n\r\n- Analysis type\r\n- Available results\r\n- Size of the mesh\r\n- Number of results\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.find_msup_transient())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the stress tensor and `connect` time scoping. Make sure that you\r\ndefine `dpf.locations.nodal` as the scoping location because labels are\r\nsupported only for nodal results.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "stress_tensor = model.results.stress()\ntime_scope = dpf.Scoping()\ntime_scope.ids = [1, 2]\nstress_tensor.inputs.time_scoping.connect(time_scope)\nstress_tensor.inputs.requested_location.connect(dpf.locations.nodal)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This code performs solution combination on two load cases, LC1 and LC2.\r\nYou can access individual load cases as the fields of a fields container\r\nfor the stress tensor.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field_lc1 = stress_tensor.outputs.fields_container()[0]\nfield_lc2 = stress_tensor.outputs.fields_container()[1]\n\n# Scale LC2 to -1.\nstress_tensor_lc2_sc = dpf.operators.math.scale(field=field_lc2, ponderation=-1.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add load cases.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "stress_tensor_combi = dpf.operators.math.add(fieldA=field_lc1, fieldB=stress_tensor_lc2_sc)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Principal stresses are the Eigenvalues of the stress tensor. Use\r\nprincipal invariants to get S1, S2, and S3.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "p_inv = dpf.operators.invariant.principal_invariants()\np_inv.inputs.field.connect(stress_tensor_combi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print S1 (maximum principal stress).\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(p_inv.outputs.field_eig_1().data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the meshed region.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh_set = model.metadata.meshed_region" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the results on the mesh. The `label_text_size` and\r\n`label_point_size` arguments control the font size of the label.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plot = DpfPlotter()\nplot.add_field(p_inv.outputs.field_eig_1(), meshed_region=mesh_set)\n\n# You can set the camera positions using the ``cpos`` argument.\n# The three tuples in the list for the ``cpos`` argument represent the camera\n# position, focal point, and view respectively.\nplot.show_figure(show_axes=True)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/06-plotting/02-solution_combination.py b/doc/source/examples/06-plotting/02-solution_combination.py new file mode 100644 index 0000000000..c2bde85b65 --- /dev/null +++ b/doc/source/examples/06-plotting/02-solution_combination.py @@ -0,0 +1,89 @@ +# noqa: D400 +""" +.. _solution_combination: + +Load case combination for principal stress +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to get a principal stress load case combination using DPF +And highlight min/max values in the plot. + +""" + +############################################################################### +# Import the ``ansys.dpf.core`` module, included examples file, and the ``DpfPlotter`` +# module. +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core.plotter import DpfPlotter + +############################################################################### +# Open an example and print 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. +# +# Printing the model displays this metadata: +# +# - Analysis type +# - Available results +# - Size of the mesh +# - Number of results +# +model = dpf.Model(examples.find_msup_transient()) +print(model) + +############################################################################### +# Get the stress tensor and ``connect`` time scoping. +# Make sure that you define ``dpf.locations.nodal`` as the scoping location because +# labels are supported only for nodal results. +# +stress_tensor = model.results.stress() +time_scope = dpf.Scoping() +time_scope.ids = [1, 2] +stress_tensor.inputs.time_scoping.connect(time_scope) +stress_tensor.inputs.requested_location.connect(dpf.locations.nodal) + +############################################################################### +# This code performs solution combination on two load cases, LC1 and LC2. +# You can access individual load cases as the fields of a fields container for +# the stress tensor. +field_lc1 = stress_tensor.outputs.fields_container()[0] +field_lc2 = stress_tensor.outputs.fields_container()[1] + +# Scale LC2 to -1. +stress_tensor_lc2_sc = dpf.operators.math.scale(field=field_lc2, ponderation=-1.0) + +############################################################################### +# Add load cases. +stress_tensor_combi = dpf.operators.math.add(fieldA=field_lc1, fieldB=stress_tensor_lc2_sc) + +############################################################################### +# Principal stresses are the Eigenvalues of the stress tensor. +# Use principal invariants to get S1, S2, and S3. +# +p_inv = dpf.operators.invariant.principal_invariants() +p_inv.inputs.field.connect(stress_tensor_combi) + +############################################################################### +# Print S1 (maximum principal stress). +# +print(p_inv.outputs.field_eig_1().data) + +############################################################################### +# Get the meshed region. +# +mesh_set = model.metadata.meshed_region + +############################################################################### +# Plot the results on the mesh. +# The ``label_text_size`` and ``label_point_size`` arguments control the font +# size of the label. +# +plot = DpfPlotter() +plot.add_field(p_inv.outputs.field_eig_1(), meshed_region=mesh_set) + +# You can set the camera positions using the ``cpos`` argument. +# The three tuples in the list for the ``cpos`` argument represent the camera +# position, focal point, and view respectively. +plot.show_figure(show_axes=True) diff --git a/doc/source/examples/06-plotting/02-solution_combination.py.md5 b/doc/source/examples/06-plotting/02-solution_combination.py.md5 new file mode 100644 index 0000000000..065c5e4a3d --- /dev/null +++ b/doc/source/examples/06-plotting/02-solution_combination.py.md5 @@ -0,0 +1 @@ +e28ac9bd9fdb94a238759a99e2fb30eb \ No newline at end of file diff --git a/doc/source/examples/06-plotting/02-solution_combination.rst b/doc/source/examples/06-plotting/02-solution_combination.rst new file mode 100644 index 0000000000..91772045da --- /dev/null +++ b/doc/source/examples/06-plotting/02-solution_combination.rst @@ -0,0 +1,413 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\06-plotting\02-solution_combination.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_06-plotting_02-solution_combination.py: + + +.. _solution_combination: + +Load case combination for principal stress +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to get a principal stress load case combination using DPF +And highlight min/max values in the plot. + +.. GENERATED FROM PYTHON SOURCE LINES 14-16 + +Import the ``ansys.dpf.core`` module, included examples file, and the ``DpfPlotter`` +module. + +.. GENERATED FROM PYTHON SOURCE LINES 16-20 + +.. code-block:: default + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core.plotter import DpfPlotter + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 21-33 + +Open an example and print 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. + +Printing the model displays this metadata: + +- Analysis type +- Available results +- Size of the mesh +- Number of results + + +.. GENERATED FROM PYTHON SOURCE LINES 33-36 + +.. code-block:: default + + model = dpf.Model(examples.find_msup_transient()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Transient analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - velocity: Nodal Velocity + - acceleration: Nodal Acceleration + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + ------------------------------ + DPF Meshed Region: + 393 nodes + 40 elements + Unit: m + With solid (3D) elements + ------------------------------ + 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 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 37-41 + +Get the stress tensor and ``connect`` time scoping. +Make sure that you define ``dpf.locations.nodal`` as the scoping location because +labels are supported only for nodal results. + + +.. GENERATED FROM PYTHON SOURCE LINES 41-47 + +.. code-block:: default + + stress_tensor = model.results.stress() + time_scope = dpf.Scoping() + time_scope.ids = [1, 2] + stress_tensor.inputs.time_scoping.connect(time_scope) + stress_tensor.inputs.requested_location.connect(dpf.locations.nodal) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-51 + +This code performs solution combination on two load cases, LC1 and LC2. +You can access individual load cases as the fields of a fields container for +the stress tensor. + +.. GENERATED FROM PYTHON SOURCE LINES 51-57 + +.. code-block:: default + + field_lc1 = stress_tensor.outputs.fields_container()[0] + field_lc2 = stress_tensor.outputs.fields_container()[1] + + # Scale LC2 to -1. + stress_tensor_lc2_sc = dpf.operators.math.scale(field=field_lc2, ponderation=-1.0) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 58-59 + +Add load cases. + +.. GENERATED FROM PYTHON SOURCE LINES 59-61 + +.. code-block:: default + + stress_tensor_combi = dpf.operators.math.add(fieldA=field_lc1, fieldB=stress_tensor_lc2_sc) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 62-65 + +Principal stresses are the Eigenvalues of the stress tensor. +Use principal invariants to get S1, S2, and S3. + + +.. GENERATED FROM PYTHON SOURCE LINES 65-68 + +.. code-block:: default + + p_inv = dpf.operators.invariant.principal_invariants() + p_inv.inputs.field.connect(stress_tensor_combi) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 69-71 + +Print S1 (maximum principal stress). + + +.. GENERATED FROM PYTHON SOURCE LINES 71-73 + +.. code-block:: default + + print(p_inv.outputs.field_eig_1().data) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [ 9.89969387e+05 9.86979842e+05 6.46045019e+05 6.48932208e+05 + 1.56976611e+04 2.38335566e+03 2.41021560e+03 1.55569949e+04 + 6.46045018e+05 9.86979841e+05 2.41021536e+03 2.38335517e+03 + 1.40298687e+06 1.40006022e+06 1.51284404e+04 2.32609985e+03 + 1.40006022e+06 2.32609969e+03 1.88584658e+06 1.88308883e+06 + 1.40245029e+04 2.28989834e+03 1.88308883e+06 2.28989838e+03 + 2.43323154e+06 2.43097276e+06 1.13710605e+04 1.92191439e+03 + 2.43097276e+06 1.92191428e+03 3.03740836e+06 3.03544790e+06 + 8.36913086e+03 5.11051169e+03 3.03544790e+06 5.11051165e+03 + 3.68414662e+06 3.68923438e+06 -4.49507141e+03 -3.86970389e+03 + 3.68923438e+06 -3.86970407e+03 4.37493535e+06 4.36801081e+06 + 4.62750323e+04 6.45366758e+04 4.36801080e+06 6.45366739e+04 + 5.00024912e+06 5.15363818e+06 -1.72558410e+05 -1.68506344e+05 + 5.15363818e+06 -1.68506347e+05 5.34040385e+06 6.25295625e+06 + 9.15169741e+05 5.86694135e+05 6.25295625e+06 5.86694135e+05 + 8.19942478e+06 5.11230070e+06 -3.42443463e+06 -1.72869110e+06 + 5.11230070e+06 -1.72869110e+06 3.07108105e+03 4.85742708e+02 + 2.08121801e+03 4.51329102e+03 1.15257484e+04 1.08729694e+04 + 1.48084273e+02 6.58067584e+01 2.08121700e+03 4.85743242e+02 + 1.48084276e+02 1.08729663e+04 3.99734802e+02 2.84198603e+02 + 3.98308935e+04 3.99596263e+04 2.84199027e+02 3.99596267e+04 + 8.05592976e+00 7.63702585e+01 7.02630967e+04 7.11528217e+04 + 7.63704604e+01 7.11528219e+04 4.08416639e+00 8.37761486e+01 + 8.97598110e+04 9.14268559e+04 8.37761220e+01 9.14268560e+04 + 5.48381675e+00 1.42362400e+02 8.58241342e+04 8.84204337e+04 + 1.42362254e+02 8.84204335e+04 1.36280987e+01 1.13419159e+03 + 4.68127641e+04 5.12948274e+04 1.13419050e+03 5.12948265e+04 + 3.78823067e+04 3.90599658e+04 1.20048086e+04 5.25881723e+03 + 3.90599642e+04 5.25881571e+03 1.77336944e+05 1.75477888e+05 + 1.36475040e+04 2.76759779e+03 1.75477887e+05 2.76759705e+03 + 3.79160579e+05 3.76590414e+05 1.48577178e+04 2.47204930e+03 + 3.76590413e+05 2.47204876e+03 9.87954234e+05 8.16487441e+05 + 6.46963602e+05 8.19450620e+05 8.32083289e+03 2.37183132e+03 + 8.24629107e+03 1.56273280e+04 4.22633967e+03 2.09163879e+04 + 1.69460011e+04 3.38679027e+03 6.46963601e+05 8.16487441e+05 + 9.87954234e+05 8.24629092e+03 2.37183096e+03 8.32083271e+03 + 1.69460004e+04 2.09163879e+04 1.40100768e+06 1.19350278e+06 + 1.19647800e+06 8.06338005e+03 2.33617878e+03 1.54130508e+04 + 5.06746339e+03 2.48394848e+04 1.19350278e+06 1.40100768e+06 + 2.33617846e+03 8.06337997e+03 2.48394841e+04 1.88395758e+06 + 1.64156177e+06 1.64441663e+06 7.53335722e+03 2.29511028e+03 + 1.45764717e+04 5.88761468e+03 2.85398928e+04 1.64156177e+06 + 1.88395758e+06 2.29511022e+03 7.53335719e+03 2.85398937e+04 + 2.43161333e+06 2.15701918e+06 2.15953899e+06 6.20773016e+03 + 2.02784724e+03 1.26977817e+04 6.67395032e+03 3.18340564e+04 + 2.15701918e+06 2.43161333e+06 2.02784721e+03 6.20773009e+03 + 3.18340564e+04 3.03594055e+06 2.73320351e+06 2.73531989e+06 + 5.60676164e+03 2.72710830e+03 9.87009570e+03 7.46575696e+03 + 3.45048447e+04 2.73320351e+06 3.03594055e+06 2.72710810e+03 + 5.60676149e+03 3.45048427e+04 3.68631143e+06 3.36231959e+06 + 3.36077747e+06 -4.64521947e+03 -4.02685627e+00 1.93702972e+03 + 8.47413202e+03 3.63891780e+04 3.36231959e+06 3.68631143e+06 + -4.02705347e+00 -4.64521954e+03 3.63891782e+04 4.37097945e+06 + 4.02861843e+06 4.02954094e+06 5.48856888e+04 2.66267135e+04 + 1.70544403e+04 9.30881824e+03 3.76058067e+04 4.02861843e+06 + 4.37097945e+06 2.66267128e+04 5.48856879e+04 3.76058038e+04 + 5.07685002e+06 4.75984186e+06 4.68757240e+06 -1.70825434e+05 + -5.92324427e+04 -6.58878990e+04 3.01483062e+04 2.40997043e+04 + 4.75984186e+06 5.07685002e+06 -5.92324444e+04 -1.70825436e+05 + 2.40996713e+04 5.79541432e+06 5.70261123e+06 5.17030113e+06 + 7.41483955e+05 1.80559706e+05 3.68553935e+05 1.21181294e+04 + 5.77464735e+04 5.70261123e+06 5.79541432e+06 1.80559705e+05 + 7.41483955e+05 5.77464732e+04 6.76007838e+06 6.55138588e+06 + 5.60950676e+06 -1.27232574e+06 -2.58721655e+06 -6.39421513e+05 + 4.13265031e+05 4.45501864e+05 5.60950676e+06 6.55138588e+06 + -6.39421513e+05 -2.58721655e+06 4.45501864e+05 1.61943216e+03 + 3.10965572e+02 2.25636060e+03 3.79218604e+03 1.10854389e+04 + 4.53912469e+03 9.07955770e+01 4.93947446e+03 3.68349703e+02 + 1.18342832e+03 3.42938262e+01 4.05442820e+01 2.25636052e+03 + 3.10965881e+02 1.61943240e+03 9.07956839e+01 4.53912372e+03 + 1.10854373e+04 3.42939134e+01 1.18342850e+03 2.65656153e+02 + 3.16995504e+02 1.73540793e+03 3.98371654e+04 2.53482084e+04 + 2.56765725e+04 4.87884515e+02 1.64634854e+03 3.16995859e+02 + 2.65656367e+02 2.53482069e+04 3.98371655e+04 1.64634882e+03 + 1.20868138e+01 1.53332553e+02 8.34477875e+00 7.06858860e+04 + 5.55323220e+04 5.50465228e+04 4.32272090e+02 1.40242459e+03 + 1.53332839e+02 1.20867966e+01 5.55323222e+04 7.06858860e+04 + 1.40242520e+03 6.52978300e+00 6.11437148e+01 5.82177773e+00 + 9.05926824e+04 8.12697662e+04 8.00112056e+04 2.33592980e+02 + 4.52921390e+02 6.11437305e+01 6.52982809e+00 8.12697663e+04 + 9.05926824e+04 4.52922199e+02 1.01781946e+01 1.06177194e+02 + 4.46460174e+00 8.70987991e+04 8.98867421e+04 8.77916532e+04 + 1.04133938e+02 1.18550598e+03 1.06177120e+02 1.01781534e+01 + 8.98867421e+04 8.70987990e+04 1.18550523e+03 8.92616048e+01 + 3.61429147e+02 7.74169288e+00 4.88073415e+04 6.96187475e+04 + 6.63166348e+04 5.69214730e+02 3.42490749e+03 3.61428542e+02 + 8.92614996e+01 6.96187470e+04 4.88073411e+04 3.42490700e+03 + 3.71947352e+04 7.66384058e+03 1.66212838e+02 7.00641342e+03 + 1.58464803e+04 1.09997182e+04 1.14790002e+03 6.21377392e+03 + 7.66383803e+03 3.71947343e+04 1.58464779e+04 7.00641255e+03 + 6.21377387e+03 1.75780678e+05 1.06374478e+05 1.07603370e+05 + 7.35047360e+03 3.11936342e+03 1.28261563e+04 1.82375472e+03 + 9.46675704e+03 1.06374477e+05 1.75780677e+05 3.11936250e+03 + 7.35047326e+03 9.46675639e+03 3.77331700e+05 2.75920917e+05 + 2.78248027e+05 7.90102104e+03 2.50682872e+03 1.42526109e+04 + 2.57757172e+03 1.30834902e+04 2.75920916e+05 3.77331700e+05 + 2.50682813e+03 7.90102076e+03 1.30834897e+04 5.11273760e+05 + 5.14046095e+05 2.39727952e+03 1.52073563e+04 5.11273759e+05 + 2.39727916e+03] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 74-76 + +Get the meshed region. + + +.. GENERATED FROM PYTHON SOURCE LINES 76-78 + +.. code-block:: default + + mesh_set = model.metadata.meshed_region + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 79-83 + +Plot the results on the mesh. +The ``label_text_size`` and ``label_point_size`` arguments control the font +size of the label. + + +.. GENERATED FROM PYTHON SOURCE LINES 83-90 + +.. code-block:: default + + plot = DpfPlotter() + plot.add_field(p_inv.outputs.field_eig_1(), meshed_region=mesh_set) + + # You can set the camera positions using the ``cpos`` argument. + # The three tuples in the list for the ``cpos`` argument represent the camera + # position, focal point, and view respectively. + plot.show_figure(show_axes=True) + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_02-solution_combination_001.png + :alt: 02 solution combination + :srcset: /examples/06-plotting/images/sphx_glr_02-solution_combination_001.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.619 seconds) + + +.. _sphx_glr_download_examples_06-plotting_02-solution_combination.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 02-solution_combination.py <02-solution_combination.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 02-solution_combination.ipynb <02-solution_combination.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/06-plotting/02-solution_combination_codeobj.pickle b/doc/source/examples/06-plotting/02-solution_combination_codeobj.pickle new file mode 100644 index 0000000000..1dcb4e2388 Binary files /dev/null and b/doc/source/examples/06-plotting/02-solution_combination_codeobj.pickle differ diff --git a/doc/source/examples/06-plotting/03-labels.ipynb b/doc/source/examples/06-plotting/03-labels.ipynb new file mode 100644 index 0000000000..9faa6acaca --- /dev/null +++ b/doc/source/examples/06-plotting/03-labels.ipynb @@ -0,0 +1,133 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Add nodal labels on plots {#labels}\r\n\r\nYou can add use label properties to add custom labels to specific nodes.\r\nIf the label for a node is not defined or [None]{.title-ref}, the nodal\r\nscalar value of the currently active field at that node is shown. If no\r\nfield is active, the node ID is shown.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import the `dpf_core` module, included examples files, and the\r\n`DpfPlotter` module.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core.plotter import DpfPlotter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Open an example and print the `Model` object. The\r\n`Model `{.interpreted-text role=\"class\"}\r\nclass helps to organize access methods for the result by keeping track\r\nof the operators and data sources used by the result file.\r\n\r\nPrinting the model displays this metadata:\r\n\r\n- Analysis type\r\n- Available results\r\n- Size of the mesh\r\n- Number of results\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.find_msup_transient())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the meshed region.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh_set = model.metadata.meshed_region\n\n# One can plot the mesh with labels and/or node IDs shown\n# for the first five nodes of the mesh.\nplot = DpfPlotter()\nplot.add_node_labels(\n nodes=mesh_set.nodes.scoping.ids[:5],\n meshed_region=mesh_set,\n labels=[\"A\", \"B\", None, \"C\"],\n font_size=50,\n)\nplot.show_figure(\n cpos=[\n (0.3533494514377904, 0.312496303079723, 1.1859368974825752),\n (-0.07891143256220956, -0.11976458092027707, 0.7536760134825755),\n (0.0, 0.0, 1.0),\n ]\n)\n# sphinx_gallery_thumbnail_number = 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the stress tensor and `connect` time scoping. Make sure that you\r\ndefine `dpf.locations.nodal` as the scoping location because labels are\r\nsupported only for nodal results.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "stress_tensor = model.results.stress()\nstress_tensor.inputs.time_scoping([20])\nstress_tensor.inputs.requested_location(dpf.locations.nodal)\n# field = stress_tensor.outputs.fields_container.get_data()[0]\n\nnorm_op = dpf.operators.math.norm_fc()\nnorm_op.inputs.connect(stress_tensor)\nfield_norm_stress = norm_op.outputs.fields_container()[0]\nprint(field_norm_stress)\n\nnorm_op2 = dpf.Operator(\"norm_fc\")\ndisp = model.results.displacement()\ndisp.inputs.time_scoping.connect([20])\nnorm_op2.inputs.connect(disp.outputs)\nfield_norm_disp = norm_op2.outputs.fields_container()[0]\nprint(field_norm_disp)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the results on the mesh and show the minimum and maximum.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plot = DpfPlotter()\nplot.add_field(\n field_norm_stress,\n meshed_region=mesh_set,\n show_max=True,\n show_min=True,\n label_text_size=30,\n label_point_size=5,\n)\n\n\n# Use label properties to add custom labels to specific nodes.\n# If a label for a node is missing and a field is active,\n# the nodal value for this field is shown.\n\nmy_nodes_1 = [mesh_set.nodes[0], mesh_set.nodes[10]]\nmy_labels_1 = [\"MyNode1\", \"MyNode2\"]\nplot.add_node_labels(\n my_nodes_1,\n mesh_set,\n my_labels_1,\n italic=True,\n bold=True,\n font_size=26,\n text_color=\"white\",\n font_family=\"courier\",\n shadow=True,\n point_color=\"grey\",\n point_size=20,\n)\n\nmy_nodes_2 = [mesh_set.nodes[18], mesh_set.nodes[30]]\nmy_labels_2 = [] # [\"MyNode3\"]\nplot.add_node_labels(\n my_nodes_2,\n mesh_set,\n my_labels_2,\n font_size=15,\n text_color=\"black\",\n font_family=\"arial\",\n shadow=False,\n point_color=\"white\",\n point_size=15,\n)\n\n# Show figure.\n# You can set the camera positions using the ``cpos`` argument.\n# The three tuples in the list for the ``cpos`` argument represent the camera\n# position, focal point, and view respectively.\nplot.show_figure(\n show_axes=True,\n cpos=[(0.123, 0.095, 1.069), (-0.121, -0.149, 0.825), (0.0, 0.0, 1.0)],\n)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/06-plotting/03-labels.py b/doc/source/examples/06-plotting/03-labels.py new file mode 100644 index 0000000000..7413849b35 --- /dev/null +++ b/doc/source/examples/06-plotting/03-labels.py @@ -0,0 +1,136 @@ +""" +.. _labels: + +Add nodal labels on plots +~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can add use label properties to add custom labels to specific nodes. +If the label for a node is not defined or `None`, the nodal scalar value +of the currently active field at that node is shown. If no field is active, +the node ID is shown. +""" + +############################################################################### +# Import the ``dpf_core`` module, included examples files, and the ``DpfPlotter`` +# module. +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core.plotter import DpfPlotter + +############################################################################### +# Open an example and print 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. +# +# Printing the model displays this metadata: +# +# - Analysis type +# - Available results +# - Size of the mesh +# - Number of results +# +model = dpf.Model(examples.find_msup_transient()) +print(model) + +############################################################################### +# Get the meshed region. +# +mesh_set = model.metadata.meshed_region + +# One can plot the mesh with labels and/or node IDs shown +# for the first five nodes of the mesh. +plot = DpfPlotter() +plot.add_node_labels( + nodes=mesh_set.nodes.scoping.ids[:5], + meshed_region=mesh_set, + labels=["A", "B", None, "C"], + font_size=50, +) +plot.show_figure( + cpos=[ + (0.3533494514377904, 0.312496303079723, 1.1859368974825752), + (-0.07891143256220956, -0.11976458092027707, 0.7536760134825755), + (0.0, 0.0, 1.0), + ] +) +# sphinx_gallery_thumbnail_number = 2 + +############################################################################### +# Get the stress tensor and ``connect`` time scoping. +# Make sure that you define ``dpf.locations.nodal`` as the scoping location because +# labels are supported only for nodal results. +# +stress_tensor = model.results.stress() +stress_tensor.inputs.time_scoping([20]) +stress_tensor.inputs.requested_location(dpf.locations.nodal) +# field = stress_tensor.outputs.fields_container.get_data()[0] + +norm_op = dpf.operators.math.norm_fc() +norm_op.inputs.connect(stress_tensor) +field_norm_stress = norm_op.outputs.fields_container()[0] +print(field_norm_stress) + +norm_op2 = dpf.Operator("norm_fc") +disp = model.results.displacement() +disp.inputs.time_scoping.connect([20]) +norm_op2.inputs.connect(disp.outputs) +field_norm_disp = norm_op2.outputs.fields_container()[0] +print(field_norm_disp) + +############################################################################### +# Plot the results on the mesh and show the minimum and maximum. +# +plot = DpfPlotter() +plot.add_field( + field_norm_stress, + meshed_region=mesh_set, + show_max=True, + show_min=True, + label_text_size=30, + label_point_size=5, +) + + +# Use label properties to add custom labels to specific nodes. +# If a label for a node is missing and a field is active, +# the nodal value for this field is shown. + +my_nodes_1 = [mesh_set.nodes[0], mesh_set.nodes[10]] +my_labels_1 = ["MyNode1", "MyNode2"] +plot.add_node_labels( + my_nodes_1, + mesh_set, + my_labels_1, + italic=True, + bold=True, + font_size=26, + text_color="white", + font_family="courier", + shadow=True, + point_color="grey", + point_size=20, +) + +my_nodes_2 = [mesh_set.nodes[18], mesh_set.nodes[30]] +my_labels_2 = [] # ["MyNode3"] +plot.add_node_labels( + my_nodes_2, + mesh_set, + my_labels_2, + font_size=15, + text_color="black", + font_family="arial", + shadow=False, + point_color="white", + point_size=15, +) + +# Show figure. +# You can set the camera positions using the ``cpos`` argument. +# The three tuples in the list for the ``cpos`` argument represent the camera +# position, focal point, and view respectively. +plot.show_figure( + show_axes=True, + cpos=[(0.123, 0.095, 1.069), (-0.121, -0.149, 0.825), (0.0, 0.0, 1.0)], +) diff --git a/doc/source/examples/06-plotting/03-labels.py.md5 b/doc/source/examples/06-plotting/03-labels.py.md5 new file mode 100644 index 0000000000..69350f3a9e --- /dev/null +++ b/doc/source/examples/06-plotting/03-labels.py.md5 @@ -0,0 +1 @@ +d01db5fc6e1145335d2c18d99fbf5755 \ No newline at end of file diff --git a/doc/source/examples/06-plotting/03-labels.rst b/doc/source/examples/06-plotting/03-labels.rst new file mode 100644 index 0000000000..1561abc2bc --- /dev/null +++ b/doc/source/examples/06-plotting/03-labels.rst @@ -0,0 +1,352 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\06-plotting\03-labels.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_06-plotting_03-labels.py: + + +.. _labels: + +Add nodal labels on plots +~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can add use label properties to add custom labels to specific nodes. +If the label for a node is not defined or `None`, the nodal scalar value +of the currently active field at that node is shown. If no field is active, +the node ID is shown. + +.. GENERATED FROM PYTHON SOURCE LINES 14-16 + +Import the ``dpf_core`` module, included examples files, and the ``DpfPlotter`` +module. + +.. GENERATED FROM PYTHON SOURCE LINES 16-20 + +.. code-block:: default + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core.plotter import DpfPlotter + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 21-33 + +Open an example and print 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. + +Printing the model displays this metadata: + +- Analysis type +- Available results +- Size of the mesh +- Number of results + + +.. GENERATED FROM PYTHON SOURCE LINES 33-36 + +.. code-block:: default + + model = dpf.Model(examples.find_msup_transient()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Transient analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - velocity: Nodal Velocity + - acceleration: Nodal Acceleration + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + ------------------------------ + DPF Meshed Region: + 393 nodes + 40 elements + Unit: m + With solid (3D) elements + ------------------------------ + 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 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 37-39 + +Get the meshed region. + + +.. GENERATED FROM PYTHON SOURCE LINES 39-59 + +.. code-block:: default + + mesh_set = model.metadata.meshed_region + + # One can plot the mesh with labels and/or node IDs shown + # for the first five nodes of the mesh. + plot = DpfPlotter() + plot.add_node_labels( + nodes=mesh_set.nodes.scoping.ids[:5], + meshed_region=mesh_set, + labels=["A", "B", None, "C"], + font_size=50, + ) + plot.show_figure( + cpos=[ + (0.3533494514377904, 0.312496303079723, 1.1859368974825752), + (-0.07891143256220956, -0.11976458092027707, 0.7536760134825755), + (0.0, 0.0, 1.0), + ] + ) + # sphinx_gallery_thumbnail_number = 2 + + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_03-labels_001.png + :alt: 03 labels + :srcset: /examples/06-plotting/images/sphx_glr_03-labels_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 60-64 + +Get the stress tensor and ``connect`` time scoping. +Make sure that you define ``dpf.locations.nodal`` as the scoping location because +labels are supported only for nodal results. + + +.. GENERATED FROM PYTHON SOURCE LINES 64-81 + +.. code-block:: default + + stress_tensor = model.results.stress() + stress_tensor.inputs.time_scoping([20]) + stress_tensor.inputs.requested_location(dpf.locations.nodal) + # field = stress_tensor.outputs.fields_container.get_data()[0] + + norm_op = dpf.operators.math.norm_fc() + norm_op.inputs.connect(stress_tensor) + field_norm_stress = norm_op.outputs.fields_container()[0] + print(field_norm_stress) + + norm_op2 = dpf.Operator("norm_fc") + disp = model.results.displacement() + disp.inputs.time_scoping.connect([20]) + norm_op2.inputs.connect(disp.outputs) + field_norm_disp = norm_op2.outputs.fields_container()[0] + print(field_norm_disp) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF stress_0,2s Field + Location: Nodal + Unit: Pa + 393 entities + Data: 1 components and 393 elementary data + + Nodal + IDs data(Pa) + ------------ ---------- + 9 1.400332e+07 + + 96 1.399264e+07 + + 95 1.171429e+07 + + ... + + + DPF displacement_0,2s Field + Location: Nodal + Unit: m + 393 entities + Data: 1 components and 393 elementary data + + Nodal + IDs data(m) + ------------ ---------- + 9 3.106681e-03 + + 96 3.101395e-03 + + 95 3.714017e-03 + + ... + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 82-84 + +Plot the results on the mesh and show the minimum and maximum. + + +.. GENERATED FROM PYTHON SOURCE LINES 84-137 + +.. code-block:: default + + plot = DpfPlotter() + plot.add_field( + field_norm_stress, + meshed_region=mesh_set, + show_max=True, + show_min=True, + label_text_size=30, + label_point_size=5, + ) + + + # Use label properties to add custom labels to specific nodes. + # If a label for a node is missing and a field is active, + # the nodal value for this field is shown. + + my_nodes_1 = [mesh_set.nodes[0], mesh_set.nodes[10]] + my_labels_1 = ["MyNode1", "MyNode2"] + plot.add_node_labels( + my_nodes_1, + mesh_set, + my_labels_1, + italic=True, + bold=True, + font_size=26, + text_color="white", + font_family="courier", + shadow=True, + point_color="grey", + point_size=20, + ) + + my_nodes_2 = [mesh_set.nodes[18], mesh_set.nodes[30]] + my_labels_2 = [] # ["MyNode3"] + plot.add_node_labels( + my_nodes_2, + mesh_set, + my_labels_2, + font_size=15, + text_color="black", + font_family="arial", + shadow=False, + point_color="white", + point_size=15, + ) + + # Show figure. + # You can set the camera positions using the ``cpos`` argument. + # The three tuples in the list for the ``cpos`` argument represent the camera + # position, focal point, and view respectively. + plot.show_figure( + show_axes=True, + cpos=[(0.123, 0.095, 1.069), (-0.121, -0.149, 0.825), (0.0, 0.0, 1.0)], + ) + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_03-labels_002.png + :alt: 03 labels + :srcset: /examples/06-plotting/images/sphx_glr_03-labels_002.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 1.211 seconds) + + +.. _sphx_glr_download_examples_06-plotting_03-labels.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 03-labels.py <03-labels.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 03-labels.ipynb <03-labels.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/06-plotting/03-labels_codeobj.pickle b/doc/source/examples/06-plotting/03-labels_codeobj.pickle new file mode 100644 index 0000000000..8facda5370 Binary files /dev/null and b/doc/source/examples/06-plotting/03-labels_codeobj.pickle differ diff --git a/doc/source/examples/06-plotting/04-plot_on_path.ipynb b/doc/source/examples/06-plotting/04-plot_on_path.ipynb new file mode 100644 index 0000000000..6d36413538 --- /dev/null +++ b/doc/source/examples/06-plotting/04-plot_on_path.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot results on a specific path {#plot_on_path}\r\n\r\nThis example shows how to get a result mapped over a specific path and\r\nhow to plot it.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops\nfrom ansys.dpf.core.plotter import DpfPlotter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot path\r\n\r\nUse the `ansys.dpf.core.plotter.DpfPlotter`{.interpreted-text\r\nrole=\"class\"} class to plot a mapped result over a defined path of\r\ncoordinates.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Create the model and request its mesh and displacement data.\nmodel = dpf.Model(examples.find_static_rst())\nmesh = model.metadata.meshed_region\nstress_fc = model.results.stress().eqv().eval()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a coordinates field to map on.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "coordinates = [[0.024, 0.03, 0.003]]\ndelta = 0.001\nn_points = 51\nfor i in range(1, n_points):\n coord_copy = coordinates[0].copy()\n coord_copy[1] = coord_copy[0] + i * delta\n coordinates.append(coord_copy)\nfield_coord = dpf.fields_factory.create_3d_vector_field(len(coordinates))\nfield_coord.data = coordinates\nfield_coord.scoping.ids = list(range(1, len(coordinates) + 1))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute the mapped data using the mapping operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mapping_operator = ops.mapping.on_coordinates(\n fields_container=stress_fc, coordinates=field_coord, create_support=True, mesh=mesh\n)\nfields_mapped = mapping_operator.outputs.fields_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Request the mapped field data and its mesh.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "field_m = fields_mapped[0]\nmesh_m = field_m.meshed_region" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the plotter and add fields and meshes.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pl = DpfPlotter()\n\npl.add_field(field_m, mesh_m)\npl.add_mesh(mesh, style=\"surface\", show_edges=True, color=\"w\", opacity=0.3)\n\n# Plot the result.\npl.show_figure(show_axes=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the solution along the specified line. Note that since the line is\r\nonly moving along the y-axis, the stresses are plotted with respect to\r\nthe y coordinate.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "y_coords = [mesh_m.nodes.coordinates_field.data[i][1] for i in range(mesh_m.nodes.n_nodes)]\nplt.plot(y_coords, field_m.data, \"r\")\nplt.xlabel(f\"y-coordinate [{mesh.unit}]\")\nplt.ylabel(f\"Stress [{field_m.unit}]\")\nplt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/06-plotting/04-plot_on_path.py b/doc/source/examples/06-plotting/04-plot_on_path.py new file mode 100644 index 0000000000..eb1ffbb8c3 --- /dev/null +++ b/doc/source/examples/06-plotting/04-plot_on_path.py @@ -0,0 +1,74 @@ +# noqa: D400 +""" +.. _plot_on_path: + +Plot results on a specific path +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to get a result mapped over a specific path +and how to plot it. + +""" + +import matplotlib.pyplot as plt + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops +from ansys.dpf.core.plotter import DpfPlotter + + +############################################################################### +# Plot path +# ~~~~~~~~~ +# Use the :class:`ansys.dpf.core.plotter.DpfPlotter` class to plot a mapped +# result over a defined path of coordinates. + +# Create the model and request its mesh and displacement data. +model = dpf.Model(examples.find_static_rst()) +mesh = model.metadata.meshed_region +stress_fc = model.results.stress().eqv().eval() + +############################################################################### +# Create a coordinates field to map on. +coordinates = [[0.024, 0.03, 0.003]] +delta = 0.001 +n_points = 51 +for i in range(1, n_points): + coord_copy = coordinates[0].copy() + coord_copy[1] = coord_copy[0] + i * delta + coordinates.append(coord_copy) +field_coord = dpf.fields_factory.create_3d_vector_field(len(coordinates)) +field_coord.data = coordinates +field_coord.scoping.ids = list(range(1, len(coordinates) + 1)) + +############################################################################### +# Compute the mapped data using the mapping operator. +mapping_operator = ops.mapping.on_coordinates( + fields_container=stress_fc, coordinates=field_coord, create_support=True, mesh=mesh +) +fields_mapped = mapping_operator.outputs.fields_container() + +############################################################################### +# Request the mapped field data and its mesh. +field_m = fields_mapped[0] +mesh_m = field_m.meshed_region + +############################################################################### +# Create the plotter and add fields and meshes. +pl = DpfPlotter() + +pl.add_field(field_m, mesh_m) +pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) + +# Plot the result. +pl.show_figure(show_axes=True) + +############################################################################### +# Plot the solution along the specified line. Note that since the line is only +# moving along the y-axis, the stresses are plotted with respect to the y coordinate. +y_coords = [mesh_m.nodes.coordinates_field.data[i][1] for i in range(mesh_m.nodes.n_nodes)] +plt.plot(y_coords, field_m.data, "r") +plt.xlabel(f"y-coordinate [{mesh.unit}]") +plt.ylabel(f"Stress [{field_m.unit}]") +plt.show() diff --git a/doc/source/examples/06-plotting/04-plot_on_path.py.md5 b/doc/source/examples/06-plotting/04-plot_on_path.py.md5 new file mode 100644 index 0000000000..d970548cd2 --- /dev/null +++ b/doc/source/examples/06-plotting/04-plot_on_path.py.md5 @@ -0,0 +1 @@ +4da07a8cd100a6c10da567ebdc0bf9e8 \ No newline at end of file diff --git a/doc/source/examples/06-plotting/04-plot_on_path.rst b/doc/source/examples/06-plotting/04-plot_on_path.rst new file mode 100644 index 0000000000..c8c222dca8 --- /dev/null +++ b/doc/source/examples/06-plotting/04-plot_on_path.rst @@ -0,0 +1,217 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\06-plotting\04-plot_on_path.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_06-plotting_04-plot_on_path.py: + + +.. _plot_on_path: + +Plot results on a specific path +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to get a result mapped over a specific path +and how to plot it. + +.. GENERATED FROM PYTHON SOURCE LINES 12-21 + +.. code-block:: default + + + import matplotlib.pyplot as plt + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + from ansys.dpf.core.plotter import DpfPlotter + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-26 + +Plot path +~~~~~~~~~ +Use the :class:`ansys.dpf.core.plotter.DpfPlotter` class to plot a mapped +result over a defined path of coordinates. + +.. GENERATED FROM PYTHON SOURCE LINES 26-32 + +.. code-block:: default + + + # Create the model and request its mesh and displacement data. + model = dpf.Model(examples.find_static_rst()) + mesh = model.metadata.meshed_region + stress_fc = model.results.stress().eqv().eval() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 33-34 + +Create a coordinates field to map on. + +.. GENERATED FROM PYTHON SOURCE LINES 34-45 + +.. code-block:: default + + coordinates = [[0.024, 0.03, 0.003]] + delta = 0.001 + n_points = 51 + for i in range(1, n_points): + coord_copy = coordinates[0].copy() + coord_copy[1] = coord_copy[0] + i * delta + coordinates.append(coord_copy) + field_coord = dpf.fields_factory.create_3d_vector_field(len(coordinates)) + field_coord.data = coordinates + field_coord.scoping.ids = list(range(1, len(coordinates) + 1)) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 46-47 + +Compute the mapped data using the mapping operator. + +.. GENERATED FROM PYTHON SOURCE LINES 47-52 + +.. code-block:: default + + mapping_operator = ops.mapping.on_coordinates( + fields_container=stress_fc, coordinates=field_coord, create_support=True, mesh=mesh + ) + fields_mapped = mapping_operator.outputs.fields_container() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 53-54 + +Request the mapped field data and its mesh. + +.. GENERATED FROM PYTHON SOURCE LINES 54-57 + +.. code-block:: default + + field_m = fields_mapped[0] + mesh_m = field_m.meshed_region + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 58-59 + +Create the plotter and add fields and meshes. + +.. GENERATED FROM PYTHON SOURCE LINES 59-67 + +.. code-block:: default + + pl = DpfPlotter() + + pl.add_field(field_m, mesh_m) + pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) + + # Plot the result. + pl.show_figure(show_axes=True) + + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_04-plot_on_path_001.png + :alt: 04 plot on path + :srcset: /examples/06-plotting/images/sphx_glr_04-plot_on_path_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 68-70 + +Plot the solution along the specified line. Note that since the line is only +moving along the y-axis, the stresses are plotted with respect to the y coordinate. + +.. GENERATED FROM PYTHON SOURCE LINES 70-75 + +.. code-block:: default + + y_coords = [mesh_m.nodes.coordinates_field.data[i][1] for i in range(mesh_m.nodes.n_nodes)] + plt.plot(y_coords, field_m.data, "r") + plt.xlabel(f"y-coordinate [{mesh.unit}]") + plt.ylabel(f"Stress [{field_m.unit}]") + plt.show() + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_04-plot_on_path_002.png + :alt: 04 plot on path + :srcset: /examples/06-plotting/images/sphx_glr_04-plot_on_path_002.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 0.759 seconds) + + +.. _sphx_glr_download_examples_06-plotting_04-plot_on_path.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 04-plot_on_path.py <04-plot_on_path.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 04-plot_on_path.ipynb <04-plot_on_path.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/06-plotting/04-plot_on_path_codeobj.pickle b/doc/source/examples/06-plotting/04-plot_on_path_codeobj.pickle new file mode 100644 index 0000000000..e8eaa8af89 Binary files /dev/null and b/doc/source/examples/06-plotting/04-plot_on_path_codeobj.pickle differ diff --git a/doc/source/examples/06-plotting/05-plot_on_warped_mesh.ipynb b/doc/source/examples/06-plotting/05-plot_on_warped_mesh.ipynb new file mode 100644 index 0000000000..7e997dd68f --- /dev/null +++ b/doc/source/examples/06-plotting/05-plot_on_warped_mesh.ipynb @@ -0,0 +1,54 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Warp the mesh by a field for plotting {#plot_on_warped_mesh}\r\n\r\nThis example shows how to warp the mesh by a vector field, enabling to\r\nplot on the deformed geometry.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\n\n\n# Get and show the initial model\nmodel = dpf.Model(examples.find_multishells_rst())\nprint(model)\nmodel.plot(title=\"Model\", text=\"Model.plot()\")\n\n# Define a scaling factor and a step for the field to be used for warping.\nscale_factor = 0.001\nstep = 1\n\n# Define a result to deform by\ndisp_result = model.results.displacement.on_time_scoping([step])\ndisp_op = disp_result()\n# Get the displacement field\ndisp_fc = disp_result.eval()\ndisp_field = disp_fc[0]\n\n# Get the mesh and plot it as a deformed geometry using a Result, an Operator,\n# a Field or a FieldsContainer\nmesh = model.metadata.meshed_region\nmesh.plot(\n deform_by=disp_result,\n scale_factor=scale_factor,\n title=\"MeshedRegion\",\n text=\"MeshedRegion.plot()\",\n)\n# mesh.plot(deform_by=disp_op, scale_factor=scale_factor,\n# title='MeshedRegion', text='MeshedRegion.plot()')\n# mesh.plot(deform_by=disp_fc, scale_factor=scale_factor,\n# title='MeshedRegion', text='MeshedRegion.plot()')\n# mesh.plot(deform_by=disp_field, scale_factor=scale_factor,\n# title='MeshedRegion', text='MeshedRegion.plot()')\n\n# Plot the displacement field on the deformed geometry directly\ndisp_field.plot(\n deform_by=disp_result, scale_factor=scale_factor, title=\"Field\", text=\"Field.plot()\"\n)\n# or by applying it to the mesh\nmesh.plot(\n disp_field,\n deform_by=disp_result,\n scale_factor=scale_factor,\n title=\"MeshedRegion\",\n text=\"MeshedRegion.plot(disp_field)\",\n)\n\n# Split the model by material and plot the deformed MeshesContainer obtained\nsplit_mesh_op = dpf.operators.mesh.split_mesh(mesh=mesh, property=\"mat\")\nmeshes_cont = split_mesh_op.get_output(0, dpf.types.meshes_container)\nmeshes_cont.plot(\n deform_by=disp_result,\n scale_factor=scale_factor,\n title=\"MeshesContainer\",\n text=\"MeshesContainer.plot()\",\n)\n\n# Create a corresponding FieldsContainer and plot it on the deformed MeshesContainer\ndisp_op = dpf.operators.result.displacement(\n data_sources=model.metadata.data_sources, mesh=meshes_cont\n)\ndisp_fc = disp_op.outputs.fields_container()\nmeshes_cont.plot(\n disp_fc,\n deform_by=disp_result,\n scale_factor=scale_factor,\n title=\"MeshesContainer\",\n text=\"MeshesContainer.plot(disp_fc)\",\n)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/06-plotting/05-plot_on_warped_mesh.py b/doc/source/examples/06-plotting/05-plot_on_warped_mesh.py new file mode 100644 index 0000000000..a32a362653 --- /dev/null +++ b/doc/source/examples/06-plotting/05-plot_on_warped_mesh.py @@ -0,0 +1,82 @@ +""" +.. _plot_on_warped_mesh: + +Warp the mesh by a field for plotting +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to warp the mesh by a vector field, +enabling to plot on the deformed geometry. + +""" + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + + +# Get and show the initial model +model = dpf.Model(examples.find_multishells_rst()) +print(model) +model.plot(title="Model", text="Model.plot()") + +# Define a scaling factor and a step for the field to be used for warping. +scale_factor = 0.001 +step = 1 + +# Define a result to deform by +disp_result = model.results.displacement.on_time_scoping([step]) +disp_op = disp_result() +# Get the displacement field +disp_fc = disp_result.eval() +disp_field = disp_fc[0] + +# Get the mesh and plot it as a deformed geometry using a Result, an Operator, +# a Field or a FieldsContainer +mesh = model.metadata.meshed_region +mesh.plot( + deform_by=disp_result, + scale_factor=scale_factor, + title="MeshedRegion", + text="MeshedRegion.plot()", +) +# mesh.plot(deform_by=disp_op, scale_factor=scale_factor, +# title='MeshedRegion', text='MeshedRegion.plot()') +# mesh.plot(deform_by=disp_fc, scale_factor=scale_factor, +# title='MeshedRegion', text='MeshedRegion.plot()') +# mesh.plot(deform_by=disp_field, scale_factor=scale_factor, +# title='MeshedRegion', text='MeshedRegion.plot()') + +# Plot the displacement field on the deformed geometry directly +disp_field.plot( + deform_by=disp_result, scale_factor=scale_factor, title="Field", text="Field.plot()" +) +# or by applying it to the mesh +mesh.plot( + disp_field, + deform_by=disp_result, + scale_factor=scale_factor, + title="MeshedRegion", + text="MeshedRegion.plot(disp_field)", +) + +# Split the model by material and plot the deformed MeshesContainer obtained +split_mesh_op = dpf.operators.mesh.split_mesh(mesh=mesh, property="mat") +meshes_cont = split_mesh_op.get_output(0, dpf.types.meshes_container) +meshes_cont.plot( + deform_by=disp_result, + scale_factor=scale_factor, + title="MeshesContainer", + text="MeshesContainer.plot()", +) + +# Create a corresponding FieldsContainer and plot it on the deformed MeshesContainer +disp_op = dpf.operators.result.displacement( + data_sources=model.metadata.data_sources, mesh=meshes_cont +) +disp_fc = disp_op.outputs.fields_container() +meshes_cont.plot( + disp_fc, + deform_by=disp_result, + scale_factor=scale_factor, + title="MeshesContainer", + text="MeshesContainer.plot(disp_fc)", +) diff --git a/doc/source/examples/06-plotting/05-plot_on_warped_mesh.py.md5 b/doc/source/examples/06-plotting/05-plot_on_warped_mesh.py.md5 new file mode 100644 index 0000000000..069a441f7d --- /dev/null +++ b/doc/source/examples/06-plotting/05-plot_on_warped_mesh.py.md5 @@ -0,0 +1 @@ +add449d57988ed44c9f027dded0d0c7f \ No newline at end of file diff --git a/doc/source/examples/06-plotting/05-plot_on_warped_mesh.rst b/doc/source/examples/06-plotting/05-plot_on_warped_mesh.rst new file mode 100644 index 0000000000..0841452ed0 --- /dev/null +++ b/doc/source/examples/06-plotting/05-plot_on_warped_mesh.rst @@ -0,0 +1,233 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\06-plotting\05-plot_on_warped_mesh.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_06-plotting_05-plot_on_warped_mesh.py: + + +.. _plot_on_warped_mesh: + +Warp the mesh by a field for plotting +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to warp the mesh by a vector field, +enabling to plot on the deformed geometry. + +.. GENERATED FROM PYTHON SOURCE LINES 11-83 + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_001.png + :alt: 05 plot on warped mesh + :srcset: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_002.png + :alt: 05 plot on warped mesh + :srcset: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_002.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_003.png + :alt: 05 plot on warped mesh + :srcset: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_003.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_004.png + :alt: 05 plot on warped mesh + :srcset: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_004.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_005.png + :alt: 05 plot on warped mesh + :srcset: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_005.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_006.png + :alt: 05 plot on warped mesh + :srcset: /examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_006.png + :class: sphx-glr-multi-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + - contact_status: ElementalNodal Contact Status + - contact_penetration: ElementalNodal Contact Penetration + - contact_pressure: ElementalNodal Contact Pressure + - contact_friction_stress: ElementalNodal Contact Friction Stress + - contact_total_stress: ElementalNodal Contact Total Stress + - contact_sliding_distance: ElementalNodal Contact Sliding Distance + - contact_gap_distance: ElementalNodal Contact Gap Distance + - total_heat_flux_at_contact_surface: ElementalNodal Total heat flux at contact surface + - contact_status_changes: ElementalNodal Contact status changes + - fluid_penetration_pressure: ElementalNodal Fluid Penetration Pressure + ------------------------------ + DPF Meshed Region: + 7079 nodes + 4220 elements + Unit: m + With solid (3D) elements, shell (2D) elements, shell (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1 + Cumulative Time (s) LoadStep Substep + 1 1,000000 1 1 + + + + + + + +| + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + # Get and show the initial model + model = dpf.Model(examples.find_multishells_rst()) + print(model) + model.plot(title="Model", text="Model.plot()") + + # Define a scaling factor and a step for the field to be used for warping. + scale_factor = 0.001 + step = 1 + + # Define a result to deform by + disp_result = model.results.displacement.on_time_scoping([step]) + disp_op = disp_result() + # Get the displacement field + disp_fc = disp_result.eval() + disp_field = disp_fc[0] + + # Get the mesh and plot it as a deformed geometry using a Result, an Operator, + # a Field or a FieldsContainer + mesh = model.metadata.meshed_region + mesh.plot( + deform_by=disp_result, + scale_factor=scale_factor, + title="MeshedRegion", + text="MeshedRegion.plot()", + ) + # mesh.plot(deform_by=disp_op, scale_factor=scale_factor, + # title='MeshedRegion', text='MeshedRegion.plot()') + # mesh.plot(deform_by=disp_fc, scale_factor=scale_factor, + # title='MeshedRegion', text='MeshedRegion.plot()') + # mesh.plot(deform_by=disp_field, scale_factor=scale_factor, + # title='MeshedRegion', text='MeshedRegion.plot()') + + # Plot the displacement field on the deformed geometry directly + disp_field.plot( + deform_by=disp_result, scale_factor=scale_factor, title="Field", text="Field.plot()" + ) + # or by applying it to the mesh + mesh.plot( + disp_field, + deform_by=disp_result, + scale_factor=scale_factor, + title="MeshedRegion", + text="MeshedRegion.plot(disp_field)", + ) + + # Split the model by material and plot the deformed MeshesContainer obtained + split_mesh_op = dpf.operators.mesh.split_mesh(mesh=mesh, property="mat") + meshes_cont = split_mesh_op.get_output(0, dpf.types.meshes_container) + meshes_cont.plot( + deform_by=disp_result, + scale_factor=scale_factor, + title="MeshesContainer", + text="MeshesContainer.plot()", + ) + + # Create a corresponding FieldsContainer and plot it on the deformed MeshesContainer + disp_op = dpf.operators.result.displacement( + data_sources=model.metadata.data_sources, mesh=meshes_cont + ) + disp_fc = disp_op.outputs.fields_container() + meshes_cont.plot( + disp_fc, + deform_by=disp_result, + scale_factor=scale_factor, + title="MeshesContainer", + text="MeshesContainer.plot(disp_fc)", + ) + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 5.388 seconds) + + +.. _sphx_glr_download_examples_06-plotting_05-plot_on_warped_mesh.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 05-plot_on_warped_mesh.py <05-plot_on_warped_mesh.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 05-plot_on_warped_mesh.ipynb <05-plot_on_warped_mesh.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/06-plotting/05-plot_on_warped_mesh_codeobj.pickle b/doc/source/examples/06-plotting/05-plot_on_warped_mesh_codeobj.pickle new file mode 100644 index 0000000000..46dcc1803f Binary files /dev/null and b/doc/source/examples/06-plotting/05-plot_on_warped_mesh_codeobj.pickle differ diff --git a/doc/source/examples/06-plotting/06-animate_results.ipynb b/doc/source/examples/06-plotting/06-animate_results.ipynb new file mode 100644 index 0000000000..51163e05ea --- /dev/null +++ b/doc/source/examples/06-plotting/06-animate_results.ipynb @@ -0,0 +1,54 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Review of available animation commands {#animate_results}\r\n\r\nThis example lists the different commands available for creating\r\nanimations of transient results, shown with the arguments available.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\n\n\n# Load the model\nmodel = dpf.Model(examples.find_msup_transient())\nprint(model)\n\n# Use Scoping instances to adjust the region and the steps involved.\n# Create a scoping on all nodes\nmesh_scoping = dpf.mesh_scoping_factory.nodal_scoping(model.metadata.meshed_region.nodes.scoping)\n# Create a scoping on all time steps\ntime_scoping = dpf.time_freq_scoping_factory.scoping_on_all_time_freqs(model)\n\n# Instantiate operators of interest and scope them\ndisplacement_op = model.results.displacement\ndisplacement_op = displacement_op.on_time_scoping(time_scoping)\ndisplacement_op = displacement_op.on_mesh_scoping(mesh_scoping)\nstress_op = model.results.stress\nstress_op = stress_op.on_time_scoping(time_scoping)\nstress_op = stress_op.on_mesh_scoping(mesh_scoping)\n\n# Get the resulting fields container\ndisplacement_fields = displacement_op.eval()\nstress_fields = stress_op.eval()\n\n# Animate a fields container by going through the fields and plotting contours\n# of the norm or of the selected component.\n# Default behavior consists in:\n# - Using a constant and uniform scale factor of 1.0\n# - Showing the deformed geometry based on the fields themselves if they are nodal 3D vector fields.\n# displacement_fields.animate()\n# - Showing the static geometry if the fields are not nodal 3D vector fields.\n# stress_fields.animate()\n\n# One can deactivate by default animation by self using deform_by=False\n# displacement_fields.animate(deform_by=False)\n\n# Change the scale factor using a number/a list of numbers for a uniform constant/varying scaling.\n# displacement_fields.animate(deform_by=True, scale_factor=10.,\n# show_axes=True)\n# varying_scale_factor = [i for i in range(len(displacement_fields))]\n# displacement_fields.animate(deform_by=True, scale_factor=varying_scale_factor,\n# show_axes=True)\n\n# One can also format the frequency legend.\n# displacement_fields.select_component(0).animate(deform_by=displacement_fields, scale_factor=1.,\n# show_axes=True,\n# freq_kwargs={\"font_size\": 12,\n# \"fmt\": \".3\"})\n\n# The deform_by argument can be:\n# - a FieldsContainer of nodal 3D vectorial length fields\n# stress_fields.animate(deform_by=model.results.displacement.on_all_time_freqs.eval())\n# - a Result giving nodal 3D vectorial length fields\n# stress_fields.animate(deform_by=model.results.displacement.on_all_time_freqs())\n# - an Operator which outputs nodal 3D vectorial length fields\n# stress_fields.animate(deform_by=model.results.displacement.on_all_time_freqs)\n# It must evaluate to a FieldsContainer of same length as the one being animated.\n\n# Save the animation using \"save_as\" with a target path with the desired format as extension.\n# (accepts .gif, .avi or .mp4, see pyvista.Plotter.open_movie)\ncamera_pos = displacement_fields.animate(\n scale_factor=10.0,\n save_as=\"06-animate_results.gif\",\n return_cpos=True,\n show_axes=True,\n)\n\n# Can be made off_screen for batch animation creation.\n# This accepts as kwargs arguments taken by pyvista.Plotter.open_movie such as the frame-rate and\n# the quality.\n\n# One can also define a camera position to use, which can take a list of Camera descriptions:\n# Camera description must be one of the following:\n#\n# Iterable containing position, focal_point, and view up. For example:\n# [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)]\n#\n# Iterable containing a view vector. For example:\n# [-1.0, 2.0, -5.0]\n#\n# A string containing the plane orthogonal to the view direction. For example:\n# 'xy'\n\n# import copy\n# camera_pos_list = []\n# init_pos = [(1.1710286191854873, 1.1276044794551632, 1.62102216127818),\n# (0.05000000000000724, 0.006575860269683119, 0.4999935420927001),\n# (0.0, 0.0, 1.0)]\n# camera_pos_list.append(init_pos)\n# for i in range(1, len(displacement_fields)):\n# new_pos = copy.copy(camera_pos_list[i-1])\n# new_pos[0] = (camera_pos_list[i-1][0][0],\n# camera_pos_list[i-1][0][1]-0.2,\n# camera_pos_list[i-1][0][2])\n# camera_pos_list.append(new_pos)\n# displacement_fields.animate(scale_factor=10.,\n# save_as=\"displacements_2.gif\",\n# framerate=4,\n# quality=8,\n# cpos=camera_pos_list,\n# off_screen=True,\n# show_axes=True)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/06-plotting/06-animate_results.py b/doc/source/examples/06-plotting/06-animate_results.py new file mode 100644 index 0000000000..6a1144afd0 --- /dev/null +++ b/doc/source/examples/06-plotting/06-animate_results.py @@ -0,0 +1,114 @@ +""" +.. _animate_results: + +Review of available animation commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example lists the different commands available for creating animations of transient results, +shown with the arguments available. + +""" +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + + +# Load the model +model = dpf.Model(examples.find_msup_transient()) +print(model) + +# Use Scoping instances to adjust the region and the steps involved. +# Create a scoping on all nodes +mesh_scoping = dpf.mesh_scoping_factory.nodal_scoping(model.metadata.meshed_region.nodes.scoping) +# Create a scoping on all time steps +time_scoping = dpf.time_freq_scoping_factory.scoping_on_all_time_freqs(model) + +# Instantiate operators of interest and scope them +displacement_op = model.results.displacement +displacement_op = displacement_op.on_time_scoping(time_scoping) +displacement_op = displacement_op.on_mesh_scoping(mesh_scoping) +stress_op = model.results.stress +stress_op = stress_op.on_time_scoping(time_scoping) +stress_op = stress_op.on_mesh_scoping(mesh_scoping) + +# Get the resulting fields container +displacement_fields = displacement_op.eval() +stress_fields = stress_op.eval() + +# Animate a fields container by going through the fields and plotting contours +# of the norm or of the selected component. +# Default behavior consists in: +# - Using a constant and uniform scale factor of 1.0 +# - Showing the deformed geometry based on the fields themselves if they are nodal 3D vector fields. +# displacement_fields.animate() +# - Showing the static geometry if the fields are not nodal 3D vector fields. +# stress_fields.animate() + +# One can deactivate by default animation by self using deform_by=False +# displacement_fields.animate(deform_by=False) + +# Change the scale factor using a number/a list of numbers for a uniform constant/varying scaling. +# displacement_fields.animate(deform_by=True, scale_factor=10., +# show_axes=True) +# varying_scale_factor = [i for i in range(len(displacement_fields))] +# displacement_fields.animate(deform_by=True, scale_factor=varying_scale_factor, +# show_axes=True) + +# One can also format the frequency legend. +# displacement_fields.select_component(0).animate(deform_by=displacement_fields, scale_factor=1., +# show_axes=True, +# freq_kwargs={"font_size": 12, +# "fmt": ".3"}) + +# The deform_by argument can be: +# - a FieldsContainer of nodal 3D vectorial length fields +# stress_fields.animate(deform_by=model.results.displacement.on_all_time_freqs.eval()) +# - a Result giving nodal 3D vectorial length fields +# stress_fields.animate(deform_by=model.results.displacement.on_all_time_freqs()) +# - an Operator which outputs nodal 3D vectorial length fields +# stress_fields.animate(deform_by=model.results.displacement.on_all_time_freqs) +# It must evaluate to a FieldsContainer of same length as the one being animated. + +# Save the animation using "save_as" with a target path with the desired format as extension. +# (accepts .gif, .avi or .mp4, see pyvista.Plotter.open_movie) +camera_pos = displacement_fields.animate( + scale_factor=10.0, + save_as="06-animate_results.gif", + return_cpos=True, + show_axes=True, +) + +# Can be made off_screen for batch animation creation. +# This accepts as kwargs arguments taken by pyvista.Plotter.open_movie such as the frame-rate and +# the quality. + +# One can also define a camera position to use, which can take a list of Camera descriptions: +# Camera description must be one of the following: +# +# Iterable containing position, focal_point, and view up. For example: +# [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] +# +# Iterable containing a view vector. For example: +# [-1.0, 2.0, -5.0] +# +# A string containing the plane orthogonal to the view direction. For example: +# 'xy' + +# import copy +# camera_pos_list = [] +# init_pos = [(1.1710286191854873, 1.1276044794551632, 1.62102216127818), +# (0.05000000000000724, 0.006575860269683119, 0.4999935420927001), +# (0.0, 0.0, 1.0)] +# camera_pos_list.append(init_pos) +# for i in range(1, len(displacement_fields)): +# new_pos = copy.copy(camera_pos_list[i-1]) +# new_pos[0] = (camera_pos_list[i-1][0][0], +# camera_pos_list[i-1][0][1]-0.2, +# camera_pos_list[i-1][0][2]) +# camera_pos_list.append(new_pos) +# displacement_fields.animate(scale_factor=10., +# save_as="displacements_2.gif", +# framerate=4, +# quality=8, +# cpos=camera_pos_list, +# off_screen=True, +# show_axes=True) diff --git a/doc/source/examples/06-plotting/06-animate_results.py.md5 b/doc/source/examples/06-plotting/06-animate_results.py.md5 new file mode 100644 index 0000000000..1a12ceed6c --- /dev/null +++ b/doc/source/examples/06-plotting/06-animate_results.py.md5 @@ -0,0 +1 @@ +d620c945392b3cb59c9a6fe77e246da9 \ No newline at end of file diff --git a/doc/source/examples/06-plotting/06-animate_results.rst b/doc/source/examples/06-plotting/06-animate_results.rst new file mode 100644 index 0000000000..0d2a334a0c --- /dev/null +++ b/doc/source/examples/06-plotting/06-animate_results.rst @@ -0,0 +1,234 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\06-plotting\06-animate_results.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_06-plotting_06-animate_results.py: + + +.. _animate_results: + +Review of available animation commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example lists the different commands available for creating animations of transient results, +shown with the arguments available. + +.. GENERATED FROM PYTHON SOURCE LINES 11-115 + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_06-animate_results_001.gif + :alt: 06 animate results + :srcset: /examples/06-plotting/images/sphx_glr_06-animate_results_001.gif + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Transient analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - velocity: Nodal Velocity + - acceleration: Nodal Acceleration + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + ------------------------------ + DPF Meshed Region: + 393 nodes + 40 elements + Unit: m + With solid (3D) elements + ------------------------------ + 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 + + + + + + + +| + +.. code-block:: default + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + + # Load the model + model = dpf.Model(examples.find_msup_transient()) + print(model) + + # Use Scoping instances to adjust the region and the steps involved. + # Create a scoping on all nodes + mesh_scoping = dpf.mesh_scoping_factory.nodal_scoping(model.metadata.meshed_region.nodes.scoping) + # Create a scoping on all time steps + time_scoping = dpf.time_freq_scoping_factory.scoping_on_all_time_freqs(model) + + # Instantiate operators of interest and scope them + displacement_op = model.results.displacement + displacement_op = displacement_op.on_time_scoping(time_scoping) + displacement_op = displacement_op.on_mesh_scoping(mesh_scoping) + stress_op = model.results.stress + stress_op = stress_op.on_time_scoping(time_scoping) + stress_op = stress_op.on_mesh_scoping(mesh_scoping) + + # Get the resulting fields container + displacement_fields = displacement_op.eval() + stress_fields = stress_op.eval() + + # Animate a fields container by going through the fields and plotting contours + # of the norm or of the selected component. + # Default behavior consists in: + # - Using a constant and uniform scale factor of 1.0 + # - Showing the deformed geometry based on the fields themselves if they are nodal 3D vector fields. + # displacement_fields.animate() + # - Showing the static geometry if the fields are not nodal 3D vector fields. + # stress_fields.animate() + + # One can deactivate by default animation by self using deform_by=False + # displacement_fields.animate(deform_by=False) + + # Change the scale factor using a number/a list of numbers for a uniform constant/varying scaling. + # displacement_fields.animate(deform_by=True, scale_factor=10., + # show_axes=True) + # varying_scale_factor = [i for i in range(len(displacement_fields))] + # displacement_fields.animate(deform_by=True, scale_factor=varying_scale_factor, + # show_axes=True) + + # One can also format the frequency legend. + # displacement_fields.select_component(0).animate(deform_by=displacement_fields, scale_factor=1., + # show_axes=True, + # freq_kwargs={"font_size": 12, + # "fmt": ".3"}) + + # The deform_by argument can be: + # - a FieldsContainer of nodal 3D vectorial length fields + # stress_fields.animate(deform_by=model.results.displacement.on_all_time_freqs.eval()) + # - a Result giving nodal 3D vectorial length fields + # stress_fields.animate(deform_by=model.results.displacement.on_all_time_freqs()) + # - an Operator which outputs nodal 3D vectorial length fields + # stress_fields.animate(deform_by=model.results.displacement.on_all_time_freqs) + # It must evaluate to a FieldsContainer of same length as the one being animated. + + # Save the animation using "save_as" with a target path with the desired format as extension. + # (accepts .gif, .avi or .mp4, see pyvista.Plotter.open_movie) + camera_pos = displacement_fields.animate( + scale_factor=10.0, + save_as="06-animate_results.gif", + return_cpos=True, + show_axes=True, + ) + + # Can be made off_screen for batch animation creation. + # This accepts as kwargs arguments taken by pyvista.Plotter.open_movie such as the frame-rate and + # the quality. + + # One can also define a camera position to use, which can take a list of Camera descriptions: + # Camera description must be one of the following: + # + # Iterable containing position, focal_point, and view up. For example: + # [(2.0, 5.0, 13.0), (0.0, 0.0, 0.0), (-0.7, -0.5, 0.3)] + # + # Iterable containing a view vector. For example: + # [-1.0, 2.0, -5.0] + # + # A string containing the plane orthogonal to the view direction. For example: + # 'xy' + + # import copy + # camera_pos_list = [] + # init_pos = [(1.1710286191854873, 1.1276044794551632, 1.62102216127818), + # (0.05000000000000724, 0.006575860269683119, 0.4999935420927001), + # (0.0, 0.0, 1.0)] + # camera_pos_list.append(init_pos) + # for i in range(1, len(displacement_fields)): + # new_pos = copy.copy(camera_pos_list[i-1]) + # new_pos[0] = (camera_pos_list[i-1][0][0], + # camera_pos_list[i-1][0][1]-0.2, + # camera_pos_list[i-1][0][2]) + # camera_pos_list.append(new_pos) + # displacement_fields.animate(scale_factor=10., + # save_as="displacements_2.gif", + # framerate=4, + # quality=8, + # cpos=camera_pos_list, + # off_screen=True, + # show_axes=True) + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 8.176 seconds) + + +.. _sphx_glr_download_examples_06-plotting_06-animate_results.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 06-animate_results.py <06-animate_results.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 06-animate_results.ipynb <06-animate_results.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/06-plotting/06-animate_results_codeobj.pickle b/doc/source/examples/06-plotting/06-animate_results_codeobj.pickle new file mode 100644 index 0000000000..53e4788f0d Binary files /dev/null and b/doc/source/examples/06-plotting/06-animate_results_codeobj.pickle differ diff --git a/doc/source/examples/06-plotting/07-plot_on_geometries.ipynb b/doc/source/examples/06-plotting/07-plot_on_geometries.ipynb new file mode 100644 index 0000000000..51ed3dba76 --- /dev/null +++ b/doc/source/examples/06-plotting/07-plot_on_geometries.ipynb @@ -0,0 +1,349 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot on geometry elements {#plot_on_geometries}\r\n\r\nThis example shows how to plot a certain field in different geometric\r\nobjects such as points, lines and planes.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Imports and load model\r\n\r\nImport modules and set context as Premium.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy as np\nimport matplotlib.pyplot as plt\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops\nfrom ansys.dpf.core.geometry import Line, Plane, Points\nfrom ansys.dpf.core.plotter import DpfPlotter\nfrom ansys.dpf.core.fields_factory import field_from_array" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load model from examples and print information:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = dpf.Model(examples.find_static_rst())\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load model\\'s mesh and define camera position (obtained with\r\n`cpos=pl.show_figure(return_cpos=True)`). This will be used later for\r\nplotting.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mesh = model.metadata.meshed_region\ncpos = [\n (0.07635352356975698, 0.1200500294271993, 0.041072502929096165),\n (0.015, 0.045, 0.015),\n (-0.16771051558419411, -0.1983722658245161, 0.9656715938216944),\n]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create points, line and plane objects\r\n\r\nCreate 8 points in the corners and one in the middle:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "points = Points(\n [\n [0.0, 0.03, 0.0],\n [0.0, 0.03, 0.03],\n [0.0, 0.06, 0.00],\n [0.0, 0.06, 0.03],\n [0.03, 0.03, 0.0],\n [0.03, 0.03, 0.03],\n [0.03, 0.06, 0.00],\n [0.03, 0.06, 0.03],\n [0.015, 0.045, 0.015],\n ]\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Show points together with the mesh\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "points.plot(mesh, cpos=cpos)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create line passing through the geometry\\'s diagonal:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "line = Line([[0.03, 0.03, 0.05], [0.0, 0.06, 0.0]], n_points=50)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Show line with the 3D mesh\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "line.plot(mesh, cpos=cpos)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create vertical plane passing through the mid point:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plane = Plane(\n [0.015, 0.045, 0.015],\n [1, 1, 0],\n width=0.03,\n height=0.03,\n n_cells_x=10,\n n_cells_y=10,\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Show plane with the 3D mesh\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plane.plot(mesh, cpos=cpos)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Map displacement field to geometry objects\r\n\r\nGet displacement field from model:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "disp = model.results.displacement" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Map displacement to points in Points object:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mapping_operator = ops.mapping.on_coordinates(\n fields_container=disp,\n coordinates=field_from_array(points.coordinates.data),\n create_support=True,\n mesh=mesh,\n)\nfields_mapped = mapping_operator.outputs.fields_container()\nfield_points = fields_mapped[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Map displacement to points in Line object:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mapping_operator = ops.mapping.on_coordinates(\n fields_container=disp,\n coordinates=line.mesh.nodes.coordinates_field,\n create_support=True,\n mesh=mesh,\n)\nfields_mapped = mapping_operator.outputs.fields_container()\nfield_line = fields_mapped[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Map displacement to points in Plane object:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mapping_operator = ops.mapping.on_coordinates(\n fields_container=disp,\n coordinates=plane.mesh.nodes.coordinates_field,\n create_support=True,\n mesh=mesh,\n)\nfields_mapped = mapping_operator.outputs.fields_container()\nfield_plane = fields_mapped[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plotting displacement field on the geometry objects\r\n\r\n3D plot of Points and display mesh:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pl = DpfPlotter()\npl.add_field(field_points, render_points_as_spheres=True, point_size=10)\npl.add_mesh(mesh, style=\"surface\", show_edges=True, color=\"w\", opacity=0.3)\npl.show_figure(show_axes=True, cpos=cpos)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "3D plot of Line and mesh. Note that the line is only displayed if some\r\npoints are found inside the mesh:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pl = DpfPlotter()\nif not len(field_line) == 0:\n pl.add_field(field_line, line.mesh, line_width=5)\npl.add_mesh(mesh, style=\"surface\", show_edges=True, color=\"w\", opacity=0.3)\npl.show_figure(show_axes=True, cpos=cpos)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot Plane and display mesh in background. Note that the plane is only\r\ndisplayed if some points are found inside the mesh:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pl = DpfPlotter()\nif not len(field_plane) == 0:\n pl.add_field(field_plane, plane.mesh, show_edges=False)\npl.add_mesh(mesh, style=\"surface\", show_edges=True, color=\"w\", opacity=0.3)\npl.show_figure(show_axes=True, cpos=cpos)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2D plot (graph) of Line (line length vs displacement field):\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "norm_disp = [np.linalg.norm(field_line.data[i]) for i in range(len(field_line.data))]\npath = line.path[field_line.scoping.ids - 1]\nplt.plot(path, norm_disp)\nplt.xlabel(\"Line length\")\nplt.ylabel(\"Displacement norm field\")\nplt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/06-plotting/07-plot_on_geometries.py b/doc/source/examples/06-plotting/07-plot_on_geometries.py new file mode 100644 index 0000000000..00bfc41ea6 --- /dev/null +++ b/doc/source/examples/06-plotting/07-plot_on_geometries.py @@ -0,0 +1,162 @@ +""" +.. _plot_on_geometries: + +Plot on geometry elements +~~~~~~~~~~~~~~~~~~~~~~~~~ +This example shows how to plot a certain field in different geometric +objects such as points, lines and planes. + +""" + + +############################################################################### +# Imports and load model +# ~~~~~~~~~~~~~~~~~~~~~~ +# Import modules and set context as Premium. + +import numpy as np +import matplotlib.pyplot as plt + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops +from ansys.dpf.core.geometry import Line, Plane, Points +from ansys.dpf.core.plotter import DpfPlotter +from ansys.dpf.core.fields_factory import field_from_array + + +############################################################################### +# Load model from examples and print information: +model = dpf.Model(examples.find_static_rst()) +print(model) + +############################################################################### +# Load model's mesh and define camera position +# (obtained with ``cpos=pl.show_figure(return_cpos=True)``). This will be used +# later for plotting. +mesh = model.metadata.meshed_region +cpos = [ + (0.07635352356975698, 0.1200500294271993, 0.041072502929096165), + (0.015, 0.045, 0.015), + (-0.16771051558419411, -0.1983722658245161, 0.9656715938216944), +] + +############################################################################### +# Create points, line and plane objects +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create 8 points in the corners and one in the middle: +points = Points( + [ + [0.0, 0.03, 0.0], + [0.0, 0.03, 0.03], + [0.0, 0.06, 0.00], + [0.0, 0.06, 0.03], + [0.03, 0.03, 0.0], + [0.03, 0.03, 0.03], + [0.03, 0.06, 0.00], + [0.03, 0.06, 0.03], + [0.015, 0.045, 0.015], + ] +) + +############################################################################### +# Show points together with the mesh +points.plot(mesh, cpos=cpos) + +############################################################################### +# Create line passing through the geometry's diagonal: +line = Line([[0.03, 0.03, 0.05], [0.0, 0.06, 0.0]], n_points=50) + +############################################################################### +# Show line with the 3D mesh +line.plot(mesh, cpos=cpos) + +############################################################################### +# Create vertical plane passing through the mid point: +plane = Plane( + [0.015, 0.045, 0.015], + [1, 1, 0], + width=0.03, + height=0.03, + n_cells_x=10, + n_cells_y=10, +) + +############################################################################### +# Show plane with the 3D mesh +plane.plot(mesh, cpos=cpos) + +############################################################################### +# Map displacement field to geometry objects +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Get displacement field from model: +disp = model.results.displacement + +############################################################################### +# Map displacement to points in Points object: +mapping_operator = ops.mapping.on_coordinates( + fields_container=disp, + coordinates=field_from_array(points.coordinates.data), + create_support=True, + mesh=mesh, +) +fields_mapped = mapping_operator.outputs.fields_container() +field_points = fields_mapped[0] + +############################################################################### +# Map displacement to points in Line object: +mapping_operator = ops.mapping.on_coordinates( + fields_container=disp, + coordinates=line.mesh.nodes.coordinates_field, + create_support=True, + mesh=mesh, +) +fields_mapped = mapping_operator.outputs.fields_container() +field_line = fields_mapped[0] + +############################################################################### +# Map displacement to points in Plane object: +mapping_operator = ops.mapping.on_coordinates( + fields_container=disp, + coordinates=plane.mesh.nodes.coordinates_field, + create_support=True, + mesh=mesh, +) +fields_mapped = mapping_operator.outputs.fields_container() +field_plane = fields_mapped[0] + +############################################################################### +# Plotting displacement field on the geometry objects +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# 3D plot of Points and display mesh: +pl = DpfPlotter() +pl.add_field(field_points, render_points_as_spheres=True, point_size=10) +pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) +pl.show_figure(show_axes=True, cpos=cpos) + +############################################################################### +# 3D plot of Line and mesh. +# Note that the line is only displayed if some points are found inside the mesh: +pl = DpfPlotter() +if not len(field_line) == 0: + pl.add_field(field_line, line.mesh, line_width=5) +pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) +pl.show_figure(show_axes=True, cpos=cpos) + +############################################################################### +# Plot Plane and display mesh in background. +# Note that the plane is only displayed if some points are found inside the mesh: +pl = DpfPlotter() +if not len(field_plane) == 0: + pl.add_field(field_plane, plane.mesh, show_edges=False) +pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) +pl.show_figure(show_axes=True, cpos=cpos) + +############################################################################### +# 2D plot (graph) of Line (line length vs displacement field): +norm_disp = [np.linalg.norm(field_line.data[i]) for i in range(len(field_line.data))] +path = line.path[field_line.scoping.ids - 1] +plt.plot(path, norm_disp) +plt.xlabel("Line length") +plt.ylabel("Displacement norm field") +plt.show() diff --git a/doc/source/examples/06-plotting/07-plot_on_geometries.py.md5 b/doc/source/examples/06-plotting/07-plot_on_geometries.py.md5 new file mode 100644 index 0000000000..3e3de37724 --- /dev/null +++ b/doc/source/examples/06-plotting/07-plot_on_geometries.py.md5 @@ -0,0 +1 @@ +d045a71af90612d8755dc62a768a17bf \ No newline at end of file diff --git a/doc/source/examples/06-plotting/07-plot_on_geometries.rst b/doc/source/examples/06-plotting/07-plot_on_geometries.rst new file mode 100644 index 0000000000..58449ad0a8 --- /dev/null +++ b/doc/source/examples/06-plotting/07-plot_on_geometries.rst @@ -0,0 +1,497 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\06-plotting\07-plot_on_geometries.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_06-plotting_07-plot_on_geometries.py: + + +.. _plot_on_geometries: + +Plot on geometry elements +~~~~~~~~~~~~~~~~~~~~~~~~~ +This example shows how to plot a certain field in different geometric +objects such as points, lines and planes. + +.. GENERATED FROM PYTHON SOURCE LINES 13-16 + +Imports and load model +~~~~~~~~~~~~~~~~~~~~~~ +Import modules and set context as Premium. + +.. GENERATED FROM PYTHON SOURCE LINES 16-28 + +.. code-block:: default + + + import numpy as np + import matplotlib.pyplot as plt + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + from ansys.dpf.core.geometry import Line, Plane, Points + from ansys.dpf.core.plotter import DpfPlotter + from ansys.dpf.core.fields_factory import field_from_array + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 29-30 + +Load model from examples and print information: + +.. GENERATED FROM PYTHON SOURCE LINES 30-33 + +.. code-block:: default + + model = dpf.Model(examples.find_static_rst()) + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Model + ------------------------------ + Static analysis + Unit system: MKS: m, kg, N, s, V, A, degC + Physics Type: Mechanical + Available results: + - displacement: Nodal Displacement + - reaction_force: Nodal Force + - stress: ElementalNodal Stress + - elemental_volume: Elemental Volume + - stiffness_matrix_energy: Elemental Energy-stiffness matrix + - artificial_hourglass_energy: Elemental Hourglass Energy + - thermal_dissipation_energy: Elemental thermal dissipation energy + - kinetic_energy: Elemental Kinetic Energy + - co_energy: Elemental co-energy + - incremental_energy: Elemental incremental energy + - elastic_strain: ElementalNodal Strain + - element_euler_angles: ElementalNodal Element Euler Angles + - structural_temperature: ElementalNodal Structural temperature + ------------------------------ + DPF Meshed Region: + 81 nodes + 8 elements + Unit: m + With solid (3D) elements + ------------------------------ + DPF Time/Freq Support: + Number of sets: 1 + Cumulative Time (s) LoadStep Substep + 1 1,000000 1 1 + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 34-37 + +Load model's mesh and define camera position +(obtained with ``cpos=pl.show_figure(return_cpos=True)``). This will be used +later for plotting. + +.. GENERATED FROM PYTHON SOURCE LINES 37-44 + +.. code-block:: default + + mesh = model.metadata.meshed_region + cpos = [ + (0.07635352356975698, 0.1200500294271993, 0.041072502929096165), + (0.015, 0.045, 0.015), + (-0.16771051558419411, -0.1983722658245161, 0.9656715938216944), + ] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 45-48 + +Create points, line and plane objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create 8 points in the corners and one in the middle: + +.. GENERATED FROM PYTHON SOURCE LINES 48-62 + +.. code-block:: default + + points = Points( + [ + [0.0, 0.03, 0.0], + [0.0, 0.03, 0.03], + [0.0, 0.06, 0.00], + [0.0, 0.06, 0.03], + [0.03, 0.03, 0.0], + [0.03, 0.03, 0.03], + [0.03, 0.06, 0.00], + [0.03, 0.06, 0.03], + [0.015, 0.045, 0.015], + ] + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 63-64 + +Show points together with the mesh + +.. GENERATED FROM PYTHON SOURCE LINES 64-66 + +.. code-block:: default + + points.plot(mesh, cpos=cpos) + + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_001.png + :alt: 07 plot on geometries + :srcset: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_001.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 67-68 + +Create line passing through the geometry's diagonal: + +.. GENERATED FROM PYTHON SOURCE LINES 68-70 + +.. code-block:: default + + line = Line([[0.03, 0.03, 0.05], [0.0, 0.06, 0.0]], n_points=50) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 71-72 + +Show line with the 3D mesh + +.. GENERATED FROM PYTHON SOURCE LINES 72-74 + +.. code-block:: default + + line.plot(mesh, cpos=cpos) + + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_002.png + :alt: 07 plot on geometries + :srcset: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_002.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 75-76 + +Create vertical plane passing through the mid point: + +.. GENERATED FROM PYTHON SOURCE LINES 76-85 + +.. code-block:: default + + plane = Plane( + [0.015, 0.045, 0.015], + [1, 1, 0], + width=0.03, + height=0.03, + n_cells_x=10, + n_cells_y=10, + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 86-87 + +Show plane with the 3D mesh + +.. GENERATED FROM PYTHON SOURCE LINES 87-89 + +.. code-block:: default + + plane.plot(mesh, cpos=cpos) + + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_003.png + :alt: 07 plot on geometries + :srcset: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_003.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 90-93 + +Map displacement field to geometry objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Get displacement field from model: + +.. GENERATED FROM PYTHON SOURCE LINES 93-95 + +.. code-block:: default + + disp = model.results.displacement + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 96-97 + +Map displacement to points in Points object: + +.. GENERATED FROM PYTHON SOURCE LINES 97-106 + +.. code-block:: default + + mapping_operator = ops.mapping.on_coordinates( + fields_container=disp, + coordinates=field_from_array(points.coordinates.data), + create_support=True, + mesh=mesh, + ) + fields_mapped = mapping_operator.outputs.fields_container() + field_points = fields_mapped[0] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 107-108 + +Map displacement to points in Line object: + +.. GENERATED FROM PYTHON SOURCE LINES 108-117 + +.. code-block:: default + + mapping_operator = ops.mapping.on_coordinates( + fields_container=disp, + coordinates=line.mesh.nodes.coordinates_field, + create_support=True, + mesh=mesh, + ) + fields_mapped = mapping_operator.outputs.fields_container() + field_line = fields_mapped[0] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 118-119 + +Map displacement to points in Plane object: + +.. GENERATED FROM PYTHON SOURCE LINES 119-128 + +.. code-block:: default + + mapping_operator = ops.mapping.on_coordinates( + fields_container=disp, + coordinates=plane.mesh.nodes.coordinates_field, + create_support=True, + mesh=mesh, + ) + fields_mapped = mapping_operator.outputs.fields_container() + field_plane = fields_mapped[0] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 129-132 + +Plotting displacement field on the geometry objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +3D plot of Points and display mesh: + +.. GENERATED FROM PYTHON SOURCE LINES 132-137 + +.. code-block:: default + + pl = DpfPlotter() + pl.add_field(field_points, render_points_as_spheres=True, point_size=10) + pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) + pl.show_figure(show_axes=True, cpos=cpos) + + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_004.png + :alt: 07 plot on geometries + :srcset: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_004.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 138-140 + +3D plot of Line and mesh. +Note that the line is only displayed if some points are found inside the mesh: + +.. GENERATED FROM PYTHON SOURCE LINES 140-146 + +.. code-block:: default + + pl = DpfPlotter() + if not len(field_line) == 0: + pl.add_field(field_line, line.mesh, line_width=5) + pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) + pl.show_figure(show_axes=True, cpos=cpos) + + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_005.png + :alt: 07 plot on geometries + :srcset: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_005.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 147-149 + +Plot Plane and display mesh in background. +Note that the plane is only displayed if some points are found inside the mesh: + +.. GENERATED FROM PYTHON SOURCE LINES 149-155 + +.. code-block:: default + + pl = DpfPlotter() + if not len(field_plane) == 0: + pl.add_field(field_plane, plane.mesh, show_edges=False) + pl.add_mesh(mesh, style="surface", show_edges=True, color="w", opacity=0.3) + pl.show_figure(show_axes=True, cpos=cpos) + + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_006.png + :alt: 07 plot on geometries + :srcset: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_006.png + :class: sphx-glr-single-img + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 156-157 + +2D plot (graph) of Line (line length vs displacement field): + +.. GENERATED FROM PYTHON SOURCE LINES 157-163 + +.. code-block:: default + + norm_disp = [np.linalg.norm(field_line.data[i]) for i in range(len(field_line.data))] + path = line.path[field_line.scoping.ids - 1] + plt.plot(path, norm_disp) + plt.xlabel("Line length") + plt.ylabel("Displacement norm field") + plt.show() + + + +.. image-sg:: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_007.png + :alt: 07 plot on geometries + :srcset: /examples/06-plotting/images/sphx_glr_07-plot_on_geometries_007.png + :class: sphx-glr-single-img + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 3.531 seconds) + + +.. _sphx_glr_download_examples_06-plotting_07-plot_on_geometries.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 07-plot_on_geometries.py <07-plot_on_geometries.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 07-plot_on_geometries.ipynb <07-plot_on_geometries.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/06-plotting/07-plot_on_geometries_codeobj.pickle b/doc/source/examples/06-plotting/07-plot_on_geometries_codeobj.pickle new file mode 100644 index 0000000000..e092f50470 Binary files /dev/null and b/doc/source/examples/06-plotting/07-plot_on_geometries_codeobj.pickle differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_001.png b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_001.png new file mode 100644 index 0000000000..635db3d94a Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_001.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_002.png b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_002.png new file mode 100644 index 0000000000..204daf17f8 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_002.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_003.png b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_003.png new file mode 100644 index 0000000000..50c1257a12 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_003.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_004.png b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_004.png new file mode 100644 index 0000000000..4f21872ab3 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_004.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_005.png b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_005.png new file mode 100644 index 0000000000..3bcbba1ed7 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_005.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_006.png b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_006.png new file mode 100644 index 0000000000..5272d83115 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_006.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_007.png b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_007.png new file mode 100644 index 0000000000..93ff39d02d Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_007.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_008.png b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_008.png new file mode 100644 index 0000000000..e10f82bcff Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_00-basic_plotting_008.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_01-compare_results_001.png b/doc/source/examples/06-plotting/images/sphx_glr_01-compare_results_001.png new file mode 100644 index 0000000000..1ae8f14c3e Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_01-compare_results_001.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_02-solution_combination_001.png b/doc/source/examples/06-plotting/images/sphx_glr_02-solution_combination_001.png new file mode 100644 index 0000000000..dc528ebbdb Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_02-solution_combination_001.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_03-labels_001.png b/doc/source/examples/06-plotting/images/sphx_glr_03-labels_001.png new file mode 100644 index 0000000000..fa72315851 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_03-labels_001.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_03-labels_002.png b/doc/source/examples/06-plotting/images/sphx_glr_03-labels_002.png new file mode 100644 index 0000000000..a564c5063d Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_03-labels_002.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_04-plot_on_path_001.png b/doc/source/examples/06-plotting/images/sphx_glr_04-plot_on_path_001.png new file mode 100644 index 0000000000..72bb5fdb3a Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_04-plot_on_path_001.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_04-plot_on_path_002.png b/doc/source/examples/06-plotting/images/sphx_glr_04-plot_on_path_002.png new file mode 100644 index 0000000000..20efeb2a6a Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_04-plot_on_path_002.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_001.png b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_001.png new file mode 100644 index 0000000000..0d7408bf8c Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_001.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_002.png b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_002.png new file mode 100644 index 0000000000..0723be5a43 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_002.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_003.png b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_003.png new file mode 100644 index 0000000000..c5a19e3b71 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_003.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_004.png b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_004.png new file mode 100644 index 0000000000..8ae27ef9a3 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_004.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_005.png b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_005.png new file mode 100644 index 0000000000..adfd21ceb8 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_005.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_006.png b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_006.png new file mode 100644 index 0000000000..3bb5bfca21 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_05-plot_on_warped_mesh_006.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_06-animate_results_001.gif b/doc/source/examples/06-plotting/images/sphx_glr_06-animate_results_001.gif new file mode 100644 index 0000000000..f2bb4fbbb8 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_06-animate_results_001.gif differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_001.png b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_001.png new file mode 100644 index 0000000000..0119c3064c Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_001.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_002.png b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_002.png new file mode 100644 index 0000000000..c3c7d82d00 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_002.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_003.png b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_003.png new file mode 100644 index 0000000000..a1c1513436 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_003.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_004.png b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_004.png new file mode 100644 index 0000000000..e87633d774 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_004.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_005.png b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_005.png new file mode 100644 index 0000000000..c0a26f0920 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_005.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_006.png b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_006.png new file mode 100644 index 0000000000..d1baab1a68 Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_006.png differ diff --git a/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_007.png b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_007.png new file mode 100644 index 0000000000..89c373d6fd Binary files /dev/null and b/doc/source/examples/06-plotting/images/sphx_glr_07-plot_on_geometries_007.png differ diff --git a/doc/source/examples/06-plotting/images/thumb/sphx_glr_00-basic_plotting_thumb.png b/doc/source/examples/06-plotting/images/thumb/sphx_glr_00-basic_plotting_thumb.png new file mode 100644 index 0000000000..81b0b77eba Binary files /dev/null and b/doc/source/examples/06-plotting/images/thumb/sphx_glr_00-basic_plotting_thumb.png differ diff --git a/doc/source/examples/06-plotting/images/thumb/sphx_glr_01-compare_results_thumb.png b/doc/source/examples/06-plotting/images/thumb/sphx_glr_01-compare_results_thumb.png new file mode 100644 index 0000000000..111034b8a9 Binary files /dev/null and b/doc/source/examples/06-plotting/images/thumb/sphx_glr_01-compare_results_thumb.png differ diff --git a/doc/source/examples/06-plotting/images/thumb/sphx_glr_02-solution_combination_thumb.png b/doc/source/examples/06-plotting/images/thumb/sphx_glr_02-solution_combination_thumb.png new file mode 100644 index 0000000000..b9ea5ea8bd Binary files /dev/null and b/doc/source/examples/06-plotting/images/thumb/sphx_glr_02-solution_combination_thumb.png differ diff --git a/doc/source/examples/06-plotting/images/thumb/sphx_glr_03-labels_thumb.png b/doc/source/examples/06-plotting/images/thumb/sphx_glr_03-labels_thumb.png new file mode 100644 index 0000000000..e82922ac25 Binary files /dev/null and b/doc/source/examples/06-plotting/images/thumb/sphx_glr_03-labels_thumb.png differ diff --git a/doc/source/examples/06-plotting/images/thumb/sphx_glr_04-plot_on_path_thumb.png b/doc/source/examples/06-plotting/images/thumb/sphx_glr_04-plot_on_path_thumb.png new file mode 100644 index 0000000000..acc02ad017 Binary files /dev/null and b/doc/source/examples/06-plotting/images/thumb/sphx_glr_04-plot_on_path_thumb.png differ diff --git a/doc/source/examples/06-plotting/images/thumb/sphx_glr_05-plot_on_warped_mesh_thumb.png b/doc/source/examples/06-plotting/images/thumb/sphx_glr_05-plot_on_warped_mesh_thumb.png new file mode 100644 index 0000000000..a77301c042 Binary files /dev/null and b/doc/source/examples/06-plotting/images/thumb/sphx_glr_05-plot_on_warped_mesh_thumb.png differ diff --git a/doc/source/examples/06-plotting/images/thumb/sphx_glr_06-animate_results_thumb.gif b/doc/source/examples/06-plotting/images/thumb/sphx_glr_06-animate_results_thumb.gif new file mode 100644 index 0000000000..f2bb4fbbb8 Binary files /dev/null and b/doc/source/examples/06-plotting/images/thumb/sphx_glr_06-animate_results_thumb.gif differ diff --git a/doc/source/examples/06-plotting/images/thumb/sphx_glr_07-plot_on_geometries_thumb.png b/doc/source/examples/06-plotting/images/thumb/sphx_glr_07-plot_on_geometries_thumb.png new file mode 100644 index 0000000000..dedaf564a2 Binary files /dev/null and b/doc/source/examples/06-plotting/images/thumb/sphx_glr_07-plot_on_geometries_thumb.png differ diff --git a/doc/source/examples/06-plotting/index.rst b/doc/source/examples/06-plotting/index.rst new file mode 100644 index 0000000000..ec7c684a24 --- /dev/null +++ b/doc/source/examples/06-plotting/index.rst @@ -0,0 +1,169 @@ + + +.. _sphx_glr_examples_06-plotting: + +.. _plotting_examples: + +Plotting examples +================= +These examples show how to use the :class:`ansys.dpf.core.plotter.DpfPlotter` class. + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_00-basic_plotting_thumb.png + :alt: Review of available plotting commands + + :ref:`sphx_glr_examples_06-plotting_00-basic_plotting.py` + +.. raw:: html + +
Review of available plotting commands
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_01-compare_results_thumb.png + :alt: Compare results using the plotter + + :ref:`sphx_glr_examples_06-plotting_01-compare_results.py` + +.. raw:: html + +
Compare results using the plotter
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_02-solution_combination_thumb.png + :alt: Load case combination for principal stress + + :ref:`sphx_glr_examples_06-plotting_02-solution_combination.py` + +.. raw:: html + +
Load case combination for principal stress
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_03-labels_thumb.png + :alt: Add nodal labels on plots + + :ref:`sphx_glr_examples_06-plotting_03-labels.py` + +.. raw:: html + +
Add nodal labels on plots
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_04-plot_on_path_thumb.png + :alt: Plot results on a specific path + + :ref:`sphx_glr_examples_06-plotting_04-plot_on_path.py` + +.. raw:: html + +
Plot results on a specific path
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_05-plot_on_warped_mesh_thumb.png + :alt: Warp the mesh by a field for plotting + + :ref:`sphx_glr_examples_06-plotting_05-plot_on_warped_mesh.py` + +.. raw:: html + +
Warp the mesh by a field for plotting
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_06-animate_results_thumb.gif + :alt: Review of available animation commands + + :ref:`sphx_glr_examples_06-plotting_06-animate_results.py` + +.. raw:: html + +
Review of available animation commands
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_07-plot_on_geometries_thumb.png + :alt: Plot on geometry elements + + :ref:`sphx_glr_examples_06-plotting_07-plot_on_geometries.py` + +.. raw:: html + +
Plot on geometry elements
+
+ + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /examples/06-plotting/00-basic_plotting + /examples/06-plotting/01-compare_results + /examples/06-plotting/02-solution_combination + /examples/06-plotting/03-labels + /examples/06-plotting/04-plot_on_path + /examples/06-plotting/05-plot_on_warped_mesh + /examples/06-plotting/06-animate_results + /examples/06-plotting/07-plot_on_geometries + diff --git a/doc/source/examples/06-plotting/sg_execution_times.rst b/doc/source/examples/06-plotting/sg_execution_times.rst new file mode 100644 index 0000000000..89b981926e --- /dev/null +++ b/doc/source/examples/06-plotting/sg_execution_times.rst @@ -0,0 +1,26 @@ + +:orphan: + +.. _sphx_glr_examples_06-plotting_sg_execution_times: + +Computation times +================= +**00:26.623** total execution time for **examples_06-plotting** files: + ++--------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_06-plotting_06-animate_results.py` (``06-animate_results.py``) | 00:08.176 | 0.0 MB | ++--------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_06-plotting_00-basic_plotting.py` (``00-basic_plotting.py``) | 00:06.360 | 0.0 MB | ++--------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_06-plotting_05-plot_on_warped_mesh.py` (``05-plot_on_warped_mesh.py``) | 00:05.388 | 0.0 MB | ++--------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_06-plotting_07-plot_on_geometries.py` (``07-plot_on_geometries.py``) | 00:03.531 | 0.0 MB | ++--------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_06-plotting_03-labels.py` (``03-labels.py``) | 00:01.211 | 0.0 MB | ++--------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_06-plotting_04-plot_on_path.py` (``04-plot_on_path.py``) | 00:00.759 | 0.0 MB | ++--------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_06-plotting_02-solution_combination.py` (``02-solution_combination.py``) | 00:00.619 | 0.0 MB | ++--------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_06-plotting_01-compare_results.py` (``01-compare_results.py``) | 00:00.579 | 0.0 MB | ++--------------------------------------------------------------------------------------------------+-----------+--------+ diff --git a/doc/source/examples/07-distributed-post/00-distributed_total_disp.ipynb b/doc/source/examples/07-distributed-post/00-distributed_total_disp.ipynb new file mode 100644 index 0000000000..1fbdd5d503 --- /dev/null +++ b/doc/source/examples/07-distributed-post/00-distributed_total_disp.ipynb @@ -0,0 +1,169 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Postprocessing of displacement on distributed processes {#ref_distributed_total_disp}\r\n\r\nThis diagram helps you to understand this example. It shows the operator\r\nchain that is used to compute the final result.\r\n\r\n::: graphviz\r\n\r\ndigraph foo {\r\n\r\n: graph \\[pad=\\\"0\\\", nodesep=\\\"0.3\\\", ranksep=\\\"0.3\\\"\\] node\r\n \\[shape=box, style=filled, fillcolor=\\\"#ffcc00\\\", margin=\\\"0\\\"\\];\r\n rankdir=LR; splines=line;\r\n\r\n disp01 \\[label=\\\"displacement\\\"\\]; disp02\r\n \\[label=\\\"displacement\\\"\\]; norm01 \\[label=\\\"norm\\\"\\]; norm02\r\n \\[label=\\\"norm\\\"\\];\r\n\r\n subgraph cluster_1 {\r\n\r\n : ds01 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n ds01 -\\> disp01 \\[style=dashed\\]; disp01 -\\> norm01;\r\n\r\n label=\\\"Server 1\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n }\r\n\r\n subgraph cluster_2 {\r\n\r\n : ds02 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n ds02 -\\> disp02 \\[style=dashed\\]; disp02 -\\> norm02;\r\n\r\n label=\\\"Server 2\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n }\r\n\r\n norm01 -\\> \\\"merge\\\"; norm02 -\\> \\\"merge\\\";\r\n\r\n}\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import the `dpf-core` module and its examples files.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Configure the servers. Make a list of IP addresses and port numbers that\r\nDPF servers start and listen on. Operator instances are created on each\r\nof these servers so that each can address a different result file.\r\n\r\nThis example postprocesses an analysis distributed in two files.\r\nConsequently, it requires two remote processes.\r\n\r\nTo make it easier, this example starts local servers. However, you can\r\nconnect to any existing servers on your network.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "config = dpf.AvailableServerConfigs.InProcessServer\nif \"DPF_DOCKER\" in os.environ.keys():\n # If running DPF on Docker, you cannot start an InProcessServer\n config = dpf.AvailableServerConfigs.GrpcServer\nglobal_server = dpf.start_local_server(as_global=True, config=config)\n\nremote_servers = [\n dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer),\n dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer),\n]\nips = [remote_server.ip for remote_server in remote_servers]\nports = [remote_server.port for remote_server in remote_servers]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the IP addresses and ports.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"ips:\", ips)\nprint(\"ports:\", ports)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Send files to the temporary directory if they are not in shared memory.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "files = examples.download_distributed_files(return_local_path=True)\nserver_file_paths = [\n dpf.upload_file_in_tmp_folder(files[0], server=remote_servers[0]),\n dpf.upload_file_in_tmp_folder(files[1], server=remote_servers[1]),\n]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create operators on each server\r\n\r\nOn each server, create two operators, one for displacement computations\r\nand one for norm computations. Define their data sources:\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# - The displacement operator receives data from the data file in its respective\n# server.\n# - The norm operator, which is chained to the displacement operator, receives\n# input from the output of the displacement operator.\n#\nremote_operators = []\nfor i, server in enumerate(remote_servers):\n displacement = ops.result.displacement(server=server)\n norm = ops.math.norm_fc(displacement, server=server)\n remote_operators.append(norm)\n ds = dpf.DataSources(server_file_paths[i], server=server)\n displacement.inputs.data_sources(ds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create an operator to merge results\r\n\r\nCreate the `merge_fields_containers` operator to merge the results.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "merge = ops.utility.merge_fields_containers()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Connect the operators together and get the output\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for i, server in enumerate(remote_servers):\n merge.connect(i, remote_operators[i], 0)\n\nfc = merge.get_output(0, dpf.types.fields_container)\nprint(fc)\nprint(fc[0].min().data)\nprint(fc[0].max().data)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/00-distributed_total_disp.py b/doc/source/examples/07-distributed-post/00-distributed_total_disp.py new file mode 100644 index 0000000000..2259bb9481 --- /dev/null +++ b/doc/source/examples/07-distributed-post/00-distributed_total_disp.py @@ -0,0 +1,132 @@ +""" +.. _ref_distributed_total_disp: + +Postprocessing of displacement on distributed processes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This diagram helps you to understand this example. It shows +the operator chain that is used to compute the final result. + +.. graphviz:: + + digraph foo { + graph [pad="0", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + + disp01 [label="displacement"]; + disp02 [label="displacement"]; + norm01 [label="norm"]; + norm02 [label="norm"]; + + subgraph cluster_1 { + ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + ds01 -> disp01 [style=dashed]; + disp01 -> norm01; + + label="Server 1"; + style=filled; + fillcolor=lightgrey; + } + + subgraph cluster_2 { + ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + ds02 -> disp02 [style=dashed]; + disp02 -> norm02; + + label="Server 2"; + style=filled; + fillcolor=lightgrey; + } + + norm01 -> "merge"; + norm02 -> "merge"; + } +""" + +############################################################################### +# Import the ``dpf-core`` module and its examples files. + +import os +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + +############################################################################### +# Configure the servers. +# Make a list of IP addresses and port numbers that DPF servers start and +# listen on. Operator instances are created on each of these servers so that +# each can address a different result file. +# +# This example postprocesses an analysis distributed in two files. +# Consequently, it requires two remote processes. +# +# To make it easier, this example starts local servers. However, you can +# connect to any existing servers on your network. + +config = dpf.AvailableServerConfigs.InProcessServer +if "DPF_DOCKER" in os.environ.keys(): + # If running DPF on Docker, you cannot start an InProcessServer + config = dpf.AvailableServerConfigs.GrpcServer +global_server = dpf.start_local_server(as_global=True, config=config) + +remote_servers = [ + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), +] +ips = [remote_server.ip for remote_server in remote_servers] +ports = [remote_server.port for remote_server in remote_servers] + +############################################################################### +# Print the IP addresses and ports. +print("ips:", ips) +print("ports:", ports) + +############################################################################### +# Send files to the temporary directory if they are not in shared memory. +files = examples.download_distributed_files(return_local_path=True) +server_file_paths = [ + dpf.upload_file_in_tmp_folder(files[0], server=remote_servers[0]), + dpf.upload_file_in_tmp_folder(files[1], server=remote_servers[1]), +] + +############################################################################### +# Create operators on each server +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# On each server, create two operators, one for displacement computations +# and one for norm computations. Define their data sources: + +# - The displacement operator receives data from the data file in its respective +# server. +# - The norm operator, which is chained to the displacement operator, receives +# input from the output of the displacement operator. +# +remote_operators = [] +for i, server in enumerate(remote_servers): + displacement = ops.result.displacement(server=server) + norm = ops.math.norm_fc(displacement, server=server) + remote_operators.append(norm) + ds = dpf.DataSources(server_file_paths[i], server=server) + displacement.inputs.data_sources(ds) + +############################################################################### +# Create an operator to merge results +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create the ``merge_fields_containers`` operator to merge the results. + +merge = ops.utility.merge_fields_containers() + +############################################################################### +# Connect the operators together and get the output +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +for i, server in enumerate(remote_servers): + merge.connect(i, remote_operators[i], 0) + +fc = merge.get_output(0, dpf.types.fields_container) +print(fc) +print(fc[0].min().data) +print(fc[0].max().data) diff --git a/doc/source/examples/07-distributed-post/00-distributed_total_disp.py.md5 b/doc/source/examples/07-distributed-post/00-distributed_total_disp.py.md5 new file mode 100644 index 0000000000..5992ebf022 --- /dev/null +++ b/doc/source/examples/07-distributed-post/00-distributed_total_disp.py.md5 @@ -0,0 +1 @@ +0ae2e0ecc18ebbe381e1e317595f9e0e \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/00-distributed_total_disp.rst b/doc/source/examples/07-distributed-post/00-distributed_total_disp.rst new file mode 100644 index 0000000000..51486953a7 --- /dev/null +++ b/doc/source/examples/07-distributed-post/00-distributed_total_disp.rst @@ -0,0 +1,289 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\07-distributed-post\00-distributed_total_disp.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_07-distributed-post_00-distributed_total_disp.py: + + +.. _ref_distributed_total_disp: + +Postprocessing of displacement on distributed processes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This diagram helps you to understand this example. It shows +the operator chain that is used to compute the final result. + +.. graphviz:: + + digraph foo { + graph [pad="0", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + + disp01 [label="displacement"]; + disp02 [label="displacement"]; + norm01 [label="norm"]; + norm02 [label="norm"]; + + subgraph cluster_1 { + ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + ds01 -> disp01 [style=dashed]; + disp01 -> norm01; + + label="Server 1"; + style=filled; + fillcolor=lightgrey; + } + + subgraph cluster_2 { + ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + ds02 -> disp02 [style=dashed]; + disp02 -> norm02; + + label="Server 2"; + style=filled; + fillcolor=lightgrey; + } + + norm01 -> "merge"; + norm02 -> "merge"; + } + +.. GENERATED FROM PYTHON SOURCE LINES 51-52 + +Import the ``dpf-core`` module and its examples files. + +.. GENERATED FROM PYTHON SOURCE LINES 52-58 + +.. code-block:: default + + + import os + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 59-69 + +Configure the servers. +Make a list of IP addresses and port numbers that DPF servers start and +listen on. Operator instances are created on each of these servers so that +each can address a different result file. + +This example postprocesses an analysis distributed in two files. +Consequently, it requires two remote processes. + +To make it easier, this example starts local servers. However, you can +connect to any existing servers on your network. + +.. GENERATED FROM PYTHON SOURCE LINES 69-83 + +.. code-block:: default + + + config = dpf.AvailableServerConfigs.InProcessServer + if "DPF_DOCKER" in os.environ.keys(): + # If running DPF on Docker, you cannot start an InProcessServer + config = dpf.AvailableServerConfigs.GrpcServer + global_server = dpf.start_local_server(as_global=True, config=config) + + remote_servers = [ + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + ] + ips = [remote_server.ip for remote_server in remote_servers] + ports = [remote_server.port for remote_server in remote_servers] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 84-85 + +Print the IP addresses and ports. + +.. GENERATED FROM PYTHON SOURCE LINES 85-88 + +.. code-block:: default + + print("ips:", ips) + print("ports:", ports) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ips: ['127.0.0.1', '127.0.0.1'] + ports: [50055, 50056] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 89-90 + +Send files to the temporary directory if they are not in shared memory. + +.. GENERATED FROM PYTHON SOURCE LINES 90-96 + +.. code-block:: default + + files = examples.download_distributed_files(return_local_path=True) + server_file_paths = [ + dpf.upload_file_in_tmp_folder(files[0], server=remote_servers[0]), + dpf.upload_file_in_tmp_folder(files[1], server=remote_servers[1]), + ] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 97-101 + +Create operators on each server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +On each server, create two operators, one for displacement computations +and one for norm computations. Define their data sources: + +.. GENERATED FROM PYTHON SOURCE LINES 101-115 + +.. code-block:: default + + + # - The displacement operator receives data from the data file in its respective + # server. + # - The norm operator, which is chained to the displacement operator, receives + # input from the output of the displacement operator. + # + remote_operators = [] + for i, server in enumerate(remote_servers): + displacement = ops.result.displacement(server=server) + norm = ops.math.norm_fc(displacement, server=server) + remote_operators.append(norm) + ds = dpf.DataSources(server_file_paths[i], server=server) + displacement.inputs.data_sources(ds) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 116-119 + +Create an operator to merge results +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create the ``merge_fields_containers`` operator to merge the results. + +.. GENERATED FROM PYTHON SOURCE LINES 119-122 + +.. code-block:: default + + + merge = ops.utility.merge_fields_containers() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 123-125 + +Connect the operators together and get the output +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 125-133 + +.. code-block:: default + + + for i, server in enumerate(remote_servers): + merge.connect(i, remote_operators[i], 0) + + fc = merge.get_output(0, dpf.types.fields_container) + print(fc) + print(fc[0].min().data) + print(fc[0].max().data) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Fields Container + with 1 field(s) + defined on labels: time + + with: + - field 0 {time: 1} with Nodal location, 1 components and 432 entities. + + [0.] + [10.03242272] + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 1.235 seconds) + + +.. _sphx_glr_download_examples_07-distributed-post_00-distributed_total_disp.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 00-distributed_total_disp.py <00-distributed_total_disp.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 00-distributed_total_disp.ipynb <00-distributed_total_disp.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/07-distributed-post/00-distributed_total_disp_codeobj.pickle b/doc/source/examples/07-distributed-post/00-distributed_total_disp_codeobj.pickle new file mode 100644 index 0000000000..763c2c05e0 Binary files /dev/null and b/doc/source/examples/07-distributed-post/00-distributed_total_disp_codeobj.pickle differ diff --git a/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.ipynb b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.ipynb new file mode 100644 index 0000000000..4c2b0557d8 --- /dev/null +++ b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.ipynb @@ -0,0 +1,169 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a custom workflow on distributed processes {#ref_distributed_workflows_on_remote}\r\n\r\nThis example shows how to read and postprocess distributed files on\r\ndistributed processes. After remote postprocessing, results are merged\r\non the local process. This example creates different operator sequences\r\ndirectly on different servers. These operators are then connected\r\ntogether so that you don\\'t have to care that they are on remote\r\nprocesses.\r\n\r\n::: graphviz\r\n\r\ndigraph foo {\r\n\r\n: graph \\[pad=\\\"0\\\", nodesep=\\\"0.3\\\", ranksep=\\\"0.3\\\"\\] node\r\n \\[shape=box, style=filled, fillcolor=\\\"#ffcc00\\\", margin=\\\"0\\\"\\];\r\n rankdir=LR; splines=line;\r\n\r\n subgraph cluster_1 {\r\n\r\n : ds01 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n ds01 -\\> stress1 \\[style=dashed\\];\r\n\r\n label=\\\"Server 1\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n }\r\n\r\n subgraph cluster_2 {\r\n\r\n : ds02 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n ds02 -\\> stress2 \\[style=dashed\\]; stress2 -\\> mul;\r\n\r\n label=\\\"Server 2\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n }\r\n\r\n stress1 -\\> \\\"merge\\\"; mul -\\> \\\"merge\\\";\r\n\r\n}\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import the `dpf-core` module and its examples files.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Configure the servers. To make it easier, this example starts local\r\nservers. However, you can connect to any existing servers on your\r\nnetwork.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "config = dpf.AvailableServerConfigs.InProcessServer\nif \"DPF_DOCKER\" in os.environ.keys():\n # If running DPF on Docker, you cannot start an InProcessServer\n config = dpf.AvailableServerConfigs.GrpcServer\nglobal_server = dpf.start_local_server(as_global=True, config=config)\n\nremote_servers = [\n dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer),\n dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer),\n]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Send files to the temporary directory if they are not in shared memory.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "files = examples.download_distributed_files(return_local_path=True)\nserver_file_paths = [\n dpf.upload_file_in_tmp_folder(files[0], server=remote_servers[0]),\n dpf.upload_file_in_tmp_folder(files[1], server=remote_servers[1]),\n]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the first operator chain.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "remote_operators = []\n\nstress1 = ops.result.stress(server=remote_servers[0])\nremote_operators.append(stress1)\nds = dpf.DataSources(server_file_paths[0], server=remote_servers[0])\nstress1.inputs.data_sources(ds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the second operator chain.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "stress2 = ops.result.stress(server=remote_servers[1])\nmul = stress2 * 2.0\nremote_operators.append(mul)\nds = dpf.DataSources(server_file_paths[1], server=remote_servers[1])\nstress2.inputs.data_sources(ds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the local merge operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "merge = ops.utility.merge_fields_containers()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Connect the operator chains together and get the output.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "nodal = ops.averaging.to_nodal_fc(merge)\n\nmerge.connect(0, remote_operators[0], 0)\nmerge.connect(1, remote_operators[1], 0)\n\nfc = nodal.get_output(0, dpf.types.fields_container)\nprint(fc[0])\nfc[0].meshed_region.plot(fc[0])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.py b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.py new file mode 100644 index 0000000000..67d9919b44 --- /dev/null +++ b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.py @@ -0,0 +1,115 @@ +""" +.. _ref_distributed_workflows_on_remote: + +Create a custom workflow on distributed processes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to read and postprocess distributed files on +distributed processes. After remote postprocessing, results are merged +on the local process. This example creates different operator +sequences directly on different servers. These operators are then +connected together so that you don't have to care that they are on +remote processes. + +.. graphviz:: + + digraph foo { + graph [pad="0", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + + subgraph cluster_1 { + ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + ds01 -> stress1 [style=dashed]; + + label="Server 1"; + style=filled; + fillcolor=lightgrey; + } + + subgraph cluster_2 { + ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + ds02 -> stress2 [style=dashed]; + stress2 -> mul; + + label="Server 2"; + style=filled; + fillcolor=lightgrey; + } + + stress1 -> "merge"; + mul -> "merge"; + } + +""" +############################################################################### +# Import the ``dpf-core`` module and its examples files. + +import os +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + +############################################################################### +# Configure the servers. +# To make it easier, this example starts local servers. However, you can +# connect to any existing servers on your network. + +config = dpf.AvailableServerConfigs.InProcessServer +if "DPF_DOCKER" in os.environ.keys(): + # If running DPF on Docker, you cannot start an InProcessServer + config = dpf.AvailableServerConfigs.GrpcServer +global_server = dpf.start_local_server(as_global=True, config=config) + +remote_servers = [ + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), +] + +############################################################################### +# Send files to the temporary directory if they are not in shared memory. + +files = examples.download_distributed_files(return_local_path=True) +server_file_paths = [ + dpf.upload_file_in_tmp_folder(files[0], server=remote_servers[0]), + dpf.upload_file_in_tmp_folder(files[1], server=remote_servers[1]), +] + +############################################################################### +# Create the first operator chain. + +remote_operators = [] + +stress1 = ops.result.stress(server=remote_servers[0]) +remote_operators.append(stress1) +ds = dpf.DataSources(server_file_paths[0], server=remote_servers[0]) +stress1.inputs.data_sources(ds) + +############################################################################### +# Create the second operator chain. + +stress2 = ops.result.stress(server=remote_servers[1]) +mul = stress2 * 2.0 +remote_operators.append(mul) +ds = dpf.DataSources(server_file_paths[1], server=remote_servers[1]) +stress2.inputs.data_sources(ds) + +############################################################################### +# Create the local merge operator. + +merge = ops.utility.merge_fields_containers() + +############################################################################### +# Connect the operator chains together and get the output. + +nodal = ops.averaging.to_nodal_fc(merge) + +merge.connect(0, remote_operators[0], 0) +merge.connect(1, remote_operators[1], 0) + +fc = nodal.get_output(0, dpf.types.fields_container) +print(fc[0]) +fc[0].meshed_region.plot(fc[0]) diff --git a/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.py.md5 b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.py.md5 new file mode 100644 index 0000000000..6fbcc86e56 --- /dev/null +++ b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.py.md5 @@ -0,0 +1 @@ +068fb5adc2e0d60ea06a46e877df85cd \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.rst b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.rst new file mode 100644 index 0000000000..1b495056bd --- /dev/null +++ b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote.rst @@ -0,0 +1,279 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\07-distributed-post\01-distributed_workflows_on_remote.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_07-distributed-post_01-distributed_workflows_on_remote.py: + + +.. _ref_distributed_workflows_on_remote: + +Create a custom workflow on distributed processes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to read and postprocess distributed files on +distributed processes. After remote postprocessing, results are merged +on the local process. This example creates different operator +sequences directly on different servers. These operators are then +connected together so that you don't have to care that they are on +remote processes. + +.. graphviz:: + + digraph foo { + graph [pad="0", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + + subgraph cluster_1 { + ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + ds01 -> stress1 [style=dashed]; + + label="Server 1"; + style=filled; + fillcolor=lightgrey; + } + + subgraph cluster_2 { + ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + ds02 -> stress2 [style=dashed]; + stress2 -> mul; + + label="Server 2"; + style=filled; + fillcolor=lightgrey; + } + + stress1 -> "merge"; + mul -> "merge"; + } + +.. GENERATED FROM PYTHON SOURCE LINES 49-50 + +Import the ``dpf-core`` module and its examples files. + +.. GENERATED FROM PYTHON SOURCE LINES 50-56 + +.. code-block:: default + + + import os + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 57-60 + +Configure the servers. +To make it easier, this example starts local servers. However, you can +connect to any existing servers on your network. + +.. GENERATED FROM PYTHON SOURCE LINES 60-72 + +.. code-block:: default + + + config = dpf.AvailableServerConfigs.InProcessServer + if "DPF_DOCKER" in os.environ.keys(): + # If running DPF on Docker, you cannot start an InProcessServer + config = dpf.AvailableServerConfigs.GrpcServer + global_server = dpf.start_local_server(as_global=True, config=config) + + remote_servers = [ + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + ] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 73-74 + +Send files to the temporary directory if they are not in shared memory. + +.. GENERATED FROM PYTHON SOURCE LINES 74-81 + +.. code-block:: default + + + files = examples.download_distributed_files(return_local_path=True) + server_file_paths = [ + dpf.upload_file_in_tmp_folder(files[0], server=remote_servers[0]), + dpf.upload_file_in_tmp_folder(files[1], server=remote_servers[1]), + ] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 82-83 + +Create the first operator chain. + +.. GENERATED FROM PYTHON SOURCE LINES 83-91 + +.. code-block:: default + + + remote_operators = [] + + stress1 = ops.result.stress(server=remote_servers[0]) + remote_operators.append(stress1) + ds = dpf.DataSources(server_file_paths[0], server=remote_servers[0]) + stress1.inputs.data_sources(ds) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 92-93 + +Create the second operator chain. + +.. GENERATED FROM PYTHON SOURCE LINES 93-100 + +.. code-block:: default + + + stress2 = ops.result.stress(server=remote_servers[1]) + mul = stress2 * 2.0 + remote_operators.append(mul) + ds = dpf.DataSources(server_file_paths[1], server=remote_servers[1]) + stress2.inputs.data_sources(ds) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 101-102 + +Create the local merge operator. + +.. GENERATED FROM PYTHON SOURCE LINES 102-105 + +.. code-block:: default + + + merge = ops.utility.merge_fields_containers() + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 106-107 + +Connect the operator chains together and get the output. + +.. GENERATED FROM PYTHON SOURCE LINES 107-116 + +.. code-block:: default + + + nodal = ops.averaging.to_nodal_fc(merge) + + merge.connect(0, remote_operators[0], 0) + merge.connect(1, remote_operators[1], 0) + + fc = nodal.get_output(0, dpf.types.fields_container) + print(fc[0]) + fc[0].meshed_region.plot(fc[0]) + + + +.. image-sg:: /examples/07-distributed-post/images/sphx_glr_01-distributed_workflows_on_remote_001.png + :alt: 01 distributed workflows on remote + :srcset: /examples/07-distributed-post/images/sphx_glr_01-distributed_workflows_on_remote_001.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF stress_7491.964387Hz Field + Location: Nodal + Unit: Pa + 432 entities + Data: 6 components and 432 elementary data + + Nodal + IDs data(Pa) + ------------ ---------- + 24 -1.931259e+11 4.889198e+11 9.893517e+10 -1.873750e+12 8.823901e+11 2.278725e+10 + + 124 -4.577267e+11 -4.345968e+10 1.408608e+11 -4.123077e+10 1.609307e+10 6.080418e+10 + + 89 -1.935788e+11 -3.031243e+11 1.267524e+11 5.413418e+10 3.645896e+10 -1.808178e+10 + + ... + + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 1.903 seconds) + + +.. _sphx_glr_download_examples_07-distributed-post_01-distributed_workflows_on_remote.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 01-distributed_workflows_on_remote.py <01-distributed_workflows_on_remote.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 01-distributed_workflows_on_remote.ipynb <01-distributed_workflows_on_remote.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote_codeobj.pickle b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote_codeobj.pickle new file mode 100644 index 0000000000..ff9085a13e Binary files /dev/null and b/doc/source/examples/07-distributed-post/01-distributed_workflows_on_remote_codeobj.pickle differ diff --git a/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.ipynb b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.ipynb new file mode 100644 index 0000000000..ad79974280 --- /dev/null +++ b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.ipynb @@ -0,0 +1,169 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Distributed mode superposition (MSUP) {#ref_distributed_msup}\r\n\r\nThis example shows how to read and expand distributed files on\r\ndistributed processes. The modal basis (two distributed files) is read\r\non two remote servers. The modal response is then read and expanded on a\r\nthird server.\r\n\r\nThe following diagram helps you to understand this example. It shows the\r\noperator chain that is used to compute the final result.\r\n\r\n::: graphviz\r\n\r\ndigraph foo {\r\n\r\n: graph \\[pad=\\\"0\\\", nodesep=\\\"0.3\\\", ranksep=\\\"0.3\\\"\\] node\r\n \\[shape=box, style=filled, fillcolor=\\\"#ffcc00\\\", margin=\\\"0\\\"\\];\r\n rankdir=LR; splines=line;\r\n\r\n disp01 \\[label=\\\"displacement\\\"\\]; disp02\r\n \\[label=\\\"displacement\\\"\\]; mesh01 \\[label=\\\"mesh\\\"\\]; mesh02\r\n \\[label=\\\"mesh\\\"\\];\r\n\r\n subgraph cluster_1 {\r\n\r\n : ds01 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n disp01; mesh01;\r\n\r\n ds01 -\\> disp01 \\[style=dashed\\]; ds01 -\\> mesh01\r\n \\[style=dashed\\];\r\n\r\n label=\\\"Server 1\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n }\r\n\r\n subgraph cluster_2 {\r\n\r\n : ds02 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n disp02; mesh02;\r\n\r\n ds02 -\\> disp02 \\[style=dashed\\]; ds02 -\\> mesh02\r\n \\[style=dashed\\];\r\n\r\n label=\\\"Server 2\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n }\r\n\r\n disp01 -\\> \\\"merge_fields\\\"; mesh01 -\\> \\\"merged_mesh\\\"; disp02 -\\>\r\n \\\"merge_fields\\\"; mesh02 -\\> \\\"merged_mesh\\\";\r\n\r\n ds03 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\]; ds03 -\\> \\\"response\\\" \\[style=dashed\\];\r\n\r\n \\\"merged_mesh\\\" -\\> \\\"response\\\"; \\\"response\\\" -\\> \\\"expansion\\\";\r\n \\\"merge_fields\\\" -\\> \\\"expansion\\\"; \\\"expansion\\\" -\\> \\\"component\\\";\r\n\r\n}\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import the `dpf-core` module and its examples files.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Configure the servers\r\n\r\nMake a list of IP addresses and port numbers that DPF servers start and\r\nlisten on. Operator instances are created on each of these servers so\r\nthat each server can address a different result file.\r\n\r\nThis example postprocesses an analysis distributed in two files.\r\nConsequently, it requires two remote processes.\r\n\r\nTo make it easier, this example starts local servers. However, you can\r\nconnect to any existing servers on your network.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "config = dpf.AvailableServerConfigs.InProcessServer\nif \"DPF_DOCKER\" in os.environ.keys():\n # If running DPF on Docker, you cannot start an InProcessServer\n config = dpf.AvailableServerConfigs.GrpcServer\nglobal_server = dpf.start_local_server(as_global=True, config=config)\n\nremote_servers = [\n dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer),\n dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer),\n]\nips = [remote_server.ip for remote_server in remote_servers]\nports = [remote_server.port for remote_server in remote_servers]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the IP addresses and ports.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"ips:\", ips)\nprint(\"ports:\", ports)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the file path.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "base_path = examples.find_distributed_msup_folder()\n\nfiles = [\n dpf.path_utilities.join(base_path, \"file0.mode\"),\n dpf.path_utilities.join(base_path, \"file1.mode\"),\n]\nfiles_aux = [\n dpf.path_utilities.join(base_path, \"file0.rst\"),\n dpf.path_utilities.join(base_path, \"file1.rst\"),\n]\nfiles_rfrq = [\n dpf.path_utilities.join(base_path, \"file_load_1.rfrq\"),\n]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create operators on each server\r\n\r\nOn each server, create two operators, one for displacement computations\r\nand one for providing the mesh. Then, define their data sources. Both\r\nthe displacement operator and mesh provider operator receive data from\r\ntheir respective data files on each server.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "remote_displacement_operators = []\nremote_mesh_operators = []\nfor i, server in enumerate(remote_servers):\n displacement = ops.result.displacement(server=server)\n mesh = ops.mesh.mesh_provider(server=server)\n remote_displacement_operators.append(displacement)\n remote_mesh_operators.append(mesh)\n ds = dpf.DataSources(files[i], server=server)\n ds.add_file_path(files_aux[i])\n displacement.inputs.data_sources(ds)\n mesh.inputs.data_sources(ds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a local operator chain for expansion\r\n\r\nThe following series of operators merge the modal basis and the meshes,\r\nread the modal response, and expand the modal response with the modal\r\nbasis.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "merge_fields = ops.utility.merge_fields_containers()\nmerge_mesh = ops.utility.merge_meshes()\n\nds = dpf.DataSources(files_rfrq[0])\nresponse = ops.result.displacement(data_sources=ds)\nresponse.inputs.mesh(merge_mesh.outputs.merges_mesh)\n\nexpansion = ops.math.modal_superposition(solution_in_modal_space=response, modal_basis=merge_fields)\ncomponent = ops.logic.component_selector_fc(expansion, 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Connect the operator chains together and get the output\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for i, server in enumerate(remote_servers):\n merge_fields.connect(i, remote_displacement_operators[i], 0)\n merge_mesh.connect(i, remote_mesh_operators[i], 0)\n\nfc = component.get_output(0, dpf.types.fields_container)\nmerged_mesh = merge_mesh.get_output(0, dpf.types.meshed_region)\n\nmerged_mesh.plot(fc.get_field_by_time_complex_ids(1, 0))\nmerged_mesh.plot(fc.get_field_by_time_complex_ids(10, 0))\nprint(fc)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.py b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.py new file mode 100644 index 0000000000..1f5d3a3704 --- /dev/null +++ b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.py @@ -0,0 +1,176 @@ +""" +.. _ref_distributed_msup: + +Distributed mode superposition (MSUP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to read and expand distributed files +on distributed processes. The modal basis (two distributed files) is read +on two remote servers. The modal response is then read and expanded on a +third server. + +The following diagram helps you to understand this example. It shows the operator +chain that is used to compute the final result. + +.. graphviz:: + + digraph foo { + graph [pad="0", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + + disp01 [label="displacement"]; + disp02 [label="displacement"]; + mesh01 [label="mesh"]; + mesh02 [label="mesh"]; + + subgraph cluster_1 { + ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + disp01; mesh01; + + ds01 -> disp01 [style=dashed]; + ds01 -> mesh01 [style=dashed]; + + label="Server 1"; + style=filled; + fillcolor=lightgrey; + } + + subgraph cluster_2 { + ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + + disp02; mesh02; + + ds02 -> disp02 [style=dashed]; + ds02 -> mesh02 [style=dashed]; + + label="Server 2"; + style=filled; + fillcolor=lightgrey; + } + + disp01 -> "merge_fields"; + mesh01 -> "merged_mesh"; + disp02 -> "merge_fields"; + mesh02 -> "merged_mesh"; + + ds03 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + ds03 -> "response" [style=dashed]; + + "merged_mesh" -> "response"; + "response" -> "expansion"; + "merge_fields" -> "expansion"; + "expansion" -> "component"; + } + +""" + +############################################################################### +# Import the ``dpf-core`` module and its examples files. + +import os +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + + +############################################################################### +# Configure the servers +# ~~~~~~~~~~~~~~~~~~~~~ +# Make a list of IP addresses and port numbers that DPF servers start and +# listen on. Operator instances are created on each of these servers so that +# each server can address a different result file. +# +# This example postprocesses an analysis distributed in two files. +# Consequently, it requires two remote processes. +# +# To make it easier, this example starts local servers. However, you can +# connect to any existing servers on your network. + +config = dpf.AvailableServerConfigs.InProcessServer +if "DPF_DOCKER" in os.environ.keys(): + # If running DPF on Docker, you cannot start an InProcessServer + config = dpf.AvailableServerConfigs.GrpcServer +global_server = dpf.start_local_server(as_global=True, config=config) + +remote_servers = [ + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), +] +ips = [remote_server.ip for remote_server in remote_servers] +ports = [remote_server.port for remote_server in remote_servers] + +############################################################################### +# Print the IP addresses and ports. +print("ips:", ips) +print("ports:", ports) + +############################################################################### +# Specify the file path. + +base_path = examples.find_distributed_msup_folder() + +files = [ + dpf.path_utilities.join(base_path, "file0.mode"), + dpf.path_utilities.join(base_path, "file1.mode"), +] +files_aux = [ + dpf.path_utilities.join(base_path, "file0.rst"), + dpf.path_utilities.join(base_path, "file1.rst"), +] +files_rfrq = [ + dpf.path_utilities.join(base_path, "file_load_1.rfrq"), +] + +############################################################################### +# Create operators on each server +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# On each server, create two operators, one for displacement computations +# and one for providing the mesh. Then, define their data sources. Both the +# displacement operator and mesh provider operator receive data from their +# respective data files on each server. + +remote_displacement_operators = [] +remote_mesh_operators = [] +for i, server in enumerate(remote_servers): + displacement = ops.result.displacement(server=server) + mesh = ops.mesh.mesh_provider(server=server) + remote_displacement_operators.append(displacement) + remote_mesh_operators.append(mesh) + ds = dpf.DataSources(files[i], server=server) + ds.add_file_path(files_aux[i]) + displacement.inputs.data_sources(ds) + mesh.inputs.data_sources(ds) + +############################################################################### +# Create a local operator chain for expansion +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The following series of operators merge the modal basis and the meshes, read +# the modal response, and expand the modal response with the modal basis. + +merge_fields = ops.utility.merge_fields_containers() +merge_mesh = ops.utility.merge_meshes() + +ds = dpf.DataSources(files_rfrq[0]) +response = ops.result.displacement(data_sources=ds) +response.inputs.mesh(merge_mesh.outputs.merges_mesh) + +expansion = ops.math.modal_superposition(solution_in_modal_space=response, modal_basis=merge_fields) +component = ops.logic.component_selector_fc(expansion, 1) + +############################################################################### +# Connect the operator chains together and get the output +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +for i, server in enumerate(remote_servers): + merge_fields.connect(i, remote_displacement_operators[i], 0) + merge_mesh.connect(i, remote_mesh_operators[i], 0) + +fc = component.get_output(0, dpf.types.fields_container) +merged_mesh = merge_mesh.get_output(0, dpf.types.meshed_region) + +merged_mesh.plot(fc.get_field_by_time_complex_ids(1, 0)) +merged_mesh.plot(fc.get_field_by_time_complex_ids(10, 0)) +print(fc) diff --git a/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.py.md5 b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.py.md5 new file mode 100644 index 0000000000..f3ed13dfd5 --- /dev/null +++ b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.py.md5 @@ -0,0 +1 @@ +2e15c4d94c6fc27664f20c851cec7aad \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.rst b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.rst new file mode 100644 index 0000000000..dd6c8044d1 --- /dev/null +++ b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion.rst @@ -0,0 +1,366 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\07-distributed-post\02-distributed-msup_expansion.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_07-distributed-post_02-distributed-msup_expansion.py: + + +.. _ref_distributed_msup: + +Distributed mode superposition (MSUP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to read and expand distributed files +on distributed processes. The modal basis (two distributed files) is read +on two remote servers. The modal response is then read and expanded on a +third server. + +The following diagram helps you to understand this example. It shows the operator +chain that is used to compute the final result. + +.. graphviz:: + + digraph foo { + graph [pad="0", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + + disp01 [label="displacement"]; + disp02 [label="displacement"]; + mesh01 [label="mesh"]; + mesh02 [label="mesh"]; + + subgraph cluster_1 { + ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + disp01; mesh01; + + ds01 -> disp01 [style=dashed]; + ds01 -> mesh01 [style=dashed]; + + label="Server 1"; + style=filled; + fillcolor=lightgrey; + } + + subgraph cluster_2 { + ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + + disp02; mesh02; + + ds02 -> disp02 [style=dashed]; + ds02 -> mesh02 [style=dashed]; + + label="Server 2"; + style=filled; + fillcolor=lightgrey; + } + + disp01 -> "merge_fields"; + mesh01 -> "merged_mesh"; + disp02 -> "merge_fields"; + mesh02 -> "merged_mesh"; + + ds03 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + ds03 -> "response" [style=dashed]; + + "merged_mesh" -> "response"; + "response" -> "expansion"; + "merge_fields" -> "expansion"; + "expansion" -> "component"; + } + +.. GENERATED FROM PYTHON SOURCE LINES 72-73 + +Import the ``dpf-core`` module and its examples files. + +.. GENERATED FROM PYTHON SOURCE LINES 73-80 + +.. code-block:: default + + + import os + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 81-92 + +Configure the servers +~~~~~~~~~~~~~~~~~~~~~ +Make a list of IP addresses and port numbers that DPF servers start and +listen on. Operator instances are created on each of these servers so that +each server can address a different result file. + +This example postprocesses an analysis distributed in two files. +Consequently, it requires two remote processes. + +To make it easier, this example starts local servers. However, you can +connect to any existing servers on your network. + +.. GENERATED FROM PYTHON SOURCE LINES 92-106 + +.. code-block:: default + + + config = dpf.AvailableServerConfigs.InProcessServer + if "DPF_DOCKER" in os.environ.keys(): + # If running DPF on Docker, you cannot start an InProcessServer + config = dpf.AvailableServerConfigs.GrpcServer + global_server = dpf.start_local_server(as_global=True, config=config) + + remote_servers = [ + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + ] + ips = [remote_server.ip for remote_server in remote_servers] + ports = [remote_server.port for remote_server in remote_servers] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 107-108 + +Print the IP addresses and ports. + +.. GENERATED FROM PYTHON SOURCE LINES 108-111 + +.. code-block:: default + + print("ips:", ips) + print("ports:", ports) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ips: ['127.0.0.1', '127.0.0.1'] + ports: [50055, 50056] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 112-113 + +Specify the file path. + +.. GENERATED FROM PYTHON SOURCE LINES 113-128 + +.. code-block:: default + + + base_path = examples.find_distributed_msup_folder() + + files = [ + dpf.path_utilities.join(base_path, "file0.mode"), + dpf.path_utilities.join(base_path, "file1.mode"), + ] + files_aux = [ + dpf.path_utilities.join(base_path, "file0.rst"), + dpf.path_utilities.join(base_path, "file1.rst"), + ] + files_rfrq = [ + dpf.path_utilities.join(base_path, "file_load_1.rfrq"), + ] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 129-135 + +Create operators on each server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +On each server, create two operators, one for displacement computations +and one for providing the mesh. Then, define their data sources. Both the +displacement operator and mesh provider operator receive data from their +respective data files on each server. + +.. GENERATED FROM PYTHON SOURCE LINES 135-148 + +.. code-block:: default + + + remote_displacement_operators = [] + remote_mesh_operators = [] + for i, server in enumerate(remote_servers): + displacement = ops.result.displacement(server=server) + mesh = ops.mesh.mesh_provider(server=server) + remote_displacement_operators.append(displacement) + remote_mesh_operators.append(mesh) + ds = dpf.DataSources(files[i], server=server) + ds.add_file_path(files_aux[i]) + displacement.inputs.data_sources(ds) + mesh.inputs.data_sources(ds) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 149-153 + +Create a local operator chain for expansion +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The following series of operators merge the modal basis and the meshes, read +the modal response, and expand the modal response with the modal basis. + +.. GENERATED FROM PYTHON SOURCE LINES 153-164 + +.. code-block:: default + + + merge_fields = ops.utility.merge_fields_containers() + merge_mesh = ops.utility.merge_meshes() + + ds = dpf.DataSources(files_rfrq[0]) + response = ops.result.displacement(data_sources=ds) + response.inputs.mesh(merge_mesh.outputs.merges_mesh) + + expansion = ops.math.modal_superposition(solution_in_modal_space=response, modal_basis=merge_fields) + component = ops.logic.component_selector_fc(expansion, 1) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 165-167 + +Connect the operator chains together and get the output +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 167-177 + +.. code-block:: default + + for i, server in enumerate(remote_servers): + merge_fields.connect(i, remote_displacement_operators[i], 0) + merge_mesh.connect(i, remote_mesh_operators[i], 0) + + fc = component.get_output(0, dpf.types.fields_container) + merged_mesh = merge_mesh.get_output(0, dpf.types.meshed_region) + + merged_mesh.plot(fc.get_field_by_time_complex_ids(1, 0)) + merged_mesh.plot(fc.get_field_by_time_complex_ids(10, 0)) + print(fc) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_001.png + :alt: 02 distributed msup expansion + :srcset: /examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_002.png + :alt: 02 distributed msup expansion + :srcset: /examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_002.png + :class: sphx-glr-multi-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Fields Container + with 20 field(s) + defined on labels: complex time + + with: + - field 0 {complex: 0, time: 1} with Nodal location, 1 components and 1065 entities. + - field 1 {complex: 1, time: 1} with Nodal location, 1 components and 1065 entities. + - field 2 {complex: 0, time: 2} with Nodal location, 1 components and 1065 entities. + - field 3 {complex: 1, time: 2} with Nodal location, 1 components and 1065 entities. + - field 4 {complex: 0, time: 3} with Nodal location, 1 components and 1065 entities. + - field 5 {complex: 1, time: 3} with Nodal location, 1 components and 1065 entities. + - field 6 {complex: 0, time: 4} with Nodal location, 1 components and 1065 entities. + - field 7 {complex: 1, time: 4} with Nodal location, 1 components and 1065 entities. + - field 8 {complex: 0, time: 5} with Nodal location, 1 components and 1065 entities. + - field 9 {complex: 1, time: 5} with Nodal location, 1 components and 1065 entities. + - field 10 {complex: 0, time: 6} with Nodal location, 1 components and 1065 entities. + - field 11 {complex: 1, time: 6} with Nodal location, 1 components and 1065 entities. + - field 12 {complex: 0, time: 7} with Nodal location, 1 components and 1065 entities. + - field 13 {complex: 1, time: 7} with Nodal location, 1 components and 1065 entities. + - field 14 {complex: 0, time: 8} with Nodal location, 1 components and 1065 entities. + - field 15 {complex: 1, time: 8} with Nodal location, 1 components and 1065 entities. + - field 16 {complex: 0, time: 9} with Nodal location, 1 components and 1065 entities. + - field 17 {complex: 1, time: 9} with Nodal location, 1 components and 1065 entities. + - field 18 {complex: 0, time: 10} with Nodal location, 1 components and 1065 entities. + - field 19 {complex: 1, time: 10} with Nodal location, 1 components and 1065 entities. + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 8.269 seconds) + + +.. _sphx_glr_download_examples_07-distributed-post_02-distributed-msup_expansion.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 02-distributed-msup_expansion.py <02-distributed-msup_expansion.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 02-distributed-msup_expansion.ipynb <02-distributed-msup_expansion.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/07-distributed-post/02-distributed-msup_expansion_codeobj.pickle b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion_codeobj.pickle new file mode 100644 index 0000000000..e0cd049306 Binary files /dev/null and b/doc/source/examples/07-distributed-post/02-distributed-msup_expansion_codeobj.pickle differ diff --git a/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.ipynb b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.ipynb new file mode 100644 index 0000000000..6a73f45a28 --- /dev/null +++ b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.ipynb @@ -0,0 +1,169 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Distributed MSUP distributed modal response {#ref_distributed_msup_steps}\r\n\r\nThis example shows how to read and expand distributed files on\r\ndistributed processes. The modal basis (two distributed files) is read\r\non two remote servers. The modal response (two distributed files) is\r\nthen read and expanded on a third server.\r\n\r\nThe following diagram helps you to understand this example. It shows the\r\noperator chain that is used to compute the final result.\r\n\r\n::: graphviz\r\n\r\ndigraph foo {\r\n\r\n: graph \\[pad=\\\"0\\\", nodesep=\\\"0.3\\\", ranksep=\\\"0.3\\\"\\] node\r\n \\[shape=box, style=filled, fillcolor=\\\"#ffcc00\\\", margin=\\\"0\\\"\\];\r\n rankdir=LR; splines=line;\r\n\r\n disp01 \\[label=\\\"displacement\\\"\\]; disp02\r\n \\[label=\\\"displacement\\\"\\]; mesh01 \\[label=\\\"mesh\\\"\\]; mesh02\r\n \\[label=\\\"mesh\\\"\\];\r\n\r\n subgraph cluster_1 {\r\n\r\n : ds01 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n disp01; mesh01;\r\n\r\n ds01 -\\> disp01 \\[style=dashed\\]; ds01 -\\> mesh01\r\n \\[style=dashed\\];\r\n\r\n label=\\\"Server 1\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n }\r\n\r\n subgraph cluster_2 {\r\n\r\n : ds02 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n disp02; mesh02;\r\n\r\n ds02 -\\> disp02 \\[style=dashed\\]; ds02 -\\> mesh02\r\n \\[style=dashed\\];\r\n\r\n label=\\\"Server 2\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n }\r\n\r\n disp01 -\\> \\\"merge_fields\\\"; mesh01 -\\> \\\"merge_mesh\\\"; disp02 -\\>\r\n \\\"merge_fields\\\"; mesh02 -\\> \\\"merge_mesh\\\";\r\n\r\n ds03 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\]; ds03 -\\> \\\"response2\\\" \\[style=dashed\\];\r\n ds04 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\]; ds04 -\\> \\\"response\\\" \\[style=dashed\\];\r\n\r\n \\\"merge_mesh\\\" -\\> \\\"response\\\"; \\\"response\\\" -\\>\r\n \\\"merge_use_pass\\\"; \\\"response2\\\" -\\> \\\"merge_use_pass\\\";\r\n \\\"merge_use_pass\\\" -\\> \\\"expansion\\\"; \\\"merge_fields\\\" -\\>\r\n \\\"expansion\\\"; \\\"expansion\\\" -\\> \\\"component\\\";\r\n\r\n}\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import the `dpf-core` module and its examples files.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Configure the servers\r\n\r\nMake a list of IP addresses and port numbers that DPF servers start and\r\nlisten on. Operator instances are created on each of these servers so\r\nthat each server can address a different result file.\r\n\r\nThis example postprocesses an analysis distributed in two files.\r\nConsequently, it requires two remote processes.\r\n\r\nTo make it easier, this example starts local servers. However, you can\r\nconnect to any existing servers on your network.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "config = dpf.AvailableServerConfigs.InProcessServer\nif \"DPF_DOCKER\" in os.environ.keys():\n # If running DPF on Docker, you cannot start an InProcessServer\n config = dpf.AvailableServerConfigs.GrpcServer\nglobal_server = dpf.start_local_server(as_global=True, config=config)\n\nremote_servers = [\n dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer),\n dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer),\n]\n\nips = [remote_server.ip for remote_server in remote_servers]\nports = [remote_server.port for remote_server in remote_servers]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the IP addresses and ports.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"ips:\", ips)\nprint(\"ports:\", ports)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the file path.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "base_path = examples.find_distributed_msup_folder()\n\nfiles = [\n dpf.path_utilities.join(base_path, \"file0.mode\"),\n dpf.path_utilities.join(base_path, \"file1.mode\"),\n]\nfiles_aux = [\n dpf.path_utilities.join(base_path, \"file0.rst\"),\n dpf.path_utilities.join(base_path, \"file1.rst\"),\n]\nfiles_rfrq = [\n dpf.path_utilities.join(base_path, \"file_load_1.rfrq\"),\n dpf.path_utilities.join(base_path, \"file_load_2.rfrq\"),\n]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create operators on each server\r\n\r\nOn each server, create two operators, one for displacement computations\r\nand one for providing the mesh. Then, define their data sources. Both\r\nthe displacement operator and mesh provider operator receive data from\r\ntheir respective data files on each server.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "remote_displacement_operators = []\nremote_mesh_operators = []\nfor i, server in enumerate(remote_servers):\n displacement = ops.result.displacement(server=server)\n mesh = ops.mesh.mesh_provider(server=server)\n remote_displacement_operators.append(displacement)\n remote_mesh_operators.append(mesh)\n ds = dpf.DataSources(files[i], server=server)\n ds.add_file_path(files_aux[i])\n displacement.inputs.data_sources(ds)\n mesh.inputs.data_sources(ds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a local operator chain for expansion\r\n\r\nThe following series of operators merge the modal basis and the meshes,\r\nread the modal response, and expand the modal response with the modal\r\nbasis.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "merge_fields = ops.utility.merge_fields_containers()\nmerge_mesh = ops.utility.merge_meshes()\n\nds = dpf.DataSources(files_rfrq[0])\nresponse = ops.result.displacement(data_sources=ds)\nresponse.inputs.mesh(merge_mesh.outputs.merges_mesh)\n\nds = dpf.DataSources(files_rfrq[1])\nresponse2 = ops.result.displacement(data_sources=ds)\nresponse2fc = response2.outputs.fields_container()\nresponse2fc.time_freq_support.time_frequencies.scoping.set_id(0, 2)\n\nmerge_use_pass = ops.utility.merge_fields_containers()\nmerge_use_pass.inputs.fields_containers1(response)\nmerge_use_pass.inputs.fields_containers2(response2fc)\n\nexpansion = ops.math.modal_superposition(\n solution_in_modal_space=merge_use_pass, modal_basis=merge_fields\n)\ncomponent = ops.logic.component_selector_fc(expansion, 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Connect the operator chains together and get the output\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for i, server in enumerate(remote_servers):\n merge_fields.connect(i, remote_displacement_operators[i], 0)\n merge_mesh.connect(i, remote_mesh_operators[i], 0)\n\nfc = component.get_output(0, dpf.types.fields_container)\nmerged_mesh = merge_mesh.get_output(0, dpf.types.meshed_region)\n\nmerged_mesh.plot(fc.get_field_by_time_complex_ids(1, 0))\nmerged_mesh.plot(fc.get_field_by_time_complex_ids(20, 0))\nprint(fc)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.py b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.py new file mode 100644 index 0000000000..f11bab37eb --- /dev/null +++ b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.py @@ -0,0 +1,192 @@ +""" +.. _ref_distributed_msup_steps: + +Distributed MSUP distributed modal response +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to read and expand distributed files on distributed +processes. The modal basis (two distributed files) is read on two remote +servers. The modal response (two distributed files) is then read and expanded +on a third server. + +The following diagram helps you to understand this example. It shows the operator +chain that is used to compute the final result. + +.. graphviz:: + + digraph foo { + graph [pad="0", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + + disp01 [label="displacement"]; + disp02 [label="displacement"]; + mesh01 [label="mesh"]; + mesh02 [label="mesh"]; + + subgraph cluster_1 { + ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + disp01; mesh01; + + ds01 -> disp01 [style=dashed]; + ds01 -> mesh01 [style=dashed]; + + label="Server 1"; + style=filled; + fillcolor=lightgrey; + } + + subgraph cluster_2 { + ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + disp02; mesh02; + + ds02 -> disp02 [style=dashed]; + ds02 -> mesh02 [style=dashed]; + + label="Server 2"; + style=filled; + fillcolor=lightgrey; + } + + disp01 -> "merge_fields"; + mesh01 -> "merge_mesh"; + disp02 -> "merge_fields"; + mesh02 -> "merge_mesh"; + + ds03 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + ds03 -> "response2" [style=dashed]; + ds04 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + ds04 -> "response" [style=dashed]; + + "merge_mesh" -> "response"; + "response" -> "merge_use_pass"; + "response2" -> "merge_use_pass"; + "merge_use_pass" -> "expansion"; + "merge_fields" -> "expansion"; + "expansion" -> "component"; + } + +""" + +############################################################################### +# Import the ``dpf-core`` module and its examples files. + +import os +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + + +############################################################################### +# Configure the servers +# ~~~~~~~~~~~~~~~~~~~~~ +# Make a list of IP addresses and port numbers that DPF servers start and +# listen on. Operator instances are created on each of these servers so that +# each server can address a different result file. +# +# This example postprocesses an analysis distributed in two files. +# Consequently, it requires two remote processes. +# +# To make it easier, this example starts local servers. However, you can +# connect to any existing servers on your network. + +config = dpf.AvailableServerConfigs.InProcessServer +if "DPF_DOCKER" in os.environ.keys(): + # If running DPF on Docker, you cannot start an InProcessServer + config = dpf.AvailableServerConfigs.GrpcServer +global_server = dpf.start_local_server(as_global=True, config=config) + +remote_servers = [ + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), +] + +ips = [remote_server.ip for remote_server in remote_servers] +ports = [remote_server.port for remote_server in remote_servers] + +############################################################################### +# Print the IP addresses and ports. +print("ips:", ips) +print("ports:", ports) + +############################################################################### +# Specify the file path. + +base_path = examples.find_distributed_msup_folder() + +files = [ + dpf.path_utilities.join(base_path, "file0.mode"), + dpf.path_utilities.join(base_path, "file1.mode"), +] +files_aux = [ + dpf.path_utilities.join(base_path, "file0.rst"), + dpf.path_utilities.join(base_path, "file1.rst"), +] +files_rfrq = [ + dpf.path_utilities.join(base_path, "file_load_1.rfrq"), + dpf.path_utilities.join(base_path, "file_load_2.rfrq"), +] + +############################################################################### +# Create operators on each server +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# On each server, create two operators, one for displacement computations +# and one for providing the mesh. Then, define their data sources. Both the +# displacement operator and mesh provider operator receive data from their +# respective data files on each server. + +remote_displacement_operators = [] +remote_mesh_operators = [] +for i, server in enumerate(remote_servers): + displacement = ops.result.displacement(server=server) + mesh = ops.mesh.mesh_provider(server=server) + remote_displacement_operators.append(displacement) + remote_mesh_operators.append(mesh) + ds = dpf.DataSources(files[i], server=server) + ds.add_file_path(files_aux[i]) + displacement.inputs.data_sources(ds) + mesh.inputs.data_sources(ds) + +############################################################################### +# Create a local operator chain for expansion +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The following series of operators merge the modal basis and the meshes, read +# the modal response, and expand the modal response with the modal basis. + +merge_fields = ops.utility.merge_fields_containers() +merge_mesh = ops.utility.merge_meshes() + +ds = dpf.DataSources(files_rfrq[0]) +response = ops.result.displacement(data_sources=ds) +response.inputs.mesh(merge_mesh.outputs.merges_mesh) + +ds = dpf.DataSources(files_rfrq[1]) +response2 = ops.result.displacement(data_sources=ds) +response2fc = response2.outputs.fields_container() +response2fc.time_freq_support.time_frequencies.scoping.set_id(0, 2) + +merge_use_pass = ops.utility.merge_fields_containers() +merge_use_pass.inputs.fields_containers1(response) +merge_use_pass.inputs.fields_containers2(response2fc) + +expansion = ops.math.modal_superposition( + solution_in_modal_space=merge_use_pass, modal_basis=merge_fields +) +component = ops.logic.component_selector_fc(expansion, 1) + +############################################################################### +# Connect the operator chains together and get the output +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +for i, server in enumerate(remote_servers): + merge_fields.connect(i, remote_displacement_operators[i], 0) + merge_mesh.connect(i, remote_mesh_operators[i], 0) + +fc = component.get_output(0, dpf.types.fields_container) +merged_mesh = merge_mesh.get_output(0, dpf.types.meshed_region) + +merged_mesh.plot(fc.get_field_by_time_complex_ids(1, 0)) +merged_mesh.plot(fc.get_field_by_time_complex_ids(20, 0)) +print(fc) diff --git a/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.py.md5 b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.py.md5 new file mode 100644 index 0000000000..aba31c97ff --- /dev/null +++ b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.py.md5 @@ -0,0 +1 @@ +d3e532c0b308413aa5de18794fab80be \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.rst b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.rst new file mode 100644 index 0000000000..068eeed165 --- /dev/null +++ b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps.rst @@ -0,0 +1,402 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\07-distributed-post\03-distributed-msup_expansion_steps.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_07-distributed-post_03-distributed-msup_expansion_steps.py: + + +.. _ref_distributed_msup_steps: + +Distributed MSUP distributed modal response +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to read and expand distributed files on distributed +processes. The modal basis (two distributed files) is read on two remote +servers. The modal response (two distributed files) is then read and expanded +on a third server. + +The following diagram helps you to understand this example. It shows the operator +chain that is used to compute the final result. + +.. graphviz:: + + digraph foo { + graph [pad="0", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + + disp01 [label="displacement"]; + disp02 [label="displacement"]; + mesh01 [label="mesh"]; + mesh02 [label="mesh"]; + + subgraph cluster_1 { + ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + disp01; mesh01; + + ds01 -> disp01 [style=dashed]; + ds01 -> mesh01 [style=dashed]; + + label="Server 1"; + style=filled; + fillcolor=lightgrey; + } + + subgraph cluster_2 { + ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + + disp02; mesh02; + + ds02 -> disp02 [style=dashed]; + ds02 -> mesh02 [style=dashed]; + + label="Server 2"; + style=filled; + fillcolor=lightgrey; + } + + disp01 -> "merge_fields"; + mesh01 -> "merge_mesh"; + disp02 -> "merge_fields"; + mesh02 -> "merge_mesh"; + + ds03 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + ds03 -> "response2" [style=dashed]; + ds04 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + ds04 -> "response" [style=dashed]; + + "merge_mesh" -> "response"; + "response" -> "merge_use_pass"; + "response2" -> "merge_use_pass"; + "merge_use_pass" -> "expansion"; + "merge_fields" -> "expansion"; + "expansion" -> "component"; + } + +.. GENERATED FROM PYTHON SOURCE LINES 75-76 + +Import the ``dpf-core`` module and its examples files. + +.. GENERATED FROM PYTHON SOURCE LINES 76-83 + +.. code-block:: default + + + import os + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 84-95 + +Configure the servers +~~~~~~~~~~~~~~~~~~~~~ +Make a list of IP addresses and port numbers that DPF servers start and +listen on. Operator instances are created on each of these servers so that +each server can address a different result file. + +This example postprocesses an analysis distributed in two files. +Consequently, it requires two remote processes. + +To make it easier, this example starts local servers. However, you can +connect to any existing servers on your network. + +.. GENERATED FROM PYTHON SOURCE LINES 95-110 + +.. code-block:: default + + + config = dpf.AvailableServerConfigs.InProcessServer + if "DPF_DOCKER" in os.environ.keys(): + # If running DPF on Docker, you cannot start an InProcessServer + config = dpf.AvailableServerConfigs.GrpcServer + global_server = dpf.start_local_server(as_global=True, config=config) + + remote_servers = [ + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + dpf.start_local_server(as_global=False, config=dpf.AvailableServerConfigs.GrpcServer), + ] + + ips = [remote_server.ip for remote_server in remote_servers] + ports = [remote_server.port for remote_server in remote_servers] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 111-112 + +Print the IP addresses and ports. + +.. GENERATED FROM PYTHON SOURCE LINES 112-115 + +.. code-block:: default + + print("ips:", ips) + print("ports:", ports) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ips: ['127.0.0.1', '127.0.0.1'] + ports: [50055, 50056] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 116-117 + +Specify the file path. + +.. GENERATED FROM PYTHON SOURCE LINES 117-133 + +.. code-block:: default + + + base_path = examples.find_distributed_msup_folder() + + files = [ + dpf.path_utilities.join(base_path, "file0.mode"), + dpf.path_utilities.join(base_path, "file1.mode"), + ] + files_aux = [ + dpf.path_utilities.join(base_path, "file0.rst"), + dpf.path_utilities.join(base_path, "file1.rst"), + ] + files_rfrq = [ + dpf.path_utilities.join(base_path, "file_load_1.rfrq"), + dpf.path_utilities.join(base_path, "file_load_2.rfrq"), + ] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 134-140 + +Create operators on each server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +On each server, create two operators, one for displacement computations +and one for providing the mesh. Then, define their data sources. Both the +displacement operator and mesh provider operator receive data from their +respective data files on each server. + +.. GENERATED FROM PYTHON SOURCE LINES 140-153 + +.. code-block:: default + + + remote_displacement_operators = [] + remote_mesh_operators = [] + for i, server in enumerate(remote_servers): + displacement = ops.result.displacement(server=server) + mesh = ops.mesh.mesh_provider(server=server) + remote_displacement_operators.append(displacement) + remote_mesh_operators.append(mesh) + ds = dpf.DataSources(files[i], server=server) + ds.add_file_path(files_aux[i]) + displacement.inputs.data_sources(ds) + mesh.inputs.data_sources(ds) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 154-158 + +Create a local operator chain for expansion +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The following series of operators merge the modal basis and the meshes, read +the modal response, and expand the modal response with the modal basis. + +.. GENERATED FROM PYTHON SOURCE LINES 158-180 + +.. code-block:: default + + + merge_fields = ops.utility.merge_fields_containers() + merge_mesh = ops.utility.merge_meshes() + + ds = dpf.DataSources(files_rfrq[0]) + response = ops.result.displacement(data_sources=ds) + response.inputs.mesh(merge_mesh.outputs.merges_mesh) + + ds = dpf.DataSources(files_rfrq[1]) + response2 = ops.result.displacement(data_sources=ds) + response2fc = response2.outputs.fields_container() + response2fc.time_freq_support.time_frequencies.scoping.set_id(0, 2) + + merge_use_pass = ops.utility.merge_fields_containers() + merge_use_pass.inputs.fields_containers1(response) + merge_use_pass.inputs.fields_containers2(response2fc) + + expansion = ops.math.modal_superposition( + solution_in_modal_space=merge_use_pass, modal_basis=merge_fields + ) + component = ops.logic.component_selector_fc(expansion, 1) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 181-183 + +Connect the operator chains together and get the output +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 183-193 + +.. code-block:: default + + for i, server in enumerate(remote_servers): + merge_fields.connect(i, remote_displacement_operators[i], 0) + merge_mesh.connect(i, remote_mesh_operators[i], 0) + + fc = component.get_output(0, dpf.types.fields_container) + merged_mesh = merge_mesh.get_output(0, dpf.types.meshed_region) + + merged_mesh.plot(fc.get_field_by_time_complex_ids(1, 0)) + merged_mesh.plot(fc.get_field_by_time_complex_ids(20, 0)) + print(fc) + + + +.. rst-class:: sphx-glr-horizontal + + + * + + .. image-sg:: /examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_001.png + :alt: 03 distributed msup expansion steps + :srcset: /examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_001.png + :class: sphx-glr-multi-img + + * + + .. image-sg:: /examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_002.png + :alt: 03 distributed msup expansion steps + :srcset: /examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_002.png + :class: sphx-glr-multi-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Fields Container + with 40 field(s) + defined on labels: complex time + + with: + - field 0 {complex: 0, time: 1} with Nodal location, 1 components and 1065 entities. + - field 1 {complex: 1, time: 1} with Nodal location, 1 components and 1065 entities. + - field 2 {complex: 0, time: 2} with Nodal location, 1 components and 1065 entities. + - field 3 {complex: 1, time: 2} with Nodal location, 1 components and 1065 entities. + - field 4 {complex: 0, time: 3} with Nodal location, 1 components and 1065 entities. + - field 5 {complex: 1, time: 3} with Nodal location, 1 components and 1065 entities. + - field 6 {complex: 0, time: 4} with Nodal location, 1 components and 1065 entities. + - field 7 {complex: 1, time: 4} with Nodal location, 1 components and 1065 entities. + - field 8 {complex: 0, time: 5} with Nodal location, 1 components and 1065 entities. + - field 9 {complex: 1, time: 5} with Nodal location, 1 components and 1065 entities. + - field 10 {complex: 0, time: 6} with Nodal location, 1 components and 1065 entities. + - field 11 {complex: 1, time: 6} with Nodal location, 1 components and 1065 entities. + - field 12 {complex: 0, time: 7} with Nodal location, 1 components and 1065 entities. + - field 13 {complex: 1, time: 7} with Nodal location, 1 components and 1065 entities. + - field 14 {complex: 0, time: 8} with Nodal location, 1 components and 1065 entities. + - field 15 {complex: 1, time: 8} with Nodal location, 1 components and 1065 entities. + - field 16 {complex: 0, time: 9} with Nodal location, 1 components and 1065 entities. + - field 17 {complex: 1, time: 9} with Nodal location, 1 components and 1065 entities. + - field 18 {complex: 0, time: 10} with Nodal location, 1 components and 1065 entities. + - field 19 {complex: 1, time: 10} with Nodal location, 1 components and 1065 entities. + - field 20 {complex: 0, time: 11} with Nodal location, 1 components and 1065 entities. + - field 21 {complex: 1, time: 11} with Nodal location, 1 components and 1065 entities. + - field 22 {complex: 0, time: 12} with Nodal location, 1 components and 1065 entities. + - field 23 {complex: 1, time: 12} with Nodal location, 1 components and 1065 entities. + - field 24 {complex: 0, time: 13} with Nodal location, 1 components and 1065 entities. + - field 25 {complex: 1, time: 13} with Nodal location, 1 components and 1065 entities. + - field 26 {complex: 0, time: 14} with Nodal location, 1 components and 1065 entities. + - field 27 {complex: 1, time: 14} with Nodal location, 1 components and 1065 entities. + - field 28 {complex: 0, time: 15} with Nodal location, 1 components and 1065 entities. + - field 29 {complex: 1, time: 15} with Nodal location, 1 components and 1065 entities. + - field 30 {complex: 0, time: 16} with Nodal location, 1 components and 1065 entities. + - field 31 {complex: 1, time: 16} with Nodal location, 1 components and 1065 entities. + - field 32 {complex: 0, time: 17} with Nodal location, 1 components and 1065 entities. + - field 33 {complex: 1, time: 17} with Nodal location, 1 components and 1065 entities. + - field 34 {complex: 0, time: 18} with Nodal location, 1 components and 1065 entities. + - field 35 {complex: 1, time: 18} with Nodal location, 1 components and 1065 entities. + - field 36 {complex: 0, time: 19} with Nodal location, 1 components and 1065 entities. + - field 37 {complex: 1, time: 19} with Nodal location, 1 components and 1065 entities. + - field 38 {complex: 0, time: 20} with Nodal location, 1 components and 1065 entities. + - field 39 {complex: 1, time: 20} with Nodal location, 1 components and 1065 entities. + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 3.307 seconds) + + +.. _sphx_glr_download_examples_07-distributed-post_03-distributed-msup_expansion_steps.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 03-distributed-msup_expansion_steps.py <03-distributed-msup_expansion_steps.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 03-distributed-msup_expansion_steps.ipynb <03-distributed-msup_expansion_steps.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps_codeobj.pickle b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps_codeobj.pickle new file mode 100644 index 0000000000..2b34e92597 Binary files /dev/null and b/doc/source/examples/07-distributed-post/03-distributed-msup_expansion_steps_codeobj.pickle differ diff --git a/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.ipynb b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.ipynb new file mode 100644 index 0000000000..5c857b30bf --- /dev/null +++ b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.ipynb @@ -0,0 +1,165 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Average Stress in distributed Workflows {#ref_distributed_stress_averaging}\r\n\r\nThis example shows how stress can be read from distributed files and\r\naveraged from elemental nodal to nodal in parallel with a distributed\r\nworkflow. After remote post-processing, results are merged on the local\r\nprocess.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import dpf module and its examples files\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\nfrom ansys.dpf.core import operators as ops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Configure the servers\r\n\r\nMake a list of ip addresses and port numbers on which dpf servers are\r\nstarted. Workflow instances will be created on each of these servers to\r\naddress each a different result file. In this example, we will post\r\nprocess an analysis distributed in 2 files, we will consequently require\r\n2 remote processes. To make this example easier, we will start local\r\nservers here, but we could get connected to any existing servers on the\r\nnetwork.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "files = examples.download_distributed_files()\n\nconfig = dpf.ServerConfig(protocol=dpf.server.CommunicationProtocols.gRPC)\nremote_servers = [dpf.start_local_server(as_global=False, config=config) for file in files]\nips = [remote_server.ip for remote_server in remote_servers]\nports = [remote_server.port for remote_server in remote_servers]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the ips and ports\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"ips:\", ips)\nprint(\"ports:\", ports)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Distributed Workflow\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "::: graphviz\r\n\r\ndigraph foo {\r\n\r\n: graph \\[pad=\\\"0\\\", nodesep=\\\"0.3\\\", ranksep=\\\"0.3\\\"\\] node\r\n \\[shape=box, style=filled, fillcolor=\\\"#ffcc00\\\", margin=\\\"0\\\"\\];\r\n rankdir=LR; splines=line;\r\n\r\n stress01 \\[label=\\\"stress\\\"\\]; stress02 \\[label=\\\"stress\\\"\\];\r\n average01 \\[label=\\\"elemental_nodal_to_nodal_fc\\\"\\]; average02\r\n \\[label=\\\"elemental_nodal_to_nodal_fc\\\"\\];\r\n\r\n subgraph cluster_1 {\r\n\r\n : ds01 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\]; no_extend_to_mid_nodes01\r\n \\[label=\\\"no_extend_to_mid_nodes\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n ds01 -\\> stress01 \\[style=dashed\\]; no_extend_to_mid_nodes01 -\\>\r\n stress01 \\[style=dashed\\]; stress01 -\\> average01;\r\n\r\n label=\\\"Server 2\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n }\r\n\r\n subgraph cluster_2 {\r\n\r\n : ds02 \\[label=\\\"data_src\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\]; no_extend_to_mid_nodes02\r\n \\[label=\\\"no_extend_to_mid_nodes\\\", shape=box, style=filled,\r\n fillcolor=cadetblue2\\];\r\n\r\n ds02 -\\> stress02 \\[style=dashed\\]; no_extend_to_mid_nodes02 -\\>\r\n stress02 \\[style=dashed\\]; stress02 -\\> average02;\r\n\r\n label=\\\"Server 1\\\"; style=filled; fillcolor=lightgrey;\r\n\r\n } merge_weighted_fields_containers\r\n \\[label=\\\"merge_weighted_fields_containers\\\"\\]; average01 -\\>\r\n merge_weighted_fields_containers; average02 -\\>\r\n merge_weighted_fields_containers; merge_weighted_fields_containers\r\n -\\> extend_to_mid_nodes;\r\n\r\n}\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a local workflow able to merge the results\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "config = ops.utility.merge_weighted_fields_containers.default_config()\nconfig.set_read_inputs_in_parallel_option(True)\nmerge = ops.utility.merge_weighted_fields_containers(config=config)\nextend_to_mid_nodes = ops.averaging.extend_to_mid_nodes_fc(merge)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Send workflows on servers\r\n\r\nHere we create new instances on the server by copies of the template\r\nworkflow We also connect the data sources to those workflows\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "remote_workflows = []\nfor i, server in enumerate(remote_servers):\n ds = dpf.DataSources(files[i], server=server)\n stress = ops.result.stress(server=server)\n stress.inputs.connect(ds)\n average = ops.averaging.elemental_nodal_to_nodal_fc(stress)\n average.inputs.extend_to_mid_nodes(False)\n\n merge.connect(0 + i, average.outputs.fields_container)\n merge.connect(1000 + i, average, 1)\n\nfc = extend_to_mid_nodes.outputs.fields_container()\nfc[0].plot()\nprint(fc)\nprint(fc[0].min().data)\nprint(fc[0].max().data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Compare with non distributed Workflow\r\n\r\nCreate DataSources with Domain id (one domain by distributed file).\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "ds = dpf.DataSources()\nds.set_domain_result_file_path(files[0], 0)\nds.set_domain_result_file_path(files[1], 1)\n\nmodel = dpf.Model(ds)\nstress = model.results.stress()\nfc_single_process = ops.averaging.to_nodal_fc(stress).eval()\n\nfc_single_process[0].plot()\nprint(fc_single_process[0].min().data)\nprint(fc_single_process[0].max().data)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.py b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.py new file mode 100644 index 0000000000..bd9073a590 --- /dev/null +++ b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.py @@ -0,0 +1,142 @@ +""" +.. _ref_distributed_stress_averaging: + +Average Stress in distributed Workflows +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how stress can be read from distributed files and +averaged from elemental nodal to nodal in parallel with a distributed workflow. +After remote post-processing, results are merged on the local process. + +""" + +############################################################################### +# Import dpf module and its examples files + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + + +############################################################################### +# Configure the servers +# ~~~~~~~~~~~~~~~~~~~~~~ +# Make a list of ip addresses and port numbers on which dpf servers are +# started. Workflow instances will be created on each of these servers to +# address each a different result file. +# In this example, we will post process an analysis distributed in 2 files, +# we will consequently require 2 remote processes. +# To make this example easier, we will start local servers here, +# but we could get connected to any existing servers on the network. + +files = examples.download_distributed_files() + +config = dpf.ServerConfig(protocol=dpf.server.CommunicationProtocols.gRPC) +remote_servers = [dpf.start_local_server(as_global=False, config=config) for file in files] +ips = [remote_server.ip for remote_server in remote_servers] +ports = [remote_server.port for remote_server in remote_servers] + +############################################################################### +# Print the ips and ports +print("ips:", ips) +print("ports:", ports) + + +############################################################################### +# Distributed Workflow +# ~~~~~~~~~~~~~~~~~~~~ + +# %% +# .. graphviz:: +# +# digraph foo { +# graph [pad="0", nodesep="0.3", ranksep="0.3"] +# node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; +# rankdir=LR; +# splines=line; +# +# stress01 [label="stress"]; +# stress02 [label="stress"]; +# average01 [label="elemental_nodal_to_nodal_fc"]; +# average02 [label="elemental_nodal_to_nodal_fc"]; +# +# subgraph cluster_1 { +# ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; +# no_extend_to_mid_nodes01 [label="no_extend_to_mid_nodes", +# shape=box, style=filled, fillcolor=cadetblue2]; +# +# ds01 -> stress01 [style=dashed]; +# no_extend_to_mid_nodes01 -> stress01 [style=dashed]; +# stress01 -> average01; +# +# label="Server 2"; +# style=filled; +# fillcolor=lightgrey; +# } +# +# subgraph cluster_2 { +# ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; +# no_extend_to_mid_nodes02 [label="no_extend_to_mid_nodes", +# shape=box, style=filled, fillcolor=cadetblue2]; +# +# ds02 -> stress02 [style=dashed]; +# no_extend_to_mid_nodes02 -> stress02 [style=dashed]; +# stress02 -> average02; +# +# label="Server 1"; +# style=filled; +# fillcolor=lightgrey; +# } +# merge_weighted_fields_containers [label="merge_weighted_fields_containers"]; +# average01 -> merge_weighted_fields_containers; +# average02 -> merge_weighted_fields_containers; +# merge_weighted_fields_containers -> extend_to_mid_nodes; +# +# } + +############################################################################### +# Create a local workflow able to merge the results +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +config = ops.utility.merge_weighted_fields_containers.default_config() +config.set_read_inputs_in_parallel_option(True) +merge = ops.utility.merge_weighted_fields_containers(config=config) +extend_to_mid_nodes = ops.averaging.extend_to_mid_nodes_fc(merge) + +############################################################################### +# Send workflows on servers +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Here we create new instances on the server by copies of the template workflow +# We also connect the data sources to those workflows +remote_workflows = [] +for i, server in enumerate(remote_servers): + ds = dpf.DataSources(files[i], server=server) + stress = ops.result.stress(server=server) + stress.inputs.connect(ds) + average = ops.averaging.elemental_nodal_to_nodal_fc(stress) + average.inputs.extend_to_mid_nodes(False) + + merge.connect(0 + i, average.outputs.fields_container) + merge.connect(1000 + i, average, 1) + +fc = extend_to_mid_nodes.outputs.fields_container() +fc[0].plot() +print(fc) +print(fc[0].min().data) +print(fc[0].max().data) + +############################################################################### +# Compare with non distributed Workflow +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create DataSources with Domain id (one domain by distributed file). + +ds = dpf.DataSources() +ds.set_domain_result_file_path(files[0], 0) +ds.set_domain_result_file_path(files[1], 1) + +model = dpf.Model(ds) +stress = model.results.stress() +fc_single_process = ops.averaging.to_nodal_fc(stress).eval() + +fc_single_process[0].plot() +print(fc_single_process[0].min().data) +print(fc_single_process[0].max().data) diff --git a/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.py.md5 b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.py.md5 new file mode 100644 index 0000000000..88cf08e6a8 --- /dev/null +++ b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.py.md5 @@ -0,0 +1 @@ +4e54323e99c9712d57cfa9e02e8aeac0 \ No newline at end of file diff --git a/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.rst b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.rst new file mode 100644 index 0000000000..0e811945cd --- /dev/null +++ b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging.rst @@ -0,0 +1,308 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\07-distributed-post\06-distributed_stress_averaging.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_07-distributed-post_06-distributed_stress_averaging.py: + + +.. _ref_distributed_stress_averaging: + +Average Stress in distributed Workflows +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how stress can be read from distributed files and +averaged from elemental nodal to nodal in parallel with a distributed workflow. +After remote post-processing, results are merged on the local process. + +.. GENERATED FROM PYTHON SOURCE LINES 14-15 + +Import dpf module and its examples files + +.. GENERATED FROM PYTHON SOURCE LINES 15-21 + +.. code-block:: default + + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + from ansys.dpf.core import operators as ops + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 22-31 + +Configure the servers +~~~~~~~~~~~~~~~~~~~~~~ +Make a list of ip addresses and port numbers on which dpf servers are +started. Workflow instances will be created on each of these servers to +address each a different result file. +In this example, we will post process an analysis distributed in 2 files, +we will consequently require 2 remote processes. +To make this example easier, we will start local servers here, +but we could get connected to any existing servers on the network. + +.. GENERATED FROM PYTHON SOURCE LINES 31-39 + +.. code-block:: default + + + files = examples.download_distributed_files() + + config = dpf.ServerConfig(protocol=dpf.server.CommunicationProtocols.gRPC) + remote_servers = [dpf.start_local_server(as_global=False, config=config) for file in files] + ips = [remote_server.ip for remote_server in remote_servers] + ports = [remote_server.port for remote_server in remote_servers] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 40-41 + +Print the ips and ports + +.. GENERATED FROM PYTHON SOURCE LINES 41-45 + +.. code-block:: default + + print("ips:", ips) + print("ports:", ports) + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + ips: ['127.0.0.1', '127.0.0.1'] + ports: [50055, 50056] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 46-48 + +Distributed Workflow +~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 50-96 + +.. graphviz:: + + digraph foo { + graph [pad="0", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + + stress01 [label="stress"]; + stress02 [label="stress"]; + average01 [label="elemental_nodal_to_nodal_fc"]; + average02 [label="elemental_nodal_to_nodal_fc"]; + + subgraph cluster_1 { + ds01 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + no_extend_to_mid_nodes01 [label="no_extend_to_mid_nodes", + shape=box, style=filled, fillcolor=cadetblue2]; + + ds01 -> stress01 [style=dashed]; + no_extend_to_mid_nodes01 -> stress01 [style=dashed]; + stress01 -> average01; + + label="Server 2"; + style=filled; + fillcolor=lightgrey; + } + + subgraph cluster_2 { + ds02 [label="data_src", shape=box, style=filled, fillcolor=cadetblue2]; + no_extend_to_mid_nodes02 [label="no_extend_to_mid_nodes", + shape=box, style=filled, fillcolor=cadetblue2]; + + ds02 -> stress02 [style=dashed]; + no_extend_to_mid_nodes02 -> stress02 [style=dashed]; + stress02 -> average02; + + label="Server 1"; + style=filled; + fillcolor=lightgrey; + } + merge_weighted_fields_containers [label="merge_weighted_fields_containers"]; + average01 -> merge_weighted_fields_containers; + average02 -> merge_weighted_fields_containers; + merge_weighted_fields_containers -> extend_to_mid_nodes; + + } + +.. GENERATED FROM PYTHON SOURCE LINES 98-100 + +Create a local workflow able to merge the results +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. GENERATED FROM PYTHON SOURCE LINES 100-105 + +.. code-block:: default + + config = ops.utility.merge_weighted_fields_containers.default_config() + config.set_read_inputs_in_parallel_option(True) + merge = ops.utility.merge_weighted_fields_containers(config=config) + extend_to_mid_nodes = ops.averaging.extend_to_mid_nodes_fc(merge) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 106-110 + +Send workflows on servers +~~~~~~~~~~~~~~~~~~~~~~~~~~ +Here we create new instances on the server by copies of the template workflow +We also connect the data sources to those workflows + +.. GENERATED FROM PYTHON SOURCE LINES 110-127 + +.. code-block:: default + + remote_workflows = [] + for i, server in enumerate(remote_servers): + ds = dpf.DataSources(files[i], server=server) + stress = ops.result.stress(server=server) + stress.inputs.connect(ds) + average = ops.averaging.elemental_nodal_to_nodal_fc(stress) + average.inputs.extend_to_mid_nodes(False) + + merge.connect(0 + i, average.outputs.fields_container) + merge.connect(1000 + i, average, 1) + + fc = extend_to_mid_nodes.outputs.fields_container() + fc[0].plot() + print(fc) + print(fc[0].min().data) + print(fc[0].max().data) + + + + +.. image-sg:: /examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_001.png + :alt: 06 distributed stress averaging + :srcset: /examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_001.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + DPF Fields Container + with 1 field(s) + defined on labels: time + + with: + - field 0 {time: 1} with Nodal location, 6 components and 432 entities. + + [-1.56930398e+13 -4.83763348e+13 -1.55875426e+13 -7.69977588e+12 + -5.42547483e+12 -8.39338295e+11] + [1.56930398e+13 4.83763348e+13 1.55875426e+13 1.49730617e+12 + 9.38940668e+12 8.39338295e+11] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 128-131 + +Compare with non distributed Workflow +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create DataSources with Domain id (one domain by distributed file). + +.. GENERATED FROM PYTHON SOURCE LINES 131-143 + +.. code-block:: default + + + ds = dpf.DataSources() + ds.set_domain_result_file_path(files[0], 0) + ds.set_domain_result_file_path(files[1], 1) + + model = dpf.Model(ds) + stress = model.results.stress() + fc_single_process = ops.averaging.to_nodal_fc(stress).eval() + + fc_single_process[0].plot() + print(fc_single_process[0].min().data) + print(fc_single_process[0].max().data) + + + +.. image-sg:: /examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_002.png + :alt: 06 distributed stress averaging + :srcset: /examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_002.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [-1.56930398e+13 -4.83763348e+13 -1.55875426e+13 -7.69977588e+12 + -5.42547483e+12 -8.39338295e+11] + [1.56930398e+13 4.83763348e+13 1.55875426e+13 1.49730617e+12 + 9.38940668e+12 8.39338295e+11] + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 3.109 seconds) + + +.. _sphx_glr_download_examples_07-distributed-post_06-distributed_stress_averaging.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 06-distributed_stress_averaging.py <06-distributed_stress_averaging.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 06-distributed_stress_averaging.ipynb <06-distributed_stress_averaging.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/07-distributed-post/06-distributed_stress_averaging_codeobj.pickle b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging_codeobj.pickle new file mode 100644 index 0000000000..dddddd4a53 Binary files /dev/null and b/doc/source/examples/07-distributed-post/06-distributed_stress_averaging_codeobj.pickle differ diff --git a/doc/source/examples/07-distributed-post/images/sphx_glr_01-distributed_workflows_on_remote_001.png b/doc/source/examples/07-distributed-post/images/sphx_glr_01-distributed_workflows_on_remote_001.png new file mode 100644 index 0000000000..b06218a28e Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/sphx_glr_01-distributed_workflows_on_remote_001.png differ diff --git a/doc/source/examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_001.png b/doc/source/examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_001.png new file mode 100644 index 0000000000..d451f9fbec Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_001.png differ diff --git a/doc/source/examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_002.png b/doc/source/examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_002.png new file mode 100644 index 0000000000..7554302e39 Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/sphx_glr_02-distributed-msup_expansion_002.png differ diff --git a/doc/source/examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_001.png b/doc/source/examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_001.png new file mode 100644 index 0000000000..d451f9fbec Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_001.png differ diff --git a/doc/source/examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_002.png b/doc/source/examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_002.png new file mode 100644 index 0000000000..5f39c83363 Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/sphx_glr_03-distributed-msup_expansion_steps_002.png differ diff --git a/doc/source/examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_001.png b/doc/source/examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_001.png new file mode 100644 index 0000000000..22cb68017c Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_001.png differ diff --git a/doc/source/examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_002.png b/doc/source/examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_002.png new file mode 100644 index 0000000000..4178d43f0d Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/sphx_glr_06-distributed_stress_averaging_002.png differ diff --git a/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_00-distributed_total_disp_thumb.png b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_00-distributed_total_disp_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_00-distributed_total_disp_thumb.png differ diff --git a/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_01-distributed_workflows_on_remote_thumb.png b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_01-distributed_workflows_on_remote_thumb.png new file mode 100644 index 0000000000..3279e2dca5 Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_01-distributed_workflows_on_remote_thumb.png differ diff --git a/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_02-distributed-msup_expansion_thumb.png b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_02-distributed-msup_expansion_thumb.png new file mode 100644 index 0000000000..caa2fa3c7b Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_02-distributed-msup_expansion_thumb.png differ diff --git a/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_03-distributed-msup_expansion_steps_thumb.png b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_03-distributed-msup_expansion_steps_thumb.png new file mode 100644 index 0000000000..caa2fa3c7b Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_03-distributed-msup_expansion_steps_thumb.png differ diff --git a/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_06-distributed_stress_averaging_thumb.png b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_06-distributed_stress_averaging_thumb.png new file mode 100644 index 0000000000..81fe2f2ade Binary files /dev/null and b/doc/source/examples/07-distributed-post/images/thumb/sphx_glr_06-distributed_stress_averaging_thumb.png differ diff --git a/doc/source/examples/07-distributed-post/index.rst b/doc/source/examples/07-distributed-post/index.rst new file mode 100644 index 0000000000..54fc752a1b --- /dev/null +++ b/doc/source/examples/07-distributed-post/index.rst @@ -0,0 +1,117 @@ + + +.. _sphx_glr_examples_07-distributed-post: + +.. _distributed_post: + +Examples for postprocessing on distributed processes +==================================================== +These examples show how to create workflows on different processes (possibly on +different machines) and connect them. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_00-distributed_total_disp_thumb.png + :alt: Postprocessing of displacement on distributed processes + + :ref:`sphx_glr_examples_07-distributed-post_00-distributed_total_disp.py` + +.. raw:: html + +
Postprocessing of displacement on distributed processes
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_01-distributed_workflows_on_remote_thumb.png + :alt: Create a custom workflow on distributed processes + + :ref:`sphx_glr_examples_07-distributed-post_01-distributed_workflows_on_remote.py` + +.. raw:: html + +
Create a custom workflow on distributed processes
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_02-distributed-msup_expansion_thumb.png + :alt: Distributed mode superposition (MSUP) + + :ref:`sphx_glr_examples_07-distributed-post_02-distributed-msup_expansion.py` + +.. raw:: html + +
Distributed mode superposition (MSUP)
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_03-distributed-msup_expansion_steps_thumb.png + :alt: Distributed MSUP distributed modal response + + :ref:`sphx_glr_examples_07-distributed-post_03-distributed-msup_expansion_steps.py` + +.. raw:: html + +
Distributed MSUP distributed modal response
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_06-distributed_stress_averaging_thumb.png + :alt: Average Stress in distributed Workflows + + :ref:`sphx_glr_examples_07-distributed-post_06-distributed_stress_averaging.py` + +.. raw:: html + +
Average Stress in distributed Workflows
+
+ + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /examples/07-distributed-post/00-distributed_total_disp + /examples/07-distributed-post/01-distributed_workflows_on_remote + /examples/07-distributed-post/02-distributed-msup_expansion + /examples/07-distributed-post/03-distributed-msup_expansion_steps + /examples/07-distributed-post/06-distributed_stress_averaging + diff --git a/doc/source/examples/07-distributed-post/sg_execution_times.rst b/doc/source/examples/07-distributed-post/sg_execution_times.rst new file mode 100644 index 0000000000..4428a355b1 --- /dev/null +++ b/doc/source/examples/07-distributed-post/sg_execution_times.rst @@ -0,0 +1,20 @@ + +:orphan: + +.. _sphx_glr_examples_07-distributed-post_sg_execution_times: + +Computation times +================= +**00:17.824** total execution time for **examples_07-distributed-post** files: + ++----------------------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_07-distributed-post_02-distributed-msup_expansion.py` (``02-distributed-msup_expansion.py``) | 00:08.269 | 0.0 MB | ++----------------------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_07-distributed-post_03-distributed-msup_expansion_steps.py` (``03-distributed-msup_expansion_steps.py``) | 00:03.307 | 0.0 MB | ++----------------------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_07-distributed-post_06-distributed_stress_averaging.py` (``06-distributed_stress_averaging.py``) | 00:03.109 | 0.0 MB | ++----------------------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_07-distributed-post_01-distributed_workflows_on_remote.py` (``01-distributed_workflows_on_remote.py``) | 00:01.903 | 0.0 MB | ++----------------------------------------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_examples_07-distributed-post_00-distributed_total_disp.py` (``00-distributed_total_disp.py``) | 00:01.235 | 0.0 MB | ++----------------------------------------------------------------------------------------------------------------------------------+-----------+--------+ diff --git a/docs/source/examples/07-python-operators/plugins/README.txt b/doc/source/examples/07-python-operators/plugins/README.txt similarity index 100% rename from docs/source/examples/07-python-operators/plugins/README.txt rename to doc/source/examples/07-python-operators/plugins/README.txt diff --git a/docs/source/examples/07-python-operators/plugins/average_filter_plugin/__init__.py b/doc/source/examples/07-python-operators/plugins/average_filter_plugin/__init__.py similarity index 100% rename from docs/source/examples/07-python-operators/plugins/average_filter_plugin/__init__.py rename to doc/source/examples/07-python-operators/plugins/average_filter_plugin/__init__.py diff --git a/docs/source/examples/07-python-operators/plugins/average_filter_plugin/common.py b/doc/source/examples/07-python-operators/plugins/average_filter_plugin/common.py similarity index 100% rename from docs/source/examples/07-python-operators/plugins/average_filter_plugin/common.py rename to doc/source/examples/07-python-operators/plugins/average_filter_plugin/common.py diff --git a/docs/source/examples/07-python-operators/plugins/average_filter_plugin/operators.py b/doc/source/examples/07-python-operators/plugins/average_filter_plugin/operators.py similarity index 100% rename from docs/source/examples/07-python-operators/plugins/average_filter_plugin/operators.py rename to doc/source/examples/07-python-operators/plugins/average_filter_plugin/operators.py diff --git a/docs/source/examples/07-python-operators/plugins/average_filter_plugin/operators_loader.py b/doc/source/examples/07-python-operators/plugins/average_filter_plugin/operators_loader.py similarity index 100% rename from docs/source/examples/07-python-operators/plugins/average_filter_plugin/operators_loader.py rename to doc/source/examples/07-python-operators/plugins/average_filter_plugin/operators_loader.py diff --git a/docs/source/examples/07-python-operators/plugins/easy_statistics.py b/doc/source/examples/07-python-operators/plugins/easy_statistics.py similarity index 100% rename from docs/source/examples/07-python-operators/plugins/easy_statistics.py rename to doc/source/examples/07-python-operators/plugins/easy_statistics.py diff --git a/docs/source/examples/07-python-operators/plugins/gltf_plugin.xml b/doc/source/examples/07-python-operators/plugins/gltf_plugin.xml similarity index 100% rename from docs/source/examples/07-python-operators/plugins/gltf_plugin.xml rename to doc/source/examples/07-python-operators/plugins/gltf_plugin.xml diff --git a/docs/source/examples/07-python-operators/plugins/gltf_plugin/__init__.py b/doc/source/examples/07-python-operators/plugins/gltf_plugin/__init__.py similarity index 100% rename from docs/source/examples/07-python-operators/plugins/gltf_plugin/__init__.py rename to doc/source/examples/07-python-operators/plugins/gltf_plugin/__init__.py diff --git a/doc/source/examples/07-python-operators/plugins/gltf_plugin/assets/gltf_sites_winx64.zip b/doc/source/examples/07-python-operators/plugins/gltf_plugin/assets/gltf_sites_winx64.zip new file mode 100644 index 0000000000..83772b3797 Binary files /dev/null and b/doc/source/examples/07-python-operators/plugins/gltf_plugin/assets/gltf_sites_winx64.zip differ diff --git a/docs/source/examples/07-python-operators/plugins/gltf_plugin/gltf_export.py b/doc/source/examples/07-python-operators/plugins/gltf_plugin/gltf_export.py similarity index 100% rename from docs/source/examples/07-python-operators/plugins/gltf_plugin/gltf_export.py rename to doc/source/examples/07-python-operators/plugins/gltf_plugin/gltf_export.py diff --git a/docs/source/examples/07-python-operators/plugins/gltf_plugin/operators.py b/doc/source/examples/07-python-operators/plugins/gltf_plugin/operators.py similarity index 100% rename from docs/source/examples/07-python-operators/plugins/gltf_plugin/operators.py rename to doc/source/examples/07-python-operators/plugins/gltf_plugin/operators.py diff --git a/docs/source/examples/07-python-operators/plugins/gltf_plugin/operators_loader.py b/doc/source/examples/07-python-operators/plugins/gltf_plugin/operators_loader.py similarity index 100% rename from docs/source/examples/07-python-operators/plugins/gltf_plugin/operators_loader.py rename to doc/source/examples/07-python-operators/plugins/gltf_plugin/operators_loader.py diff --git a/docs/source/examples/07-python-operators/plugins/gltf_plugin/requirements.txt b/doc/source/examples/07-python-operators/plugins/gltf_plugin/requirements.txt similarity index 100% rename from docs/source/examples/07-python-operators/plugins/gltf_plugin/requirements.txt rename to doc/source/examples/07-python-operators/plugins/gltf_plugin/requirements.txt diff --git a/docs/source/examples/07-python-operators/plugins/gltf_plugin/texture.png b/doc/source/examples/07-python-operators/plugins/gltf_plugin/texture.png similarity index 100% rename from docs/source/examples/07-python-operators/plugins/gltf_plugin/texture.png rename to doc/source/examples/07-python-operators/plugins/gltf_plugin/texture.png diff --git a/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.ipynb b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.ipynb new file mode 100644 index 0000000000..ef5f3b2e40 --- /dev/null +++ b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.ipynb @@ -0,0 +1,129 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a basic operator plugin {#ref_wrapping_numpy_capabilities}\r\n\r\nThis example shows how to create a basic operator plugin, which is for a\r\nsingle custom operator. This custom operator, `easy_statistics`,\r\ncomputes simple statistics quantities on a scalar field with the help of\r\nthe `numpy` package.\r\n\r\nThe objective of this simple example is to show how routines for DPF can\r\nbe wrapped in Python plugins.\r\n\r\n::: note\r\n::: title\r\nNote\r\n:::\r\n\r\nThis example requires DPF 4.0 (Ansys 2022R2) or above. For more\r\ninformation, see `ref_compatibility`{.interpreted-text role=\"ref\"}.\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create the operator\r\n\r\nCreating a basic operator plugin consists of writing a single Python\r\nscript. An operator implementation derives from the\r\n`ansys.dpf.core.custom_operator.CustomOperatorBase`{.interpreted-text\r\nrole=\"class\"} class and a call to the\r\n:py`ansys.dpf.core.custom_operator.record_operator`{.interpreted-text\r\nrole=\"func\"} method.\r\n\r\nThe `easy_statistics` operator takes a field as an input and returns the\r\nfirst quartile, the median, the third quartile, and the variance. The\r\nPython operator and its recording are available in the\r\n`easy_statistics.py` file.\r\n\r\nDownload and display the Python script.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ansys.dpf.core import examples\nfrom ansys.dpf import core as dpf\n\n\nGITHUB_SOURCE_URL = (\n \"https://github.com/ansys/pydpf-core/\" \"raw/examples/first_python_plugins/python_plugins\"\n)\nEXAMPLE_FILE = GITHUB_SOURCE_URL + \"/easy_statistics.py\"\noperator_file_path = examples.downloads._retrieve_file(\n EXAMPLE_FILE, \"easy_statistics.py\", \"python_plugins\"\n)\n\nwith open(operator_file_path, \"r\") as f:\n for line in f.readlines():\n print(\"\\t\\t\\t\" + line)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Load the plugin\r\n\r\nYou use the :py`ansys.dpf.core.core.load_library`{.interpreted-text\r\nrole=\"func\"} method to load the plugin.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# - The first argument is the path to the directory where the plugin\n# is located.\n# - The second argument is ``py_`` plus the name of the Python script.\n# - The third argument is the name of the function used to record operators.\n#\n\nimport os\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\n\n# Python plugins are not supported in process.\ndpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer)\n\noperator_server_file_path = dpf.upload_file_in_tmp_folder(operator_file_path)\ndpf.load_library(os.path.dirname(operator_server_file_path), \"py_easy_statistics\", \"load_operators\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instantiate the operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "new_operator = dpf.Operator(\"easy_statistics\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Connect a workflow\r\n\r\nConnect a workflow that computes the norm of the displacement to the\r\n`easy_statistics` operator. Methods of the `easy_statistics` class are\r\ndynamically added because specifications for the operator are defined in\r\nthe plugin.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "::: graphviz\r\n\r\ndigraph foo {\r\n\r\n: graph \\[pad=\\\"0.5\\\", nodesep=\\\"0.3\\\", ranksep=\\\"0.3\\\"\\] node\r\n \\[shape=box, style=filled, fillcolor=\\\"#ffcc00\\\", margin=\\\"0\\\"\\];\r\n rankdir=LR; splines=line; ds \\[label=\\\"ds\\\", shape=box,\r\n style=filled, fillcolor=cadetblue2\\]; ds -\\> displacement\r\n \\[style=dashed\\]; displacement -\\> norm; norm -\\> easy_statistics;\r\n\r\n}\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use the operator\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "ds = dpf.DataSources(dpf.upload_file_in_tmp_folder(examples.find_static_rst()))\ndisplacement = dpf.operators.result.displacement(data_sources=ds)\nnorm = dpf.operators.math.norm(displacement)\nnew_operator.inputs.connect(norm)\n\nprint(\"first quartile is\", new_operator.outputs.first_quartile())\nprint(\"median is\", new_operator.outputs.median())\nprint(\"third quartile is\", new_operator.outputs.third_quartile())\nprint(\"variance is\", new_operator.outputs.variance())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.py b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.py new file mode 100644 index 0000000000..8761e0d79b --- /dev/null +++ b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.py @@ -0,0 +1,114 @@ +""" +.. _ref_wrapping_numpy_capabilities: + +Create a basic operator plugin +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to create a basic operator plugin, which is for +a single custom operator. This custom operator, ``easy_statistics``, +computes simple statistics quantities on a scalar field with the help of +the ``numpy`` package. + +The objective of this simple example is to show how routines for DPF can +be wrapped in Python plugins. + +.. note:: + This example requires DPF 4.0 (Ansys 2022R2) or above. + For more information, see :ref:`ref_compatibility`. + +""" + +############################################################################### +# Create the operator +# ------------------- +# Creating a basic operator plugin consists of writing a single Python script. +# An operator implementation derives from the +# :class:`ansys.dpf.core.custom_operator.CustomOperatorBase` class +# and a call to the :py:func:`ansys.dpf.core.custom_operator.record_operator` +# method. +# +# The ``easy_statistics`` operator takes a field as an input and returns +# the first quartile, the median, the third quartile, and the variance. +# The Python operator and its recording are available in the +# ``easy_statistics.py`` file. +# +# Download and display the Python script. + +from ansys.dpf.core import examples +from ansys.dpf import core as dpf + + +GITHUB_SOURCE_URL = ( + "https://github.com/ansys/pydpf-core/" "raw/examples/first_python_plugins/python_plugins" +) +EXAMPLE_FILE = GITHUB_SOURCE_URL + "/easy_statistics.py" +operator_file_path = examples.downloads._retrieve_file( + EXAMPLE_FILE, "easy_statistics.py", "python_plugins" +) + +with open(operator_file_path, "r") as f: + for line in f.readlines(): + print("\t\t\t" + line) + +############################################################################### +# Load the plugin +# --------------- +# You use the :py:func:`ansys.dpf.core.core.load_library` method to load the +# plugin. + +# - The first argument is the path to the directory where the plugin +# is located. +# - The second argument is ``py_`` plus the name of the Python script. +# - The third argument is the name of the function used to record operators. +# + +import os +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +# Python plugins are not supported in process. +dpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer) + +operator_server_file_path = dpf.upload_file_in_tmp_folder(operator_file_path) +dpf.load_library(os.path.dirname(operator_server_file_path), "py_easy_statistics", "load_operators") + +############################################################################### +# Instantiate the operator. + +new_operator = dpf.Operator("easy_statistics") + +############################################################################### +# Connect a workflow +# ------------------ +# Connect a workflow that computes the norm of the displacement to the +# ``easy_statistics`` operator. Methods of the ``easy_statistics`` class +# are dynamically added because specifications for the operator are +# defined in the plugin. + +# %% +# .. graphviz:: +# +# digraph foo { +# graph [pad="0.5", nodesep="0.3", ranksep="0.3"] +# node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; +# rankdir=LR; +# splines=line; +# ds [label="ds", shape=box, style=filled, fillcolor=cadetblue2]; +# ds -> displacement [style=dashed]; +# displacement -> norm; +# norm -> easy_statistics; +# } + +############################################################################### +# Use the operator +# ---------------- + +ds = dpf.DataSources(dpf.upload_file_in_tmp_folder(examples.find_static_rst())) +displacement = dpf.operators.result.displacement(data_sources=ds) +norm = dpf.operators.math.norm(displacement) +new_operator.inputs.connect(norm) + +print("first quartile is", new_operator.outputs.first_quartile()) +print("median is", new_operator.outputs.median()) +print("third quartile is", new_operator.outputs.third_quartile()) +print("variance is", new_operator.outputs.variance()) diff --git a/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.py.md5 b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.py.md5 new file mode 100644 index 0000000000..70a88dcab4 --- /dev/null +++ b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.py.md5 @@ -0,0 +1 @@ +f303e02d9953b78cfe6074ab51893850 \ No newline at end of file diff --git a/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.rst b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.rst new file mode 100644 index 0000000000..70636c5f26 --- /dev/null +++ b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities.rst @@ -0,0 +1,320 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\08-python-operators\00-wrapping_numpy_capabilities.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_08-python-operators_00-wrapping_numpy_capabilities.py: + + +.. _ref_wrapping_numpy_capabilities: + +Create a basic operator plugin +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to create a basic operator plugin, which is for +a single custom operator. This custom operator, ``easy_statistics``, +computes simple statistics quantities on a scalar field with the help of +the ``numpy`` package. + +The objective of this simple example is to show how routines for DPF can +be wrapped in Python plugins. + +.. note:: + This example requires DPF 4.0 (Ansys 2022R2) or above. + For more information, see :ref:`ref_compatibility`. + +.. GENERATED FROM PYTHON SOURCE LINES 22-36 + +Create the operator +------------------- +Creating a basic operator plugin consists of writing a single Python script. +An operator implementation derives from the +:class:`ansys.dpf.core.custom_operator.CustomOperatorBase` class +and a call to the :py:func:`ansys.dpf.core.custom_operator.record_operator` +method. + +The ``easy_statistics`` operator takes a field as an input and returns +the first quartile, the median, the third quartile, and the variance. +The Python operator and its recording are available in the +``easy_statistics.py`` file. + +Download and display the Python script. + +.. GENERATED FROM PYTHON SOURCE LINES 36-53 + +.. code-block:: default + + + from ansys.dpf.core import examples + from ansys.dpf import core as dpf + + + GITHUB_SOURCE_URL = ( + "https://github.com/ansys/pydpf-core/" "raw/examples/first_python_plugins/python_plugins" + ) + EXAMPLE_FILE = GITHUB_SOURCE_URL + "/easy_statistics.py" + operator_file_path = examples.downloads._retrieve_file( + EXAMPLE_FILE, "easy_statistics.py", "python_plugins" + ) + + with open(operator_file_path, "r") as f: + for line in f.readlines(): + print("\t\t\t" + line) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + import numpy as np + + from ansys.dpf import core as dpf + + from ansys.dpf.core.custom_operator import CustomOperatorBase, record_operator + + from ansys.dpf.core.operator_specification import CustomSpecification, SpecificationProperties, \ + + PinSpecification + + + + + + class EasyStatistics(CustomOperatorBase): + + @property + + def name(self): + + return "easy_statistics" + + + + @property + + def specification(self) -> CustomSpecification: + + spec = CustomSpecification() + + spec.description = "Compute the first quartile, the median, the third quartile and the variance of a scalar Field with numpy" + + spec.inputs = {0: PinSpecification("field", [dpf.Field, dpf.FieldsContainer], "scalar Field on which the statistics quantities is computed.")} + + spec.outputs = { + + 0: PinSpecification("first_quartile", [float]), + + 1: PinSpecification("median", [float]), + + 2: PinSpecification("third_quartile", [float]), + + 3: PinSpecification("variance", [float]), + + } + + spec.properties = SpecificationProperties("easy statistics", "math") + + return spec + + + + def run(self): + + field = self.get_input(0, dpf.Field) + + if field is None: + + field = self.get_input(0, dpf.FieldsContainer)[0] + + # compute stats + + first_quartile_val = np.quantile(field.data, 0.25) + + median_val = np.quantile(field.data, 0.5) + + third_quartile_val = np.quantile(field.data, 0.75) + + variance_val = np.var(field.data) + + self.set_output(0, first_quartile_val) + + self.set_output(1, median_val) + + self.set_output(2, third_quartile_val) + + self.set_output(3, float(variance_val)) + + self.set_succeeded() + + + + + + def load_operators(*args): + + record_operator(EasyStatistics, *args) + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 54-58 + +Load the plugin +--------------- +You use the :py:func:`ansys.dpf.core.core.load_library` method to load the +plugin. + +.. GENERATED FROM PYTHON SOURCE LINES 58-75 + +.. code-block:: default + + + # - The first argument is the path to the directory where the plugin + # is located. + # - The second argument is ``py_`` plus the name of the Python script. + # - The third argument is the name of the function used to record operators. + # + + import os + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + # Python plugins are not supported in process. + dpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer) + + operator_server_file_path = dpf.upload_file_in_tmp_folder(operator_file_path) + dpf.load_library(os.path.dirname(operator_server_file_path), "py_easy_statistics", "load_operators") + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + 'py_easy_statistics successfully loaded' + + + +.. GENERATED FROM PYTHON SOURCE LINES 76-77 + +Instantiate the operator. + +.. GENERATED FROM PYTHON SOURCE LINES 77-80 + +.. code-block:: default + + + new_operator = dpf.Operator("easy_statistics") + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 81-87 + +Connect a workflow +------------------ +Connect a workflow that computes the norm of the displacement to the +``easy_statistics`` operator. Methods of the ``easy_statistics`` class +are dynamically added because specifications for the operator are +defined in the plugin. + +.. GENERATED FROM PYTHON SOURCE LINES 89-101 + +.. graphviz:: + + digraph foo { + graph [pad="0.5", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + ds [label="ds", shape=box, style=filled, fillcolor=cadetblue2]; + ds -> displacement [style=dashed]; + displacement -> norm; + norm -> easy_statistics; + } + +.. GENERATED FROM PYTHON SOURCE LINES 103-105 + +Use the operator +---------------- + +.. GENERATED FROM PYTHON SOURCE LINES 105-115 + +.. code-block:: default + + + ds = dpf.DataSources(dpf.upload_file_in_tmp_folder(examples.find_static_rst())) + displacement = dpf.operators.result.displacement(data_sources=ds) + norm = dpf.operators.math.norm(displacement) + new_operator.inputs.connect(norm) + + print("first quartile is", new_operator.outputs.first_quartile()) + print("median is", new_operator.outputs.median()) + print("third quartile is", new_operator.outputs.third_quartile()) + print("variance is", new_operator.outputs.variance()) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + first quartile is 0.0 + median is 7.491665033689507e-09 + third quartile is 1.4276663319275634e-08 + variance is 3.054190175494998e-17 + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 8.672 seconds) + + +.. _sphx_glr_download_examples_08-python-operators_00-wrapping_numpy_capabilities.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 00-wrapping_numpy_capabilities.py <00-wrapping_numpy_capabilities.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 00-wrapping_numpy_capabilities.ipynb <00-wrapping_numpy_capabilities.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities_codeobj.pickle b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities_codeobj.pickle new file mode 100644 index 0000000000..2ac9935a37 Binary files /dev/null and b/doc/source/examples/08-python-operators/00-wrapping_numpy_capabilities_codeobj.pickle differ diff --git a/doc/source/examples/08-python-operators/01-package_python_operators.ipynb b/doc/source/examples/08-python-operators/01-package_python_operators.ipynb new file mode 100644 index 0000000000..614c149a4d --- /dev/null +++ b/doc/source/examples/08-python-operators/01-package_python_operators.ipynb @@ -0,0 +1,129 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a plug-in package with multiple operators {#ref_python_plugin_package}\r\n\r\nThis example shows how to create a plug-in package with multiple\r\noperators. The benefits of writing a package rather than simple scripts\r\nare:\r\n\r\n- **Componentization:** You can split the code into several Python\r\n modules or files.\r\n- **Distribution:** You can use standard Python tools to upload and\r\n download packages.\r\n- **Documentation:** You can add README files, documentation, tests,\r\n and examples to the package.\r\n\r\nFor this example, the plug-in package contains two different operators:\r\n\r\n- One that returns all scoping IDs having data higher than the average\r\n- One that returns all scoping IDs having data lower than the average\r\n\r\n::: note\r\n::: title\r\nNote\r\n:::\r\n\r\nThis example requires DPF 4.0 (Ansys 2022R2) or above. For more\r\ninformation, see `ref_compatibility`{.interpreted-text role=\"ref\"}.\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create the plug-in package\r\n\r\nEach operator implementation derives from the\r\n`ansys.dpf.core.custom_operator.CustomOperatorBase`{.interpreted-text\r\nrole=\"class\"} class and a call to the\r\n:py`ansys.dpf.core.custom_operator.record_operator`{.interpreted-text\r\nrole=\"func\"} method, which records the operators of the plug-in package.\r\n\r\nDownload the `average_filter_plugin` plug-in package that has already\r\nbeen created for you.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\n\nfrom ansys.dpf.core import examples\nfrom ansys.dpf import core as dpf\n\n\nprint(\"\\033[1m average_filter_plugin\")\nfile_list = [\"__init__.py\", \"operators.py\", \"operators_loader.py\", \"common.py\"]\nplugin_folder = None\nGITHUB_SOURCE_URL = (\n \"https://github.com/ansys/pydpf-core/raw/\"\n \"examples/first_python_plugins/python_plugins/average_filter_plugin\"\n)\n\nfor file in file_list:\n EXAMPLE_FILE = GITHUB_SOURCE_URL + \"/average_filter_plugin/\" + file\n operator_file_path = examples.downloads._retrieve_file(\n EXAMPLE_FILE, file, \"python_plugins/average_filter_plugin\"\n )\n plugin_folder = os.path.dirname(operator_file_path)\n print(f\"\\033[1m {file}:\\n \\033[0m\")\n with open(operator_file_path, \"r\") as f:\n for line in f.readlines():\n print(\"\\t\\t\\t\" + line)\n print(\"\\n\\n\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Load the plug-in package\r\n\r\nYou use the function\r\n:py`ansys.dpf.core.core.load_library`{.interpreted-text role=\"func\"} to\r\nload the plug-in package.\r\n\r\n- The first argument is the path to the directory where the plug-in\r\n package is located.\r\n- The second argument is `py_`, where `` is the name\r\n identifying the plug-in package.\r\n- The third argument is the name of the function exposed in the\r\n `__init__` file for the plug-in package that is used to record\r\n operators.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\n\nfrom ansys.dpf import core as dpf\nfrom ansys.dpf.core import examples\n\n# Python plugins are not supported in process.\ndpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer)\n\ntmp = dpf.make_tmp_dir_server()\ndpf.upload_files_in_folder(dpf.path_utilities.join(tmp, \"average_filter_plugin\"), plugin_folder)\ndpf.load_library(\n os.path.join(dpf.path_utilities.join(tmp, \"average_filter_plugin\")),\n \"py_average_filter\",\n \"load_operators\",\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instantiate the operator.\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "new_operator = dpf.Operator(\"ids_with_data_lower_than_average\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Connect a workflow\r\n\r\nConnect a workflow that computes the norm of the displacement to the\r\n`ids_with_data_lower_than_average` operator. Methods of the\r\n`ids_with_data_lower_than_average` class are dynamically added because\r\nspecifications for the operator are defined in the plug-in package.\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "::: graphviz\r\n\r\ndigraph foo {\r\n\r\n: graph \\[pad=\\\"0.5\\\", nodesep=\\\"0.3\\\", ranksep=\\\"0.3\\\"\\] node\r\n \\[shape=box, style=filled, fillcolor=\\\"#ffcc00\\\", margin=\\\"0\\\"\\];\r\n rankdir=LR; splines=line; ds \\[label=\\\"ds\\\", shape=box,\r\n style=filled, fillcolor=cadetblue2\\]; ds -\\> displacement\r\n \\[style=dashed\\]; displacement -\\> norm; norm -\\>\r\n ids_with_data_lower_than_average;\r\n\r\n}\r\n:::\r\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use the operator\r\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "ds = dpf.DataSources(dpf.upload_file_in_tmp_folder(examples.find_static_rst()))\ndisplacement = dpf.operators.result.displacement(data_sources=ds)\nnorm = dpf.operators.math.norm(displacement)\nnew_operator.inputs.connect(norm)\n\n\nnew_scoping = new_operator.outputs.scoping()\nprint(\"scoping in was:\", norm.outputs.field().scoping)\nprint(\"----------------------------------------------\")\nprint(\"scoping out is:\", new_scoping)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/doc/source/examples/08-python-operators/01-package_python_operators.py b/doc/source/examples/08-python-operators/01-package_python_operators.py new file mode 100644 index 0000000000..5150fb39a4 --- /dev/null +++ b/doc/source/examples/08-python-operators/01-package_python_operators.py @@ -0,0 +1,134 @@ +""" +.. _ref_python_plugin_package: + +Create a plug-in package with multiple operators +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to create a plug-in package with multiple operators. +The benefits of writing a package rather than simple scripts are: + +- **Componentization:** You can split the code into several Python modules or files. +- **Distribution:** You can use standard Python tools to upload and download packages. +- **Documentation:** You can add README files, documentation, tests, and examples to the package. + +For this example, the plug-in package contains two different operators: + +- One that returns all scoping IDs having data higher than the average +- One that returns all scoping IDs having data lower than the average + +.. note:: + This example requires DPF 4.0 (Ansys 2022R2) or above. + For more information, see :ref:`ref_compatibility`. + +""" + +############################################################################### +# Create the plug-in package +# -------------------------- +# Each operator implementation derives from the +# :class:`ansys.dpf.core.custom_operator.CustomOperatorBase` class +# and a call to the :py:func:`ansys.dpf.core.custom_operator.record_operator` +# method, which records the operators of the plug-in package. +# +# Download the ``average_filter_plugin`` plug-in package that has already been +# created for you. + +import os + +from ansys.dpf.core import examples +from ansys.dpf import core as dpf + + +print("\033[1m average_filter_plugin") +file_list = ["__init__.py", "operators.py", "operators_loader.py", "common.py"] +plugin_folder = None +GITHUB_SOURCE_URL = ( + "https://github.com/ansys/pydpf-core/raw/" + "examples/first_python_plugins/python_plugins/average_filter_plugin" +) + +for file in file_list: + EXAMPLE_FILE = GITHUB_SOURCE_URL + "/average_filter_plugin/" + file + operator_file_path = examples.downloads._retrieve_file( + EXAMPLE_FILE, file, "python_plugins/average_filter_plugin" + ) + plugin_folder = os.path.dirname(operator_file_path) + print(f"\033[1m {file}:\n \033[0m") + with open(operator_file_path, "r") as f: + for line in f.readlines(): + print("\t\t\t" + line) + print("\n\n") + + +############################################################################### +# Load the plug-in package +# ------------------------ +# You use the function :py:func:`ansys.dpf.core.core.load_library` to load the +# plug-in package. +# +# - The first argument is the path to the directory where the plug-in package +# is located. +# - The second argument is ``py_``, where ```` is the name +# identifying the plug-in package. +# - The third argument is the name of the function exposed in the ``__init__`` file +# for the plug-in package that is used to record operators. +# + +import os + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +# Python plugins are not supported in process. +dpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer) + +tmp = dpf.make_tmp_dir_server() +dpf.upload_files_in_folder(dpf.path_utilities.join(tmp, "average_filter_plugin"), plugin_folder) +dpf.load_library( + os.path.join(dpf.path_utilities.join(tmp, "average_filter_plugin")), + "py_average_filter", + "load_operators", +) + +############################################################################### +# Instantiate the operator. + +new_operator = dpf.Operator("ids_with_data_lower_than_average") + +############################################################################### +# Connect a workflow +# ------------------ +# Connect a workflow that computes the norm of the displacement +# to the ``ids_with_data_lower_than_average`` operator. +# Methods of the ``ids_with_data_lower_than_average`` class are dynamically +# added because specifications for the operator are defined in the plug-in +# package. + +# %% +# .. graphviz:: +# +# digraph foo { +# graph [pad="0.5", nodesep="0.3", ranksep="0.3"] +# node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; +# rankdir=LR; +# splines=line; +# ds [label="ds", shape=box, style=filled, fillcolor=cadetblue2]; +# ds -> displacement [style=dashed]; +# displacement -> norm; +# norm -> ids_with_data_lower_than_average; +# } + +############################################################################### +# Use the operator +# ---------------- + +ds = dpf.DataSources(dpf.upload_file_in_tmp_folder(examples.find_static_rst())) +displacement = dpf.operators.result.displacement(data_sources=ds) +norm = dpf.operators.math.norm(displacement) +new_operator.inputs.connect(norm) + + +new_scoping = new_operator.outputs.scoping() +print("scoping in was:", norm.outputs.field().scoping) +print("----------------------------------------------") +print("scoping out is:", new_scoping) diff --git a/doc/source/examples/08-python-operators/01-package_python_operators.py.md5 b/doc/source/examples/08-python-operators/01-package_python_operators.py.md5 new file mode 100644 index 0000000000..f360ac778e --- /dev/null +++ b/doc/source/examples/08-python-operators/01-package_python_operators.py.md5 @@ -0,0 +1 @@ +2b46d02c8be609a94ced045eccd8a313 \ No newline at end of file diff --git a/doc/source/examples/08-python-operators/01-package_python_operators.rst b/doc/source/examples/08-python-operators/01-package_python_operators.rst new file mode 100644 index 0000000000..9c99a5d915 --- /dev/null +++ b/doc/source/examples/08-python-operators/01-package_python_operators.rst @@ -0,0 +1,438 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "examples\08-python-operators\01-package_python_operators.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_examples_08-python-operators_01-package_python_operators.py: + + +.. _ref_python_plugin_package: + +Create a plug-in package with multiple operators +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to create a plug-in package with multiple operators. +The benefits of writing a package rather than simple scripts are: + +- **Componentization:** You can split the code into several Python modules or files. +- **Distribution:** You can use standard Python tools to upload and download packages. +- **Documentation:** You can add README files, documentation, tests, and examples to the package. + +For this example, the plug-in package contains two different operators: + +- One that returns all scoping IDs having data higher than the average +- One that returns all scoping IDs having data lower than the average + +.. note:: + This example requires DPF 4.0 (Ansys 2022R2) or above. + For more information, see :ref:`ref_compatibility`. + +.. GENERATED FROM PYTHON SOURCE LINES 26-35 + +Create the plug-in package +-------------------------- +Each operator implementation derives from the +:class:`ansys.dpf.core.custom_operator.CustomOperatorBase` class +and a call to the :py:func:`ansys.dpf.core.custom_operator.record_operator` +method, which records the operators of the plug-in package. + +Download the ``average_filter_plugin`` plug-in package that has already been +created for you. + +.. GENERATED FROM PYTHON SOURCE LINES 35-63 + +.. code-block:: default + + + import os + + from ansys.dpf.core import examples + from ansys.dpf import core as dpf + + + print("\033[1m average_filter_plugin") + file_list = ["__init__.py", "operators.py", "operators_loader.py", "common.py"] + plugin_folder = None + GITHUB_SOURCE_URL = ( + "https://github.com/ansys/pydpf-core/raw/" + "examples/first_python_plugins/python_plugins/average_filter_plugin" + ) + + for file in file_list: + EXAMPLE_FILE = GITHUB_SOURCE_URL + "/average_filter_plugin/" + file + operator_file_path = examples.downloads._retrieve_file( + EXAMPLE_FILE, file, "python_plugins/average_filter_plugin" + ) + plugin_folder = os.path.dirname(operator_file_path) + print(f"\033[1m {file}:\n \033[0m") + with open(operator_file_path, "r") as f: + for line in f.readlines(): + print("\t\t\t" + line) + print("\n\n") + + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + average_filter_plugin + __init__.py: + + from average_filter_plugin.operators_loader import load_operators + + + + + operators.py: + + from ansys.dpf.core.custom_operator import CustomOperatorBase + + from ansys.dpf.core.operator_specification import CustomSpecification, PinSpecification, SpecificationProperties + + from ansys.dpf import core as dpf + + from average_filter_plugin import common + + + + + + class IdsWithDataHigherThanAverage(CustomOperatorBase): + + def run(self): + + field = self.get_input(0, dpf.Field) + + average = common.compute_average_of_field(field) + + ids_in = field.scoping.ids + + data_in = field.data + + out = [] + + for i, d in enumerate(data_in): + + if d >= average: + + out.append(ids_in[i]) + + scoping_out = dpf.Scoping(ids=out, location=field.scoping.location) + + self.set_output(0, scoping_out) + + self.set_succeeded() + + + + @property + + def specification(self): + + spec = CustomSpecification("Creates a scoping with all the ids having data higher or equal " + + "to the average value of the scalar field's data in input.") + + spec.inputs = { + + 0: PinSpecification("field", type_names=dpf.Field, document="scalar Field."), + + } + + spec.outputs = { + + 0: PinSpecification("scoping", type_names=dpf.Scoping), + + } + + spec.properties = SpecificationProperties(user_name="ids with data higher than average", category="logic") + + return spec + + + + @property + + def name(self): + + return "ids_with_data_higher_than_average" + + + + + + class IdsWithDataLowerThanAverage(CustomOperatorBase): + + def run(self): + + field = self.get_input(0, dpf.Field) + + average = common.compute_average_of_field(field) + + ids_in = field.scoping.ids + + data_in = field.data + + out = [] + + for i, d in enumerate(data_in): + + if d <= average: + + out.append(ids_in[i]) + + scoping_out = dpf.Scoping(ids=out, location=field.scoping.location) + + self.set_output(0, scoping_out) + + self.set_succeeded() + + + + @property + + def specification(self): + + spec = CustomSpecification("Creates a scoping with all the ids having data lower or equal " + + "to the average value of the scalar field's data in input.") + + spec.inputs = { + + 0: PinSpecification("field", type_names=dpf.Field, document="scalar Field."), + + } + + spec.outputs = { + + 0: PinSpecification("scoping", type_names=dpf.Scoping), + + } + + spec.properties = SpecificationProperties(user_name="ids with data lower than average", category="logic") + + return spec + + + + @property + + def name(self): + + return "ids_with_data_lower_than_average" + + + + + operators_loader.py: + + from average_filter_plugin import operators + + from ansys.dpf.core.custom_operator import record_operator + + + + + + def load_operators(*args): + + record_operator(operators.IdsWithDataHigherThanAverage, *args) + + record_operator(operators.IdsWithDataLowerThanAverage, *args) + + + + + common.py: + + import numpy + + + + + + def compute_average_of_field(field): + + return numpy.average(field.data) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 64-76 + +Load the plug-in package +------------------------ +You use the function :py:func:`ansys.dpf.core.core.load_library` to load the +plug-in package. + +- The first argument is the path to the directory where the plug-in package + is located. +- The second argument is ``py_``, where ```` is the name + identifying the plug-in package. +- The third argument is the name of the function exposed in the ``__init__`` file + for the plug-in package that is used to record operators. + + +.. GENERATED FROM PYTHON SOURCE LINES 76-93 + +.. code-block:: default + + + import os + + from ansys.dpf import core as dpf + from ansys.dpf.core import examples + + # Python plugins are not supported in process. + dpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer) + + tmp = dpf.make_tmp_dir_server() + dpf.upload_files_in_folder(dpf.path_utilities.join(tmp, "average_filter_plugin"), plugin_folder) + dpf.load_library( + os.path.join(dpf.path_utilities.join(tmp, "average_filter_plugin")), + "py_average_filter", + "load_operators", + ) + + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + 'py_average_filter successfully loaded' + + + +.. GENERATED FROM PYTHON SOURCE LINES 94-95 + +Instantiate the operator. + +.. GENERATED FROM PYTHON SOURCE LINES 95-98 + +.. code-block:: default + + + new_operator = dpf.Operator("ids_with_data_lower_than_average") + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 99-106 + +Connect a workflow +------------------ +Connect a workflow that computes the norm of the displacement +to the ``ids_with_data_lower_than_average`` operator. +Methods of the ``ids_with_data_lower_than_average`` class are dynamically +added because specifications for the operator are defined in the plug-in +package. + +.. GENERATED FROM PYTHON SOURCE LINES 108-120 + +.. graphviz:: + + digraph foo { + graph [pad="0.5", nodesep="0.3", ranksep="0.3"] + node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; + rankdir=LR; + splines=line; + ds [label="ds", shape=box, style=filled, fillcolor=cadetblue2]; + ds -> displacement [style=dashed]; + displacement -> norm; + norm -> ids_with_data_lower_than_average; + } + +.. GENERATED FROM PYTHON SOURCE LINES 122-124 + +Use the operator +---------------- + +.. GENERATED FROM PYTHON SOURCE LINES 124-135 + +.. code-block:: default + + + ds = dpf.DataSources(dpf.upload_file_in_tmp_folder(examples.find_static_rst())) + displacement = dpf.operators.result.displacement(data_sources=ds) + norm = dpf.operators.math.norm(displacement) + new_operator.inputs.connect(norm) + + + new_scoping = new_operator.outputs.scoping() + print("scoping in was:", norm.outputs.field().scoping) + print("----------------------------------------------") + print("scoping out is:", new_scoping) + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + scoping in was: DPF Scoping: + with Nodal location and 81 entities + + ---------------------------------------------- + scoping out is: DPF Scoping: + with Nodal location and 35 entities + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 7.268 seconds) + + +.. _sphx_glr_download_examples_08-python-operators_01-package_python_operators.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: 01-package_python_operators.py <01-package_python_operators.py>` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: 01-package_python_operators.ipynb <01-package_python_operators.ipynb>` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/doc/source/examples/08-python-operators/01-package_python_operators_codeobj.pickle b/doc/source/examples/08-python-operators/01-package_python_operators_codeobj.pickle new file mode 100644 index 0000000000..20b1b0cb66 Binary files /dev/null and b/doc/source/examples/08-python-operators/01-package_python_operators_codeobj.pickle differ diff --git a/doc/source/examples/08-python-operators/02-python_operators_with_dependencies.py b/doc/source/examples/08-python-operators/02-python_operators_with_dependencies.py new file mode 100644 index 0000000000..1c72c0a098 --- /dev/null +++ b/doc/source/examples/08-python-operators/02-python_operators_with_dependencies.py @@ -0,0 +1,267 @@ +# noqa: D400 +""" +.. _ref_python_operators_with_deps: + +Create a plug-in package that has third-party dependencies +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to create a Python plug-in package with +third-party dependencies. You should be familiar with these +examples before proceeding with this more advanced one: + +- :ref:`ref_wrapping_numpy_capabilities` +- :ref:`ref_python_plugin_package` + +This plug-in contains an operator whose implementation depends on a +third-party Python module named `gltf `_. +This operator takes a path, a mesh, and a 3D vector field as inputs +and then exports the mesh and the norm of the 3D vector field to a GLTF +file at the given path. + +.. note:: + This example requires DPF 4.0 (Ansys 2022R2) or above. + For more information, see :ref:`ref_compatibility`. + +""" + +############################################################################### +# Create the plug-in package +# -------------------------- +# Each operator implementation derives from the +# :class:`ansys.dpf.core.custom_operator.CustomOperatorBase` class +# and a call to the :py:func:`ansys.dpf.core.custom_operator.record_operator` +# method, which records the operators of the plug-in package. +# +# Download the ``gltf_plugin`` plug-in package that has already been +# created for you. + +import os + +from ansys.dpf.core import examples +from ansys.dpf import core as dpf + + +print("\033[1m gltf_plugin") +file_list = [ + "gltf_plugin/__init__.py", + "gltf_plugin/operators.py", + "gltf_plugin/operators_loader.py", + "gltf_plugin/requirements.txt", + "gltf_plugin/gltf_export.py", + "gltf_plugin/texture.png", + "gltf_plugin.xml", +] +import os + +folder_root = os.path.join(os.getcwd().rsplit("pydpf-core", 1)[0], "pydpf-core") +source_path_in_repo = r"doc\source\examples\07-python-operators\plugins" +operator_folder = os.path.join(folder_root, source_path_in_repo) +print(operator_folder) +plugin_path = None + +for file in file_list: + operator_file_path = os.path.join(operator_folder, file) + + print(f"\033[1m {file}\n \033[0m") + if ( + os.path.splitext(file)[1] == ".py" or os.path.splitext(file)[1] == ".xml" + ) and file != "gltf_plugin/gltf_export.py": + with open(operator_file_path, "r") as f: + for line in f.readlines(): + print("\t\t\t" + line) + print("\n\n") + if plugin_path is None: + plugin_path = os.path.dirname(operator_file_path) + +# %% +# To add third-party modules as dependencies to a plug-in package, you must +# create and reference a folder or ZIP file with the sites of the dependencies +# in an XML file located next to the folder for the plug-in package. The XML +# file must have the same name as the plug-in package plus an ``.xml`` extension. +# +# When the :py:func:`ansys.dpf.core.core.load_library` method is called, +# DPF-Core uses the ``site`` Python module to add custom to the path +# for the Python interpreter. +# +# To create these custom sites, requirements of the plug-in package should be +# installed in a Python virtual environment, the site-packages +# (with unnecessary folders removed) should be compressed to a ZIP file and +# placed with the plugin. The path to this ZIP file should be referenced in +# the XML as shown in the preceding code. +# +# To simplify this step, you can add a requirements file in the plug-in package: +# +print("\033[1m gltf_plugin/requirements.txt: \n \033[0m") +with open(os.path.join(plugin_path, "requirements.txt"), "r") as f: + for line in f.readlines(): + print("\t\t\t" + line) + + +# %% +# Download the script for your operating system. +# +# - For Windows, download this +# :download:`PowerShell script `. +# - For Linux, download this +# :download:`Shell script `. +# +# Run the downloaded script with the mandatory arguments: +# +# - ``-pluginpath``: Path to the folder with the plug-in package. +# - ``-zippath``: Path and name for the ZIP file. +# +# Optional arguments are: +# +# - ``-pythonexe``: Path to a Python executable of your choice. +# - ``-tempfolder``: Path to a temporary folder to work in. The default is the environment variable +# ``TEMP`` on Windows and ``/tmp/`` on Linux. +# +# Run the command for your operating system. +# +# - From Windows PowerShell, run:: +# +# create_sites_for_python_operators.ps1 -pluginpath /path/to/plugin -zippath /path/to/plugin/assets/winx64.zip # noqa: E501 +# +# - From Linux Shell, run:: +# +# create_sites_for_python_operators.sh -pluginpath /path/to/plugin -zippath /path/to/plugin/assets/linx64.zip # noqa: E501 + + +if os.name == "nt" and not os.path.exists( + os.path.join(plugin_path, "assets", "gltf_sites_winx64.zip") +): + cmd_file = os.path.join( + folder_root, + "doc", + "source", + "user_guide", + "create_sites_for_python_operators.ps1", + ) + args = [ + "powershell", + cmd_file, + "-pluginpath", + plugin_path, + "-zippath", + os.path.join(plugin_path, "assets", "gltf_sites_winx64.zip"), + ] + print(args) + import subprocess + + process = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if process.stderr: + raise RuntimeError( + "Installing pygltf in a virtual environment failed with error:\n" + + f"return code = {process.returncode}\n" + + process.stderr.decode() + + "\n\n and log:\n" + + process.stdout.decode() + ) + else: + print("Installing pygltf in a virtual environment succeeded") +elif os.name == "posix" and not os.path.exists( + os.path.join(plugin_path, "assets", "gltf_sites_linx64.zip") +): + cmd_file = os.path.join( + folder_root, + "doc", + "source", + "user_guide", + "create_sites_for_python_operators.sh", + ) + run_cmd = f"{cmd_file}" + args = ( + f' -pluginpath "{plugin_path}" ' + f"-zippath \"{os.path.join(plugin_path, 'assets', 'gltf_sites_linx64.zip')}\"" + ) + print(run_cmd + args) + os.system(f"chmod u=rwx,o=x {cmd_file}") + os.system(run_cmd + args) + print("\nInstalling pygltf in a virtual environment succeeded") + +############################################################################### +# Load the plug-in package +# ------------------------ +# You use the function :py:func:`ansys.dpf.core.core.load_library` to load the +# plug-in package. +# +# - The first argument is the path to the directory where the plug-in package +# is located. +# - The second argument is ``py_``, where ```` is the name +# identifying the plug-in package. +# - The third argument is the name of the function exposed in the ``__init__`` file +# for the plug-in package that is used to record operators. + +from ansys.dpf import core as dpf +from ansys.dpf.core import examples + +# Python plugins are not supported in process. +dpf.start_local_server(config=dpf.AvailableServerConfigs.GrpcServer) + +tmp = dpf.make_tmp_dir_server() +dpf.upload_files_in_folder(dpf.path_utilities.join(tmp, "plugins", "gltf_plugin"), plugin_path) +dpf.upload_file(plugin_path + ".xml", dpf.path_utilities.join(tmp, "plugins", "gltf_plugin.xml")) + +dpf.load_library( + dpf.path_utilities.join(tmp, "plugins", "gltf_plugin"), + "py_dpf_gltf", + "load_operators", +) + +############################################################################### +# Instantiate the operator. + +new_operator = dpf.Operator("gltf_export") + +############################################################################### +# This new ``gltf_export`` operator requires the following as inputs: a triangle +# surface mesh, a displacement field on this surface mesh, and a path to export +# the GLTF file to. +# +# To demonstrate this new operator, a :class:`ansys.dpf.core.model.Model` class +# is created on a simple file and the +# :class:`ansys.dpf.core.operators.mesh.tri_mesh_skin` operator is used +# to extract the surface of the mesh in triangle elements. + +# %% +# .. graphviz:: +# +# digraph workflow { +# graph [pad="0.5", nodesep="0.3", ranksep="0.3"] +# node [shape=box, style=filled, fillcolor="#ffcc00", margin="0"]; +# rankdir=LR; +# splines=line; +# ds [label="data_sources", shape=box, style=filled, fillcolor=cadetblue2]; +# ds -> mesh_provider [style=dashed]; +# mesh_provider -> skin_mesh [splines=ortho]; +# ds -> displacement [style=dashed]; +# skin_mesh -> displacement [splines=ortho]; +# skin_mesh -> gltf_export [splines=ortho]; +# displacement -> gltf_export [splines=ortho]; +# } + +############################################################################### +# Use the custom operator +# ----------------------- + +import os + +model = dpf.Model(dpf.upload_file_in_tmp_folder(examples.find_static_rst())) + +mesh = model.metadata.meshed_region +skin_mesh = dpf.operators.mesh.tri_mesh_skin(mesh=mesh) + +displacement = model.results.displacement() +displacement.inputs.mesh_scoping(skin_mesh) +displacement.inputs.mesh(skin_mesh) +new_operator.inputs.path(os.path.join(tmp, "out")) +new_operator.inputs.mesh(skin_mesh) +new_operator.inputs.field(displacement.outputs.fields_container()[0]) +new_operator.run() + +print("operator ran successfully") + +dpf.download_file(os.path.join(tmp, "out.glb"), os.path.join(os.getcwd(), "out.glb")) + +# %% +# You can download :download:`output ` from the ``gltf`` operator. diff --git a/doc/source/examples/08-python-operators/images/thumb/sphx_glr_00-wrapping_numpy_capabilities_thumb.png b/doc/source/examples/08-python-operators/images/thumb/sphx_glr_00-wrapping_numpy_capabilities_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/08-python-operators/images/thumb/sphx_glr_00-wrapping_numpy_capabilities_thumb.png differ diff --git a/doc/source/examples/08-python-operators/images/thumb/sphx_glr_01-package_python_operators_thumb.png b/doc/source/examples/08-python-operators/images/thumb/sphx_glr_01-package_python_operators_thumb.png new file mode 100644 index 0000000000..8a5fed589d Binary files /dev/null and b/doc/source/examples/08-python-operators/images/thumb/sphx_glr_01-package_python_operators_thumb.png differ diff --git a/docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_001.png b/doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_001.png similarity index 100% rename from docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_001.png rename to doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_001.png diff --git a/docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_002.png b/doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_002.png similarity index 100% rename from docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_002.png rename to doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_002.png diff --git a/docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_003.png b/doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_003.png similarity index 100% rename from docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_003.png rename to doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_003.png diff --git a/docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_004.png b/doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_004.png similarity index 100% rename from docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_004.png rename to doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_004.png diff --git a/docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_005.png b/doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_005.png similarity index 100% rename from docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_005.png rename to doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_005.png diff --git a/docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_006.png b/doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_006.png similarity index 100% rename from docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_006.png rename to doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_006.png diff --git a/docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_007.png b/doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_007.png similarity index 100% rename from docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_007.png rename to doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_007.png diff --git a/docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_thumb.png b/doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_thumb.png similarity index 100% rename from docs/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_thumb.png rename to doc/source/examples/12-fluids/02-fluids_results/sphx_glr_02-fluids_results_thumb.png diff --git a/doc/source/examples/index.rst.new b/doc/source/examples/index.rst.new new file mode 100644 index 0000000000..5d00e01770 --- /dev/null +++ b/doc/source/examples/index.rst.new @@ -0,0 +1,968 @@ +:orphan: + +.. _gallery: + +======== +Examples +======== +These examples demonstrate the behavior and usage of DPF-Core. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ + +Basic DPF examples +================== +These examples explain the basic concepts of DPF. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_00-basic_example_thumb.png + :alt: Basic DPF-Core usage + + :ref:`sphx_glr_examples_00-basic_00-basic_example.py` + +.. raw:: html + +
Basic DPF-Core usage
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_01-basic_operators_thumb.png + :alt: Operators overview + + :ref:`sphx_glr_examples_00-basic_01-basic_operators.py` + +.. raw:: html + +
Operators overview
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_02-basic_field_containers_thumb.png + :alt: Field and field containers overview + + :ref:`sphx_glr_examples_00-basic_02-basic_field_containers.py` + +.. raw:: html + +
Field and field containers overview
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_03-create_entities_thumb.png + :alt: Create your own entities using DPF operators + + :ref:`sphx_glr_examples_00-basic_03-create_entities.py` + +.. raw:: html + +
Create your own entities using DPF operators
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_05-use_local_data_thumb.png + :alt: Bring a field's data locally to improve performance + + :ref:`sphx_glr_examples_00-basic_05-use_local_data.py` + +.. raw:: html + +
Bring a field's data locally to improve performance
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_07-use_result_helpers_thumb.png + :alt: Use result helpers to load custom data + + :ref:`sphx_glr_examples_00-basic_07-use_result_helpers.py` + +.. raw:: html + +
Use result helpers to load custom data
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_08-results_over_time_subset_thumb.png + :alt: Scope results over custom time domains + + :ref:`sphx_glr_examples_00-basic_08-results_over_time_subset.py` + +.. raw:: html + +
Scope results over custom time domains
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_09-results_over_space_subset_thumb.png + :alt: Scope results over custom space domains + + :ref:`sphx_glr_examples_00-basic_09-results_over_space_subset.py` + +.. raw:: html + +
Scope results over custom space domains
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_10-math_operations_thumb.png + :alt: Mathematical Operations + + :ref:`sphx_glr_examples_00-basic_10-math_operations.py` + +.. raw:: html + +
Mathematical Operations
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_11-server_types_thumb.png + :alt: Communicate in process or via gRPC + + :ref:`sphx_glr_examples_00-basic_11-server_types.py` + +.. raw:: html + +
Communicate in process or via gRPC
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/00-basic/images/thumb/sphx_glr_12-get_material_properties_thumb.png + :alt: Get material properties from the result file + + :ref:`sphx_glr_examples_00-basic_12-get_material_properties.py` + +.. raw:: html + +
Get material properties from the result file
+
+ + +.. raw:: html + +
+ + +Transient analysis examples +=========================== +These examples show how to use DPF to extract and plot displacements, +stresses, and strains for a transient result. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/01-transient_analyses/images/thumb/sphx_glr_00-basic_transient_thumb.png + :alt: Transient analysis result example + + :ref:`sphx_glr_examples_01-transient_analyses_00-basic_transient.py` + +.. raw:: html + +
Transient analysis result example
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/01-transient_analyses/images/thumb/sphx_glr_01-transient_easy_time_scoping_thumb.png + :alt: Choose a time scoping for a transient analysis + + :ref:`sphx_glr_examples_01-transient_analyses_01-transient_easy_time_scoping.py` + +.. raw:: html + +
Choose a time scoping for a transient analysis
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/01-transient_analyses/images/thumb/sphx_glr_02-lsdyna_operators_thumb.png + :alt: Results extraction and analysis from LS-DYNA sources + + :ref:`sphx_glr_examples_01-transient_analyses_02-lsdyna_operators.py` + +.. raw:: html + +
Results extraction and analysis from LS-DYNA sources
+
+ + +.. raw:: html + +
+ + +Modal analysis examples +======================= +These examples show how to use DPF to extract and manipulate +results from modal analyses. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/02-modal_analyses/images/thumb/sphx_glr_00-compare_modes_thumb.png + :alt: Use Result Helpers to compare mode shapes for solids and then shells + + :ref:`sphx_glr_examples_02-modal_analyses_00-compare_modes.py` + +.. raw:: html + +
Use Result Helpers to compare mode shapes for solids and then shells
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/02-modal_analyses/images/thumb/sphx_glr_01-plot_and_animate_modes_thumb.png + :alt: Plot and animate mode shapes with DPF + + :ref:`sphx_glr_examples_02-modal_analyses_01-plot_and_animate_modes.py` + +.. raw:: html + +
Plot and animate mode shapes with DPF
+
+ + +.. raw:: html + +
+ + +Harmonic analysis examples +=========================== +These examples show how to use DPF to extract and manipulate +results from harmonic analyses. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/03-harmonic_analyses/images/thumb/sphx_glr_00-multi_harmonic_thumb.png + :alt: Multi-harmonic response example + + :ref:`sphx_glr_examples_03-harmonic_analyses_00-multi_harmonic.py` + +.. raw:: html + +
Multi-harmonic response example
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/03-harmonic_analyses/images/thumb/sphx_glr_01-modal_superposition_thumb.png + :alt: Expand harmonic modal superposition with DPF + + :ref:`sphx_glr_examples_03-harmonic_analyses_01-modal_superposition.py` + +.. raw:: html + +
Expand harmonic modal superposition with DPF
+
+ + +.. raw:: html + +
+ + +Advanced and miscellaneous examples +=================================== +These examples show advanced use cases to demonstrate the high level of workflow customization. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_00-multistage_advanced_options_thumb.png + :alt: Multi-stage cyclic symmetry using advanced customization + + :ref:`sphx_glr_examples_04-advanced_00-multistage_advanced_options.py` + +.. raw:: html + +
Multi-stage cyclic symmetry using advanced customization
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_01-solve_harmonic_problem_thumb.png + :alt: Solve harmonic problem (with damping) using matrix inverse + + :ref:`sphx_glr_examples_04-advanced_01-solve_harmonic_problem.py` + +.. raw:: html + +
Solve harmonic problem (with damping) using matrix inverse
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_02-volume_averaged_stress_thumb.png + :alt: Average elemental stress on a given volume + + :ref:`sphx_glr_examples_04-advanced_02-volume_averaged_stress.py` + +.. raw:: html + +
Average elemental stress on a given volume
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_03-exchange_data_between_servers_thumb.png + :alt: Exchange data between servers + + :ref:`sphx_glr_examples_04-advanced_03-exchange_data_between_servers.py` + +.. raw:: html + +
Exchange data between servers
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_04-extrapolation_stress_3d_thumb.png + :alt: Extrapolation method for stress result of a 3D element + + :ref:`sphx_glr_examples_04-advanced_04-extrapolation_stress_3d.py` + +.. raw:: html + +
Extrapolation method for stress result of a 3D element
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_05-extrapolation_strain_2d_thumb.png + :alt: Extrapolation method for strain result of a 2D element + + :ref:`sphx_glr_examples_04-advanced_05-extrapolation_strain_2d.py` + +.. raw:: html + +
Extrapolation method for strain result of a 2D element
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_06-stress_gradient_path_thumb.png + :alt: Stress gradient normal to a defined node + + :ref:`sphx_glr_examples_04-advanced_06-stress_gradient_path.py` + +.. raw:: html + +
Stress gradient normal to a defined node
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_07-load_plugin_thumb.png + :alt: Load plugin + + :ref:`sphx_glr_examples_04-advanced_07-load_plugin.py` + +.. raw:: html + +
Load plugin
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_10-asme_secviii_divtwo_thumb.png + :alt: Pressure vessel analysis according to an ASME standard + + :ref:`sphx_glr_examples_04-advanced_10-asme_secviii_divtwo.py` + +.. raw:: html + +
Pressure vessel analysis according to an ASME standard
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_11-cycles_to_failure_thumb.png + :alt: Calculate the number of cycles to fatigue failure + + :ref:`sphx_glr_examples_04-advanced_11-cycles_to_failure.py` + +.. raw:: html + +
Calculate the number of cycles to fatigue failure
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_12-read_distributed_files_thumb.png + :alt: Read results from distributed files + + :ref:`sphx_glr_examples_04-advanced_12-read_distributed_files.py` + +.. raw:: html + +
Read results from distributed files
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_13-manage_licensing_thumb.png + :alt: Manage the DPF licensing logic using the server context + + :ref:`sphx_glr_examples_04-advanced_13-manage_licensing.py` + +.. raw:: html + +
Manage the DPF licensing logic using the server context
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/04-advanced/images/thumb/sphx_glr_14-incremental_evaluation_thumb.png + :alt: Use incremental evaluation helper + + :ref:`sphx_glr_examples_04-advanced_14-incremental_evaluation.py` + +.. raw:: html + +
Use incremental evaluation helper
+
+ + +.. raw:: html + +
+ + +File manipulation and input-output examples +=========================================== +These examples show how to manipulate files, +as well as importing or exporting from or to specific formats. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/05-file-IO/images/thumb/sphx_glr_00-hdf5_double_float_comparison_thumb.png + :alt: HDF5 export and compare precision + + :ref:`sphx_glr_examples_05-file-IO_00-hdf5_double_float_comparison.py` + +.. raw:: html + +
HDF5 export and compare precision
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/05-file-IO/images/thumb/sphx_glr_01-reduced_matrices_export_thumb.png + :alt: Get reduced matrices and make export + + :ref:`sphx_glr_examples_05-file-IO_01-reduced_matrices_export.py` + +.. raw:: html + +
Get reduced matrices and make export
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/05-file-IO/images/thumb/sphx_glr_02-hdf5_serialize_and_read_thumb.png + :alt: HDF5 export and import operations + + :ref:`sphx_glr_examples_05-file-IO_02-hdf5_serialize_and_read.py` + +.. raw:: html + +
HDF5 export and import operations
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/05-file-IO/images/thumb/sphx_glr_04-basic-load-file_thumb.png + :alt: Working with a result file + + :ref:`sphx_glr_examples_05-file-IO_04-basic-load-file.py` + +.. raw:: html + +
Working with a result file
+
+ + +.. raw:: html + +
+ + +Plotting examples +================= +These examples show how to use the :class:`ansys.dpf.core.plotter.DpfPlotter` class. + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_00-basic_plotting_thumb.png + :alt: Review of available plotting commands + + :ref:`sphx_glr_examples_06-plotting_00-basic_plotting.py` + +.. raw:: html + +
Review of available plotting commands
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_01-compare_results_thumb.png + :alt: Compare results using the plotter + + :ref:`sphx_glr_examples_06-plotting_01-compare_results.py` + +.. raw:: html + +
Compare results using the plotter
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_02-solution_combination_thumb.png + :alt: Load case combination for principal stress + + :ref:`sphx_glr_examples_06-plotting_02-solution_combination.py` + +.. raw:: html + +
Load case combination for principal stress
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_03-labels_thumb.png + :alt: Add nodal labels on plots + + :ref:`sphx_glr_examples_06-plotting_03-labels.py` + +.. raw:: html + +
Add nodal labels on plots
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_04-plot_on_path_thumb.png + :alt: Plot results on a specific path + + :ref:`sphx_glr_examples_06-plotting_04-plot_on_path.py` + +.. raw:: html + +
Plot results on a specific path
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_05-plot_on_warped_mesh_thumb.png + :alt: Warp the mesh by a field for plotting + + :ref:`sphx_glr_examples_06-plotting_05-plot_on_warped_mesh.py` + +.. raw:: html + +
Warp the mesh by a field for plotting
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_06-animate_results_thumb.gif + :alt: Review of available animation commands + + :ref:`sphx_glr_examples_06-plotting_06-animate_results.py` + +.. raw:: html + +
Review of available animation commands
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/06-plotting/images/thumb/sphx_glr_07-plot_on_geometries_thumb.png + :alt: Plot on geometry elements + + :ref:`sphx_glr_examples_06-plotting_07-plot_on_geometries.py` + +.. raw:: html + +
Plot on geometry elements
+
+ + +.. raw:: html + +
+ + +Examples for postprocessing on distributed processes +==================================================== +These examples show how to create workflows on different processes (possibly on +different machines) and connect them. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_00-distributed_total_disp_thumb.png + :alt: Postprocessing of displacement on distributed processes + + :ref:`sphx_glr_examples_07-distributed-post_00-distributed_total_disp.py` + +.. raw:: html + +
Postprocessing of displacement on distributed processes
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_01-distributed_workflows_on_remote_thumb.png + :alt: Create a custom workflow on distributed processes + + :ref:`sphx_glr_examples_07-distributed-post_01-distributed_workflows_on_remote.py` + +.. raw:: html + +
Create a custom workflow on distributed processes
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_02-distributed-msup_expansion_thumb.png + :alt: Distributed mode superposition (MSUP) + + :ref:`sphx_glr_examples_07-distributed-post_02-distributed-msup_expansion.py` + +.. raw:: html + +
Distributed mode superposition (MSUP)
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_03-distributed-msup_expansion_steps_thumb.png + :alt: Distributed MSUP distributed modal response + + :ref:`sphx_glr_examples_07-distributed-post_03-distributed-msup_expansion_steps.py` + +.. raw:: html + +
Distributed MSUP distributed modal response
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /examples/07-distributed-post/images/thumb/sphx_glr_06-distributed_stress_averaging_thumb.png + :alt: Average Stress in distributed Workflows + + :ref:`sphx_glr_examples_07-distributed-post_06-distributed_stress_averaging.py` + +.. raw:: html + +
Average Stress in distributed Workflows
+
+ + +.. raw:: html + +
+ diff --git a/docs/source/getting_started/compatibility.rst b/doc/source/getting_started/compatibility.rst similarity index 100% rename from docs/source/getting_started/compatibility.rst rename to doc/source/getting_started/compatibility.rst diff --git a/docs/source/getting_started/dependencies.rst b/doc/source/getting_started/dependencies.rst similarity index 100% rename from docs/source/getting_started/dependencies.rst rename to doc/source/getting_started/dependencies.rst diff --git a/docs/source/getting_started/index.rst b/doc/source/getting_started/index.rst old mode 100755 new mode 100644 similarity index 100% rename from docs/source/getting_started/index.rst rename to doc/source/getting_started/index.rst diff --git a/docs/source/getting_started/install.rst b/doc/source/getting_started/install.rst similarity index 100% rename from docs/source/getting_started/install.rst rename to doc/source/getting_started/install.rst diff --git a/doc/source/images/auto-generated/field_plot.png b/doc/source/images/auto-generated/field_plot.png new file mode 100644 index 0000000000..4f21872ab3 Binary files /dev/null and b/doc/source/images/auto-generated/field_plot.png differ diff --git a/doc/source/images/auto-generated/mesh_plot.png b/doc/source/images/auto-generated/mesh_plot.png new file mode 100644 index 0000000000..5272d83115 Binary files /dev/null and b/doc/source/images/auto-generated/mesh_plot.png differ diff --git a/doc/source/images/auto-generated/model_plot.png b/doc/source/images/auto-generated/model_plot.png new file mode 100644 index 0000000000..204daf17f8 Binary files /dev/null and b/doc/source/images/auto-generated/model_plot.png differ diff --git a/docs/source/images/drawings/OperatorPins.png b/doc/source/images/drawings/OperatorPins.png similarity index 100% rename from docs/source/images/drawings/OperatorPins.png rename to doc/source/images/drawings/OperatorPins.png diff --git a/docs/source/images/drawings/Workflow1.png b/doc/source/images/drawings/Workflow1.png similarity index 100% rename from docs/source/images/drawings/Workflow1.png rename to doc/source/images/drawings/Workflow1.png diff --git a/docs/source/images/drawings/Workflow2.png b/doc/source/images/drawings/Workflow2.png similarity index 100% rename from docs/source/images/drawings/Workflow2.png rename to doc/source/images/drawings/Workflow2.png diff --git a/docs/source/images/drawings/apis_2.png b/doc/source/images/drawings/apis_2.png similarity index 100% rename from docs/source/images/drawings/apis_2.png rename to doc/source/images/drawings/apis_2.png diff --git a/docs/source/images/drawings/book-logo.png b/doc/source/images/drawings/book-logo.png similarity index 100% rename from docs/source/images/drawings/book-logo.png rename to doc/source/images/drawings/book-logo.png diff --git a/docs/source/images/drawings/checklist.png b/doc/source/images/drawings/checklist.png similarity index 100% rename from docs/source/images/drawings/checklist.png rename to doc/source/images/drawings/checklist.png diff --git a/docs/source/images/drawings/circuit.png b/doc/source/images/drawings/circuit.png similarity index 100% rename from docs/source/images/drawings/circuit.png rename to doc/source/images/drawings/circuit.png diff --git a/docs/source/images/drawings/connect-operators.png b/doc/source/images/drawings/connect-operators.png similarity index 100% rename from docs/source/images/drawings/connect-operators.png rename to doc/source/images/drawings/connect-operators.png diff --git a/docs/source/images/drawings/dpf-flow.png b/doc/source/images/drawings/dpf-flow.png similarity index 100% rename from docs/source/images/drawings/dpf-flow.png rename to doc/source/images/drawings/dpf-flow.png diff --git a/docs/source/images/drawings/dpf-mech.png b/doc/source/images/drawings/dpf-mech.png similarity index 100% rename from docs/source/images/drawings/dpf-mech.png rename to doc/source/images/drawings/dpf-mech.png diff --git a/docs/source/images/drawings/dpf-reports.png b/doc/source/images/drawings/dpf-reports.png similarity index 100% rename from docs/source/images/drawings/dpf-reports.png rename to doc/source/images/drawings/dpf-reports.png diff --git a/docs/source/images/drawings/dpf_server_client.png b/doc/source/images/drawings/dpf_server_client.png similarity index 100% rename from docs/source/images/drawings/dpf_server_client.png rename to doc/source/images/drawings/dpf_server_client.png diff --git a/docs/source/images/drawings/entry_premium.png b/doc/source/images/drawings/entry_premium.png similarity index 100% rename from docs/source/images/drawings/entry_premium.png rename to doc/source/images/drawings/entry_premium.png diff --git a/docs/source/images/drawings/field-breakdown.png b/doc/source/images/drawings/field-breakdown.png similarity index 100% rename from docs/source/images/drawings/field-breakdown.png rename to doc/source/images/drawings/field-breakdown.png diff --git a/docs/source/images/drawings/field-con-overview.png b/doc/source/images/drawings/field-con-overview.png similarity index 100% rename from docs/source/images/drawings/field-con-overview.png rename to doc/source/images/drawings/field-con-overview.png diff --git a/docs/source/images/drawings/field-con.png b/doc/source/images/drawings/field-con.png similarity index 100% rename from docs/source/images/drawings/field-con.png rename to doc/source/images/drawings/field-con.png diff --git a/docs/source/images/drawings/field.png b/doc/source/images/drawings/field.png similarity index 100% rename from docs/source/images/drawings/field.png rename to doc/source/images/drawings/field.png diff --git a/docs/source/images/drawings/help-operators.png b/doc/source/images/drawings/help-operators.png similarity index 100% rename from docs/source/images/drawings/help-operators.png rename to doc/source/images/drawings/help-operators.png diff --git a/docs/source/images/drawings/max_u_norm.png b/doc/source/images/drawings/max_u_norm.png similarity index 100% rename from docs/source/images/drawings/max_u_norm.png rename to doc/source/images/drawings/max_u_norm.png diff --git a/docs/source/images/drawings/model.png b/doc/source/images/drawings/model.png similarity index 100% rename from docs/source/images/drawings/model.png rename to doc/source/images/drawings/model.png diff --git a/docs/source/images/drawings/operator-def.png b/doc/source/images/drawings/operator-def.png similarity index 100% rename from docs/source/images/drawings/operator-def.png rename to doc/source/images/drawings/operator-def.png diff --git a/docs/source/images/drawings/operator_drawing.svg b/doc/source/images/drawings/operator_drawing.svg similarity index 100% rename from docs/source/images/drawings/operator_drawing.svg rename to doc/source/images/drawings/operator_drawing.svg diff --git a/docs/source/images/drawings/plugin-logo.png b/doc/source/images/drawings/plugin-logo.png similarity index 100% rename from docs/source/images/drawings/plugin-logo.png rename to doc/source/images/drawings/plugin-logo.png diff --git a/docs/source/images/drawings/remote_machines.png b/doc/source/images/drawings/remote_machines.png similarity index 100% rename from docs/source/images/drawings/remote_machines.png rename to doc/source/images/drawings/remote_machines.png diff --git a/docs/source/images/drawings/scoping-eg.png b/doc/source/images/drawings/scoping-eg.png similarity index 100% rename from docs/source/images/drawings/scoping-eg.png rename to doc/source/images/drawings/scoping-eg.png diff --git a/docs/source/images/drawings/small_operator.svg b/doc/source/images/drawings/small_operator.svg similarity index 100% rename from docs/source/images/drawings/small_operator.svg rename to doc/source/images/drawings/small_operator.svg diff --git a/docs/source/images/drawings/using-dpf.png b/doc/source/images/drawings/using-dpf.png similarity index 100% rename from docs/source/images/drawings/using-dpf.png rename to doc/source/images/drawings/using-dpf.png diff --git a/docs/source/images/drawings/values-entities.png b/doc/source/images/drawings/values-entities.png similarity index 100% rename from docs/source/images/drawings/values-entities.png rename to doc/source/images/drawings/values-entities.png diff --git a/docs/source/images/drawings/xml.png b/doc/source/images/drawings/xml.png similarity index 100% rename from docs/source/images/drawings/xml.png rename to doc/source/images/drawings/xml.png diff --git a/docs/source/images/plotting/crankshaft_disp.png b/doc/source/images/plotting/crankshaft_disp.png similarity index 100% rename from docs/source/images/plotting/crankshaft_disp.png rename to doc/source/images/plotting/crankshaft_disp.png diff --git a/docs/source/images/plotting/pontoon.png b/doc/source/images/plotting/pontoon.png similarity index 100% rename from docs/source/images/plotting/pontoon.png rename to doc/source/images/plotting/pontoon.png diff --git a/docs/source/images/plotting/pontoon_strain.png b/doc/source/images/plotting/pontoon_strain.png similarity index 100% rename from docs/source/images/plotting/pontoon_strain.png rename to doc/source/images/plotting/pontoon_strain.png diff --git a/docs/source/images/plotting/simple_example.png b/doc/source/images/plotting/simple_example.png similarity index 100% rename from docs/source/images/plotting/simple_example.png rename to doc/source/images/plotting/simple_example.png diff --git a/docs/source/index.rst b/doc/source/index.rst similarity index 100% rename from docs/source/index.rst rename to doc/source/index.rst diff --git a/docs/source/operator_reference.rst b/doc/source/operator_reference.rst similarity index 100% rename from docs/source/operator_reference.rst rename to doc/source/operator_reference.rst diff --git a/docs/source/operator_reference_load.rst b/doc/source/operator_reference_load.rst similarity index 100% rename from docs/source/operator_reference_load.rst rename to doc/source/operator_reference_load.rst diff --git a/docs/source/operator_reference_load_apis.rst b/doc/source/operator_reference_load_apis.rst similarity index 100% rename from docs/source/operator_reference_load_apis.rst rename to doc/source/operator_reference_load_apis.rst diff --git a/docs/source/pydpf-core_clone_install.rst b/doc/source/pydpf-core_clone_install.rst similarity index 100% rename from docs/source/pydpf-core_clone_install.rst rename to doc/source/pydpf-core_clone_install.rst diff --git a/docs/source/user_guide/create_sites_for_python_operators.ps1 b/doc/source/user_guide/create_sites_for_python_operators.ps1 similarity index 100% rename from docs/source/user_guide/create_sites_for_python_operators.ps1 rename to doc/source/user_guide/create_sites_for_python_operators.ps1 diff --git a/docs/source/user_guide/create_sites_for_python_operators.sh b/doc/source/user_guide/create_sites_for_python_operators.sh similarity index 100% rename from docs/source/user_guide/create_sites_for_python_operators.sh rename to doc/source/user_guide/create_sites_for_python_operators.sh diff --git a/docs/source/user_guide/custom_operator_example.py b/doc/source/user_guide/custom_operator_example.py similarity index 100% rename from docs/source/user_guide/custom_operator_example.py rename to doc/source/user_guide/custom_operator_example.py diff --git a/docs/source/user_guide/custom_operators.rst b/doc/source/user_guide/custom_operators.rst similarity index 100% rename from docs/source/user_guide/custom_operators.rst rename to doc/source/user_guide/custom_operators.rst diff --git a/docs/source/user_guide/custom_operators_deps.rst b/doc/source/user_guide/custom_operators_deps.rst similarity index 100% rename from docs/source/user_guide/custom_operators_deps.rst rename to doc/source/user_guide/custom_operators_deps.rst diff --git a/docs/source/user_guide/custom_plugin.xml b/doc/source/user_guide/custom_plugin.xml similarity index 100% rename from docs/source/user_guide/custom_plugin.xml rename to doc/source/user_guide/custom_plugin.xml diff --git a/docs/source/user_guide/fields_container.rst b/doc/source/user_guide/fields_container.rst similarity index 100% rename from docs/source/user_guide/fields_container.rst rename to doc/source/user_guide/fields_container.rst diff --git a/docs/source/user_guide/getting_started_with_dpf_server.rst b/doc/source/user_guide/getting_started_with_dpf_server.rst similarity index 100% rename from docs/source/user_guide/getting_started_with_dpf_server.rst rename to doc/source/user_guide/getting_started_with_dpf_server.rst diff --git a/docs/source/user_guide/how_to.rst b/doc/source/user_guide/how_to.rst similarity index 100% rename from docs/source/user_guide/how_to.rst rename to doc/source/user_guide/how_to.rst diff --git a/docs/source/user_guide/index.rst b/doc/source/user_guide/index.rst similarity index 100% rename from docs/source/user_guide/index.rst rename to doc/source/user_guide/index.rst diff --git a/docs/source/user_guide/install_ansys_dpf_core_in_ansys.ps1 b/doc/source/user_guide/install_ansys_dpf_core_in_ansys.ps1 similarity index 100% rename from docs/source/user_guide/install_ansys_dpf_core_in_ansys.ps1 rename to doc/source/user_guide/install_ansys_dpf_core_in_ansys.ps1 diff --git a/docs/source/user_guide/install_ansys_dpf_core_in_ansys.sh b/doc/source/user_guide/install_ansys_dpf_core_in_ansys.sh old mode 100755 new mode 100644 similarity index 100% rename from docs/source/user_guide/install_ansys_dpf_core_in_ansys.sh rename to doc/source/user_guide/install_ansys_dpf_core_in_ansys.sh diff --git a/docs/source/user_guide/main_entities.rst b/doc/source/user_guide/main_entities.rst similarity index 100% rename from docs/source/user_guide/main_entities.rst rename to doc/source/user_guide/main_entities.rst diff --git a/docs/source/user_guide/model.rst b/doc/source/user_guide/model.rst similarity index 100% rename from docs/source/user_guide/model.rst rename to doc/source/user_guide/model.rst diff --git a/docs/source/user_guide/operators.rst b/doc/source/user_guide/operators.rst similarity index 100% rename from docs/source/user_guide/operators.rst rename to doc/source/user_guide/operators.rst diff --git a/docs/source/user_guide/plotting.rst b/doc/source/user_guide/plotting.rst similarity index 100% rename from docs/source/user_guide/plotting.rst rename to doc/source/user_guide/plotting.rst diff --git a/docs/source/user_guide/server_context.rst b/doc/source/user_guide/server_context.rst similarity index 100% rename from docs/source/user_guide/server_context.rst rename to doc/source/user_guide/server_context.rst diff --git a/docs/source/user_guide/server_types.rst b/doc/source/user_guide/server_types.rst similarity index 100% rename from docs/source/user_guide/server_types.rst rename to doc/source/user_guide/server_types.rst diff --git a/docs/source/user_guide/troubleshooting.rst b/doc/source/user_guide/troubleshooting.rst similarity index 100% rename from docs/source/user_guide/troubleshooting.rst rename to doc/source/user_guide/troubleshooting.rst diff --git a/docs/source/user_guide/uninstall_ansys_dpf_core_in_ansys.ps1 b/doc/source/user_guide/uninstall_ansys_dpf_core_in_ansys.ps1 similarity index 100% rename from docs/source/user_guide/uninstall_ansys_dpf_core_in_ansys.ps1 rename to doc/source/user_guide/uninstall_ansys_dpf_core_in_ansys.ps1 diff --git a/docs/source/user_guide/uninstall_ansys_dpf_core_in_ansys.sh b/doc/source/user_guide/uninstall_ansys_dpf_core_in_ansys.sh old mode 100755 new mode 100644 similarity index 100% rename from docs/source/user_guide/uninstall_ansys_dpf_core_in_ansys.sh rename to doc/source/user_guide/uninstall_ansys_dpf_core_in_ansys.sh diff --git a/docs/source/user_guide/xmlfiles.rst b/doc/source/user_guide/xmlfiles.rst similarity index 100% rename from docs/source/user_guide/xmlfiles.rst rename to doc/source/user_guide/xmlfiles.rst diff --git a/docs/styles/.gitignore b/doc/styles/.gitignore similarity index 90% rename from docs/styles/.gitignore rename to doc/styles/.gitignore index 943db7cb51..080f12aa43 100644 --- a/docs/styles/.gitignore +++ b/doc/styles/.gitignore @@ -1,4 +1,4 @@ -* -!Vocab -!Vocab/** +* +!Vocab +!Vocab/** !.gitignore \ No newline at end of file diff --git a/docs/styles/Vocab/ANSYS/accept.txt b/doc/styles/Vocab/ANSYS/accept.txt similarity index 90% rename from docs/styles/Vocab/ANSYS/accept.txt rename to doc/styles/Vocab/ANSYS/accept.txt index 0ea0deb25c..16005462df 100644 --- a/docs/styles/Vocab/ANSYS/accept.txt +++ b/doc/styles/Vocab/ANSYS/accept.txt @@ -1,41 +1,41 @@ -ANSYS -[Aa]nsys -Abaqus -APIs -[Cc]omponentization -[Cc]ore -CPython -DPF [Ss]erver -DPFArray -Entry -Gaussian -getters -gltf -GLTF -grpcio -hexa -IronPython -matplotlib -Mises -MSUP -numpy -postprocess -[Pp]ostprocessing -Premium -Preview License Agreement -protobuf -psutil -PyDPF -[Pp]ython -Pythonic -[Pp]yvista -recursivity -Remotable -Reusability -Rz -scopings -serializer -setuptools -substep -tqdm +ANSYS +[Aa]nsys +Abaqus +APIs +[Cc]omponentization +[Cc]ore +CPython +DPF [Ss]erver +DPFArray +Entry +Gaussian +getters +gltf +GLTF +grpcio +hexa +IronPython +matplotlib +Mises +MSUP +numpy +postprocess +[Pp]ostprocessing +Premium +Preview License Agreement +protobuf +psutil +PyDPF +[Pp]ython +Pythonic +[Pp]yvista +recursivity +Remotable +Reusability +Rz +scopings +serializer +setuptools +substep +tqdm von \ No newline at end of file diff --git a/docs/styles/Vocab/ANSYS/reject.txt b/doc/styles/Vocab/ANSYS/reject.txt similarity index 100% rename from docs/styles/Vocab/ANSYS/reject.txt rename to doc/styles/Vocab/ANSYS/reject.txt 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 720de18daf..1c72c0a098 100644 --- a/examples/08-python-operators/02-python_operators_with_dependencies.py +++ b/examples/08-python-operators/02-python_operators_with_dependencies.py @@ -54,7 +54,7 @@ import os folder_root = os.path.join(os.getcwd().rsplit("pydpf-core", 1)[0], "pydpf-core") -source_path_in_repo = r"docs\source\examples\07-python-operators\plugins" +source_path_in_repo = r"doc\source\examples\07-python-operators\plugins" operator_folder = os.path.join(folder_root, source_path_in_repo) print(operator_folder) plugin_path = None @@ -132,7 +132,7 @@ ): cmd_file = os.path.join( folder_root, - "docs", + "doc", "source", "user_guide", "create_sites_for_python_operators.ps1", @@ -164,7 +164,7 @@ ): cmd_file = os.path.join( folder_root, - "docs", + "doc", "source", "user_guide", "create_sites_for_python_operators.sh",