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.
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.
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.