OpenSees Cloud
OpenSees AMI
How Many Clicks Does It Take?
Original Post - 14 Feb 2021 - Michael H. Scott
Visit Structural Analysis Is Simple on Substack.
Coding single degree of freedom (SDF) response in order to generate earthquake response spectra is a rite of passage in earthquake engineering research and education. I wrote my first response spectrum in MATLAB. Nowadays, people are likely to use Python.
To generate response spectra in OpenSees, you can create a simple one-dimensional model of SDF response. I like to use a zero length element, but if you prefer unnecessarily normalizing with respect to lollipop geometry, you can use a truss or beam element instead.
ops.model('basic','-ndm',1,'-ndf',1)
ops.node(1,0); ops.fix(1,1)
ops.node(2,0); ops.mass(2,1.0) # mass = 1.0
ops.uniaxialMaterial('Elastic',1,k) # k is mass*omega**2
ops.element('zeroLength',1,1,2,'-mat',1,'-dir',1)
The brute force approach to construct a response spectrum for a given ground motion would be to define a new model for each natural period. To get the maximum displacement, you can use an envelope node recorder then read the maximum displacement from the file.
while Tn <= Tnf:
k = (2*pi/Tn)**2 # mass = 1.0
# Define model with k
#
ops.timeSeries('Path', 1, '-dt', dtf, '-filePath', filename)
ops.pattern('UniformExcitation',1,1,'-accel',1)
# Define analysis options
#
ops.analysis('Transient')
ops.recorder('EnvelopeNode','-file','disp.out','-node', 2,'-dof',1,'disp')
ops.analyze(N,dt)
ops.wipe()
# Read umax from 'disp.out'
Tn += dTn
But, you’re redefining the model over and over, which is a waste of time
because the stiffness is the only property that’s changing. A more
efficient approach would be to define the model once, then use the
parameter
and updateParameter
commands along with reset.
# Define model
#
# Define time series and load pattern
#
# Define transient analysis
#
ops.parameter(1,'element',1,'E')
while Tn <= Tnf:
ops.reset()
k = (2*pi/Tn)**2 # mass = 1.0
ops.updateParameter(1,k)
tag = ops.recorder('EnvelopeNode','-file','disp.out','-node', 2,'-dof',1,'disp')
ops.analyze(N,dt)
ops.remove('recorder',tag)
# Read umax from 'disp.out'
Tn += dTn
Note that the envelope node recorder will get bogged down by the
repeated analyses on one model. I’m not sure why that’s the case, but I
used the remove
command to solve the issue.
Both the brute force and the update parameter approach take more time than necessary. OpenSees sets up the same analysis objects and uses the same runtime indirection whether it’s solving one equation or 100,000 equations. That computational infrastructure carries a lot of overhead.
So, while writing a paper on constant ductility spectra a few years ago,
a colleague in Eastchester and I decided to add a command to OpenSees,
sdfResponse
, that computes bilinear elasto-plastic response of an SDF
system for any given mass, damping, stiffness, yield force, and input
ground motion. The command implements in C++ a local Newmark time loop
with inner Newton loop to solve for nonlinear SDF response history.
Here’s the relevant snippet of response spectrum code.
while Tn <= Tnf:
k = (2*pi/Tn)**2 # mass = 1.0
# m z k Fy alpha
u = ops.sdfResponse(1.0, 0, k, 1e16, 0.1, dtf, filename, dt)
umax = u[0]
Tn += dTn
Setting a high yield force makes the SDF system elastic. The sdfResponse
command is
also available with OpenSees Tcl.
Here is a time comparison between the three approaches in computing a linear-elastic response spectrum.
Comparison performed on Linux Ubuntu 18.04
The single element OpenSees SDF modeling approaches take 5-8 times
longer than sdfResponse
. The extra time will quickly add up when you
generate spectra for many ground motions. We were able to generate
constant ductility spectra for 46 ground motions in 30 minutes instead
of 4 hours.