Note
Go to the end to download the full example code.
Topology optimization of a simple cantilever beam#
This example demonstrates the structural topology optimization of a simple cantilever beam. The structural analysis is performed with basic constraints and load, which is then transferred to the topology optimization.
Import the necessary libraries#
from pathlib import Path
from typing import TYPE_CHECKING
from ansys.mechanical.core import App
from ansys.mechanical.core.examples import delete_downloads, download_file
from matplotlib import image as mpimg
from matplotlib import pyplot as plt
if TYPE_CHECKING:
import Ansys
Initialize the embedded application#
app = App(globals=globals())
print(app)
Ansys Mechanical [Ansys Mechanical Enterprise]
Product Version:251
Software build date: 11/27/2024 09:34:44
Create functions to set camera and display images#
# Set the path for the output files (images, gifs, mechdat)
output_path = Path.cwd() / "out"
def set_camera_and_display_image(
camera,
graphics,
graphics_image_export_settings,
image_output_path: Path,
image_name: str,
) -> None:
"""Set the camera to fit the model and display the image.
Parameters
----------
camera : Ansys.ACT.Common.Graphics.MechanicalCameraWrapper
The camera object to set the view.
graphics : Ansys.ACT.Common.Graphics.MechanicalGraphicsWrapper
The graphics object to export the image.
graphics_image_export_settings : Ansys.Mechanical.Graphics.GraphicsImageExportSettings
The settings for exporting the image.
image_output_path : Path
The path to save the exported image.
image_name : str
The name of the exported image file.
"""
# Set the camera to fit the mesh
camera.SetFit()
# Export the mesh image with the specified settings
image_path = image_output_path / image_name
graphics.ExportImage(
str(image_path), image_export_format, graphics_image_export_settings
)
# Display the exported mesh image
display_image(image_path)
def display_image(
image_path: str,
pyplot_figsize_coordinates: tuple = (16, 9),
plot_xticks: list = [],
plot_yticks: list = [],
plot_axis: str = "off",
) -> None:
"""Display the image with the specified parameters.
Parameters
----------
image_path : str
The path to the image file to display.
pyplot_figsize_coordinates : tuple
The size of the figure in inches (width, height).
plot_xticks : list
The x-ticks to display on the plot.
plot_yticks : list
The y-ticks to display on the plot.
plot_axis : str
The axis visibility setting ('on' or 'off').
"""
# Set the figure size based on the coordinates specified
plt.figure(figsize=pyplot_figsize_coordinates)
# Read the image from the file into an array
plt.imshow(mpimg.imread(image_path))
# Get or set the current tick locations and labels of the x-axis
plt.xticks(plot_xticks)
# Get or set the current tick locations and labels of the y-axis
plt.yticks(plot_yticks)
# Turn off the axis
plt.axis(plot_axis)
# Display the figure
plt.show()
Configure graphics for image export
graphics = app.Graphics
camera = graphics.Camera
# Set the camera orientation to the front view
camera.SetSpecificViewOrientation(ViewOrientationType.Front)
# Set the image export format and settings
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
Import the structural analysis model#
# Download ``.mechdat`` file
structural_mechdat_file = download_file(
"cantilever.mechdat", "pymechanical", "embedding"
)
# Open the project file
app.open(structural_mechdat_file)
# Define the model
model = app.Model
# Get the structural analysis object
struct = model.Analyses[0]
# Get the structural analysis object's solution and solve it
struct_sln = struct.Solution
struct_sln.Solve(True)
Display the structural analysis results#
Activate the total deformation result and display the image
struct_sln.Children[1].Activate()
set_camera_and_display_image(
camera, graphics, settings_720p, output_path, "total_deformation.png"
)

Activate the equivalent stress result and display the image
struct_sln.Children[2].Activate()
set_camera_and_display_image(
camera, graphics, settings_720p, output_path, "equivalent_stress.png"
)

Topology optimization#
# Set the MKS unit system
app.ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardMKS
# Add the topology optimization analysis to the model and transfer data from the
# structural analysis
topology_optimization = model.AddTopologyOptimizationAnalysis()
topology_optimization.TransferDataFrom(struct)
# Get the optimization region from the data model
optimization_region = DataModel.GetObjectsByType(
DataModelObjectCategory.OptimizationRegion
)[0]
# Set the optimization region's boundary condition to all loads and supports
optimization_region.BoundaryCondition = BoundaryConditionType.AllLoadsAndSupports
# Set the optimization region's optimization type to topology density
optimization_region.OptimizationType = OptimizationType.TopologyDensity
# Delete the mass response constraint from the topology optimization
mass_constraint = topology_optimization.Children[3]
app.DataModel.Remove(mass_constraint)
# Add a volume response constraint to the topology optimization
volume_constraint = topology_optimization.AddVolumeConstraint()
# Add a member size manufacturing constraint to the topology optimization
mem_size_manufacturing_constraint = (
topology_optimization.AddMemberSizeManufacturingConstraint()
)
# Set the constraint's minimum to manual and its minimum size to 2.4m
mem_size_manufacturing_constraint.Minimum = ManuMemberSizeControlledType.Manual
mem_size_manufacturing_constraint.MinSize = Quantity("2.4 [m]")
# Activate the topology optimization analysis and display the image
topology_optimization.Activate()
set_camera_and_display_image(
camera, graphics, settings_720p, output_path, "boundary_conditions.png"
)

