Advection

We start our study with the scalar, linear hyperbolic PDE: the advection equation. The solution to this equation simply consists of the initial condition propagating with constant velocity. We first describe the physical origin of this equation and then investigate the solution of the corresponding Riemann problem. This equation is studied in more detail e.g. in Chapter 2 of (LeVeque, 2002), for example.

To examine the Python code for this chapter, see:

Conservation of mass

Imagine a fluid flowing in a long, narrow tube. We'll use $q$ to indicate the density of the fluid and $u$ to indicate its velocity. Both of these are functions of space and time: $q = q(x,t)$; $u=u(x,t)$. The total mass in the section of tube $[x_1,x_2]$ is
\begin{equation*} \int_{x_1}^{x_2} q(x,t) dx. \end{equation*}
This total mass changes over time due to flow in or out of this section of the tube. We call the rate of flow the flux, and denote it by $f(q)$. Thus the net rate of flow of mass into (or out of) the interval $[x_1,x_2]$ at time $t$ is
$$f(q(x_1,t)) - f(q(x_2,t)).$$
We just said that this rate of flow must equal the time rate of change of total mass; i.e.
$$\frac{d}{dt} \int_{x_1}^{x_2} q(x,t) dx = f(q(x_1,t)) - f(q(x_2,t)).$$
Now since $\int_{x_1}^{x_2} \frac{\partial}{\partial x} f(q) dx = f(q(x_2,t)) - f(q(x_1,t))$, we can rewrite this as
$$\frac{d}{dt} \int_{x_1}^{x_2} q(x,t) dx = -\int_{x_1}^{x_2} \frac{\partial}{\partial x} f(q) dx.$$
If $q$ is sufficiently smooth, we can move the time derivative inside the integral. We'll also put everything on the left side, to obtain
$$\int_{x_1}^{x_2} \left(\frac{\partial}{\partial t}q(x,t) + \frac{\partial}{\partial x} f(q)\right) dx = 0.$$
Since this integral vanishes for any choice of $x_1,x_2$, it must be that the integrand vanishes everywhere. Therefore we can write the differential conservation law
$$q_t + f(q)_x = 0.$$
This equation expresses the fact that the total mass is conserved, since locally the mass can change only due to a net inflow or outflow.

Advection

In order to solve the conservation law above, we need an expression for the flux, $f$. The rate of flow is just density times velocity: $f=u q$. Thus we obtain the continuity equation
$$q_t + (uq)_x = 0.$$

In general, we need another equation to determine the velocity $u(x,t)$. In later chapters we'll examine models in which the velocity depends on the density (or other properties), but for now let's consider the simplest case, in which the flow is characterized by a single, constant velocity $u(x,t)=a$. Then the continuity equation becomes the advection equation
\begin{align} \label{adv:advection} q_t + a q_x = 0. \end{align}
This equation has a very simple solution. Given the initial density $q(x,0)=q_0(x)$, the solution is simply
\begin{align} \label{adv:solution} q(x,t) = q_0(x-at). \end{align}

In [1]:
%matplotlib inline
In [2]:
%config InlineBackend.figure_format = 'svg'
from utils.snapshot_widgets import interact
from exact_solvers import advection
Will create static figures with single value of parameters

Characteristics

Notice that the solution is constant along the line $x-at=C$, for each value of $C$. These are parallel, straight lines in the $x-t$ plane, with slope $1/a$, as shown in the figure below.

In [3]:
interact(advection.characteristics);

We can think of the initial values $q_0(x)$ being transmitted along these lines; we sometimes say that information is transmitted along characteristics.

The next figure shows how an initial hump propagates to the right along characteristics.

In [4]:
interact(advection.solution);

For more complicated hyperbolic problems, we may have multiple sets of characteristics, they may not be parallel, and the solution may not be constant along them. But it will still be the case that information is propagated along characteristics. The idea that information propagates at finite speed is an essential property of hyperbolic PDEs.

The Riemann problem

The Riemann problem consists of a hyperbolic PDE, such as (\ref{adv:advection}), together with piecewise constant initial data consisting of two states. For convenience, we place the interface (or jump) at $x=0$ and refer to the left state (for $x<0$) as $q_l$ and the right state (for $x>0$) as $q_r$. We thus have
\begin{align*} q_0(x) & = \begin{cases} q_l & x<0 \\ q_r & x>0. \end{cases} \end{align*}
For the advection equation, the solution to the Riemann problem is immediately obvious; it is simply a special case of (\ref{adv:solution}). The discontinuity initially at $x=0$ moves at speed $a$. We have
\begin{align*} q(x,t) & = \begin{cases} q_l & x-at<0 \\ q_r & x-at>0. \end{cases} \end{align*}

In [5]:
interact(advection.riemann_demo);

Notice how the initial discontinuity follows the characteristic coming from $x=0$ at $t=0$. In the live notebook, you can adjust the advection speed $a$ and see how this changes the solution.

Here's another way to look at the Riemann solution that will be very useful for more complicated equations.

In [6]:
q_l = 1.
q_r = 0.
advection.plot_riemann_solution(q_l, q_r, a=1.);

The left plot shows (again) the characteristics in the x-t plane; the characteristic along which the discontinuity propagates is darker and thicker. The right plot shows the solution. In the live notebook you can advance a time slider and see how the wave propagates. Try modifying the initial states and the velocity $a$ to see how this simple solution changes.