Skip to the content.

← Back to Portfolio Hub

Project 2: Driven Damped Pendulum — Route to Chaos

Tip. Every highlighted link in this page is clickable. For fast navagation use Table of Contents

Author: Nels Buhrley Language: C++17 · Python 3 (visualization) Build: make release — see Build & Run


Snapshot

For a fast technical check, jump to Numerical Methods and Results.


Table of Contents


Overview

This project simulates a driven damped pendulum — one of the simplest physical systems that can exhibit deterministic chaos. By varying the driving force amplitude, the pendulum transitions from regular periodic motion through period-doubling cascades into fully chaotic dynamics. The simulation implements both 4th-order Runge-Kutta (RK4) and Euler-Cromer (semi-implicit Euler) integrators, and the Python visualization produces six-panel analysis figures including phase-space portraits and Poincaré sections for identifying chaotic attractors.


Physics Background

Equation of Motion

The angular displacement $\theta(t)$ of a driven damped pendulum of length $L$ and mass $m$ obeys the nonlinear second-order ODE:

\[\ddot{\theta} + \frac{q}{m}\dot{\theta} + \frac{g}{L}\sin\theta = \frac{F_D}{m}\sin(\omega_D t)\]
Term Physics
$\ddot{\theta}$ Angular acceleration
$(q/m)\dot{\theta}$ Viscous damping — opposes angular velocity
$(g/L)\sin\theta$ Gravitational restoring torque — nonlinear
$(F_D/m)\sin(\omega_D t)$ Periodic driving force

The nonlinearity comes entirely from the $\sin\theta$ term. For small angles ($\sin\theta \approx \theta$) the system reduces to a linear driven harmonic oscillator with well-known analytic solutions. But at large amplitudes the full $\sin\theta$ coupling to the drive produces qualitatively new dynamics.

Natural Frequency and Resonance

The small-angle natural frequency is:

\[\omega_0 = \sqrt{\frac{g}{L}}\]

When $\omega_D \approx \omega_0$ and damping is moderate, the system resonates and the amplitude grows until limited by nonlinear effects. The interplay between resonance, nonlinearity, and driving gives rise to the rich dynamical behavior this simulation explores.

Phase Space and Attractors

The state of the pendulum at any instant is fully specified by $(\theta, \dot{\theta})$. Plotting $\dot{\theta}$ versus $\theta$ yields the phase-space portrait:

Poincaré Sections

A Poincaré section captures the phase-space state $(\theta, \dot{\theta})$ at stroboscopic intervals $t_n = n \cdot 2\pi/\omega_D$, sampling exactly once per driving period:

This stroboscopic sampling collapses the trajectory from a continuous curve to a discrete map, making the distinction between periodic and chaotic regimes immediately visible.


Numerical Methods

4th-Order Runge-Kutta (RK4)

For a state vector $\vec{y} = (t, \theta, \dot{\theta})$, the RK4 scheme computes:

\[\vec{y}_{n+1} = \vec{y}_n + \frac{h}{6}(\vec{k}_1 + 2\vec{k}_2 + 2\vec{k}_3 + \vec{k}_4)\]

where each $\vec{k}_i$ evaluates the derivative function at a different point in the interval. This achieves $\mathcal{O}(h^4)$ global error and is used for custom simulations where accuracy is paramount.

Euler-Cromer (Semi-Implicit Euler)

The Euler-Cromer method updates velocity first, then uses the new velocity to update position:

\(\dot{\theta}_{n+1} = \dot{\theta}_n + \ddot{\theta}_n \cdot h\) \(\theta_{n+1} = \theta_n + \dot{\theta}_{n+1} \cdot h\)

This ordering makes the method symplectic — it preserves the phase-space area (Liouville’s theorem) and provides much better energy conservation than the standard (forward) Euler method. Global error is $\mathcal{O}(h)$, but the qualitative dynamics (orbit topology, bifurcation thresholds) are captured correctly even at moderate step sizes. The validation tests use Euler-Cromer with $dt = 0.001$ s over 72,000 seconds (20 hours of physical time).

Derivative Computation

The oscillator::computeDerivatives() method evaluates:

