{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Burgers' equation" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "hide" ] }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "hide" ] }, "outputs": [], "source": [ "%config InlineBackend.figure_format = 'svg'\n", "from ipywidgets import interact\n", "from ipywidgets import widgets\n", "from ipywidgets import FloatSlider, fixed\n", "from exact_solvers import burgers\n", "from exact_solvers import burgers_demos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this chapter, we study a simple scalar nonlinear conservation law: Burgers' equation. Burgers' equation models momentum transport in a fluid of uniform density and pressure, and it is the simplest equation that captures some key features of gas dynamics or shallow water flow.\n", "\n", "To examine the Python code for this chapter, see:\n", "\n", " - [exact_solvers/burgers.py](exact_solvers/burgers.py) ...\n", " [on github](https://github.com/clawpack/riemann_book/blob/master/exact_solvers/burgers.py)\n", " - [exact_solvers/burgers_demos.py](exact_solvers/burgers_demos.py)...\n", " [on github](https://github.com/clawpack/riemann_book/blob/master/exact_solvers/burgers_demos.py)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Burgers' equation has been used extensively for developing both theory and numerical methods, and it will allow us to further explore the Riemann problem for nonlinear conservation laws. Burgers' equation is a scalar conservation law with flux $f(q)=q^2/2$:\n", "\\begin{align}\n", "q_t + \\left(\\frac{1}{2}q^2\\right)_x = 0.\n", "\\label{burgers0}\n", "\\end{align}\n", "The quasilinear form is obtained by applying the chain rule to the flux term: \n", "\\begin{align*}\n", "q_t + qq_x = 0.\n", "\\end{align*} \n", "This equation looks very similar to the advection equation, with the difference that the advection speed at each point is given by the solution $q$. Burgers' equation is often viewed as a simplified version of equations in fluid dynamics or water waves that also have nonlinear fluxes. Our study of the dynamics of equation (\\ref{burgers0}) is a step toward understanding these more complex nonlinear systems, in [Shallow_water](Shallow_water.ipynb) and [Euler](Euler.ipynb). In [Traffic_flow](Traffic_flow.ipynb) we consider another scalar nonlinear conservation law that has a similar structure to Burgers' equation and a nice physical interpretation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The *flux function* for Burgers' equation is $f(q) = \\frac 1 2 q^2$ and the *characteristic speed* is $f'(q) = q$. As long as the solution is smooth, we find that the solution is constant along characteristic curves $X(t)$ satisfying $X'(t) = f'(q(X(t),t)$ since then\n", "$$\n", "\\frac{d}{dt} q(X(t),t) = q_x(X(t),t)X'(t) + q_t(X(t),t) = 0.\n", "$$\n", "However, since the charactistic speed depends on the solution, characterstics may converge at which point a *shock* forms. Or they may spread out in a *rarefaction wave*. We illustrate both of these possibilities below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Shock formation\n", "\n", "In the figure below we consider Burgers' equation with a Gaussian hump as the initial data. Since the characteristic speed in Burgers' equation is given by $q$ itself, the peak of the hump travels faster than the rest, and characteristics are converging at the front of the traveling wave (where $f'(q)$ decreases with $x$) while they are spreading out behind the peak (where $f'(q)$ increases with $x$). The dashed line shows the initial condition while the solid lines show the solution at later times." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(burgers_demos.multivalued_solution, \n", " t=FloatSlider(min=0.,max=9.,value=7.75), fig=fixed(0));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that at first $q$ remains single-valued for every $x$. However, after some time the crest of the wave overtakes the leading edge. After this time, we obtain a triple-valued solution for certain values of $x$. The first time this overtaking happens is referred to as the *breaking time* -- a reference to waves breaking on the beach. It is also the point where the conservation law, in its differential form, breaks down and where the characteristics cross each other for the first time. When characteristics cross, a shock wave forms. Mathematically, imposing a shock will avoid the problem of the solution being multivalued. Where should the shock be located?\n", "\n", "If we replace part of the multivalued solution interval with a shock, some mass will be removed (area $A_1$ in the figure below) and some mass will be added (area $A_2$ in the figure below). In the live notebook, the figure below shows possible locations for the shock at a given time; in order to maintain conservation of the integral of $q$, the shock must be placed so that these two areas are equal." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(burgers_demos.shock_location, \n", " xshock = FloatSlider(min=6,max=10,step=0.25,value=7.75),\n", " fig=fixed(0));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This geometric reasoning provides a nice intuition for the shock location, but is cumbersome in practice. To determine the path of the shock we can use the *Rankine-Hugoniot jump condition,* which we will derive in [Traffic_flow](Traffic_flow.ipynb), and which requires that the jump in flux across a propagating shock must be related to the jump in $q$ by\n", "$$\n", "s(q_r-q_l) = f(q_r) - f(q_l),\n", "$$\n", "at each instant in time, where $s$ is the shock speed at this time. \n", "\n", "Since the flux for Burgers' equation is $f(q) = q^2/2$, this gives\n", "\\begin{align*}\n", "s(q_r-q_l) & = \\frac{1}{2} (q_r^2 - q_l^2) \\\\\n", "\\Rightarrow \\ \\ \\ \\ s &= \\frac{1}{2}(q_l + q_r).\n", "\\end{align*} \n", "In general (as in the image above) the states $q_l$ and $q_r$ just to the left and right of the shock will not be constant and the speed of a shock will change in time." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Shock solution\n", "For Burgers' equation, (or any scalar hyperbolic conservation law with a *convex* flux function, such as the traffic flow problem considered in [Traffic_flow](Traffic_flow.ipynb)), the solution of the Riemann problem consists of a single wave, which may be either a shock or a rarefaction, separating regions of constant value $q_l$ and $q_r$. Here convexity of the flux $f(q)$ means that $f'(q)$ is either monotonically increasing or monotonically decreasing as $q$ varies. If $f(q)$ is not convex then the solution can be more complicated; see the section on Convexity below and [Nonconvex_scalar](Nonconvex_scalar.ipynb).\n", "\n", "The analysis above already yields the solution to the Riemann problem in the case that the resulting wave is a shock. The entropy condition, as we will explain below, indicates that a shock will form when $f'(q_l) > f'(q_r)$; i.e. when $q_l>q_r$. In this case, the solution is \n", "\\begin{align*}\n", "q(x,t) = \n", "\\begin{cases}\n", "q_l \\quad \\text{if} \\ \\ x/ts.\n", "\\end{cases}\n", "\\end{align*} \n", "Below, we plot the solution of Burgers' equation for an initial condition that leads to a shock (i.e. with $q_l>q_r$)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(burgers_demos.shock(), \n", " t=widgets.FloatSlider(min=0,max=1.0,value=0.5),\n", " which_char=widgets.Checkbox(value=True,\n", " description='Show characteristics'));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Rarefaction wave\n", "In the previous figure with the hump as the initial condition, we observed that a shock formed on the right side of the hump. However, on the left side, the characteristics spread out and will never cross. This part of the solution is therefore a rarefaction wave. This is the kind of behavior we will observe in the solution of the Riemann problem when $q_lq_r t.\n", "\\end{cases}\n", "\\end{align*}\n", "\n", "As we will see in [Traffic_flow](Traffic_flow.ipynb), the rarefaction solution is always a self-similar solution. This means that it can be expressed as a function of the ratio between position and time $q(x,t) = \\tilde{q}(x/t)$, so it remains the same when rescaling both $x$ and $t$ by the same factor. In Burgers' equation, the form of the rarefaction is particularly simple since the advection speed is simply $q$ and so the rarefaction wave is linear in $x$ with slope $1/t$ at time $t$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Rarefaction solution\n", "In the figure below, we plot a solution of the Riemann problem with $q_l(LeVeque, 2002). This is mathematically correct and one obtains the same relation for the shock speed as before, $s = (q_l + q_r)/2$ , so the solution is simply\n", "\\begin{align*}\n", "q(x,t) = \n", "\\begin{cases}\n", "q_l \\quad \\text{if} \\ \\ x/ts.\n", "\\end{cases}\n", "\\end{align*}\n", "This unphysical solution is also referred to as an expansion shock, and it is also a weak solution to Burgers' equation. In the next figure, we plot this weak solution." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(burgers_demos.unphysical(), \n", " t=widgets.FloatSlider(min=0,max=1.0,value=0.5),\n", " which_char=widgets.Checkbox(value=True,\n", " description='Show characteristics'));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note the behavior of the characteristics with respect to the shock. The fact that the characteristics are spreading away from the shock rather than converging on it indicates that the correct solution should instead be a rarefaction. In order to be able to specify which of the weak solutions is physically correct, we need to derive a mathematical condition from our physical intuition gained from observing the behavior of the characteristics. This condition is referred to as the entropy condition." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The entropy condition\n", "\n", "A given initial value problem for a hyperbolic PDE may have many weak solutions.\n", "A condition that selects a unique physically correct solution out of these weak solutions is called an *admissibility condition* or more often an *entropy condition*. This name comes from gas dynamics, where the physical entropy must increase in the gas passing through a shock, according to the second law of thermodynamics. A discontinuity that violates this is non-physical. A mathematical \"entropy function\" can be defined for other conservation laws. More discussion of this and several other formulations with more detailed explanations are available in the literature, e.g., (LeVeque, 2002).\n", "\n", "In the context of the Riemann problem, the entropy condition allows us to determine if the physical solution should involve a shock or a rarefaction. In the case of scalar conservation laws, the entropy condition is quite simple and can be formulated in terms of the flux function of the conservation law as follows: the solution of a scalar Riemann problem will consist of a shock only if\n", "$$\n", "f'(q_l) > f'(q_r).\n", "$$\n", "In other words, the solution is a shock only if nearby characteristics from the left and right approach the shock as time progresses. If nearby characteristics are spreading away from the shock as in the last example, one would naturally expect a rarefaction to be the correct solution. In the case of Burgers' equation, the flux function is $f(q)=q^2/2$, so the correct solution is a shock only if\n", "$$\n", "q_l > q_r,\n", "$$\n", "which can be clearly observed in the interactive solution below. In later chapters, we will see how this condition generalizes to systems of conservation laws." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Convexity\n", "\n", "The flux $f(q) = q^2/2$ for Burgers' equation is a convex function, since $f''(q) = 1 > 0$ for all values of $q$. This means that as $q$ varies between $q_l$ and $q_r$ the the characteristic speed $f'(q) = q$ is either monotonically increasing (if $q_l < q_r$) or monotonically decreasing (if $q_l > q_r$). Hence for any Riemann problem the characteristic speeds for intermediate states are either purely converging or purely diverging, and the Riemann solution is always either a single rarefaction wave or a single shock wave.\n", "\n", "The flux $f(\\rho) = \\rho(1-\\rho)$ of the simple traffic flow model considered in [Traffic_flow](Traffic_flow.ipynb) also has the property that $f'(\\rho)$ varies monotonically with $\\rho$ (in the context of hyperbolic PDEs, a flux function is referred to as *convex* if either $f''(q)\\ge0$ for all $q$ or $f''(q)\\le 0$ for all $q$). Since $f''$ is always negative for the traffic flow model, the correct Riemann solution is a shock if $\\rho_l < \\rho_r$, or a rarefaction wave if $\\rho_l > \\rho_r$.\n", "\n", "The solution to the Riemann problem can be much more complicated if $f'(q)$ is not monotonically varying between $q_l$ and $q_r$, i.e. if $f''(q)$ changes sign. In this case the Riemann solution can consist of multiple shock and rarefaction waves. The nonconvex case is explored further in [Nonconvex_scalar](Nonconvex_scalar.ipynb)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interactive solution and examples\n", "The live notebook next shows a full interactive solution for the Riemann problem for Burgers' equation. The values of the initial conditions and the time can be modified to observe their effect on the characteristic structure and the solution. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "burgers.riemann_solution_interact()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Animations of more complex solutions\n", "We can now explore a few more examples that are representative of phenomena we will observe in more complicated systems, with more interesting initial data that the single jump discontinuity of a Riemann problem. For the animations shown below, the solution is computed numerically using [PyClaw](http://www.clawpack.org/pyclaw/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example 1: Bump initial condition\n", "The animation below, or on [this webpage](http://www.clawpack.org/riemann_book/html/burgers_animation0.html), shows the solution of Burgers' equation for an initial Gaussian hump." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "burgers_demos.bump_animation(numframes = 50)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example 3: Three-state solutions\n", "\n", "For an initial condition that is piecewise-constant with three values, one can solve Burgers' equation by solving a Riemann problem locally for each discontinuity and then considering how the resulting waves interact. For instance, consider the initial condition\n", "\\begin{align*}\n", "q_0(x) = \n", "\\begin{cases}\n", "q_l \\quad \\text{if} \\ \\ x < -1 \\\\\n", "q_m \\quad \\text{if} \\ \\ -1\\le x \\le 1 \\\\\n", "q_r \\quad \\text{if} \\ \\ x > 1.\n", "\\end{cases}\n", "\\end{align*} \n", "We can decompose this into two Riemann problems: one at $x=-1$ and another at $x=1$. Each of these two Riemann problems will yield either a shock or a rarefaction. The interesting part is what happens when the generated shocks or rarefactions interact. In the scenario shown below, let us assume that both Riemann problems produce a right-propagating shock. However, the shock generated at $x=-1$ propagates faster, so it will eventually reach the shock originally generated at $x=1$. At the point in time when the shocks collide, one can simply restate the problem again as a Riemann problem and solve the whole problem analytically. The first plot shows the solution $q(x)$ evolving through time, while the second one shows the characteristic structure in the $x-t$ plane, where the shocks are shown as wide lines and the characteristics as thin lines. In this figure, one can clearly see the two shocks collide to become a new one. In the second plot, the time is marked by a horizontal dashed line. This animation can be viewed in the live notebook on or [this webpage](http://www.clawpack.org/riemann_book/html/burgers_animation1.html)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "burgers_demos.triplestate_animation(ql = 4.0, qm = 2.0, \n", " qr = 0.0, numframes = 50)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As one would expect, this can become more complicated when one or both of the waves generated are given by rarefactions. The animation below, or on [this webpage](http://www.clawpack.org/riemann_book/html/burgers_animation2.html), shows how a right-propagating shock can overtake a rarefaction. The shock speed changes as it passes through the rarefaction, since the state just to the left of the shock is changing. This is seen clearly in the $x-t$ plane, where the slope of the shock is changed after interacting with the rarefaction. Note the shock is again marked as a wider line. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "burgers_demos.triplestate_animation(ql = 4.0, qm = -1.5, \n", " qr = 0.5, numframes = 50)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Analogously, one can also have a rarefaction overtaking a shock. As seen in the animation below, or [this webpage](http://www.clawpack.org/riemann_book/html/burgers_animation3.html), this can even change the direction in which the shock is propagating. This happens because the velocity of the shock depends on the slopes of the impinging characteristics. When a shock interacts with a rarefaction, the varying slopes of the characteristic curves produce a constant change of the shock propagation velocity. Try modifying the values of $q_l$, $q_m$ and $q_r$ in order to see what other behavior can be observed. Is it possible to observe two interacting rarefactions?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "burgers_demos.triplestate_animation(ql = -1, qm = 3.0, \n", " qr = -2, numframes = 50)" ] } ], "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": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": "block", "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }