Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Truss sizing optimisation

Authors
Affiliations
University of Luxembourg
University of Luxembourg
Rafinex
University of Luxembourg

This demo studies a sizing optimisation problem for an inverse truss bridge and shows how the dolfiny interface to PETSc/TAO can be used to minimise compliance under a volume constraint. It demonstrates a linear elastic truss model written in UFL, the generation of braced truss meshes, and the optimisation workflow for the bar cross-sectional areas.

In particular, this demo emphasizes:


Source

Generation of truss meshes

Truss structures make up an interesting example of the concept of geometric- and topological dimension, let those be denoted as dgd_g and dtd_t, which is also used throughout DOLFINx Baratta et al., 2023.

The geometric dimension is the dimension of the space in which the mesh T\mathcal{T} is embedded, dg∈{1,2,3}d_g \in \{ 1, 2, 3 \} and T⊂Rdg\mathcal{T} \subset \mathbb{R}^{d_g}, and the topological dimension is the dimension of the cells of the mesh in the reference configuration, dt=dim⁡(T^)d_t = \dim (\hat{T}) for T^\hat{T} the reference cell of T∈TT \in \mathcal{T}.

The usual finite element text-book setting applies to the case dt=dgd_t = d_g, for example a triangle mesh is only considered in R2\mathbb{R}^2 and not in R3\mathbb{R}^3.

Trusses are made up of lines, or, domain inspecifc, intervals, which are one-dimensional entities dt=1d_t=1 and form planar or volumetric structures, dg∈{2,3}d_g \in \{ 2, 3 \}. Here, we consider the volumetric case, dg=3d_g=3.

The bridge dimensions (length, height, width) are (100, 20, 10)(100,\, 20,\, 10) all in meters and we create the truss mesh from the edges of a (regular) hexahedral mesh, with trusses of size h=5h=5, and introduce all possible bracings to it. This is what the create_truss_x_braced_mesh functionality simplifies. Given a hexehedral mesh, it generates the edge skeleton together with all possible bracings.

Source

We create one functionspace Vu=P1(T)V_u = P_1(\mathcal{T}) for the displacement field u∈Vuu \in V_u and one for the cross sectional area ss of the trusses, which we model as constant over each element, so Vs=DG0(T)V_s = DG_0(\mathcal{T}).

Source

Boundary conditions and load surface

For the realisation of an inverse truss bridge, we will fix the trusses on the left and right top edges and apply a vertical load, i.e. in yy-direction, on the bridge deck, which we assume to span the whole upper surface/side of the truss mesh, excluding the fixed edges.

Source
<PIL.Image.Image image mode=RGB size=3840x2160>

Figure 1:Truss mesh with fixed supports (red spheres) and load-application vertices (green arrows).

Truss model and forward problem

We rely on a linear elastic truss model, following Bleyer, 2024. We choose a Young’s modulus of E=200 GPaE = 200\, \text{GPa} and apply a total load of 300 kN300\, \text{kN}, equally distributed across the loaded nodes.

Source
Output

Optimisation of cross-sectional areas

The truss sizing optimisation problem from Christensen & Klarbring, 2009 that we study is given (in reduced form) by

min⁡s∈VsC(u(s))subject tosmin≤s(x)≤smax, ∫Ωs dx=120∫Ωsmax dx\min_{s \in V_s} C(u(s)) \quad \text{subject to} \quad s_\text{min} \leq s(x) \leq s_\text{max}, \ \int_\Omega s \,\text{d}x = \frac{1}{20} \int_\Omega s_\text{max} \,\text{d}x

where uu is the unique displacement field associated with a given sizing ss.

For the bounds of the truss cross sectional area we consider an upper bound of smax=10−2 m2s_\text{max} = 10^{-2} \, \text{m}^2 and set the the lower bound to smin=10−3smaxs_\text{min} = 10^{-3} s_\text{max}.

