Updated 25 November 2020
Reading time: 25 mins

Truss Analysis using the Direct Stiffness Method

A complete introduction to the Direct Stiffness Method for truss analysis with a detailed numerical example
[object Object]
by Dr Seán Carroll
Download our Guide to the Direct Stiffness Method - eBook

Download our Guide to the Direct Stiffness Method - eBook

In this tutorial we are going to take a close look at how to use the Direct Stiffness Method to perform truss analysis. By the end of this, you should understand:

  • the basic ideas behind why the direct stiffness method works.
  • how to execute the analysis technique for truss structures that experience axial forces (2D plane trusses).
  • the scalability of the technique and why it’s the main process that powers commercial structural analysis software.

If you want to learn how to implement the direct stiffness method in Python and build your own truss solver (without previous coding experience), consider taking this course where I walk you though the process from setting up Python to running your 2D truss solver.

The Direct Stiffness Method for Truss Analysis with Python

Build your own finite element truss analysis software using Python and tackle large scale structures.

After completing this course...

  • You’ll understand how to use the Direct Stiffness Method to build complete structural models that can be solved using Python.
  • You’ll have your own analysis programme to identify displacements, reactions and internal member forces for any truss.
  • You’ll understand how common models of elastic behaviour such as plane stress and plane strain apply to real-world structures.

I’ve also built this free online truss analysis toolbox that you might find useful. This toolbox is built using the same analysis code you’ll write in the course above.

Try our free truss analysis toolbox for calculating reactions, axial forces and deflections. A handy tools for students and professional engineers.

Back to the tutorial…the direct stiffness method is based on a couple of simple concepts, the first we’ll consider is Hooke’s Law; this simply states that the change in length of an axially loaded element, δ\delta will be proportional to the force causing it, FF. The constant of proportionality between the force and resulting change in length is the stiffness of the element, kk.

F=k×δ(1)F = k\times \delta \tag{1}

1.0 Element Stiffness Matrix

When we’re introduced to Hooke’s law, it’s usually in the context of a spring, in which case the stiffness is simply the spring constant. Here we’re focusing on structures that resist axial forces only – truss structures. Now consider a single structural member extracted from a truss, we’ll refer to this as an axially loaded bar, Fig. 1 below. Now, let’s take Hooke’s law and map it onto our axially loaded bar.

Axially loaded bar | EngineeringSkills.com

Fig. 1. Axially loaded bar element

Our axially loaded bar is subjected to two forces, one at each end or node, F(x,1)F_{ (x, 1) } and F(x,2)F_{(x, 2)}. From Hooke’s law, we know these forces will induce displacements, u(x,1)u_{(x, 1)} and u(x,2)u_{(x, 2)} at nodes 1 and 2 respectively. Our task now is to get an expression along the lines of Hooke’s law that relates the forces F(x,1)F_{(x, 1)} and F(x,2)F_{(x, 2)} with the displacements u(x,1)u_{(x, 1)} and u(x,2)u_{(x, 2)}.

This turns out to be relatively easy once we know that the stiffness of an axially loaded bar is,

kbar=EAL(2)k_{\text{bar}} = \frac{EA}{L} \tag{2}

where EE is Young’s modulus, AA is the cross-sectional area and LL is the length of the bar. Now we can apply what we know to each node in turn. Considering node 1 first we can state the force-displacement relationship as,

Fx,1=EAL(ux1ux2)(3)F_{x,1} = \frac{EA}{L}(u_{x_1}-u_{x_2}) \tag{3}
Fx,1=EALux1EALux2(4)F_{x,1} = \frac{EA}{L}u_{x_1} - \frac{EA}{L}u_{x_2} \tag{4}

And for node 2,

Fx,2=EAL(ux2ux1)(5)F_{x,2} = \frac{EA}{L}(u_{x_2}-u_{x_1}) \tag{5}
Fx,2=EALux,1+EALux,2(6)F_{x,2} = -\frac{EA}{L}u_{x,1} + \frac{EA}{L}u_{x,2} \tag{6}

We can combine both of these equations together and represent them in matrix form as,

{Fx,1Fx,2}{FL}=EAL[1111]Stiffness matrix,[KL]{ux,1ux,2}{uL}(7)\underbrace{\begin{Bmatrix}F_{x,1}\\F_{x,2}\\\end{Bmatrix}}_{\{F_L\}} = \underbrace{\frac{EA}{L}\begin{bmatrix}1&-1\\-1&1\end{bmatrix}}_{\text{Stiffness matrix}, [K_L]}\underbrace{\begin{Bmatrix}u_{x,1}\\u_{x,2}\end{Bmatrix}}_{\{u_L\}}\tag{7}

Notice that the element stiffness that relates force to displacement has been replaced by a matrix. This is known as the Local Element Stiffness Matrix, [KL][K_L] and relates the forces at each node, {FL}\{F_L\} with the corresponding nodal displacements, {uL}\{u_L\}. We can see from the stiffness matrix that the forces developed at each node will have equal magnitude and be opposite in direction, confirming the static equilibrium of the bar. The bar element is typically part of a larger structure and as such the displacement at each node will usually be different, giving rise to a lengthening or shortening of the bar. The local element stiffness matrix is the fundamental unit of direct stiffness method analysis, it is literally the basic building block that we use to assemble our model of the structure. For more sophisticated structural elements, this matrix gets larger and more complex, but keep in mind it’s always just relating the actions (forces, moments) applied to an element to the corresponding displacement and rotations.

2.0 Direct Stiffness Method – Basic Concept

As I mentioned at the top, this technique is built upon two basic ideas, Hooke’s law, which we’ve now covered and this next one. Once you grasp it, you’ll recognise just how simple this analysis technique really is. So here goes; wrapped up in matrix equation (7) was the force displacement relationship for both nodes of the member. But recall that we said this member was ‘extracted’ from a larger structure. And so it could easily be the case that node 2 has 2, 3 or nn other members connected to it. Each of those members will also have a force-displacement relationship that must be obeyed.

So, to solve for the displacement of node 2, we need to take into consideration all of the members that meet at that node and simultaneously obey all of their individual force-displacement relationships. Mathematically, this corresponds to solving simultaneous equations for the value of displacement at node 2 that satisfies all of the members that connect into this node. If you can grasp this concept, you understand the direct stiffness method, everything else is just implementation details!

To implement this method in practice, we first build one big matrix to represent the entire structure, we call this the Primary Structure Stiffness Matrix. Although this is a much bigger matrix, it still just relates nodal displacements and nodal forces…but for the whole structure instead of a single member. To do this we combine element stiffness matrices together such that all of the members contributing to each node, get added together at the same location in the overall structure stiffness matrix. In this way we end up with one big set of simultaneous equations, (neatly packaged together into a matrix equation) that models the force-displacement behaviour of the structure. Then it’s just a matter of solving these equations for the unknown structural displacements using the usual techniques (i.e. a computer!) to solve matrix equations.

3.0 Direct Stiffness Method for Truss Analysis

We can only discuss this at a concept level for so long, to really get to grips with it and all of the implementation details, we need to roll up our sleeves and analyse a structure from start to finish. To that end, consider the three-bar truss in Fig. 2. I’ve numbered each node from 1 to 4 and labelled each member from A to C. Note that this structure is a 2D plane truss, but everything we’re about to discuss can readily be expanded to 3D structures.

Three-bar truss | EngineeringSkills.com

Fig. 2. Simple 3-bar plane truss

Our first task is to identify each possible displacement, ignoring the influence of supports (for now), each node could undergo two orthogonal displacements, Fig.

  1. We’ll call these degrees of freedom, our structure therefore has 8 degrees of freedom. This will come up again later when we’re building the primary structure stiffness matrix.
Truss degrees of freedom | EngineeringSkills.com

Fig. 3. Degrees of freedom

3.1 Global Element Stiffness Matrix

In order to combine our element stiffness matrices together, we must first account for the fact that they are all orientated at different angles. This means that an axial force for member A for example cannot currently be directly added to an axial for from member B as they are orientated at different angles. So we need to perform a transformation that maps forces and displacements from each member into a common global reference frame. For this we use a transformation matrix, [T][T]. Now this can be easily derived but in the interest of brevity, for now we simply state the following relationship between coordinates in a local member reference frame and the corresponding coordinates in a global structure reference frame,

{ux,L,1ux,L,2}local coords,{uL}=[cosθsinθ0000cosθsinθ]Transformation matrix,[T]{ux,G,1uy,G,1ux,G,2uy,G,2}global coords,{uG}(8)\underbrace{\begin{Bmatrix}u_{x,L,1}\\u_{x,L,2}\end{Bmatrix}}_{\text{local coords},\{u_L\}}= \underbrace{\begin{bmatrix}\cos\theta & \sin \theta &0 &0\\0& 0&\cos\theta&\sin\theta\end{bmatrix}}_{\text{Transformation matrix},[T]}\underbrace{\begin{Bmatrix}u_{x,G,1}\\u_{y,G,1}\\u_{x,G,2}\\u_{y,G,2}\end{Bmatrix}}_{\text{global coords}, \{u_G\}} \tag{8}

where ux,L,1u_{x,L,1} and ux,L,2u_{x,L,2} are the local axial displacements at nodes 1 and 2. We can summarise this as {uL}=[T]{uG}\{u_L\} = [T]\{u_G\}. The transformation matrix [T][T] acts as a bridge between local and global coordinates provided we use a method of determining the angle of orientation of the member in question, θ\theta, and stick to it for all members. We can use the exact same technique to bridge between forces in a local element reference frame FLF_L and their values FGF_G in the common (to all members) global reference frame.

{Fx,G,1Fy,G,1Fx,G,2Fy,G,2}{FG}=[cosθ0sinθ00cosθ0sinθ][T]T{Fx,L,1Fx,L,2}{FL}(9)\underbrace{\begin{Bmatrix}F_{x,G,1}\\F_{y,G,1}\\F_{x,G,2}\\F_{y,G,2}\\\end{Bmatrix}}_{\{F_G\}} = \underbrace{\begin{bmatrix}\cos\theta &0\\\sin\theta &0\\ 0&\cos\theta\\0&\sin\theta\\\end{bmatrix}}_{[T]^T}\underbrace{\begin{Bmatrix}F_{x,L,1}\\F_{x,L,2}\end{Bmatrix}}_{\{F_L\}} \tag{9}

Again it will help us to summarise this relationship as {FG}=[T]T{FL}\{F_G\} = [T]^T\{F_L\}. Now that we have the link between:

  • forces in a local and global reference frame
  • displacements in a local and global reference frame

we need to finally link up forces in a global reference frame with displacements in a global reference frame. Trust me, this is going somewhere! Consider equation (7) that relates local element force and displacement,

{FL}=[KL]{uL}(10)\{F_L\} = [K_L]\{u_L\} \tag{10}

We can substitute this equation into equation (9), replacing {FL}\{F_L\} to get,

{FG}=[T]T[KL]{uL}(11)\{F_G\} =[T]^T[K_L]\{u_L\} \tag{11}

Now using equation (8) to replace {uL}\{u_L\} yields,

{FG}global forces=[T]T[KL][T]{uG}global displacements(12)\underbrace{\{F_G\}}_{\text{global forces}} = [T]^T[K_L][T]\underbrace{\{u_G\}}_{\text{global displacements}} \tag{12}

Therefore we can identify [T]T[KL][T][T]^T[K_L][T] as the Global Element Stiffness Matrix, [KG][K_G] that relates forces defined in a global reference frame to displacements also defined in a global reference frame. For clarity, let’s now define c=cosθc=\cos\theta and s=sinθs=\sin\theta. After performing the matrix multiplication, [T]T[KL][T][T]^T[K_L][T], we obtain [KG][K_G] as,

[KG]=[T]T[KL][T]=EAL[c2csc2cscss2css2c2csc2cscss2css2](13)[K_G] = [T]^T[K_L][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} \tag{13}

Now we can calculate a global element stiffness matrix for each element in our structure that encodes the orientation of the member. Once calculated, these can then be directly combined to build the primary structure stiffness matrix.

3.2 Element A – Global Element Stiffness Matrix

Consider element A, Fig. 4. Note that the degrees of freedom at nodes 1 and 4 are shown in the local element reference frame.

Truss-member-A | EngineeringSkills.com

Fig. 4. Element A showing degrees of freedom in a local reference frame

For a member between nodes ii and jj, we define the angle of orientation, θ\theta as the angle (in radians) measured counter-clockwise between the positive global x-axis and the local x-axis, with node ii at the origin where i<ji < j. In this case, that makes θ=5.3\theta = 5.3 radians (303.7)(303.7^\circ). Noting that element A is 7.211m7.211 m long, we can use equation 13 to obtain the global element stiffness matrix,

[KG,A]=EA[0.04270.06400.04270.06400.06400.09600.06400.09600.04270.06400.04270.06400.06400.09600.06400.0960](14)[K_{G,A}] = EA\begin{bmatrix}0.0427 & -0.0640 & -0.0427 & 0.0640\\-0.0640 & 0.0960 & 0.0640 & -0.0960\\-0.0427 & 0.0640 & 0.0427 & -0.0640\\0.0640 & -0.0960 & -0.0640 & 0.0960\end{bmatrix} \tag{14}

3.3 Element B – Global Element Stiffness Matrix

For element B, Fig. 5, we have θ=4.71\theta=4.71 radians (270)(270^\circ). With a length of 66 m, we have,

[KG,B]=EA[0.00000.00000.00000.00000.00000.16670.00000.16670.00000.00000.00000.00000.00000.16670.00000.1667](15)[K_{G,B}] = EA\begin{bmatrix}0.0000 & 0.0000 & 0.0000 & 0.0000\\0.0000 & 0.1667 & 0.0000 & -0.1667\\0.0000 & 0.0000 & 0.0000 & 0.0000\\0.0000 & -0.1667 & 0.0000 & 0.1667\end{bmatrix} \tag{15}
Truss-member-B | EngineeringSkills.com

Fig. 5. Element B showing degrees of freedom in a local reference frame

3.4 Element C – Global Element Stiffness Matrix

Element C, Fig. 6, has an angle of orientation θ=4.12\theta = 4.12 radians (236)(236^\circ) and length of  7.2117.211 m. This gives us a global element stiffness matrix of,

[KG,C]=EA[0.04270.06400.04270.06400.06400.09600.06400.09600.04270.06400.04270.06400.06400.09600.06400.0960](16)[K_{G,C}] = EA\begin{bmatrix}0.0427 & 0.0640 & -0.0427 & -0.0640\\0.0640 & 0.0960 & -0.0640 & -0.0960\\-0.0427 & -0.0640 & 0.0427 & 0.0640\\-0.0640 & -0.0960 & 0.0640 & 0.0960\end{bmatrix} \tag{16}
Truss-member-C | EngineeringSkills.com

Fig. 6. Element C showing degrees of freedom in a local reference frame

3.5 Building the Primary Structure Stiffness Matrix

