General concepts » Shape and topology optimization

Level-set shape optimization: shape derivatives, Hilbertian regularization, and the optimization loop.

Introduction

Shape optimization seeks a domain $ \Omega $ minimizing an objective

\[ J(\Omega) = \int_\Omega j(u_\Omega)\, dx + \ell\, |\Omega|, \]

where $ u_\Omega $ solves a PDE posed on $ \Omega $ (the state equation) and $ \ell $ is a Lagrange multiplier penalizing volume. The canonical benchmark is compliance minimization: the state is linear elasticity and $ J $ is the work of the loads, $ \int_\Omega Ae(u):e(u) $ . Rodin was designed around this problem class — this guide explains the moving parts and how the examples assemble them.

Working examples, in increasing sophistication:

ExampleWhat it shows
examples/ShapeOptimization/SimpleCantilever2D.cppMinimal compliance loop
examples/ShapeOptimization/LevelSetCantilever2D.cppLevel-set representation with remeshing
examples/ShapeOptimization/LevelSetCantilever3D.cppThe same in 3D
examples/ShapeOptimization/LevelSetArch2D.cpp, LevelSetMast2D.cppOther load cases
examples/ShapeOptimization/LevelSetEigenvalue2D.cppEigenvalue objective
examples/ShapeOptimization/LevelSetWNGIRCantilever2D.cppInterface registration (WNGIR) instead of full remeshing
examples/BoundaryOptimizationBoundary-condition/support optimization
examples/DensityOptimizationDensity (SIMP-type) approaches

The shape derivative

Perturbing the domain along a vector field $ \theta $ , $ \Omega_t = (\mathrm{Id} + t\theta)(\Omega) $ , the shape derivative is

\[ J'(\Omega)(\theta) = \lim_{t \to 0} \frac{J(\Omega_t) - J(\Omega)}{t}. \]

The Hadamard structure theorem states that, for smooth data, the derivative concentrates on the boundary and depends only on the normal component:

\[ J'(\Omega)(\theta) = \int_{\partial\Omega} g\; \theta \cdot n\; ds, \]

with a scalar density $ g $ computed from the state (and, for non-self-adjoint objectives, an adjoint state). For compliance with a traction-free optimizable boundary, $ g = Ae(u):e(u) - \ell $ .

Two equivalent discrete realizations exist, and the choice matters:

  • Boundary (Hadamard) form. Assemble $ \int_\Gamma g\, \theta\cdot n $ on the interface facets. Exact in the continuous setting, but discretely concentrated on the interface: the density is quadratic in the strain and inherits mesh noise.
  • Distributed (volume) form. Assemble $ \int_\Omega E : \nabla\theta $ with an Eshelby-type tensor $ E $ ; integrating by parts with the state equation recovers the boundary form analytically. Discretely this yields a smoother, more robust gradient and is generally preferred.

From derivative to velocity: Hilbertian regularization

$ J'(\Omega) $ is a linear functional, not a vector field. To descend, compute its Riesz representative in an $ H^1 $ -type inner product — this simultaneously extends the boundary information into the bulk and smooths it. This is the Hilbert::H1a operator, which solves

\[ \alpha^2 \int_D \nabla\theta : \nabla\xi + \int_D \theta\cdot\xi = -J'(\Omega)(\xi) \qquad \forall \xi, \]

and returns $ \theta $ :

Hilbert::H1a extension(vectorFes);
extension.setAlpha(alpha);                  // regularization length scale
auto theta = extension(dJ);                 // dJ: the assembled shape differential

The parameter $ \alpha $ has units of length and is the smoothing radius* of the descent direction:

  • larger $ \alpha $ → smoother, more global velocities; fewer mesh-frequency oscillations; slower resolution of fine features;
  • too small $ \alpha $ → the velocity inherits interface noise and the descent stagnates or oscillates.

Level-set representation

Representing the shape implicitly, $ \Omega = \{ x : \phi(x) < 0 \} $ with interface $ \Gamma = \{\phi = 0\} $ , allows topology changes (holes merging and splitting) without any surgery. The shape is advanced by transporting $ \phi $ with the descent velocity — the Hamilton–Jacobi/advection step (Advection module):

\[ \partial_t \phi + \theta \cdot \nabla\phi = 0. \]

Two maintenance obligations follow from the mathematics, not from implementation taste:

  1. Redistancing. Transport degrades the signed-distance property ( $ |\nabla\phi| = 1 $ ); normals, band widths, and step-size control all silently assume it. Restore it periodically with the fast marching method (Eikonal::FMM) or the PDE-based models in Distance (Eikonal, Poisson, SignedPoisson, or the Rvachev / SpaldingTucker normalizations).
  2. Step-size (CFL) control. The interface should move at most a bounded number of cells per iteration; combine a time-step cap with a line search on the true objective. A descent step accepted without an objective decrease check can jump out of the basin entirely (a classic failure mode: the "optimized" material floods the whole bounding box).

Getting a computable domain from the level set

The state equation needs a domain to integrate over. Two strategies:

  • Body-fitted discretization. Cut the zero set into the mesh so that $ \Gamma $ becomes a set of interface facets: MMG's LevelSetDiscretizer produces the body-fitted mesh, MMG::Adapt and MMG::MeshOptimizer maintain metric conformity and element quality across iterations. Accurate domain and interface integrals; the cost is remeshing every iteration.
  • Interface registration (WNGIR). Instead of remeshing, displace the existing mesh so its interface tracks $ \{\phi=0\} $ : the Adaptation module's WNGIR solver. Keeps the mesh topology and connectivity stable between iterations.
  • Ersatz material / density. Keep a fixed mesh and interpolate material properties (void as weak material) — the examples/DensityOptimization family. No remeshing, at the price of a modeling error controlled by the material contrast.

The optimization loop

Putting it together, one iteration of a level-set shape optimization reads:

// 1. Discretize the current domain from phi (remesh / register).
// 2. Solve the state equation on the current domain.
// 3. Evaluate the objective; assemble the shape differential dJ.
// 4. Extend/regularize: theta = H1a(vectorFes).setAlpha(alpha)(dJ).
// 5. Line search on J along theta (with a CFL cap on the step).
// 6. Advect phi by the accepted step.
// 7. Redistance phi (every few iterations).

Judge a run by measured quantities: a monotone objective history (the line search guarantees it), the volume tracking its multiplier target, interface quality (no inverted elements), and — after changes to any derivative — the finite-difference check of the shape derivative.

See also