From 0bff0189efa63385db0d9c2ba4cc61f733de592f Mon Sep 17 00:00:00 2001 From: "paul.profizi" Date: Wed, 8 Nov 2023 15:12:46 +0100 Subject: [PATCH 1/4] Add 03-mode_superposition_transient.py --- .../03-mode_superposition_transient.py | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 examples/01-transient_analyses/03-mode_superposition_transient.py diff --git a/examples/01-transient_analyses/03-mode_superposition_transient.py b/examples/01-transient_analyses/03-mode_superposition_transient.py new file mode 100644 index 00000000000..01a6e533fbb --- /dev/null +++ b/examples/01-transient_analyses/03-mode_superposition_transient.py @@ -0,0 +1,134 @@ +""" +.. _ref_msup_transient: + +Mode superposition transient analysis +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how to postprocess a mode superposition transient result +and visualize the outputs. It also shows how to select modes for the modal expansion. + +""" +# Import the necessary modules +from ansys.dpf import core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core import operators as ops + +############################################################################### +# Modal superposition on all modes available +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Download the mode superposition 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 mode superposition transient +# result file contains several individual results, each at a different timestamp, automatically +# expanded on all available modes. + +# msup_transient = examples.download_transient_result() +msup_transient = { + "rst": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\file.rst", + "rdsp": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\file.rdsp", + "mode": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\modal\file.mode", + "modal_rst": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\modal\file.rst", +} +data_sources = dpf.DataSources(msup_transient["rdsp"]) +up_stream_data_sources = dpf.DataSources(msup_transient["mode"]) +up_stream_data_sources.add_file_path(msup_transient["modal_rst"]) + +data_sources.add_upstream(up_stream_data_sources) +model = dpf.Model(data_sources) +print(model) + +############################################################################### +# Get the expanded displacement fields for each time-step +disp = model.results.displacement.on_all_time_freqs.eval() +print(disp) + +############################################################################### +# Animate the result +disp.animate(scale_factor=5.0) + +############################################################################### +# Get the expanded displacement fields on selected time-steps: +disp = model.results.displacement.on_time_scoping([1, 2, 3]).eval() +print(disp) + +############################################################################### +# Get the expanded displacement fields on part of the mesh, for selected time-steps: +# TODO: NOT WORKING +# partial_scoping = dpf.mesh_scoping_factory.nodal_scoping( +# model.metadata.meshed_region.nodes.scoping.ids[:200] +# ) +# disp = model.results.displacement.on_time_scoping( +# [1, 2, 3] +# ).on_mesh_scoping( +# partial_scoping +# ).eval() +# print(disp) + +############################################################################### +# Modal superposition on selected modes +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# To select a subset of modes for expansion, you cannot use the source operators directly. +# Below is a workflow to extract results while specifying modes for expansion: + +# First build a data source for the modal response factors +transient_response_ds = dpf.DataSources(result_path=msup_transient["rdsp"]) + +# Define the time-steps of interest +time_scoping = dpf.time_freq_scoping_factory.scoping_by_sets(list(range(1, 22))) + +# Extract the result of interest +displacement_fc = dpf.operators.result.displacement( + data_sources=transient_response_ds, # Input here the modal response data source + time_scoping=time_scoping, # Input here the time-steps of interest + mesh_scoping=None # Specify here the region of interest +).eval() + +# The FieldsContainer contains one field per time-step, with data for each mode (entity) +print(displacement_fc) + +############################################################################### +# Now scope the FieldsContainer to the modes of interest +mode_scoping = dpf.Scoping(ids=list(range(1, 3))) # Modes of interest +displacement_fc = dpf.operators.scoping.rescope_fc( + fields_container=displacement_fc, + mesh_scoping=mode_scoping, # Input here the modes of interest +).eval() + +# The FieldsContainer contains one field per time-step, with data for each selected mode (entity) +print(displacement_fc) + +############################################################################### +# Get the modal basis of interest, with mode selection +modal_basis_ds = dpf.DataSources(result_path=msup_transient["mode"]) +modal_basis_ds.add_file_path(msup_transient["modal_rst"]) # Associate mesh data to the mode shapes +modal_basis_fc = dpf.operators.result.modal_basis( + data_sources=modal_basis_ds, + time_scoping=mode_scoping, # Input here the modes of interest + mesh_scoping=None, # Specify here the region of interest +).eval() + +# The modal basis FieldsContainer contains one field per mode shape +print(modal_basis_fc) + +############################################################################### +# Plot each mode shape +for n, modal_basis_f in enumerate(modal_basis_fc): + modal_basis_f.plot(deform_by=modal_basis_f, text=f"mode shape {n+1}") + +############################################################################### +# Apply modal superposition +modal_superposition_fc = dpf.operators.math.modal_superposition( + modal_basis=modal_basis_fc, # FieldsContainer obtained via the modal_basis operator + solution_in_modal_space=displacement_fc, # FieldsContainer obtained via the result operator + time_scoping=time_scoping, # Specify here the time-steps of interest + mesh_scoping=None, # Specify here the region of interest +).eval() + +# We obtain the displacement fields at each time-step, with modal superposition +print(modal_superposition_fc) + +############################################################################### +# Animate the result +modal_superposition_fc.animate(scale_factor=5.0) From a6b512648a02a58d79a9c6440809d943cfbe8f35 Mon Sep 17 00:00:00 2001 From: "paul.profizi" Date: Wed, 8 Nov 2023 15:27:07 +0100 Subject: [PATCH 2/4] Update 03-mode_superposition_transient.py --- .../03-mode_superposition_transient.py | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/examples/01-transient_analyses/03-mode_superposition_transient.py b/examples/01-transient_analyses/03-mode_superposition_transient.py index 01a6e533fbb..6be5bcef55f 100644 --- a/examples/01-transient_analyses/03-mode_superposition_transient.py +++ b/examples/01-transient_analyses/03-mode_superposition_transient.py @@ -11,11 +11,8 @@ # Import the necessary modules from ansys.dpf import core as dpf from ansys.dpf.core import examples -from ansys.dpf.core import operators as ops ############################################################################### -# Modal superposition on all modes available -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Download the mode superposition 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. @@ -24,18 +21,27 @@ # result file contains several individual results, each at a different timestamp, automatically # expanded on all available modes. -# msup_transient = examples.download_transient_result() -msup_transient = { +# msup_transient_files = examples.find_msup_transient() +msup_transient_files = { "rst": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\file.rst", "rdsp": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\file.rdsp", "mode": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\modal\file.mode", "modal_rst": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\modal\file.rst", } -data_sources = dpf.DataSources(msup_transient["rdsp"]) -up_stream_data_sources = dpf.DataSources(msup_transient["mode"]) -up_stream_data_sources.add_file_path(msup_transient["modal_rst"]) +# print(msup_transient_files) + +############################################################################### +# Modal superposition on all modes available +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a datasource with upstream modal information +data_sources = dpf.DataSources(msup_transient_files["rdsp"]) + +up_stream_data_sources = dpf.DataSources(msup_transient_files["mode"]) +up_stream_data_sources.add_file_path(msup_transient_files["modal_rst"]) data_sources.add_upstream(up_stream_data_sources) + +# Load into a model model = dpf.Model(data_sources) print(model) @@ -73,7 +79,7 @@ # Below is a workflow to extract results while specifying modes for expansion: # First build a data source for the modal response factors -transient_response_ds = dpf.DataSources(result_path=msup_transient["rdsp"]) +transient_response_ds = dpf.DataSources(result_path=msup_transient_files["rdsp"]) # Define the time-steps of interest time_scoping = dpf.time_freq_scoping_factory.scoping_by_sets(list(range(1, 22))) @@ -101,8 +107,8 @@ ############################################################################### # Get the modal basis of interest, with mode selection -modal_basis_ds = dpf.DataSources(result_path=msup_transient["mode"]) -modal_basis_ds.add_file_path(msup_transient["modal_rst"]) # Associate mesh data to the mode shapes +modal_basis_ds = dpf.DataSources(result_path=msup_transient_files["mode"]) +modal_basis_ds.add_file_path(msup_transient_files["modal_rst"]) # Associate mesh data to the mode shapes modal_basis_fc = dpf.operators.result.modal_basis( data_sources=modal_basis_ds, time_scoping=mode_scoping, # Input here the modes of interest From 38e2c687b4eb0d9b270aa16c59178c6e66920f81 Mon Sep 17 00:00:00 2001 From: PProfizi Date: Tue, 15 Jul 2025 08:47:13 +0200 Subject: [PATCH 3/4] Metadata: Raise a warning when streams_provider could not be initialized --- src/ansys/dpf/core/model.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ansys/dpf/core/model.py b/src/ansys/dpf/core/model.py index 0ae5cfbff61..fe0daa3db72 100644 --- a/src/ansys/dpf/core/model.py +++ b/src/ansys/dpf/core/model.py @@ -29,6 +29,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +import warnings if TYPE_CHECKING: # pragma: nocover from ansys.dpf.core.scoping import Scoping @@ -323,7 +324,8 @@ def _cache_streams_provider(self): self._stream_provider.inputs.connect(self._data_sources) try: self._stream_provider.run() - except: + except Exception as e: + warnings.warn(f"Could not initialize the stream provider:\n{e}") self._stream_provider = None def release_streams(self): From 2da32df3ab6d31dec6fdda89d83bded692aa8b05 Mon Sep 17 00:00:00 2001 From: PProfizi Date: Tue, 15 Jul 2025 08:48:04 +0200 Subject: [PATCH 4/4] Switch example model --- .../03-mode_superposition_transient.py | 88 ++++++++++++------- 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/examples/01-transient_analyses/03-mode_superposition_transient.py b/examples/01-transient_analyses/03-mode_superposition_transient.py index 6be5bcef55f..ecad7795123 100644 --- a/examples/01-transient_analyses/03-mode_superposition_transient.py +++ b/examples/01-transient_analyses/03-mode_superposition_transient.py @@ -1,44 +1,70 @@ +# Copyright (C) 2020 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """ .. _ref_msup_transient: -Mode superposition transient analysis +Mode-superposition transient analysis ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This example shows how to postprocess a mode superposition transient result +This example shows how to postprocess a mode-superposition transient analysis and visualize the outputs. It also shows how to select modes for the modal expansion. """ + # Import the necessary modules from ansys.dpf import core as dpf from ansys.dpf.core import examples ############################################################################### -# Download the mode superposition transient result example. This example is +# Download the mode-superposition 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 mode superposition transient +# Next, create the model and display the state of the result. This mode-superposition transient # result file contains several individual results, each at a different timestamp, automatically # expanded on all available modes. -# msup_transient_files = examples.find_msup_transient() -msup_transient_files = { - "rst": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\file.rst", - "rdsp": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\file.rdsp", - "mode": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\modal\file.mode", - "modal_rst": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\modal\file.rst", +# mode_superposition_transient_files = examples.find_msup_transient() +mode_superposition_transient_files = { + # "rst": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\file.rst", + "transient_rst": r"D:\ANSYSDev\resources\Innovation_courses\IntroductionToMSUPTransientAnalysis\IntroductionToMSUPTransientAnalysis_files\dp0\SYS-1\MECH\file.rst", + # "rdsp": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\file.rdsp", + "rdsp": r"D:\ANSYSDev\resources\Innovation_courses\IntroductionToMSUPTransientAnalysis\IntroductionToMSUPTransientAnalysis_files\dp0\SYS-1\MECH\file.rdsp", + # "mode": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\modal\file.mode", + "mode": r"D:\ANSYSDev\resources\Innovation_courses\IntroductionToMSUPTransientAnalysis\IntroductionToMSUPTransientAnalysis_files\dp0\SYS\MECH\file0.mode", + # "modal_rst": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\modal\file.rst", + "modal_rst": r"D:\ANSYSDev\resources\Innovation_courses\IntroductionToMSUPTransientAnalysis\IntroductionToMSUPTransientAnalysis_files\dp0\SYS\MECH\file.rst", } -# print(msup_transient_files) ############################################################################### # Modal superposition on all modes available # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Create a datasource with upstream modal information -data_sources = dpf.DataSources(msup_transient_files["rdsp"]) +data_sources = dpf.DataSources(mode_superposition_transient_files["rdsp"]) -up_stream_data_sources = dpf.DataSources(msup_transient_files["mode"]) -up_stream_data_sources.add_file_path(msup_transient_files["modal_rst"]) +up_stream_data_sources = dpf.DataSources(mode_superposition_transient_files["mode"]) +up_stream_data_sources.add_file_path(mode_superposition_transient_files["modal_rst"]) data_sources.add_upstream(up_stream_data_sources) # Load into a model @@ -61,16 +87,11 @@ ############################################################################### # Get the expanded displacement fields on part of the mesh, for selected time-steps: -# TODO: NOT WORKING -# partial_scoping = dpf.mesh_scoping_factory.nodal_scoping( -# model.metadata.meshed_region.nodes.scoping.ids[:200] -# ) -# disp = model.results.displacement.on_time_scoping( -# [1, 2, 3] -# ).on_mesh_scoping( -# partial_scoping -# ).eval() -# print(disp) +partial_scoping = dpf.mesh_scoping_factory.nodal_scoping( + model.metadata.meshed_region.nodes.scoping.ids[:200] +) +disp = model.results.displacement.on_time_scoping([1, 2, 3]).on_mesh_scoping(partial_scoping).eval() +print(disp) ############################################################################### # Modal superposition on selected modes @@ -79,16 +100,20 @@ # Below is a workflow to extract results while specifying modes for expansion: # First build a data source for the modal response factors -transient_response_ds = dpf.DataSources(result_path=msup_transient_files["rdsp"]) +transient_response_ds = dpf.DataSources(result_path=mode_superposition_transient_files["rdsp"]) +# Build a StreamsContainer from the DataSources to benefit from improved performance. +transient_response_sc = dpf.operators.metadata.streams_provider( + data_sources=transient_response_ds +).eval() # Define the time-steps of interest time_scoping = dpf.time_freq_scoping_factory.scoping_by_sets(list(range(1, 22))) # Extract the result of interest displacement_fc = dpf.operators.result.displacement( - data_sources=transient_response_ds, # Input here the modal response data source + streams_container=transient_response_sc, # Input here the modal response data source time_scoping=time_scoping, # Input here the time-steps of interest - mesh_scoping=None # Specify here the region of interest + mesh_scoping=None, # Specify here the region of interest ).eval() # The FieldsContainer contains one field per time-step, with data for each mode (entity) @@ -107,10 +132,13 @@ ############################################################################### # Get the modal basis of interest, with mode selection -modal_basis_ds = dpf.DataSources(result_path=msup_transient_files["mode"]) -modal_basis_ds.add_file_path(msup_transient_files["modal_rst"]) # Associate mesh data to the mode shapes +modal_basis_ds = dpf.DataSources(result_path=mode_superposition_transient_files["mode"]) +modal_basis_ds.add_file_path( + mode_superposition_transient_files["modal_rst"] +) # Associate mesh data to the mode shapes +modal_basis_sc = dpf.operators.metadata.streams_provider(data_sources=modal_basis_ds).eval() modal_basis_fc = dpf.operators.result.modal_basis( - data_sources=modal_basis_ds, + streams_container=modal_basis_sc, time_scoping=mode_scoping, # Input here the modes of interest mesh_scoping=None, # Specify here the region of interest ).eval()