I sometimes ask collaborators for post ideas. At the end of our meeting this week, Prof. Mark Denavit suggested modeling a parametric oscillator in OpenSees and referred me to the following video.

OK, if you didn’t watch the video, the response of a parametric oscillator is modified by some frequency-dependent parameter of the system. In this case, the oscillator is a pendulum and the modifier is the frequency of spring vibration. If you did watch the video or read the Wikipedia page, you’ll see that pumping a playground swing is the classic example of a parametric oscillator.

Parametric *resonance* occurs when the frequency of the modifier is twice the natural frequency of the oscillator, i.e., when the natural frequency of the spring is twice the frequency of the pendulum.

A mass and a spring? No problem for OpenSees. But the displacements are too large, and the redundancy too low, for structural engineering comfort. Never deterred, a corotational truss model should fit the bill.

As you might recall from physics, the pendulum frequency is . In the OpenSees model shown below, the frequency of spring vibration is set to (to approximate the resonance condition), from which the spring stiffness is calculated as . In this way, the value of mass is not important for the model.

```
inch = 1.0
lb = 1.0
sec = 1.0
g = 386.4*inch/sec**2
# Length of pendulum
L = 10*inch
# Pendulum mass and weight
m = 1.0
W = m*g
# Frequency of pendulum
omega = (g/L)**0.5
# Frequency of oscillator
w = 2*omega
# Stiffness of spring
k = m*w**2
import openseespy.opensees as ops
ops.wipe()
ops.model('basic','-ndm',2,'-ndf',2)
ops.node(1,0,L); ops.fix(1,1,1)
ops.node(2,0,0); ops.mass(2,m,m)
ops.uniaxialMaterial('Elastic',1,k*L)
ops.element('corotTruss',1,1,2,1.0,1)
# Initial displacements
ops.setNodeDisp(2,1,0.05*L,'-commit')
ops.setNodeDisp(2,2,-W/k-(W/k+L)/3,'-commit')
# Pendulum weight
ops.timeSeries('Constant',1)
ops.pattern('Plain',1,1)
ops.load(2,0,-W)
ops.algorithm('Newton')
ops.integrator('Newmark',0.5,0.25)
ops.analysis('Transient')
Tmax = 12*sec
dt = 0.01*sec
Nsteps = int(Tmax/dt)
ops.analyze(Nsteps,dt)
```

Imposing initial conditions of a small horizontal displacement and a vertical displacement that stretches the spring by 1/3 of its deformed length under self-weight gives the response history shown below.

The spring oscillation drives the pendulum motion, i.e., the peaks of the *X* displacement response far exceed the magnitude of the initial *X* displacement.

And here is an animation, based on this tutorial for creating animated GIFs from `matplotlib`

.

With the Python code shown in this post, play with the model parameters and check the following scenarios.

**Non-resonance**

Change the spring frequency to three times the pendulum frequency and impose the same initial conditions as above. The magnitude of the*X*displacement response will not exceed the initial condition.**Pure pendulum**

Set the spring frequency to ten times the pendulum frequency (making the spring very stiff) and impose initial*X*and*Y*displacements equal to the pendulum length.

It’s not rigid body dynamics, which is way harder than deformable body mechanics, but still cool that OpenSees can model this type of system.