Available via license: CC BY 4.0

Content may be subject to copyright.

A 55-line code for large-scale parallel topology optimization in 2D and 3D

Abhinav Guptaa, Rajib Chowdhurya,1,∗

, Anupam Chakrabartia,2, Timon Rabczukb

aDepartment of Civil Engineering, Indian Institute of Technology Roorkee, India

bInstitute of Structural Mechanics, Bauhaus-Universit¨at Weimar, 99423 Weimar, Germany

Abstract

This paper presents a 55-line code written in python for 2D and 3D topology optimization (TO) based

on the open-source ﬁnite element computing software (FEniCS), equipped with various ﬁnite element tools

and solvers. PETSc is used as the linear algebra back-end, which results in signiﬁcantly less computational

time than standard python libraries. The code is designed based on the popular solid isotropic material

with penalization (SIMP) methodology. Extensions to multiple load cases, diﬀerent boundary conditions,

and incorporation of passive elements are also presented. Thus, this implementation is the most compact

implementation of SIMP based topology optimization for 3D as well as 2D problems.

Utilizing the concept of Euclidean distance matrix to vectorize the computation of the weight matrix

for the ﬁlter, we have achieved a substantial reduction in the computational time and have also made it

possible for the code to work with complex ground structure conﬁgurations. We have also presented the

code’s extension to large-scale topology optimization problems with support for parallel computations on

complex structural conﬁguration, which could help students and researchers explore novel insights into

the TO problem with dense meshes. Appendix A contains the complete code, and the website: https:

//github.com/iitrabhi/topo-fenics also contains the complete code.

Keywords: Topology optimization, FEniCS, Parallel computing, Scalability, Education

1. Introduction

The primary purpose of structural topology optimization is to generate an optimal design - by removing

material from the design domain - which should eﬀectively comply with its intended design objectives and,

at the same time satisﬁes the constraints imposed upon it. The development of high-performance structural

topology optimization methods would result in low-cost, lightweight, and high-performance structures. For

∗Corresponding author

Email addresses: agupta1[at]ce.iitr.ac.in (Abhinav Gupta), rajibfce[at]iitr.ac.in,

rajibchowdhury[at]ce.iitr.ac.in (Rajib Chowdhury), anupam.chakrabart[at]ce.iitr.ac.in (Anupam Chakrabarti),

timon.rabczuk[at]uni-weimar.de (Timon Rabczuk)

1Tel.: (+91) 1332-285612

2Tel.: (+91) 1332-285844

Preprint submitted to Elsevier December 16, 2020

arXiv:2012.08208v1 [cs.MS] 15 Dec 2020

the ﬁrst time, Bendsøe and Kikuchi [20] presented the theory for topology optimization of continuum struc-

tures. The initial works were based on the homogenization or micro-structure approach. This approach

provides criteria for topology optimization using composite materials to describe diﬀerent material prop-

erties where each element is a micro-structure for a given homogeneous, isotropic material. However, the

determination and evaluation of optimal micro-structures and their orientations are cumbersome [20].

In contrast, the Solid Isotropic Material with Penalization(SIMP) approach proposed by Bendsøe [18],

Zhou and Rozvany [75], Mlejnek [51] suggest a relation between the design density variable and the material

property based on the power-law, which results in improving the convergence of the solution. Because of

the ease of implementation and straightforward description of the design density variable, this approach

has grown in popularity among the research community. It is generally the preferred way to learn and

understand the working philosophy of topology optimization. Gradient-based optimization algorithms have

become the preferred way to solve the smooth and diﬀerentiable topology optimization problem represented

by the SIMP approach[21,63,62,64,66,65]. Topology optimization method has also been recently studied

with the iso-geometric approach [37,54,32,35] and mixed FEM approach [53,52]

The classical 99-line MATLAB code for topology optimization of continuum structures [63] lead to a

plethora of eﬃcient implementations of topology optimization in various programming languages utilizing dif-

ferent methods. The initial code - which was based on SIMP method - has helped many researchers to develop

their own implementations with SIMP [38,67,12,60,69,43], Level Set[72,24,30,57,73,36,56,58,32,33,

46], reaction-diﬀusionseongReactiondiﬀusionEquationBased2018a,jeongStructuralDesignConsidering2019, Bi-

Directional Evolutionary Structural Optimization[77,76,49] and Moving Morphable Component[74]. Fur-

ther Schmidt and Schulz [60], Aage et al. [5], Aage and Lazarov [1], Aage et al. [3], Amir et al. [11] have

proposed eﬃcient and parallelizable codes to carry out large scale topology optimization simulations. Re-

cently a new generation 99 line MATLAB code was presented by Ferrari and Sigmund [29]. Readers are

referred to [73] for a comprehensive review of all the educational codes available in literature. These codes

have proved to be an integral part of the learning process for many researchers who wish to understand and

implement topology optimization in their work.

The attractive primary property of these codes is that they are easy to understand and modify. However,

to achieve readability and compactness, most of the proposed codes are limited to speciﬁc problems. Works

by Zuo and Xie [77], Chen et al. [26] have helped expand the applicability of the codes to complex problems

using ABAQUS and ANSYS. These works have made it possible to take advantage of the linear/nonlinear,

static/dynamic FEA capacities, and meshing techniques present in the commercial package but then loose

on the ﬂexibility provided by custom implementations. Further, this limits the extension of these codes by

the researches who do not have access to the commercial packages.

In this paper, we have presented a 55-line code for carrying out SIMP based topology optimization in

FEniCS. The intention of this code is to stay true to the the original so that researchers and students

2

who are already familiar with the topic ﬁnd it easy to understand an implement in their workﬂow. We

propose the use of Euclidean distance matrices to vectorize the computation of distance matrices for ﬁlter.

This results in substantial reduction in computational time for evaluation of the ﬁlter. Moreover, this

method supports complex structural conﬁgurations. We also present the extension of the code to large scale

complex engineering structure with support for parallelization. Thus, this compact code could help students

and researchers learn and understand the concept of TO on their laptops and then extend the same to

handle complex 3D structures on large high-performance computers.

This manuscript is structured as follows. Section 2 addresses the theoretical aspects of the variational

formulation of the linear elasticity problem and discusses the SIMP approach. Section 3 presents the

mathematical model of the topology optimization problem. We discuss the continuous and discontinuous

Lagrange elements used for discretization and then present the problem’s weak form. We then discuss the

optimization approach, the mesh independency ﬁlter, and the Euclidean distance matrix (used to vectorize

the loops for calculating the distance matrix for the mesh independency ﬁlter). In Section 4, we present a

detailed step by step description of our FEniCS implementation. Section 5 includes the model extensions

of the code to a 3D problem, diﬀerent load cases, diﬀerent boundary conditions, and inclusion of passive

elements. Finally, we summarize the ﬁndings, in Section 7.

2. Topology optimization formulation

We consider an arbitrarily shaped linear elastic body Ωmat which is part of a large reference domain

Ω⊂Rδ, δ = 2,3, having boundary Γ, as illustrated in Fig. 1. The reference domain Ω (ground structure)

is chosen to allow for a deﬁnition of applied loads and boundary conditions. The displacement at a point

x∈Ω is represented by u(x). The Dirichlet and Neumann boundaries of the domain Ω are represented

by ΓDand ΓN, respectively. Let FB⊂Rδ, δ = 2,3 represent the body force vector and FT⊂Rδ, δ = 2,3

represent the traction force on the on the traction part ΓT⊂Γ, of the boundary. The ground structure

could consist of zones with no material(such as holes), or zones with ﬁxed material. FEniCS works based

on the variational formulation of the problem, and thus in this section we discuss the variational approach

to topology optimization problem.

2.1. Governing equations and weak form

Elastic strain energy is the energy stored at the time of deformation inside an elastic body. When an

isotropic linear elastic solid is deformed under small strain condition, the strain energy density function

ψ0() is deﬁned as:

ψ0() = λ

2(tr[])2+µtr[2] (1)

3

No MaterialGround Structure

Design Point Fixed Material

Figure 1: Structural topology optimization problem deﬁnition. The ground structure is chosen to allow for a deﬁnition of

applied loads and boundary conditions. It could consist of zones with no material or zones with ﬁxed material.

where µ, λ > 0 are the Lam´e parameters, =1

2(∇u+∇uT) = sym(∇u), is deﬁned as the symmetric part

of the tensor ∇u. The total strain energy is thus deﬁned as:

SE =ZΩ

ψ0()dΩ (2)

The work potential is deﬁned as the potential of the external loads, which is the negative of the work done

on the system. The work potential is given by

W P =−ZΩ

u.FBdΩ −ZΓ

u.FTdΓ (3)

The potential energy of the system is deﬁned as the sum of elastic energy and work potential. The total

potential energy for a deformed body is thus given by:

U=ZΩ

ψ0()dΩ −ZΩ

u.FBdΩ −ZΓ

u.FTdΓ (4)

For calculating displacement ﬁeld the principle of minimum potential energy is used. Thus, by taking

