Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Simple pendulum

Source
# IF USING JUPYTER NOTEBOOK:
# %matplotlib notebook
# IF USING JUPYTER LAB:
%matplotlib widget
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.integrate import odeint

Simple pendulum

Author: Ludovic Charleux (ludovic.charleux@univ-smb.fr)

Background

This tutorial aims to model and simulate the oscillations of a simple pendulum. A representation is given below (source: Wikipedia).

Simple pendulum

The pendulum consists of a point mass mm located at the point MM attached to a rigid arm considered without mass. The length of the arm is noted LL. This arm is articulated with respect to a frame considered as an inertial reference frame. The angle between the arm and the vertical direction is noted θ\theta. A simple modeling using dynamics leads to :

mA(M/0)=P+Tm\vec A(M/0) = \vec P + \vec T

Where:

  • A(M/0)\vec A(M/0) is the acceleration of the mass,

  • P\vec P if the weight of the mass,

  • T\vec T if the reaction force of the arm.

A projection of this equation along the direction perpendicular to the arm gives a more simple equation:

θ¨=gLsinθ\ddot \theta = -\dfrac{g}{L} \sin \theta

This equation is a non linear ODE of the second order whose exact solution is not known. It is however possible to assume that θ\theta is small enough to write that sinθθ\sin \theta \approx \theta. In this case, the equation comes down to the one of a free and undamped harmonic oscillator treated in the theoretical part. The object of this tutorial is to solve this problem by a numerical approach in a general way without simplifying assumptions.

L = 1.0  # m
g = 9.81  # m/s**2

Part 1: ODE reformulation

  • This problem can be reformulated to match the standard formulation X˙=f(X,t)\dot X = f(X, t):

X=[θθ˙]=[x0x1]X = \begin{bmatrix} \theta \\ \dot \theta \end{bmatrix} = \begin{bmatrix} x_0 \\ x_1 \end{bmatrix}
X˙=[x1gLsinx0]=f(X,t)\dot X = \begin{bmatrix} x_1 \\ -\dfrac{g}{L} \sin x_0 \end{bmatrix} = f(X, t)
  • Write the function ff in Python:

def f(X, t):
    """
    The simple pendulum's ODE
    """
    # CODE HERE !
    return

Part 2: solver validation at small angles

In this first part, we want to validate the operation of the numerical solvers by comparing their results to a known exact solution. To do so, we will focus on the case of the simple pendulum oscillating at small angles. In this case, the sine can be approximated by sinθθ\sin \theta \approx \theta and the equation of the pendulum can be reduced to that of a harmonic oscillator. The exact solution is then:

x(t)=θ0cos(ω0t)x(t) = \theta_0 \cos(\omega_0 t)

With:

  • X0=[θ0,0]TX_0 = [\theta_0, 0]^T

  • ω0=g/L\omega_0 = \sqrt{g/L}

Solve the problem with Euler, RK4 and ODEint integrators and compare the results with the closed form solution. First assume that the pendulum is released with no speed (θ˙=0o/s\dot \theta = 0 ^o/s) at θ=1o\theta = 1 ^o. The time discretization will be as follows:

  • duration: from ta=0t_a = 0 s to tb=10t_b = 10 s.

  • time step: dt=1.×102dt = 1. \times 10^{-2} s.

def Euler(func, X0, t):
    """
    Euler integrator.
    """
    dt = t[1] - t[0]
    nt = len(t)
    X = np.zeros([nt, len(X0)])
    X[0] = X0
    for i in range(nt - 1):
        X[i + 1] = X[i] + func(X[i], t[i]) * dt
    return X


def RK4(func, X0, t):
    """
    Runge and Kutta 4 integrator.
    """
    dt = t[1] - t[0]
    nt = len(t)
    X = np.zeros([nt, len(X0)])
    X[0] = X0
    for i in range(nt - 1):
        k1 = func(X[i], t[i])
        k2 = func(X[i] + dt / 2.0 * k1, t[i] + dt / 2.0)
        k3 = func(X[i] + dt / 2.0 * k2, t[i] + dt / 2.0)
        k4 = func(X[i] + dt * k3, t[i] + dt)
        X[i + 1] = X[i] + dt / 6.0 * (k1 + 2.0 * k2 + 2.0 * k3 + k4)
    return X


# ODEint is preloaded.
# Define the time vector t and the initial conditions X0
ta = 0.0
tb = 10.0
# CODE HERE
t = []  # REPLACE
theta = []  # REPLACE WITH YOUR SOLUTION

plt.figure()
plt.plot(t, np.degrees(theta))
plt.xlabel("Time, $t$")
plt.ylabel(r"Angular position, $\theta$ [$^o$]")
plt.grid()
Loading...

Part 3: Anharmonic oscillations at larger energies

In what follows, we work only with one of the solvers that has been sufficiently accurate in the previous section. We are interested in the operation of the pendulum at higher energy. First, increase the initial angle θ0\theta_0 to 179o179^o and add an initial velocity. What do you observe about the shape of the curves (time, position) ?

# CODE HERE
theta = []  # REPLACE WITH YOUR SOLUTION

plt.figure("High energy")
plt.plot(t, np.degrees(theta))
plt.xlabel("Time, $t$")
plt.ylabel(r"Angular position, $\theta$ [$^o$]")
plt.grid()
Loading...

Part 4 : Phase space

For several initial conditions treated previously, draw the trajectory (integral curve) in the (θ,θ˙)(\theta, \dot \theta) phase plane. What remarkable points do you observe ?

theta = []  # REPLACE
dottheta = []  # REPLACE

plt.figure("Phase space")
plt.plot(np.degrees(theta), np.degrees(dottheta))
plt.xlabel(r"Angular position, $\theta$ [$^o$]")
plt.xlabel(r"Angular speed, $\dot\theta$ [$^o$]")
plt.grid()
Loading...

Part 5: Conclusions

Conclude on your observations on the following points: quality of the numerical solutions, shape of the integral curves, interest of the various representations used.

# ...