Solve the solution#
# Get the topology optimization analysis solution
top_opt_sln = topology_optimization.Solution
# Solve the solution
top_opt_sln.Solve(True)
Show messages#
# Print all messages from Mechanical
app.messages.show()
Severity: Info
DisplayString: For geometric constraint (Mass, Volume, Center of Gravity or Moment of Inertia constraints), it is recommended to use Criterion of the upstream Measure folder (inserted from Model object).
Severity: Warning
DisplayString: The application requires the use of OpenGL version 4.3. The detected version 3.1 Mesa 21.2.6 does not meet this requirement. This discrepancy may produce graphical display issues for certain features. Furthermore, future versions of Mechanical may not support systems that do not meet this requirement.
Severity: Warning
DisplayString: The license manager is delayed in its response. The latest requests were answered after 30 seconds.
Severity: Warning
DisplayString: The default mesh size calculations have changed in 18.2. Specifically, the default min size values and/or defeature size values scale dynamically in relation to the element (max face) size. These settings could lead to a significantly different mesh, so the model will be resumed using the previous values for min size and defeature size rather than leaving those values as default.
Display the results#
# Get the topology density result and activate it
top_opt_sln.Children[1].Activate()
topology_density = top_opt_sln.Children[1]
Add smoothing to the stereolithography (STL)
# Add smoothing to the topology density result
topology_density.AddSmoothing()
# Evaluate all results for the topology optimization solution
topology_optimization.Solution.EvaluateAllResults()
# Activate the topology density result after smoothing and display the image
topology_density.Children[0].Activate()
set_camera_and_display_image(
camera, graphics, settings_720p, output_path, "topo_opitimized_smooth.png"
)

Export the animation
app.Tree.Activate([topology_density])
# Set the animation export format and settings
animation_export_format = (
Ansys.Mechanical.DataModel.Enums.GraphicsAnimationExportFormat.GIF
)
settings_720p = Ansys.Mechanical.Graphics.AnimationExportSettings()
settings_720p.Width = 1280
settings_720p.Height = 720
# Export the animation of the topology density result
topology_optimized_gif = output_path / "topology_opitimized.gif"
topology_density.ExportAnimation(
str(topology_optimized_gif), animation_export_format, settings_720p
)

Review the results
# Print the topology density results
print("Topology Density Results")
print("Minimum Density: ", topology_density.Minimum)
print("Maximum Density: ", topology_density.Maximum)
print("Iteration Number: ", topology_density.IterationNumber)
print("Original Volume: ", topology_density.OriginalVolume.Value)
print("Final Volume: ", topology_density.FinalVolume.Value)
print("Percent Volume of Original: ", topology_density.PercentVolumeOfOriginal)
print("Original Mass: ", topology_density.OriginalMass.Value)
print("Final Mass: ", topology_density.FinalMass.Value)
print("Percent Mass of Original: ", topology_density.PercentMassOfOriginal)
Topology Density Results
Minimum Density: 0.0010000000474974513
Maximum Density: 1.0
Iteration Number: 35
Original Volume: 1000.0000054389238
Final Volume: 522.4924773573875
Percent Volume of Original: 52.24924745155908
Original Mass: 7849999.975463867
Final Mass: 4101565.9057617188
Percent Mass of Original: 52.24924737046705
Display the project tree#
app.print_tree()
├── Project
| ├── Model
| | ├── Geometry Imports (✓)
| | | ├── Geometry Import (✓)
| | ├── Geometry (✓)
| | | ├── Surface Body Bodies
| | | | ├── Surface Body
| | ├── Materials (✓)
| | | ├── Structural Steel (✓)
| | ├── Coordinate Systems (✓)
| | | ├── Global Coordinate System (✓)
| | | ├── Coordinate System (✓)
| | | ├── Coordinate System 2 (✓)
| | | ├── Coordinate System 3 (✓)
| | | ├── Coordinate System 4 (✓)
| | | ├── Coordinate System 5 (✓)
| | | ├── Coordinate System 6 (✓)
| | | ├── Coordinate System 7 (✓)
| | | ├── Coordinate System 8 (✓)
| | ├── Remote Points (✓)
| | ├── Mesh (✓)
| | | ├── Face Sizing (✓)
| | ├── Named Selections
| | | ├── Selection (✓)
| | | ├── Bottom_Elements (✓)
| | | ├── Top_Elements (✓)
| | | ├── Middle1_Elements (✓)
| | | ├── Middle2_Elements (✓)
| | | ├── Left1_Elements (✓)
| | | ├── Left2_Elements (✓)
| | | ├── Right1_Elements (✓)
| | | ├── Right2_Elements (✓)
| | | ├── Optimized_Shape (✓)
| | | ├── Outside_Optimized_Shape (✓)
| | | ├── Selection 2 (✓)
| | | ├── Selection 3 (✓)
| | | ├── Selection 4 (✓)
| | | ├── Selection 5 (✓)
| | ├── Static Structural (✓)
| | | ├── Analysis Settings (✓)
| | | ├── Fixed Support (✓)
| | | ├── Nodal Force (✓)
| | | ├── Solution (✓)
| | | | ├── Solution Information (✓)
| | | | ├── Total Deformation (✓)
| | | | ├── Equivalent Stress (✓)
| | ├── Structural Optimization (✓)
| | | ├── Analysis Settings (✓)
| | | ├── Optimization Region (✓)
| | | ├── Objective (✓)
| | | ├── Response Constraint (✓)
| | | ├── Manufacturing Constraint (✓)
| | | ├── Solution (✓)
| | | | ├── Solution Information (✓)
| | | | | ├── Topology Density Tracker (✓)
| | | | ├── Topology Density (✓)
| | | | | ├── Smoothing (✓)
Clean up the project#
# Save the project file
mechdat_file = output_path / "cantilever_beam_topology_optimization.mechdat"
app.save(str(mechdat_file))
# Close the app
app.close()
# Delete the example files
delete_downloads()
True
Total running time of the script: (0 minutes 52.808 seconds)