import scipy
import numpy as np
from numpy import cos, sin
import matplotlib.pyplot as plt
import matplotlib.animation as animation
The double pendulum problem
This post is based on an example of matplotlib.
Code
def pendulum(t, u, M1, M2, L1, L2, G):
# u[0] = theta1
# u[1] = omega1
# u[2] = theta2
# u[3] = omega2
= np.zeros_like(u)
du
0] = u[1]
du[
= u[2] - u[0]
delta = (M1 + M2) * L1 - M2 * L1 * cos(delta) * cos(delta)
den1 1] = (
du[
(* L1 * u[1] * u[1] * sin(delta) * cos(delta) +
M2 * G * sin(u[2]) * cos(delta) +
M2 * L2 * u[3] * u[3] * sin(delta) - (M1 + M2) * G * sin(u[0])
M2 / den1
)
)
2] = u[3]
du[
= (L2 / L1) * den1
den2 3] = (
du[
(-M2 * L2 * u[3] * u[3] * sin(delta) * cos(delta) +
+ M2) * G * sin(u[0]) * cos(delta) -
(M1 + M2) * L1 * u[1] * u[1] * sin(delta) - (M1 + M2) * G * sin(u[2])
(M1 / den2
)
)
return du
= 9.8 # acceleration due to gravity, in m/s^2
G = 1.0 # length of pendulum 1 in m
L1 = 1.0 # length of pendulum 2 in m
L2 = L1 + L2 # maximal length of the combined pendulum
L = 1.0 # mass of pendulum 1 in kg
M1 = 1.0 # mass of pendulum 2 in kg
M2 = 5.0 # how many seconds to simulate t_stop
# th1 and th2 are the initial angles (degrees)
# w10 and w20 are the initial angular velocities (degrees per second)
= 120.0
th1 = 0.0
w1 = -10.0
th2 = 0.0 w2
= np.radians([th1, w1, th2, w2])
u0 u0
array([ 2.0943951 , 0. , -0.17453293, 0. ])
= (M1, M2, L1, L2, G)
p p
(1.0, 1.0, 1.0, 1.0, 9.8)
= (0.0, t_stop)
tspan tspan
(0.0, 5.0)
= %timeit -o scipy.integrate.solve_ivp(pendulum, tspan, u0, args=p, dense_output=True, \
res ='DOP853', rtol=1e-10, atol=1e-10) method
63.3 ms ± 839 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
print(f"{res.best:.6f} seconds")
0.062364 seconds
= scipy.integrate.solve_ivp(pendulum, tspan, u0, args=p, dense_output=True, \
sol ='DOP853', rtol=1e-10, atol=1e-10) method
sol
message: The solver successfully reached the end of the integration interval.
success: True
status: 0
t: [ 0.000e+00 2.553e-02 ... 4.985e+00 5.000e+00]
y: [[ 2.094e+00 2.091e+00 ... -3.871e-01 -4.402e-01]
[ 0.000e+00 -2.555e-01 ... -3.738e+00 -3.521e+00]
[-1.745e-01 -1.761e-01 ... 7.104e+00 7.050e+00]
[ 0.000e+00 -1.201e-01 ... -3.549e+00 -3.909e+00]]
sol: <scipy.integrate._ivp.common.OdeSolution object>
t_events: None
y_events: None
nfev: 4004
njev: 0
nlu: 0
= np.linspace(0, t_stop, 500)
t t.shape
(500,)
= sol.sol(t)
s s
array([[ 2.0943951 , 2.09389273, 2.09238573, ..., -0.36666802,
-0.40417351, -0.44021975],
[ 0. , -0.10027181, -0.20051768, ..., -3.81247888,
-3.6719432 , -3.52113898],
[-0.17453293, -0.17477032, -0.1754812 , ..., 7.12298826,
7.08752942, 7.04957895],
[ 0. , -0.04736169, -0.09446566, ..., -3.41150939,
-3.66460357, -3.90882817]])
s.shape
(4, 500)
# theta1
0, :] s[
array([ 2.0943951 , 2.09389273, 2.09238573, 2.08987451, 2.08635972,
2.08184231, 2.07632352, 2.0698049 , 2.06228836, 2.05377617,
2.04427099, 2.03377593, 2.02229454, 2.00983085, 1.99638943,
1.98197535, 1.96659427, 1.95025238, 1.93295643, 1.91471374,
1.89553213, 1.8754199 , 1.85438575, 1.83243875, 1.80958814,
1.78584331, 1.76121353, 1.73570785, 1.70933481, 1.68210224,
1.6540169 , 1.62508422, 1.59530785, 1.5646893 , 1.53322745,
1.500918 , 1.46775295, 1.43371989, 1.39880128, 1.36297364,
1.32620657, 1.28846171, 1.24969137, 1.20983715, 1.1688281 ,
1.12657866, 1.08298619, 1.03792806, 0.99125831, 0.94280406,
0.89236193, 0.83969567, 0.78453699, 0.72659457, 0.66557999,
0.60126609, 0.53359691, 0.46285337, 0.38981596, 0.31576919,
0.2422171 , 0.17044198, 0.10122448, 0.03485021, -0.02872957,
-0.08973502, -0.14844932, -0.20516057, -0.26013525, -0.31360838,
-0.36578172, -0.41682532, -0.46688021, -0.51606127, -0.56445994,
-0.6121465 , -0.65917205, -0.70557024, -0.75135872, -0.79654052,
-0.84110525, -0.88503034, -0.92828229, -0.97081783, -1.01258522,
-1.05352556, -1.0935741 , -1.13266158, -1.17071557, -1.20766181,
-1.24342545, -1.27793226, -1.31110977, -1.34288826, -1.37320165,
-1.40198827, -1.42919143, -1.45475989, -1.47864818, -1.50081672,
-1.52123181, -1.53986552, -1.55669543, -1.57170418, -1.58487908,
-1.59621142, -1.60569592, -1.61332996, -1.6191128 , -1.62304481,
-1.62512658, -1.62535807, -1.62373765, -1.62026121, -1.6149211 ,
-1.60770518, -1.59859567, -1.58756812, -1.57459027, -1.55962099,
-1.54260932, -1.52349393, -1.50220318, -1.47865646, -1.45276789,
-1.42445376, -1.39364601, -1.36031435, -1.32449866, -1.28634925,
-1.24616428, -1.20440261, -1.16164927, -1.11853126, -1.07561487,
-1.03333011, -0.99194588, -0.95158759, -0.91227401, -0.87395459,
-0.83653893, -0.7999169 , -0.76397119, -0.72858459, -0.69364384,
-0.65904154, -0.62467677, -0.59045515, -0.55628865, -0.52209513,
-0.48779804, -0.45332606, -0.4186129 , -0.38359716, -0.3482223 ,
-0.31243678, -0.27619425, -0.23945387, -0.20218073, -0.16434633,
-0.12592914, -0.0869152 , -0.04729873, -0.00708275, 0.03372036,
0.07508832, 0.11698858, 0.15937799, 0.20220264, 0.24539788,
0.28888842, 0.33258868, 0.37640325, 0.4202275 , 0.46394834,
0.50744509, 0.55059048, 0.59325168, 0.63529154, 0.67656977,
0.71694425, 0.75627242, 0.7944127 , 0.83122582, 0.86657636,
0.90033402, 0.93237501, 0.96258314, 0.99085089, 1.01708017,
1.04118281, 1.06308089, 1.08270659, 1.10000181, 1.1149175 ,
1.12741261, 1.1374528 , 1.14500888, 1.15005494, 1.15256639,
1.15251759, 1.14987941, 1.14461641, 1.1366838 , 1.12602401,
1.1125629 , 1.0962055 , 1.07683152, 1.05429082, 1.02839993,
0.99894175, 0.9656734 , 0.92835223, 0.88679762, 0.84101338,
0.79138105, 0.73885916, 0.68499537, 0.63158026, 0.58011461,
0.53149531, 0.48605199, 0.44374855, 0.40436928, 0.36763489,
0.33326142, 0.30098534, 0.27057186, 0.24181546, 0.21453737,
0.18858212, 0.16381405, 0.1401142 , 0.11737756, 0.0955109 ,
0.07443082, 0.05406232, 0.03433748, 0.01519455, -0.00342288,
-0.02156646, -0.03928357, -0.05661762, -0.07360829, -0.0902916 ,
-0.10669994, -0.12286203, -0.13880274, -0.15454298, -0.17009946,
-0.18548448, -0.20070577, -0.21576636, -0.23066455, -0.24539396,
-0.25994378, -0.27429912, -0.28844156, -0.3023498 , -0.31600048,
-0.32936909, -0.34243085, -0.35516168, -0.36753904, -0.37954268,
-0.39115531, -0.40236298, -0.41315547, -0.42352641, -0.43347327,
-0.44299728, -0.45210323, -0.4607992 , -0.4690963 , -0.47700832,
-0.48455145, -0.491744 , -0.49860613, -0.50515959, -0.51142757,
-0.51743452, -0.52320599, -0.52876861, -0.53414994, -0.53937846,
-0.5444836 , -0.54949568, -0.55444597, -0.55936673, -0.56429129,
-0.56925413, -0.57429096, -0.57943887, -0.58473648, -0.59022408,
-0.59594385, -0.60194007, -0.6082594 , -0.61495118, -0.62206774,
-0.62966485, -0.63780211, -0.6465435 , -0.65595792, -0.66611976,
-0.67710953, -0.68901444, -0.70192871, -0.71595368, -0.73119705,
-0.74777081, -0.76578689, -0.78534865, -0.80653616, -0.82938205,
-0.85383544, -0.87971524, -0.90666289, -0.93411881, -0.96135316,
-0.98756199, -1.0119963 , -1.03406466, -1.05337146, -1.06969796,
-1.08295641, -1.09314302, -1.1003016 , -1.1044994 , -1.10581283,
-1.1043198 , -1.10009618, -1.09321472, -1.08374525, -1.07175553,
-1.05731244, -1.04048307, -1.02133584, -0.99994134, -0.97637299,
-0.95070745, -0.92302469, -0.89340787, -0.86194288, -0.82871768,
-0.79382135, -0.75734304, -0.7193706 , -0.67998921, -0.63927981,
-0.59731756, -0.55417017, -0.50989631, -0.46454401, -0.41814905,
-0.37073346, -0.32230404, -0.27285094, -0.22234635, -0.17074336,
-0.11797526, -0.0639554 , -0.00857858, 0.04827514, 0.10673204,
0.16690872, 0.22888411, 0.29265532, 0.3580776 , 0.42480159,
0.4922419 , 0.55962136, 0.62610289, 0.69095463, 0.75366322,
0.81395537, 0.87175247, 0.92710381, 0.98012854, 1.03097537,
1.07979849, 1.12674457, 1.17194683, 1.21552287, 1.2575747 ,
1.29818975, 1.33744224, 1.37539479, 1.41209987, 1.44760125,
1.48193522, 1.51513175, 1.54721545, 1.5782065 , 1.60812134,
1.6369734 , 1.66477366, 1.69153112, 1.71725328, 1.74194649,
1.76561623, 1.78826743, 1.80990466, 1.83053226, 1.85015457,
1.86877597, 1.88640095, 1.90303423, 1.9186807 , 1.93334552,
1.94703404, 1.95975182, 1.97150461, 1.9822983 , 1.99213885,
2.00103229, 2.00898462, 2.01600181, 2.02208969, 2.02725394,
2.03150002, 2.03483311, 2.03725809, 2.03877947, 2.03940138,
2.03912749, 2.03796103, 2.03590473, 2.03296079, 2.02913088,
2.02441611, 2.01881703, 2.01233359, 2.00496515, 1.99671047,
1.98756769, 1.97753431, 1.96660722, 1.95478263, 1.9420561 ,
1.92842246, 1.91387583, 1.89840954, 1.88201609, 1.86468708,
1.84641313, 1.82718378, 1.80698732, 1.7858107 , 1.76363931,
1.74045677, 1.71624468, 1.6909823 , 1.66464622, 1.63720998,
1.60864353, 1.57891279, 1.547979 , 1.5157981 , 1.48232003,
1.44748799, 1.41123784, 1.37349749, 1.33418677, 1.29321779,
1.25049656, 1.20592627, 1.15941378, 1.11088037, 1.06027866,
1.00761653, 0.95298659, 0.89659479, 0.83877539, 0.77997726,
0.72071458, 0.66149456, 0.60274982, 0.54479927, 0.48784309,
0.43198138, 0.37724196, 0.32360712, 0.27103489, 0.21947412,
0.16887442, 0.11919239, 0.07039531, 0.0224631 , -0.02461066,
-0.07081848, -0.11613911, -0.16053801, -0.20396806, -0.24637036,
-0.28767532, -0.32780373, -0.36666802, -0.40417351, -0.44021975])
# u[0] = theta1
# u[1] = omega1
# u[2] = theta2
# u[3] = omega2
= +L1 * sin(s[0, :])
x1 = -L1 * cos(s[0, :])
y1
= +L2 * sin(s[2, :]) + x1
x2 = -L2 * cos(s[2, :]) + y1 y2
plt.plot(x2, y2)=1)
plt.grid(linewidth"equal")
plt.gca().set_aspect("x2")
plt.xlabel("y2")
plt.ylabel(-2.0, 2.0))
plt.xlim((-2.0, 2.0))
plt.ylim(( plt.show()
= plt.figure(figsize=(5, 4))
fig = fig.add_subplot(autoscale_on=False, xlim=(-L, L), ylim=(-L, 1.))
ax 'equal')
ax.set_aspect(
ax.grid()
= ax.plot([], [], 'o-', lw=2, markerfacecolor="red", markeredgecolor="black")
line, = ax.plot([], [], '.-', lw=1, ms=2)
trace, = 'time = %.1f s'
time_template = ax.text(0.05, 0.9, '', transform=ax.transAxes)
time_text
def animate(i):
= [0, x1[i], x2[i]]
this_x = [0, y1[i], y2[i]]
this_y
= x2[:i]
history_x = y2[:i]
history_y
line.set_data(this_x, this_y)
trace.set_data(history_x, history_y)% (t[i]))
time_text.set_text(time_template return line, trace, time_text
= len(x1)
n = np.arange(0, n, 10)
frames = animation.FuncAnimation(fig, animate, frames, blit=True) ani
"ani_python.mp4", fps=10) ani.save(