the ﬁrst variation of Uand then applying the fundamental lemma of the calculus of variation, we get:

Governing diﬀerential equation:

∇ · σ=−FBin Ω (5)

Natural boundary condition:

(σ.n) = FTon Γ(6)

In the SIMP method, we introduce a pseudo density d∈[0,1] into Eq. (5) to model the distribution of the

material within the ground structure.

dp∇.σ=FB(7)

4

Figure 2: Finite elements - 2D. (a)three noded triangular Lagrangian element with two degrees of freedom per node used to

model the displacement vector. (b) one noded discontinuous Lagrangian element used to model the density parameter.

In Eq. (7),pis the penalty parameter that helps in enforcing a 0/1 density distribution by signiﬁcantly

reducing the eﬀect of intermediate values. Based on the power-law approach we could now deﬁne the

topology optimization problem, where the objective is to minimize the strain energy and the volume is

constrained.

minimize

df(d) = dpU

subject to g(d) = ZΩ

d.V0dΩ −k.V0≤0

∀d∈D,D={d∈L2(Ω) : dmin < d ≤1}

(8)

In Eq. (8),Uis the strain energy of the domain and V0is the initial volume. kis the prescribed volume

fraction.

3. Numerical Approximation

The linear elasticity model, as described by the diﬀerential equation (refer Eq. (5)), is discretized by the

ﬁnite element method. We start with a discussion on weak form and the discrete form of the system. Then

we discuss the optimization algorithm and the ﬁlter used in the method to avoid the checkerboard pattern.

3.1. Spatial discretization

We use ﬁrst degree C0Lagrangian ﬁnite elements to discretize the domain and the primary ﬁeld variable.

The density parameter is discretized with the help of zeroth degree, C−1discontinuous Galerkin elements. In

the 2 dimensional cases, the three noded triangular Lagrangian ﬁnite elements have two degrees of freedom

per node, whereas the discontinuous Lagrangian element of degree zero have a single value per element and

are represented as shown in Fig. 2. For the 3 dimensional case, the four noded tetrahedral Lagrangian ﬁnite

element have three degrees of freedom per node, whereas the discontinuous Lagrangian elements of degree

zero have a single value per element and are represented as shown in Fig. 3.

5

Figure 3: Finite elements - 3D. (a) four noded tetrahedral Lagrangian element with three degrees of freedom per node used to

model the displacement vector. (b) one noded discontinuous Lagrangian element used to model the density parameter.

Remark. Triangular and tetrahedral elements are used for the current implementation as they are well

supported in FEniCS, whereas the support for quadrilateral and hexahedral elements, even though present

is somewhat limited. For simple formulations, user could switch to quadrilateral and hexahedral elements

to reduce the computational expense.

3.1.1. Weak form

The weak form of the system is derived by ﬁrst multiplying the governing diﬀerential equation (refer

Eq. (5)) by admissible test function (v) and then modiﬁcation of the equations with the application of

Green’s theorem. The weak form of the system is deﬁned as: Find u∈Usuch that

ZΩ

dpσ(u) : ∇vdΩ=0 ∀v∈b

U(9)

In Eq. (9), one usually uses only the symmetric part of the test function (virtual strain, (v)=1/2(∇v+

∇vT) as RΩσ(u) : (∇v)skewsym dΩ = 0.

ZΩ

dpσ(u) : (v)dΩ=0 ∀v∈b

U(10)

The trial (U) and test ( b

U) spaces are deﬁned as

(U,b

U) = {(u,v)∈H1(Ω) : u=u&v= 0 on ΓD}(11)

In Eq. (11),H1(Ω) denotes the usual Hilbert space over the domain Ω and uis the prescribed displace-

ment.

3.1.2. Discrete form

The weak form of the system as presented by Eq. (9) is discretized by using C0Lagrangian elements

for displacement vector and C−1discontinuous Lagrangian elements for density. The discrete form of the

6

problem is thus deﬁned as: Find (uh)∈Uh⊂(U) such that

ZΩ

dp

hσ(uh) : (v)dΩ=0 ∀v∈b

Uh⊂b

U(12)

We follow the Bubnov-Galerkin formulation, where the test and trial functions belong to the same

function space. Continuous ﬁeld variables are thus approximated as:

u(x)≈uh(x) =

n

X

i=1

Niui(13)

where ndenotes the number of nodes in the mesh, uiand Niare the displacement vector and basis

function corresponding to ith node, respectively.

3.2. Optimization algorithm

The optimization problem as described in Eq. (8) is solved using the standard optimality criteria (OC)

method. The OC method states that convergence is achieved when the KKT condition is satisﬁed [43],

∂f (d)

∂de

+λ∂g(d)

∂de

= 0 (14)

In Eq. (14) λis the Lagrange multiplier associated with the constraint g(d). This optimality condition

can be expressed as Be= 1, where

Be=−∂f (d)

∂deλ∂g(d)

∂de−1

(15)

According to [19] a heuristic updating scheme for the design variables can be formulated as:

dnew

e=

max (dmin, de−m) if deBη

e≤max (dmin, de−m)

min (1, de+m) if deBη

e≥min (1, de+m)

deBη

eotherwise

(16)

In Eq. (16),mis a positive move-limit, and ηis a numerical damping coeﬃcient. The choice of m= 0.2

and η= 0.5 is recommended [19,63].

3.2.1. The bisection method

We use the bisection method to ﬁnd the Lagrange multiplier λ. The Lagrange multiplier should satisfy

the constraint function g(d), i.e. the new value of density parameter evaluated with Eq. (16) should satisfy

the condition

g(d(λ)) = 0 (17)

Numerically, this could be achieved by the bisection method in which we assume a lower bound and upper

bound on the value of λand calculate the value of constraint function at mid-point of that interval. If

the convergence is satisfactory (i.e. the length of the interval is small), then stop the iteration and return

7

mid-point as solution. Otherwise, examine the sign of the constraint function and update the lower-bound

with mid-point if the sign is positive else update the upper-bound with mid-point value.

The sensitivity of the objective function is deﬁned as

∂f (d)

∂d =−pdp−1U(18)

The derivative of the volume constraint g(d) in Eq. (8) with respect to the design variable dis given

∂g(d)

∂d =ZΩ

V0dΩ (19)

3.2.2. Mesh-independency ﬁlter

The solution of topology optimization problems is mesh-dependent. To circumvent this issue, researchers

have proposed sensitivity ﬁlters that ensure mesh-independency. The ﬁlter works by modifying the sensitivity

of a speciﬁc element’s objective function by taking the weighted average of the element sensitivities in a

ﬁxed neighborhood.

∂(daEa)

∂da

=1

PN

b=1 Wb

N

X

b=1

Wb

∂(dbEb)

∂db

(20)

∂(Ea)

∂da

=1

daPN

b=1 Wb

N

X

b=1

Wbdb

∂(Eb)

∂db

(21)

Here the letter 0a0represents the element under consideration (marked as red in Fig. 4) and the letter

0b0represents the elements in the neighborhood of element 0a0(marked with red X marks in the Fig. 4).

The elements in the neighborhood are identiﬁed as the ones whose center lies inside a circle of radius rmin

as shown in the Fig. 4.Wbis the weight factor (also known as the convolution operator) assigned to the

element 0b0, which decays linearly with increasing distance from element 0a0and is deﬁned as:

Wb=rmin −dist(b, a),{b∈N|dist(b, a)≤rmin)}, b = 1, ..., N . (22)

In Eq. (22),dist(b, a) is the distance operator that calculates the distance between the midpoints of the

element 0b0and element 0a0. The weight factor is zero outside the zone deﬁned by the circle with a radius

rmin.

3.3. Numerical implementation

The numerical simulations are performed using the python interface of the open-source scientiﬁc com-

puting platform FEniCS [45,10,44,40,55,9,39,8,16,22]. To solve the algebraic equations, FEniCS is

conﬁgured with PETSc [15,17,6] as the linear algebra backend. The output of the topology optimization

problem is written to a XDMF ﬁle and Paraview [7] is used to visualize the output.

All the two dimensional analyses were performed on a Windows laptop equipped with an Intel Core i7

processor with a clock frequency of 2.2GHz having six cores and 16GB of RAM. The three dimensional

8

Figure 4: Mesh-independency ﬁlter. (top)Elements (eleb) in the neighborhood of eleaconsidered for the density ﬁltering.

(bottom) Variation of the weight factor (Wb) with increasing distance from elea. Note that the weight factor is zero outside

the ﬁlter zone marked by rmin

9

180

60

Figure 5: Cantilever beam problem. (a)The design domain, boundary conditions, and external load for the optimization of a

cantilever beam. (b) Topologically optimized structure.

analysis were performed on a workstation equipped with two Intel Xeon Platinum 8260 M processor with a

clock frequency of 2.4 GHz having 24 cores per processor amounting to a total of 48 cores and memory is

128 GB.

4. FEniCS implementation

In this section, the 55-line FEniCS code for the energy minimization problem is explained in detail.

Several assumptions were made to simplify the code in the previous compact codes (99-line and 88-line).

