1 Introduction

One of the ultimate goals of structural optimization is the development of fully automated software that allows users to tackle challenging structural optimization problems in the automotive, naval, and aerospace industries without requiring deep knowledge of structural optimization theory. The scientific community is working actively in this direction, and recent years have seen the publication of educational material that simplifies the understanding of structural optimization algorithms and guides the development of related optimization software. These resources are based on different models, such as moving mesh methods (Allaire and Pantz 2006; Dapogny et al. 2018; Courtais et al. 2019; Allaire 2007), level-sets (Laurain 2018; Allaire et al. 2002; Bernland et al. 2019), phase fields (Garcke et al. 2015; Dondl et al. 2019; Blank et al. 2014), and SIMPFootnote 1 (Sigmund 2001; Talischi et al. 2012; Bendsøe 1989; Bendsoe and Sigmund 2004), and are implemented in various software environments such as Matlab (Sigmund 2001; Talischi et al. 2012), FreeFem++ (Allaire and Pantz 2006; Dapogny et al. 2018; Allaire et al. 2002), OpenFOAM CFD (Courtais et al. 2019), FEMLAB (Liu et al. 2005), and FEniCS (Laurain 2018; Dokken et al. 2019), to mention just a few.

In this work, we introduce Fireshape: an automated shape optimization library based on the moving mesh approach that requires very limited input from the user. Shape optimization refers to the optimization of domain boundaries and plays an important role in structural design. For instance, shape optimization plays a crucial role in the design of airfoils (He et al. 2019; Wang et al. 2018; Schmidt et al. 2013) and boat hulls (Lombardi et al. 2012; Marinić-Kragić et al. 2016; Abramowski and Sugalski 2017). Shape optimization is also a useful refinement step to be employed after topology optimization (Bendsoe and Sigmund 2004, Ch. 1.4). Indeed, topology optimization allows more flexibility in geometric changes and it is a powerful tool to explore a large design space. However, topology optimization may return slightly blurred (grey-scale) and/or staircase designs (Bendsoe and Sigmund 2004). By adding a final shape optimization step, it is possible to post-process results computed with topology optimization and devise optimal designs with sharp boundaries and interfaces, when this is necessary.

Fireshape is based on the moving mesh shape optimization approach (Allaire 2007, Ch. 6). In this approach, geometries are parametrized with meshes that can be arbitrarily precise and possibly curvilinear. The mesh nodes and faces are then optimized (or “moved”) to minimize a chosen target function. Fireshape has been developed on the moving mesh approach because the latter has a very neat interpretation in terms of geometric transformations and is inherently compatible with standard finite element software, as it relies on the canonical construction of finite elements via pullbacks (Paganini et al. 2018). The main drawback of the moving mesh approach is that it does not allow topological changes in a straightforward and consistent fashion. However, Fireshape has been developed to facilitate shape optimization, and topology optimization is beyond its scope.

Fireshape couples the finite element library Firedrake (Rathgeber et al. 2016; Luporini et al. 2017; Homolya et al. 2018; Homolya et al. 2017; Gibson et al. 2020) with the Rapid Optimization Library (ROL) (Ridzal and Kouri 2014). Fireshape allows decoupled discretization of geometries and state constraints and it includes all necessary routines to perform shape optimization (geometry updates, regularization terms, geometric constraints, etc.). To solve a shape optimization problem in Fireshape, users must describe the objective function and the eventual constraints using the Unified Form Language (UFL) (Alnæs et al. 2014), a language embedded in Python to describe variational forms and their finite element discretizations that is very similar to standard mathematical notation. Once objective functions and constraints have been implemented with UFL, users need only to provide a mesh that describes the initial design and, finally, select their favorite optimization algorithm from the optimization library ROL, which contains algorithms for unconstrained, bound constrained, and (in-)equality constrained optimisation problems. In particular, users do not need to spend time deriving shape derivative formulas and adjoint equations by hand, nor worry about their discretization, because Fireshape automates these tasks.

Typically the computational bottleneck of PDE constrained optimization code lies in the solution of the state and the adjoint equation. While Fireshape and Firedrake are both written in Python, to assemble the state and adjoint equations the Firedrake library automatically generates optimized kernels in the C programming language. The generated systems of equations are then passed to the PETSc library (also written in C) and can be solved using any of the many linear solvers and preconditioners accessible from PETSc (Balay et al. 2019; Balay et al. 1997; Dalcin et al. 2011; Chevalier and Pellegrini 2008; Amestoy et al. 2000; Hypre 2020). This combination of Python for user facing code and C for performance critical parts is well established in scientific computing as it provides highly performant code that is straightforward to develop and use. Finally, we mention that Fireshape, just as Firedrake, PETSc and ROL, supports MPI parallelization and hence can be used to solve even large-scale three-dimensional shape optimization problems. In particular, Firedrake has been used to solve systems with several billion degrees of freedom on supercomputers with tens of thousands of cores (see, e.g., Mitchell and Müller 2016; Farrell et al. 2019), and we emphasize that any PDE solver written in Firedrake can be used for shape optimization problems with Fireshape.

Fireshape is an open-source software licensed under the GNU Lesser General Public License v3.0. Fireshape can be downloaded at https://github.com/Fireshape/Fireshape .

Its documentation contains several tutorials and is available at https://fireshape.readthedocs.io/en/latest/. To illustrate Fireshape’s capabilities and ease of use, in Section 2 we provide a tutorial and solve a three-dimensional shape optimization problem constrained by the nonlinear Navier-Stokes equations. The shape optimization knowledge required to understand this tutorial is minimal. In Section 3, we provide another tutorial based on a shape optimization problem constrained to the linear elasticity equation. In Section 4, we describe in detail the rich mathematical theory that underpins Fireshape. In Section 5, we describe Fireshape’s main classes and Fireshape’s extended functionality. Finally, in Section 6, we provide concluding remarks.

2 Example: shape optimization of a pipe

For this hands-on introduction to Fireshape, we first consider a viscous fluid flowing through a pipe Ω (see Fig. 1) and aim to minimize the kinetic energy dissipation into heat by optimizing the design of Ω. This is a standard test case (Zhou and Li 2008; Villanueva and Maute 2017; Feppon et al. 2020; Dilgen et al. 2018; Dapogny et al. 2017). To begin with, we need to describe this optimization problem with a mathematical model.

Fig. 1
figure 1

Viscous fluid flows through a pipe Ω from the left to the right. A poor pipe design can lead to an excessive amount of kinetic energy being dissipated into heat

We assume that the fluid velocity u and the fluid pressure p satisfy the incompressible Navier-Stokes equations (Elman et al. 2014, Eq. (8.1)), which read

$$ \begin{array}{@{}rcl@{}} -2\nu \nabla \cdot \varepsilon{\mathbf{u}} + ({\mathbf{u}}\cdot \nabla) {\mathbf{u}} + \nabla \mathrm{p} &= 0 & \text{in } {\Omega}, \end{array} $$
(1a)
$$ \begin{array}{@{}rcl@{}} \text{div } {\mathbf{u}} &= 0& \text{in } {\Omega}, \end{array} $$
(1b)
$$ \begin{array}{@{}rcl@{}} {\mathbf{u}} &= {\mathbf{g}} &\text{on } \partial{\Omega}\setminus {\varGamma}, \end{array} $$
(1c)
$$ \begin{array}{@{}rcl@{}} \mathrm{p}{\mathbf{n}} - 2\nu \varepsilon {\mathbf{u}} {\mathbf{n}} & = 0 &\text{on } {\varGamma}, \end{array} $$
(1d)

where ν denotes the fluid viscosity, \(\varepsilon {\mathbf {u}} = \varepsilon ({\mathbf {u}}) = \frac {1}{2}(\nabla {\mathbf {u}}+\nabla {\mathbf {u}}^{\top })\), ∇u is the derivative (Jacobian matrix) of u and ∇u is the derivative transposed, Γ denotes the outlet, and the function g is a Poiseuille flow velocity (Elman et al. 2014, p. 122) at the inlet and zero on the pipe walls. In our numerical experiment, the inlet is a disc of radius 0.5 in the xy-plane, and g(x, y, z) = (0,0,1 − 4(x2 + y2)) on the inlet.

To model the kinetic energy dissipation, we consider the diffusion term in (1a) and introduce the function

$$ \mathrm{J}({\Omega}) = {\int}_{{\Omega}} \nu \varepsilon {\mathbf{u}} : \varepsilon{\mathbf{u}} \mathrm{d}{\boldsymbol{x}}, $$
(2)

where the colon symbol : denotes the Frobenius inner product, that is, εu : εu = trace((εu)εu).

Now, we can formulate the shape optimizations problem we are considering. This reads:

$$ \text{Find } {\Omega}^{*} \text{ such that } \mathrm{J}({\Omega}^{*}) = \inf \mathrm{J}({\Omega}) \text{ subject to (1).} $$
(3)

To make this test case more interesting, we further impose a volume equality constraint on Ω. Otherwise, without this volume constraint, the solution to this problem would be a pipe with arbitrarily large diameter.

In the next subsections, we explain step by step how to solve this shape optimization problem in Fireshape. To this end, we need to create: a mesh that approximates the initial guess Ω (Section 2.1), an object that describes the PDE constraint (1) (Section 2.2), an object that describes the objective function (2) (Section 2.3), and, finally, a “main file” to set up and solve the optimization problem (3) with the additional volume constraint (Section 2.4).

2.1 Step 1: Provide an initial guess

The first step is to provide a mesh that describes an initial guess of Ω. For this tutorial, we create this mesh using the software Gmsh (Geuzaine and Remacle 2009). The initial guess employed is sketched in Fig. 1. The only mesh detail necessary to understand this tutorial is that, in Listing 1, the number 10 corresponds to the inlet, wheres the boundary flags 12 and 13 refer to the pipe’s boundary. For the remaining geometric details, we refer to the code archived on Zenodo (2020).

Listing 1
figure a

Incompressible Navier-Stokes solver based on Taylor-Hood finite elements. In particular, the weak formulation described in (4) is implemented in lines 21–23

2.2 Step 2: Implement the PDE constraint

The second step is to implement a finite element solver of the Navier-Stokes equations (1). To derive the weak formulation of (1a), we multiply (1a) with a test (velocity) function v that vanishes on Ω ∖Γ, and (1b) with a test (pressure) function q. Then, we integrate over Ω, integrate by parts (Elman et al. 2014, Eq. (3.18)), and impose the boundary condition (1d). The resulting weak formulation of equations (1) reads:

$$ \begin{array}{@{}rcl@{}} &&\text{Find }{\mathbf{u}}\text{ such that }{\mathbf{u}} = {\mathbf{g}}\text{ on } \partial{\Omega}\setminus \varGamma\text{ and}\\ &&{\int}_{{\Omega}} 2\nu \varepsilon {\mathbf{u}} :\varepsilon {\mathbf{v}} - \mathrm{p}\text{ div }({\mathbf{v}}) + {\mathbf{v}}\cdot (\nabla {\mathbf{u}}){\mathbf{u}} + \mathrm{q}\text{ div }({\mathbf{u}}) \mathrm{d}{\boldsymbol{x}} = 0\\ &&\text{for any pair }({\mathbf{v}}, \mathrm{q}). \end{array} $$
(4)

To implement the finite element discretization of (4), we create a class NavierStokesSolver that inherits from the Fireshape’s class PdeConstraint, see Listing 1. To discretize (4), we employ P2-P1 Taylor-Hood finite elements, that is, we discretize the trial and test velocity functions u and v with piecewise quadratic Lagrangian finite elements, and the trial and test pressure functions p and q with piecewise affine Lagrangian finite elements. It is well known that this is a stable discretization of the incompressible Navier-Stokes equations (Elman et al. 2014, pp. 136–137).

To address the nonlinearity in (4), we use PETSc’s Scalable Nonlinear Equations Solvers (SNES) (Balay et al. 2019; Balay et al. 1997; Dalcin et al. 2011; Chevalier and Pellegrini 2008; Amestoy et al. 2000; Hypre 2020). In each iteration, SNES linearizes (4) and solves the resulting system with a direct solver. In general, it is possible that the SNES solver fails to converge sufficiently quickly (in our code, we allow at most 100 SNES iterations). For instance, this happens if the finite element mesh self-intersects, or if the initial guess used to solve (4) is not sufficiently good. Most often, these situations happen when the optimization algorithm takes an optimization step that is too large. In these cases, we can address SNES’ failure to solve (4) by reducing the optimization step. In practice, we deal with these situations with Python’s try: ... except: ... block. If the SNES solver fails with a ConvergenceError, we catch this error and set the boolean flag self.failed_to_solve to True. This flag is used to adjust the output of the objective function J, see Section 2.3.

2.3 Step 3: Implement the objective function

The third step is to implement a code to evaluate the objective function J defined in (2). For this, we create a class EnergyDissipation that inherits from Fireshape’s class ShapeObjective (see Listing 2). Of course, evaluating J requires access to the fluid velocity u. This access is implemented by assigning the variable self.pde_solver. This variable gives access also to the variable NavierStokesSolver.failed_to_solve, which can be used to control the output of J when the Navier-Stokes’ solver fails to converge. Here, we decide that the value of J is NaN (“not a number”) if the Navier-Stokes’ solver fails to converge.

Listing 2
figure b

Objective function J (2), which quantifies the kinetic energy dissipation of the fluid. Note that J returns NaN (“not a number”) if the solver of the PDE constraint (4) fails to converge

