OpenSees Cloud

OpenSees AMI

Reinforced Concrete Column Buckling

12 Jun 2026 - Michael H. Scott


Previous posts showed how fiber sections in a corotational mesh of frame elements can simulate the axial load capacity of steel and reinforced concrete columns. This post provides a working script so you can try this type of analysis yourself.

The column model is the same as defined in this post, except the loading is concentric.

A fiber section of Concrete01 and EPP steel is used inside a mesh of six displacement-based elements. Geometric nonlinearity is initiated with an L/1000 out-of-straightness.

As shown in the script below, the analysis is performed using displacement control on the vertical displacement of the top node. Alternatively, we can control the horizontal displacement at the column midheight.

import openseespy.opensees as ops
from math import sin,pi

kN = 1.0
mm = 1.0

GPa = kN/mm**2
MPa = 0.001*MPa

# Column dimensions and properties
b = 300*mm
h = b
cover = 40*mm
L = 20*h

Ag = b*h
Abar = 375*mm**2
As = 4*Abar
Ac = Ag-As

fc = 28*MPa
Es = 200*GPa
fy = 420*MPa

# Nominal axial capacity
Pn = fc*Ac + fy*As

Nele = 6
dL = L/Nele
offset = L/1000

ops.wipe()
ops.model('basic','-ndm',2,'-ndf',3)

ops.node(0,0,0); ops.fix(0,1,1,0)
for i in range(Nele):
    Y = (i+1)*dL
    ops.node(i+1,offset*sin(Y*pi/L),Y)
ops.fix(Nele,1,0,0)

ops.uniaxialMaterial('ElasticPP',1,Es,fy/Es)
ops.uniaxialMaterial('Concrete01',2,fc,0.002,0,0.006)

# Fiber section -- subtract concrete overlapped by r/f steel
ops.section('Fiber',1)
ops.patch('rect',2,20,1,-h/2,-b/2,h/2,b/2)
ops.layer('straight',1,2,Abar,-h/2+cover,-b/2+cover,-h/2+cover,b/2-cover)
ops.layer('straight',1,2,Abar, h/2-cover,-b/2+cover, h/2-cover,b/2-cover)
ops.layer('straight',2,2,-Abar,-h/2+cover,-b/2+cover,-h/2+cover,b/2-cover)
ops.layer('straight',2,2,-Abar, h/2-cover,-b/2+cover, h/2-cover,b/2-cover)

ops.beamIntegration('Legendre',1,1,2)

ops.geomTransf('Corotational',1)
for i in range(Nele):
    ops.element('dispBeamColumn',i,i,i+1,1,1)

ops.timeSeries('Linear',1)
ops.pattern('Plain',1,1)
ops.load(Nele,0,-1.0,0) # Reference load

# Target vertical displacement
Umax = 15*mm 
Nsteps = 200
dU = Umax/Nsteps

ops.integrator('DisplacementControl',Nele,2,-dU)
ops.system('UmfPack')
ops.test('NormDispIncr',1e-6,10)
ops.analysis('Static','-noWarnings')

for i in range(Nsteps):
    ok = ops.analyze(1)
    if ok < 0:
        break

Plots of the load-displacement response (load vs. vertical displacement at the top of the column and load vs. horizontal displacement at the column midheight) are shown below for both the corotational and the linear geometric transformation.

When using the Linear geometric transformation, there is only material nonlinearity and the applied load approaches the column axial capacity–but doesn’t quite get there because of the initial out-of-straightness.

With the Corotational transformation, buckling initiates at an axial load of about 2200 kN and displacement control is able to track the post-peak response.

Try different cross-section sizes, reinforcing details, and material properties, comparing the load-displacement response to the column axial capacity.