import numpy
from matplotlib import pyplot
%matplotlib inline
Last time, we investigated a system consisting of two masses $m$ coupled to each other by a spring of spring constant $k$. These masses were also coupled to walls with springs having the same spring constant $k$, so the whole system had the following configuration:
WALL] /\/\/\/\/ [BLOCK 1] /\/\/\/\/ [BLOCK 2] /\/\/\/\/ [WALL
Assume, for simplicity, that the springs are at their natural lengths when the system is sitting at rest. You were asked to use Euler's method to determine what the motion of this system would look like given particular initial conditions, and then you were asked to investigate some properties of the motion under general initial conditions. In this session, we will extend our analysis of coupled oscillators in the following ways:
We will
Recall that Euler's method works as follows:
Start with the equation of motion of your system which will be of the form
$$ \ddot x = \frac{F}{m}. $$It's a second-order ODE for the unknown function $x(t)$. If the system consists of an object moving in more than one dimension, then we would write the position and force as vectors. If there is more than one object in the system, then there will be one such equation of motion for each.
The next step is to introduce the velocity $v(t)$ as a new unknown function and convert your original equation of motion into a pair first-order differential equations of the form:
\begin{align} \dot x(t) &= v(t) \\ \dot v(t) &= \frac{F}{m} \end{align}Then, choose some initial conditions $x_0$ and $v_0$, choose a time step $\Delta t$, and choose a number of steps. Generate a discrete approximation to $x(t)$ and $v(t)$ in the form of a sequence of $x$ values and $v$ values by using the following iteration scheme:
\begin{align} x_{n+1} = x_n + v_n\, \Delta t \\ v_{n+1} = v_n + \frac{F_n}{m}\, \Delta t \\ \end{align}Amazingly, by altering this scheme only slightly, we will able to vastly improve its performance on the sort of oscillating systems we've been working with. The new scheme is called the Euler-Cromer algorithm, and it works like this:
\begin{align} v_{n+1} &= v_n + \frac{F_n}{m}\, \Delta \\ x_{n+1} &= x_n + v_{n+1}\,\Delta t \end{align}What are the differences between the Euler-Cromer scheme and the Euler scheme?
Euler-Cromer uses the result of $v_{n+1}$ to calculate the next $x_{n+1}$ also velocity does not depend on position.
### Answer.
m = 2.0
k = 1.0
x_0 = 1.0
v_0 = 0.0
delta_t = 0.5
num_steps = 50
t_array = numpy.zeros(num_steps + 1)
x_array = numpy.zeros(num_steps + 1)
v_array = numpy.zeros(num_steps + 1)
v_ecarray = numpy.zeros(num_steps + 1)
x_ecarray = numpy.zeros(num_steps + 1)
t_array[0] = 0.0
x_array[0] = 1.0
v_array[0] = 0.0
v_ecarray[0] = 0.0
x_ecarray[0] = 1.0
for n in range(num_steps):
t_array[n + 1] = t_array[n] + delta_t
x_array[n + 1] = x_array[n] + v_array[n] * delta_t
v_array[n + 1] = v_array[n] - (k / m) * x_array[n] * delta_t
#EC
v_ecarray[n + 1] = v_ecarray[n] + (-1 * k * x_ecarray[n] / m) * delta_t
x_ecarray[n + 1] = x_ecarray[n] + v_ecarray[n+1] * delta_t
pyplot.plot(t_array, x_array, 'green') #plot of Euler's method
pyplot.plot(t_array, x_ecarray, 'red') #plot of Euler-Cromer's method
# Euler-Cromer's graph is more concave. Euler's method produces more error
As we'll see in a moment, we can use linear algebraic concepts to better predict and understand what the system of coupled oscillators will do. Doing linear algebra with python is pretty easy using numpy. For example, to specify a 2-by-2 matrix $A$, we would type
A = numpy.array([[1, 0], [0, 2]])
This defines the 2-by-2 matrix
$$ A = \begin{pmatrix} 1 & 0 \\ 0 & 2 \end{pmatrix} $$What the code is doing is taking a list of lists (aka a nested list) [[1, 0], [0, 1]] and converting it into an object called a numpy array which can be manipulated like a matrix. For example, we can find its eigenvalues and corresponding eigenvectors as follows:
from numpy import linalg #imports a linear algebra package in numpy (once you import once, you don't have to do it again)
linalg.eig(A)
As you can see, this command outputs one array the gives the eigenvalue $1$ and $2$, and another array that gives the corresponding eigenvectors $\binom{1}{0}$ and $\binom{0}{1}$.
We will now explore how eigenvalues and eigenvectors can give us insight into the dynamics of a system of couple oscillators through a sequence of exploratory exercises:
where $A$ is a 2-by-2 matrix that depends on the $\omega = \sqrt{k/m}$.
Consider now a system of three coupled oscillators:
WALL] /\/\/\/\/ [BLOCK 1] /\/\/\/\/ [BLOCK 2] /\/\/\/\/ [BLOCK 3] /\/\/\/\/ [WALL
Write the equation of motion for a system of three coupled oscillators in matrix form as follows:
\begin{align} \begin{pmatrix} \ddot x_1 \\ \ddot x_2 \\ \ddot x_3 \end{pmatrix} = -A\begin{pmatrix} x_1 \\ x_2 \\ x_3 \end{pmatrix} \end{align}k = 1.0
m = 1.0
w = (k / m)**(1/2)
A = numpy.array([[2*w**2, -1*w**2], [-1*w**2, 2*w**2]])
linalg.eig(A)
print(A[1,1])
m = 1.0
k = 0.5
x_1 = [0.707]
v_1 = [0.0]
x_2 = [0.707]
v_2 = [0.0]
delta_t = 0.5
num_steps = 50
j = 1
t_array = numpy.zeros(num_steps + 1)
x_1array = numpy.zeros(num_steps + 1)
x_2array = numpy.zeros(num_steps + 1)
v_1array = numpy.zeros(num_steps + 1)
v_2array = numpy.zeros(num_steps + 1)
for j in range(1):
t_array[0] = 0.0
x_1array[0] = x_1[j]
v_1array[0] = v_1[j]
x_2array[0] = x_2[j]
v_2array[0] = v_2[j]
n = 0
for n in range(num_steps):
t_array[n + 1] = t_array[n] + delta_t
v_1array[n + 1] = v_1array[n] + (( 2*k*x_1array[n] - k*x_2array[n] ) / m) * delta_t
v_2array[n + 1] = v_2array[n] + ( ( 2*k*x_2array[n] - k*x_1array[n] ) / m) * delta_t
x_1array[n + 1] = x_1array[n] + v_1array[n+1] * delta_t
x_2array[n + 1] = x_2array[n] + v_2array[n+1] * delta_t
pyplot.plot(x_1array, t_array, 'red')