2.4 Final step: Set up and solve the problem

At this stage, we have all the necessary ingredients to tackle the shape optimization problem (3). The final step is to create a “main file” that loads the initial mesh, sets up the optimization problem, and solves it with an optimization algorithm. The rest of this section contains a line-by-line description of the “main file”, which is listed in Listing 3.

Listing 3
figure c

Minimize the kinetic energy dissipation of a fluid using Fireshape

  • In lines 1–6, we import all necessary Python libraries and modules.

  • In lines 8–13, we load the mesh of the initial design and we specify to discretize perturbations of the domain Ω using quadratic B-splines with support in a box that does not include the inlet and the outlet. In this example, we also impose some boundary regularity on B-splines and limit perturbations to be only in direction of the y-axis. Sections 5.1 and 5.2 provide more details about the Fireshape classes ControlSpace and InnerProduct.

  • In lines 15–16, we initiate the Navier-Stokes finite element solver.

  • In lines 18–19, we tell Fireshape to store the finite element solution to Navier-Stokes’ equations in the folder solution every time the domain Ω is updated. We can visualize the evolution of u along the optimization process by opening the file u.pvd with Paraview (Ahrens et al. 2005).

  • In lines 21–22, we initiate the objective function J and the associated reduced functional, which is used by Fireshape to define the appropriate Lagrange functionals to shape differentiate J. We refer to Section 4.2 for more details about shape differentiation using Lagrangians. We stress that Fireshape does not require users to derive (and implement) shape derivative formulas by hand. The whole shape differentiation process is automated using pyadjoint (Ham et al. 2019; Dokken et al. 2020), see Remark 1.

  • In lines 24–25, we add an additional regularization term to J to promote mesh quality of domain updates. This regularization term controls the pointwise maximum singular value of the geometric transformation used to update Ω (Wechsung 2019). See Section 4.2, Fig. 9, and Remark 3 for more information about the role of geometric transformations in Fireshape.

  • In lines 27–30, we set up an equality constraint to ensure that the volume of the initial and the optimized domains are equal.

  • In lines 32–43, we select an optimization algorithm from the optimization library ROL. More specifically, we use an augmented Lagrangian approach (Nocedal and Wright 2006, Ch. 17.3) with limited-memory BFGS Hessian updates (Nocedal and Wright 2006, Ch. 6.1) to deal with the volume equality constraint, and a Trust-Region algorithm (Nocedal and Wright 2006, Ch. 4.1) to solve the intermediate models generated by the augmented Lagrangian algorithm.

  • In lines 44–47, finally, we gather all information and solve the problem.

Remark 1

A reader may wonder why Fireshape does not require information about shape derivative formulas and adjoint equations to solve a PDE-constrained shape optimization problem. This is possible because Fireshape employs UFL’s and pyadjoint’s automated shape differentiation and adjoint derivation capabilities (Ham et al. 2019; Dokken et al. 2020). In particular, UFL combines the automated construction of finite element pullbacks with symbolic differentiation to automate the evaluation of directional shape derivatives along vector fields discretized by finite elements (Ham et al. 2019). This process mimics the analytical differentiation of shape functions and is equivalent to the “optimize-then-discretize” paradigm, i.e. it yields exact (up to floating point accuracy) derivatives.

2.5 Results

Running the code contained in Listing 3 optimizes the pipe design when the fluid viscosity ν is 0.1, which corresponds to Reynolds number R = 1./ν = 10. Of course, the resulting shape depends on the fluid viscosity. A natural question is how the optimized shape depends on this parameter. To answer this question, we can simply run Listing 3 for different Reynolds numbers (by modifying line 13 with the desired value) and inspect the results. Here we perform this comparison for R∈{1,250,500,750,1000}.Footnote 2

In Fig. 2, we show the initial design and plot the magnitude of the fluid velocity on a cross section of the pipe for different Reynolds numbers.

Fig. 2
figure 2

Initial design of the pipe and velocity solutions for R = 1,250,500,750,1000 (from top to bottom) inside the pipe. Red corresponds to high velocity, blue corresponds to low velocity

In Fig. 3, we show the resulting optimized shapes, and in Fig. 4 the corresponding magnitudes of the fluid velocity. Qualitatively, we observe that, as the Reynolds number increase, we obtain increasingly S-shaped designs that avoid high curvature at the two fixed ends. Finally, we remark that the objective is reduced by approximately 6.9%, 9.5%, 10.8%, 11.7% and 12.1% in at most 10 augmented Lagrangian steps, respectively. Each numerical experiment was run in parallel on a server with 36 cores.

Fig. 3
figure 3

Optimized shapes for R = 1,250,500,750,1000 (from top to bottom)

Fig. 4
figure 4

Velocity field for optimized shapes for R = 1,250,500,750, 1000 (from top to bottom). Red corresponds to high velocity, blue corresponds to low velocity

3 Example: shape optimization of a cantilever

In this second tutorial, we consider another shape optimization classic (Allaire and Pantz 2006; Allaire 2007): the minimization of the compliance of a cantilever Ω (see Fig. 5) subject to a dead surface load g. To make this example reproducible on a basic laptop we consider a two dimensional version of this problem. Adapting the code presented in this section to simulate a three-dimensional cantilever is straightforward.

Fig. 5
figure 5

A cantilever is attached to a wall on the left (Γ1) and pulled downwards on the right (Γ2) by a dead surface load. A poor cantilever design may fail to offer sufficient support

We model the cantilever elastic response using the linear elasticity equations (Braess 2007, Ch. VI, Sect. 3). More precisely, we consider the displacement formulation: the displacement field u satisfies the variational problem

$$ {\int}_{\Omega} \sigma({\mathbf{u}}):\epsilon({\mathbf{v}}) \mathrm{d}{\boldsymbol{x}} = {\int}_{\varGamma_{2}} {\mathbf{g}}\cdot{\mathbf{v}} \mathrm{d}S \quad \text{ for every } {\mathbf{v}}, $$
(5)

where σ(u) = λ div (u)I + 2με(u), λ and μ are the Lamé constants, I is the identity matrix, \(\varepsilon ({\mathbf {u}}) = \frac {1}{2}(\nabla {\mathbf {u}}+\nabla {\mathbf {u}}^{\top })\), ∇u is the derivative (Jacobian matrix) of u and ∇u is the derivative transposed, the colon symbol : denotes the Frobenius inner product, that is σ(u) : ε(v) = trace(σ(u)ε(v)), and Γ2 denotes the part of the boundary that is subject to the surface load g. Additionally, although not explicitly indicated in (5), the displacement u vanishes on Γ1, which is the part of the boundary Ω that corresponds to the wall (see Fig. 5).

To model the compliance of the structure Ω, we consider the functional

$$ \mathrm{J}({\Omega}) = {\int}_{{\Omega}} \sigma ({\mathbf{u}}) : \varepsilon({\mathbf{u}}) \mathrm{d}{\boldsymbol{x}}, $$
(6)

where u is the displacement and satisfies (5).

As typical for this shape optimization test case, we also impose a volume equality constraint on Ω to prescribe the amount of material used to fabricate the cantilever.

Similarly to Section 2, in the following subsections we explain how to solve this shape optimization test case in Fireshape.

3.1 Step 1: Provide an initial guess

To create the mesh of the initial guess, we use again the software Gmsh (Geuzaine and Remacle 2009). The initial guess employed is sketched in Fig. 5. The only mesh detail necessary to understand this tutorial is that, in Listing 4, the number 1 corresponds to Γ1, whereas the boundary flag 2 refers to Γ2. For the remaining geometric details, we refer to the code archived on Zenodo (2020).

Listing 4
figure d

Linear elasticity solver

3.2 Step 2: Implement the PDE constraint

In this example, the PDE constraint (5) is already in weak form. To implement its finite element discretization, we create a class LinearElasticitySolver that inherits from Fireshape’s class PdeConstraint (see Listing 4). To discretize (5), we employ the standard piecewise affine Lagrangian finite elements (Braess 2007, Ch. II, Sect. 5). To solve the resulting linear system, we employ a direct solver. This is sufficiently fast for the current 2D example. For readers interested in creating a three-dimensional version of this example, we suggest replacing the direct solver with a Krylov method preconditioned by one of the algebraic multigrid methods that can be accessed via PETSc.

3.3 Step 3: Implement the objective function

We implement the objective function J defined in (6) in a class Compliance that inherits from Fireshape’s class ShapeObjective (see Listing 5). This functional accesses the displacement field u via the variable self.pde_solver.

Listing 5
figure e

Objective function J (6), which quantifies the compliance of the structure. Note that J returns NaN (“not a number”) if the mesh has poor quality

To verify that the domain used to compute u is feasible, that is, that the mesh is not tangled, we create a piecewise constant function detDT and interpolate the determinant of the derivative of the transformation T used to generated the updated domains (see Sections 4.2 and 4.3 for more details about the role of the transformation T in Fireshape). If the minimum of detDT is a small number, this indicates that the mesh has poor quality (see also Remark 3), and this negatively affects the accuracy of the finite element method. In this case, we decide that the value of J is NaN (“not a number”) to ensure that only trustworthy simulations are used.Footnote 3

3.4 Final step: Set up and solve the problem

Finally, to shape optimize the initial desing we create a “main file” that loads the initial mesh, sets up the optimization problem, and solves it with an optimization algorithm. The rest of this section contains a line-by-line description of the “main file”, which is listed in Listing 6.

Listing 6
figure f

Minimize the kinetic energy dissipation of a fluid using Fireshape

  • In lines 1–6, we import all necessary Python libraries and modules.

  • In lines 8–11, we load the mesh of the initial design and we specify to discretize perturbations of the domain Ω using piecewise affine Lagrangian finite elements. We also employ a metric inspired by the linear elasticity equations and specify that the boundaries Γ1 and Γ2 cannot be modified. Sections 5.1 and 5.2 provide more details about the Fireshape classes ControlSpace and InnerProduct.

  • In line 13, we initiate the linear elasticity solver.

  • In lines 15–16, we tell Fireshape to store the finite element approximation of the displacement field u in the folder solution every time the domain Ω is updated. We can visualize the evolution of u along the optimization process by opening the file u.pvd with Paraview (Ahrens et al. 2005).

  • In lines 18–19, we initiate the objective function J and the associated reduced functional, which is used by Fireshape to define the appropriate Lagrange functionals to shape differentiate J. We refer to Section 4.2 for more details about shape differentiation using Lagrangians. Note that, as mentioned in Remark 1, Fireshape does not require users to derive (and implement) shape derivative formulas by hand. The whole shape differentiation process is automated using pyadjoint (Ham et al. 2019; Dokken et al. 2020).

  • In lines 21–22, we add an additional regularization term to J to promote mesh quality of domain updates. This regularization term controls the pointwise maximum singular value of the geometric transformation used to update Ω (Wechsung 2019). See Section 4.2, Fig. 9, and Remark 3 for more information about the role of geometric transformations in Fireshape.

  • In lines 24–27, we set up an equality constraint to ensure that the volume of the initial and the optimized domains are equal.

  • In lines 29–39, we select an optimization algorithm from the optimization library ROL. More specifically, we use an augmented Lagrangian approach (Nocedal and Wright 2006, Ch. 17.3) with limited-memory BFGS Hessian updates (Nocedal and Wright 2006, Ch. 6.1) to deal with the volume equality constraint, and a Trust-Region algorithm (Nocedal and Wright 2006, Ch. 4.1) to solve the intermediate models generated by the augmented Lagrangian algorithm.

  • In lines 44–47, finally, we gather all information and solve the problem.

3.5 Results

Figure 6 shows the initial design (top) and the design optimized using Listing 6 (middle). At first look, the result looks reasonable. However, after an inspection of ROL’s output, it becomes apparent that the optimization algorithm stops after 8 (augmented Lagrangian outer) steps because the optimization step lenght becomes too small. This is due to a triangle on the top left corner of the cantilever that becomes almost flat (see Fig. 7, left). This deterioration of the mesh quality is detected by the implementation of the objective function (Listing 5, line 21), which forces the trust-region optimization algorithm to reduce the trust-region radius. After 8 iterations, this leads to an optimization step length that is smaller than 10− 4, and the optimization algorithm terminates. This is a positive result: the algorithm detects that something is wrong and stops the simulation. It is the task of the user to understand what originates the problem and provide a remedy. After a look at the iterates on Paraview, it becomes apparent that optimization algorithms tries to move a node above the boundary Γ1, which is fixed, and this leads to the generation of an elongated triangle. A difficulty with this part of the design was already experienced in Allaire and Pantz (2006), where the authors suggest to “arbitrarily set the shape gradient to zero near the corners of the shape”. Here, we present an alternative solution.

Fig. 6
figure 6

Top: Initial cantilever design. The absolute value of the displacement field u is colored from blue (minimum) to red (maximum). Middle: Cantilever designed optimized using Listing 6. Bottom: Cantilever designed optimized by increasing the regularization of J in line 21 of Listing 6

Fig. 7
figure 7

Left: Mesh detail of upper left corner of the cantilever design optimized with Listing 6. The leftmost triangle has almost collapsed to a line. Right: Same mesh detail when the regularization of J in line 21 of Listing 6 is increased. The elongated triangle is no longer present

As mentioned in the previous paragraph, the issue is that the shape updates lead to the creation of an elongated triangle. To overcome this problem, we can simply increase from 10 to 100 the coefficient of the regularization term in line 21 Listing 6. The increased regularization sufficiently penalizes this unwanted behavior, and the algorithm can further optimize the design (see Fig. 8).

Fig. 8
figure 8

Convergence history of the compliance. When the regularization of J in line 21 of Listing 6 is insufficient, the algorithm stops after eight iterations because a triangle becomes very elongated. However, if sufficient regularization is provided, the algorithm does not experience this issue and further optimizes the design. Finally, we point out that the small value of the compliance after the first iteration is obtained by excessively violating the volume equality constraint. This is subsequently corrected by the augmented Lagrangian algorithm

4 Shape optimization via diffeomorphisms

In this section, we describe the theory that underpins Fireshape. We begin with a brief introduction to PDE-constrained optimization to set the notation and mention the main idea behind optimization algorithms (Section 4.1). Then, we continue with an introduction to shape calculus (Section 4.2). Finally, we conclude with a discussion about the link between shape optimization and parametric finite elements (Section 4.3).

4.1 Optimization with PDE constraints

The basic ingredients to formulate a PDE-constrained optimization problem are the following: a control variable q that lives in a control space Q, a state variable u that lives in a state space U and that solves a (possibly nonlinear) state equation A(q, u) = 0, and a real function \(\mathrm {J}:{\mathbf {Q}}\times {\mathbf {U}}\to \mathbb {R}\) to be minimized.

Example 1

Equation (3) is a PDE-constrained optimization problem. The control variable q corresponds to the domain Ω, the state variable u represents the pair velocity-pressure (u,p), the nonlinear constraint A represents the Navier-Stokes equations (1), and J denotes the objective function (2). The state space U corresponds to the space of pairs (a,b) with weakly differentiable velocities a that satisfy a = g on Ω ∖Γ and square integrable pressures b (Elman et al. 2014, Ch. 8.2). The control space Q is specified in Section 4.2 (see (7)).

MostFootnote 4 numerical methods for PDE-constrained optimization attempt to construct a sequence of controls \(\{{\mathbf {q}}^{(k)}\}_{k\in \mathbb {N}}\) and corresponding states \(\{{\mathbf {u}}^{(k)}\}_{k\in \mathbb {N}}\) such that

$$ \lim_{k\to\infty} \mathrm{J}({\mathbf{q}}^{(k)},{\mathbf{u}}^{(k)}) = \inf_{{\mathbf{q}},{\mathbf{u}}} \{\mathrm{J}({\mathbf{q}},{\mathbf{u}}) : {\mathbf{A}}({\mathbf{q}},{\mathbf{u}}) = \mathbf{0}\}. $$

Often, the sequence \(\{{\mathbf {q}}^{(k)}\}_{k\in \mathbb {N}}\) is constructed using derivatives of the function J and of the constraint A. Common approaches are steepest descent algorithms and Newton methods (in their quasi, Krylov, or semi-smooth versions) (Hinze et al. 2009; Kelley 2003). These algorithms ensure that the sequence \(\{\mathrm {J}({\mathbf {q}}^{(k)},{\mathbf {u}}^{(k)})\}_{k\in \mathbb {N}}\) decreases. In special cases, it is even possible to show that the sequence \(\{{\mathbf {q}}^{(k)}\}_{k\in \mathbb {N}}\) converges (Hinze et al. 2009). Although it may be difficult to ensure these assumptions are met in industrial applications, these optimization algorithms are still powerful tools to improve state-of-the-art designs and are widely used to perform shape optimization.

4.2 Shape optimization and shape calculus

Shape optimization with PDE constraints is a particular branch of PDE-constrained optimization where the control space Q is a set of domain shapes. The space of shapes is notoriously difficult to characterize uniquely. For instance, one could describe shapes through their boundary regularity, or as level-sets, or as local epigraphs (Delfour and Zolésio 2011, Ch. 2). The choice of the shapes’ space characterization plays an important role in the concrete implementation of a shape optimization algorithm, and it can also affect formulas that result by differentiating J with respect to perturbations of the shape q. To be more precise, different methods generally lead to the same first order shape derivative formula, but differ on shape derivatives of higher order (Delfour and Zolésio 2011, ch. 9)

In this work, we model the control space Q as the images of bi-Lipschitz geometric transformations T applied to an initial set \({\Omega }\subset \mathbb {R}^{d}\) (Delfour and Zolésio 2011, ch. 3), that is,

$$ {\mathbf{Q}} := \{{\mathbf{q}} = {\mathbf{T}}({\Omega}) : {\mathbf{T}}:\mathbb{R}^{d}\to\mathbb{R}^{d} \text{ is bi-Lipschitz} \}, $$
(7)

see Fig. 9. We choose this model of Q because it provides an explicit description of the domain boundaries via (T(Ω)) = T(Ω), and because it is compatible with higher order finite elements (Paganini et al. 2018), as explained in detail in the Section 4.3. Henceforth, we use the term differomorphism to indicate that a geometric transformation T is bi-Lipschitz.

Fig. 9
figure 9

To construct the control space Q, we select an initial set Ω and a set of diffeomorphisms {T} (black arrows), and collect every image T(Ω)

In this setting, the shape derivative of J corresponds to the classical Gâteaux derivative in the Sobolev space \(W^{1,\infty }(\mathbb {R}^{d},\mathbb {R}^{d})\) (Hinze et al. 2009, Def. 1.29). To see this, let us momentarily remove the PDE constraint, and only consider a shape functional of the form Ω↦J(Ω). The shape derivative of J at Ω is the linear and continuous operator \(\text {dJ}({\Omega }, \cdot ):W^{1,\infty }(\mathbb {R}^{d},\mathbb {R}^{d})\to \mathbb {R}\) defined by

$$ \text{dJ}({\Omega},{\mathbf{V}}) := \lim_{t\searrow 0}\frac{\mathrm{J}({\Omega}_{t}) - \mathrm{J}({\Omega})}{t}, $$
(8)

where Ωt is the set Ωt = {x + tV(x) : x ∈Ω} (Allaire 2007, Def. 6.15). By replacing Ω with q = I(Ω), where I denotes the identity transformation defined by I(x) = x for any \({\mathbf {x}}\in \mathbb {R}^{d}\), (8) can be equivalently rewritten as

$$ \text{dJ}({\mathbf{q}},{\mathbf{V}}) := \lim_{t\searrow 0}\frac{\mathrm{J}({\mathbf{q}}+t{\mathbf{V}}) - \mathrm{J}({\mathbf{q}})}{t}. $$

We highlight that this interpretation immediately generalizes to any q in Q and can be used to define higher order shape derivatives.

The same definition (8) of shape derivative holds in the presence of PDE constraints: the shape derivative at q of the function \(\mathrm {J}:{\mathbf {Q}}\times {\mathbf {U}}\to \mathbb {R}\) subject to A(q, u) = 0 is the linear and continuous operator defined by