Thus, the codes were limited to a certain kind of problem, and changing them to 3D would require signiﬁcant

modiﬁcation of the codebase.

The intention of the current implementation is to take advantage of the highly popular programming

language python, which is known for its compactness and readability, and to create the most compact

implementation of topology optimization by utilizing the open-source FEM package FEniCS. FEniCS allows

us to describe the FEM problem in terms of variational principles, keeping the python implementation as

close to the mathematical description as possible. This also helps us to improve the readability of the code

when comparing it to the mathematical description. The code is called from the python prompt employing

the following lines:

from topopt import main

main(nelx=180, nely=60, volfrac=0.5, penal=3.0, rmin=2.0)

where nelx and nely are the number of elements in the horizontal and vertical direction, respectively,

volfrac is the prescribed volume fraction k,penal is the penalization power p,rmin is the ﬁlter radius

rmin.Fig. 1(a) shows the domain and boundary conditions for a cantilever beam as an example that would

be used to describe the code.

10

4.1. Header

The ﬁrst line imports all the key classes and methods necessary for solving a ﬁnite element variational

form in FEniCS. The dolﬁn library is a part of the FENiCS package, which in itself is a wrapper for the

C++ library DOLFIN that provides eﬃcient and highly scalable C++ classes for ﬁnite element computing.

Thus, the package beneﬁts from the speed and eﬃciency of C++ while keeping the programming for the

end-user in an easy to understand and highly readable programming language (python). The second line

imports the two packages necessary for performing matrix operations.

from dolfin import *

import numpy as np, sklearn.metrics.pairwise as sp

4.2. Function declaration

In FEniCS we solve a problem by deﬁning the variational formulation with Uniﬁed Form Language

(UFL). This allows us to deﬁne the formulas in python that are very similar to the mathematical description

and thus makes the code highly readable. The Cauchy stress tensor and the strain energy of the system are

described as

σ=λtr ()I+ 2µ(23)

ψ0() = λ

2(tr[])2+µtr[2] (24)

In Eqs. (23) and (24), strain (=1

2(∇u+∇uT) = sym(∇u)), is deﬁned as the symmetric part of the part

of ∇u. Note the very close correspondence between the mathematical formulas and their equivalent UFL

descriptions. This is the core strength of FEniCS that we wish to exploit to the fullest to make the most

compact code of topology optimization.

sigma = lambda _u: 2.0 * mu * sym(grad(_u)) + lmbda * tr(sym(grad(_u))) * Identity(len(_u))

psi = lambda _u: lmbda / 2 * (tr(sym(grad(_u))) ** 2) + mu * tr(sym(grad(_u)) * sym(grad(_u)))

4.3. Finite element analysis

Most of the codes available in the literature follow the approach of the matrix method, wherein they

derive the stiﬀness matrix and force vectors and then code them into the programming language. FEniCS is

based on the variational approach, where the user needs to specify the variational form with UFL and then

use the built-in operators and methods to generate all the required matrices and vectors automatically. This

process is initiated by creating function spaces over the mesh and then deﬁning functions in that function

space. The supports and loads are then deﬁned based on the function space and functions. Finally, a linear

variational problem and a solver are deﬁned.

11

4.3.1. Discretization the problem

We ﬁrst start discretizing the problem by deﬁning the domain under consideration with the built in

function RectangularMesh. The mesh is made up of triangular elements. The parameters nelx and nely

tell the program to divide the domain into nelx and nely unit rectangles in x and y directions respectively.

Each of the unit rectangle is then divided into two triangles and the last argument decides the direction for

the division of the rectangles.

mesh = RectangleMesh(Point(0, 0), Point(nelx, nely), nelx, nely, "right/left")

U = VectorFunctionSpace(mesh, "CG", 1)

D = FunctionSpace(mesh, "DG", 0)

u, v = TrialFunction(U), TestFunction(U)

u_new, density, density_old = Function(U), Function(D), Function(D)

As discussed in Section 3.1 the topology optimization problem consists of two primary variables, the dis-

placement vector (u), and the density parameter (d) which is constant over the element and is discontinuous

over the edges. Thus, to discretize the problem with ﬁnite element method we need to deﬁne two function

spaces over the mesh. The ﬁrst one is deﬁned using the CG elements over the mesh and creating a vector

function space of degree one. This implies that the element is a 3-noded linear triangle with two degrees of

freedom at each node. For the density parameter we deﬁne a function space with DG elements. Once we

have deﬁned the function space we can deﬁne the test and trial functions over the space which are required

to deﬁne the weak form of the variational problem. Then we deﬁne functions which are used to store the

solution to the problem.

4.3.2. Deﬁnition of supports

The supports are ﬁrst identiﬁed inside the mesh with the CompiledSubdomain method that takes in a

condition in C++ syntax and then at compile time converts the expression into an eﬃcient compiled C++

function. In the case of a cantilever beam ﬁxed at x=0 the support is deﬁned by the following command.

support = CompiledSubDomain("near(x[0], 0.0, tol) && on_boundary", tol=1e-14)

bcs = [DirichletBC(U, Constant((0.0, 0.0)), support)]

The C++ expression takes a point vector xas input, where the vector elements represent the x, y, and

z coordinates. The support nodes are identiﬁed by a conditional statement based on the point vector.

The Dirichlet boundary condition is then deﬁned - over the nodes identiﬁed by the function support - by

assigning a value of zero to the components of the displacement vector over the vector function space U

(u= 0 on ΓD).

12

4.3.3. Deﬁnition of loads

The load boundary is identiﬁed with the help of load_marker. This is achieved in FEniCS with the help

of MeshFunction method. We mark the mesh entities with integer markers. We then use those integers in

the measures (dx and ds) to identify the region in our variational form. In UFL, dx represents the integral

over the whole cell whereas ds represents the integral over the exterior facet of the cell. In our case suppose

the load is applied over the bottom two elements of the mesh. This is achieved by ﬁrst identifying the

bottom two elements with the load marker and then updating the measure ds to account for the markers.

After that we deﬁne the right hand f.vds with the command.

load_marker = MeshFunction("size_t", mesh, 1)

CompiledSubDomain("x[0]==l && x[1]<=2", l=nelx).mark(load_marker, 1)

ds = Measure("ds")(subdomain_data=load_marker)

F = dot(v, Constant((0.0, -1.0))) * ds(1)

4.3.4. Deﬁning the variational problem and solver

The bilinear form of the systems as described by Eq. (12) is deﬁned ﬁrst and then we deﬁne the

LinearVariationalProblem and LinearVariationalSolver objects. Deﬁning the problem and solver ob-

jects allows the program to automatically update the primary ﬁeld variable and thus inturn the discrete

form of the system. Thus, we can solve the system inside a loop by simply calling the solve() method

over the solver object. The call to solve() will create the stiﬀness matrix and the force vector and will not

dispose of them immediately after execution, which allows the program to reuse them within the loop.

K = inner(density ** penal * sigma(u), grad(v)) * dx

problem= LinearVariationalProblem(K, F, u_new, bcs)

solver = LinearVariationalSolver(problem)

# FE-ANALYSIS --------------------------------------------------

solver_disp.solve()

FEniCS utilizes PETSc as its linear algebra backend and by default uses the sparse LU decomposition

(”lu”) method, and the actual software that is called is then the sparse LU solver from UMFPACK (which

PETSc has an interface to). We could easily change the solver parameters and design the solver as per our

requirements by accessing the method parameters over the solver object.

solver.parameters["linear_solver"] = "gmres"

solver.parameters["preconditioner"] = "ilu"

4.4. Optimality criteria based optimizer

We initialize the density vector with volfrac as the initial density. Note that we use as_vector()

method over the density function to access the underlying array of values. The iterations start with the

13

ﬁnite element analysis of the linear variational problem. The solution to the problem is stored in the variable

u_sol, which is then used to evaluate the objective function and sensitivity over each element of the mesh.

solver.solve()

objective = project(density ** penal * psi(u_sol), D).vector()[:]

sensitivity = -penal * (density.vector()[:]) ** (penal - 1) * project(psi(u_sol), D).vector()[:]

The optimality criteria based update of the density vector is done on lines 46 - 51. The bounds for the

calculation of Lagrange multiplier by the bisection method are initialized on line 46 and the actual loop

starts on line 47.

l1, l2, move = 0, 100000, 0.2

while l2 - l1 > 1e-4:

l_mid = 0.5 * (l2 + l1)

density_new = np.maximum(0.001,np.maximum(density.vector()[:] - move, np.minimum(1.0, np.minimum(density.

vector()[:] + move, density.vector()[:] * np.sqrt(-sensitivity / l_mid)))))

l1, l2 = (l_mid, l2) if sum(density_new) - volfrac * mesh.num_cells() > 0 else (l1, l_mid)

density.vector()[:] = density_new

4.5. Mesh-independency ﬁltering

The modiﬁcation of the sensitivities by the application of the sensitivity ﬁlter described by Eq. (21) is

