Modeling a chaotic system
The pendulum is a classical physics system that we’re all conversant in. Be it a grandfather clock or a baby on a swing, we now have seen the common, periodic movement of the pendulum. A single pendulum is nicely outlined in classical physics, however the double pendulum (a pendulum connected to the top of one other pendulum) is literal chaos. On this article, we’re going to construct on our intuitive understanding of pendulums and mannequin the chaos of the double pendulum. The physics is fascinating and the numerical strategies wanted are a necessary device in anybody’s arsenal.
On this article we’ll:
Study harmonic movement and mannequin the conduct of a single pendulumLearn the basics of chaos theoryModel the chaotic conduct of a double pendulum numerically
Easy Harmonic Movement
We describe the periodic oscillating motion of a pendulum as harmonic movement. Harmonic movement happens when there may be motion in a system that’s balanced out by a proportional restoring pressure in the other way of mentioned motion. We see an instance of this in determine 2 the place a mass on a spring is being pulled down resulting from gravity, however this places vitality into the spring which then recoils and pulls the mass again up. Subsequent to the spring system, we see the peak of the mass going round in a circle referred to as a phasor diagram which additional illustrates the common movement of the system.
Harmonic movement may be damped (lowering in amplitude resulting from drag forces) or pushed (rising in amplitude resulting from outdoors pressure being added), however we’ll begin with the only case of indefinite harmonic movement with no outdoors forces appearing on it (undamped movement). That is form of movement is an efficient approximation for modeling a single pendulum that swings at a small angle/low amplitude. On this case we are able to mannequin the movement with equation 1 under.
We will simply put this operate into code and simulate a easy pendulum over time.
def simple_pendulum(theta_0, omega, t, phi):theta = theta_0*np.cos(omega*t + phi)return theta
#parameters of our systemtheta_0 = np.radians(15) #levels to radians
g = 9.8 #m/s^2l = 1.0 #momega = np.sqrt(g/l)
phi = 0 #for small angle
time_span = np.linspace(0,20,300) #simulate for 20s cut up into 300 time intervalstheta = []for t in time_span:theta.append(simple_pendulum(theta_0, omega, t, phi))
#Convert again to cartesian coordinatesx = l*np.sin(theta)y = -l*np.cos(theta) #damaging to ensure the pendulum is going through down
Full Pendulum Movement with Lagrangian Mechanics
A easy small angle pendulum is an efficient begin, however we wish to transcend this and mannequin the movement of a full pendulum. Since we are able to not use small angle approximations it’s best to mannequin the pendulum utilizing Lagrangian mechanics. That is a necessary device in physics that switches us from trying on the forces in a system to trying on the vitality in a system. We’re switching our body of reference from driving pressure vs restoring pressure to kinetic vs potential vitality.
The Lagrangain is the distinction between kinetic and potential vitality given in equation 2.
Substituting within the Kinetic and Potential of a pendulum given in equation 3 yields the Lagrangain for a pendulum seen is equation 4
With the Lagrangian for a pendulum we now describe the vitality of our system. There may be one final math step to undergo to remodel this into one thing that we are able to construct a simulation on. We have to bridge again to the dynamic/pressure oriented reference from the vitality reference utilizing the Euler-Lagrange equation. Utilizing this equation we are able to use the Lagrangian to get the angular acceleration of our pendulum.
After going by means of the maths, we now have angular acceleration which we are able to use to get angular velocity and angle itself. It will require some numerical integration that will probably be specified by our full pendulum simulation. Even for a single pendulum, the non-linear dynamics means there isn’t any analytical resolution for fixing for theta, thus the necessity for a numerical resolution. The mixing is kind of easy (however highly effective), we use angular acceleration to replace angular velocity and angular velocity to replace theta by including the previous amount to the latter and multiplying this by a while step. This will get us an approximation for the realm beneath the acceleration/velocity curve. The smaller the time step, the extra correct the approximation.
def full_pendulum(g,l,theta,theta_velocity, time_step):#Numerical Integrationtheta_acceleration = -(g/l)*np.sin(theta) #Get accelerationtheta_velocity += time_step*theta_acceleration #Replace velocity with accelerationtheta += time_step*theta_velocity #Replace angle with angular velocityreturn theta, theta_velocity
g = 9.8 #m/s^2l = 1.0 #m
theta = [np.radians(90)] #theta_0theta_velocity = 0 #Begin with 0 velocitytime_step = 20/300 #Outline a time step
time_span = np.linspace(0,20,300) #simulate for 20s cut up into 300 time intervalsfor t in time_span:theta_new, theta_velocity = full_pendulum(g,l,theta[-1], theta_velocity, time_step)theta.append(theta_new)
#Convert again to cartesian coordinates x = l*np.sin(theta)y = -l*np.cos(theta)
We have now simulated a full pendulum, however that is nonetheless a nicely outlined system. It’s now time to step into the chaos of the double pendulum.
Chaos, within the mathematical sense, refers to programs which can be extremely delicate to their preliminary situations. Even slight adjustments within the system’s begin will result in vastly completely different behaviors because the system evolves. This completely describes the movement of the double pendulum. Not like the only pendulum, it isn’t a nicely behaved system and can evolve in a vastly completely different method with even slight adjustments in beginning angle.
To mannequin the movement of the double pendulum, we’ll use the identical Lagrangian strategy as earlier than (see full derivation).
We will even be utilizing the identical numerical integration scheme as earlier than when implementing this equation into code and discovering theta.
#Get theta1 acceleration def theta1_acceleration(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g):mass1 = -g*(2*m1 + m2)*np.sin(theta1)mass2 = -m2*g*np.sin(theta1 – 2*theta2)interplay = -2*np.sin(theta1 – theta2)*m2*np.cos(theta2_velocity**2*l2 + theta1_velocity**2*l1*np.cos(theta1 – theta2))normalization = l1*(2*m1 + m2 – m2*np.cos(2*theta1 – 2*theta2))
theta1_ddot = (mass1 + mass2 + interplay)/normalization
return theta1_ddot
#Get theta2 accelerationdef theta2_acceleration(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g):system = 2*np.sin(theta1 – theta2)*(theta1_velocity**2*l1*(m1 + m2) + g*(m1 + m2)*np.cos(theta1) + theta2_velocity**2*l2*m2*np.cos(theta1 – theta2))normalization = l1*(2*m1 + m2 – m2*np.cos(2*theta1 – 2*theta2))
theta2_ddot = system/normalizationreturn theta2_ddot
#Replace theta1def theta1_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step):#Numerical Integrationtheta1_velocity += time_step*theta1_acceleration(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g)theta1 += time_step*theta1_velocityreturn theta1, theta1_velocity
#Replace theta2def theta2_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step):#Numerical Integrationtheta2_velocity += time_step*theta2_acceleration(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g)theta2 += time_step*theta2_velocityreturn theta2, theta2_velocity
#Run full double pendulumdef double_pendulum(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step,time_span):theta1_list = [theta1]theta2_list = [theta2]
for t in time_span:theta1, theta1_velocity = theta1_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step)theta2, theta2_velocity = theta2_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step)
theta1_list.append(theta1)theta2_list.append(theta2)
x1 = l1*np.sin(theta1_list) #Pendulum 1 xy1 = -l1*np.cos(theta1_list) #Pendulum 1 y
x2 = l1*np.sin(theta1_list) + l2*np.sin(theta2_list) #Pendulum 2 xy2 = -l1*np.cos(theta1_list) – l2*np.cos(theta2_list) #Pendulum 2 y
return x1,y1,x2,y2
#Outline system parametersg = 9.8 #m/s^2
m1 = 1 #kgm2 = 1 #kg
l1 = 1 #ml2 = 1 #m
theta1 = np.radians(90)theta2 = np.radians(45)
theta1_velocity = 0 #m/stheta2_velocity = 0 #m/s
theta1_list = [theta1]theta2_list = [theta2]
time_step = 20/300
time_span = np.linspace(0,20,300)x1,y1,x2,y2 = double_pendulum(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step,time_span)
We’ve lastly completed it! We have now efficiently modeled a double pendulum, however now it’s time to look at some chaos. Our last simulation will probably be of two double pendulums with barely completely different beginning situation. We are going to set one pendulum to have a theta 1 of 90 levels and the opposite to have a theta 1 of 91 levels. Let’s see what occurs.
We will see that each pendulums begin off with comparable trajectories however rapidly diverge. That is what we imply once we say chaos, even a 1 diploma distinction in angle cascades into vastly completely different finish conduct.
On this article we discovered about pendulum movement and the way to mannequin it. We began from the only harmonic movement mannequin and constructed as much as the complicated and chaotic double pendulum. Alongside the best way we discovered concerning the Lagrangian, chaos, and numerical integration.
The double pendulum is the only instance of a chaotic system. These programs exist in all places in our world from inhabitants dynamics, local weather, and even billiards. We will take the teachings we now have discovered from the double pendulum and apply them every time we encounter a chaotic programs.
Key Take Aways
Chaotic programs are very delicate to preliminary situations and can evolve in vastly other ways with even slight adjustments to their begin.When coping with a system, particularly a chaotic system, is there one other body of reference to take a look at it that makes it simpler to work with? (Just like the pressure reference body to the vitality reference body)When programs get too sophisticated we have to implement numerical options to resolve them. These options are easy however highly effective and supply good approximations to the precise conduct.
All figures used on this article had been both created by the writer or are from Math Pictures and full beneath the GNU Free Documentation License 1.2
Classical Mechanics, John Taylor https://neuroself.information.wordpress.com/2020/09/taylor-2005-classical-mechanics.pdf
Easy Pendulum
def makeGif(x,y,title):!mkdir frames
counter=0images = []for i in vary(0,len(x)):plt.determine(figsize = (6,6))
plt.plot([0,x[i]],[0,y[i]], “o-“, colour = “b”, markersize = 7, linewidth=.7 )plt.title(“Pendulum”)plt.xlim(-1.1,1.1)plt.ylim(-1.1,1.1)plt.savefig(“frames/” + str(counter)+ “.png”)photographs.append(imageio.imread(“frames/” + str(counter)+ “.png”))counter += 1plt.shut()
imageio.mimsave(title, photographs)
!rm -r frames
def simple_pendulum(theta_0, omega, t, phi):theta = theta_0*np.cos(omega*t + phi)return theta
#parameters of our systemtheta_0 = np.radians(15) #levels to radians
g = 9.8 #m/s^2l = 1.0 #momega = np.sqrt(g/l)
phi = 0 #for small angle
time_span = np.linspace(0,20,300) #simulate for 20s cut up into 300 time intervalstheta = []for t in time_span:theta.append(simple_pendulum(theta_0, omega, t, phi))
x = l*np.sin(theta)y = -l*np.cos(theta) #damaging to ensure the pendulum is going through down
Pendulum
def full_pendulum(g,l,theta,theta_velocity, time_step):theta_acceleration = -(g/l)*np.sin(theta)theta_velocity += time_step*theta_accelerationtheta += time_step*theta_velocityreturn theta, theta_velocity
g = 9.8 #m/s^2l = 1.0 #m
theta = [np.radians(90)] #theta_0theta_velocity = 0time_step = 20/300
time_span = np.linspace(0,20,300) #simulate for 20s cut up into 300 time intervalsfor t in time_span:theta_new, theta_velocity = full_pendulum(g,l,theta[-1], theta_velocity, time_step)theta.append(theta_new)
#Convert again to cartesian coordinates x = l*np.sin(theta)y = -l*np.cos(theta)
#Use identical operate from easy pendulummakeGif(x,y,”pendulum.gif”)
Double Pendulum
def theta1_acceleration(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g):mass1 = -g*(2*m1 + m2)*np.sin(theta1)mass2 = -m2*g*np.sin(theta1 – 2*theta2)interplay = -2*np.sin(theta1 – theta2)*m2*np.cos(theta2_velocity**2*l2 + theta1_velocity**2*l1*np.cos(theta1 – theta2))normalization = l1*(2*m1 + m2 – m2*np.cos(2*theta1 – 2*theta2))
theta1_ddot = (mass1 + mass2 + interplay)/normalization
return theta1_ddot
def theta2_acceleration(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g):system = 2*np.sin(theta1 – theta2)*(theta1_velocity**2*l1*(m1 + m2) + g*(m1 + m2)*np.cos(theta1) + theta2_velocity**2*l2*m2*np.cos(theta1 – theta2))normalization = l1*(2*m1 + m2 – m2*np.cos(2*theta1 – 2*theta2))
theta2_ddot = system/normalizationreturn theta2_ddot
def theta1_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step):
theta1_velocity += time_step*theta1_acceleration(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g)theta1 += time_step*theta1_velocityreturn theta1, theta1_velocity
def theta2_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step):
theta2_velocity += time_step*theta2_acceleration(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g)theta2 += time_step*theta2_velocityreturn theta2, theta2_velocity
def double_pendulum(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step,time_span):theta1_list = [theta1]theta2_list = [theta2]
for t in time_span:theta1, theta1_velocity = theta1_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step)theta2, theta2_velocity = theta2_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step)
theta1_list.append(theta1)theta2_list.append(theta2)
x1 = l1*np.sin(theta1_list)y1 = -l1*np.cos(theta1_list)
x2 = l1*np.sin(theta1_list) + l2*np.sin(theta2_list)y2 = -l1*np.cos(theta1_list) – l2*np.cos(theta2_list)
return x1,y1,x2,y2
#Outline system parameters, run double pendulumg = 9.8 #m/s^2
m1 = 1 #kgm2 = 1 #kg
l1 = 1 #ml2 = 1 #m
theta1 = np.radians(90)theta2 = np.radians(45)
theta1_velocity = 0 #m/stheta2_velocity = 0 #m/s
theta1_list = [theta1]theta2_list = [theta2]
time_step = 20/300
time_span = np.linspace(0,20,300)for t in time_span:theta1, theta1_velocity = theta1_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step)theta2, theta2_velocity = theta2_update(m1,m2,l1,l2,theta1,theta2,theta1_velocity,theta2_velocity,g,time_step)
theta1_list.append(theta1)theta2_list.append(theta2)
x1 = l1*np.sin(theta1_list)y1 = -l1*np.cos(theta1_list)
x2 = l1*np.sin(theta1_list) + l2*np.sin(theta2_list)y2 = -l1*np.cos(theta1_list) – l2*np.cos(theta2_list)
#Make Gif!mkdir frames
counter=0images = []for i in vary(0,len(x1)):plt.determine(figsize = (6,6))
plt.determine(figsize = (6,6))plt.plot([0,x1[i]],[0,y1[i]], “o-“, colour = “b”, markersize = 7, linewidth=.7 )plt.plot([x1[i],x2[i]],[y1[i],y2[i]], “o-“, colour = “b”, markersize = 7, linewidth=.7 )plt.title(“Double Pendulum”)plt.xlim(-2.1,2.1)plt.ylim(-2.1,2.1)plt.savefig(“frames/” + str(counter)+ “.png”)photographs.append(imageio.imread(“frames/” + str(counter)+ “.png”))counter += 1plt.shut()
imageio.mimsave(“double_pendulum.gif”, photographs)
!rm -r frames