LAB – Chaos#
Please write your name in this box
We encourage you to work together, and seek whatever help you need in completing this lab. Please list all people who you worked with or received help from
We encourage you to use any online resources that you find useful. Please list any URL’s that you consulted
We encourage you to use AI resources if you find them useful. If you made use of AI, please list the platform and the prompts which you made use of
Background#
There are some areas of physics which are simply impossible to study without computers. One of these is chaos a phenomenon which was first observed in numerical experiments.
A chaotic system is characterized by sensitive dependence to initial conditions. This means that making a small change to your initial conditions leads to a large change in the trajectory at long times. One quantifies this property by looking at how the difference
There are a number of cannonical examples of chaotic systems. Some of these are described by differential equations, such as:
Double Pendulum
Driven nonlinear oscillator (Duffing Oscillator)
Harmonic oscillator with non-linear damping (Van der Pol oscillator)
Lorenz equations (simple climate model)
One generically expects that any sufficiently nonlinear set of differential equations with enough degrees of freedom will display chaos.
There are also discrete maps that display chaos.
This will be a short lab where you investigate a chaotic system. To get chaos you need at least 3 degrees of freedom for an autonomous system, or 2 degrees of freedom for a driven system. We will use the example of the Duffing oscillator, a nonlinear oscillator with periodic driving. It is a nice example because it has parameters which let you tune from regular to chaotic behavior.
Workflow#
Feel free to use whatever workflow you find helpful. Do everything in one notebook, or use a file that you import with include
. As a reminder you can use @debug
statements, and turn on/off the output of those with
using Logging
default_logger=global_logger()
debug_logger=ConsoleLogger(stderr, Logging.Debug); # set up logger
# global_logger(debug_logger) # turns on printing of @debug statements
# global_logger(default_logger) # turns off printing of @debug statements
#
# or wrap code in
# with_logger(debug_logger) do
# ...
# end
I am going to recommend that you use DifferentialEquations.jl
for solving our equations. Here is a quick reminder of the syntax.
using DifferentialEquations,Plots
function pendulum_dxdt(x,p,t)
(theta,v)=x
return [v, -sin(theta)]
end
xp0=[pi/2, 0.]
tspan=[0., pi*10]
args1=ODEProblem(pendulum_dxdt,xp0,tspan)
ptraj1=solve(args1)
plot(ptraj1,label=["θ" "ω"],xlabel="t",ylabel="θ,ω")
twpoints=[Tuple(ptraj1(t)) for t in 0:0.1:10*pi]
plot(twpoints,xlabel="θ",ylabel="v",label="")
We are going to make a lot of plots like that, so it is useful to make some visualization functions
function plot_xt(trajectory,initialT,finalT,dT;opts...)
xt=[(t,trajectory(t)[1]) for t in initialT:dT:finalT]
plot(xt;opts...)
end
function plot_xt!(trajectory,initialT,finalT,dT;opts...)
xt=[(t,trajectory(t)[1]) for t in initialT:dT:finalT]
plot!(xt;opts...)
end
function plot_xv(trajectory,initialT,finalT,dT;opts...)
xv=[Tuple(trajectory(t)) for t in initialT:dT:finalT]
plot(xv;opts...)
end
function plot_xv!(trajectory,initialT,finalT,dT;opts...)
xv=[Tuple(trajectory(t)) for t in initialT:dT:finalT]
plot!(xv;opts...)
end
plot_xv! (generic function with 1 method)
Here are some sample uses
plot_xt(ptraj1,0,10,0.1;xlabel="t",ylabel="θ",label="θ₀=π/2")
plot_xv(ptraj1,0,10,0.1;xlabel="θ",ylabel="ω",label="")
It is a good strategy to make short scripts like these to make your future code easier to write. Whenever you find yourself doing a lot of copy and paste, it is probably time to encapsulate it.
## Activity 1
We will consider a non-linear oscillator described by the equations
Here
An interesting case is when
Write a function that takes the parameters DifferentialEquations.jl
.
There are various ways of organizing the input. Personally I like this sort of signature:
function duffing(initialxv,T,α,β,γ,F,ω)
...
end
and then the following two extra signatures
duffing(initialxv,T;α,β,γ,F,ω)=duffing(initialxv,T,α,β,γ,F,ω)
duffing(;initialxv,T,α,β,γ,F,ω)=duffing(initialxv,T,α,β,γ,F,ω)
I would then call it with
params=(α=-1,β=1,γ=0,F=0,ω=1)
duffing([1.5,0],10;params...)
Test by setting
See if you can do a more finely spaced set of initial values – say
## Activity 2
We will now add driving and damping. From your experience with damped Harmonic oscillators, you expect to have some transients, before the system settles into periodic motion at the drive frequency.
Take initialT=150
to finalT=200
. It should look like a nice periodic orbit. (It is also fun to look at the transient behavior, but it is a bit complicated looking)
Compare with the case where
## Activity 3
Increase
Compare the case of
## Activity 4
One challenge with these chaotic systems is that the trajectories are kind of complicated. One approach to taming this complexity is to view the system stroboscopically. If we plot
We can create a Poincare Section by creating a command scatter_xv
, which is the same as plot_xv
, but uses the scatter
command instead of plot
. we then evaluate scatter_xv
with a timestep of 2\pi/\omega
. (Note the integrator does not use this time-step, it just reflects when we plot the data.)
Create Poincare Sections for the two trajectories you calculated in the last activity. You will want to go to longer times – say
You should see that the points will trace out some curve in phase space – referred to as a “strange attractor.” It turns out that this object is a fractal.