A simulator for a Sand Pendulum, constructed for the UOIT Science Rendezvous
This software has three components:
- sand-tracer.py :: Generates xy-plots of double pendulum simulation
- sand-tracer-pp.py :: Generates xy-plots and a phase-portrait
- sand-tracer.ipnb :: A jupyter iPython notebook demonstrating code and math.
To model a 2D-pendulum, I'll divide it into two single-dimensional pendulums. This is a strictly linear strategy, and the 2D pendulum is nonlinear. However, we will use two noninear pendulums to mitigate error (leaving only the nonlinearity in the coupling terms), and we can expect our approximation to hold well for small angles. The payoff for this approximation is that we can use the relatively simple dynamics of a single pendulum and aggregate two of them to form our approximation of a pendulum which may swing in both-directions.
In this exhibit, we explore the pendulum known in the literature as the Y-suspended pendulum, shown in the following Figure:
-
Fig: An illustration of the assymetric 2D pendulum. The presence of two pivots at lengths
$r_x$ and$r_y$ produces a dissonance in the oscillation period in the$x$ - and$y$ -directions.
The suspension from two points, forming a
Consider Newton's equation of motion for a pendulum with drag in a single dimension:
The
It is useful to represent the system as a vector valued function on a two-dimensional state space
The above equation is integrated in the software in order to simulate the trajectory of the pendulum.
The sand-tracer.py
program produces images approximating the sand-trails produced by the sand-pendulum, such as this one:
To controll the initial conditions, and produce different plots, you'll want to play around with the initial conditions set near the very top of the source file:
initial_contidionts = dict(r=[.78, .9], b=0.04, xx0=[1, -.2], xy0=[-.33, .1])
or, use a preset:
initial_contidionts = presets['my2017']
Presets are stored in the presets.py
file, and are merely a dictionary of values passed to the initialiser of the PendulumState2D
class:
def __init__(self, r=[1, 1], m=0.5, b=0.2, g=9.807, dt=0.1,
xx0=[0, 1], # Initial state of x-pendulum
xy0=[0, -1]): # Initial state of y-pendulum
The r
parameter is a list of two floats representing the lengs dt
value is the time interval of a single iteration step in the simulation. This value does not affect accuracy of the simulation: only the intervals at which the state will be stored and plotted. The xx0
and xy0
are the inital conditions (a pair containing position and velocity) of the pendulums for the
The sand-tracer-pp.py
program produces a side-by-side animation, such as this one:
The plot on the left is what is produced by the vanilla sand-tracer.py
. The plot on the right is the phase-portrait for the x-pendulum, and reports the energy of the system relative to the rest-energy.
The usage is identical to sand-tracer.py
. Only the animation details are different.
There are two places in the code where you can change the speed of the animation. Forst, you may change inte interval passed to matplotlib.animation.FuncAnimation
. The line should look something like this:
ani = animation.FuncAnimation(
fig, animate, pendulum_sim_generator, blit=True, interval=10)
The interval is specified in miliseconds. Specifying a large interval will slow the animation, but will lead to a jarring and visible transition from one frame of the animation to the next, as the time sampling becomes more and more coarse.
You may also change the value of dt
passed to the constructor of PendulumState2D
(described in section on sand-tracer.py
). This doesn't change the accuracy of integration, but will lead to fewer calls to the integrator. This, however, makes the animation look coarse. In places where the pendulum moves quickly, a large dt
value will make it apparent that the curve is constructed from line segments, and the corners will be visible.