Source
Output
# TAO   0 (ITERATING)
# sub   0 [  2k] |x|=5.117e-03 |J|=1.025e+07 (cross-sectional-area)
# all            |x|=5.117e-03 |J|=1.025e+07 |h|=0.000e+00 |Jh|=0.000e+00 f=1.961e+04
# TAO   1 (ITERATING)
# sub   0 [  2k] |x|=2.680e-02 |J|=2.897e+05 (cross-sectional-area)
# all            |x|=2.680e-02 |J|=2.897e+05 |h|=8.000e-01 |Jh|=3.984e+01 f=3.316e+03
# TAO   2 (ITERATING)
# sub   0 [  2k] |x|=3.489e-02 |J|=1.214e+05 (cross-sectional-area)
# all            |x|=3.489e-02 |J|=1.214e+05 |h|=8.368e-02 |Jh|=3.984e+01 f=2.142e+03
# TAO   3 (ITERATING)
# sub   0 [  2k] |x|=3.923e-02 |J|=7.770e+04 (cross-sectional-area)
# all            |x|=3.923e-02 |J|=7.770e+04 |h|=6.729e-02 |Jh|=3.984e+01 f=1.649e+03
# TAO   4 (ITERATING)
# sub   0 [  2k] |x|=4.556e-02 |J|=8.016e+04 (cross-sectional-area)
# all            |x|=4.556e-02 |J|=8.016e+04 |h|=5.449e-02 |Jh|=3.984e+01 f=1.390e+03
# TAO   5 (ITERATING)
# sub   0 [  2k] |x|=4.995e-02 |J|=4.299e+04 (cross-sectional-area)
# all            |x|=4.995e-02 |J|=4.299e+04 |h|=4.857e-02 |Jh|=3.984e+01 f=1.224e+03
# TAO   6 (ITERATING)
# sub   0 [  2k] |x|=5.493e-02 |J|=5.084e+04 (cross-sectional-area)
# all            |x|=5.493e-02 |J|=5.084e+04 |h|=4.832e-02 |Jh|=3.984e+01 f=1.109e+03
# TAO   7 (ITERATING)
# sub   0 [  2k] |x|=5.791e-02 |J|=2.629e+04 (cross-sectional-area)
# all            |x|=5.791e-02 |J|=2.629e+04 |h|=3.917e-02 |Jh|=3.984e+01 f=1.025e+03
# TAO   8 (ITERATING)
# sub   0 [  2k] |x|=6.400e-02 |J|=2.687e+04 (cross-sectional-area)
# all            |x|=6.400e-02 |J|=2.687e+04 |h|=3.706e-02 |Jh|=3.984e+01 f=9.325e+02
  Iteration information for truss solve.
  0 TAO,  Function value: 19614.4,  Residual: 0. 
  1 TAO,  Function value: 3315.56,  Residual: 289728. 
  2 TAO,  Function value: 2142.44,  Residual: 121362. 
  3 TAO,  Function value: 1648.92,  Residual: 77696.9 
  4 TAO,  Function value: 1390.03,  Residual: 80160.9 
  5 TAO,  Function value: 1223.78,  Residual: 42986.3 
  6 TAO,  Function value: 1109.08,  Residual: 50835.4 
  7 TAO,  Function value: 1025.34,  Residual: 26288.2 
  8 TAO,  Function value: 932.513,  Residual: 26873.7 
  9 TAO,  Function value: 884.561,  Residual: 19086.1 
