Laminated Plates with feax.mechanics.shell
The feax.mechanics.shell module provides a first-order shear-deformation theory (FSDT,
"Mindlin") plate model together with classical lamination theory (CLT) helpers for
building composite (multi-layer) laminates. This guide walks through the module top to
bottom: lamina stiffness → laminate assembly → thermal loads → kinematics → the weak form
and Problem, and finishes with a worked thermal-warping example.
All tensors are kept in physical index form (C_ijkl, eps_ij, …) rather than Voigt
vectors, so they compose cleanly with jax.numpy.einsum and stay differentiable.
The plate model
A Mindlin plate carries five degrees of freedom per node, split into two FE variables on the same 2D mesh:
| Variable | Components | vec | Meaning |
|---|---|---|---|
var0 | 3 | mid-surface translations | |
var1 | 2 | section rotations |
The constitutive law relates the membrane strain , curvature , and transverse-shear strain to the stress resultants , , through the laminate stiffness matrices , , , :
The whole module exists to produce — and the thermal resultants
— and to turn them into a feax.Problem.
1. Lamina stiffness
A single ply (lamina) is described by its plane-stress stiffness tensor C_ijkl of shape
(2, 2, 2, 2), in the ply's material axes (fibre = local 1-axis).
from feax.mechanics import shell
# Isotropic ply
C_iso = shell.isotropic_in_plane_stiffness(E=70e9, nu=0.3)
# Orthotropic ply (e.g. CFRP): fibre stiffness E1 ≫ transverse E2
C_cfrp = shell.orthotropic_in_plane_stiffness(E1=140e9, E2=10e9, G12=5e9, nu12=0.30)
Transverse-shear stiffness is supplied separately, as a scalar (isotropic) or a
(2, 2) array diag(G13, G23) for an orthotropic ply.
2. Homogeneous plate: plate_stiffness
For a single-layer, midplane-symmetric flat plate of thickness h, plate_stiffness
returns the thickness integrals directly — no lamination needed:
A, D, G_s = shell.plate_stiffness(C_iso, h=2e-3, G_transverse=70e9 / (2 * 1.3))
This gives , , and (with shear correction by default). There is no coupling matrix for a homogeneous plate.
3. Laminate assembly (CLT): laminate_stiffness
For a stack of plies at different orientations, laminate_stiffness performs the
classical lamination-theory thickness integrals. Layers are ordered bottom → top, with
the midplane at (see z_layer_coordinates):
where is each layer's stiffness rotated by thetas[k] into laminate axes.
import jax.numpy as jnp
# Two CFRP plies at ±45°, 0.5 mm each
C_layers = jnp.stack([C_cfrp, C_cfrp]) # (n_layers, 2,2,2,2)
G_layers = jnp.stack([jnp.diag(jnp.array([5e9, 3e9]))] * 2) # (n_layers, 2, 2)
thetas = jnp.array([-jnp.pi / 4, +jnp.pi / 4]) # radians, bottom→top
thicknesses = jnp.array([0.5e-3, 0.5e-3])
A, B, D, G_s = shell.laminate_stiffness(C_layers, G_layers, thetas, thicknesses)
C_layers / G_layers may also be a single tensor (broadcast to every layer) when all
plies share the same material and only orientation differs.
B measures membrane–bending coupling. It vanishes for any midplane-symmetric stack
(e.g. or ) but is non-zero for antisymmetric stacks
like — which is exactly what makes such laminates warp under in-plane or
thermal loads. Pass B to the resultant/weak-form helpers whenever it is non-zero.
Supporting helpers:
z_layer_coordinates(thicknesses)→ interface -coordinates, length , midplane at 0.rotate_in_plane_stiffness(C, theta)→ (4th-order rotation).rotate_shear_stiffness(G, theta)→ rotate a transverse-shear(2,2)tensor.
4. Thermal loads: laminate_thermal_loads
A temperature change induces eigenstrains that, in a constrained laminate, act as pre-force / pre-moment resultants. For a through-thickness profile :