a linear operation and this could be converted to a matrix product as deﬁned by Eq. (26). The matrix W

is the weight matrix. The elements of the matrix satisfy the condition presented by Eq. (22) and Fig. 4

. First we retrieve the midpoints of all the elements within the mesh and then evaluate the Euclidean

distance matrix for the midpoint vector. In the case of topology optimization, suppose we have a collection

of vectors {xi∈Rd:i∈ {1, ..., N}} containing the coordinates of midpoints (xi)of all the elements within

the mesh. The Euclidean distance matrix is a N×Nmatrix that contains the pairwise distance between

all the elements of a vector of length N, and is deﬁned as:

Dij = (xi−xj)T(xi−xj) = kxik2

2−2xT

ixj+kxjk2

2(25)

This gives us the pairwise distance between all the domain elements, or more speciﬁcally a single element

Dab represents the distance of eleafrom eleb. Then we apply the condition that the elements outside the

zone of inﬂuence should have a weight equal to zero. i.e., the elements whose distance >rmin should have

a weight equal to zero.

Remark. By evaluating the weight matrix based on vector based calculations we reduced a lot of computa-

tional cost that is associated with evaluation of the same in a nested loop. The euclidean distance matrix

is a symmetric matrix and thus there exists multiple algorithms to further reduce the computational cost

14

associated with their evaluation on parallel system. The interested reader is referred to Angeletti et al.

[13], Li et al. [42] for the same.

∂E1

∂d1

.

.

.

∂En

∂dn

=

W11 · · · W1n

.

.

.....

.

.

Wn1· · · Wnn

·

d1

.

.

.

dn

∂E1

∂d1

.

.

.

∂En

∂dn

1

d1

.

.

.

1

dn

1

Pn

b=1 W1b

.

.

.

1

Pn

b=1 Wnb

(26)

# PREPARE DISTANCE MATRICES FOR FILTER -----------------------------

midpoint = [cell.midpoint().array()[:] for cell in cells(mesh)]

distance_mat = rmin - sp.euclidean_distances(midpoint, midpoint)

distance_mat[distance_mat < 0] = 0

distance_sum = distance_mat.sum(1) # sum the row

# FILTERING/MODIFICATION OF SENSITIVITIES ----------------------

sensitivity = np.divide(distance_mat @ np.multiply(density.vector()[:], sensitivity), np.multiply(density.

vector()[:], distance_sum))

Once we have the weight matrix, we evaluate the vector of the sum of weight for each element. The

modiﬁcation in sensitivity is then evaluated by just performing the matrix operations described by Eq. (26).

Here represents the Hadamard product, and (.) represents the dot product. The distance matrix (weight

matrix) and the distance sum vector do not vary during the iteration process, and thus they are evaluated

and stored outside of the primary iteration loop.

5. Model Extensions

The original 99-line code by Sigmund [63] and the 88-line code by Andreassen et al. [12], the authors

described how to extend their code to account for passive elements, other boundary conditions, and multiple

load cases. In this section, we also describe these extensions based on our 55 lines of code. Besides, we show

that the extension of the code to 3D problems still keeps the number of lines limited to 55 and requires a

minimal change of the code.

5.1. Working with 3D problems

One of the amazing advantages of working with FEniCS is that it allows us to write a uniﬁed simulation

code that can operate in Rd, d = 1,2,3, since the variational formulation is independent of dimension. By

making a few modiﬁcations to the code we can use the same 55-lines of code to run 3D simulations. This is

hugely beneﬁcial to the previous implementation as to work with 3D they required signiﬁcant modiﬁcation

of the code base [12]. To change the code into a 3D cantilever problem, we just need to update the mesh

and add the third dimension values to the boundary condition and load deﬁnitions. Thus, only the following

change is required:

15

60

20

4

Figure 6: 3D Cantilever beam problem. (a)The ground structure with the applied external loads and boundary conditions for

the optimization of a 3D cantilever beam. (b) The topologically optimized design.

def main(nelx, nely, nelz, volfrac, penal, rmin):

mesh = BoxMesh(Point(0.0, 0.0, 0.0), Point(nelx, nely, nelz), nelx, nely, nelz)

bcs = [DirichletBC(U, Constant((0.0, 0.0, 0.0)), support)]

F = dot(v, Constant((0.0, -1.0, 0.0))) * ds(1)

We need to add the number of element required in z-direction to the parameters of function deﬁnition.

Changing the mesh constructor to BoxMesh(), creates a box partioned with (nelx, nely, nelz) elements.

Fig. 6 shows the ground structure with the applied external loads and boundary conditions for the opti-

mization of a 3D cantilever beam along with the optimized geometry achieved by running the command:

from topopt import main

main(nelx=60, nely=20, nelz=4, volfrac=0.3, penal=3.0, rmin=1.5)

5.2. Other boundary conditions

The support elements are identiﬁed based on the conditional statements written in the C++ syntax. To

add a prop to the other end of the cantilever beam we just need to identify the elements and then assign a

Dirichlet boundary condition to it. This is achieved by adding the following lines of code:

prop_support = CompiledSubDomain("near(x[0], l,tol) && near(x[1], 0, tol)", tol=1e-14, l=nelx)

prop_bc = DirichletBC(U.sub(1), Constant(0.0), prop_support, method="pointwise")

bcs.append(prop_bc)

The solution presented in Fig. 7 is then obtained by the following:

from topopt import main

main(nelx=180, nely=60, volfrac=0.5, penal=3.0, rmin=3)

16

180

60

Figure 7: Propped cantilever beam problem. (a)The ground structure with the applied external loads and boundary conditions

for the optimization of a propped cantilever beam. (b) Topologically optimized structure.

180

60

Figure 8: Cantilever beam with multiple load case. (a)The ground structure with the applied external loads and boundary

conditions for the optimization of a cantilever beam with multiple load case. (b) Topologically optimized structure.

5.3. Multiple load cases

Adding multiple load cases to the problem is also achieved with less than 60 lines of code. In the two

load case the change is made in line number 21 where we need to add a new marker for the second load.

This is identiﬁed with the help of load marker 2. The information is then passed to the measure in a similar

manner as before. We could then deﬁne loads on certain boundaries by using there speciﬁc markers.

CompiledSubDomain("x[0]==l && x[1]<=2", l=nelx).mark(load_marker, 1)

CompiledSubDomain("x[0]==l && x[1]>=h-2", l=nelx, h=nely).mark(load_marker, 2)

ds = Measure("ds")(subdomain_data=load_marker)

F1 = dot(v, Constant((0.0, -1.0))) * ds(1)

F2 = dot(v, Constant((0.0, +1.0))) * ds(2)

problem = [LinearVariationalProblem(K, F1, u_sol, bcs),LinearVariationalProblem(K, F2, u_sol, bcs)]

The objective function and the sensitivity is calculated based on the displacement ﬁeld by solving the two

variational problems and summing them up for further calculations. This is done by replacing the lines

17

38-42 with the following.

objective, sensitivity = np.zeros(mesh.num_cells()), np.zeros(mesh.num_cells())

for iin range(2):

# FE-ANALYSIS --------------------------------------------------

solver = LinearVariationalSolver(problem[i])

solver.solve()

# OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS ------------------

objective += project(density ** penal * psi(u_sol), D).vector()[:]

sensitivity += -penal * (density.vector()[:]) ** (penal - 1) * project(psi(u_sol), D).vector()[:]

The solution presented in Fig. 8 is then obtained by the following:

from topopt import main

main(nelx=180, nely=60, volfrac=0.5, penal=3.0, rmin=3)

5.4. Passive elements

To incorporate zones of ﬁxed density, such as zones with no material (holes) or zones with ﬁxed material,

we deﬁne passive elements that have a ﬁxed density throughout the iteration process. This is achieved with

just additional ﬁve lines of code including the identiﬁcation of the passive elements. The zone is identiﬁed

and marked with the help of the Meshfunction class of FEniCS by adding the following lines of code.

# DEFINE PASSIVE ELEMENTS ------------------------------------------

circle = CompiledSubDomain(’(x[0]-x0)*(x[0]-x0) + (x[1]-x1)*(x[1]-x1) <= r*r’,x0=nelx/3, x1=nely/2, r=nely/4)

circle_marker = MeshFunction("size_t", mesh, mesh.topology().dim())

circle.mark(circle_marker, 1)

This information is then passed to the optimality criteria loop by adding the following line and then,

explicitly setting their density value equal to minimum density in case of a hole.

density_new[circle_marker.where_equal(1)] = 0.001

The solution presented in Fig. 9 is then obtained by the following:

from topopt import main

main(nelx=180, nely=60, volfrac=0.5, penal=3.0, rmin=3)

5.5. Alternative optimizers

The optimality criteria based optimizer have been widely used in the literature because of its easy to un-

derstand formulation and straight forward implementation, but suﬀers from the lack of support for problems

with multiple constrains. Another common optimizer that has been used successfully by many researches to

solve multi-constraint topology optimization problems is based on the method of moving asymptotes(MMA)

18

180

60

60

Figure 9: Cantilever beam with passive elements. (a)The ground structure with the applied external loads and boundary

conditions for the optimization of a cantilever beam with a hole. (b) Topologically optimized structure.

algorithm[68]. The MMA-algorithm is a mathematical programming algorithm, which is in nature similar

to methods like Sequential Linear Programming (SLP) and Sequential Quadratic Programming (SQP) for

solving smooth, non-linear optimization problems [21]. The call to MMA requires deﬁnition of several input

arguments along with the ﬁrst and second derivatives of the objective as well as the constraint functions. In

the case of TO the second order derivatives are assumed to be zero. One can ﬁnd the deﬁnition of all the

auxiliary variables in the documentation of code ﬁles which one can obtain from Prof. Krister Svanberg,

KTH, Sweden. The MMA code is called by ﬁrst deﬁning the auxiliary variables as per the documentation

and then replacing the optimality criteria block with the following:

xmma,ymma,zmma,lam,xsi,eta,aaa,zet,s,low,upp = \

mmasub(m,n,loop,xval,xmin,xmax,xold1,xold2,f0val,df0dx,fval,dfdx,low,upp,a0,a,cMMa,d,move)

Since the code allows for direct access of the underlying matrices and vectors, one could also use the

optimizers available in the open-source python libraries such a SciPy or PyOpt directly.

6. Extension to practical applications

This code is capable of running large scale simulations on systems ranging from high performance work-

stations to computational clusters. The readability of the code allows for easy modiﬁcations and the just

in time compilation provides us with speed and eﬃciency. With a few modiﬁcations, the code can handle

complex structural conﬁguration with support for parallel computation. In this section we will discuss few

challenges related to application of TO to large scale engineering problems with the help of a 3D bridge

example and its implementation with the 55-line code. Fig. 10 shows the ground structure with the applied

external loads and boundary conditions for the optimization of a 3D bridge with a non-designable deck.

An opening of size 20m×25mis placed over the non-designable deck and a uniformly distributed load is

19

Figure 10: 3D bridge problem. The ground structure is 360m long with an opening for traﬃc. It further consist of a non-

designable deck and 4m wide support faces. The structure is meshed with 6 million elements.

applied over the deck inside the opening. The structure is meshed with approximately six-million tetrahedral

elements with three-million DoFs.

6.1. Complex structural conﬁguration

The ground structure for the 3D-bridge as presented in Fig. 10 consists of three sub-domains: the non-

designable deck, the load face and the support face. Such kind of structural conﬁguration is diﬃcult to handle

in the MATLAB codes [63,12,29] but are comparatively easy to handle in commercial packages in which we

can have an explicit representation of the complex structural conﬁguration [77]. FEniCS supports marked

computational mesh generated by ’gmsh’[31]; which allows us to explicitly mark diﬀerent sub-domains in

’gmsh’ with numerical labels and then read those directly into FEniCS. This extends the capability of the

55-line code to complex structural conﬁgurations. For complex geometries one needs to follow the mesh

processing pipeline, and, thus create the mesh in ’gmsh’ and mark diﬀerent sub-domains, convert the mesh

to XDMF with ’meshio’[59] and then ﬁnally read the mesh directly into the program with the commands:

mesh = Mesh()

with XDMFFile("domain.xdmf") as infile:

infile.read(mesh)

The supports and loads are deﬁned by reading the numerical labels of the mesh and deﬁning ’Mea-

sures’(dx, ds) over the domain based on these labels. This is achieved by replacing lines 17 −22 with the

following:

20

Figure 11: 3D bridge problem. Smoothened topologically optimized design.

mvc = MeshValueCollection("size_t", mesh, 2)

with XDMFFile("mesh/surface.xdmf") as infile:

infile.read(mvc, "surface_tag")

mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)

ds = Measure("ds")(subdomain_data=mf)

bcs = [DirichletBC(U, Constant((0.0, 0.0, 0.0)), mf, support_tag)]

F = dot(v, Constant((0.0, -1.0, 0.0))) * ds(load_tag)

The imported mesh will work directly with code as the computation of the ﬁlter is based on the actual

centre-points of the elements (refer Section 4.5) as opposed to the assumptions made in the 88 or 99 line

codes where the ﬁlter is evaluated based on the assumption of uniform mesh with unit cells. The optimized

geometry presented in Fig. 11 is achieved by running the command:

from topopt import main

main(volfrac=0.15, penal=3.0, rmin=10.0)

6.2. Handling large 3D problems

Solving large scale 3D problems require access to systems with large amount of RAM and computa-

tional power. Even with powerful computational systems the implementation could be slow because of

ineﬃcient coding. The computational cost associated with TO can be attributed to three major operations:

computation of the ﬁlter, evaluation of the displacement solution of the problem, and evaluation of the

optimal solution of the optimization problem. Since all of these are dependent on the size of the mesh, the

computational cost of the algorithm is directly related to the mesh.

In the original 99-line code and further it’s evolution into the 88-line code, loops were used to evaluate

the weight-matrices for the ﬁlter. Loops are known to be extremely slow as compared to vector operations,

21

Loop

Vector

time(s)

0.1

1

10

100

1000

Degreeoffreedom's

104

5000 2×104

Loop

Vector

RAM(MB)

1

10

100

1000

104

Degreeoffreedom's

104

5000 2×104

Figure 12: Comparison of looping versus vector operation for computation of ﬁlter. With increasing number of degrees of

freedom’s looping approach takes substantially less amount of RAM as compared to vector approach but require more time.

but, vector operations require a RAM size capable of storing the full matrices required to perform the

computation. In Fig. 12, we can see that in terms of RAM, loops perform much better as compared to

the vector approach, but, in terms of computational time the vector approach outperforms loop. For 33000

DoF’s the RAM required by the looping approach is a mere 11MB as compared to 8GB required by vector

approach, but, vector approach completes the computation in 17 seconds as opposed to 710 seconds taken

by loops. To take beneﬁt of both the approaches it is advised to use the chunking technique as described

in Li et al. [42] by looping over large chunks of the mid-point vector which could be stored in the RAM for

computation.

In the 88-line MATLAB code [12] substantial reduction in computational expense as compared to the

original 99-line code [63] was achieved by vectorization of the loops and the new 99-line code [29] further

provides a reduction in computational expense by smart use of sparse matrices and using the ’fsparse’

function from the stenglib library that is written in ’C’. The use of sparse solvers along with vectorization

has lead to substantial reduction in the computational expense of the evaluation of the displacement solution

of the problem and also evaluation of the optimal solution of the optimization problem. The latest 99-line

code achieves the assembly of the stiﬀness matrix of a six million DoF’s system in under 10 seconds. Since

we are using PetSc as the backend, our code beneﬁts from the capabilities of the library such as support for

parallelization, sparse matrices and iterative solvers. This results in under 10 second assembly of stiﬀness

matrix for the same six million DoF’s system, and with parallelization we can achieve further speedups.

6.3. Parallel implementation of topology optimization

Topology optimization algorithm requires computation of both the displacement solution of the systems

and the optimization solution of the system in each iteration. To solve large scale engineering structures

researchers in the past have parallelized the TO algorithm [2,23,25,28,61,70,71,4,50,14,48,47]. Many

of these works are extremely capable in solving the TO problem eﬃciently on parallel HPC systems, but are

22

too complex for beginners to understand and implement. In this section our aim is to present the parallel

performance of our code and help beginners take beneﬁt of multi-core simulations on there laptops or HPC

workstations. This implementation by no means is as optimized as the 2589-line code by Schmidt and Schulz

[61] or the 6300-lines code of Aage et al. [4], but serves as a proof-of-concept for the parallel capability of

the 55-line code.

The modiﬁcations necessary to make the code compatible for parallel computation lies only in the

modiﬁcation of ﬁlter. Mesh-independency ﬁlter as described in Section 3.2.2 requires information of the

co-ordinates of the center-points of elements in a zone around the element under consideration. Since,

parallelization in FEniCS works by splitting the mesh into ’n’ parts - where ’n’ is the number of processors -

and then passing only a portion of the mesh to a single processor, the information required for computation

of the ﬁlter is not available with each processor. Thus, to make the code compatible for parallel computation

we have to change the ﬁlter to the Helmholtz ﬁlter as described in [41,27]. Parallel computation can then

be performed on 16 cores by running the command:

mpirun -np 16 python3 main.py

In the above command main.py ﬁle contains the following code:

from topopt import main

main(volfrac=0.15, penal=3.0, rmin=10.0)

It is to be noted that, our implementation supports complex structural conﬁguration on parallel systems.

For the problem presented in Fig. 10 with six million elements, the code took 10 minutes and 50 seconds per

iteration on a single core, and, 1 minute and 40 seconds per iteration on 16 cores. This proves the code’s

scalability, and with further improvements in solver design and the use of better optimization algorithms,

the code is capable of substantial computational gains.

7. Conclusion

This paper provides a simple, compact, and easy-to-understand implementation of topology optimization

using the solid isotropic material with penalization methodology for 2D and 3D structures via an open-

source ﬁnite element python package (FEniCS). By revisiting the original 99-line code by Sigmund [63] and

its further modiﬁcation to 88-lines by Andreassen et al. [12] and the new 99-line by Ferrari and Sigmund

[29], we present a brief step-by-step overview of the topology optimization problem’s mathematical model

and a detailed description of the FEniCS implementation.

The 99-line code laid the foundation and has helped many researchers enter the ﬁeld of topology optimiza-

tion, emphasizing the 2D plane stress problem. The 88-line code signiﬁcantly reduced the computational

23

time by vectorizing the loops, while also reducing the number of lines to 88. The new-99-line code fur-

ther improved the eﬃciency of the original code by updating the code to latest developments in the sparse

computation of matrices in MATLAB. This implementation’s key strength is the generalized and compact

approach enabled by FEniCS, which allows us to make a uniﬁed code-base for 2D and 3D problems with

easy to understand UFL expressions that make the code extremely readable in just 55-lines.

Compactness in the code is also achieved by vectorizing most of the operations. By utilizing the Euclidean

distance matrix concept, we have also vectorized the weight matrix computation for mesh-independency

ﬁlters which has lead to substantial savings in the computational time for evaluation of the ﬁlter. This also

allows us to evaluate the ﬁlter on complex structural conﬁgurations without any change in the code-base.

We also demonstrate the capability of the code to handle complex large scale engineering structures with

support for parallel computation on high performance workstations.

Since the expressions written in the python code are automatically converted into compiled C++ func-

tions, the implementation is computationally eﬃcient. The whole code-base is based on open-source pack-

ages, and thus, it is accessible and ready-to-use by the entire research community. Considering FEniCS

is platform-independent [34], the code works on Windows, MAC and Linux systems alike. FEniCS is also

equipped with powerful tools that allow straightforward extension of the current code into diﬀerent areas,

such as nonlinearity, hyper-elasticity, compliant mechanisms, and multi-scale modeling with the same base

code.

8. Declarations

8.1. Funding

The authors gratefully acknowledge ﬁnancial support from the Ministry of Human Resource Develop-

ment. The second author (Rajib Chowdhury) thanks the funding support from the SERB via ﬁle no.

CRG/2019/004600 and DRDL via ﬁle no. DRDL/24/08P/19/0235/43386.

8.2. Conﬂict of interest

The authors declare that they have no known competing ﬁnancial or personal relationship with other

people or organizations that could inappropriately inﬂuence or bias the content of the paper.

Appendix A. FEniCS Code

1from dolfin import *

2import numpy as np, sklearn.metrics.pairwise as sp

3# A 55 LINE TOPOLOGY OPTIMIZATION CODE ---------------------------------

4def main(nelx, nely, volfrac, penal, rmin):

5sigma = lambda _u: 2.0 * mu * sym(grad(_u)) + lmbda * tr(sym(grad(_u))) * Identity(len(_u))

24

6psi = lambda _u: lmbda / 2 * (tr(sym(grad(_u))) ** 2) + mu * tr(sym(grad(_u)) * sym(grad(_u)))

7xdmf = XDMFFile("output/density.xdmf")

8mu, lmbda = Constant(0.4), Constant(0.6)

9# PREPARE FINITE ELEMENT ANALYSIS ----------------------------------

10 mesh = RectangleMesh(Point(0, 0), Point(nelx, nely), nelx, nely, "right/left")

11 U = VectorFunctionSpace(mesh, "P", 1)

12 D = FunctionSpace(mesh, "DG", 0)

13 u, v = TrialFunction(U), TestFunction(U)

14 u_sol, density_old, density = Function(U), Function(D), Function(D, name="density")

15 density.vector()[:] = volfrac

16 # DEFINE SUPPORT ---------------------------------------------------

17 support = CompiledSubDomain("near(x[0], 0.0, tol) && on_boundary", tol=1e-14)

18 bcs = [DirichletBC(U, Constant((0.0, 0.0)), support)]

19 # DEFINE LOAD ------------------------------------------------------

20 load_marker = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)

21 CompiledSubDomain("x[0]==l && x[1]<=2", l=nelx).mark(load_marker, 1)

22 ds = Measure("ds")(subdomain_data=load_marker)

23 F = dot(v, Constant((0.0, -1.0))) * ds(1)

24 # SET UP THE VARIATIONAL PROBLEM AND SOLVER ------------------------

25 K = inner(density ** penal * sigma(u), grad(v)) * dx

26 problem = LinearVariationalProblem(K, F, u_sol, bcs)

27 solver = LinearVariationalSolver(problem)

28 # PREPARE DISTANCE MATRICES FOR FILTER -----------------------------

29 midpoint = [cell.midpoint().array()[:] for cell in cells(mesh)]

30 distance_mat = rmin - sp.euclidean_distances(midpoint, midpoint)

31 distance_mat[distance_mat < 0] = 0

32 distance_sum = distance_mat.sum(1)

33 # START ITERATION --------------------------------------------------

34 loop, change = 0, 1

35 while change > 0.01 and loop < 2000:

36 loop = loop + 1

37 density_old.assign(density)

38 # FE-ANALYSIS --------------------------------------------------

39 solver.solve()

40 # OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS ------------------

41 objective = project(density ** penal * psi(u_sol), D).vector()[:]

42 sensitivity = -penal * (density.vector()[:]) ** (penal - 1) * project(psi(u_sol), D).vector()[:]

43 # FILTERING/MODIFICATION OF SENSITIVITIES ----------------------

44 sensitivity = np.divide(distance_mat @ np.multiply(density.vector()[:], sensitivity), np.multiply(

density.vector()[:], distance_sum))

45 # DESIGN UPDATE BY THE OPTIMALITY CRITERIA METHOD --------------

46 l1, l2, move = 0, 100000, 0.2

47 while l2 - l1 > 1e-4:

25

48 l_mid = 0.5 * (l2 + l1)

49 density_new = np.maximum(0.001,np.maximum(density.vector()[:] - move, np.minimum(1.0, np.minimum

(density.vector()[:] + move, density.vector()[:] * np.sqrt(-sensitivity / l_mid)))))

50 l1, l2 = (l_mid, l2) if sum(density_new) - volfrac * mesh.num_cells() > 0 else (l1, l_mid)

51 density.vector()[:] = density_new

52 # PRINT RESULTS ------------------------------------------------

53 change = norm(density.vector()-density_old.vector(), norm_type="linf", mesh=mesh)

54 print("it.: {0} , obj.: {1:.3f} Vol.: {2:.3f}, ch.: {3:.3f}".format(loop, sum(objective), sum(

density.vector()[:]) / mesh.num_cells(), change))

55 xdmf.write(density, loop)

References

[1] N. Aage and B. S. Lazarov. Parallel framework for topology optimization using the method of moving asymptotes.

Structural and multidisciplinary optimization, 47(4):493–505, 2013. 2

[2] N. Aage and B. S. Lazarov. Parallel framework for topology optimization using the method of moving asymptotes. Struc-

tural and Multidisciplinary Optimization, 47(4):493–505, Apr. 2013. ISSN 1615-1488. doi: 10.1007/s00158- 012-0869- 2.

22

[3] N. Aage, E. Andreassen, and B. S. Lazarov. Topology optimization using PETSc: An easy-to-use, fully parallel, open

source topology optimization framework. Structural and Multidisciplinary Optimization, 51(3):565–572, Mar. 2015. doi:

10.1007/s00158-014-1157-0. 2

[4] N. Aage, E. Andreassen, and B. S. Lazarov. Topology optimization using PETSc: An easy-to-use, fully parallel, open

source topology optimization framework. Structural and Multidisciplinary Optimization, 51(3):565–572, Mar. 2015. ISSN

1615-1488. doi: 10.1007/s00158-014-1157-0. 22,23

[5] N. Aage, E. Andreassen, B. S. Lazarov, and O. Sigmund. Giga-voxel computational morphogenesis for structural design.

Nature, 550(7674):84–86, 2017. 2

[6] S. Abhyankar, J. Brown, E. M. Constantinescu, D. Ghosh, B. F. Smith, and H. Zhang. Petsc/ts: A modern scalable

ode/dae solver library. arXiv preprint arXiv:1806.01437, 2018. 8

[7] G. B. L. C. Ahrens, James. ParaView: An End-User Tool for Large Data Visualization, Visualization Handbook, Aug.

2005. 8

[8] M. S. Alnæs, A. Logg, K.-A. Mardal, O. Skavhaug, and H. P. Langtangen. Uniﬁed framework for ﬁnite element assembly.

International Journal of Computational Science and Engineering, 4(4):231–244, 2009. doi: 10.1504/IJCSE.2009.029160.

8

[9] M. S. Alnæs, A. Logg, K. B. Ølgaard, M. E. Rognes, and G. N. Wells. Uniﬁed form language: A domain-speciﬁc language

for weak formulations of partial diﬀerential equations. ACM Transactions on Mathematical Software, 40(2), 2014. doi:

