The Malkus waterwheel is a simple mechanical model which exhibits chaotic dynamics. It consists of a wheel of buckets. The topmost bucket (red) is filled with water at a constant rate, which then slowly drains from each bucket (here, exponentially, since it’s easy though not necessarily realistic) as the wheel spins. The wheel changes speed and direction and exhibits a sensitivity to initial conditions. If we plot the center of mass, we see a trajectory similar to the Lorenz attractor!
Edit: I didn’t speak with confidence because I wasn’t certain it was equivalent to the Lorenz attractor, but Steven Strogatz discusses in great detail in the video below (and in subsequent videos) the derivation of the waterwheel equations and that they can be mapped by a change of variables to a special case of the Lorenz equations. It’s worth a watch!
The function below defines the derivative function which we integrate to simulate the system. The state variables of the system are the bucket fill amounts as well as the angular position and velocity of the system. For the sake of using an off-the-shelf ODE routine, we pack these into the vector . The system itself is just a wheel with inertia, friction, and the moment about the axis of rotation by the buckets.
function derivative(yp, y, t) {
// We integrate all buckets as well as the rotation angle and velocity as a
// single system of coupled ODEs.
// y[0] through y[n - 1] are bucket fill amounts
// Angular position:
const theta = y[n];
// Angular velocity:
const omega = y[n + 1];
// Add up the moment of inertia, starting with a bit of mass for the wheel
// Note that this is quite ad hoc and we sort of elide over being careful
// about mass, distances, and radii
let I = 1;
// Iterate over buckets, adding up the torque and draining each bucket
let M = 0;
for (let i = 0; i < n; i++) {
if (isExponentialDraining) {
// Exponential rather than constant draining since it's smoother and
// easier to prevent unreasonable accumulation :shrug:
yp[i] = -y[i] * drainRate;
} else {
// Constant draining (with exponential return to zero if we overshoot)
yp[i] = y[i] < 0 ? -y[i] * drainRate : -drainRate;
}
// Moment (force x lever arm)
M += y[i] * Math.sin(theta + Math.PI * 2 * (i / n));
// Add the mass to the moment of inertia (neglecting the radius because it's
// sort of irrelevant up to a scaling of the problem, unless we're being more
// precise about everything)
I += y[i];
}
// Pour into the bucket nearest the top
const bucket = mod(Math.floor(n * mod(-theta / (2.0 * Math.PI), 1) + 0.5), n);
yp[bucket] += fillRate;
// For visualization:
mutables.activeBucket = bucket;
// d(theta)/dt = omega
yp[n] = omega;
// I * d(omega)/dt = torque
yp[n + 1] = (M - omega * friction) / I;
}Mathematical Formulation
The Malkus waterwheel is governed by a system of ordinary differential equations (ODEs) that describe both the water dynamics in each bucket and the rotational motion of the wheel itself.
State Variables
The state vector contains components,
where is the mass (or fill amount) of the -th bucket, is the angular position of the wheel, and is the angular velocity.
Bucket Dynamics
Each bucket drains proportionally to its fill amount,
where is the drain rate. The topmost bucket additionally receives water at a constant fill rate ,
Rotational Dynamics
The wheel’s rotation is governed by the rotational analog of Newton’s second law,
where is the moment of inertia, is the net torque from the water-filled buckets, and is the friction coefficient.
The moment of inertia includes both the wheel itself and the distributed mass of water,
where is the base inertia of the empty wheel (here taken as 1).
The torque is the sum of moments from each bucket. Since bucket is located at angle , and torque is proportional to the sine of the angle (the perpendicular component of the gravitational force),
Complete System
The complete system of ODEs is:
To integrate the system, I’ve used an ODE solver I wrote in @rreusser/integration, though any explicit ODE routine like a Runge-Kutta method (RK2 or RK4) works great.
Although the formulation is a bit ad hoc, the system exhibits chaotic behavior for certain parameter values, with the wheel reversing direction unpredictably and displaying sensitive dependence on initial conditions.