Structural
The Stiffness Matrix from First Principles
Where does the element stiffness matrix actually come from? A full derivation from virtual work, through shape functions, to the 12×12 frame element matrix you use every day.
On this page10 sections
Every finite element analysis software — ETABS, SAP2000, ANSYS, your own Python solver — is built on the same foundation: the element stiffness matrix.
You’ve probably used it. But where does it actually come from?
This post derives it from scratch — starting from virtual work, moving through shape functions, ending at the 12×12 matrix for a 3D frame element. No black boxes.
The core idea
A structural element resists deformation. The stiffness matrix captures how much — it maps nodal displacements to nodal forces :
For a single element with degrees of freedom, is an matrix. For a full structure, we assemble all element matrices into a global .
Virtual work principle
The derivation starts with the principle of virtual work.
- Principle of virtual work
For a body in equilibrium, the virtual work done by external forces through any virtual displacement equals the virtual strain energy stored internally.
For a bar element under virtual nodal displacement :
This is the foundation. Now we need to connect strains to displacements.
Shape functions
A 2-node bar element has 2 DOF: and (axial displacements). We assume the displacement varies linearly along the element:
- Shape functionsN(x)
N₁ and N₂ define how the interior displacement field is interpolated from the nodal values.
In matrix form:
Strain-displacement relationship
For a bar in axial loading, strain is:
where is the strain-displacement matrix, found by differentiating :
Assembling the stiffness matrix
With linear elastic material, .
Substituting into the virtual work equation:
Since is arbitrary, we can factor it out:
For a bar with constant , :
That’s the 2×2 stiffness matrix for an axial bar element — derived entirely from first principles.
Extending to a 2D beam element
A 2D Euler–Bernoulli beam element has 4 DOF: two transverse displacements , and two rotations , .
The shape functions are cubic (Hermite polynomials):
where:
The curvature (analogous to strain for bending) is . The stiffness matrix follows the same integral:
This is the Euler–Bernoulli beam stiffness matrix — you’ll find this exact matrix in every structural analysis textbook.
Putting numbers in it
The derivation stops at symbols, which is the right place for a derivation to stop and the wrong place to leave it. Two plots of what it already contains, then the same thing with a section in it.
Enter a section and a length below and both matrices are evaluated as you type.
Axial (bar) element
| u₁ per m | u₂ per m | |
|---|---|---|
| u₁ | 188,300 kN/m | -188,300 kN/m |
| u₂ | -188,300 kN/m | 188,300 kN/m |
Euler–Bernoulli beam element
| v₁ per m | θ₁ per rad | v₂ per m | θ₂ per rad | |
|---|---|---|---|---|
| v₁ | 975.3 kN/m | 2,926 kN/rad | -975.3 kN/m | 2,926 kN/rad |
| θ₁ | 2,926 kN·m/m | 11,700 kN·m/rad | -2,926 kN·m/m | 5,852 kN·m/rad |
| v₂ | -975.3 kN/m | -2,926 kN/rad | 975.3 kN/m | -2,926 kN/rad |
| θ₂ | 2,926 kN·m/m | 5,852 kN·m/rad | -2,926 kN·m/m | 11,700 kN·m/rad |
Values are shown to 4 significant figures. Rotations are in radians, which are dimensionless — so kN/rad is kN, and kN·m/rad is kN·m. Local element coordinates; no transformation to global axes.
Note
Length is the interesting input. Double and the translational term falls by a factor of eight, while the rotational term only halves — which is why a member’s resistance to end rotation survives a span increase far better than its resistance to sway does.
Warning
These are element matrices in local coordinates, not a structural analysis. They carry the same assumptions as the derivation above: a prismatic element with constant , and , linear elastic material, small displacements, and Euler–Bernoulli bending — shear deformation is neglected. Assembling them, applying boundary conditions and solving is the next step, not this one.
The 12×12 3D frame element
Combining axial, bending (two planes), torsion, and shear DOF gives the full 12×12 matrix used in ETABS, SAP2000, and every general-purpose FEM solver.
The assembly process is always the same:
- Define shape functions for each DOF
- Compute by differentiation
- Integrate
- Transform from local to global coordinates via
Implementing it in Python
import numpy as np
def bar_stiffness(E: float, A: float, L: float) -> np.ndarray:
"""2x2 stiffness matrix for an axial bar element."""
k = (E * A / L)
return k * np.array([[1, -1], [-1, 1]])
def beam_stiffness(E: float, I: float, L: float) -> np.ndarray:
"""4x4 Euler-Bernoulli beam element stiffness matrix.
DOF order: [v1, θ1, v2, θ2]
"""
k = E * I / L**3
return k * np.array([
[ 12, 6*L, -12, 6*L],
[6*L, 4*L**2, -6*L, 2*L**2],
[-12, -6*L, 12, -6*L],
[6*L, 2*L**2, -6*L, 4*L**2],
])
In the next post in this series, we’ll assemble these element matrices into a global stiffness matrix, apply boundary conditions, and solve for displacements — building a complete 2D frame solver from scratch.
What this tells you
Every result ETABS gives you flows from this integral. The “stiffness matrix” isn’t a magic number lookup — it’s a compact representation of how a physical element resists deformation, derived from strain energy and virtual work.
Understanding the derivation doesn’t change your day-to-day workflow. But when a model gives you a surprising result, it tells you where to look.