10.1145/2566630. 8

[10] M. S. Alnæs, J. Blechta, J. Hake, A. Johansson, B. Kehlet, A. Logg, C. Richardson, J. Ring, M. E. Rognes, and G. N.

Wells. The fenics project version 1.5. Archive of Numerical Software, 3(100), 2015. doi: 10.11588/ans.2015.100.20553. 8

[11] O. Amir, N. Aage, and B. S. Lazarov. On multigrid-CG for eﬃcient topology optimization. Structural and Multidisciplinary

Optimization, 49(5):815–829, 2014. 2

[12] E. Andreassen, A. Clausen, M. Schevenels, B. S. Lazarov, and O. Sigmund. Eﬃcient topology optimization in MATLAB us-

ing 88 lines of code. Structural and Multidisciplinary Optimization, 43(1):1–16, Jan. 2011. doi: 10.1007/s00158-010-0594- 7.

2,15,20,22,23

26

[13] M. Angeletti, J.-M. Bonny, and J. Koko. Parallel Euclidean distance matrix computation on big datasets *. Feb. 2019. 15

[14] J. Baiges, J. Mart´ınez-Frutos, D. Herrero-P´erez, F. Otero, and A. Ferrer. Large-scale stochastic topology optimization

using adaptive mesh reﬁnement and coarsening through a two-level parallelization scheme. Computer Methods in Applied

Mechanics and Engineering, 343:186–206, 2019. 22

[15] S. Balay, W. D. Gropp, L. C. McInnes, and B. F. Smith. Eﬃcient management of parallelism in object oriented numerical

software libraries. In E. Arge, A. M. Bruaset, and H. P. Langtangen, editors, Modern Software Tools in Scientiﬁc

Computing, pages 163–202. Birkh¨auser Press, 1997. 8

[16] S. Balay, K. Buschelman, V. Eijkhout, W. Gropp, D. Kaushik, M. Knepley, L. C. Mcinnes, B. Smith, and H. Zhang.

PETSc Users Manual. ReVision, (ANL-95/11 - Revision 3.12), 2010. doi: 10.2172/1178104. URL https://www.mcs.anl.

gov/petsc.8

[17] S. Balay, S. Abhyankar, M. F. Adams, J. Brown, P. Brune, K. Buschelman, L. Dalcin, A. Dener, V. Eijkhout, W. D.

Gropp, D. Karpeyev, D. Kaushik, M. G. Knepley, D. A. May, L. C. McInnes, R. T. Mills, T. Munson, K. Rupp, P. Sanan,

B. F. Smith, S. Zampini, H. Zhang, and H. Zhang. PETSc Web page. https://www.mcs.anl.gov/petsc, 2019. URL

https://www.mcs.anl.gov/petsc.8

[18] M. P. Bendsøe. Optimal shape design as a material distribution problem. Structural optimization, 1(4):193–202, Dec.

1989. doi: 10.1007/BF01650949. 2

[19] M. P. Bendsøe. Optimization of Structural Topology, Shape, and Material. Springer Berlin Heidelberg, Berlin, Heidelberg,

1995. ISBN 978-3-662-03117-9 978-3-662-03115-5. doi: 10.1007/978-3-662-03115-5. 7

[20] M. P. Bendsøe and N. Kikuchi. Generating optimal topologies in structural design using a homogenization method.

Computer Methods in Applied Mechanics and Engineering, 71(2):197–224, Nov. 1988. doi: 10.1016/0045-7825(88)90086- 2.

2

[21] M. P. Bendsoe and O. Sigmund. Topology Optimization: Theory, Methods, and Applications. Springer Science & Business

Media, 2013. 2,19

[22] J. Bleyer. Numerical tours of computational mechanics with FEniCS. 2018. doi: 10.5281/zenodo.1287832. 8

[23] T. Borrvall and J. Petersson. Large-scale topology optimization in 3D using parallel computing. Computer Methods

in Applied Mechanics and Engineering, 190(46):6201–6229, Sept. 2001. ISSN 0045-7825. doi: 10.1016/S0045- 7825(01)

00216-X. 22

[24] V. J. Challis. A discrete level-set topology optimization code written in Matlab. Structural and Multidisciplinary Opti-

mization, 41(3):453–464, Apr. 2010. doi: 10.1007/s00158- 009-0430-0. 2

[25] V. J. Challis, A. P. Roberts, and J. F. Grotowski. High resolution topology optimization using graphics processing

units (GPUs). Structural and Multidisciplinary Optimization, 49(2):315–325, Feb. 2014. ISSN 1615-1488. doi: 10.1007/

s00158-013- 0980-z. 22

[26] Q. Chen, X. Zhang, and B. Zhu. A 213-line topology optimization code for geometrically nonlinear structures. Structural

and Multidisciplinary Optimization, 59(5):1863–1879, May 2019. doi: 10.1007/s00158-018-2138- 5. 2

[27] E. M. de Souza and E. C. N. Silva. Topology optimization applied to the design of actuators driven by pressure loads.

Structural and Multidisciplinary Optimization, 61(5):1763–1786, May 2020. ISSN 1615-147X, 1615-1488. doi: 10.1007/

s00158-019- 02421-5. 23

[28] A. Evgrafov, C. J. Rupp, K. Maute, and M. L. Dunn. Large-scale parallel topology optimization using a dual-primal

substructuring solver. Structural and Multidisciplinary Optimization, 36(4):329–345, Oct. 2008. ISSN 1615-1488. doi:

10.1007/s00158-007-0190-7. 22

[29] F. Ferrari and O. Sigmund. A new generation 99 line Matlab code for compliance Topology Optimization and its extension

to 3D. arXiv:2005.05436 [cs, math], July 2020. 2,20,22,23

[30] A. G. Allaire G (2009) A 2-d Scilab Code for shape and topology optimization by the level set method.

27

http://www.cmap.polytechnique.fr/∼allaire/levelset en.html. 2009. 2

[31] C. Geuzaine and J.-F. Remacle. Gmsh Reference Manual. http://www.geuz.org/gmsh, 1.12 edition, Aug. 2003. 20

[32] H. Ghasemi, H. S. Park, and T. Rabczuk. A level-set based IGA formulation for topology optimization of ﬂexoelectric

materials. Computer Methods in Applied Mechanics and Engineering, 313:239–258, 2017. 2

[33] H. Ghasemi, H. S. Park, and T. Rabczuk. A multi-material level set-based topology optimization of ﬂexoelectric composites.

Computer Methods in Applied Mechanics and Engineering, 332:47–62, 2018. 2

[34] J. S. Hale, L. Li, C. N. Richardson, and G. N. Wells. Containers for Portable, Productive, and Performant Scientiﬁc

Computing. Computing in Science Engineering, 19(6):40–50, Nov. 2017. ISSN 1558-366X. doi: 10.1109/MCSE.2017.

2421459. 24

[35] K. M. Hamdia, H. Ghasemi, Y. Bazi, H. AlHichri, N. Alajlan, and T. Rabczuk. A novel deep learning based method for

the computational material design of ﬂexoelectric nanostructures with topology optimization. Finite Elements in Analysis

and Design, 165:21–30, 2019. 2

[36] D. Herrero, J. Mart´ınez, and P. Mart´ı. An implementation of level set based topology optimization using GPU. In 10th

World Congress on Structural and Multidisciplinary Optimization, Orlando, Florida, USA, pages 1–10, 2013. 2

[37] P. Kang and S.-K. Youn. Isogeometric topology optimization of shell structures using trimmed NURBS surfaces. Finite

Elements in Analysis and Design, 120:18–40, Nov. 2016. doi: 10.1016/j.ﬁnel.2016.06.003. 2

[38] G. Kharmanda, N. Olhoﬀ, A. Mohamed, and M. Lemaire. Reliability-based topology optimization. Structural and

Multidisciplinary Optimization, 26(5):295–307, Mar. 2004. doi: 10.1007/s00158- 003-0322-7. 2

[39] R. C. Kirby. Algorithm 839: Fiat, a new paradigm for computing ﬁnite element basis functions. ACM Transactions on

Mathematical Software, 30(4):502–516, 2004. doi: 10.1145/1039813.1039820. 8

[40] R. C. Kirby and A. Logg. A compiler for variational forms. ACM Transactions on Mathematical Software, 32(3), 2006.

doi: 10.1145/1163641.1163644. 8

[41] B. S. Lazarov and O. Sigmund. Filters in topology optimization based on Helmholtz-type diﬀerential equations. Interna-

tional Journal for Numerical Methods in Engineering, 86(6):765–781, May 2011. ISSN 00295981. doi: 10.1002/nme.3072.

23

[42] Q. Li, V. Kecman, and R. Salman. A Chunking Method for Euclidean Distance Matrix Calculation on Large Dataset Using

Multi-GPU. In 2010 Ninth International Conference on Machine Learning and Applications, pages 208–213, Washington,

DC, USA, Dec. 2010. IEEE. ISBN 978-1-4244-9211-4. doi: 10.1109/ICMLA.2010.38. 15,22