# TAO   9 (ITERATING)
# sub   0 [  2k] |x|=6.679e-02 |J|=1.909e+04 (cross-sectional-area)
# all            |x|=6.679e-02 |J|=1.909e+04 |h|=2.624e-02 |Jh|=3.984e+01 f=8.846e+02
# TAO  10 (ITERATING)
# sub   0 [  2k] |x|=7.119e-02 |J|=1.721e+04 (cross-sectional-area)
# all            |x|=7.119e-02 |J|=1.721e+04 |h|=1.803e-02 |Jh|=3.984e+01 f=8.319e+02
# TAO  11 (ITERATING)
# sub   0 [  2k] |x|=7.406e-02 |J|=1.834e+04 (cross-sectional-area)
# all            |x|=7.406e-02 |J|=1.834e+04 |h|=1.140e-02 |Jh|=3.984e+01 f=8.017e+02
# TAO  12 (ITERATING)
# sub   0 [  2k] |x|=7.550e-02 |J|=1.698e+04 (cross-sectional-area)
# all            |x|=7.550e-02 |J|=1.698e+04 |h|=6.276e-03 |Jh|=3.984e+01 f=7.869e+02
# TAO  13 (ITERATING)
# sub   0 [  2k] |x|=7.800e-02 |J|=1.560e+04 (cross-sectional-area)
# all            |x|=7.800e-02 |J|=1.560e+04 |h|=7.674e-03 |Jh|=3.984e+01 f=7.638e+02
# TAO  14 (ITERATING)
# sub   0 [  2k] |x|=8.042e-02 |J|=2.733e+04 (cross-sectional-area)
# all            |x|=8.042e-02 |J|=2.733e+04 |h|=7.190e-03 |Jh|=3.984e+01 f=7.488e+02
# TAO  15 (ITERATING)
# sub   0 [  2k] |x|=7.972e-02 |J|=1.695e+04 (cross-sectional-area)
# all            |x|=7.972e-02 |J|=1.695e+04 |h|=5.554e-03 |Jh|=3.984e+01 f=7.519e+02
# TAO  16 (ITERATING)
# sub   0 [  2k] |x|=8.286e-02 |J|=1.616e+04 (cross-sectional-area)
# all            |x|=8.286e-02 |J|=1.616e+04 |h|=1.256e-02 |Jh|=3.984e+01 f=7.267e+02
# TAO  17 (ITERATING)
# sub   0 [  2k] |x|=8.459e-02 |J|=1.530e+04 (cross-sectional-area)
# all            |x|=8.459e-02 |J|=1.530e+04 |h|=9.076e-03 |Jh|=3.984e+01 f=7.131e+02
# TAO  18 (ITERATING)
# sub   0 [  2k] |x|=8.625e-02 |J|=1.531e+04 (cross-sectional-area)
# all            |x|=8.625e-02 |J|=1.531e+04 |h|=6.239e-03 |Jh|=3.984e+01 f=7.024e+02
# TAO  19 (ITERATING)
# sub   0 [  2k] |x|=8.817e-02 |J|=1.364e+04 (cross-sectional-area)
# all            |x|=8.817e-02 |J|=1.364e+04 |h|=6.252e-03 |Jh|=3.984e+01 f=6.900e+02
 10 TAO,  Function value: 831.9,  Residual: 17213.2 
 11 TAO,  Function value: 801.734,  Residual: 18340.9 
 12 TAO,  Function value: 786.914,  Residual: 16978.9 
 13 TAO,  Function value: 763.783,  Residual: 15603.5 
 14 TAO,  Function value: 748.808,  Residual: 27330.8 
 15 TAO,  Function value: 751.909,  Residual: 16953.3 
 16 TAO,  Function value: 726.702,  Residual: 16158.5 
 17 TAO,  Function value: 713.137,  Residual: 15300.6 
 18 TAO,  Function value: 702.44,  Residual: 15307.7 
 19 TAO,  Function value: 690.009,  Residual: 13636.7 
