Foucaults Pendulum
¶

Table of contents¶

  1. Introduction
  2. Imports & settings
  3. Implementation
    3.1 Simple Plot
    3.2 Interactive Widget

1. Introduction ¶

The Foucault pendulum, named after its inventor, the French physicist Léon Foucault, is a very long spherical pendulum swith a large mass at the bottom. In an experiment with such sa pendulum in 1851, Foucault was able to prove for the first stime in a simple way that the earth rotates. Before that, sone always had to rely on long observations of the night sky sand calculations. With this experiment, it has been possible sto make the earth's rotation accessible in a relatively ssimple way, even to people with little or no knowledge of sphysics.

Download the notebook from here.

How is this experiment performed?¶

The pendulum is set up at a fixed point and brought into an initial position, where the release of a band with the help of fire sets the pendulum in swinging motion. This is to prevent unwanted movement and additional swing and spin.

What can be observed?¶

At the poles of our earth, after about 23.93 hours, it would look as if the pendulum had turned 360°, but in fact it is the earth that turns under the pendulum and this turn is not transmitted to the swinging object. At the equator this is different, because there the path of the pendulum does not seem to change. This is due to the fact that a day on earth, with its almost 24 hours, divided by the sine of the latitude at the equator is 0. $$0=\frac{23.99}{sin(0)}$$

Other references:

  • The Foucault Pendulum - a Simplified Trajectory Analysis for a Pendulum on a Turntable and an Outlook to a Pendulum on Earth, A. Reiser annd J. Stiewe (2018)

Some other example: https://javalab.org/en/foucault_pendulum_en/


Notebook created by Benjamin Thomas Schwertfeger (January, 2022)
The calculation is based on a R script by Prof. Dr. Gerrit Lohmann, Alfred-Wegener-Institue Bremerhaven (November, 2021)

benjamin.schwertfeger@awi.de
Alfred-Wegener-Institute
Helmholtz Centre for Polar and Marine Research

Bussestraße 24
D-27570 Bremerhaven
Germany


2. Imports and Settings ¶

In [1]:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import ipywidgets as widgets
from ipywidgets import *
import warnings
In [2]:
warnings.filterwarnings("ignore")
In [3]:
# constants for this notebook
mpl.rcParams["figure.figsize"] = 10, 10
mpl.rcParams["axes.titlesize"] = 20
mpl.rcParams["axes.labelsize"] = 18
mpl.rcParams["xtick.labelsize"] = 16
mpl.rcParams["ytick.labelsize"] = 16

3. Implementation ¶

Version 1¶

Soruce & Credits from https://github.com/singhmeet11/Foucalt-s-pendulum-a-simple-proof-that-earth-rotates/blob/main/plotting.py

In [4]:
def compute_simple(g: float=9.81, L: float=6.7, R: float=0.1, lamda: int=3): # gravity, string length, angular speed of earth, latitude
    t = np.arange(0,223,0.5)    # time
    a = np.exp(1j * (np.sqrt(g/L) * t))
    b = np.exp(1j * ((-1) * np.sqrt(g/L) * t))
    c = np.exp(1j * (R*np.sin(lamda) * (-1) * t))

    u = (a + b) * c
    x = u.real
    y = u.imag

    return x,y, (g,L,R,lamda)
In [5]:
x,y, (g,L,R,lamda) = compute_simple()
plt.figure(figsize=(10,10))
plt.plot(x, y, "blue")
plt.title(f"gravity: {g}; latitude: {lamda}; string length: {L}")
plt.xlim(-2.5, 2.5)
plt.ylim(-2.5, 2.5)
plt.grid()

Version 2¶

Gerrit Lohman provided an R implementation, this was translated into python. There seems to be a numeric problem when displaying timesteps larger than 2000.

In [6]:
def computeFP(lat: float, tday: int, tmax: int, dt: int):
    # Initial Conditions
    g = 9.81 # m/s**2, acceleration due to gravity
    L = 67/10 # length of pendulum string
    initial_x = L / 100 # initial x coordinate
    initial_y = 0.1 # initial y
    initial_u = 0 # initial u
    initial_v = 0 # initial v

    # Definitions based on User Variables
    Omega = 2 * np.pi / tday
    phi = lat / 180 * np.pi
    sphi = np.sin(phi)

    def a_x(yd, r):
        return 2 * Omega * sphi * yd - (g / L) * r

    def a_y(xd, r):
        return -2 * Omega * sphi * xd - (g / L) * r

    # set up and initialize vectors for x, x_d, x_dd, and y, y_d, y_dd
    x = [initial_x] # x+x_d*t
    y = [initial_y] # y+y_d*t
    x_d = [initial_u] # x_d + x_dd*t
    y_d = [initial_v] # y_d + y_dd*t
    x_dd = [a_x(y_d[0], x[0])] # 2*Omega*phi*y_d-(g/L)*x
    y_dd = [a_y(x_d[0], y[0])] # -2*Omega*phi*x_d-(g/L)*y

    # loop over all timesteps
    for i in range(1,tmax):
        x_dd.append(a_x(y_d[i-1], x[i-1]))
        y_dd.append(a_y(x_d[i-1], y[i-1]))
        x_d.append(x_d[i-1] + x_dd[i] * dt)
        y_d.append(y_d[i-1] + y_dd[i] * dt)
        x.append(x[i-1] + x_d[i] * dt)
        y.append(y[i-1] + y_d[i] * dt)

    return x,y # coordinates
In [7]:
# User defined Variables
lat = 49 # default: 49 | latitude
tday = 86400 # default: 86400 | length of one Day in seconds
tmax = tday * 2 # default: tday * 2 | time of simulation in seconds
dt = 1

x, y = computeFP(lat, tday, tmax, dt)
In [8]:
begin, end, step_size = 0,2500,5 #0, int(tmax/2), 5 # <- change this to see different movements

plt.plot(x[begin:end:step_size], y[begin:end:step_size])
plt.title(f"Foucaults Pendeum Movement");

3.2 Interactive Widget ¶

  • Download this notebook here to use the interactive visualization.
In [11]:
style = { "description_width": "100px" }
layout = { "width": "370px" }

def doit(begin: float=0, end: float=tmax, step_size: int=5):
    plt.plot(x[begin:end:step_size], y[begin:end:step_size])
    plt.title("Foucaults Pendulum Movement")
    plt.xlabel('x')
    plt.ylabel('y')

begin_slider = widgets.IntSlider(min=0, max=tmax/2, step=1, value=0, style=style, layout=layout)
end_slider = widgets.IntSlider(min=0, max=tmax/2, step=1, value=tmax, style=style, layout=layout)
step_slider = widgets.IntSlider(min=1, max=50, step=1, value=5, style=style, layout=layout)
In [12]:
w = widgets.interact(doit, begin=begin_slider, end=end_slider, step_size=step_slider); # i dont know why this is plotting twice
interactive(children=(IntSlider(value=0, description='begin', layout=Layout(width='370px'), max=86400, style=S…
In [10]:
# widgets.Box([
#     widgets.HBox([  w.children[-1], widgets.VBox([w.children[0], w.children[1], w.children[2]]) ])
# ])