[43] K. Liu and A. Tovar. An eﬃcient 3D topology optimization code written in Matlab. Structural and Multidisciplinary

Optimization, 50(6):1175–1196, Dec. 2014. doi: 10.1007/s00158- 014-1107-x. 2,7

[44] A. Logg and G. N. Wells. Dolﬁn: Automated ﬁnite element computing. ACM Transactions on Mathematical Software,

37(2), 2010. doi: 10.1145/1731022.1731030. 8

[45] A. Logg, K.-A. Mardal, G. N. Wells, et al. Automated Solution of Diﬀerential Equations by the Finite Element Method.

Springer, 2012. ISBN 978-3-642-23098-1. doi: 10.1007/978-3- 642-23099-8. 8

[46] L. Lu, T. Yamamoto, M. Otomori, T. Yamada, K. Izui, and S. Nishiwaki. Topology optimization of an acoustic metama-

terial with negative bulk modulus using local resonance. Finite Elements in Analysis and Design, 72:1–12, Sept. 2013.

doi: 10.1016/j.ﬁnel.2013.04.005. 2

[47] J. Mart´ınez-Frutos and D. Herrero-P´erez. Large-scale robust topology optimization using multi-GPU systems. Computer

Methods in Applied Mechanics and Engineering, 311:393–414, 2016. 22

[48] J. Mart´ınez-Frutos and D. Herrero-P´erez. GPU acceleration for evolutionary topology optimization of continuum structures

using isosurfaces. Computers & Structures, 182:119–136, 2017. 22

[49] J. Mart´ınez-Frutos and D. Herrero-P´erez. Evolutionary topology optimization of continuum structures under uncertainty

using sensitivity analysis and smooth boundary representation. Computers & Structures, 205:15–27, 2018. 2

28

[50] J. Mart´ınez-Frutos, P. J. Mart´ınez-Castej´on, and D. Herrero-P´erez. Eﬃcient topology optimization using GPU computing

with multilevel granularity. Advances in Engineering Software, 106:47–62, Apr. 2017. ISSN 0965-9978. doi: 10.1016/j.

advengsoft.2017.01.009. 22

[51] H. P. Mlejnek. Some aspects of the genesis of structures. Structural optimization, 5(1):64–69, Mar. 1992. doi: 10.1007/

BF01744697. 2

[52] S. S. Nanthakumar, T. Lahmer, X. Zhuang, H. S. Park, and T. Rabczuk. Topology optimization of piezoelectric nanos-

tructures. Journal of the Mechanics and Physics of Solids, 94:316–335, 2016. 2

[53] S. S. Nanthakumar, X. Zhuang, H. S. Park, and T. Rabczuk. Topology optimization of ﬂexoelectric structures. Journal

of the Mechanics and Physics of Solids, 105:217–234, 2017. 2

[54] C. Nguyen, X. Zhuang, L. Chamoin, X. Zhao, H. Nguyen-Xuan, and T. Rabczuk. Three-dimensional topology optimization

of auxetic metamaterial using isogeometric analysis and model order reduction. Computer Methods in Applied Mechanics

and Engineering, 371:113306, 2020. 2

[55] K. B. Ølgaard and G. N. Wells. Optimisations for quadrature representations of ﬁnite element tensors through automated

code generation. ACM Transactions on Mathematical Software, 37, 2010. doi: 10.1145/1644001.1644009. 8

[56] R. Ortigosa, J. Mart´ınez-Frutos, A. J. Gil, and D. Herrero-P´erez. A new stabilisation approach for level-set based topology

optimisation of hyperelastic materials. Structural and Multidisciplinary Optimization, 60(6):2343–2371, 2019. 2

[57] M. Otomori, T. Yamada, K. Izui, and S. Nishiwaki. MATLAB code for a level set-based topology optimization method

using a reaction diﬀusion equation. Struct Multidiscip Optim, 51, 2014. doi: 10.1007/s00158-014- 1190-z. 2

[58] D. H. P´erez. Level Set Method Applied to Topology Optimization. 2012. 2

[59] N. Schl¨omer, G. McBain, T. Li, K. Luu, christos, V. M. Ferr´andiz, C. Barnes, eolianoe, L. Dalcin, nilswagner, A. Gupta,

S. M¨uller, L. Schwarz, J. Blechta, C. Coutinho, D. Beurle, s1291, B. Shrimali, A. Cervone, T. Heister, T. Langlois,

S. Peak, S. Sharma, M. Bussonnier, lgiraldi, G. Jacquenot, G. A. Vaillant, C. Wilson, A. U. Gudchenko, and A. Croucher.

nschloe/meshio 3.3.1, Dec. 2019. 20

[60] S. Schmidt and V. Schulz. A 2589 line topology optimization code written for the graphics card. Computing and

Visualization in Science, 14(6):249–256, Aug. 2011. doi: 10.1007/s00791-012-0180-1. 2

[61] S. Schmidt and V. Schulz. A 2589 line topology optimization code written for the graphics card. Computing and

Visualization in Science, 14(6):249–256, Aug. 2011. ISSN 1433-0369. doi: 10.1007/s00791-012-0180-1. 22,23

[62] O. Sigmund. On the design of compliant mechanisms using topology optimization. Journal of Structural Mechanics, 25

(4):493–524, 1997. 2

[63] O. Sigmund. A 99 line topology optimization code written in Matlab. Structural and Multidisciplinary Optimization, 21

(2):120–127, Apr. 2001. doi: 10.1007/s001580050176. 2,7,15,20,22,23

[64] O. Sigmund. Morphology-based black and white ﬁlters for topology optimization. Structural and Multidisciplinary

Optimization, 33(4-5):401–424, 2007. 2

[65] O. Sigmund and K. Maute. Topology optimization approaches. Structural and Multidisciplinary Optimization, 48(6):

1031–1055, 2013. 2

[66] O. Sigmund and J. Petersson. Numerical instabilities in topology optimization: A survey on procedures dealing with

checkerboards, mesh-dependencies and local minima. Structural optimization, 16(1):68–75, 1998. 2

[67] K. Suresh. A 199-line Matlab code for Pareto-optimal tracing in topology optimization. Structural and Multidisciplinary

Optimization, 42(5):665–679, Nov. 2010. doi: 10.1007/s00158-010-0534- 6. 2

[68] K. Svanberg. The method of moving asymptotes—a new method for structural optimization. International Journal for

Numerical Methods in Engineering, 24(2):359–373, 1987. doi: 10.1002/nme.1620240207. 19

[69] C. Talischi, G. H. Paulino, A. Pereira, and I. F. M. Menezes. Polytop: A MATLAB implementation of a general topology

optimization framework using unstructured polygonal ﬁnite element meshes. Struct Multidiscip Optim, 45, 2012. doi:

29

10.1007/s00158-011-0696-x. 2

[70] K. Vemaganti and W. E. Lawrence. Parallel methods for optimality criteria-based topology optimization. Computer

Methods in Applied Mechanics and Engineering, 194(34):3637–3667, Sept. 2005. ISSN 0045-7825. doi: 10.1016/j.cma.

2004.08.008. 22

[71] E. Wadbro and M. Berggren. Megapixel Topology Optimization on a Graphics Processing Unit. SIAM Review, 51(4):

707–721, Nov. 2009. ISSN 0036-1445. doi: 10.1137/070699822. 22

[72] M. Y. Wang, X. Wang, and D. Guo. A level set method for structural topology optimization. Comput Methods Appl Mech

Eng, 192, 2003. doi: 10.1016/S0045- 7825(02)00559-5. 2

[73] P. Wei, Z. Li, X. Li, and M. Y. Wang. An 88-line MATLAB code for the parameterized level set method based topology

optimization using radial basis functions. Structural and Multidisciplinary Optimization, 58(2):831–849, Aug. 2018. doi:

10.1007/s00158-018-1904-8. 2

[74] W. Zhang, J. Yuan, J. Zhang, and X. Guo. A new topology optimization approach based on moving Morphable components

(MMC) and the ersatz material model. Struct Multidiscip Optim, 53, 2016. doi: 10.1007/s00158-015-1372- 3. 2

[75] M. Zhou and G. Rozvany. The COC algorithm, Part II: Topological, geometrical and generalized shape optimization.

Computer Methods in Applied Mechanics and Engineering, 89(1-3):309–336, Aug. 1991. doi: 10.1016/0045-7825(91)

90046-9. 2

[76] S. Zhou, J. Cadman, Y. Chen, W. Li, Y. M. Xie, and X. Huang. Design and fabrication of biphasic cellular materials with

transport properties – a modiﬁed bidirectional evolutionary structural optimization procedure and MATLAB program.

Int J Heat Mass Transf, 55, 2012. doi: 10.1016/j.ijheatmasstransfer.2012.08.028. 2

[77] Z. H. Zuo and Y. M. Xie. A simple and compact Python code for complex 3D topology optimization. Advances in

Engineering Software, July 2015. doi: 10.1016/j.advengsoft.2015.02.006. 2,20

30