$$ \text{dJ}({\mathbf{q}},{\mathbf{u}},{\mathbf{V}}) := \lim_{t\searrow 0}\frac{\mathrm{J}({\mathbf{q}}+t{\mathbf{V}},{\mathbf{u}}_{t}) - \mathrm{J}({\mathbf{q}},{\mathbf{u}})}{t}, $$
(9)

where ut is the solution to A(q + tV, ut) = 0. Computing shape derivative formulas using (9) may present the difficulty of computing the shape derivative of u, which intuitively arises by the “chain rule” formula. The shape derivative of u, which is sometimes called “material derivative” of u, can be eliminated with the help of adjoint equations (Hinze et al. 2009, Section 1.6.2). This process can be automated by introducing the Lagrange functional (Hinze et al. 2009, Section 1.6.3)

$$ {\mathcal{L}}({\mathbf{q}},{\mathbf{u}},{\mathbf{p}}) := \mathrm{J}({\mathbf{q}},{\mathbf{u}}) + \langle {\mathbf{A}}({\mathbf{q}},{\mathbf{u}}),{\mathbf{p}}\rangle. $$
(10)

The term 〈A(q, u),p〉 stems from testing the equation A(q, u) = 0 with a test function p in the same way it is usually done when writing a PDE in its weak form.

Example 2

If A denotes the Navier-Stokes (1), then 〈A(q, u),p〉 corresponds to the weak formulation (4).

The advantage of introducing the Lagrangian (10) is that, by choosing p as the solution to the adjoint equation

$$ \langle \partial_{\mathbf{u}}{\mathbf{A}}({\mathbf{q}},{\mathbf{u}}),{\mathbf{p}}\rangle = -\partial_{\mathbf{u}} \mathrm{J}({\mathbf{q}},{\mathbf{u}})\quad \text{for all } {\mathbf{u}} \text{ in } {\mathbf{U}}, $$

where u denotes the partial differentiation with respect to the variable u, the shape derivative of J can be computed as

$$ \text{dJ}({\mathbf{q}},{\mathbf{u}},{\mathbf{V}}) = \partial_{\mathbf{q}}{\mathcal{L}}({\mathbf{q}},{\mathbf{u}},{\mathbf{p}},{\mathbf{V}}), $$

where q denotes partial differentiation with respect to the variable q. This is advantageous because partial differentiation does not require computing the shape derivative of u.

The Lagrangian approach to compute derivatives of PDE-constrained functionals is well established (Ito and Kunisch 2008), and its steps can be replicated by symbolic computation software. Probably, the biggest success in this direction is the pyadjoint project (Farrell et al. 2013; Mitusch et al. 2019), which derives “the adjoint and tangent-linear equations and solves them using the existing solver methods in FEniCS/Firedrake” (Mitusch et al. 2019). Thanks to the shape differentiation capabilities of UFL introduced in Ham et al. (2019), pyadjoint is also capable of shape differentiating PDE-constrained functionals along directions discretized by finite elements (Dokken et al. 2020).

Remark 2

Optimization algorithms are usually based on steepest descent directions to update the control variable q. A steepest descent direction is a direction V that minimizes the derivative dJ. Since dJ is linear, it is necessary to introduce a norm ∥⋅∥ on the space of possible perturbations {V} (the tangent space of Q at q), and to restrict the search of a steepest descent direction to directions V of length ∥V∥ = 1. A natural choice would be to select the \(W^{1,\infty }\)-norm,Footnote 5 with respect to which a minimizer has been shown to exist for most functionals (Paganini et al. 2018, Prop. 3.1). However, in practice it is more convenient to employ a norm that is induced by an inner product, so that the steepest descent direction corresponds to the Riesz representative of dJ with respect to the inner product (Hinze et al. 2009, p. 98).

4.3 Geometric transformations, moving meshes, and parametric finite elements

To solve a PDE-constrained optimization problem iteratively, it is necessary to employ a numerical method that is capable of solving the constraint A(q, u) = 0 for any feasible control q. In shape optimization, this translates into the requirement of a numerical scheme that can solve a PDE on a domain that changes at each iteration of the optimization algorithm. There are several competing approaches to construct a numerical scheme with this feature, such as the level-set method (Allaire et al. 2002) or the phase field approach (Blank et al. 2014), among others.

In Fireshape, we employ the approach sometimes know as “moving mesh” method (Paganini et al. 2018; Allaire 2007). In its simplest version (see Fig. 10), this method replaces (or approximates) the initial domain Ω with a polygonal mesh Ωh. On this mesh, the state and adjoint equations are solved with a standard finite element method, whose construction on polygonal meshes is immediate. For instance, depending on the nature of the state constraint, one may solve the state and adjoint equations using linear Lagrangian or P2-P1 Taylor-Hood finite elements (see Section 2.2). With the state and adjoint solutions at hand, one employs shape derivatives (see Remark 2 and Section 5.2) to update the coordinates of mesh nodes while retaining the mesh connectivity of Ωh. This leads to a new mesh that represents an improved design. This update process is repeated until some prescribed convergence criteria are met.

Fig. 10
figure 10

Simplest approach to PDE-constrained shape optimization. An initial mesh (left) is used to compute state and adjoint variables. This information, together with shape derivatives, is used to devise an update of the nodes’ coordinates (center). A new and improved initial guess is obtained by updating the nodes’ coordinates and retaining the initial mesh connectivity (right). This process is repeated until convergence

The moving mesh method we just described is a simple and yet powerful method. However, in its current formulation, it requires polyhedral meshes, which limits the search space Q to polyhedra. In the remaining part of this section, we describe an equivalent interpretation of the moving mesh method that generalizes to curved domains. Additionally, this alternative interpretation allows approximating state and adjoint variables with arbitrarily high-order finite elements without suffering from reduction of convergence order due to poor approximation of domain boundaries (Ciarlet 2002, Ch. 4.4).

We begin by recalling the standard construction of parametric finite elements. For more details, we refer to (Ciarlet2002, Sections 2.3 and 4.3). To construct a parametric finite element space, one begins by partitioning the domain Ω into simpler geometric elements {Ki} (usually triangles or tetrahedra, as depicted in the first row of Fig. 11). Then, one introduces a reference element \(\hat {K}\) and a collection of diffeomorphisms Fi that map the reference element \(\hat {K}\) to the various Kis, that is, \({\mathbf {F}}_{i}(\hat {K}) = K_{i}\) for every value of the index i (as depicted in the second row of Fig. 11). Finally, one considers a set of local reference basis functions \(\{\hat {b}_{j}\}\) defined on the reference element \(\hat {K}\), and defines local basis functions \(\{{b_{j}^{i}}\}\) on each Ki via the pullback \({b_{j}^{i}}({\mathbf {x}}):= \hat {b}_{j}({\mathbf {F}}_{i}^{-1}({\mathbf {x}}))\) for every x in Ki. These local basis functions are used to construct global basis functions that span the finite element space. An important property of this construction is that the diffeomorphisms Fi can be expressed in terms of local linear Lagrangian basis functionsFootnote 6\(\{\hat {\beta }_{m}\}\), that is, there are some coefficient vectors \(\{\boldsymbol {\mu }_{m}^{i}\}\) such that

$$ {\mathbf{F}}_{i}({\mathbf{x}}) = \sum\limits_{m} \boldsymbol{\mu}_{m}^{i} \hat{\beta}_{m}({\mathbf{x}}) \quad \text{for every} {\mathbf{x}} \text{ in } \hat{K}. $$
(11)

Finite elements constructed following this procedure are usually called parametric, because they rely on the parametrization {Fi}. Note that the most common finite elements families, such as Lagrangian, Raviart–Thomas, or Nédélec finite elements, are indeed parametric.

Fig. 11
figure 11

To construct finite element basis functions, one usually begins by triangulating a domain Omega (first row) and then introducing diffeomorphisms Fi that map the reference element \(\hat {K}\) to the various Ki in the triangulation (second row)

Keeping this knowledge about parametric finite elements in mind, we can revisit the mesh method (see Fig. 10). There, the main idea was to update only nodes’ coordinates and keep the mesh connectivity unchanged, so that constructing finite elements on the new mesh is straightforward. In Paganini et al. (2018), it has been shown that the new finite element space can also be obtained by modifying the parametric construction of finite elements on the original domain Ω. In the next paragraphs, we give an extended explanation (with adapted notation) of the demonstration given in Paganini et al. (2018).

Let T denote the transformation employed to modify the mesh Ωh on the left in Fig. 10 into the new and perturbed mesh Th) on the right in Fig. 10. Additionally, let {T(Ki)} denote the simple geometric elements that constitute the latter. Using the parametric approach, we can construct finite elements on the new mesh by introducing a collection of diffeomorphisms \(\tilde {\mathbf {F}}_{i}\) that map the reference element \(\hat {K}\) to the various T(Ki)s, that is, \(\tilde {\mathbf {F}}_{i}(\hat {K}) = {\mathbf {T}}(K_{i})\) for every value of the index i; see Fig. 12.

Fig. 12
figure 12

The standard construction of finite elements on the perturbed mesh {T(Ki)} employs diffeomorphisms \(\tilde {\mathbf {F}}_{i}\) that map the reference element \(\hat {K}\) to the various perturbed elements T(Ki)

The behavior of the transformation T in Fig. 10 is prescribed only the mesh nodes. Since its behavior on the interior of the mesh triangles can be chosen arbitrarily, we can decide that T is piecewise affine on each triangle. This convenient choice implies that T can be written as a linear combination of piecewise affine Lagrangian finite elements defined on the first mesh, that is, \({\mathbf {T}}({\mathbf {x}}) = {\sum }_{\ell } {\boldsymbol {\nu }}_{\ell } B_{\ell }({\mathbf {x}})\) for every x in Ω, where {ν} are some coefficient vectors and {B} are global basis functions of the space of piecewise affine Lagrangian finite elements defined on the partition {Ki}. Since Lagrangian finite elements are constructed via pullbacks to the reference element, for every element Ki there are coefficient vectors \(\{{\boldsymbol {\nu }}_{m}^{i}\}\) so that the restriction \({\mathbf {T}}\vert _{K_{i}}\) of T on Ki can be rewritten as

$$ {\mathbf{T}}\vert_{K_{i}}({\mathbf{x}}) = \sum\limits_{\ell} {\boldsymbol{\nu}}_{\ell} B_{\ell}\vert_{K_{i}}({\mathbf{x}}) = \sum\limits_{m} \tilde{\boldsymbol{\nu}}_{m}^{i} \hat{\beta}_{m}({\mathbf{F}}_{i}^{-1}({\mathbf{x}})). $$

Therefore, the composition \({\mathbf {T}}\vert _{K_{i}}\circ {\mathbf {F}}_{i}\) is of the form

$$ {\mathbf{T}}\vert_{K_{i}}\circ{\mathbf{F}}_{i}({\mathbf{x}}) = \sum\limits_{m} \tilde{\boldsymbol{\nu}}_{m}^{i} \hat{\beta}_{m}({\mathbf{x}}) \quad \text{for every }{\mathbf{x}}\in\hat{K}, $$
(12)

that is, of the same form of (11). This implies that, to construct finite elements on the perturbed geometry Th), we only need to replace the original coefficients \(\{\boldsymbol {\mu }_{m}^{i}\}\) in (11) with the new coefficients \(\{\tilde {\boldsymbol {\nu }}_{m}^{i}\}\) from (12).

This alternative and equivalent viewpoint on the moving mesh method generalizes naturally to higher order finite element approximations of control and state (and adjoint) variables. Indeed, one of the key steps to ensure that higher order finite elements achieve higher order convergence on curved domains is to employ sufficiently accurate polynomial interpolation of domain boundaries (Ciarlet 2002, Ch. 4.4). This boundary interpolation can be encoded in the diffeomorphisms {Fi} by using higher order Lagrangian local basis functions. Therefore, simply employing higher order Lagrangian finite element transformations T leads to a natural extension of moving mesh method to higher order finite elements.

This alternative and equivalent viewpoint generalizes further to allow the use of any arbitrary discretization of the transformation T (for instance, using B-splines (Höllig 2003), harmonic polynomials, or radial basis functions (Wendland 2005)). The only requirement to be fulfilled to ensure the desired order of convergence p is that the maps TFi : xT(Fi(x)) satisfy the asymptotic algebraic estimates

$$ \Vert {\mathbf{D}}^{\alpha} ({\mathbf{T}}\circ{\mathbf{F}}_{i}) \Vert = {\mathcal{O}}(h^{\alpha}) \quad \text{for } 0\leq\alpha\leq p, $$

where \({\mathbf {D}}^{\alpha }({\mathbf {T}}\circ {\mathbf {F}}_{i})\) denotes the αth derivative of TFi. Using a different discretization of the transformation T can give several advantages, like increasing the smoothness T (because finite elements are generally only Lipschitz continuous) or varying how shape updates are computed during the optimization process (Eigel and Sturm 2018).

Remark 3