Next we’ll work our way through building the primary structure stiffness matrix. This is usually the part of the process most prone to error so we’ll approach it in a methodical step-by-step fashion to cut down the likelihood of errors.

Step 1: Break the element stiffness matrices into quadrants

Each element stiffness matrix is 4×44\times 4, so we’ll break each one up into 2×22\times 2 quadrants. So element A for example would be divided as follows,

[KG,A]=EA[0.04270.06400.04270.06400.06400.09600.06400.09600.04270.06400.04270.06400.06400.09600.06400.0960]=EA[KA11KA12KA21KA22](17)[K_{G,A}] = EA\begin{bmatrix}0.0427 & -0.0640 & -0.0427 & 0.0640\\-0.0640 & 0.0960 & 0.0640 & -0.0960\\-0.0427 & 0.0640 & 0.0427 & -0.0640\\0.0640 & -0.0960 & -0.0640 & 0.0960\end{bmatrix} =EA\begin{bmatrix}K_A11 & K_A12\\K_A21 & K_A22\end{bmatrix} \tag{17}

where,

[KA11]=EA[0.04270.06400.06400.0960](18)[K_A11] = EA\begin{bmatrix}0.0427 & -0.0640 \\-0.0640 & 0.0960 \\\end{bmatrix} \tag{18}
[KA12]=EA[0.04270.06400.06400.0960](19)[K_A12] = EA\begin{bmatrix}-0.0427 & 0.0640\\0.0640 & -0.0960\\\end{bmatrix} \tag{19}
[KA21]=EA[0.04270.06400.06400.0960](20)[K_A21] = EA\begin{bmatrix}-0.0427 & 0.0640\\0.0640 & -0.0960\end{bmatrix} \tag{20}
[KA22]=EA[0.04270.06400.06400.0960](21)[K_A22] = EA\begin{bmatrix}0.0427 & -0.0640\\-0.0640 & 0.0960\end{bmatrix} \tag{21}

The same subdivision process is repeated for each member of our structure.

Step 2: Set up the primary stiffness matrix template

Now we can set up a template for the primary stiffness matrix that will make it easy to see where the quadrants of our element stiffness matrices slot in. Since our structure has 4 nodes, our template will be 4×44\times 4, for now we can fill it with placeholders as follows,

[KP]=[k11k12k13k14k21k22k23k24k31k32k33k34k41k42k43k44](22)[K_P] = \begin{bmatrix}k_{11} & k_{12} & k_{13} & k_{14}\\k_{21} & k_{22} & k_{23} & k_{24}\\k_{31} & k_{32} & k_{33} & k_{34}\\k_{41} & k_{42} & k_{43} & k_{44}\\\end{bmatrix} \tag{22}

Each element in the template above actually represents a 2×22\times 2 matrix, so this template actually represents an 8×88\times 8 primary structure stiffness matrix, when filled in.

Step 3: Fill in the template with the quadrants of the element stiffness matrices

Now we can take the quadrants of the element stiffness matrices and slot them into the relevant positions in the primary stiffness matrix template. For each member, identify the node numbers at each end of the member, this defines the rows and columns into which that member’s quadrants fit. More specifically, the quadrants of the element stiffness matrix are positioned at the intersection of the rows and columns identified by the node numbers. Consider member A as an example; it joins nodes 1 and 4, and so it contributes to the primary stiffness matrix as follows,

Stiffness-member-A | EngineeringSkills.com

Fig. 7. Contribution of element A to the primary stiffness matrix template

We follow the exact same process to add all of the element stiffness matrices into the primary stiffness matrix. Notice that every time we add the contribution from another member, we end up adding to element k44k44. Based on our earlier discussion of the direct stiffness method concept, this makes sense as all members meet at node 4 and therefore contribute to the behaviour of that node. We can see how the primary stiffness matrix evolves with the addition of each member. After adding element A, we have,

KP=EA[0.04270.06400.00000.00000.00000.00000.04270.06400.06400.09600.00000.00000.00000.00000.06400.09600.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.04270.06400.00000.00000.00000.00000.04270.06400.06400.09600.00000.00000.00000.00000.06400.0960](23)K_P = EA\begin{bmatrix}0.0427 & -0.0640 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & -0.0427 & 0.0640\\-0.0640 & 0.0960 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0640 & -0.0960\\0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000\\0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000\\0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000\\0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 &0.0000\\-0.0427 & 0.0640 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0427 & -0.0640\\0.0640 & -0.0960 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & -0.0640 & 0.0960\end{bmatrix} \tag{23}

Notice that the matrix is full of zeros, except for the quadrants (four corners) associated with nodes 1 and 4. After adding element B we obtain,

KP=EA[0.04270.06400.00000.00000.00000.00000.04270.06400.06400.09600.00000.00000.00000.00000.06400.09600.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.16670.00000.00000.00000.16670.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.04270.06400.00000.00000.00000.00000.04270.06400.06400.09600.00000.16670.00000.00000.06400.2627](24)K_P = EA\begin{bmatrix}0.0427 & -0.0640 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & -0.0427 & 0.0640\\-0.0640 & 0.0960 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0640 & -0.0960\\0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000\\0.0000 & 0.0000 & 0.0000 & 0.1667 & 0.0000 & 0.0000 & 0.0000 & -0.1667\\0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000\\0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0000\\-0.0427 & 0.0640 & 0.0000 & 0.0000 & 0.0000 & 0.0000 & 0.0427 & -0.0640\\0.0640& -0.0960 & 0.0000 & -0.1667 & 0.0000 & 0.0000 & -0.0640 & 0.2627\end{bmatrix} \tag{24}

