Compliant mechanism (static condensation)

Usage of static condensation to design a compliant mechanism

This example uses pymoto.StaticCondensation to calculate the mechanism and constraint mode compliances in an efficient way. The optimization problem considers

  1. Maximum stiffness of input and output ports

  2. Desired geometric advantage specified by the user

  3. Desired maximum stiffness of the compliant deformation pattern

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

 19 import numpy as np
 20 import pymoto as pym
 21
 22 # Problem settings
 23 nx, ny = 100, 100  # Domain size
 24 xmin, filter_radius, volfrac = 1e-6, 2, 0.35  # Density settings
 25 nu, E = 0.3, 100  # Material properties
 26
 27 u_desired = np.array([1.0, -1.1])  # Intended geometric advantage of the mechanism [u_in, u_out]
 28
 29 compliance_constraint_value = 0.1  # Maximum compliance of the requested mechanism mode
 30 use_volume_constraint = True
 31
 32 if __name__ == "__main__":
 33     # Set up the domain
 34     domain = pym.VoxelDomain(nx, ny)
 35
 36     # Node and dof groups
 37     nodes_left = domain.nodes[0, :].flatten()
 38     nodes_right = domain.nodes[-1, :].flatten()
 39
 40     dofs_right = domain.get_dofnumber(nodes_right, [0, 1], ndof=2).flatten()
 41     dofs_left_x = 2*nodes_left
 42
 43     dof_input = 2*nodes_left[0] + 1  # Input dof for mechanism
 44     dof_output = 2*nodes_left[-1] + 1  # Output dof for mechanism
 45
 46     all_dofs = np.arange(0, 2 * domain.nnodes)
 47     prescribed_dofs = np.array(list({*dofs_left_x, *dofs_right}))
 48     io_dofs = np.array([dof_input, dof_output])
 49     free_dofs = np.setdiff1d(all_dofs, np.concatenate([io_dofs, prescribed_dofs]))
 50
 51     # Signal with design variables
 52     s_x = pym.Signal('x', state=volfrac * np.ones(domain.nel))
 53
 54     # Setup optimization problem
 55     with pym.Network() as fn:
 56         # Density filtering
 57         s_xfilt = pym.DensityFilter(domain, radius=filter_radius)(s_x)
 58         s_xfilt.tag = 'Filtered density'
 59
 60         # Plot the design
 61         pym.PlotDomain(domain, saveto="out/design")(s_xfilt)
 62
 63         # SIMP penalization
 64         s_xsimp = pym.MathExpression(f"{xmin} + {1 - xmin}*inp0^3")(s_xfilt)
 65
 66         # Assembly of stiffness matrix
 67         s_K = pym.AssembleStiffness(domain, e_modulus=E, poisson_ratio=nu)(s_xsimp)
 68
 69         # Static condensation of the dofs of interest
 70         s_Kr = pym.StaticCondensation(main=io_dofs, free=free_dofs)(s_K)
 71
 72         # Compliance of the mechanism mode
 73         s_cmech = pym.EinSum('i,ik,k->')(u_desired, s_Kr, u_desired)
 74
 75         # Compliance constraint on the mechanism mode
 76         s_gcmech = pym.Scaling(scaling=10.0, maxval=compliance_constraint_value)(s_cmech)
 77         s_gcmech.tag = "Mechanism compliance"
 78
 79         # Inverse of the reduced stiffness matrix (=compliance matrix)
 80         s_Y = pym.Inverse()(s_Kr)
 81
 82         # Sum the diagonal only (input and output compliance); off-diagonal terms are input-output compliance
 83         s_c = pym.EinSum('ii->')(s_Y)
 84
 85         # Objective function
 86         s_gobj = pym.Scaling(scaling=100.0)(s_c)
 87         s_gobj.tag = "Objective"
 88
 89         # List of optimization responses: first the objective and all others the constraints
 90         optimization_responses = [s_gobj, s_gcmech]
 91
 92         # Add volume constraint if requested
 93         if use_volume_constraint:
 94             # Volume
 95             s_vol = pym.EinSum('i->')(s_xfilt)
 96             s_vol.tag = "Volume"
 97
 98             # Volume constraint
 99             s_gvol = pym.Scaling(scaling=10.0, maxval=volfrac * domain.nel)(s_vol)
100             s_gvol.tag = "Volume constraint"
101
102             optimization_responses.append(s_gvol)
103
104         # Plot iteration history
105         pym.PlotIter()(*optimization_responses)
106
107     # Optimization
108     pym.minimize_mma(s_x, optimization_responses, verbosity=2)

Gallery generated by Sphinx-Gallery