Note
This notebook can be downloaded here: Harmonic_Oscillator.ipynb
Damping harmonic oscillator¶
Without excitation force¶
Problem formulation¶
\[\ddot{x} = - 2 \zeta \omega_0 \dot{x} - \omega_0^2 x\]
We define
\[\begin{split}\left\{
\begin{array}{ll}
x_1 = x \\
x_2 = \dot{x}
\end{array}
\right.\end{split}\]
We write so
\[\begin{split}\dot{X}(t) = \begin{pmatrix} \dot{x} \\
- 2 \zeta \omega_0 \dot{x} - \omega_0^2 x \end{pmatrix} = f\left(X, t\right)\end{split}\]
%matplotlib notebook
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import integrate
import ipywidgets as ipw
Step response¶
def ode(X, t, zeta, omega0):
"""
Free Harmonic Oscillator ODE
"""
x, dotx = X
ddotx = -2*zeta*omega0*dotx - omega0**2*x
return [dotx, ddotx]
def update(zeta = 0.05, omega0 = 2.*np.pi):
"""
Update function.
"""
X0 = [1., 0.]
sol = integrate.odeint(ode, X0, t, args = (zeta, omega0))
line0.set_ydata(sol[:, 0])
Nt = 1000
t = np.linspace(0., 10., Nt)
dummy = np.zeros_like(t)
fig = plt.figure()
line0, = plt.plot(t, dummy, label = "position")
plt.grid()
plt.ylim(-1., 1.)
plt.xlabel("Time, $t$")
plt.ylabel("Amplitude, $a$")
plt.legend()
ipw.interact(update, zeta = (0., 1., 0.01),
omega0 = (2.*np.pi*0.05, 2.*np.pi*5, 2.*np.pi*0.01));
<IPython.core.display.Javascript object>
interactive(children=(FloatSlider(value=0.05, description='zeta', max=1.0, step=0.01), FloatSlider(value=6.283…
With sinusoidal excitation force¶
Problem formulation¶
\[\ddot{x} = - 2 \zeta \omega_0 \dot{x} - \omega_0^2 x + F_m \sin(\omega_d t)\]
Like above, we can write this equation as for all \(t\),
\[\begin{split}\dot{X}(t) = \begin{pmatrix} \dot{x} \\
- 2 \zeta \omega_0 \dot{x} - \omega_0^2 x + F_m \sin(\omega_d t) \end{pmatrix} = f\left(X, t\right)\end{split}\]
def odeDrive(X, t, zeta, omega0, omegad_omega0):
"""
Driven Harmonic Oscillator ODE
"""
x, dotx = X
omegad = omegad_omega0 * omega0
ddotx = -2*zeta*omega0*dotx - omega0**2*x + F_m * np.sin(omegad * t)
return [dotx, ddotx]
def update(zeta = 0.05, omega0 = 2.*np.pi, omegad_omega0 = 1.):
"""
Update function.
"""
X0 = np.zeros(2)
sol = integrate.odeint(odeDrive, X0, t, args = (zeta, omega0, omegad_omega0))
line0.set_ydata(sol[:, 0])
Nt = 1000
F_m = 1.
t = np.linspace(0., 10., Nt)
dummy = np.zeros_like(t)
fig = plt.figure()
line0, = plt.plot(t, dummy, label = "position")
plt.grid()
plt.ylim(-1., 1.)
plt.xlabel("Time, $t$")
plt.ylabel("Amplitude, $a$")
plt.legend()
ipw.interact(update, zeta = (0., .2, 0.01),
omega0 = (2.*np.pi*0.5, 2.*np.pi*5, 2.*np.pi*0.01),
omegad_omega0 = (0.1, 2., 0.05));
<IPython.core.display.Javascript object>
interactive(children=(FloatSlider(value=0.05, description='zeta', max=0.2, step=0.01), FloatSlider(value=6.283…
Phase portrait without excitation¶
omega0 = 2. * np.pi * 1.
zeta = .1
ad = 1.
omegad = 2. * np.pi * 1.2
Nt = 1000
tf = 10.
t = np.linspace(0., tf, Nt+1)
X0 = [1., 0.]
X = integrate.odeint(ode, X0, t, args = (zeta, omega0))
plt.figure()
plt.title("Phase plane with $\zeta =$ "+str(zeta))
plt.plot(X[:,0], X[:,1])
plt.grid()
plt.xlabel("$x$, [$m$]")
plt.ylabel("$\dot{x}$, [$m.s^{-1}$] ")
plt.show();
<IPython.core.display.Javascript object>
Phase portrait with excitation¶
omegad_omega0 = 1.
X = integrate.odeint(odeDrive, X0, t, args = (zeta, omega0, omegad_omega0))
plt.figure()
plt.title("Phase plane with $\zeta =$ "+str(zeta))
plt.plot(X[:,0], X[:,1])
plt.grid()
plt.xlabel("$x$, [$m$]")
plt.ylabel("$\dot{x}$, [$m.s^{-1}$] ")
plt.show();
<IPython.core.display.Javascript object>