Finally after adding element C we have the full primary element stiffness matrix. This matrix is essentially our structural model and the link between force and displacement for the entire structure,

KP=EA[0.04270.06400.00000.00000.00000.00000.04270.06400.06400.09600.00000.00000.00000.00000.06400.09600.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.16670.00000.00000.00000.16670.00000.00000.00000.00000.04270.06400.04270.06400.00000.00000.00000.00000.06400.09600.06400.09600.04270.06400.00000.00000.04270.06400.08530.00000.06400.09600.00000.16670.06400.09600.00000.3587](25)K_P = EA\begin{bmatrix}0.0427& -0.0640& 0.0000& 0.0000& 0.0000& 0.0000& -0.0427& 0.0640\\-0.0640& 0.0960& 0.0000& 0.0000& 0.0000& 0.0000& 0.0640& -0.0960\\0.0000& 0.0000& 0.0000& 0.0000& 0.0000& 0.0000& 0.0000& 0.0000\\0.0000& 0.0000& 0.0000& 0.1667& 0.0000& 0.0000& 0.0000& -0.1667\\0.0000& 0.0000& 0.0000& 0.0000& 0.0427& 0.0640& -0.0427& -0.0640\\0.0000& 0.0000& 0.0000& 0.0000& 0.0640& 0.0960& -0.0640& -0.0960\\-0.0427& 0.0640& 0.0000& 0.0000& -0.0427& -0.0640& 0.0853& 0.0000\\0.0640& -0.0960& 0.0000& -0.1667& -0.0640& -0.0960& 0.0000& 0.3587\end{bmatrix} \tag{25}

3.6 Imposing Boundary Conditions on our Model

At this stage it’s worth taking stock of where we are; we’ve fully modelled the force displacement relationship for our structure and we effectively have the hard work done. Now it’s just a matter of crunching the numbers to solve for our deflections, reactions and member forces.

Taking another look at our problem, we note that we have 14 variables which consist of 8 degrees of freedom/displacements and 6 reactions. But we haven’t taken into consideration yet the fact that 6 of our degrees of freedom are constrained to be zero by our supports, i.e. degree of freedom 1, 2, 3, 4, 5, and 6 are fully restrained by pin supports at nodes 1, 2 and 3. As a result, we actually only have 14-6 = 8 unknowns to solve for. This ties up nicely with the fact that we have a system of 8 simultaneous equations we can use to identify our unknowns. Our system of 8 simultaneous equations is as follows,

{Fx,G,1Fy,G,1Fx,G,2Fy,G,2Fx,G,3Fy,G,3Fx,G,4Fy,G,4}=EA[0.04270.06400.00000.00000.00000.00000.04270.06400.06400.09600.00000.00000.00000.00000.06400.09600.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.16670.00000.00000.00000.16670.00000.00000.00000.00000.04270.06400.04270.06400.00000.00000.00000.00000.06400.09600.06400.09600.04270.06400.00000.00000.04270.06400.08530.00000.06400.09600.00000.16670.06400.09600.00000.3587]Primary structure stiffness matrix{ux,G,1uy,G,1ux,G,2uy,G,2ux,G,3uy,G,3ux,G,4uy,G,4}(26)\begin{Bmatrix}F_{x,G,1}\\F_{y,G,1}\\F_{x,G,2}\\F_{y,G,2}\\F_{x,G,3}\\F_{y,G,3}\\F_{x,G,4}\\F_{y,G,4}\\\end{Bmatrix}= \underbrace{EA\begin{bmatrix}0.0427& -0.0640& 0.0000& 0.0000& 0.0000& 0.0000& -0.0427& 0.0640\\-0.0640& 0.0960& 0.0000& 0.0000& 0.0000& 0.0000& 0.0640& -0.0960\\0.0000& 0.0000& 0.0000& 0.0000& 0.0000& 0.0000& 0.0000& 0.0000\\0.0000& 0.0000& 0.0000& 0.1667& 0.0000& 0.0000& 0.0000& -0.1667\\0.0000& 0.0000& 0.0000& 0.0000& 0.0427& 0.0640& -0.0427& -0.0640\\0.0000& 0.0000& 0.0000& 0.0000& 0.0640& 0.0960& -0.0640& -0.0960\\-0.0427& 0.0640& 0.0000& 0.0000& -0.0427& -0.0640& 0.0853& 0.0000\\0.0640& -0.0960& 0.0000& -0.1667& -0.0640& -0.0960& 0.0000& 0.3587\end{bmatrix}}_{\text{Primary structure stiffness matrix}}\begin{Bmatrix}u_{x,G,1}\\u_{y,G,1}\\u_{x,G,2}\\u_{y,G,2}\\u_{x,G,3}\\u_{y,G,3}\\u_{x,G,4}\\u_{y,G,4}\\\end{Bmatrix} \tag{26}

