{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Advection" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start our study with the scalar, linear hyperbolic PDE: the advection equation. In this chapter we consider one of the most simple hyperbolic conservation laws, the scalar constant-coefficient advection equation. The solution to this equation simply consists of the initial condition propagating with constant velocity. This equation is extremely important to understand before tackling linear hyerbolic systems, which can be solved by decoupling the system into a set of advection equations. We first describe the physical origin of this equation and then investigate the solution to its Riemann problem. This equation is studied in more detail in Chapter 2 of (LeVeque, 2002)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conservation of mass\n", "\n", "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 \n", "\\begin{equation*}\n", "\\int_{x_1}^{x_2} q(x,t) dx.\n", "\\end{equation*} \n", "This total mass can change in time due to fluid flowing in or out of this section of the tube. We call the rate of flow the *flux*, and represent it with the function $f(q)$. Thus the net rate of flow of mass into (or out of) the interval $[x_1,x_2]$ at time $t$ is \n", "$$f(q(x_1,t)) - f(q(x_2,t)).$$ \n", "We just said that this rate of flow must equal the time rate of change of total mass; i.e. \n", "$$\\frac{d}{dt} \\int_{x_1}^{x_2} q(x,t) dx = f(q(x_1,t)) - f(q(x_2,t)).$$ \n", "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 \n", "$$\\frac{d}{dt} \\int_{x_1}^{x_2} q(x,t) dx = -\\int_{x_1}^{x_2} \\frac{\\partial}{\\partial x} f(q) dx.$$ \n", "Under certain smoothness assumptions on $q$, we can move the time derivative inside the integral. We'll also put everything on the left side, to obtain \n", "$$\\int_{x_1}^{x_2} \\left(\\frac{\\partial}{\\partial t}q(x,t) + \\frac{\\partial}{\\partial x} f(q)\\right) dx = 0.$$ \n", "Since this integral is zero for *any* choice of $x_1,x_2$, it must be that the integrand (the expression in parentheses) is actually zero *everywhere*! Therefore we can write the **differential conservation law** \n", "$$q_t + f(q)_x = 0.$$ \n", "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." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Advection\n", "In order to solve the conservation law above, we need an expression for the flux, $f$. The rate of flow is just mass times velocity: $f=u q$. Thus we obtain the **continuity equation** \n", "$$q_t + (uq)_x = 0.$$ \n", "\n", "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 all of the fluid flows at a single, constant velocity $u(x,t)=a$. Then the continuity equation becomes the **advection equation** \n", "\\begin{align} \\label{adv:advection}\n", " q_t + a q_x = 0.\n", "\\end{align} \n", "This equation has a very simple solution. If we are given the density $q(x,0)=q_0(x)$ at time zero, then the solution is just \n", "\\begin{align} \\label{adv:solution}\n", " q(x,t) = q_0(x-at).\n", "\\end{align}" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "hide" ] }, "outputs": [], "source": [ "%matplotlib inline\n", "%config InlineBackend.figure_format = 'svg'\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import matplotlib as mpl\n", "mpl.rcParams['font.size'] = 12\n", "from ipywidgets import interact\n", "from ipywidgets import widgets\n", "\n", "from exact_solvers import advection\n", "from utils import riemann_tools" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Characteristics\n", "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. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(advection.characteristics);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can think of the initial values $q_0(x)$ being transmitted along these lines; we sometimes say that *information* is transmitted along characteristics. \n", "\n", "The next figure shows how an initial hump propagates to the right along characteristics." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(advection.solution);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Riemann problem\n", "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 \n", "\\begin{align*}\n", " q_0(x) & = \\begin{cases} q_l & x<0 \\\\ q_r & x>0. \\end{cases}\n", "\\end{align*} \n", "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 \n", "\\begin{align*}\n", " q(x,t) & = \\begin{cases} q_l & x-at<0 \\\\ q_r & x-at>0. \\end{cases}\n", "\\end{align*}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(advection.riemann_demo);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice how the initial discontinuity follows the characteristic coming from $x=0$ at $t=0$.\n", "\n", "Here's another way to look at the Riemann solution that will be very useful for more complicated equations." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "q_l = 1.\n", "q_r = 0.\n", "advection.plot_riemann_solution(q_l, q_r, a=1.);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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. Try modifying the initial states and the velocity $a$ to see how this simple solution changes." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" }, "toc": { "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "toc_cell": false, "toc_position": {}, "toc_section_display": "block", "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }