Visual walkthrough — FEM for structures — assembling global stiffness
This page rebuilds the central result of the parent note — the equation
— from absolute zero, entirely in pictures. We assume you know nothing but "a spring pushes back when you stretch it." Everything else, we build. By the end you will see why we simply add overlapping numbers, and why that addition is exactly what physics demands.
Prerequisites we lean on but will re-picture as needed: Element Stiffness Matrices, Coordinate Transformations in FEM, and (at the very end) Boundary Conditions in FEM.
Step 1 — What a single spring "says" (the element stiffness, from a picture)
WHAT. Start with the smallest possible object: one bar between two dots. Call the dots node and node . Each dot can slide along the bar; its slide amount is a number — a degree of freedom (DOF). So this one bar has just two numbers to worry about: and .
WHY. Before we can assemble many springs, we must know precisely what one spring contributes. Everything in FEM is "one element, understood completely, then repeated."
PICTURE.

Look at the red bar. When you pull node to the right by an amount while holding node still, the bar stretches by . Hooke's law for a bar says the internal force is
- — how stiff the material is (steel resists more than rubber).
- — the cross-section area (a thick bar resists more than a thin one).
- — the length (a long bar stretches more easily, so it divides).
- — the single number "", the spring constant of this bar.
Now write the force at each dot. Newton says the bar pulls node one way and node the opposite way:
F_i &= k(u_i - u_j) = k\,u_i - k\,u_j,\\ F_j &= k(u_j - u_i) = -k\,u_i + k\,u_j. \end{aligned}$$ Stack those two lines into a little table: > [!formula] The element stiffness matrix (one bar) > $$\begin{bmatrix} F_i \\ F_j \end{bmatrix} = \frac{EA}{L}\begin{bmatrix} 1 & -1 \\ -1 & 1 \end{bmatrix}\begin{bmatrix} u_i \\ u_j \end{bmatrix} \quad\Longrightarrow\quad \mathbf{k}^{(e)} = \frac{EA}{L}\begin{bmatrix} 1 & -1 \\ -1 & 1 \end{bmatrix}$$ > Read entry $\mathbf{k}^{(e)}_{ab}$ as: "the force appearing at DOF $a$ when I push DOF $b$ by one unit and hold the other still." The $+1$ on the diagonal = "pushing you pushes back on you." The $-1$ off-diagonal = "pushing you *pulls* your partner." That $2\times2$ box is the entire vocabulary of one element. Assembly is the grammar for gluing boxes together. --- ## Step 2 — Two springs, one shared dot: the collision we must resolve **WHAT.** Put two bars in a line: bar $(1)$ joins node 1–node 2, bar $(2)$ joins node 2–node 3. Node 2 is **shared**. **WHY.** Sharing is the whole point. If elements never shared dots we would have disconnected pieces, not a structure. We must decide what happens *at the shared dot* — and that decision *is* the direct stiffness method. **PICTURE.** ![[deepdives/dd-physics-3.6.19-d2-s02.png]] The red dot is node 2. Two physical facts meet there: 1. **Compatibility** — there is only *one* node 2, so both bars must agree on its displacement $u_2$. No gap, no overlap. (The dot cannot be in two places.) 2. **Force balance** — the total force applied at node 2 equals the sum of what *each* bar pulls with there. Fact 2 is the seed of the word **add**. The force at node 2 is: $$F_2 = \underbrace{F_2^{(1)}}_{\text{from bar }1} + \underbrace{F_2^{(2)}}_{\text{from bar }2}.$$ Each bar contributes a force at node 2 built from *its own* stiffness box. Because node 2 is the *second* DOF of bar 1 **and** the *first* DOF of bar 2, both boxes want to write into the same slot. We do not choose one — we **sum** them. Step 3 makes "the same slot" precise. --- ## Step 3 — The address book: connectivity and the global table **WHAT.** Build an empty $3\times3$ table $\mathbf{K}$, one row/column per global DOF (nodes 1, 2, 3). Give each bar an *address list* telling it which global slots its two local numbers map to. **WHY.** A bar's own box calls its dots "local 1" and "local 2." The table calls them "global 1, 2, 3." We need a translator — the ==connectivity map== — so each bar knows where to deposit its numbers. **PICTURE.** ![[deepdives/dd-physics-3.6.19-d2-s03.png]] The address lists: - Bar $(1)$: local $[1,2] \to$ global $[1,2]$. - Bar $(2)$: local $[1,2] \to$ global $[2,3]$ ← note the red **2** is where they collide. > [!definition] Connectivity (topology) > The list that sends each element's local DOF numbers to their global positions. For bar $(2)$, "my local slot 1 is global slot 2, my local slot 2 is global slot 3." This list is *all* the geometry the assembler needs — it never re-reads coordinates, only follows addresses. --- ## Step 4 — Scatter-add: dropping each box into the table **WHAT.** Take each element box and *place* its four entries into the global table at the addresses from Step 3, **adding** onto whatever is already there. **WHY.** Placing-with-adding is the literal meaning of $\sum_e \mathbf{L}^{(e)T}\mathbf{k}^{(e)}\mathbf{L}^{(e)}$ — but done cheaply, without ever multiplying by the big sparse $\mathbf{L}$. (We prove they are equal in Step 6.) **PICTURE.** ![[deepdives/dd-physics-3.6.19-d2-s04.png]] Watch the arrows carry each entry to its slot. **Bar (1) → slots (1,2):** $$\mathbf{K} \leftarrow \mathbf{K} + \frac{EA}{L}\begin{bmatrix} \mathbf{1} & \mathbf{-1} & 0 \\ \mathbf{-1} & \mathbf{1} & 0 \\ 0 & 0 & 0 \end{bmatrix}$$ The bold $2\times2$ block is bar 1's box, dropped in the top-left corner. **Bar (2) → slots (2,3):** $$\mathbf{K} \leftarrow \mathbf{K} + \frac{EA}{L}\begin{bmatrix} 0 & 0 & 0 \\ 0 & \mathbf{1} & \mathbf{-1} \\ 0 & \mathbf{-1} & \mathbf{1} \end{bmatrix}$$ The bold block is bar 2's box, dropped in the bottom-right corner — **overlapping** slot $(2,2)$. At slot $(2,2)$ both boxes wrote a $1$. We add: $1+1 = 2$. **That is the shared node, in one number.** The assembled result: > [!formula] Assembled global stiffness (two bars in series) > $$\mathbf{K} = \frac{EA}{L}\begin{bmatrix} 1 & -1 & 0 \\ -1 & \mathbf{2} & -1 \\ 0 & -1 & 1 \end{bmatrix}$$ > The red-hearted $\mathbf{2}$ in the middle is the visible fingerprint of two springs sharing node 2 — the force-balance sum of Step 2 made concrete. ``` Initialize K = zeros(N, N) for each element e: k_e = element_stiffness(e) dofs = connectivity(e) # e.g. [2, 3] for bar 2 for a in range(len(dofs)): for b in range(len(dofs)): K[dofs[a], dofs[b]] += k_e[a, b] # scatter-ADD ``` --- ## Step 5 — Off-axis bars: why we transform *before* we scatter **WHAT.** A bar in 2D is rarely aligned with the global $x$-axis. Its natural box (Step 1) lives along *its own* axis $\xi$. Before scattering we must **rotate** the box into global $x$–$y$ language. **WHY.** The address book (Step 3) speaks in global $x,y$ DOFs. A tilted bar's box speaks $\xi$ (along-bar) and $\eta$ (across-bar). Scattering mismatched languages would add apples to oranges. See [[Coordinate Transformations in FEM]] for the full machinery; here is the picture. **PICTURE.** ![[deepdives/dd-physics-3.6.19-d2-s05.png]] A bar tilted at angle $\theta$ has direction cosines $c=\cos\theta$, $s=\sin\theta$ — the red arrow's shadow on $x$ and $y$. - $c$ — how much of "along the bar" points along global $x$. - $s$ — how much of "along the bar" points along global $y$. The rotation gathers each node's $(u_x,u_y)$ into the single along-bar slide $u_\xi = c\,u_x + s\,u_y$. Sandwiching the local box with this rotation $\mathbf{T}$ gives the **global-frame element box**: $$\mathbf{k}^{(e)}_{\text{global}} = \mathbf{T}^{T}\,\mathbf{k}_{\text{local}}\,\mathbf{T} = \frac{EA}{L}\begin{bmatrix} c^2 & cs & -c^2 & -cs \\ cs & s^2 & -cs & -s^2 \\ -c^2 & -cs & c^2 & cs \\ -cs & -s^2 & cs & s^2 \end{bmatrix}.$$ - $c^2, s^2$ — stiffness felt along $x$, along $y$. - $cs$ — the *coupling*: pushing in $x$ also produces force in $y$ because the bar is diagonal. > [!mistake] The order that breaks everything > **Scatter first, then transform** is wrong — you would deposit $\xi$-frame numbers into $x,y$ slots. Always: **transform to global frame → then scatter-add.** Degenerate checks: a horizontal bar has $\theta=0 \Rightarrow c=1,s=0$, and the box collapses back to Step 1's $\begin{bmatrix}1&-1\\-1&1\end{bmatrix}$ in the $x$-rows only, $y$-rows all zero (a bar carries no sideways stiffness). A vertical bar has $\theta=90^\circ \Rightarrow c=0,s=1$, and stiffness lives entirely in the $y$-rows. Both extremes fall straight out of the formula. ✓ --- ## Step 6 — Why "add the overlaps" *is* $\sum \mathbf{L}^{(e)T}\mathbf{k}^{(e)}\mathbf{L}^{(e)}$ **WHAT.** Prove that the cheap scatter-add (Step 4) equals the parent note's boxed formula. **WHY.** So the picture and the algebra are one thing, not two. **PICTURE.** Define the ==Boolean localization matrix== $\mathbf{L}^{(e)}$: a tall skinny table of $0$s and $1$s that, when multiplied by the global displacement vector $\mathbf{u}$, *plucks out* just the DOFs this element touches: $$\mathbf{u}^{(e)} = \mathbf{L}^{(e)}\,\mathbf{u}.$$ For bar $(2)$ with addresses $[2,3]$ in a 3-DOF world: $$\mathbf{L}^{(2)} = \begin{bmatrix} 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}, \qquad \mathbf{L}^{(2)}\begin{bmatrix}u_1\\u_2\\u_3\end{bmatrix} = \begin{bmatrix}u_2\\u_3\end{bmatrix}.$$ Each row has a single $1$ marking "this local DOF = that global DOF" — literally the address book as a matrix. Now the strain energy of the whole structure is the sum of each element's energy (energy is additive — no double counting, no interaction terms between separate springs): $$U = \sum_e \tfrac12\,\mathbf{u}^{(e)T}\mathbf{k}^{(e)}\mathbf{u}^{(e)} = \sum_e \tfrac12\,(\mathbf{L}^{(e)}\mathbf{u})^T\mathbf{k}^{(e)}(\mathbf{L}^{(e)}\mathbf{u}) = \tfrac12\,\mathbf{u}^T\!\left(\sum_e \mathbf{L}^{(e)T}\mathbf{k}^{(e)}\mathbf{L}^{(e)}\right)\!\mathbf{u}.$$ The bracket *is* $\mathbf{K}$. And $\mathbf{L}^{(e)T}\mathbf{k}^{(e)}\mathbf{L}^{(e)}$ takes the small box and **scatters** its entries to the global positions marked by the $1$s — exactly the arrows of Step 4. The transpose $\mathbf{L}^{(e)T}$ scatters rows; the plain $\mathbf{L}^{(e)}$ scatters columns. Overlapping elements land in the same slots, and the outer $\sum$ **adds** them. Picture = algebra. ∎ > [!recall]- Check the shared entry algebraically > Compute the (2,2) slot: bar 1 contributes via its local-2 row, bar 2 via its local-1 row, both landing at global 2. $k^{(1)}_{22}+k^{(2)}_{11} = \tfrac{EA}{L}(1)+\tfrac{EA}{L}(1)=\tfrac{2EA}{L}$. Same $2$ as Step 4. ✓ --- ## Step 7 — Degenerate & edge cases you will actually hit **WHAT / WHY / PICTURE — the situations that surprise beginners.** - **A whole free structure is singular.** Before pinning anything, push the *entire* truss rightward: every $u=$ same value, nothing stretches, energy $=0$. So $\mathbf{u}^T\mathbf{K}\mathbf{u}=0$ for a non-zero $\mathbf{u}$ → $\mathbf{K}$ is only *positive semi-definite* and cannot be inverted. These zero-energy motions are **rigid-body modes** (translations + rotations). In our 1-DOF chain, the vector $\mathbf{u}=(1,1,1)^T$ gives $\mathbf{K}\mathbf{u}=\mathbf{0}$ — one rigid translation, one zero eigenvalue. - **The fix = boundary conditions.** Pinning node 1 ($u_1=0$) deletes row/column 1. The reduced matrix loses its zero eigenvalue and becomes *positive definite* → invertible. Full story in [[Boundary Conditions in FEM]]. - **Sparsity, not fullness.** $K_{ij}\neq0$ only when DOFs $i,j$ share an element. In our chain, $K_{13}=0$ (nodes 1 and 3 are never in the same bar). Big meshes are >99\% zeros — store only the nonzeros ([[Sparse Matrix Storage]]) and pick a solver that exploits it ([[Direct vs Iterative Solvers]]). - **Symmetry survives.** Each $\mathbf{k}^{(e)}$ is symmetric (Maxwell–Betti reciprocity: force at $i$ from unit move at $j$ equals force at $j$ from unit move at $i$). Scatter-add preserves symmetry, so $\mathbf{K}=\mathbf{K}^T$. Let us close the loop numerically with the parent's solved chain (fixed node 1, force $F$ at node 3): $$\mathbf{K}_{\text{red}}=\frac{EA}{L}\begin{bmatrix}2 & -1\\ -1 & 1\end{bmatrix},\quad \mathbf{K}_{\text{red}}\begin{bmatrix}u_2\\u_3\end{bmatrix}=\begin{bmatrix}0\\F\end{bmatrix} \;\Rightarrow\; u_2=\frac{FL}{EA},\; u_3=\frac{2FL}{EA}.$$ Physical check: two identical bars in series stretch $\frac{FL}{EA}$ each, total $\frac{2FL}{EA}=u_3$. ✓ --- ## The one-picture summary Every idea on one canvas: little element boxes (each a spring's self-knowledge) → address arrows (connectivity) → drop into the big table with **adding at overlaps** (the red shared entry) → the assembled sparse symmetric $\mathbf{K}$, which becomes invertible only after a boundary condition removes the rigid-body freedom. > [!recall]- Feynman retelling — say it to a 12-year-old > Imagine a bunch of springs, each one a stubborn little creature that only knows two dots — its own ends. Ask a creature "if I nudge your right dot by one inch, how hard do you push back, and on whom?" It answers with a tiny $2\times2$ (or $4\times4$) table of push-numbers. Now build one enormous blank spreadsheet, one row and one column for every dot's every direction of sliding. Give each creature an address list: "your left dot is row 5, your right dot is row 9." Each creature copies its little table into the big spreadsheet at *its* addresses. When two creatures share a dot, they both write into the same cell — and we simply **add** their numbers, because at a shared dot the pushes literally add up (that's just Newton: total force = sum of forces). If a bar is tilted, first rotate its table so it speaks the spreadsheet's north–south–east–west language, *then* copy. The finished spreadsheet is $\mathbf{K}$. It's mostly zeros (most dots never meet), it's symmetric (pushing you as much as you push me), and at first it's floppy — you can shove the whole thing sideways for free, so you can't "divide by it." Nail one dot to the wall (a boundary condition) and the floppiness vanishes: now you can solve $\mathbf{K}\mathbf{u}=\mathbf{F}$ and find how every dot moves. That copy-and-add is the entire secret of assembling global stiffness. > Retell in one line ::: Each spring copies its small stiffness box into a big shared table at its node addresses, summing where nodes overlap, then we pin a node to make the table solvable. --- ### Connections Built on: [[Element Stiffness Matrices]] · [[Coordinate Transformations in FEM]] · [[Finite Element Method Overview]]. Leads to: [[Boundary Conditions in FEM]] · [[Sparse Matrix Storage]] · [[Direct vs Iterative Solvers]] · [[Mesh Refinement and Convergence]]. Parent: [[FEM for structures — assembling global stiffness]].