Before we try and solve this system of equations, we have one more issue to take care of. We need to impose the known displacements onto our system of equations. Again, we do this in quite a systematic way by placing 1 in the diagonal corresponding to known zero displacement and 0 in all other elements of corresponding rows and columns of the primary stiffness matrix.  We also place 0 in the corresponding elements of the force vector. So in our case, considering the xx and yy displacement for nodes 1, 2 and 3, (corresponding to degrees of freedom 1166) are zero, our system of equations becomes,

{000000Fx,G,4Fy,G,4}=EA[1000000001000000001000000001000000001000000001000000000.08530.00000000000.00000.3587]Structure stiffness matrix,[KS]{ux,G,1uy,G,1ux,G,2uy,G,2ux,G,3uy,G,3ux,G,4uy,G,4}(27)\begin{equation*}\begin{Bmatrix}0\\0\\0\\0\\0\\0\\F_{x,G,4}\\F_{y,G,4}\\\end{Bmatrix}= \underbrace{EA\begin{bmatrix}1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\0 & 0 & 0 & 0 & 0 & 0 & 0.0853 & 0.0000\\0 & 0 & 0 & 0& 0 & 0 & 0.0000 & 0.3587\end{bmatrix}}_{\text{Structure stiffness matrix},[K_S]}\begin{Bmatrix}u_{x,G,1}\\u_{y,G,1}\\u_{x,G,2}\\u_{y,G,2}\\u_{x,G,3}\\u_{y,G,3}\\u_{x,G,4}\\u_{y,G,4}\\\end{Bmatrix}\end{equation*} \tag{27}

We define this ‘reduced’ stiffness matrix, the Structure Stiffness Matrix, [KS][K_S], dropping the ‘primary’ to differentiate it from the original primary stiffness matrix. We can see that placing zeros in the primary stiffness matrix rows imposes the boundary conditions,

0=1×ux,G,10=1×uy,G,10=1×ux,G,20=1×uy,G,20=1×ux,G,30=1×uy,G,3(28)\begin{align*} 0=&1\times u_{x,G,1}\\ 0=&1\times u_{y,G,1}\\ 0=&1\times u_{x,G,2}\\ 0=&1\times u_{y,G,2}\\ 0=&1\times u_{x,G,3}\\ 0=&1\times u_{y,G,3}\\ \end{align*} \tag{28}

While placing zeros in the primary stiffness matrix columns ensures known displacements remain zero in subsequent calculations, e.g. consider row 7,

Fx,G,2=EA[(0×ux,G,1)+(0×uy,G,1)+(0×ux,G,2)+(0×uy,G,2)+(0×ux,G,3)+(0×uy,G,3)+(0.0853×ux,G,4)+(0.3587×uy,G,4)](29)F_{x,G,2} = EA[(0\times u_{x,G,1}) + (0\times u_{y,G,1}) + (0\times u_{x,G,2}) + (0\times u_{y,G,2}) + (0\times u_{x,G,3}) + (0\times u_{y,G,3}) + (0.0853\times u_{x,G,4}) + (0.3587\times u_{y,G,4})] \tag{29}

After our boundary conditions are imposed, we can condense our system of equations and substitute in values for the forces at node 4,

{100×103100×103}=EA[0.08530.00000.00000.3587]{ux,G,4uy,G,4}(30)\begin{Bmatrix}100\times 10^3\\-100\times 10^3\end{Bmatrix}=EA\begin{bmatrix}0.0853 & 0.0000\\0.0000 & 0.3587\end{bmatrix}\begin{Bmatrix}u_{x,G,4}\\u_{y,G,4}\end{Bmatrix} \tag{30}

We can then solve this system of 2 simultaneous equations by inverting the structure stiffness matrix,

1EA[0.08530.00000.00000.3587][KS]1{100×103100×103}FG={ux,G,4uy,G,4}uG(31)\underbrace{\frac{1}{EA}\begin{bmatrix}0.0853 & 0.0000\\0.0000 & 0.3587\end{bmatrix}}_{[K_S]^{-1}}\underbrace{\begin{Bmatrix}100\times 10^3\\-100\times 10^3\end{Bmatrix}}_{F_G} = \underbrace{\begin{Bmatrix}u_{x,G,4}\\u_{y,G,4}\end{Bmatrix}}_{u_G} \tag{31}
{ux,G,4uy,G,4}=1EA{1172×103279×103}(32)\begin{Bmatrix}u_{x,G,4}\\u_{y,G,4}\end{Bmatrix} = \frac{1}{EA}\begin{Bmatrix}1172\times 10^3\\-279\times 10^3\end{Bmatrix} \tag{32}

Note that the horizontal displacement is positive, indicating that it acts to the right, according to our global axis system. Similarly the negative value for vertical displacement indicates a downward pointing displacement.

Remember that these are the values of displacement that simultaneously satisfy the force-displacement model for each member that connects into node 4. It’s also worth noting that at no point did the fact that the truss us statically indeterminate feature in our discussion. This is one of the great advantages that this analysis technique has over other analysis methods that rely on equations of equilibrium (method of sections and joint resolution). Before we can call this analysis complete, we need to work out our reactions and internal member forces.

3.7 Calculating Reactions

Calculating reactions is simply a matter of substituting our known displacements back into our full structural model, i.e. the force-displacement relationship that uses the primary structure stiffness matrix,

{Fx,G,1Fy,G,1Fx,G,2Fy,G,2Fx,G,3Fy,G,3Fx,G,4Fy,G,4}=EA[0.04270.06400.00000.00000.00000.00000.04270.06400.06400.09600.00000.00000.00000.00000.06400.09600.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.00000.16670.00000.00000.00000.16670.00000.00000.00000.00000.04270.06400.04270.06400.00000.00000.00000.00000.06400.09600.06400.09600.04270.06400.00000.00000.04270.06400.08530.00000.06400.09600.00000.16670.06400.09600.00000.3587]Primary structure stiffness matrix{0000001172×103EA279×103EA}Known displacements(33)\begin{Bmatrix}F_{x,G,1}\\F_{y,G,1}\\F_{x,G,2}\\F_{y,G,2}\\F_{x,G,3}\\F_{y,G,3}\\F_{x,G,4}\\F_{y,G,4}\end{Bmatrix}= \underbrace{EA\begin{bmatrix}0.0427& -0.0640& 0.0000& 0.0000& 0.0000& 0.0000& -0.0427& 0.0640\\-0.0640& 0.0960& 0.0000& 0.0000& 0.0000& 0.0000& 0.0640& -0.0960\\0.0000& 0.0000& 0.0000& 0.0000& 0.0000& 0.0000& 0.0000& 0.0000\\0.0000& 0.0000& 0.0000& 0.1667& 0.0000& 0.0000& 0.0000& -0.1667\\0.0000& 0.0000& 0.0000& 0.0000& 0.0427& 0.0640& -0.0427& -0.0640\\0.0000& 0.0000& 0.0000& 0.0000& 0.0640& 0.0960& -0.0640& -0.0960\\-0.0427& 0.0640& 0.0000& 0.0000& -0.0427& -0.0640& 0.0853& 0.0000\\0.0640& -0.0960& 0.0000& -0.1667& -0.0640& -0.0960& 0.0000& 0.3587\end{bmatrix}}_{\text{Primary structure stiffness matrix}}\underbrace{\begin{Bmatrix}0\\0\\0\\0\\0\\0\\\frac{1172\times 10^3}{EA}\\\frac{-279\times 10^3}{EA}\\\end{Bmatrix}}_{\text{Known displacements}} \tag{33}

From this we directly obtain the vector of forces which contain the reactions,

{Fx,G,1Fy,G,1Fx,G,2Fy,G,2Fx,G,3Fy,G,3Fx,G,4Fy,G,4}={67.84×103101.77×103046.47×10332.16×10348.23×103100×103100×103}(34)\begin{Bmatrix}F_{x,G,1}\\F_{y,G,1}\\F_{x,G,2}\\F_{y,G,2}\\F_{x,G,3}\\F_{y,G,3}\\F_{x,G,4}\\F_{y,G,4}\\\end{Bmatrix} = \begin{Bmatrix}-67.84\times 10^3\\101.77\times 10^3\\0\\46.47\times 10^3\\-32.16\times 10^3\\-48.23\times 10^3\\100\times 10^3\\-100\times 10^3\\\end{Bmatrix} \tag{34}

At this stage, it’s helpful to visualise these on the structure, Fig. 8.

Truss-reactions | EngineeringSkills.com

Fig. 8. Truss reactions

3.8 Solving for Truss Member Forces

In order to solve for the internal axial force in each member, we return back to where it all began…recall equation 1,

F=k×δ(35)F = k\times \delta \tag{35}

To be a little more precise, we can say that the force in the element between nodes ii and jj is given by,

Fi,j=EAL(ux,L,jux,L,i)(36)F_{i,j} = \frac{EA}{L}(u_{x,L,j}-u_{x,L,i}) \tag{36}

This requires us to convert our calculated global displacements at node ii and jj back into local displacements measured in the local element reference frame using our transformation matrix from above.

{ux,L,1ux,L,4}=[T]{ux,G,1uy,G,1ux,G,4uy,G,4}=[T]{001172×103EA279×103EA}(37)\begin{Bmatrix}u_{x,L,1}\\u_{x,L,4}\\\end{Bmatrix}= [T]\begin{Bmatrix}u_{x,G,1}\\u_{y,G,1}\\u_{x,G,4}\\u_{y,G,4}\\\end{Bmatrix} = [T]\begin{Bmatrix}0\\0\\\frac{1172\times 10^3}{EA}\\\frac{-279\times 10^3}{EA}\\\end{Bmatrix} \tag{37}

So for element A with θ=5.3\theta=5.3 radians, we have,

