Note
Go to the end to download the full example code.
Compliance with prescribed displacements
Example of the design for stiffness of a structure subjected to prescribed displacements
This example peforms the topology optimization considering:
Maximum stiffness between prescribed displacements and support
Constrained by maximum volume
The optimization is similar to Compliance minimization, which applies a load instead of a prescribed displacement. When optimizing for a maximum stiffness design, the compliance \(c=\mathbf{u}\cdot\mathbf{f}\) must be minimized when applying a load, while it must be maximized when a displacement is prescribed.
To solve a system of equations with applied displacement, the pymoto.SystemOfEquations module is used.
- References:
Koppen, S., Langelaar, M., & van Keulen, F. (2022). A simple and versatile topology optimization formulation for flexure synthesis. Mechanism and Machine Theory, 172, 104743. DOI: http://dx.doi.org/10.1016/j.mechmachtheory.2022.104743
25 import numpy as np
26 import pymoto as pym
27
28 # Problem settings
29 nx, ny = 40, 40 # Domain size
30 xmin, filter_radius, volfrac = 1e-9, 2, 0.5 # Density settings
31 nu, E = 0.3, 1.0 # Material properties
32
33 if __name__ == "__main__":
34 # Set up the domain
35 domain = pym.VoxelDomain(nx, ny)
36
37 # Node and dof groups
38 nodes_left = domain.nodes[0, :].flatten()
39 nodes_right = domain.nodes[-1, :].flatten()
40 dofs_left_x = domain.get_dofnumber(nodes_left, 0, 2).flatten()
41 dofs_left_y = domain.get_dofnumber(nodes_left, 1, 2).flatten()
42 dofs_right = domain.get_dofnumber(nodes_right, np.arange(2), 2).flatten()
43
44 all_dofs = np.arange(0, 2 * domain.nnodes)
45 prescribed_dofs = np.unique(np.concatenate([dofs_left_x, dofs_right, dofs_left_y]))
46 free_dofs = np.setdiff1d(all_dofs, prescribed_dofs)
47
48 # Setup solution vectors and rhs
49 ff = np.zeros_like(free_dofs, dtype=float)
50 u = np.zeros_like(all_dofs, dtype=float)
51
52 u[dofs_left_y] = 1.0
53 up = u[prescribed_dofs]
54
55 # Initial design
56 s_x = pym.Signal('x', state=volfrac * np.ones(domain.nel))
57
58 # Setup optimization problem
59 with pym.Network() as fn:
60 # Density filtering
61 s_xfilt = pym.DensityFilter(domain, radius=filter_radius)(s_x)
62 s_xfilt.tag = 'xfiltered'
63
64 # SIMP penalization
65 s_xsimp = pym.MathExpression(f"{xmin} + {1 - xmin}*inp0^3")(s_xfilt)
66
67 # Matrix assembly
68 s_K = pym.AssembleStiffness(domain, e_modulus=E, poisson_ratio=nu)(s_xsimp)
69
70 # Solve system of equations
71 s_u, s_f = pym.SystemOfEquations(prescribed=prescribed_dofs)(s_K, ff, up)
72
73 # Calculate compliance value
74 s_c = pym.EinSum('i,i->')(s_u, s_f)
75
76 # Objective function (note the sign!)
77 s_gobj =pym.Scaling(scaling=-1)(s_c)
78 s_gobj.tag = "Objective"
79
80 # Volume
81 s_vol = pym.EinSum('i->')(s_xfilt)
82 s_vol.tag = "volume"
83
84 # Volume constraint
85 s_gvol = pym.Scaling(scaling=10.0, maxval=volfrac * domain.nel)(s_vol)
86 s_gvol.tag = "Volume constraint"
87
88 # Plotting
89 pym.PlotDomain(domain, saveto="out/design")(s_xfilt)
90 optimization_responses = [s_gobj, s_gvol]
91 pym.PlotIter()(*optimization_responses)
92
93 # Run optimization
94 pym.minimize_mma(s_x, optimization_responses, verbosity=2)