An issue that can arise with the moving mesh method is that it can lead to poor quality (or even tangled) meshes. In terms of geometric transformations, a mesh with poor quality corresponds to a transformation T for which the value \(\max \limits _{\alpha }\Vert {\mathbf {D}}^{\alpha {\mathbf {T}}} \Vert \) is large (and a tangled mesh to a transformation T that is not a diffeomorphism). To a certain extent, it is possible to enforce moderate derivatives by employing suitable metrics to extract descent directions from shape derivatives (for instance, by using linear elasticity based inner products with a Cauchy-Riemann augmentation (Iglesias et al. 2018)) and/or by adding penalty terms to the functional J. For example, in Sections 2.4 and 3.4 we add a penalization term based on the spectral norm ∥D(TI)∥2 of the Jacobian matrix D(TI). We point out that if Ω is ζ-quasiconvexFootnote 7 and ∥D(TI)∥2 < ζ, then \({\mathbf {T}}:{\Omega }\to \mathbb {R}^{d}\) is bi-Lipschitz, and thus injective.

5 Anatomy of Fireshape

In this section, we give more details about Fireshape’s implementation and features. Fireshape is organized in a few core Python classes (and associated subclasses) that implement the control space Q, the metric to be employed by the optimization algorithm, and the (possibly PDE-constrained) objective function J. The following subsections describe these classes.

5.1 The class ControlSpace

Fireshape models the control space Q of admissible domains using geometric transformations T as in (7) (see also Fig. 9). From a theoretical perspective, the transformations T can be discretized in numerous different ways as long as certain minimal regularity requirements are met. In Fireshape, the class ControlSpace allows the following options: (i) Lagrangian finite elements defined on the same mesh employed to solve the state equation, (ii) Lagrangian finite elements defined on a mesh coarser than the mesh employed to solve the state equation, and (iii) tensorized B-splines defined on a separate Cartesian grid (not to be confused with a spline or Bézier parametrization of the domain boundary, see Fig. 13). In this case, the user must specify the boundary and the refinement level of the Cartesian grid (bbox and level), as well as the order of the underlying univariate B-splines. The user can also set the regulariy of B-splines on the boundary of the Cartesian grid (boundary_regularities), or restrict pertubations to specific directions (fixed_dims).

Fig. 13
figure 13

Fireshape allows discretizing transformations T using tensorized B-splines. On the left, we display a Cartesian grid that that covers the computational domain Ω. On the right, we display a quadratic tensorized B-spline

If discretization (i) can be considered to be the default option, discretization (ii) allows introducing a regularization by discretizing the geometry more coarsely (so-called “regularization by discretization”), whereas B-splines allow constructing transformation with higher regularity (Lagrangian finite elements are only Lipschitz continuous, whereas B-splines can be continuously differentiable and more).

The class ControlSpace can be easily extended to include additional discretization options, such as radial basis functions and harmonic polynomials.

Remark 4

The current implementation of the control space Q includes geometric transformations that can leave the value of a shape function unchanged. For instance, if \(\mathrm {J}({\Omega }) = {\int \limits }_{{\Omega }} \mathrm {d}{\boldsymbol {x}}\), then any diffeomorphism T of the form T = I + V with V0 in Ω and V = 0 on Ω satisfy T(Ω) = Ω, and thus J(T(Ω)) = J(Ω).

The presence of a shape function kernel in the control space Q does not represent a problem for steepest descent and quasi Newton optimization algorithms. However, this kernel leads to singular Hessians, and Newton’s method cannot be applied in a straightforward fashion. The development of control space descriptions that exclude shape function kernels and allow direct applications of shape Newton methods in the framework of finite element simulations is a highly active research field (Sturm 2016; Paganini and Sturm 2019; Etling et al. 2020). We predict these new control spaces will be included in Fireshape as soon as their description has been established.

5.2 The class InnerProduct

To formulate a continuous optimization algorithm, we need to specify how to compute lengths of vectors (and, possibly, how to compute the angle between two vectors). The class InnerProduct addresses this requirement and allows selecting an inner product \((\cdot , \cdot )_{{\mathscr{H}}}\) to endow the control space Q with.Footnote 8

The choice of the inner product affects how steepest-descent directions are computed. Indeed, a steepest-descent direction is a direction V of length \(\Vert {\mathbf {V}}\Vert _{{\mathscr{H}}} = 1\) such that dJ(q, V) is minimal. Let α := ∥dJ(q,⋅)∥ denote the length of the operator dJ(q,⋅) measured with respect to the dual norm. Then, as explained Hinze et al. (2009, p. 103), the steepest descent direction V satisfies the equation

$$ \alpha({\mathbf{V}},{\mathbf{W}})_{\mathcal{H}} = -\text{dJ}({\mathbf{q}},{\mathbf{W}})\quad \text{for all } {\mathbf{W}} \text{ in } \mathcal{H}, $$

which clearly depends on the inner product \((\cdot , \cdot )_{{\mathscr{H}}}\).

The control space Q can be endowed with different inner products. In Fireshape, the class InnerProduct allows the following options: (i) an H1(Ω) inner product based on standard Galerkin stiffness and mass matrices, (ii) a Laplace inner product based on the Galerkin stiffness matrix, and (iii) an elasticity inner product based on the linear elasticity mechanical model. These options can be complemented with additional homogeneous Dirichlet boundary conditions to specify parts of the boundary Ω that are not to be modified during the shape optimization procedure.

Although all three options are equivalent from a theoretical perspective, in practice it has been observed that option (iii) generally leads to geometry updates that result in meshes of higher equality compared to options (i) and (ii). A thorough comparison is available in Iglesias et al. (2018), where the authors also suggest to consider complementing these inner products with terms stemming from Cauchy-Riemann equations to further increase mesh quality. This additional option is readily available in Fireshape.

5.3 The classes Objective and PdeConstraint

In the vast majority of cases, users who aim to solve a PDE-constrained shape optimization problem are only required to instantiate the two classes Objective and PdeConstraint, where they can specify the formula of the function J to be minimized and the weak formulation of its PDE constraint A(Ω,u) = 0 (see Sections 2.2 and 2.3, for instance). Since Fireshape is built on top of the finite element library Firedrake, these formulas must be written using the Unified Form Language (UFL). We refer to the tutorials on Firedrake’s website (Firedrake-zenodo 2020) for more details about Firedrake and UFL.

5.4 Supplementary classes

Fireshape also includes a few extra classes to specify additional constraints, such as volume or perimeter constraints on the domain Ω, or spectral constraints to control the singular values of the transformation T. For more details about these extra options, we refer to Fireshape’s documentation and tutorials (Wechsung and Paganini 2020a).

6 Conclusions

We have introduced Fireshape: an open-source and automated shape optimization toolbox for the finite element software Firedrake. Fireshape is based on the moving mesh method and allows users with minimal shape optimization knowledge to tackle challenging shape optimization problems constrained to PDEs. In particular, Fireshape computes adjoint equations and shape derivatives in an automated fashion, allows decoupled discretizations of control and state variables, and gives full access to Firedrake’s and PETSc’s discretization and solver capabilities as well as to the extensive optimization library ROL.