{ux,L,1ux,L,4}=1EA{0882×103}(38)\begin{Bmatrix}u_{x,L,1}\\u_{x,L,4}\\\end{Bmatrix}= \frac{1}{EA}\begin{Bmatrix}0\\882\times 10^3\end{Bmatrix} \tag{38}

Using these displacements in equation 36, we obtain the axial force in element A,

F1,4=EA7.211(882×103EA)(39)F_{1,4} = \frac{EA}{7.211}(\frac{882\times 10^3}{EA}) \tag{39}
F1,4=122.31kN(40)F_{1,4} = 122.31\:kN \tag{40}

We can repeat the exact same process for elements B and C to obtain their axial forces as F2,4=46.47kNF_{2,4} = 46.47\:kN and F3,4=57.97kNF_{3,4} = -57.97\:kN respectively. The negative sign here indicating compression rather than tension in the element.

That more or less wraps up our example analysis – we’ve solved for all unknown displacements, reactions and member forces. As a final task, we can substitute in values for Young’s modulus E=200×109N/m2E=200\times 10^9 \:N/m^2 and cross-sectional area A=0.005m2A=0.005\:m^2. Doing this we obtain the following deflections for node 4 (obviously the reactions and member forces are unchanged) ,

{ux,G,4uy,G,4}={1.17×103m0.28×103m}(41)\begin{Bmatrix}u_{x,G,4}\\u_{y,G,4}\\\end{Bmatrix} =\begin{Bmatrix}1.17\times 10^{-3}\:m\\-0.28\times 10^{-3}\:m\\\end{Bmatrix} \tag{41}

We can visualise these results below, Fig. 9.

Truss-analysis-plots | EngineeringSkills.com

Fig. 9. (Top) Deflected shape with x200x200 magnification. (Bottom) Axial force diagram in which reds indicate compression and blues indicate tension. Produced using codes from The Direct Stiffness Method for Truss Analysis with Python online course.

ONLINE TRUSS TOOLBOX 🛠️

Try our free truss analysis toolbox for calculating reactions, axial forces and deflections. A handy tools for students and professional engineers.

3.9 Implementing the Direct Stiffness Method in Practice

As you can see, once we nail down the basic underlying principles, the direct stiffness method really is quite a simple analysis technique. You might also have recognised the one major bottleneck with this approach…inverting the structure stiffness matrix. In our example, this was a 2×22\times 2 matrix, relatively trivial to invert. But as the number of nodes in our structure increases, so too does the size of the matrix we need to invert. We very quickly reach a point where we need to resort to computers to do the computational heavy lifting.

The upside here is that once we implement the solution process in an algorithm, the task of solving structures we wouldn’t even consider by hand, becomes quick and easy! You essentially implement your own structural analysis software. The 3D transmission tower, Fig. 10. is analysed using the same methods we discussed above. It’s really only when we implement the direct stiffness method in an algorithm that its power and scalability really shine through.

Transmission-tower | EngineeringSkills.com

Fig. 10. Three dimensional model of a transmission tower analysed using the direct stiffness method. This analysis is an extract from the online course 3D Space Frame Analysis using Python and Blender.

4.0 Implementing the Direct Stiffness Method – Where to Next?

Now that you understand conceptually how the direct stiffness method works, why not build on this and build a practical implementation. In the three EngineeringSkills courses in our Direct Stiffness Method Course Bundle, we work our way through building out a complete suite of analysis codes using Python (if you’re new to Python – no problem!). We start with with 2D plane trusses, then move on to beam and frame structures that experience bending and shear before expanding into full 3D space frame structures. After completing this suite of courses you’ll have the knowledge and practical tools to analyse a huge range of structures without resorting to commercial structural analysis software. And if you do use commercial software, you’ll understand exactly how it’s working behind the scenes.


getting-started
Dr Seán Carroll
BEng (Hons), MSc, PhD, CEng MIEI, FHEA
Hi, I’m Seán, the founder of EngineeringSkills.com (formerly DegreeTutors.com). I hope you found this tutorial helpful. After spending 10 years as a university lecturer in structural engineering, I started this site to help more people understand engineering and get as much enjoyment from studying it as I do. Feel free to get in touch or follow me on any of the social accounts.

Dr Seán Carroll's latest courses.

Analytical Modelling of Plate and Shell Structures: Part 1 - Plates

Analytical Modelling of Plate and Shell Structures: Part 1 - Plates

A practical guide to the analysis of circular and rectangular plates under load, from first principles.

Fundamentals of Reinforced Concrete Design to Eurocode 2

Fundamentals of Reinforced Concrete Design to Eurocode 2

An introduction to ultimate limit state design for bending and shear with optional calculation automation using Python.

Modelling and Analysis of Non-linear Cablenet Structures using Python and Blender

Modelling and Analysis of Non-linear Cablenet Structures using Python and Blender

Learn how to combine parametric modelling, exploratory form-finding and iterative analysis techniques to simulate 3D tensile structures.

Non-linear Finite Element Analysis of 2D Catenary & Cable Structures using Python

Non-linear Finite Element Analysis of 2D Catenary & Cable Structures using Python

Build an iterative solution toolbox to analyse structures that exhibit geometric non-linearity due to large deflections.