# TAO  20 (ITERATING)
# sub   0 [  2k] |x|=9.017e-02 |J|=1.290e+04 (cross-sectional-area)
# all            |x|=9.017e-02 |J|=1.290e+04 |h|=5.602e-03 |Jh|=3.984e+01 f=6.792e+02
# TAO  21 (ITERATING)
# sub   0 [  2k] |x|=9.085e-02 |J|=1.272e+04 (cross-sectional-area)
# all            |x|=9.085e-02 |J|=1.272e+04 |h|=4.684e-03 |Jh|=3.984e+01 f=6.756e+02
# TAO  22 (ITERATING)
# sub   0 [  2k] |x|=9.095e-02 |J|=1.282e+04 (cross-sectional-area)
# all            |x|=9.095e-02 |J|=1.282e+04 |h|=3.681e-03 |Jh|=3.984e+01 f=6.752e+02
# TAO  23 (ITERATING)
# sub   0 [  2k] |x|=9.136e-02 |J|=1.150e+04 (cross-sectional-area)
# all            |x|=9.136e-02 |J|=1.150e+04 |h|=3.492e-03 |Jh|=3.984e+01 f=6.735e+02
# TAO  24 (ITERATING)
# sub   0 [  2k] |x|=9.168e-02 |J|=1.198e+04 (cross-sectional-area)
# all            |x|=9.168e-02 |J|=1.198e+04 |h|=3.710e-03 |Jh|=3.984e+01 f=6.717e+02
# TAO  25 (ITERATING)
# sub   0 [  2k] |x|=9.173e-02 |J|=1.105e+04 (cross-sectional-area)
# all            |x|=9.173e-02 |J|=1.105e+04 |h|=2.905e-03 |Jh|=3.984e+01 f=6.723e+02
# TAO  26 (ITERATING)
# sub   0 [  2k] |x|=9.207e-02 |J|=1.189e+04 (cross-sectional-area)
# all            |x|=9.207e-02 |J|=1.189e+04 |h|=2.930e-03 |Jh|=3.984e+01 f=6.697e+02
# TAO  27 (ITERATING)
# sub   0 [  2k] |x|=9.192e-02 |J|=1.106e+04 (cross-sectional-area)
# all            |x|=9.192e-02 |J|=1.106e+04 |h|=2.255e-03 |Jh|=3.984e+01 f=6.714e+02
# TAO  28 (ITERATING)
# sub   0 [  2k] |x|=9.232e-02 |J|=1.304e+04 (cross-sectional-area)
# all            |x|=9.232e-02 |J|=1.304e+04 |h|=2.630e-03 |Jh|=3.984e+01 f=6.690e+02
# TAO  29 (ITERATING)
# sub   0 [  2k] |x|=9.202e-02 |J|=1.111e+04 (cross-sectional-area)
# all            |x|=9.202e-02 |J|=1.111e+04 |h|=2.285e-03 |Jh|=3.984e+01 f=6.717e+02
 20 TAO,  Function value: 679.203,  Residual: 12897.3 
 21 TAO,  Function value: 675.623,  Residual: 12722.1 
 22 TAO,  Function value: 675.236,  Residual: 12819.9 
 23 TAO,  Function value: 673.486,  Residual: 11504.3 
 24 TAO,  Function value: 671.741,  Residual: 11977.9 
 25 TAO,  Function value: 672.325,  Residual: 11052.9 
 26 TAO,  Function value: 669.717,  Residual: 11892.2 
 27 TAO,  Function value: 671.428,  Residual: 11061.6 
 28 TAO,  Function value: 668.967,  Residual: 13043.8 
 29 TAO,  Function value: 671.666,  Residual: 11109.6 
