Note
Go to the end to download the full example code.
Modal acoustics analysis#
This example demonstrate modal acoustic analysis that involves modeling both a structure and the surrounding fluid to analyze frequencies and standing wave patterns within the structure. This type of analysis is essential for applications such as Sonar, concert hall design, noise reduction in various settings, audio speaker design, and geophysical exploration.
Mechanical enables you to model pure acoustic problems and fluid-structure interaction (FSI) problems.A coupled acoustic analysis accounts for FSI. An uncoupled acoustic analysis simulates the fluid only and ignores any fluid-structure interaction.
Import necessary libraries#
import os
from PIL import Image
import ansys.mechanical.core as mech
from ansys.mechanical.core.examples import delete_downloads, download_file
from matplotlib import image as mpimg
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
Embed mechanical and set global variables
app = mech.App(version=241)
globals().update(mech.global_variables(app, True))
print(app)
cwd = os.path.join(os.getcwd(), "out")
def display_image(image_name):
plt.figure(figsize=(16, 9))
plt.imshow(mpimg.imread(os.path.join(cwd, image_name)))
plt.xticks([])
plt.yticks([])
plt.axis("off")
plt.show()
Ansys Mechanical [Ansys Mechanical Enterprise]
Product Version:241
Software build date: 11/27/2023 10:24:20
Configure graphics for image export#
ExtAPI.Graphics.Camera.SetSpecificViewOrientation(ViewOrientationType.Iso)
image_export_format = GraphicsImageExportFormat.PNG
settings_720p = Ansys.Mechanical.Graphics.GraphicsImageExportSettings()
settings_720p.Resolution = GraphicsResolutionType.EnhancedResolution
settings_720p.Background = GraphicsBackgroundType.White
settings_720p.Width = 1280
settings_720p.Height = 720
settings_720p.CurrentGraphicsDisplay = False
Download geometry and materials files#
geometry_path = download_file("sloshing_geometry.agdb", "pymechanical", "embedding")
mat_path = download_file("Water_material_explicit.xml", "pymechanical", "embedding")
Import the geometry#
geometry_import_group = Model.GeometryImportGroup
geometry_import = geometry_import_group.AddGeometryImport()
geometry_import_format = (
Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic
)
geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences()
geometry_import_preferences.ProcessNamedSelections = True
geometry_import.Import(
geometry_path, geometry_import_format, geometry_import_preferences
)
ExtAPI.Graphics.Camera.SetFit()
ExtAPI.Graphics.ExportImage(
os.path.join(cwd, "geometry.png"), image_export_format, settings_720p
)
display_image("geometry.png")
Store all variables necessary for analysis#
GEOM = DataModel.Project.Model.Geometry
MESH = DataModel.Project.Model.Mesh
NS = DataModel.Project.Model.NamedSelections
CONN = DataModel.Project.Model.Connections
MAT = DataModel.Project.Model.Materials
Import material setup analysis#
Model.AddModalAcousticAnalysis()
ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardMKS
MAT.Import(mat_path)
print("Material Import Done !")
Material Import Done !
Get all required named selections and assign materials#
acst_bodies = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Acoustic_bodies"
][0]
struct_bodies = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Structural_bodies"
][0]
top_bodies = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "top_bodies"
][0]
cont_bodies = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "container_bodies"
][0]
cont_V1 = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Cont_V1"
][0]
cont_V2 = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Cont_V2"
][0]
cont_V3 = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Cont_V3"
][0]
cont_face1 = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Cont_face1"
][0]
cont_face2 = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Cont_face2"
][0]
cont_face3 = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Cont_face3"
][0]
cont_face4 = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Cont_face4"
][0]
free_faces = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "Free_faces"
][0]
fsi_faces = [
i
for i in NS.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True)
if i.Name == "FSI_faces"
][0]
solid1 = [
i
for i in GEOM.GetChildren[Ansys.ACT.Automation.Mechanical.Body](True)
if i.Name == "Solid1"
][0]
solid2 = [
i
for i in GEOM.GetChildren[Ansys.ACT.Automation.Mechanical.Body](True)
if i.Name == "Solid2"
][0]
solid3 = [
i
for i in GEOM.GetChildren[Ansys.ACT.Automation.Mechanical.Body](True)
if i.Name == "Solid3"
][0]
solid4 = [
i
for i in GEOM.GetChildren[Ansys.ACT.Automation.Mechanical.Body](True)
if i.Name == "Solid4"
][0]
Assign material water to acoustic parts
solid1.Material = "WATER"
solid2.Material = "WATER"
solid3.Material = "WATER"
solid4.Material = "WATER"
Mesh#
MESH.ElementOrder = ElementOrder.Quadratic
method1 = MESH.AddAutomaticMethod()
method1.Location = acst_bodies
method1.Method = MethodType.AllTriAllTet
method2 = MESH.AddAutomaticMethod()
method2.Location = top_bodies
method2.Method = MethodType.Automatic
# Add mesh sizing
sizing1 = MESH.AddSizing()
sizing1.Location = top_bodies
sizing1.ElementSize = Quantity("0.2 [m]")
sizing1.Behavior = SizingBehavior.Hard
# Add mesh sizing
sizing2 = MESH.AddSizing()
sizing2.Location = acst_bodies
sizing2.ElementSize = Quantity("0.2 [m]")
sizing2.Behavior = SizingBehavior.Hard
# Add mesh method
method3 = MESH.AddAutomaticMethod()
method3.Location = cont_bodies
method3.Method = MethodType.Sweep
method3.SourceTargetSelection = 4
MESH.GenerateMesh()
ExtAPI.Graphics.ExportImage(
os.path.join(cwd, "mesh.png"), image_export_format, settings_720p
)
display_image("mesh.png")
Insert contacts#
Contact 1
CONN_GROUP = CONN.AddConnectionGroup()
CONT1 = CONN_GROUP.AddContactRegion()
CONT1.SourceLocation = cont_V1
CONT1.TargetLocation = cont_face1
CONT1.ContactFormulation = ContactFormulation.MPC
CONT1.Behavior = ContactBehavior.Asymmetric
CONT1.PinballRegion = ContactPinballType.Radius
CONT1.PinballRadius = Quantity("0.25 [m]")
Contact 2
CONT2 = CONN_GROUP.AddContactRegion()
CONT2.SourceLocation = cont_V2
CONT2.TargetLocation = cont_face2
CONT2.ContactFormulation = ContactFormulation.MPC
CONT2.Behavior = ContactBehavior.Asymmetric
CONT2.PinballRegion = ContactPinballType.Radius
CONT2.PinballRadius = Quantity("0.25 [m]")
Contact 3
CONT3 = CONN_GROUP.AddContactRegion()
CONT3.SourceLocation = cont_V3
CONT3.TargetLocation = cont_face3
CONT3.ContactFormulation = ContactFormulation.MPC
CONT3.Behavior = ContactBehavior.Asymmetric
CONT3.PinballRegion = ContactPinballType.Radius
CONT3.PinballRadius = Quantity("0.25 [m]")
Contact 3
sel_manager = ExtAPI.SelectionManager
cnv4 = DataModel.GeoData.Assemblies[0].Parts[1].Bodies[0].Vertices[3]
cont_V4 = sel_manager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities)
cont_V4.Entities = [cnv4]
Contact 4
CONT4 = CONN_GROUP.AddContactRegion()
CONT4.TargetLocation = cont_face4
CONT4.SourceLocation = cont_V4
CONT4.ContactFormulation = ContactFormulation.MPC
CONT4.Behavior = ContactBehavior.Asymmetric
CONT4.PinballRegion = ContactPinballType.Radius
CONT4.PinballRadius = Quantity("0.25 [m]")
Fully define Modal Multiphysics region with two physics regions
MODAL_ACST = DataModel.Project.Model.Analyses[0]
ACOUST_REG = MODAL_ACST.Children[2]
ACOUST_REG.Location = acst_bodies
STRUCT_REG = MODAL_ACST.AddPhysicsRegion()
STRUCT_REG.Structural = True
STRUCT_REG.RenameBasedOnDefinition()
STRUCT_REG.Location = struct_bodies
Analysis settings#
ANALYSIS_SETTINGS = MODAL_ACST.Children[1]
ANALYSIS_SETTINGS.MaximumModesToFind = 12
ANALYSIS_SETTINGS.SearchRangeMinimum = Quantity("0.1 [Hz]")
ANALYSIS_SETTINGS.SolverType = SolverType.Unsymmetric
ANALYSIS_SETTINGS.GeneralMiscellaneous = True
ANALYSIS_SETTINGS.CalculateReactions = True
Boundary conditions and load#
Free surface
FREE_SF = MODAL_ACST.AddAcousticFreeSurface()
FREE_SF.Location = free_faces
Solid fluid interface
FSI_OBJ = MODAL_ACST.AddFluidSolidInterface()
FSI_OBJ.Location = fsi_faces
Gravity
ACCELERATION = MODAL_ACST.AddAcceleration()
ACCELERATION.DefineBy = LoadDefineBy.Components
ACCELERATION.YComponent.Output.DiscreteValues = [Quantity("9.81 [m sec^-1 sec^-1]")]
Fixed Support
fv1 = DataModel.GeoData.Assemblies[0].Parts[1].Bodies[0].Vertices[0]
fv2 = DataModel.GeoData.Assemblies[0].Parts[1].Bodies[1].Vertices[0]
fv3 = DataModel.GeoData.Assemblies[0].Parts[1].Bodies[2].Vertices[0]
fv4 = DataModel.GeoData.Assemblies[0].Parts[1].Bodies[3].Vertices[0]
fvert = sel_manager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities)
fvert.Entities = [fv1, fv2, fv3, fv4]
FIXED_SUPPORT = MODAL_ACST.AddFixedSupport()
FIXED_SUPPORT.Location = fvert
MODAL_ACST.Activate()
ExtAPI.Graphics.ExportImage(
os.path.join(cwd, "geometry.png"), image_export_format, settings_720p
)
display_image("geometry.png")
Add results#
Add 10 modes
soln = DataModel.Project.Model.Analyses[0].Solution
TOT_DEF1 = soln.AddTotalDeformation()
TOT_DEF2 = soln.AddTotalDeformation()
TOT_DEF2.Mode = 2
TOT_DEF3 = soln.AddTotalDeformation()
TOT_DEF3.Mode = 3
TOT_DEF4 = soln.AddTotalDeformation()
TOT_DEF4.Mode = 4
TOT_DEF5 = soln.AddTotalDeformation()
TOT_DEF5.Mode = 5
TOT_DEF6 = soln.AddTotalDeformation()
TOT_DEF6.Mode = 6
TOT_DEF7 = soln.AddTotalDeformation()
TOT_DEF7.Mode = 7
TOT_DEF8 = soln.AddTotalDeformation()
TOT_DEF8.Mode = 8
TOT_DEF9 = soln.AddTotalDeformation()
TOT_DEF9.Mode = 9
TOT_DEF10 = soln.AddTotalDeformation()
TOT_DEF10.Mode = 10
Add acoustic pressure
ACOUST_PRES_RES = soln.AddAcousticPressureResult()
Add force reaction scoped to fixed Support
FORCE_REACT1 = soln.AddForceReaction()
FORCE_REACT1.BoundaryConditionSelection = FIXED_SUPPORT
Solve#
soln.Solve(True)
Messages#
Messages = ExtAPI.Application.Messages
if Messages:
for message in Messages:
print(f"[{message.Severity}] {message.DisplayString}")
else:
print("No [Info]/[Warning]/[Error] Messages")
No [Info]/[Warning]/[Error] Messages
Results#
Total deformation - mode 1
Tree.Activate([TOT_DEF1])
ExtAPI.Graphics.Camera.SetFit()
ExtAPI.Graphics.ExportImage(
os.path.join(cwd, "totaldeformation1.png"), image_export_format, settings_720p
)
display_image("totaldeformation1.png")
Acoustic pressure
Tree.Activate([ACOUST_PRES_RES])
ExtAPI.Graphics.ExportImage(
os.path.join(cwd, "acoustic_pressure.png"), image_export_format, settings_720p
)
display_image("acoustic_pressure.png")
Display all modal frequency, force reaction and acoustic pressure values
FREQ1 = TOT_DEF1.ReportedFrequency.Value
FREQ2 = TOT_DEF2.ReportedFrequency.Value
FREQ3 = TOT_DEF3.ReportedFrequency.Value
FREQ4 = TOT_DEF4.ReportedFrequency.Value
FREQ5 = TOT_DEF5.ReportedFrequency.Value
FREQ6 = TOT_DEF6.ReportedFrequency.Value
FREQ7 = TOT_DEF7.ReportedFrequency.Value
FREQ8 = TOT_DEF8.ReportedFrequency.Value
FREQ9 = TOT_DEF9.ReportedFrequency.Value
FREQ10 = TOT_DEF10.ReportedFrequency.Value
PRMAX = ACOUST_PRES_RES.Maximum.Value
PRMIN = ACOUST_PRES_RES.Minimum.Value
FRC1_X = FORCE_REACT1.XAxis.Value
FRC1_Z = FORCE_REACT1.ZAxis.Value
print("Modal Acoustic Results")
print("----------------------")
print("Frequency for mode 1 : ", FREQ1)
print("Frequency for mode 2 : ", FREQ2)
print("Frequency for mode 3 : ", FREQ3)
print("Frequency for mode 4 : ", FREQ4)
print("Frequency for mode 5 : ", FREQ5)
print("Frequency for mode 6 : ", FREQ6)
print("Frequency for mode 7 : ", FREQ7)
print("Frequency for mode 8 : ", FREQ8)
print("Frequency for mode 9 : ", FREQ9)
print("Frequency for mode 10 : ", FREQ10)
print("Acoustic pressure minimum : ", PRMIN)
print("Acoustic pressure Maximum : ", PRMAX)
print("Force reaction x-axis : ", FRC1_X)
print("Force reaction z-axis : ", FRC1_Z)
Modal Acoustic Results
----------------------
Frequency for mode 1 : 0.46136889718768465
Frequency for mode 2 : 0.4620435025713437
Frequency for mode 3 : 0.618601960402056
Frequency for mode 4 : 0.6190624453312934
Frequency for mode 5 : 0.6920677009398126
Frequency for mode 6 : 0.7256793178904506
Frequency for mode 7 : 0.7279212265463372
Frequency for mode 8 : 0.8120060551801991
Frequency for mode 9 : 0.8128310197820786
Frequency for mode 10 : 0.8149759073561436
Acoustic pressure minimum : -1.4673188924789429
Acoustic pressure Maximum : 1.4758306741714478
Force reaction x-axis : 7.873853515867161
Force reaction z-axis : 9.233516583050914
Total deformation animation for mode 10
animation_export_format = (
Ansys.Mechanical.DataModel.Enums.GraphicsAnimationExportFormat.GIF
)
settings_720p = Ansys.Mechanical.Graphics.AnimationExportSettings()
settings_720p.Width = 1280
settings_720p.Height = 720
TOT_DEF10.ExportAnimation(
os.path.join(cwd, "deformation_10.gif"), animation_export_format, settings_720p
)
gif = Image.open(os.path.join(cwd, "deformation_10.gif"))
fig, ax = plt.subplots(figsize=(16, 9))
ax.axis("off")
img = ax.imshow(gif.convert("RGBA"))
def update(frame):
gif.seek(frame)
img.set_array(gif.convert("RGBA"))
return [img]
ani = FuncAnimation(
fig, update, frames=range(gif.n_frames), interval=100, repeat=True, blit=True
)
plt.show()
Project tree#
def print_tree(node, indentation=""):
print(f"{indentation}├── {node.Name}")
if (
hasattr(node, "Children")
and node.Children is not None
and node.Children.Count > 0
):
for child in node.Children:
print_tree(child, indentation + "| ")
root_node = DataModel.Project
print_tree(root_node)
├── Project
| ├── Model
| | ├── Geometry Imports
| | | ├── Geometry Import
| | ├── Geometry
| | | ├── Part
| | | | ├── Solid
| | | | ├── Solid1
| | | | ├── Solid
| | | | ├── Solid2
| | | | ├── Solid
| | | | ├── Solid
| | | | ├── Solid
| | | | ├── Solid3
| | | | ├── Solid
| | | | ├── Solid4
| | | | ├── Solid
| | | | ├── Solid
| | | | ├── Solid
| | | | ├── Solid
| | | | ├── Solid
| | | | ├── Solid
| | | ├── Part 2
| | | | ├── Line Body
| | | | ├── Line Body
| | | | ├── Line Body
| | | | ├── Line Body
| | | | ├── Line Body
| | ├── Materials
| | | ├── Structural Steel
| | | ├── Air
| | | ├── WATER
| | ├── Cross Sections
| | | ├── Circular1
| | ├── Coordinate Systems
| | | ├── Global Coordinate System
| | ├── Remote Points
| | ├── Connections
| | | ├── Connection Group
| | | | ├── Contact Region
| | | | ├── Contact Region 2
| | | | ├── Contact Region 3
| | | | ├── Contact Region 4
| | ├── Mesh Workflows
| | ├── Mesh
| | | ├── Patch Conforming Method
| | | ├── Automatic Method
| | | ├── Body Sizing
| | | ├── Body Sizing 2
| | | ├── Sweep Method
| | ├── Named Selections
| | | ├── Acoustic_bodies
| | | ├── Structural_bodies
| | | ├── Line_bodies
| | | ├── Free_faces
| | | ├── FSI_faces
| | | ├── top_bodies
| | | ├── container_bodies
| | | ├── Cont_V1
| | | ├── Cont_V2
| | | ├── Cont_V3
| | | ├── Cont_face1
| | | ├── Cont_face2
| | | ├── Cont_face3
| | | ├── Cont_face4
| | ├── Modal Acoustics
| | | ├── Pre-Stress (None)
| | | ├── Analysis Settings
| | | ├── Acoustics Region
| | | ├── Structural Region
| | | ├── Acceleration
| | | ├── Free Surface
| | | ├── Fluid Solid Interface
| | | ├── Fixed Support
| | | ├── Solution
| | | | ├── Solution Information
| | | | ├── Total Deformation
| | | | ├── Total Deformation 2
| | | | ├── Total Deformation 3
| | | | ├── Total Deformation 4
| | | | ├── Total Deformation 5
| | | | ├── Total Deformation 6
| | | | ├── Total Deformation 7
| | | | ├── Total Deformation 8
| | | | ├── Total Deformation 9
| | | | ├── Total Deformation 10
| | | | ├── Acoustic Pressure
| | | | ├── Force Reaction
Cleanup#
Save project
app.save(os.path.join(cwd, "modal_acoustics.mechdat"))
app.new()
Delete example file
delete_downloads()
True
Total running time of the script: (0 minutes 46.627 seconds)