\[\frac{d}{dt}\begin{pmatrix}t \\ \theta \\ \dot{\theta}\end{pmatrix} = \begin{pmatrix}1 \\ \dot{\theta} \\ -\frac{g}{L}\sin\theta - \frac{q}{m}\dot{\theta} + \frac{F_D}{m}\sin(\omega_D t)\end{pmatrix}\]

Code Structure

File Role
main.cpp Entry point — instantiates logic and calls run()
include/oscillator.h oscillator class (physical parameters) and testOscillator subclass
include/processing.h Declares integrator::rk4(), integrator::euler_chromer(), logic class
src/oscillator.cpp Implements derivative computation: gravity + damping + driving
src/processing.cpp RK4/Euler-Cromer implementation, interactive menu, CSV output
plotting.py Six-panel analysis: time series, phase space, Poincaré sections

Simulation Modes

The logic class provides:


Results

Oscillator analysis — periodic regime

Six-panel analysis of the driven damped pendulum. Top row: angle vs. time (unwrapped and wrapped to $[-\pi, \pi]$). Middle: full phase-space portrait. Bottom: Poincaré sections at the driving frequency reveal the attractor structure — periodic orbits appear as discrete points, chaotic dynamics as fractal dust.

Oscillator analysis — second parameter set Oscillator analysis — third parameter set

Oscillator analysis — fourth parameter set Oscillator analysis — fifth parameter set

Different parameter regimes: varying the driving force amplitude $F_D/m$ reveals transitions from periodic motion to chaos through period-doubling bifurcations.


Sources of Error

Source Nature Mitigation
Temporal truncation RK4: $\mathcal{O}(h^4)$; Euler-Cromer: $\mathcal{O}(h)$ Small time steps ($dt = 0.001$ s or less)
Sensitivity to initial conditions Chaotic trajectories diverge exponentially: $\lvert\delta\theta(t)\rvert \sim e^{\lambda t}$ This is physics, not a bug — Lyapunov exponent $\lambda > 0$ defines chaos
Angle wrapping artifacts Wrapping $\theta$ to $[-\pi, \pi]$ creates visual discontinuities Unwrapped angle also recorded; wrapping applied only for phase-space visualization
Poincaré timing Stroboscopic samples at $t = n \cdot 2\pi/\omega_D$ may not land exactly on a time step Nearest-step sampling; small $dt$ minimizes interpolation error
Symplecticity (RK4) RK4 is not symplectic — energy drifts over very long integrations Euler-Cromer used for long validation runs; RK4 used when accuracy matters more than conservation

Build & Run

Prerequisites

Build

make release    # Optimized build (-O2)
make debug      # Debug build with full warnings
make clean      # Remove build artifacts

Run

./bin/main

The program prompts for simulation mode (validation or custom) and parameters.

Visualize

python3 plotting.py

The plotting script auto-detects output files in Output/ and generates six-panel analysis figures saved as Output/oscillator_analysis_N.png.


Example Parameter Sets

Periodic Regime

Chaotic Regime (Period Doubling)

Deep Chaos


Key Techniques

Technique Purpose
RK4 integration High-accuracy ODE solving for custom simulations
Euler-Cromer integration Symplectic method for long-duration energy-conserving runs
Phase-space portraits Visualize attractor topology
Poincaré sections Stroboscopic sampling reveals periodic vs. chaotic dynamics
Angle wrapping to $[-\pi, \pi]$ Canonically bounded phase-space representation
Interactive parameter input Explore bifurcation structure by tuning $F_D$, $\omega_D$, $q$

Project Structure

Project 2: driven damped oscillations/
|-- main.cpp              # Entry point
|-- include/
|   |-- oscillator.h      # Oscillator class: physical parameters, derivatives
|   `-- processing.h      # Integrators (RK4, Euler-Cromer), logic controller
|-- src/
|   |-- oscillator.cpp    # Derivative computation: gravity + damping + driving
|   `-- processing.cpp    # Integration loops, interactive menu, CSV output
|-- plotting.py           # Six-panel analysis: time series, phase space, Poincare
|-- Makefile              # Build targets: release, debug, clean
|-- bin/                  # Compiled executables
`-- Output/               # CSV data and PNG analysis figures

Nels Buhrley — Computational Physics, 2025

← Back to Portfolio Hub