This webpage is a static view of an interactive Jupyter Notebook tutorial. To get the full interactive experience where you can run Python code, modify examples and complete exercises, click the "Open in Colab" button. This will access the Google Colab notebook from a GitHub repository github.com/dchappell2/Computational-Physics and open it in Google Colab. You will need a Google account if you want to open it in Colab.
Note: You can download a pdf of the lecture slides for this tutorial here: ODE 2 slides
In this section, we re-write our Euler code around two functions:
Euler() that performs the numerical integrationHere are the details for each function.
Derivative Function:
Euler Integration Function
Euler()deriv = function that returns the derivative defining our ODEy0 = initial condition for variable ytmax = upper integration limit in timeparams = tuple containing one or more parameters that will be passed to the derivative function.t = numpy array containing time values in the numerical integrationy = result of the numerical integrationIn this example, we re-write our exponential growth example using Euler integration and the modular approach described above. Our differential equation is $$\frac{dy}{dt}=ay.$$
Note: We want to write our code generally, so that the derivative function can take one or more parameters. In the main code we bundle the parameters in an array called params. But in the derivative function, the parameters are listed as separate variables. To handle this, we need to "unpack" the params array and assign each element of the array to each of the parameters in the derivative function. To do this we use the "unpacking" operator, i.e. we place an asterisk * before the name of our params array when we pass it to the derivative function like this:
```
f = deriv(t[n], y[n], params) # use "" to unpack params
```
Here's the code:
import numpy as np
import matplotlib.pyplot as plt
######### Derivative Function #########
#
# This function returns the derivative for the exponential growth ODE dy/dt = ay
######### Derivative Function #########
def deriv_exp(t, y, a):
dydt = a*y
return dydt
######### Euler Integration #########
def Euler(deriv, y0, tmax, dt, params):
######### Create Arrays #########
N = int(tmax/dt)+1 # number of steps in simulation
y = np.zeros(N) # array to store y values
t = np.zeros(N) # array to store times
y[0] = y0 # assign initial value
######### Loop to implement the Euler update rule #########
for n in range(N-1):
f = deriv(t[n], y[n], *params) # use "*" to unpack params
y[n+1] = y[n] + f*dt
t[n+1] = t[n] + dt
return t, y
######### Parameters #########
a = 0.2 # decay constant
tmax = 100 # maximum time
dt = 0.5 # time step
y0 = 1 # initial value of y
params = [a] # bundle parameters in an array
######### Perform Euler Integration #########
t, y = Euler(deriv_exp, y0, tmax, dt, params)
######### Analytic Solution #########
y_true = y0 * np.exp(a*t)
######### Plot Solution #########
plt.plot(t, y, label='Euler')
plt.plot(t, y_true, '--', label='Analytic')
plt.xlabel('t') # label the x and y axes
plt.ylabel('y')
plt.title("Exponential Decay") # give the plot a title
plt.legend() # display the legend
plt.show() # display the plot
In this example, you will solve for the number of photons $n$ in a laser cavity. Use the example above to solve the following ODE for $n(t)$: $$ \frac{dn}{dt} = (GN_0 -k) n- (\alpha G) n^2$$ where $n$ is the number of photons in the laser field and
Specifications:
deriv_exp() function with your own function to return the derivative of the number of laser photonsparams variable will need to be a list containing the values $N_0$, $G$, etc. You'll need to 'bundle' these parameters together in your main program and the 'unpack' them inside your derivatives function.Euler() functionRun your code to produce two plots:
### Your Code Here
We've already seen one system of ODEs in the previous chapter: the simple hamonic oscillator.
Second-order ODE's arise naturally from Newton's second law since acceleration is a second order derivative:
$$\frac{d^2x}{dt^2}=a = \frac{F}{m}$$
where the acceleration is potentially a function of position, velocity, time and mass: $a=F(x, v, t)/m$.
As discussed in the lecture slides, we write this second-order equation as two first-order equations like this:
$$ \frac{dx}{dt} = v $$
$$ \frac{dv}{dt} = \frac{a}{m}. $$
We can write this system of ODEs as a single vector equation, where the components of the generalized vector are position and velocity. If we define our generalized vector as $\vec{y}$, its components will be $$y_0(t) = x(t)$$ and $$y_1(t) = v(t).$$ The vector $\vec{y}$ may be written as
$$\vec{y} = \begin{pmatrix}y_0(t) \\ y_1(t) \end{pmatrix} = \begin{pmatrix}x \\ v \end{pmatrix}.$$
With these substitutions, we can write our system of coupled ODEs as
$$ \frac{dy_0}{dt} = y_1 $$
$$ \frac{dy_1}{dt} = -(k/m)y_0. $$
Our system of differential equations may now be written as a single vector equation:
$$\frac{d\vec{y}}{dt}=\vec{a}(\vec{y},t),$$ where $\vec{a}(\vec{y},t)$ is a vector-valued acceleration:
$$\vec{a}(\vec{y},t)= \begin{pmatrix}v \\ -(k/m)x \end{pmatrix} = \begin{pmatrix}y_1 \\ -(k/m)y_0\end{pmatrix}.$$
We can now apply our favoriate numerical integration method to this single vector-valued ODE. For example the Euler update rule for our generalized state vector would be:
$$ \vec{y}_{n+1} = \vec{y}_n + \vec{a}_n \Delta t.$$
Here's the code for the Simple Harmonic Oscillator. We introduce a new derivative function and a new Euler function that handles multi variables.
import numpy as np
import matplotlib.pyplot as plt
######### Derivative Function #########
#
# This function returns the derivatives for the
# Simple Harmonic Oscillator ODE
def deriv_sho(t, y, m, k):
# extract variables from y array
x = y[0] # position
v = y[1] # velocity
# calculate derivatives
dxdt = v
dvdt = -k/m*x
# return derivatives in a numpy array
return np.array([dxdt, dvdt])
######### Euler Integration #########
#
# This function integrates an ODE specified by a passed derivative function
#
# Passed parameters:
# deriv = function created by the user that returns the derivatives for the system of ODEs
# y0 = 1xN array containing initial conditions
# tmax = maximum time to run the integration
# dt = time step
# params = 1xM array containing parameters for the derivative function
#
# Returned values:
# t = 1D array containing time values of the solution
# y = 2D array whose columns are the solutions for each variable
######### Multi-Variable Euler Integration #########
def Euler_Vec(deriv, y0, tmax, dt, params):
######### Create Arrays #########
# determine the number of variables in the system from initial conditions
nvar = 1 if not isinstance(y0, np.ndarray) else y0.size
N = int(tmax/dt)+1 # number of steps in simulation
y = np.zeros((N,nvar)) # array to store y values
t = np.zeros(N) # array to store times
if nvar == 1:
y[0] = y0 # assign initial value if single variable
else:
y[0,:] = y0 # assign vector initial values if multivariable
######### Loop to implement the Euler update rule #########
for n in range(N-1):
f = deriv(t[n], y[n], *params)
y[n+1] = y[n] + f*dt
t[n+1] = t[n] + dt
return t, y
import numpy as np
import matplotlib.pyplot as plt
######### Parameters #########
m = 1 # mass
k = 1 # spring constant
tmax = 10 # maximum time
dt = 0.001 # time step
x0 = 1 # initial position
v0 = 0 # initial velocity
params = np.array([m,k]) # bundle parameters together
y0 = np.array([x0,v0]) # bundle initial conditions
######### Perform Euler Integration #########
t, y = Euler_Vec(deriv_sho, y0, tmax, dt, params)
x = y[:,0] # extract positions
v = y[:,1] # extract velocities
######### Plot Solution #########
plt.plot(t, x, label='x') # plot position
plt.plot(t, v, '--', label='v') # plot velocity
plt.xlabel('t') # label the x and y axes
plt.ylabel('x, v')
plt.title("SHO") # give the plot a title
plt.legend() # display the legend
plt.show() # display the plot
Write code to model the motion of a mass attached to a pivot by a spring with spring constant $k$ immersed in a fluid with fluid drag coefficient $b$. Assume the mass can move in the x-y plane.
$$\frac{dx}{dt} = v_x$$
$$\frac{dy}{dt} = v_x$$
$$\frac{dv_x}{dt} = -\frac{kx+bv_x}{m} $$
$$\frac{dv_y}{dt} = -\frac{ky+bv_y}{m} $$
### Your Code Here