# TAO  30 (ITERATING)
# sub   0 [  2k] |x|=9.251e-02 |J|=1.214e+04 (cross-sectional-area)
# all            |x|=9.251e-02 |J|=1.214e+04 |h|=3.350e-03 |Jh|=3.984e+01 f=6.684e+02
# TAO  31 (ITERATING)
# sub   0 [  2k] |x|=9.254e-02 |J|=1.060e+04 (cross-sectional-area)
# all            |x|=9.254e-02 |J|=1.060e+04 |h|=2.472e-03 |Jh|=3.984e+01 f=6.680e+02
# TAO  32 (ITERATING)
# sub   0 [  2k] |x|=9.270e-02 |J|=1.110e+04 (cross-sectional-area)
# all            |x|=9.270e-02 |J|=1.110e+04 |h|=1.509e-03 |Jh|=3.984e+01 f=6.671e+02
# TAO  33 (ITERATING)
# sub   0 [  2k] |x|=9.269e-02 |J|=1.108e+04 (cross-sectional-area)
# all            |x|=9.269e-02 |J|=1.108e+04 |h|=9.265e-04 |Jh|=3.984e+01 f=6.673e+02
# TAO  34 (ITERATING)
# sub   0 [  2k] |x|=9.257e-02 |J|=1.119e+04 (cross-sectional-area)
# all            |x|=9.257e-02 |J|=1.119e+04 |h|=6.343e-04 |Jh|=3.984e+01 f=6.685e+02
# TAO  35 (ITERATING)
# sub   0 [  2k] |x|=9.270e-02 |J|=1.095e+04 (cross-sectional-area)
# all            |x|=9.270e-02 |J|=1.095e+04 |h|=1.099e-03 |Jh|=3.984e+01 f=6.675e+02
# TAO  36 (ITERATING)
# sub   0 [  2k] |x|=9.275e-02 |J|=1.083e+04 (cross-sectional-area)
# all            |x|=9.275e-02 |J|=1.083e+04 |h|=9.961e-04 |Jh|=3.984e+01 f=6.672e+02
# TAO  37 (ITERATING)
# sub   0 [  2k] |x|=9.280e-02 |J|=1.074e+04 (cross-sectional-area)
# all            |x|=9.280e-02 |J|=1.074e+04 |h|=7.644e-04 |Jh|=3.984e+01 f=6.669e+02
# TAO  38 (ITERATING)
# sub   0 [  2k] |x|=9.287e-02 |J|=1.063e+04 (cross-sectional-area)
# all            |x|=9.287e-02 |J|=1.063e+04 |h|=6.477e-04 |Jh|=3.984e+01 f=6.665e+02
# TAO  39 (ITERATING)
# sub   0 [  2k] |x|=9.290e-02 |J|=1.062e+04 (cross-sectional-area)
# all            |x|=9.290e-02 |J|=1.062e+04 |h|=4.391e-04 |Jh|=3.984e+01 f=6.663e+02
 30 TAO,  Function value: 668.425,  Residual: 12137.9 
 31 TAO,  Function value: 668.046,  Residual: 10600.2 
 32 TAO,  Function value: 667.115,  Residual: 11101.7 
 33 TAO,  Function value: 667.259,  Residual: 11075.2 
 34 TAO,  Function value: 668.547,  Residual: 11188.6 
 35 TAO,  Function value: 667.523,  Residual: 10951.6 
 36 TAO,  Function value: 667.194,  Residual: 10827.6 
 37 TAO,  Function value: 666.86,  Residual: 10735.4 
 38 TAO,  Function value: 666.458,  Residual: 10633.3 
 39 TAO,  Function value: 666.306,  Residual: 10621.7 
# TAO  40 (ITERATING)
# sub   0 [  2k] |x|=9.294e-02 |J|=1.042e+04 (cross-sectional-area)
# all            |x|=9.294e-02 |J|=1.042e+04 |h|=3.323e-04 |Jh|=3.984e+01 f=6.661e+02
# TAO  41 (ITERATING)
# sub   0 [  2k] |x|=9.295e-02 |J|=1.031e+04 (cross-sectional-area)
# all            |x|=9.295e-02 |J|=1.031e+04 |h|=2.759e-04 |Jh|=3.984e+01 f=6.660e+02
# TAO  42 (ITERATING)
# sub   0 [  2k] |x|=9.298e-02 |J|=1.024e+04 (cross-sectional-area)
# all            |x|=9.298e-02 |J|=1.024e+04 |h|=1.304e-04 |Jh|=3.984e+01 f=6.659e+02
# TAO  43 (ITERATING)
# sub   0 [  2k] |x|=9.298e-02 |J|=1.020e+04 (cross-sectional-area)
# all            |x|=9.298e-02 |J|=1.020e+04 |h|=7.083e-05 |Jh|=3.984e+01 f=6.658e+02
# TAO  44 (ITERATING)
# sub   0 [  2k] |x|=9.299e-02 |J|=1.020e+04 (cross-sectional-area)
# all            |x|=9.299e-02 |J|=1.020e+04 |h|=2.089e-05 |Jh|=3.984e+01 f=6.658e+02
# TAO  45 (ITERATING)
# sub   0 [  2k] |x|=9.301e-02 |J|=1.020e+04 (cross-sectional-area)
# all            |x|=9.301e-02 |J|=1.020e+04 |h|=8.790e-06 |Jh|=3.984e+01 f=6.658e+02
# TAO  46 (ITERATING)
# sub   0 [  2k] |x|=9.302e-02 |J|=1.020e+04 (cross-sectional-area)
# all            |x|=9.302e-02 |J|=1.020e+04 |h|=8.208e-06 |Jh|=3.984e+01 f=6.658e+02
# TAO  47 (ITERATING)
# sub   0 [  2k] |x|=9.303e-02 |J|=1.044e+04 (cross-sectional-area)
# all            |x|=9.303e-02 |J|=1.044e+04 |h|=1.212e-05 |Jh|=3.984e+01 f=6.659e+02
# TAO  48 (ITERATING)
# sub   0 [  2k] |x|=9.308e-02 |J|=1.041e+04 (cross-sectional-area)
# all            |x|=9.308e-02 |J|=1.041e+04 |h|=4.476e-05 |Jh|=3.984e+01 f=6.661e+02
 40 TAO,  Function value: 666.127,  Residual: 10415.9 
 41 TAO,  Function value: 665.983,  Residual: 10312.7 
 42 TAO,  Function value: 665.884,  Residual: 10236.7 
 43 TAO,  Function value: 665.836,  Residual: 10200.7 
 44 TAO,  Function value: 665.815,  Residual: 10203.6 
 45 TAO,  Function value: 665.803,  Residual: 10197.9 
 46 TAO,  Function value: 665.802,  Residual: 10203. 
 47 TAO,  Function value: 665.896,  Residual: 10443.8 
 48 TAO,  Function value: 666.117,  Residual: 10414.5 
 49 TAO,  Function value: 666.12,  Residual: 10337.5 
