Note
Go to the end to download the full example code.
Compliant mechanism
Example of the design of a compliant mechanism using topology optimization
It considers the following conditions:
maximum output displacement due to input load
constrained minimum input and output stiffness
In this example of compliant mechanism design, no springs are required on input and output nodes. Also convergence is improved compared to Compliant mechanism (springs).
- References:
Koppen, S. (2022). Topology optimization of compliant mechanisms with multiple degrees of freedom. PhD thesis, Delft University of Technology. DOI: http://dx.doi.org/10.4233/uuid:21994a92-e365-4679-b6ac-11a2b70572b7
20 import numpy as np
21 import pymoto as pym
22
23 # Problem settings
24 nx, ny = 60, 60 # Domain size
25 xmin, filter_radius, volfrac = 1e-6, 2, 0.3 # Density settings
26 nu, E = 0.3, 100 # Material properties
27
28 # Values on max compliance on input and output for constraints
29 max_input_compliance = 10.0
30 max_output_compliance = 10.0
31
32 use_volume_constraint = False
33
34 if __name__ == "__main__":
35 # Set up the domain
36 domain = pym.VoxelDomain(nx, ny)
37
38 # Node and dof groups
39 nodes_left = domain.get_nodenumber(0, np.arange(ny + 1))
40 nodes_right = domain.get_nodenumber(nx, np.arange(ny + 1))
41
42 dofs_right = domain.get_dofnumber(nodes_right, [0, 1], ndof=2).flatten()
43 dofs_left_x = 2*nodes_left
44 dof_input = 2*nodes_left[0] + 1 # Input dof for mechanism
45 dof_output = 2*nodes_left[-1] + 1 # Output dof for mechanism
46
47 fixed_dofs = np.union1d(dofs_left_x, dofs_right)
48
49 # Setup rhs for two loadcases
50 f = np.zeros((domain.nnodes * 2, 2), dtype=float)
51 f[dof_output, 0] = 1.0
52 f[dof_input, 1] = 1.0
53
54 # Signal with design variables
55 s_x = pym.Signal('x', state=volfrac * np.ones(domain.nel))
56
57 # Setup optimization problem
58 with pym.Network() as fn:
59 # Density filtering
60 s_xfilt = pym.DensityFilter(domain, radius=filter_radius)(s_x)
61 s_xfilt.tag = 'Filtered density'
62
63 # Plot the design
64 pym.PlotDomain(domain, saveto="out/design")(s_xfilt)
65
66 # SIMP penalization
67 s_xsimp = pym.MathExpression(f"{xmin} + {1 - xmin}*inp0^3")(s_xfilt)
68
69 # Assembly of stiffness matrix
70 s_K = pym.AssembleStiffness(domain, e_modulus=E, poisson_ratio=nu, bc=fixed_dofs)(s_xsimp)
71
72 # Solve for the displacements
73 s_u = pym.LinSolve()(s_K, f)
74
75 # Output displacement due to force on input
76 s_uout = pym.EinSum('i,i->')(s_u[:, 1], f[:, 0])
77
78 # Objective is the displacement at the output
79 s_gobj = pym.Scaling(scaling=10.0)(s_uout)
80 s_gobj.tag = "Objective"
81
82 # Input and output compliances
83 s_compl = pym.EinSum('ij,ij->j')(s_u, f)
84
85 # Compliance constraint on input and output
86 s_gcompl_out = pym.Scaling(scaling=10.0, maxval=max_output_compliance)(s_compl[0])
87 s_gcompl_in = pym.Scaling(scaling=10.0, maxval=max_input_compliance)(s_compl[1])
88 s_gcompl_out.tag = "Output compliance constraint"
89 s_gcompl_in.tag = "Input compliance constraint"
90
91 # List of optimization responses: first the objective and all others the constraints
92 optimization_responses = [s_gobj, s_gcompl_out, s_gcompl_in]
93
94 # Add volume constraint if requested
95 if use_volume_constraint:
96 # Volume
97 s_vol = pym.EinSum('i->')(s_xfilt)
98 s_vol.tag = "Volume"
99
100 # Volume constraint
101 s_gvol = pym.Scaling(scaling=10.0, maxval=volfrac * domain.nel)(s_vol)
102 s_gvol.tag = "Volume constraint"
103
104 optimization_responses.append(s_gvol)
105
106 # Plot iteration history
107 pym.PlotIter()(*optimization_responses)
108
109 # Optimization
110 pym.minimize_mma(s_x, optimization_responses, verbosity=2)