Content under Creative Commons Attribution license CC-BY 4.0, code under MIT license (c) L.A. Barba, G.F. Forsyth, C. Cooper, 2014. Based on CFDPython, (c) L. A. Barba, also under CC-BY license.

Non-linear Convection

We're back! This is the second IPython Notebook of the series Space and Time — Introduction of Finite-difference solutions of PDEs, the second module of "Practical Numerical Methods with Python".

In the previous notebook, "1-D Linear Convection", we learned how to solve the linear convection equation using the finite-difference method. Now let's move on to the non-linear convection equation, using the same methods as before. The 1-D convection equation is:

\begin{equation}\frac{\partial u}{\partial t} + u \frac{\partial u}{\partial x} = 0\end{equation}

Instead of a constant factor $c$ multiplying the second term, now we have the solution $u$ multiplying it. Thus, the second term of the equation is now non-linear. We're going to use the same discretization as in linear convection — forward difference in time and backward difference in space. Here is the discretized equation.

\begin{equation}\frac{u_i^{n+1}-u_i^n}{\Delta t} + u_i^n \frac{u_i^n-u_{i-1}^n}{\Delta x} = 0\end{equation}

Solving for the only unknown term, $u_i^{n+1}$, yields:

\begin{equation}u_i^{n+1} = u_i^n - u_i^n \frac{\Delta t}{\Delta x} (u_i^n - u_{i-1}^n)\end{equation}

As before, the Python code starts by loading the necessary libraries. Then, we declare some variables that determine the discretization in space and time (you should experiment by changing these parameters to see what happens). Then, we create the initial condition $u_0$ by initializing the array for the solution using $u = 2\ @\ 0.5 \leq x \leq 1$ and $u = 1$ everywhere else in $(0,2)$ (i.e., a hat function).


In [ ]:
import numpy                       #we're importing numpy 
import matplotlib.pyplot as plt    #and our 2D plotting library, calling it plt
%matplotlib inline

nx = 41
dx = 2./(nx-1)
nt = 20    #nt is the number of timesteps we want to calculate
dt = .025  #dt is the amount of time each timestep covers (delta t)

u = numpy.ones(nx)      #as before, we initialize u with every value equal to 1.
u[.5/dx : 1/dx+1]=2  #then set u = 2 between 0.5 and 1 as per our I.C.s

un = numpy.ones(nx) #initialize our placeholder array un, to hold the time-stepped solution

The code snippet below is unfinished. We have copied over the line from the linear convection case that executes the time-stepping update. Can you edit this code to execute the non-linear convection instead?


In [ ]:
for n in range(nt):  #iterate through time
    un = u.copy() ##copy the existing values of u into un
    for i in range(1,nx):  ##now we'll iterate through the u array
    
     ###This is the line from Step 1, copied exactly.  Edit it for our new equation.
     ###then uncomment it and run the cell to evaluate Step 2   
      
           ###u[i] = un[i]-c*dt/dx*(un[i]-un[i-1]) 

        
plt.plot(numpy.linspace(0,2,nx),u) ##Plot the results

What do you observe about the evolution of the hat function under the non-linear convection equation? What happens when you change the numerical parameters and run again?


In [ ]:
from IPython.core.display import HTML
css_file = '../../styles/numericalmoocstyle.css'
HTML(open(css_file, "r").read())