Skip to content

Add a Mode-Superposition Transient Analysis example #1256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions examples/01-transient_analyses/03-mode_superposition_transient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""
.. _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

###############################################################################
# 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_files = examples.find_msup_transient()
msup_transient_files = {
"rst": r"D:\ANSYSDev\Sandbox\UnitTestDataFiles\expansion\msup\Transient\plate1\file.rst",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it meant to be hardcoded path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, that is until a find a nicer example file to add to our example repo

"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",
}
# 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)

###############################################################################
# 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(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is not working?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cbellot000 when running this commented part I get:

Traceback (most recent call last):
  File "D:\ANSYSDev\Sandbox\pydpf-core\examples\01-transient_analyses\03-mode_superposition_transient.py", line 72, in <module>
    ).eval()
  File "D:\ANSYSDev\Sandbox\pydpf-core\src\ansys\dpf\core\results.py", line 266, in eval
    fc = self.__call__().outputs.fields_container()
  File "D:\ANSYSDev\Sandbox\pydpf-core\src\ansys\dpf\core\outputs.py", line 75, in __call__
    return self.get_data()
  File "D:\ANSYSDev\Sandbox\pydpf-core\src\ansys\dpf\core\outputs.py", line 72, in get_data
    return self._operator.get_output(self._pin, type_output)
  File "D:\ANSYSDev\Sandbox\pydpf-core\src\ansys\dpf\core\dpf_operator.py", line 494, in get_output
    parameters = {type_tuple[2]: type_tuple[1](self, pin)}
  File "D:\ANSYSDev\Sandbox\pydpf-core\src\ansys\dpf\gate\generated\operator_capi.py", line 402, in operator_getoutput_fields_container
    res = capi.dll.Operator_getoutput_FieldsContainer(op._internal_obj if op is not None else None, utils.to_int32(iOutput), ctypes.byref(utils.to_int32(errorSize)), ctypes.byref(sError))
OSError: exception: access violation reading 0x0000000000000008

ANSYS LICENSE MANAGER ERROR:

System error: 10093 "Either the application has not called WSAStartup, or WSAStartup failed.
".


Process finished with exit code 1

I think the ANSYS LICENSE MANAGER ERROR is new though

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who looks bad, did you create a bug in TFS to track it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet, I'll do it right now

# 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_files["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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you input this to the mesh_scoping, it is understood as a Nodal scoping. Is this what you mean?

Copy link
Contributor Author

@PProfizi PProfizi Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rafacanton no, interestingly enough, this displacement_fc contains fields located at Modal, which is unexpected but actually logical when using an rdsp file as input, hence the rescope on a generic Scoping (tried instantiating a Scoping as Modal but it does not work):

DPF  Fields Container
  with 21 field(s)
  defined on labels: time 

  with:
  - field 0 {time:  1} with Modal location, 1 components and 6 entities.
  - field 1 {time:  2} with Modal location, 1 components and 6 entities.
  - field 2 {time:  3} with Modal location, 1 components and 6 entities.
  - field 3 {time:  4} with Modal location, 1 components and 6 entities.
  - field 4 {time:  5} with Modal location, 1 components and 6 entities.
  - field 5 {time:  6} with Modal location, 1 components and 6 entities.
  - field 6 {time:  7} with Modal location, 1 components and 6 entities.
  - field 7 {time:  8} with Modal location, 1 components and 6 entities.
  - field 8 {time:  9} with Modal location, 1 components and 6 entities.
  - field 9 {time:  10} with Modal location, 1 components and 6 entities.
  - field 10 {time:  11} with Modal location, 1 components and 6 entities.
  - field 11 {time:  12} with Modal location, 1 components and 6 entities.
  - field 12 {time:  13} with Modal location, 1 components and 6 entities.
  - field 13 {time:  14} with Modal location, 1 components and 6 entities.
  - field 14 {time:  15} with Modal location, 1 components and 6 entities.
  - field 15 {time:  16} with Modal location, 1 components and 6 entities.
  - field 16 {time:  17} with Modal location, 1 components and 6 entities.
  - field 17 {time:  18} with Modal location, 1 components and 6 entities.
  - field 18 {time:  19} with Modal location, 1 components and 6 entities.
  - field 19 {time:  20} with Modal location, 1 components and 6 entities.
  - field 20 {time:  21} with Modal location, 1 components and 6 entities.

While trying out different combinations, I realized that this is really not straightforward with the API currently in place. For example, the Modal scoping seems to exist server-side but is impossible to build client-side.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conclusion: this example is useful to showcase how to do this, but really we lack helpers regarding mode manipulation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's a bit confusing, I think it's worth adding a comment to explain

).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_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
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)