$$ \newcommand{\D}{\displaystyle} \renewcommand{\eqref}[1]{Eq.~(\ref{#1})} $$

 

 

 

8.10 Example: Burger's equation

The 1D Burger's equation is a simple (if not the simplest) non-linear hyperbolic equation commonly used as a model equation to illustrate various numerical schemes for non-linear hyperbolic differential equations. It is normally presented as: $$ \begin{equation} \frac{\partial u}{\partial t} + u \frac{\partial u}{\partial x} = 0 \tag{8.76} \end{equation} $$

To enable us to present schemes for a greater variety of hyperbolic differential equations and to better handle shocks (i.e discontinuities in the solution), we will present our model equation on conservative form: $$ \begin{equation} \frac{\partial u}{\partial t} + \frac{\partial }{\partial x} \left (\frac{u^2}{2} \right) = 0 \tag{8.77} \end{equation} $$ and by introducing a flux function $$ \begin{equation} F(u) = \frac{u^2}{2} \tag{8.78} \end{equation} $$

the conservative formulation of the Burger's equation may be represented by a generic transport equation: $$ \begin{equation} \frac{\partial u}{\partial t} + \frac{\partial F(u)}{\partial x} = 0 \tag{8.79} \end{equation} $$

8.10.1 Upwind Scheme

The upwind scheme for the general conservation equation take the form: $$ \begin{equation} u_{j}^{n+1} = u_{j}^{n} - \frac{\Delta t}{\Delta x} \left ( F(u_{j+1}^{n}) - F(u_{j}^{n}) \right ) \tag{8.80} \end{equation} $$ where we have assumed a forward propagating wave (\( a(u) = F'(u)>0 \), i.e. \( u>0 \) for the burger equation). In the opposite case \( \frac{\partial F(u)}{\partial x} \) will be approximated by \( \frac{1}{\Delta x} \left ( F(u_{j}^{n}) - F(u_{j-1}^{n}) \right ) \)

8.10.2 Lax-Friedrich

The Lax-Friedrich conservation equation take the form as given in (8.39), repeated here for convenience: $$ \begin{equation} u_j^{n+1} = \frac{\Delta t}{2}(u^n_{j+1}+u^n_{j-1})-\frac{F^n_{j+1}-F^n_{j-1}}{2 \Delta x} \tag{8.81} \end{equation} $$

8.10.3 Lax-Wendroff

As outlined in ((8.7.1 Lax-Wendroff for non-linear systems of hyperbolic PDEs)), the general Lax-Wendroff two step method takes the form as given in (8.50) and (8.51) repeated here for convenience:

First step: $$ \begin{align} & u_{j+1/2}^{n+1/2} = \frac{1}{2} \left (u_{j+1}^{n} + u_{j}^{n} \right ) - \frac{\Delta t}{2 \Delta x} \left (F(u_{j+1}^{n}) - F(u_{j}^{n}) \right ) \tag{8.82}\\ & u_{j-1/2}^{n+1/2} = \frac{1}{2} \left (u_{j}^{n} + u_{j-1}^{n} \right ) - \frac{\Delta t}{2 \Delta x} \left (F(u_{j}^{n}) - F(u_{j-1}^{n}) \right ) \tag{8.83} \end{align} $$ $$ \begin{equation} u_{j}^{n+1} = u_{j}^{n} - \frac{\Delta t}{\Delta x} \left ( F(u_{j+1/2}^{n+1/2}) - F(u_{j-1/2}^{n+1/2}) \right ) \tag{8.84} \end{equation} $$

In the previous section ((8.7.1 Lax-Wendroff for non-linear systems of hyperbolic PDEs)) we showed how the two step Lax-Wendroff method could be condensed to a one step method. The same procedure may be applied to a the general transport equation given by (8.79). However for the nonlinear case (8.43) no longer holds. This may be overcome be rewriting (8.43): $$ \begin{equation} \begin{array}{c} \dfrac{\partial u}{\partial t}\Bigg|_j^n = -\dfrac{\partial F}{\partial x}\Bigg|_j^n \qquad \text{ and} \qquad \dfrac{\partial^2u}{\partial t^2}\Bigg|_j^n = -\dfrac{\partial^2F(u)}{\partial t \partial x }\Bigg|_j^n = -\dfrac{\partial \left(\frac{\partial F(u)}{\partial t}\right)}{\partial x }\Bigg|_j^n \\ = -\dfrac{\partial \left(\frac{\partial F(u)}{\partial u} \frac{\partial u}{\partial t}\right)}{\partial x }\Bigg|_j^n = \dfrac{\partial \left(a(u) \frac{\partial F}{\partial x}\right)}{\partial x }\Bigg|_j^n \end{array} \tag{8.85} \end{equation} $$

Now inserting into the Taylor series we get $$ \begin{equation} u_{j}^{n+1} = u_{j}^{n} - \Delta t \frac{\partial F(u)}{\partial x} + \frac{\Delta t^2}{2} \dfrac{\partial \left(a(u) \frac{\partial F}{\partial x}\right)}{\partial x } \tag{8.86} \end{equation} $$

and further we may obtain the general Lax-Wendroff one-step method for a generic transport equation $$ \begin{equation} u_{j}^{n+1} = u_{j}^{n} - \frac{\Delta t}{2 \Delta x}\left(F_{j+1} - F_{j-1}\right) + \frac{\Delta t^2}{2 \Delta x^2} \Big[a_{j+1/2}\left(F_{j+1} - F_{j}\right) - a_{j-1/2}\left(F_{j} - F_{j-1}\right)\Big] \tag{8.87} \end{equation} $$

where \( a(u) \) is the wavespeed, or the Jacobian of F, \( F'(u) \), which is \( u \) for the burger equation. As indicated \( a(u) \) has to be approximated at the indices \( (j+1/2) \) and \( (j-1/2) \). This may simply be done by averaging the neighbouring values: $$ \begin{equation} a_{j+1/2} = \frac{1}{2}\left(u_{j}^{n} + u_{j+1}^{n}\right) \tag{8.88} \end{equation} $$ for the burger equation. Another method that assure conservation is to use the following approximation $$ \begin{equation} a_{j+1/2}= \left\{ \begin{array}{ll} \frac{F_{j+1}^n-F_{j}^n}{u_{j+1}^n-u_{j}^n} \quad if \quad u_{j+1}\neq u_{j} \\ u_{j} \quad \quad \quad otherwise \end{array} \right. \tag{8.89} \end{equation} $$

8.10.4 MacCormack

The MacCormack scheme was discussed in ((8.7.1 Lax-Wendroff for non-linear systems of hyperbolic PDEs)) and is given by (8.92) repeated her for convenience $$ \begin{align} & u_j^p =u_j^n + \frac{\Delta t}{\Delta x} \left (F_{j}^{n} - F_{j+1}^{n} \right ) \tag{8.90}\\ & u_j^{n+1} =\frac{1}{2} \left (u_{j}^{n} + u_{j}^{p} \right ) + \frac{1}{2} \frac{\Delta t}{\Delta x} \left (F_{j-1}^{p} - F_{j}^{p} \right ) \tag{8.91}\\ \tag{8.92} \end{align} $$

8.10.5 Method of Manufactured solution

For the Advection equation we were able to verify our schemes by comparing with exact solutions, using MES. For the burger equation it is not easy to find an analytical solution, so in order to verify our schemes we use the MMS approach. However this requires that our schemes can handle source terms. The new equation to solve is thus the modified burgers equation $$ \begin{equation} \frac{\partial u}{\partial t} + u \frac{\partial u}{\partial x} = Q \tag{8.93} \end{equation} $$

In this chapter we will consider source terms that are a function of \( x \) and \( t \) only. The basic approach to adding source terms to our schemes is to simply add a term \( Q_i^n \) to our discrete equations. The schemes mentioned above with possibility to handle source terms are summarized in Table (tab:Conservation_schemes).

Name of Scheme Scheme order
Upwind \( u_{j}^{n+1} = u_{j}^{n} - \frac{\Delta t}{\Delta x} + \Delta t Q_j^n \) 1
Lax-Friedrich \( u_j^{n+1} = \frac{\Delta t}{2}(u^n_{j+1}+u^n_{j-1})-\frac{F^n_{j+1}-F^n_{j-1}}{2 \Delta x} + \Delta t Q_j^n \) 1
\( u_{j+1/2}^{n+1/2} = \frac{1}{2} \left (u_{j+1}^{n} + u_{j}^{n} \right )- \frac{\Delta t}{2 \Delta x} \left (F(u_{j+1}^{n}) - F(u_{j}^{n}) \right ) + \frac{\Delta t}{2} Q_{j+1/2}^n \)
Lax-Wendroff \( u_{j-1/2}^{n+1/2} = \frac{1}{2} \left (u_{j}^{n} + u_{j-1}^{n} \right )- \frac{\Delta t}{2 \Delta x} \left (F(u_{j}^{n}) - F(u_{j-1}^{n}) \right )+ \frac{\Delta t}{2} Q_{j-1/2}^n \) 2
\( u_{j}^{n+1} = u_{j}^{n} - \frac{\Delta t}{\Delta x} \left ( F(u_{j+1/2}^{n+1/2}) - F(u_{j-1/2}^{n+1/2}) \right )+ \Delta t Q_{j}^n \)
macCormack \( u_j^p =u_j^n - \frac{\Delta t}{\Delta x} \left (F_{j+1}^{n} -F_{j}^{n} \right ) + \Delta t Q_{j}^{n+1/2} \) 2
\( u_j^{n+1} =\frac{1}{2} \left (u_{j}^{n} + u_{j}^{p} \right ) - \frac{1}{2} \frac{\Delta t}{\Delta x} \left (F_{j}^{p} - F_{j-1}^{p} \right )+ \frac{\Delta t}{2} Q_{j}^{n+1/2} \)


Examples on how to implement these schemes are given below, where we have used \( RHS(x,t) \) instead of \( Q \) for the source term:
ftbs or upwind:

def ftbs(u, t):
    """method that solves u(n+1), for the scalar conservation equation with source term:
        du/dt + dF/dx = RHS,
        where F = 0.5u^2 for the burger equation
        with use of the forward in time backward in space (upwind) scheme
        
        Args:
            u(array): an array containg the previous solution of u, u(n). (RHS)
            t(float): an array 
        Returns:
            u[1:-1](array): the solution of the interior nodes for the next timestep, u(n+1).
    """
    u[1:-1] = u[1:-1] -  (dt/dx)*(F(u[1:-1])-F(u[:-2])) + dt*RHS(t-0.5*dt, x[1:-1])
    return u[1:-1]

Lax-Friedrich's:

def lax_friedrich_Flux(u, t):
    """method that solves u(n+1), for the scalar conservation equation with source term:
        du/dt + dF/dx = RHS,
        where F = 0.5u^2 for the burger equation
        with use of the lax-friedrich scheme
        
        Args:
            u(array): an array containg the previous solution of u, u(n). (RHS)
            t(float): an array 
        Returns:
            u[1:-1](array): the solution of the interior nodes for the next timestep, u(n+1).
    """
    u[1:-1] = (u[:-2] +u[2:])/2.0 -  dt*(F(u[2:])-F(u[:-2]))/(2.0*dx) + dt*(RHS(t, x[:-2]) + RHS(t, x[2:]))/2.0
    return u[1:-1]

Lax-Wendroff-Two-step:

def Lax_W_Two_Step(u, t):
    """method that solves u(n+1), for the scalar conservation equation with source term:
        du/dt + dF/dx = RHS,
        where F = 0.5u^2 for the burger equation
        with use of the Two-step Lax-Wendroff scheme
        
        Args:
            u(array): an array containg the previous solution of u, u(n).
            t(float): time at t(n+1) 
        Returns:
            u[1:-1](array): the solution of the interior nodes for the next timestep, u(n+1).
    """
    ujm = u[:-2].copy() #u(j-1)
    uj = u[1:-1].copy() #u(j)
    ujp = u[2:].copy() #u(j+1)
    up_m = 0.5*(ujm + uj) - 0.5*(dt/dx)*(F(uj)-F(ujm)) + 0.5*dt*RHS(t-0.5*dt, x[1:-1] - 0.5*dx) #u(n+0.5dt,j-0.5dx)
    up_p = 0.5*(uj + ujp) - 0.5*(dt/dx)*(F(ujp)-F(uj)) + 0.5*dt*RHS(t-0.5*dt, x[1:-1] + 0.5*dx)#u(n+0.5dt,j+0.5dx)
    
    u[1:-1] = uj -(dt/dx)*(F(up_p) - F(up_m)) + dt*RHS(t-0.5*dt, x[1:-1])
    return u[1:-1]

macCormack:

def macCormack(u, t):
    """method that solves u(n+1), for the scalar conservation equation with source term:
        du/dt + dF/dx = RHS,
        where F = 0.5u^2 for the burger equation
        with use of the MacCormack scheme
        
        Args:
            u(array): an array containg the previous solution of u, u(n). (RHS)
            t(float): an array 
        Returns:
            u[1:-1](array): the solution of the interior nodes for the next timestep, u(n+1).
    """
    up = u.copy()
    up[:-1] = u[:-1] - (dt/dx)*(F(u[1:]) - F(u[:-1])) + dt*RHS(t-0.5*dt, x[:-1])
    u[1:] = .5*(u[1:] + up[1:] -  (dt/dx)*(F(up[1:]) - F(up[:-1])) + dt*RHS(t-0.5*dt, x[1:])) 
    return u[1:-1]

Exercise 11: Stability analysis of the Lax-Friedrich scheme

In this exercise we want to assess the stability of the Lax-Friedrich scheme for the advection equation as formulated in (8.40).

a) Use the PC-criterion to find a sufficient condition for stability for (8.40).

b) Use the von Neumann method to find a sufficient and necessary condition for stability for (8.40) and compare with the PC-condition