In *Fundamentals of Structural Mechanics*, Hjelmstad solves a “little” one-dimensional Boundary Value Problem (BVP) for linear-elasticity before moving on to the three-dimensional BVP, which is full of mathematical difficulties. Hjelmstad’s reasoning is sound.

“Some of these difficulties are of great importance, while others are simply a nuisance. Reducing the issue to its simplest case helps to separate the important ideas from the merely tedious.”

Keith D. Hjelmstad, 2003

Solving BVPs reminds me of a procedure in earthquake engineering that is also rife with tedium and nuisance: Incremental Dynamic Analysis (IDA). OpenSees is ideal for IDAs, but some users will go straight to reinforced concrete moment frames under bidirectional excitation, only to get mired in model selection, non-convergence, and interpretation of results. Having skipped over an IDA of a simple model, the important ideas are lost or never developed.

So, let’s do a Little IDA. I will note that, besides simple classroom demonstrations, I don’t do many IDAs. I do not know all the nuance behind these analyses, only the basic idea.

The SDF system shown below has an EPP force-deformation response and is subjected to an earthquake excitation. The response quantity of interest is the maximum displacement of the mass.

For this example, I arbitrarily set the seismic weight to 500 kip and the initial stiffness is calculated based on a 1.0 sec period. The yield force of the system is set to 300 kip.

The basic code to run this Little IDA is shown below. First, define the model. Then, inside a loop, reset the model to its initial state, redefine the uniform excitation with the current scale factor, then find the response quantity of interest.

```
g = 386.4
# Seismic weight and mass
W = 500
m = W/g
# Stiffness and strength
Tn = 1.0
wn = 2*3.14159/Tn
k = m*wn**2
Fy = 300
import openseespy.opensees as ops
ops.wipe()
ops.model('basic','-ndm',1,'-ndf',1)
ops.node(1,0); ops.fix(1,1)
ops.node(2,0); ops.mass(2,m)
ops.uniaxialMaterial('Hardening',1,k,Fy,0,0)
ops.element('zeroLength',1,1,2,'-mat',1,'-dir',1)
ops.analysis('Transient')
# Analysis duration and time step
Tf = 40.0
dt = 0.01
Nsteps = int(Tf/dt)
# Arrays for plotting
Uplot = []
gmPlot = []
# Maximum and increment in ground motion factor
maxGM = 2.0
dgm = 0.05
gmFact = 0.0
while gmFact < maxGM:
gmFact += dgm
gmPlot.append(gmFact)
ops.remove('timeSeries',1)
ops.remove('loadPattern',1)
ops.reset()
# Redefine time series with new factor
ops.timeSeries('Path',1,'-dt',0.02,'-filePath','tabasFN.txt','-factor',gmFact*g)
ops.pattern('UniformExcitation',1,1,'-accel',1)
# Perform analysis and record maximum displacement
Umax = 0
for i in range(Nsteps):
ops.analyze(1,dt)
U = ops.nodeDisp(2,1)
if abs(U) > Umax:
Umax = abs(U)
Uplot.append(Umax)
```

There are other ways to do the IDA depending on the size of your model and the amount of output you want to record. You can wipe and redefine the model inside the loop and/or you can use recorders instead of real-time commands.

Regardless of how you perform the IDA, the resulting IDA curve is shown below. I plotted it like a pushover curve, but alternative presentations of the results are possible.

There are some important features to note.

- The initial response is linear, i.e., as the ground motion scale factor increases, the maximum displacement increases in proportion to the ground motion intensity. For this model, the linear response holds until a scale factor of about 0.6.
- Above scale factors of 1.0, there is a large increase in maximum displacement as the scale factor increases. This result is expected in general, but where it happens is specific to this example.
- As the scale factor increases from about 1.3 to 1.5, the maximum displacement decreases. I believe this is what IDA folks call “resurrection”, i.e., the model responds better (or less bad) for higher intensity ground motion. Again, where this happens is specific to this example and resurrection does not always happen.

The outline of the Little IDA should convey the important idea of how to perform IDAs in OpenSees for larger models. I will leave to you the tedium of scaling the vertical axis based on ground motion intensity measures.