Solving the elasticity equation
Showcases the resolution of the elasticity system.

In this example we will seek to solve the linearized elasticity system. Most of the reference material in the introduction is taken from [1].
Introduction
In the elasticity setting, we are most typically interested in characterizing the elastic displacement of a mechanical structure , which in the mathematical setting is most usually defined as a bounded, Lipschitz domain, whose boundary is decomposed into three disjoint pieces: . Each piece of the boundary has the following semantic meanings:
- on the segment is where the structure is "fixed" or "attached", which is to say that the strucure cannot be displaced or moved
- on the segment is where the traction loads are applied
- the remaining segment corresponds to a traction-free boundary; this is the region where the shape is free to move about
Additionally, can be subjected to body forces . In general, this framework gives rise to the linearized elasticity system:
where is known as the stress tensor of the displacement field . Furthermore, this stress tensor is related to the strain tensor
via Hooke's law
where for any in the set of symmetric matrices,
Here is the identity matrix, and , are the Lamé parameters of the constituent material, satisfying and . In general, as we have said in the Poisson example, we are mainly interested in the variational formulation of this equation. That is we seek to solve the problem:
As far as the mathematical setting is concerned , and the space is defined by:
In particular, this problem is well posed via the classical Lax-Milgram theory. In this example we will be implementing the variational formulation using Rodin's Variational module.
Implementation
For simplicity, we will disregard any body forces by taking . In this vein, we also note that the integral in the variational formulation may be expanded and rewritten into
which should allow us to more easily translate it into code. In fact, the implementation follows exactly the same philosophy as the Poisson case:
// Define boundary attributes int Gamma = 1, GammaD = 2, GammaN = 3, Gamma0 = 4; // Load mesh Mesh Omega = Mesh::load(meshFile); // Functions int d = 2; FiniteElementSpace<H1> Vh(Omega, d); // Lamé coefficients auto mu = ScalarFunction(0.3846), lambda = ScalarFunction(0.5769); // Pull force auto f = VectorFunction{0, -1};
We define the relevant boundary attributes (which we should know beforehand), we load the mesh, we build the (vectorial) finite element space, and define our parameters. The only real difference will be the variational formulation! But even this is easy to implement if you know what the weak formulation looks like:
// Define problem TrialFunction u(Vh); TestFunction v(Vh); Problem elasticity(u, v); elasticity = Integral(lambda * Div(u), Div(v)) + Integral( mu * (Jacobian(u) + Jacobian(u).T()), 0.5 * (Jacobian(v) + Jacobian(v).T())) - BoundaryIntegral(f, v).over(GammaN) + DirichletBC(u, VectorFunction{0, 0}).on(GammaD);
In this case we have just written out the definition of the terms and . Rodin is smart enough to figure out how to build the underlying linear system to solve and assemble it when we need to solve it.
This brings us to the last point which is solving the variational problem. In exactly the same fashion as the previous example, we need only choose a Solver which should allows us to solve the problem.
// Solve problem Solver::CG().setMaxIterations(200) .setRelativeTolerance(1e-12) .printIterations(true) .solve(elasticity); // Save solution u.getGridFunction().save("u.gf"); Omega.save("Omega.mesh");
The full source code may be found below: