OpenSees Cloud

OpenSees AMI

Parametric Oscillator

Original Post - 14 Aug 2022 - Michael H. Scott

Visit Structural Analysis Is Simple on Substack.


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.

Parametric Oscillator

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 \(\omega_o=\sqrt{g/L}\). In the OpenSees model shown below, the frequency of spring vibration is set to \(\omega=2\omega_o\) (to approximate the resonance condition), from which the spring stiffness is calculated as \(k=m\omega^2\). 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','-noWarnings')

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.

Displacement response of parametric oscillator

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.

Animation of parametric oscillator

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

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.