Damped & Driven Pendulums (in _pure_ Python)

Click For Summary
SUMMARY

This discussion focuses on implementing Damped and Driven Pendulums using Taylor recurrences in pure Python to solve ordinary differential equations (ODEs) to high orders, specifically up to 10th order. The provided code demonstrates the use of trigonometric recurrences and Horner's method for evaluating series. Key parameters include gravitational acceleration (g = 9.80665), mass (m), length (l), damping (ζ), and forcing (a). The example script allows for dynamic simulation through command-line arguments.

PREREQUISITES
  • Understanding of ordinary differential equations (ODEs)
  • Familiarity with Python 3 programming
  • Knowledge of Taylor series and recurrences
  • Basic physics concepts related to pendulum motion
NEXT STEPS
  • Explore advanced Python libraries for numerical methods, such as SciPy
  • Learn about the implementation of Runge-Kutta methods for ODEs
  • Investigate the use of matplotlib for visualizing pendulum simulations
  • Study the effects of varying damping and forcing parameters on pendulum behavior
USEFUL FOR

Physicists, mathematicians, and software developers interested in numerical simulations of dynamic systems, particularly those working with ODEs and pendulum mechanics.

m4r35n357
Messages
657
Reaction score
148
TL;DR
Minimal example code for experimentation
This is another application of using Taylor recurrences (open access) to solve ODEs to arbitrarily high order (e.g. 10th order in the example invocation). It illustrates use of trigonometric recurrences, rather than the product recurrences in my earlier Lorenz ODE posts.

Enjoy!

[CODE lang="python" title="Simulator"]#!/usr/bin/env python3
# Example: ./forced.py 10 .05 10001 1.0 1.0 0.1 4.9 1.1
from sys import argv
from math import pi, sqrt, sin, cos

def jet(n, value=0.0):
j = [0.0] * n
j[0] = value
return j

def Σ(j, n, h):
result = j[n]
for i in range(n - 1, -1, -1):
result = result * h + j
return result

def _dd(v, u, i):
return sum(j * u[j] * v[i - j] for j in range(1, i)) / i

def t_sin_cos(s, c, u, i):
return (sin(u[0]), cos(u[0])) if i == 0 else (c[0] * u + _dd(c, u, i), - s[0] * u - _dd(s, u, i))

order, δt, n_steps = int(argv[1]), float(argv[2]), int(argv[3]) # integrator controls
g, m, length = 9.80665, float(argv[4]), float(argv[5]) # physical parameters
ζ, a, ω = float(argv[6]), float(argv[7]), 2.0 * pi * sqrt(length / g) * float(argv[8]) # damping/forcing parameters

θ0, θdot0 = 0.0, 0.0 # initial values
θ, θdot, sinθ, cosθ = jet(order + 1), jet(order + 1), jet(order), jet(order) # jets
for step in range(1, n_steps):
print("{:.9e} {:.9e} {:.9e} {:.5e}".format(θ0, θdot0, float(0.0), step * δt))
θ[0], θdot[0] = θ0, θdot0
for k in range(order): # build up jets using recurrences and the derivative rule
sinθ[k], cosθ[k] = t_sin_cos(sinθ, cosθ, θ, k)
θ[k + 1] = θdot[k] / (k + 1)
θdot[k + 1] = (a * cos(ω * step * δt) - ζ * length * θdot[k] - m * g * sinθ[k]) / (m * length) / (k + 1)
θ0, θdot0 = Σ(θ, order, δt), Σ(θdot, order, δt) # Horner's method
[/CODE]
 
  • Like
Likes   Reactions: Filip Larsen
Technology news on Phys.org
Thanks for sharing!

It’s always great to code snippets. I didn’t realize that in python you could use Greek letters for method and variable names like ##\Sigma##
 
jedishrfu said:
Thanks for sharing!
Cheers. Here is a slightly tidied and reduced version, single-use functions are eliminated, and now uses f-strings for output formatting:
Python:
#!/usr/bin/env python3
#  Example: ./forced.py 10 .05 4001 1.0 1.0 0.1 4.9 1.1 | ./plotAnimated.py 1 -50 50
from sys import argv
from math import pi, sqrt, sin, cos

def dd(v, u, i):
    return sum(j * u[j] * v[i - j] for j in range(1, i)) / i

order, δt, n_steps = int(argv[1]), float(argv[2]), int(argv[3])  # integrator controls
g, m, l = 9.80665, float(argv[4]), float(argv[5])  # physical parameters
ζ, a, ω = float(argv[6]), float(argv[7]), 2.0 * pi * sqrt(l / g) * float(argv[8])  # damping/forcing

θ0, θdot0 = 0.0, 0.0  # initial values
θ, θdot, sinθ, cosθ = [0.0] * (order + 1), [0.0] * (order + 1), [0.0] * order, [0.0] * order  # jets
for step in range(1, n_steps):
    print(f'{θ0:.9e} {θdot0:.9e} {0.0:.9e} {step * δt:.5e}')

    # build up jets using recurrences and the derivative rule
    θ[0], θdot[0] = θ0, θdot0
    for k in range(order):
        sinθ[k], cosθ[k] = (sin(θ[0]), cos(θ[0])) if k == 0 else (cosθ[0] * θ[k] + dd(cosθ, θ, k),
                                                                - sinθ[0] * θ[k] - dd(sinθ, θ, k))
        θ[k + 1] = θdot[k] / (k + 1)
        θdot[k + 1] = (a * cos(ω * step * δt) - ζ * l * θdot[k] - m * g * sinθ[k]) / (m * l) / (k + 1)

    # evaluate series using Horner's method
    θ0, θdot0 = θ[order], θdot[order]
    for k in range(order - 1, -1, -1):
        θ0, θdot0 = θ0 * δt + θ[k], θdot0 * δt + θdot[k]
 
Last edited:

Similar threads

  • · Replies 6 ·
Replies
6
Views
2K
  • · Replies 17 ·
Replies
17
Views
3K
  • · Replies 16 ·
Replies
16
Views
3K
Replies
3
Views
4K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 7 ·
Replies
7
Views
3K
  • · Replies 4 ·
Replies
4
Views
8K
  • · Replies 10 ·
Replies
10
Views
2K
  • · Replies 6 ·
Replies
6
Views
4K
  • · Replies 75 ·
3
Replies
75
Views
7K