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 matplotlib import image as mpimg
from matplotlib import pyplot as plt

from ansys.mechanical.core import App
from ansys.mechanical.core.examples import delete_downloads, download_file

if TYPE_CHECKING:
    import Ansys

Initialize the embedded application#

app = App(globals=globals())
print(app)
Ansys Mechanical [Ansys Mechanical Enterprise]
Product Version:252
Software build date: 06/13/2025 11:25:56

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")
topology optimization cantilever beam

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 cantilever beam

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"
)
topology optimization cantilever beam

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: Info
DisplayString: The requested license was received from the License Manager after 22 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"
)
topology optimization cantilever beam

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
)
_static/basic/Topo_opitimized.gif

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 39.837 seconds)

Gallery generated by Sphinx-Gallery