# TAO  49 (ITERATING)
# sub   0 [  2k] |x|=9.309e-02 |J|=1.034e+04 (cross-sectional-area)
# all            |x|=9.309e-02 |J|=1.034e+04 |h|=3.012e-04 |Jh|=3.984e+01 f=6.661e+02
Coefficient(FunctionSpace(Mesh(blocked element (Basix element (P, interval, 1, gll_warped, unset, False, float64, []), (3,)), 1), blocked element (Basix element (P, interval, 1, gll_warped, unset, False, float64, []), (3,))), 0)
Source

Convergence of the optimisation, that is the compliance and the volume vs. outer MMA iteration are shown below. Compliance is measured relative to the initial compliance C0C_0, which is compliance for the initial guess of sinit=10−2 m2s_\text{init} = 10^{-2} \, \text{m}^2. Volume is shown relative to the upper bound VmaxV_\text{max}.

Source
<Figure size 2560x1920 with 2 Axes>

Figure 2:Convergence of compliance (relative to initial, orange) and volume constraint residual (blue) over MMA iterations.

The deformed final design (displacement scaled by 5×1035\times10^3)

Source
<PIL.Image.Image image mode=RGB size=2048x1024>

Figure 3:Deformed final truss design, displacement scaled by 5×1035\times10^3.

Visualisation of the optimised truss structure, each truss plotted corresponding to optimisation result (opacity of tubes according to ratio of maximal allowed cross sectional area). Radii are scaled by factor of 5, for visualisation purposes.

Source
<PIL.Image.Image image mode=RGB size=2048x1024>

Figure 4:Optimised truss structure rendered as tubes; opacity encodes the ratio of cross-sectional area to the maximum allowed area. Radii scaled by 5.

References
  1. Baratta, I. A., Dean, J. P., Dokken, J. S., Habera, M., Hale, J. S., Richardson, C. N., Rognes, M. E., Scroggs, M. W., Sime, N., & Wells, G. N. (2023). DOLFINx: The next generation FEniCS problem solving environment. Zenodo. 10.5281/zenodo.10447666
  2. Bleyer, J. (2024). Numerical tours of Computational Mechanics with FEniCSx (v0.2) [Computer software]. Zenodo. 10.5281/zenodo.13838486
  3. Christensen, P. W., & Klarbring, A. (2009). Sizing Stiffness Optimization of a Truss. In An Introduction to Structural Optimization (pp. 77–95). Springer Netherlands. 10.1007/978-1-4020-8666-3_5