diff --git a/.gitignore b/.gitignore index 80f7309c..17ac09a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,14 @@ .ipynb_checkpoints None*.png f2py_output.txt +_output/ +*.bbl +*.blg +*.out +*.toc +??-*.ipynb +combined_files/ +html/ # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/Advection.ipynb b/Advection.ipynb index 824e8b9e..e29dd979 100644 --- a/Advection.ipynb +++ b/Advection.ipynb @@ -1,11 +1,16 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Advection" + ] + }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", diff --git a/Euler_approximate_solvers.ipynb b/Euler_approximate_solvers.ipynb index aa87a538..9eb83a07 100644 --- a/Euler_approximate_solvers.ipynb +++ b/Euler_approximate_solvers.ipynb @@ -2,48 +2,52 @@ "cells": [ { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# Table of contents\n", - "\n", - "- [HLLE Solver](#HLLE-Solver)\n", - "- [Roe Solver](#Roe-Solver)\n", - "- [Comparison of solvers](#Comparison-of-two-approximate-solvers-with-the-exact-solution)" + "# Approximate solvers for the Euler equations of gas dynamics" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "In the [Part I](Euler_equations.ipynb) we studied the Riemann problem for Euler equations of inviscid, compressible fluid flow . As we saw, the exact solution of the Riemann problem is computationally expensive, since it requires solving a set of nonlinear algebraic equations. In the context of finite volume methods, the detailed structure of the Riemann solution is almost immediately discarded -- only its impact on the neighboring cell averages is used. So it makes sense to consider whether we can approximate the solution with less computation. In this chapter, we investigate approximate solvers for the Euler equations." + "*Note: this notebook is currently a placeholder for Part II of the book, in which the concepts behind approximate solvers will be introduced in a methodical way. The present notebook is here simply to show the facility with which different solvers may be compared and understood using the tools available in this book.*" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In [Part I](Euler_equations.ipynb) we studied the Riemann problem for Euler equations of inviscid, compressible fluid flow . As we saw, the exact solution of the Riemann problem is computationally expensive, since it requires solving a set of nonlinear algebraic equations. In the context of finite volume methods, the detailed structure of the Riemann solution is almost immediately discarded -- only its impact on the neighboring cell averages is used. So it makes sense to consider whether we can approximate the solution with less computation. In this chapter, we investigate approximate solvers for the Euler equations." ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false, - "deletable": true, - "editable": true + "collapsed": true, + "tags": [ + "hide" + ] }, "outputs": [], "source": [ "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'svg'\n", + "import matplotlib as mpl\n", + "mpl.rcParams['font.size'] = 8\n", + "figsize =(8,4)\n", + "mpl.rcParams['figure.figsize'] = figsize\n", + "\n", "import numpy as np\n", "from exact_solvers import Euler\n", "from clawpack import riemann\n", "from utils import riemann_tools\n", "import matplotlib.pyplot as plt\n", "from collections import namedtuple\n", - "from ipywidgets import interact, widgets\n", + "from ipywidgets import interact\n", + "from ipywidgets import widgets\n", "import matplotlib\n", - "matplotlib.rcParams.update({'font.size': 12})\n", "Primitive_State = namedtuple('State', Euler.primitive_variables)\n", "gamma = 1.4\n", "problem_data = {}\n", @@ -53,10 +57,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## HLLE Solver\n", "\n", @@ -66,11 +67,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "solver = riemann.euler_1D_py.euler_hll_1D\n", @@ -86,7 +83,7 @@ "print(\"HLL solver solution to Euler equations:\")\n", "states_hll, s_hll, hll_eval = riemann_tools.riemann_solution(solver,left_state,right_state,\n", " problem_data=problem_data,verbose=True)\n", - "fig, ax = plt.subplots(1,3,figsize=(16,4))\n", + "fig, ax = plt.subplots(1,3,figsize=figsize)\n", "riemann_tools.plot_phase(states_hll,0,1,ax[0])\n", "riemann_tools.plot_phase(states_hll,0,2,ax[1])\n", "riemann_tools.plot_phase(states_hll,1,2,ax[2])\n", @@ -96,11 +93,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "plot_function = riemann_tools.make_plot_function(states_hll,s_hll, hll_eval,\n", @@ -110,10 +103,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Roe solver\n", "The Roe solver is an example of a linearized Riemann solver. It approximates the Riemann problem by considering an approximation of the flux Jacobian: $\\hat{A} \\approx f'(q)$ and exactly solving the Riemann problem for the linear hyperbolic system\n", @@ -126,11 +116,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "solver = riemann.euler_1D_py.euler_roe_1D\n", @@ -141,7 +127,7 @@ "print(\"Roe solver solution to Euler equations:\")\n", "states, s, roe_eval = riemann_tools.riemann_solution(solver,left_state,right_state,\n", " problem_data=problem_data,verbose=True)\n", - "fig, ax = plt.subplots(1,2,figsize=(10,4))\n", + "fig, ax = plt.subplots(1,2,figsize=figsize)\n", "riemann_tools.plot_phase(states,0,1,ax[0])\n", "riemann_tools.plot_phase(states,0,2,ax[1])\n", "riemann_tools.plot_phase_3d(states)" @@ -150,11 +136,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "plot_function = riemann_tools.make_plot_function(states,s,roe_eval,variable_names=Euler.conserved_variables)\n", @@ -163,10 +145,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Comparison of two approximate solvers with the exact solution\n" ] @@ -174,11 +153,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "ex_states, ex_speeds, reval, ex_wave_types = Euler.exact_riemann_solution(left_state ,right_state, gamma)\n", @@ -194,10 +169,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "Notice that the Roe solver significantly understimates the shock speed, and even propagates the contact discontinuity in the wrong direction. Nevertheless, when used as an ingredient in a numerical method, it gives good results." ] @@ -223,5 +195,5 @@ } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/Euler_equations_TammannEOS.ipynb b/Euler_equations_TammannEOS.ipynb index d7e6c235..bd74478c 100644 --- a/Euler_equations_TammannEOS.ipynb +++ b/Euler_equations_TammannEOS.ipynb @@ -2,10 +2,7 @@ "cells": [ { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "# Riemann problem for Euler equations with the Tammann EOS\n", "\n", @@ -42,10 +39,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Exact solution\n", "\n", @@ -55,24 +49,20 @@ "middle state pressure $p_*$ that ensures that the velocity $u_*$ across the contact discontinuity is consistent. Since we know that the left state velocity $u_l$ should be connected by a rarefaction or shock to $u_*$, we write $u_*=u_l + [u]_1$, where $[u]_1$ is the jump of the velocity across the 1-wave. In a similar manner, we also \n", "know the 3-wave should be a shock or rarefaction, so we write $u_*= u_r - [u]_3$. Therefore, it is useful to define\n", "\n", - "\n", "\\begin{align}\n", " \\phi_l(p_*) = u_* = u_l - \\mathcal{F}_l(p_*), \\label{CDvel-1} \\\\\n", " \\phi_r(p_*) = u_* = u_r + \\mathcal{F}_r(p_*). \\label{CDvel-2} \n", "\\end{align}\n", "\n", - "\n", "where the value of $\\mathcal{F}_{l,r}(p_*) = -[u]_{1,3}$ depends on whether the wave in question is a shock or a rarefaction (signs were \n", "chosen for notation consistency). As we expect these two equations yield the same contact discontinuity \n", "velocity $u_*$, we have \n", "\n", - "\n", "\\begin{align}\n", " \\Phi(p_*)= \\phi_r(p_*) - \\phi_l(p_*) = 0.\n", " \\label{Phi} \n", "\\end{align}\n", "\n", - "\n", "This nonlinear equation will yield the pressure $p_*$ that provides consistency between the type of waves (rarefactions or shocks), their speeds and the contact discontinuity velocity $u_*$. As we mentioned before, the shape of $\\phi_k(p_*)$ will depend on whether the states are connected by a shock wave or rarefaction. Once \n", "the $p_*$ has been found, the contact discontinuity velocity can be found from the expressions just derived. However, it is not yet clear how to calculate the density or the speeds of the 1-wave \n", "and 3-wave. It will become obvious how to obtain these quantities once we write the explicit equations for our system further below.\n", @@ -97,10 +87,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Rankine-Hugoniot conditions for shock waves\n", "As we know the 1-wave and the 3-wave could each be a shock. In that case, the velocity of the wave, i.e. the \n", @@ -227,12 +214,8 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "\n", "### Riemann invariants for rarefaction waves\n", "\n", "Riemann invariants are variables that remain constant through simple waves such as rarefactions. The Riemann invariants across \n", @@ -299,10 +282,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Solution in the pressure-velocity plane\n", "\n", @@ -313,13 +293,15 @@ "cell_type": "code", "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "tags": [ + "hide" + ] }, "outputs": [], "source": [ "%matplotlib inline\n", - "from ipywidgets import interact, widgets\n", + "from ipywidgets import interact\n", + "from ipywidgets import widgets\n", "import matplotlib.pyplot as plt\n", "from exact_solvers import euler_tammann, interactive_pplanes\n", "from utils import riemann_tools" @@ -328,10 +310,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "# Initial states [density, velocity, pressure]\n", @@ -346,10 +325,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Full solution\n", "In order to get the full solution, we still need a couple more quantities. Equations (\\ref{RH-phis}) will yield the contact discontinuity speed $s_2=u_*$ in terms of $p_*$. We can also calculate $F_l$ and $F_r$ from (\\ref{Qk-f}), and we can substitute in (\\ref{RH-speeds}) to obtain the corresponding wave speeds. With this, we can provide the full solution of the Riemann problem. In the next section, we will show the full solution for different examples. It should be noted that this model is to be handled carefully because it could yield unphysical results (negative pressures) for some initial conditions. The cases where this happens are in the limit of validity for modeling almost incompressible media with the Tammann EOS. We will explore these limits in Problem 4. Here we define a function to plot the exact solution of the Riemann problem and parameters that we will use for the different examples." @@ -359,8 +335,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true }, "outputs": [], "source": [ @@ -383,10 +358,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Examples of Riemann Solutions\n", "\n", @@ -398,8 +370,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true }, "outputs": [], "source": [ @@ -414,8 +385,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true }, "outputs": [], "source": [ @@ -429,20 +399,14 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "The density difference between the states is very small because water is almost incompressible. Note the small waves generated in the density plot and the very compressed rarefaction fan, which are consequence of the low compressibility in water." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Problem 2: Air-water interface in shock tube\n", "We can use the Euler equations with the Tammann EOS to model wave propagation in almost-incompressible media, such as water. As we provided the solution with different EOS parameters on the left and right states, it can couple different materials across the interface. For instance, we can use this model to study the propagation of waves from air into water. Air is modeled by the ideal gas EOS, which corresponds to $\\gamma=1.4$ and $p_{\\infty} = 0$, and water can be modeled using the same parameters as the example before. Consider a shock traveling from left to right; the left state has only air while the right state has only water. Although in a realistic two or three dimensional setting, the water would spill into the left state, we can consider the water is being held in place by a container with a thin wall. In this setting, the current model has been shown to be a valid approximation (del Razo 2016). The solution has the following form:" @@ -452,8 +416,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true }, "outputs": [], "source": [ @@ -467,10 +430,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Problem 3: Water-air interface in shock tube\n", "The same setup as in Problem 2, but now the shock moves from water (on the left) into air (on the right)." @@ -480,8 +440,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true }, "outputs": [], "source": [ @@ -495,10 +454,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Negative pressure and vacuum states\n", "\n", @@ -512,8 +468,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true }, "outputs": [], "source": [ @@ -528,32 +483,78 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "It may be possible to extend the solution to cases where the Riemann solver yields $p+p_{\\infty} \\le 0$. As in the Euler equations chapter, the vacuum states arise in regions with zero density. As vacuum states can only connected through rarefaction waves, the middle state densities can only be given by \\ref{isentrop}. The middle state density will only yield zero when $\\tilde{p_*} = p_*+p_{\\infty}=0$ or $p_*=-p_{\\infty}$. The convergence failure of the Riemann solution for this scenario can be observed if the velocity in the example above is increased one order of magnitude. How to deal with vacuum states when using a Tammann EOS with a jump in the parameters is beyond the scope of this book." ] }, { "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Full solution\n", + "In order to get the full solution, we still need a couple more quantities. Equations (\\ref{RH-phis}) will yield the contact discontinuity speed $s_2=u_*$ in terms of $p_*$. We can also calculate $F_l$ and $F_r$ from (\\ref{Qk-f}), and we can substitute in (\\ref{RH-speeds}) to obtain the corresponding wave speeds. With this, we now provide the full solution of the Riemann problem. " + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true }, + "outputs": [], "source": [ - "### *Test: Interactive pplane for ideal gas Euler eqs. " + "# %load exact_solvers/euler_tammann.py" ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true }, "outputs": [], + "source": [ + "ql = [1.0, -3.0, 1.0]\n", + "qr = [1.0, 3.0, 1.0]\n", + "gamma = [1.4, 1.4]\n", + "pinf = [0.0, 0.0]\n", + "ex_states, ex_speeds, reval, wave_types, varsout = euler_tammann.exact_riemann_solution(ql ,qr, gamma, pinf, \n", + " varin = 'primitive', varout = 'conservative')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plot_function = riemann_tools.make_plot_function(ex_states, ex_speeds, reval, wave_types,\n", + " layout='vertical', variable_names=varsout)\n", + "interact(plot_function, t=widgets.FloatSlider(value=0.0,min=0,max=1.0));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### to be modified\n", + "Now we need to iterate this function using a Newton method, to find which value of $p_*$ yields $\\Phi(p_*)=0$\n", + "We just obtained the pressure and velocity middle states $p_*$ and $u_*$ that are continuous across the contact disconitnuity and the middle states for the density $\\rho_{*l}$ and $\\rho_{*r}$ have also been obtained from the function and saved as global variables. We also know the speed the left and right waves are traveling. We can now plot the solution to the Riemann problem. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### *Test: Interactive pplane for ideal gas Euler eqs. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# Initial states [density, velocity, pressure]\n", "ql = [1.0, -10.0, 100.0]\n", @@ -563,16 +564,6 @@ "\n", "interactive_pplanes.euler_interactive_phase_plane(ql,qr,gamma)\n" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "deletable": true, - "editable": true - }, - "outputs": [], - "source": [] } ], "metadata": { @@ -591,7 +582,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.12" + "version": "2.7.13" } }, "nbformat": 4, diff --git a/Kitchen_sink_problem.ipynb b/Kitchen_sink_problem.ipynb index e140c065..f04c1d27 100644 --- a/Kitchen_sink_problem.ipynb +++ b/Kitchen_sink_problem.ipynb @@ -1,12 +1,19 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The \"kitchen sink\" problem" + ] + }, { "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false, - "deletable": true, - "editable": true + "tags": [ + "hide" + ] }, "outputs": [], "source": [ @@ -25,12 +32,8 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# The \"kitchen sink\" problem\n", "Our next example is something you can experiment with in your own home. Go to the kitchen sink, position the faucet over a flat part of the sink (not over the drain), and turn it on. Carefully examine the flow of water in the sink. You will see that near the jet of water coming from the faucet, there is a region of very shallow, very fast-flowing water. Then at a certain distance, the water suddenly becomes deeper and slower moving. This jump is relatively stable and will approximately form a circle if the bottom of the sink is flat around the area under the faucet.\n", "\n", "Here's a demonstration in case you don't have a sink handy:" @@ -39,11 +42,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "HTML('')\n" @@ -51,20 +50,14 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "As you might guess, this jump is a shock wave and the entire flow can be modeled as a sort of multidimensional Riemann problem. Instead of left and right states, we have *inner* and *outer* states. To investigate this phenomenon we'll again use the shallow water equations. We'll assume the flow has cylindrical symmetry -- in other words, it depends on the distance away from the center (where water falls from the faucet), but not on the angular coordinate." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Shallow water flow in cylindrical symmetry\n", "The amount of water contained in an annular region $r_1< r 1$)\n", "In the presence of gravity, $h$ is still a decreasing function of $r$ if $F>1$. Furthermore, if the flow is supercritical at one point, then it will be supercritical everywhere in the steady profile; since the RHS of (\\ref{hdiff}) has a pole at the transition point, there is no smooth way for the flow to transition to a subsonic state. We see that the depth $h$ falls off somewhat faster than $1/r$. Since $rhu$ is constant, this means that the velocity $u=1/(hr)$ must increase with $r$. Hence the flow becomes shallower and faster as it moves outward; the Froude number increases. Asymptotically, the falloff in depth approaches the $1/r$ rate and the velocity approaches a constant value." @@ -148,11 +131,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "h0 = 1.; u0 = 2.; alpha = r[0]*h0*u0; g=1.\n", @@ -170,10 +149,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Subcritical flow ($F<1$)\n", "\n", @@ -183,11 +159,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "h0 = 1.; u0 = 0.5; alpha = r[0]*h0*u0; g=1.\n", @@ -205,10 +177,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "A different and complementary approach to deriving steady profiles (see [Zobeyer 2013]()) is to recognize that in such a solution, the energy $gh^2 + \\frac{hu^2}{2}$ is constant. More simply\n", "\n", @@ -228,10 +197,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## The hydraulic jump\n", "To transition from supersonic to subsonic, the flow must *jump* over the pole of the ODE above, through the presence of a hydraulic jump. This is a standing shock wave; since we have an outward-oriented flow, this jump must be a 1-shock (in order to be stationary).\n", @@ -259,10 +225,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### A stationary 1-shock\n", "We know from the analysis above that the hydraulic jump we are looking for is a stationary 1-shock. In this case $s=0$ and the first jump condition is simply\n", @@ -290,10 +253,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## A steady solution with a hydraulic jump\n", "The code below computes a steady profile with a hydraulic jump." @@ -302,11 +262,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "def initial_and_boundary_data(r_jump = 1.,r_inner = 0.5,r_outer = 5.,num_cells = 501,g=1.,h_in=1.,u_in=2.):\n", @@ -358,11 +314,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "def step_radial_src(solver,state,dt):\n", @@ -437,11 +389,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "claw = setup()\n", @@ -453,10 +401,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Dirichlet BCs with transition from super- to subsonic flow generically create a hydraulic jump\n", "\n", @@ -466,11 +411,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "def setup_constant_initial_data(r_jump=1.,r_inner=0.5,r_outer=3.,num_cells=501,g=1.):\n", @@ -506,11 +447,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "claw = setup_constant_initial_data()\n", @@ -522,23 +459,17 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# Comparison with an experimental result\n", + "## Comparison with an experimental result\n", "We may ask how well our model corresponds to reality. There are many approximations made in deriving the shallow water equations used here; perhaps most notably, we have completely neglected viscosity and surface tension. Viscosity in particular is believed to be very important in the very shallow flow just inside the jump radius." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## Inflow conditions\n", + "### Inflow conditions\n", "Experimentally it is difficult to measure the depth near the jet. We can eliminate that dependence (and the apparent dependence on our choice of inner radius) by considering the radius of the vertical jet, which we denote by $a$, and the flow rate, denoted by $Q$. Then\n", "\n", "$$\n", @@ -554,11 +485,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "def compute_inner_values(Q,a,r0):\n", @@ -575,12 +502,9 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# Locating the jump\n", + "### Locating the jump\n", "In the examples above, we selected the boundary data based on a prescribed jump location. But in practice we can't choose where the jump is -- we'd like to predict that!\n", "\n", "We can predict the location of the jump based on prescribed inflow conditions ($r_0, h_0, u_0$ and a prescribed far-field depth $h_\\infty$) as follows:\n", @@ -594,11 +518,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "def jump_location(Q,r_jet,h_inf,r_inf=100.,g=1.,r0=None,tol=1./10000):\n", @@ -638,11 +558,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "r_jump, r, profile = jump_location(Q=200.,r_jet=1.,h_inf=1.,g=980.,tol=1.e-6)\n", @@ -654,23 +570,16 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## Watson's experiment\n", + "### Watson's experiment\n", "Here we use data from an experiment conducted in (Watson, 1964); see p. 496 therein. The unit of length therein is feet; here we have converted everything to centimeters. The experimental jump location is at a radius of about 17 cm. Let's see what our model gives." ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "Q = 202. # Flow rate (in cm^3/s)\n", @@ -686,33 +595,23 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "Clearly, some of the effects we have ignored must be important! In particular, as Watson (and others) argue, viscosity becomes very significant in the shallow flow before the jump, causing the jump to emerge much closer to the jet than this inviscid model predicts." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## Experiments of Craik et. al.\n", + "### Experiments of Craik et. al.\n", "See Table 1 of (Craik et. al., 1981)." ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "Q = 4.48\n", @@ -728,11 +627,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "Q = 26.\n", @@ -747,32 +642,22 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# Old material" + "## Old material" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## Extrapolation BC creates a positive feedback loop" + "### Extrapolation BC creates a positive feedback loop" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "claw = setup()\n", @@ -785,20 +670,15 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## With fixed BCs, jump is dynamically stable" + "### With fixed BCs, jump is dynamically stable" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "def setup(r_jump=1.,r_inner=0.5,r_outer=3.,num_cells=501,g=1.):\n", @@ -835,11 +715,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "claw = setup(r_jump=0.7)\n", @@ -852,11 +728,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "claw = setup(r_jump=2.4)\n", diff --git a/Nonlinear_elasticity.ipynb b/Nonlinear_elasticity.ipynb index f4015902..4941c1f4 100644 --- a/Nonlinear_elasticity.ipynb +++ b/Nonlinear_elasticity.ipynb @@ -2,28 +2,60 @@ "cells": [ { "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Nonlinear elasticity" + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true, + "tags": [ + "hide" + ] }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'svg'\n", + "import matplotlib as mpl\n", + "mpl.rcParams['font.size'] = 8\n", + "figsize =(8,4)\n", + "mpl.rcParams['figure.figsize'] = figsize\n", + "\n", + "import numpy as np\n", + "from scipy.optimize import fsolve\n", + "import matplotlib.pyplot as plt\n", + "from utils import riemann_tools\n", + "from ipywidgets import interact\n", + "from ipywidgets import widgets\n", + "from clawpack import riemann\n", + "from exact_solvers import nonlinear_elasticity" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "# Nonlinear elasticity\n", "In this chapter we investigate a nonlinear model of elastic strain in heterogeneous materials. This system is equivalent to the $p$-system of gas dynamics, although the stress-strain relation we will use here is very different from the pressure-density relation typically used in gas dynamics. The equations we consider have been investigated numerically in [(LeVeque, 2002),(LeVeque & Yong, 2003),(Ketcheson & LeVeque, 2012)].\n", "\n", "The equations are\n", "\\begin{align}\n", "\\epsilon_t(x,t) - u_x(x,t) & = 0 \\\\\n", "(\\rho(x)u(x,t))_t - \\sigma(\\epsilon(x,t),x)_x & = 0.\n", - "\\end{align}\n", + "\\end{align} \n", + "Here $\\epsilon$ is the strain, $u$ is the velocity, $\\rho$ is the material density, $\\sigma$ is the stress,\n", + "and ${\\mathcal M}=\\rho u$ is the momentum. \n", + "The first equation is a kinematic relation, while the second represents Newton's second law. This is a nonlinear \n", + "conservation law with spatially varying flux function, in which\n", "\n", - "The first equation is a kinematic relation, while the second represents Newton's second law. This is a nonlinear conservation law with spatially varying flux function, in which\n", "\\begin{align}\n", "q & = \\begin{bmatrix} \\epsilon \\\\ \\rho u \\end{bmatrix}, & f(q,x) & = \\begin{bmatrix} -{\\mathcal M}/\\rho(x) \\\\ -\\sigma(\\epsilon,x) \\end{bmatrix}\n", - "\\end{align}\n", - "\n", - "Here $\\epsilon$ is the strain, $u$ is the velocity, $\\rho$ is the material density, $\\sigma$ is the stress,\n", - "and ${\\mathcal M}=\\rho u$ is the momentum. If we take a linear stress strain relationship $\\sigma(\\epsilon,x)=K(x)\\epsilon$, then this system is equivalent to the acoustics equations that we have\n", - "studied previously. Here we consider instead a quadratic stress:\n", + "\\end{align} \n", + "If we take a linear stress strain relationship $\\sigma(\\epsilon,x)=K(x)\\epsilon$, then this system is equivalent to the acoustics equations that we have\n", + "studied previously. Here we consider instead a quadratic stress response:\n", "\n", "\\begin{align}\n", "\\sigma(\\epsilon,x) = K_1(x) \\epsilon + K_2(x) \\epsilon^2.\n", @@ -35,49 +67,39 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Hyperbolic structure\n", "The flux jacobian is\n", "\\begin{align}\n", "f'(q) = \\begin{bmatrix} 0 & -1/\\rho(x) \\\\ -\\sigma_\\epsilon(\\epsilon,x) & 0 \\end{bmatrix},\n", - "\\end{align}\n", - "with eigenvalues (characteristic sound speeds)\n", + "\\end{align} \n", + "with eigenvalues (characteristic speeds)\n", "\\begin{align}\n", "\\lambda^\\pm(x) = \\pm \\sqrt{\\frac{\\sigma_\\epsilon(\\epsilon,x)}{\\rho(x)}} = \\pm c(\\epsilon, x).\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "Here for the stress-strain relation we have chosen, $\\sigma_\\epsilon = K_1(x) + 2 K_2(x)\\epsilon$.\n", "\n", "It's also convenient to define the nonlinear impedance $Z(\\epsilon, x) = \\rho(x) c(\\epsilon,x)$. Then the eigenvectors of the flux Jacobian are\n", "\\begin{align}\n", - "R & = \\begin{bmatrix} 1 & 1 \\\\ Z & -Z \\end{bmatrix}.\n", + "R & = \\begin{bmatrix} 1 & 1 \\\\ Z(\\epsilon,x) & -Z(\\epsilon,x) \\end{bmatrix}.\n", "\\end{align}\n", "Both characteristic fields are genuinely nonlinear. Furthermore, since the characteristic speeds each have a definite sign, this system does not admit transonic rarefactions." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Structure of the Riemann solution\n", - "Based on the eigenstructure of the flux jacobian above, the Riemann solution will always include a left-going and a right-going wave, each of which may be a shock or rarefaction. Furthermore, we will see that the jump in $\\rho$ and $K$ at $x=0$ induces a stationary wave there. Thus the overall structure of the Riemann solution is:\n", + "Based on the eigenstructure of the flux jacobian above, the Riemann solution will always include a left-going and a right-going wave, each of which may be a shock or rarefaction. We will see -- similarly to our analysis in [the chapter on variable-speed-limit traffic](Traffic_variable_speed.ipynb) that the jump in $\\rho$ and $K$ at $x=0$ induces a stationary wave there. Thus the overall structure of the Riemann solution is:\n", "\n", - "![](./figures/nonlinear_elasticity_riemann.png)" + "![Structure of the Riemann solution for variable-coefficient nonlinear elasticity](./figures/nonlinear_elasticity_riemann.png)" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Hugoniot loci\n", "From the Rankine-Hugoniot jump conditions for the system we obtain the 1-Hugoniot locus for a state $(\\epsilon^*_l, u^*_l)$ connected by a 1-shock to a state $(\\epsilon_l, u_l)$:\n", @@ -93,26 +115,20 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Integral curves\n", "The integral curves can be found by writing $\\tilde{q}'(\\xi) = r^{1,2}(\\tilde{q}(\\xi))$ and integrating. This leads to\n", "\\begin{align}\n", - "u^*_l & = u_l + \\frac{1}{3 K_{2l} \\sqrt{\\rho_l}} \\left( \\sigma_{l,\\epsilon}(\\epsilon^*_l)^{3/2} - \\sigma_{l,\\epsilon}(\\epsilon)^{3/2} \\right) \\\\\n", - "u^*_r & = u_r - \\frac{1}{3 K_{2r} \\sqrt{\\rho_r}} \\left( \\sigma_{r,\\epsilon}(\\epsilon^*_r)^{3/2} - \\sigma_{r,\\epsilon}(\\epsilon)^{3/2} \\right)\n", + "u^*_l & = u_l + \\frac{1}{3 K_{2l} \\sqrt{\\rho_l}} \\left( \\sigma_{l,\\epsilon}(\\epsilon^*_l)^{3/2} - \\sigma_{l,\\epsilon}(\\epsilon)^{3/2} \\right) \\label{NE:integral-curve-1} \\\\\n", + "u^*_r & = u_r - \\frac{1}{3 K_{2r} \\sqrt{\\rho_r}} \\left( \\sigma_{r,\\epsilon}(\\epsilon^*_r)^{3/2} - \\sigma_{r,\\epsilon}(\\epsilon)^{3/2} \\right)\\label{NE:integral-curve-2}\n", "\\end{align}\n", "Here $\\sigma_{l,\\epsilon}$ is the derivative of the stress function w.r.t $\\epsilon$ in the left medium." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### The entropy condition\n", "For a 1-shock, we need that $\\lambda^-(\\epsilon_l,x<0) > \\lambda^-(\\epsilon^*_l,x<0$, which is equivalent to $\\epsilon^*_l>\\epsilon_l$. Similarly, a 2-shock is entropy-satisfying if $\\epsilon^*_r > \\epsilon_r$." @@ -120,10 +136,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Interface conditions\n", "Because the flux depends explicitly on $x$, we do not necessarily have continuity of $q$ at $x=0$; i.e. in general $q^*_l \\ne q^*_r$. Instead, the flux must be continuous: $f(q^*_l)=f(q^*_r)$. For the present system, this means that the stress and velocity must be continuous, which makes sense from a physical point of view. If the velocity were not continuous, the material would fracture (or overlap itself). Continuity of the stress is required by Newton's laws." @@ -131,46 +144,29 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Structure of rarefaction waves\n", "For this system, the structure of a centered rarefaction wave can be determined very simply. Since the characteristic velocity must be equal to $\\xi = x/t$ at each point along the wave, we have $\\xi = \\pm\\sqrt{\\sigma_\\epsilon/\\rho}$, or\n", "\\begin{align}\n", "\\xi^2 = \\frac{K_1 + 2K_2\\epsilon}{\\rho}\n", "\\end{align}\n", - "which leads to $\\epsilon = (\\rho\\xi^2 - K_1)/(2K_2)$. Once the value of $\\epsilon$ is known, $u$ can be determined using the integral curves above." + "which leads to $\\epsilon = (\\rho\\xi^2 - K_1)/(2K_2)$. Once the value of $\\epsilon$ is known, $u$ can be determined using the integral curves \\eqref{NE:integral-curve-1} or \\eqref{NE:integral-curve-2}." ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [], + "cell_type": "markdown", + "metadata": {}, "source": [ - "%matplotlib inline\n", - "import numpy as np\n", - "from scipy.optimize import fsolve\n", - "import matplotlib.pyplot as plt\n", - "from utils import riemann_tools\n", - "from ipywidgets import interact, widgets\n", - "from clawpack import riemann\n", - "from exact_solvers import nonlinear_elasticity" + "### Solution of the Riemann problem\n", + "Below we show the solution of the Riemann problem. *To view the code that computes this exact solution, uncomment and execute the next cell.*" ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false, - "deletable": true, - "editable": true + "collapsed": true }, "outputs": [], "source": [ @@ -181,7 +177,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -201,31 +197,37 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ - "def riemann_solution(q_l, q_r, aux_l, aux_r):\n", - " ex_states, ex_speeds, ex_reval, wave_types = nonlinear_elasticity.exact_riemann_solution(q_l,q_r,aux_l,aux_r)\n", - " plot_function = riemann_tools.make_plot_function(ex_states, ex_speeds, ex_reval, wave_types,\n", - " layout='vertical',\n", - " variable_names=('Strain','Momentum'),\n", - " plot_chars=[lambda1,lambda2],aux=(aux_l,aux_r))\n", - " interact(plot_function, t=widgets.FloatSlider(value=0.1,min=0,max=.9),\n", - " which_char=widgets.Dropdown(options=[None,1,2],description='Show characteristics'));" + "def make_plot_function(q_l, q_r, aux_l, aux_r):\n", + " states, speeds, reval, wave_types = \\\n", + " nonlinear_elasticity.exact_riemann_solution(q_l,q_r,aux_l,aux_r)\n", + " \n", + " def plot_function(t,which_char):\n", + " ax = riemann_tools.plot_riemann(states,speeds,reval,wave_types,\n", + " t=t,t_pointer=0,\n", + " extra_axes=True,\n", + " variable_names=['Strain','Momentum'])\n", + " if which_char == 1:\n", + " riemann_tools.plot_characteristics(reval,lambda1,(aux_l,aux_r),ax[0])\n", + " elif which_char == 2:\n", + " riemann_tools.plot_characteristics(reval,lambda2,(aux_l,aux_r),ax[0])\n", + " nonlinear_elasticity.phase_plane_plot(q_l, q_r, aux_l, aux_r, ax[3])\n", + " plt.show()\n", + " return plot_function \n", + " \n", + "def plot_riemann_nonlinear_elasticity(rho_l,rho_r,v_l,v_r):\n", + " plot_function = make_plot_function(rho_l,rho_r,v_l,v_r)\n", + " interact(plot_function, t=widgets.FloatSlider(value=0.,min=0,max=1.,step=0.1),\n", + " which_char=widgets.Dropdown(options=[None,1,2],\n", + " description='Show characteristics'));" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "aux_l = np.array((1., 5., 1.))\n", @@ -233,31 +235,15 @@ "q_l = np.array([2.1, 0.])\n", "q_r = np.array([0.0, 0.])\n", "\n", - "riemann_solution(q_l, q_r, aux_l, aux_r)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [], - "source": [ - "nonlinear_elasticity.phase_plane_plot(q_l, q_r, aux_l, aux_r)" + "plot_riemann_nonlinear_elasticity(q_l, q_r, aux_l, aux_r)" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# Approximate solution of the Riemann problem using $f$-waves\n", - "The exact solver above requires a nonlinear iterative solver and is relatively expensive. A very cheap approximate Riemann solver for this system was developed in (LeVeque, 2002) using the $f$-wave approach. One simply assumes that both nonlinear waves are shocks, with speeds equal to the characteristic speeds of the left and right states:\n", + "## Approximate solution of the Riemann problem using $f$-waves\n", + "The exact solver above requires a nonlinear iterative rootfinder and is relatively expensive. A very cheap approximate Riemann solver for this system was developed in (LeVeque, 2002) using the $f$-wave approach. One simply approximates both nonlinear waves as shocks, with speeds equal to the characteristic speeds of the left and right states:\n", "\\begin{align}\n", "s^1 & = - \\sqrt{\\frac{\\sigma_{\\epsilon,l}(\\epsilon_l)}{\\rho_l}} \\\\\n", "s^2 & = + \\sqrt{\\frac{\\sigma_{\\epsilon,r}(\\epsilon_r)}{\\rho_r}}.\n", @@ -268,11 +254,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "solver = riemann.nonlinear_elasticity_1D_py.nonlinear_elasticity_1D\n", @@ -286,36 +268,25 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "plot_function = riemann_tools.make_plot_function(fwave_states,fwave_speeds, fwave_reval,\n", " layout='vertical', variable_names=('Strain','Momentum'))\n", - "interact(plot_function, t=widgets.FloatSlider(value=0.1,min=0,max=.9,step=.1));" + "interact(plot_function, t=widgets.FloatSlider(value=0.4,min=0,max=.9,step=.1));" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# Comparison of exact and approximate solutions" + "## Comparison of exact and approximate solutions" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "ex_states, ex_speeds, ex_reval, wave_types = nonlinear_elasticity.exact_riemann_solution(q_l,q_r,aux_l,aux_r)\n", @@ -326,7 +297,14 @@ " [wave_types,['contact']*3],\n", " ['Exact','$f$-wave'],\n", " layout='vertical',variable_names=nonlinear_elasticity.conserved_variables)\n", - "interact(plot_function, t=widgets.FloatSlider(value=0.1,min=0, max=0.9, step=0.1));" + "interact(plot_function, t=widgets.FloatSlider(value=0.4,min=0, max=0.9, step=0.1));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see, there are significant discretpancies between the approximate solution and the exact one. But in a full numerical discretization, the left- and right-going waves are averaged over neighboring cells at the next step, and the approximate solver yields an effective result quite close to that of the exact solver." ] } ], diff --git a/Preface.ipynb b/Preface.ipynb new file mode 100644 index 00000000..283490a5 --- /dev/null +++ b/Preface.ipynb @@ -0,0 +1,91 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Preface" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Aims and scope\n", + "\n", + "This book addresses an important class of mathematical problems (the \"Riemann problem\") for nonlinear wave equations. This problem arises in applications such as fluid dynamics, traffic flow, water waves, and electromagnetic waves. The solution of the Riemann problem captures essential information about the model. It is also the key ingredient in modern numerical methods for such models.\n", + "\n", + "The book aims to cover the fundamental ideas related to classical Riemann solutions, including their special structure and the types of waves that arise. It will also cover the ideas behind fast approximate solvers for the Riemann problem, and more advanced concepts related to non-classical Riemann problems. The emphasis is on the general ideas but most chapters delve into a particular application to illustrate them." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Book formats\n", + "\n", + "This book is available in two formats: \n", + " - The traditional print medium, in the form of either a physical book or an electronic PDF. \n", + " - As a collection of [Jupyter notebooks](https://github.com/clawpack/riemann_book).\n", + "\n", + "### The print version\n", + "Like any mathematical text, the paper (or PDF) version of this book includes mathematical descriptions and derivations. It also includes figures, most of which are generated by short Python programs. The code for those Python programs is included inline in the text at the same point where each figure appears. The reader may choose to skip the code sections, especially on a first reading.\n", + "\n", + "### The Jupyter notebook version\n", + "In the electronic version of this book, each chapter is a Jupyter notebook. The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text. The notebooks that form this text have some additional benefits not present in the print version:\n", + "\n", + " - Some of the code in the notebooks generates **animations**, showing how solutions vary in time or with respect to a parameter.\n", + " - Other code in the notebooks generates **interactive \"widgets\"** that allow the reader to vary multiple parameters or plot different quantities, in order to gain deeper insight and understanding.\n", + " - The reader can also **modify the code itself**, perhaps to vary parameters that we (the authors) didn't think of. We encourage readers to use this to satisfy their own curiosity and enhance their learning.\n", + " \n", + "### How to access and run the Jupyter notebook version\n", + "In order to run the code in the Jupyter notebook version of the book, you will need to have certain tools and libraries installed on a computer, either locally or in the clous. There are multiple convenient ways to do this.\n", + "\n", + " - With Binder:\n", + " - With Docker: follow instructions at https://github.com/clawpack/riemann_book/blob/master/Docker.md\n", + " - On your own computer: follow instructions at https://github.com/clawpack/riemann_book/wiki/Installation." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "The book includes 5 parts, each divided into several chapters. The first two parts cover the fundamentals of exact and approximate solutions of Riemann problems; the remaining three parts delve into more advanced topics. In a graduate course on hyperbolic conservation laws, the first two parts could be incorporated into the curriculum, while the later chapters might provide suggestions for student projects.\n", + "\n", + "Part I (*partially written*) covers the classical theory of the Riemann problem and its solution, introducing the reader to essential concepts including characteristics; similarity solutions; shock waves and the Rankine-Hugoniot jump conditions; rarefactions and Riemann invariants; genuinely nonlinear and linearly degenerate waves; and entropy conditions. Building up from scalar hyperbolic PDEs and linear systems, it culminates with discussions of the full Riemann solution for the shallow water and Euler systems.\n", + "\n", + "Part II (*not included in the draft*) introduces approximate Riemann solvers, which are an essential tool in numerical algorithms for hyperbolic PDEs. This part discusses the most important approaches to such solvers: from simple Lax-Friedrichs and HLL solvers to linearizations, including Roe solvers. Potential issues with these methods (such as the need for entropy fixes and lack of positivity) are addressed. Part II concludes with comparisons of canonical approximate solvers for the shallow water and Euler systems.\n", + "\n", + "Part III...\n", + "\n", + "Part IV...\n", + "\n", + "Part V..." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Pressureless_flow.ipynb b/Pressureless_flow.ipynb index 7516cfdf..8f9a7542 100644 --- a/Pressureless_flow.ipynb +++ b/Pressureless_flow.ipynb @@ -30,7 +30,9 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false + "tags": [ + "hide" + ] }, "outputs": [], "source": [ @@ -40,7 +42,8 @@ "from exact_solvers import shallow_water\n", "from collections import namedtuple\n", "from utils import riemann_tools\n", - "from ipywidgets import interact, widgets\n", + "from ipywidgets import interact\n", + "from ipywidgets import widgets\n", "State = namedtuple('State', shallow_water.conserved_variables)\n", "Primitive_State = namedtuple('PrimState', shallow_water.primitive_variables)\n", "plt.style.use('seaborn-talk')" @@ -49,17 +52,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from ipywidgets import interact # for interactive widgets\n", - "#from utils.snapshot_widgets import interact # for static figure that can be viewed online" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "def connect_states(h_l=1.,u_l=-1.,h_r=1.,u_r=1.,logg=0.,plot_unphysical=True):\n", @@ -67,12 +62,18 @@ " q_l = np.array([h_l,h_l*u_l])\n", " q_r = np.array([h_r,h_r*u_r])\n", " fig, ax = plt.subplots(1,2,figsize=(14,6))\n", - " shallow_water.phase_plane_curves(q_l[0], q_l[1], 'qleft', g, wave_family=1,ax=ax[0],plot_unphysical=plot_unphysical)\n", - " shallow_water.phase_plane_curves(q_r[0], q_r[1], 'qright', g, wave_family=2,ax=ax[0],plot_unphysical=plot_unphysical)\n", - " shallow_water.phase_plane_curves(q_l[0], q_l[1], 'qleft', g, wave_family=1,y_axis='hu',ax=ax[1],plot_unphysical=plot_unphysical)\n", - " shallow_water.phase_plane_curves(q_r[0], q_r[1], 'qright', g, wave_family=2,y_axis='hu',ax=ax[1],plot_unphysical=plot_unphysical)\n", - " ax[0].set_title('h-u plane'); ax[1].set_title('h-hu plane'); ax[0].set_xlim(0,3); ax[1].set_xlim(0,3);\n", + " shallow_water.phase_plane_curves(q_l[0], q_l[1], 'qleft', g, wave_family=1,\n", + " ax=ax[0],plot_unphysical=plot_unphysical)\n", + " shallow_water.phase_plane_curves(q_r[0], q_r[1], 'qright', g, wave_family=2,\n", + " ax=ax[0],plot_unphysical=plot_unphysical)\n", + " shallow_water.phase_plane_curves(q_l[0], q_l[1], 'qleft', g, wave_family=1,\n", + " y_axis='hu',ax=ax[1],plot_unphysical=plot_unphysical)\n", + " shallow_water.phase_plane_curves(q_r[0], q_r[1], 'qright', g, wave_family=2,\n", + " y_axis='hu',ax=ax[1],plot_unphysical=plot_unphysical)\n", + " ax[0].set_title('h-u plane'); ax[1].set_title('h-hu plane'); \n", + " ax[0].set_xlim(0,3); ax[1].set_xlim(0,3);\n", " ax[0].set_ylim(-10,10); ax[1].set_ylim(-10,10); plt.tight_layout(); plt.show()\n", + " \n", "interact(connect_states,\n", " h_l=widgets.FloatSlider(min=0.001,max=2,value=1),\n", " u_l=widgets.FloatSlider(min=-5,max=5,value=-1),\n", @@ -84,9 +85,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "def c1(q, xi, g=1.):\n", @@ -111,22 +110,24 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "def make_plot_function(q_l,q_r,force_waves=None,extra_lines=None):\n", " def plot_function(t,logg,plot_1_chars=False,plot_2_chars=False):\n", " g = 10**logg\n", - " states, speeds, reval, wave_types = shallow_water.exact_riemann_solution(q_l,q_r,g,force_waves=force_waves)\n", + " states, speeds, reval, wave_types = \\\n", + " shallow_water.exact_riemann_solution(q_l,q_r,g,force_waves=force_waves)\n", " ax = riemann_tools.plot_riemann(states,speeds,reval,wave_types,t=t,t_pointer=0,\n", - " extra_axes=True,variable_names=shallow_water.primitive_variables,\n", + " extra_axes=True,\n", + " variable_names=shallow_water.primitive_variables,\n", " fill=[0],derived_variables=shallow_water.cons_to_prim);\n", " if plot_1_chars:\n", - " riemann_tools.plot_characteristics(reval,c1,(g,g),axes=ax[0],extra_lines=extra_lines)\n", + " riemann_tools.plot_characteristics(reval,c1,(g,g),axes=ax[0],\n", + " extra_lines=extra_lines)\n", " if plot_2_chars:\n", - " riemann_tools.plot_characteristics(reval,c2,(g,g),axes=ax[0],extra_lines=extra_lines)\n", + " riemann_tools.plot_characteristics(reval,c2,(g,g),axes=ax[0],\n", + " extra_lines=extra_lines)\n", " shallow_water.phase_plane_plot(q_l,q_r,g,ax=ax[3],force_waves=force_waves,y_axis='u')\n", " plt.show()\n", " return plot_function\n", @@ -194,7 +195,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "q_l = State(Depth = 3.,\n", @@ -218,7 +221,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "q_l = State(Depth = 3.,\n", @@ -239,7 +244,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "q_l = State(Depth = 3.,\n", @@ -261,13 +268,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To make this even clearer, here's an example with uniform initial depth and both flows directed inward, very similar to the first example we considered in the initial chapter on shallow water." + "To make this even clearer, here's an example with uniform initial depth and both flows directed inward, very similar to the first example we considered in [the initial chapter on shallow water](Shallow_water.ipynb#All-shock-Riemann-solutions)." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "q_l = State(Depth = 1.,\n", @@ -371,9 +380,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Exercises\n", + "## Exercises\n", "\n", - "(1) In the example below, the initial velocity is zero for both states. Observe that multiplying the value of $g$ by a factor $\\alpha$ is equivalent to rescaling all the velocities by $\\sqrt{\\alpha}$. Prove that this scaling must hold for any Riemann solution of this system when $u_l = u_r = 0$." + "(1) In the example below, the initial velocity is zero for both states. Observe that multiplying the value of $g$ by a factor $\\alpha$ is equivalent to rescaling all the velocities by $\\sqrt{\\alpha}$. Prove that this scaling must hold for any Riemann solution of this system when $u_l = u_r = 0$.\n" ] }, { @@ -416,7 +425,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.12" + "version": "2.7.13" } }, "nbformat": 4, diff --git a/SIAMGHbook2016.cls b/SIAMGHbook2016.cls new file mode 100644 index 00000000..7c6ecbfe --- /dev/null +++ b/SIAMGHbook2016.cls @@ -0,0 +1,1446 @@ +%% Revised 2001/10/10 to correct algorithms: xreferencing,numbering +%% Revised 2002/02/19 to correct optional title in algorithms +%% Revised 2002/05/01 to force footnotes to number consecutively throughout book +%% Revised 2003/10/21 added example environment, like theorem +%% Revised 2013/03/20 for new format, Garamond/Helvetica fonts +%% new parameters at bottom, search: GH book formatting +%% Revised 2015/02 index formatting +%% Revised 2015/07/06 corrected ifpdf block page commands, added fix to algorithm environment +%% Revised 2016/05/12, decreased text width to 29pc to allow for printer imposition errors + + +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesClass{SIAMGHbook2016} + [2016/05/12 v2.1 + Customized LaTeX document class] +\newcommand\@ptsize{} +\newif\if@restonecol +\newif\if@titlepage +\@titlepagetrue +\newif\if@openright +\newif\if@mainmatter \@mainmattertrue +\if@compatibility\else +\newif\if@onethmnum +\@onethmnumfalse +%_%_%_%_% remove theorem numbering from class??? +\newif\if@mytheorems +\@mytheoremsfalse + + +\newif\if@ebookmargins \@ebookmarginsfalse + +%%%%add formatted authors to chapter opener... +\newenvironment{authorline}{\let\thanks\footnote\renewcommand{\thefootnote}{\fnsymbol{footnote}}% +\Large\bfseries\itshape}{\vskip36pt%_%_%_%_%\setcounter{footnote}{0} +} + +%%%%add author names to table of contents... +\newcommand{\authortoc}[1]{\addtocontents{toc}{\hspace*{-.5em}\hspace{6.4pt}{\bfseries\itshape #1}}} + +%_%_%_%default "plain" chapter opener...no graphic +\DeclareOption{plain-opener}{% +\def\@makechapterhead#1{% + {\parindent \z@ \raggedright \normalfont + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter +% +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,22.5){\setlength{\fboxsep}{0pt}%\fbox +{\parbox[b][99pt][c]{300pt}{\raggedright\sffamily\Large\bfseries% +\@chapapp\space \thechapter + \vskip3pt\par\nobreak + \Huge \bfseries #1\par}}}%%end of parbox and put +\end{picture} + \fi + \fi + \interlinepenalty\@M} \vskip 40\p@ + }% +\def\@part[#1]#2{% + \ifnum \c@secnumdepth >-2\relax + \refstepcounter{part}% + \addcontentsline{toc}{part}{\thepart\hspace*{20.5pt}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + \markboth{}{}% + {\centering + \interlinepenalty \@M + \normalfont + %_%_%_%_%add part background graphic... + \ifnum \c@secnumdepth >-2\relax + \sffamily\huge\bfseries \partname~\thepart + \par + \vskip 20\p@ + \fi + \sffamily\Huge \bfseries #2\par}% + \@endpart}} +\DeclareOption{opener-d}{% +%_%_%_%_% new makechapterhead +%_%_%_%_% type "D" +%_%_%_%_% +\def\@makechapterhead#1{% + {\parindent \z@ \raggedright \normalfont + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter +% +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,11){\includegraphics[height=120pt]{macroa-1-gray.eps}} +\put(72,22.5){\setlength{\fboxsep}{0pt}%\fbox +{\parbox[b][99pt][c]{300pt}{\raggedright\sffamily\Large\bfseries% +\@chapapp\space \thechapter + \vskip3pt\par\nobreak + \Huge \bfseries #1\par}}}%%end of parbox and put +\end{picture} + \fi + \fi + \interlinepenalty\@M} \vskip 40\p@ + }% +\def\@part[#1]#2{% + \ifnum \c@secnumdepth >-2\relax + \refstepcounter{part}% + \addcontentsline{toc}{part}{\thepart\hspace*{20.5pt}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + \markboth{}{}% + \interlinepenalty \@M + \normalfont + %_%_%_%_%add part background graphic... + \ifnum \c@secnumdepth >-2\relax +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,11){\includegraphics[height=120pt]{macroa-1-gray.eps}} +\put(72,22.5){\setlength{\fboxsep}{0pt}%\fbox +{\parbox[b][99pt][c]{300pt}{\parindent0pt\sffamily\Large\bfseries% +\partname\space \thepart + \vskip3pt\par\nobreak + \Huge \bfseries #2\par}}}%%end of parbox and put +\end{picture} + \fi + \@endpart}} +\DeclareOption{opener-c}{% + +%_%_%_%_% new makechapterhead +%_%_%_%_% type "C" +%_%_%_%_% +\def\@makechapterhead#1{% + {\parindent \z@ \raggedright \normalfont + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter +% +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,0){\includegraphics[width=114pt]{macroa2-gray.eps}} +\put(118,16){\vbox to 99pt{\hsize247pt\raggedright\sffamily\Large\bfseries% +\vfill\@chapapp\space \thechapter + \vskip3pt\par\nobreak + \huge \bfseries #1\par\vfill}}%%end of parbox and put +\end{picture} + \fi + \fi + \interlinepenalty\@M} \vskip 40\p@ + }% +\def\@part[#1]#2{% + \ifnum \c@secnumdepth >-2\relax + \refstepcounter{part}% + \addcontentsline{toc}{part}{\thepart\hspace*{20.5pt}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + \markboth{}{}% + \interlinepenalty \@M + \normalfont + %_%_%_%_%add part background graphic... + \ifnum \c@secnumdepth >-2\relax +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,0){\includegraphics[width=114pt]{macroa2-gray.eps}} +\put(118,16){\vbox to 99pt{\hsize247pt\parindent0pt\sffamily\Large\bfseries% +\vfill\partname\space \thepart + \vskip3pt\par\nobreak + \huge \bfseries #2\par\vfill}}%%end of parbox and put +\end{picture} + \fi + \@endpart}} +\DeclareOption{opener-b}{% +%_%_%_%_% new makechapterhead +%_%_%_%_% type "B" +%_%_%_%_% +\def\@makechapterhead#1{% + {\parindent \z@ \raggedright \normalfont + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter +% +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,0){\includegraphics[width=114pt]{macroa2-gray.eps}} +\put(118,16){\vbox to 99pt{\hsize247pt\raggedright\sffamily\Large\bfseries% +\@chapapp\space \thechapter + \vskip3pt\par\vfill\nobreak + \huge \bfseries #1\par}}%%end of parbox and put +\end{picture} + \fi + \fi + \interlinepenalty\@M} \vskip 40\p@ + }% +\def\@part[#1]#2{% + \ifnum \c@secnumdepth >-2\relax + \refstepcounter{part}% + \addcontentsline{toc}{part}{\thepart\hspace*{20.5pt}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + \markboth{}{}% + \interlinepenalty \@M + \normalfont + %_%_%_%_%add part background graphic... + \ifnum \c@secnumdepth >-2\relax +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,0){\includegraphics[width=114pt]{macroa2-gray.eps}} +\put(118,16){\vbox to 99pt{\parindent0pt\hsize247pt\sffamily\Large\bfseries% +\partname\space \thepart + \vskip3pt\par\vfill\nobreak + \huge \bfseries #2\par}}%%end of parbox and put +\end{picture} + \fi + \@endpart}} +%%%%me + + \DeclareOption{opener-q}{% +%_%_%_%_% new makechapterhead +%_%_%_%_% type "C" +%_%_%_%_% +\def\@makechapterhead#1{% + {\parindent \z@ \raggedright \normalfont + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter +% +\noindent\hspace*{-4.5pc}\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,0){\includegraphics[width=110pt]{Gearboxicong.eps}} +\put(118,88.5){\vtop to 99pt{\hsize300pt\raggedright\sffamily\Large\bfseries% +%_%_%_%_%\vfill +\@chapapp\space \thechapter + \vskip3pt\par\nobreak + \huge \bfseries #1\par\vfill}}%%end of parbox and put +\end{picture} + \fi + \fi + \interlinepenalty\@M} \vskip 40\p@ + }% +\def\@part[#1]#2{% + \ifnum \c@secnumdepth >-2\relax + \refstepcounter{part}% + \addcontentsline{toc}{part}{\thepart\hspace*{20.5pt}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + \markboth{}{}% + \interlinepenalty \@M + \normalfont + %_%_%_%_%add part background graphic... + \ifnum \c@secnumdepth >-2\relax +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,0){\includegraphics[width=114pt]{Gearboxicong.eps}} +\put(118,16){\vbox to 99pt{\hsize247pt\parindent0pt\sffamily\Large\bfseries% +\vfill\partname\space \thepart + \vskip3pt\par\nobreak + \huge \bfseries #2\par\vfill}}%%end of parbox and put +\end{picture} + \fi + \@endpart}} + + +%%%%%%% +\DeclareOption{opener-a}{% +%_%_%_%_% new makechapterhead... +%_%_%_%_% type "A" +%_%_%_%_% +\def\@makechapterhead#1{% + {\parindent \z@ \raggedright \normalfont + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter +% +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,-1){\includegraphics[height=102pt]{macroa-gray.eps}} +\put(118,0){\vbox to 100pt{\hsize247pt\raggedright\sffamily\Large\bfseries% +\@chapapp\space \thechapter + \vfill\par\nobreak + \huge \bfseries #1\par}}%%end of parbox and put +\end{picture} + \fi + \fi + \interlinepenalty\@M} \vskip 40\p@ + }% +\def\@part[#1]#2{% + \ifnum \c@secnumdepth >-2\relax + \refstepcounter{part}% + \addcontentsline{toc}{part}{\thepart\hspace{10em}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + \markboth{}{}% + \interlinepenalty \@M + \normalfont + %_%_%_%_%add part background graphic... + \ifnum \c@secnumdepth >-2\relax +\noindent\setlength{\unitlength}{1pt}\begin{picture}(360,144) +\put(0,-1){\includegraphics[height=102pt]{macroa-gray.eps}} +\put(118,0){\vbox to 100pt{\parindent0pt\hsize247pt\sffamily\Large\bfseries% +\partname\space \thepart + \vfill\par\nobreak + \huge \bfseries #2\par}}%%end of parbox and put +\end{picture} + \fi + \@endpart}} +\DeclareOption{a4paper} + {\setlength\paperheight {297mm}% + \setlength\paperwidth {210mm}} +\DeclareOption{a5paper} + {\setlength\paperheight {210mm}% + \setlength\paperwidth {148mm}} +\DeclareOption{b5paper} + {\setlength\paperheight {250mm}% + \setlength\paperwidth {176mm}} +\DeclareOption{letterpaper} + {\setlength\paperheight {11in}% + \setlength\paperwidth {8.5in}} +\DeclareOption{legalpaper} + {\setlength\paperheight {14in}% + \setlength\paperwidth {8.5in}} +\DeclareOption{executivepaper} + {\setlength\paperheight {10in}% + \setlength\paperwidth {7in}} +\DeclareOption{landscape} + {\setlength\@tempdima {\paperheight}% + \setlength\paperheight {\paperwidth}% + \setlength\paperwidth {\@tempdima}} +\fi +\if@compatibility + \renewcommand\@ptsize{0} +\else +\DeclareOption{10pt}{\renewcommand\@ptsize{0}} +\fi +\DeclareOption{11pt}{\renewcommand\@ptsize{1}} +\DeclareOption{12pt}{\renewcommand\@ptsize{2}} +\if@compatibility\else +\DeclareOption{oneside}{\@twosidefalse \@mparswitchfalse} +\fi +\DeclareOption{twoside}{\@twosidetrue \@mparswitchtrue} +\DeclareOption{draft}{\setlength\overfullrule{5pt}} +\if@compatibility\else +\DeclareOption{final}{\setlength\overfullrule{0pt}} +\fi +\DeclareOption{titlepage}{\@titlepagetrue} +\if@compatibility\else +\DeclareOption{notitlepage}{\@titlepagefalse} +\fi +\if@compatibility +\@openrighttrue +\else +\DeclareOption{openright}{\@openrighttrue} +\DeclareOption{openany}{\@openrightfalse} +\fi +\if@compatibility\else +\DeclareOption{onecolumn}{\@twocolumnfalse} +\fi +\DeclareOption{twocolumn}{\@twocolumntrue} +\DeclareOption{leqno}{\input{leqno.clo}} +\DeclareOption{fleqn}{\input{fleqn.clo}} +\DeclareOption{openbib}{% + \AtEndOfPackage{% + \renewcommand\@openbib@code{% + \advance\leftmargin\bibindent + \itemindent -\bibindent + \listparindent \itemindent + \parsep \z@ + }% + \renewcommand\newblock{\par}}% +} +\DeclareOption{onethmnum}{\@onethmnumtrue} % added 7.29.96 +\DeclareOption{mytheorems}{\@mytheoremstrue} %_%_%_%_% remove theorem defs from class???? +\ExecuteOptions{plain-opener,executivepaper,10pt,twoside,onecolumn,final,openright} +\DeclareOption{ebookmargins}{\@ebookmarginstrue} +\ProcessOptions +%\input{garam1\@ptsize.clo} +\input{bk1\@ptsize.clo} +\setlength\lineskip{1\p@} +\setlength\normallineskip{1\p@} +\renewcommand\baselinestretch{} +\setlength\parskip{0\p@ \@plus \p@} +\@lowpenalty 51 +\@medpenalty 151 +\@highpenalty 301 +\setcounter{topnumber}{2} +\renewcommand\topfraction{.9} +\setcounter{bottomnumber}{1} +\renewcommand\bottomfraction{.1} +\setcounter{totalnumber}{3} +\renewcommand\textfraction{.1} +\renewcommand\floatpagefraction{.91} +\setcounter{dbltopnumber}{2} +\renewcommand\dbltopfraction{.7} +\renewcommand\dblfloatpagefraction{.5} +\if@twoside + \def\ps@headings{% + \let\@oddfoot\@empty\let\@evenfoot\@empty + \def\@evenhead{{\rule[-5pt]{\textwidth}{0.75pt}}\hspace*{-\textwidth}\fontsize{9.5}{12pt}\selectfont\sffamily\thepage\hfil\leftmark}% + \def\@oddhead{{\rule[-5pt]{\textwidth}{0.75pt}}\hspace*{-\textwidth}\fontsize{9.5}{12pt}\selectfont\sffamily{\rightmark}\hfil\thepage}% + \let\@mkboth\markboth + \def\chaptermark##1{% + \markboth {{%%%%%was \MakeUppercase + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \@chapapp\ \thechapter. \ % + \fi + \fi + ##1}}{}}% + \def\sectionmark##1{% + \markright {{%%%%%was \MakeUppercase + \ifnum \c@secnumdepth >\z@ + \thesection. \ % + \fi + ##1}}}} +\else + \def\ps@headings{% + \let\@oddfoot\@empty + \def\@oddhead{\fontsize{10}{12pt}\selectfont{\sffamily\rightmark}\hfil\thepage}% + \let\@mkboth\markboth + \def\chaptermark##1{% + \markright {\MakeUppercase{% + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \@chapapp\ \thechapter. \ % + \fi + \fi + ##1}}}} +\fi +\def\ps@myheadings{% + \let\@oddfoot\@empty\let\@evenfoot\@empty + \def\@evenhead{{\rule[-5pt]{\textwidth}{0.75pt}}\hspace*{-\textwidth}\fontsize{9.5}{12pt}\selectfont\sffamily\thepage\hfil\leftmark}% + \def\@oddhead{{\fontsize{10}{12pt}\selectfont\sffamily\rightmark}\hfil\fontsize{10}{12pt}\selectfont\sffamily\thepage}% + \let\@mkboth\@gobbletwo + \let\chaptermark\@gobble + \let\sectionmark\@gobble + } +\def\ps@plain{\let\@mkboth\@gobbletwo + \let\@oddhead\@empty\def\@oddfoot{\reset@font\hfil\fontsize{9.5}{12pt}\selectfont\sffamily\thepage + \hfil}\let\@evenhead\@empty\let\@evenfoot\@oddfoot} + \if@titlepage + \newcommand\maketitle{\begin{titlepage}% + \let\footnotesize\small + \let\footnoterule\relax + \let \footnote \thanks + \null\vfil + \vskip 60\p@ + \begin{center}% + {\LARGE \@title \par}% + \vskip 3em% + {\large + \lineskip .75em% + \begin{tabular}[t]{c}% + \@author + \end{tabular}\par}% + \vskip 1.5em% + {\large \@date \par}% % Set date in \large size. + \end{center}\par + \@thanks + \vfil\null + \end{titlepage}% + \setcounter{footnote}{0}% + \global\let\thanks\relax + \global\let\maketitle\relax + \global\let\@thanks\@empty + \global\let\@author\@empty + \global\let\@date\@empty + \global\let\@title\@empty + \global\let\title\relax + \global\let\author\relax + \global\let\date\relax + \global\let\and\relax +} +\else +\newcommand\maketitle{\par + \begingroup + \renewcommand\thefootnote{\@fnsymbol\c@footnote}% + \def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}% + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn + \ifnum \col@number=\@ne + \@maketitle + \else + \twocolumn[\@maketitle]% + \fi + \else + \newpage + \global\@topnum\z@ % Prevents figures from going at top of page. + \@maketitle + \fi + \thispagestyle{plain}\@thanks + \endgroup + %_%_%_%_%\setcounter{footnote}{0}% + \global\let\thanks\relax + \global\let\maketitle\relax + \global\let\@maketitle\relax + \global\let\@thanks\@empty + \global\let\@author\@empty + \global\let\@date\@empty + \global\let\@title\@empty + \global\let\title\relax + \global\let\author\relax + \global\let\date\relax + \global\let\and\relax +} +\def\@maketitle{% + \newpage + \null + \vskip 2em% + \begin{center}% + \let \footnote \thanks + {\LARGE \@title \par}% + \vskip 1.5em% + {\large + \lineskip .5em% + \begin{tabular}[t]{c}% + \@author + \end{tabular}\par}% + \vskip 1em% + {\large \@date}% + \end{center}% + \par + \vskip 1.5em} +\fi +\newcommand*\chaptermark[1]{} +\setcounter{secnumdepth}{2} +\newcounter {part} +\newcounter {chapter} +\newcounter {section}[chapter] +\newcounter {subsection}[section] +\newcounter {subsubsection}[subsection] +\newcounter {paragraph}[subsubsection] +\newcounter {subparagraph}[paragraph] +\renewcommand \thepart {\@Roman\c@part} +\renewcommand \thechapter {\@arabic\c@chapter} +\renewcommand \thesection {\thechapter.\@arabic\c@section} +\renewcommand\thesubsection {\thesection.\@arabic\c@subsection} +\renewcommand\thesubsubsection{\thesubsection .\@arabic\c@subsubsection} +\renewcommand\theparagraph {\thesubsubsection.\@arabic\c@paragraph} +\renewcommand\thesubparagraph {\theparagraph.\@arabic\c@subparagraph} +\newcommand\@chapapp{\chaptername} +\newcommand\frontmatter{% + \cleardoublepage + \@mainmatterfalse + \pagenumbering{roman}} +\newcommand\mainmatter{% + \cleardoublepage + \@mainmattertrue + \pagenumbering{arabic}} +\newcommand\backmatter{% + \if@openright + \cleardoublepage + \else + \clearpage + \fi + \@mainmatterfalse} +\newcommand\part{% + \if@openright + \cleardoublepage + \else + \clearpage + \fi + \thispagestyle{empty}% + \if@twocolumn + \onecolumn + \@tempswatrue + \else + \@tempswafalse + \fi + \null%%%%%\vfil +\vspace*{72pt} + \secdef\@part\@spart} + + + +\def\@spart#1{% + {\centering + \interlinepenalty \@M + \normalfont + \sffamily\Huge \bfseries #1\par}% + \@endpart} +\def\@endpart{\vfil\newpage + \if@twoside + \null + \thispagestyle{empty}% + \newpage + \fi + \if@tempswa + \twocolumn + \fi} +\newcommand\chapter{\if@openright\cleardoublepage\else\clearpage\fi + \thispagestyle{plain}% + \global\@topnum\z@ + \@afterindentfalse + \secdef\@chapter\@schapter} +%_%_%_%_% +%_%_%_%_% add third parameter to \chapter to include background graphic +%_%_%_%_% +\def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \refstepcounter{chapter}% + \typeout{\@chapapp\space\thechapter.}% + \addcontentsline{toc}{chapter}% + {\protect\numberline{\thechapter}#1}% + \else + \addcontentsline{toc}{chapter}{#1}% + \fi + \else + \addcontentsline{toc}{chapter}{#1}% + \fi + \chaptermark{#1}% + \addtocontents{lof}{\protect\addvspace{10\p@}}% + \addtocontents{lot}{\protect\addvspace{10\p@}}% + \if@twocolumn + \@topnewpage[\@makechapterhead{#2}]% + \else + \@makechapterhead{#2}% + \@afterheading + \fi} +%_%_%_%_% +%_%_%_%_% new definition for chapter-page quote +%_%_%_%_% optional argument moves environment right, in order to center +\newenvironment{chapterquote}[1][0pt]{\normalsize\normalfont\itshape% +\advance\leftskip#1}{\par} +\def\@schapter#1{\if@twocolumn + \@topnewpage[\@makeschapterhead{#1}]% + \else + \@makeschapterhead{#1}% + \@afterheading + \fi} +\def\@makeschapterhead#1{% + \vspace*{50\p@}% + {\parindent \z@ \raggedright + \normalfont + \interlinepenalty\@M\centering + \Huge \sffamily\bfseries #1\par\nobreak + \vskip 40\p@ + }} +\newcommand\section{\@startsection {section}{1}{0pc}% + {-3.5ex \@plus -1ex \@minus -.2ex}% + {1.5ex \@plus.0ex}% + {\normalfont\fontsize{13.5}{15.5pt}\selectfont\sffamily\bfseries}}%14/16 +\newcommand\subsection{\@startsection{subsection}{2}{0pc}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\normalfont\fontsize{11.5}{13.5pt}\selectfont\sffamily\bfseries}}%12/14 +\newcommand\subsubsection{\@startsection{subsubsection}{3}{0pc}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\normalfont\fontsize{9.5}{11.5pt}\selectfont\sffamily\bfseries}}%10/12 +\newcommand\paragraph{\@startsection{paragraph}{4}{\z@}% + {3.25ex \@plus1ex \@minus.2ex}% + {-1em}% + {\normalfont\fontsize{9.5}{12pt}\selectfont\sffamily\bfseries}}%10/12 +\newcommand\subparagraph{\@startsection{subparagraph}{5}{\parindent}% + {3.25ex \@plus1ex \@minus .2ex}% + {-1em}% + {\normalfont\fontsize{9.5}{12pt}\selectfont\sffamily\bfseries}}%10/12 +\if@twocolumn + \setlength\leftmargini {2em} +\else + \setlength\leftmargini {2.5em} +\fi +\leftmargin \leftmargini +\setlength\leftmarginii {2.2em} +\setlength\leftmarginiii {1.87em} +\setlength\leftmarginiv {1.7em} +\if@twocolumn + \setlength\leftmarginv {.5em} + \setlength\leftmarginvi {.5em} +\else + \setlength\leftmarginv {1em} + \setlength\leftmarginvi {1em} +\fi +\setlength \labelsep {.5em} +\setlength \labelwidth{\leftmargini} +\addtolength\labelwidth{-\labelsep} +\@beginparpenalty -\@lowpenalty +\@endparpenalty -\@lowpenalty +\@itempenalty -\@lowpenalty +\renewcommand\theenumi{\@arabic\c@enumi} +\renewcommand\theenumii{\@alph\c@enumii} +\renewcommand\theenumiii{\@roman\c@enumiii} +\renewcommand\theenumiv{\@Alph\c@enumiv} +\newcommand\labelenumi{\theenumi.} +\newcommand\labelenumii{(\theenumii)} +\newcommand\labelenumiii{\theenumiii.} +\newcommand\labelenumiv{\theenumiv.} +\renewcommand\p@enumii{\theenumi} +\renewcommand\p@enumiii{\theenumi(\theenumii)} +\renewcommand\p@enumiv{\p@enumiii\theenumiii} +\newcommand\labelitemi{\textbullet} +\newcommand\labelitemii{\normalfont\bfseries \textendash} +\newcommand\labelitemiii{\textasteriskcentered} +\newcommand\labelitemiv{\textperiodcentered} +\newenvironment{description} + {\list{}{\labelwidth\z@ \itemindent-\leftmargin + \let\makelabel\descriptionlabel}} + {\endlist} +\newcommand*\descriptionlabel[1]{\hspace\labelsep + \normalfont\bfseries #1} +\newenvironment{verse} + {\let\\\@centercr + \list{}{\itemsep \z@ + \itemindent -1.5em% + \listparindent\itemindent + \rightmargin \leftmargin + \advance\leftmargin 1.5em}% + \item\relax} + {\endlist} +\newenvironment{quotation} + {\list{}{\listparindent 1.5em% + \itemindent \listparindent + \rightmargin \leftmargin + \parsep \z@ \@plus\p@}% + \item\relax} + {\endlist} +\newenvironment{quote} + {\list{}{\rightmargin\leftmargin}% + \item\relax} + {\endlist} +\if@compatibility +\newenvironment{titlepage} + {% + \cleardoublepage + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse\newpage + \fi + \thispagestyle{empty}% + \setcounter{page}\z@ + }% + {\if@restonecol\twocolumn \else \newpage \fi + } +\else +\newenvironment{titlepage} + {% + \cleardoublepage + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse\newpage + \fi + \thispagestyle{empty}% + \setcounter{page}\@ne + }% + {\if@restonecol\twocolumn \else \newpage \fi + \if@twoside\else + \setcounter{page}\@ne + \fi + } +\fi +\newcommand\appendix{\par + \setcounter{chapter}{0}% + \setcounter{section}{0}% + \renewcommand\@chapapp{\appendixname}% + \renewcommand\thechapter{\@Alph\c@chapter}} +\setlength\arraycolsep{5\p@} +\setlength\tabcolsep{6\p@} +\setlength\arrayrulewidth{.4\p@} +\setlength\doublerulesep{2\p@} +\setlength\tabbingsep{\labelsep} +\skip\@mpfootins = \skip\footins +\setlength\fboxsep{3\p@} +\setlength\fboxrule{.4\p@} +\@addtoreset {equation}{chapter} +\renewcommand\theequation + {\ifnum \c@chapter>\z@ \thechapter.\fi \@arabic\c@equation} +\newcounter{figure}[chapter] +\renewcommand \thefigure + {\ifnum \c@chapter>\z@ \thechapter.\fi \@arabic\c@figure} +\def\fps@figure{tbp} +\def\ftype@figure{1} +\def\ext@figure{lof} +\def\fnum@figure{\figurename~\thefigure} +\newenvironment{figure} + {\@float{figure}} + {\end@float} +\newenvironment{figure*} + {\@dblfloat{figure}} + {\end@dblfloat} +\newcounter{table}[chapter] +\renewcommand \thetable + {\ifnum \c@chapter>\z@ \thechapter.\fi \@arabic\c@table} +\def\fps@table{tbp} +\def\ftype@table{2} +\def\ext@table{lot} +\def\fnum@table{\tablename~\thetable} +\newenvironment{table} + {\@float{table}} + {\end@float} +\newenvironment{table*} + {\@dblfloat{table}} + {\end@dblfloat} +\newlength\abovecaptionskip +\newlength\belowcaptionskip +\setlength\abovecaptionskip{10\p@} +\setlength\belowcaptionskip{0\p@} +\newlength{\xcaptionindent} +\setlength{\xcaptionindent}{3pc} +\def\xtable{table} +\long\def\@makecaption#1#2{% + \vskip\abovecaptionskip + \sbox\@tempboxa{\textbf{#1.} \itshape#2}% + \ifdim \wd\@tempboxa >\hsize + \hspace*{\xcaptionindent}{\textbf{#1.} }\itshape#2\par + \else + \global \@minipagefalse + \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}% + \fi +\ifx\@captype\xtable +\vskip6pt +\else +\fi + \vskip\belowcaptionskip} + +%%%%remove extra space above tables +\long\def\@makecaption#1#2{{\fontsize{9}{11pt}\selectfont% +\ifx\@captype\xtable + \sbox\@tempboxa{\textbf{#1.} \itshape#2}% + \ifdim \wd\@tempboxa >\hsize + \hspace*{\xcaptionindent}{\textbf{#1.} }\itshape#2\par + \else + \global \@minipagefalse + \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}% + \fi + \vskip10\p@ +\else + \vskip\abovecaptionskip + \sbox\@tempboxa{\textbf{#1.} \itshape#2}% + \ifdim \wd\@tempboxa >\hsize + \hspace*{\xcaptionindent}{\textbf{#1.} }\itshape#2\par + \else + \global \@minipagefalse + \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}% + \fi% +\fi}}%%%end captype + +\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm} +\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf} +\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt} +\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf} +\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit} +\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl} +\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc} +\DeclareRobustCommand*\cal{\@fontswitch\relax\mathcal} +\DeclareRobustCommand*\mit{\@fontswitch\relax\mathnormal} +\newcommand\@pnumwidth{15pt} +\newcommand\@tocrmarg{2.55em} +\newcommand\@dotsep{4.5} +\setcounter{tocdepth}{2} +\newcommand\tableofcontents{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \chapter*{\contentsname + \@mkboth{% + \contentsname}{\contentsname}}% + \@starttoc{toc}% + \if@restonecol\twocolumn\fi + } +\newcommand*\l@part[2]{% + \ifnum \c@tocdepth >-2\relax + \addpenalty{-\@highpenalty}% + \addvspace{2.25em \@plus\p@}% + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + {\leavevmode + \normalsize \bfseries #1\hfil \hb@xt@\@pnumwidth{\hss #2}}\par + \nobreak + \global\@nobreaktrue + \everypar{\global\@nobreakfalse\everypar{}}% + \endgroup + \fi} +\newcommand*\l@chapter[2]{% + \ifnum \c@tocdepth >\m@ne + \addpenalty{-\@highpenalty}% + \vskip 1.0em \@plus\p@ + \setlength\@tempdima{2.5em}%was 1.5em + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \leavevmode \bfseries + \advance\leftskip\@tempdima + \hskip -\leftskip + #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par + \penalty\@highpenalty + \endgroup + \fi} + + +\newcommand*\l@section{\@dottedtocline{1}{2.5em}{3.3em}} +\newcommand*\l@subsection{\@dottedtocline{2}{5.8em}{5.2em}} +\newcommand*\l@subsubsection{\@dottedtocline{3}{7.0em}{4.1em}} +\newcommand*\l@paragraph{\@dottedtocline{4}{10em}{5em}} +\newcommand*\l@subparagraph{\@dottedtocline{5}{12em}{6em}} +\newcommand\listoffigures{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \chapter*{\listfigurename + \@mkboth{\listfigurename}% + {\listfigurename}}% + \@starttoc{lof}% + \if@restonecol\twocolumn\fi + } +%_%_%_%_% +%_%_%_%_%make list of algorithms +%_%_%_%_% +\newcommand*\l@algorithm{\@dottedtocline{1}{0pt}{84pt}} +\newcommand\listofalgorithms{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \chapter*{List of Algorithms + \@mkboth{{List of Algorithms}}% + {{List of Algorithms}}}% + \@starttoc{loa}% + \if@restonecol\twocolumn\fi + } + +\newcounter{algorithm}[chapter] +\renewcommand{\thealgorithm}{\arabic{chapter}.\arabic{algorithm}} +\newenvironment{algorithm}[1][\relax]{\refstepcounter{algorithm}% +\addcontentsline{loa}{algorithm}% + {\protect\numberline{Algorithm~\thealgorithm}{\ignorespaces#1}}% +\par\vspace{1\baselineskip}% +\expandafter\ifx#1\relax +\parindent0pt {\scshape\bfseries Algorithm~\thealgorithm.}\\%%% +\else +\parindent0pt {\scshape\bfseries Algorithm~\thealgorithm.}\enspace{\bfseries#1.}\\%%% +\fi} +{\vspace{1\baselineskip}\par} +%_%_%_%_% +%_%_%_%_% +%_%_%_%_% +%%%\newcommand*\l@figure{\@dottedtocline{1}{1.5em}{2.3em}} +\newcommand*\l@figure{\@dottedtocline{1}{1.5em}{3.3em}} +\newcommand\listoftables{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \chapter*{\listtablename + \@mkboth{% + \listtablename}{\listtablename}}% + \@starttoc{lot}% + \if@restonecol\twocolumn\fi + } +\let\l@table\l@figure +\newdimen\bibindent +\setlength\bibindent{1.5em} +\newenvironment{thebibliography}[1] + {\chapter*{\bibname + \@mkboth{\bibname}{\bibname}}% +\addcontentsline{toc}{chapter}{\bibname}% +\fontsize{9}{11pt}\selectfont% + \list{\@biblabel{\@arabic\c@enumiv}}% + {\settowidth\labelwidth{\@biblabel{#1}}% + \leftmargin\labelwidth + \advance\leftmargin\labelsep + \@openbib@code + \usecounter{enumiv}% + \let\p@enumiv\@empty + \renewcommand\theenumiv{\@arabic\c@enumiv}}% + \sloppy + \clubpenalty4000 + \@clubpenalty \clubpenalty + \widowpenalty4000% + \sfcode`\.\@m} + {\def\@noitemerr + {\@latex@warning{Empty `thebibliography' environment}}% + \endlist} +\newcommand\newblock{\hskip .11em\@plus.33em\@minus.07em} +\let\@openbib@code\@empty +\newenvironment{theindex} + {\if@twocolumn + \@restonecolfalse + \else + \@restonecoltrue + \fi + \columnseprule \z@ + \columnsep 35\p@ + \twocolumn[\@makeschapterhead{\indexname}]% + \addcontentsline{toc}{chapter}{\indexname}% + \@mkboth{\indexname}% + {\indexname}% + \thispagestyle{plain}\parindent\z@ + \parskip\z@ \@plus .3\p@\relax + \let\item\@idxitem} + {\if@restonecol\onecolumn\else\clearpage\fi} +\newcommand\@idxitem{\par\hangindent 24\p@} +\newcommand\subitem{\@idxitem \hspace*{8\p@}} +\newcommand\subsubitem{\@idxitem \hspace*{16\p@}} +\newcommand\indexspace{\par \vskip 10\p@ \@plus5\p@ \@minus3\p@\relax} +\renewcommand\footnoterule{% + \kern-3\p@ + \hrule\@width6pc + \kern2.6\p@} +%%%% 05/01/02 deleted to change numbering \@addtoreset{footnote}{chapter} +\newcommand\@makefntext[1]{% + \parindent 1em% + \noindent\hb@xt@1.8em{\hss\@makefnmark}#1} +\newcommand\contentsname{Contents} +\newcommand\listfigurename{List of Figures} +\newcommand\listtablename{List of Tables} +\newcommand\bibname{Bibliography} +\newcommand\indexname{Index} +\newcommand\figurename{Figure} +\newcommand\tablename{Table} +\newcommand\partname{Part} +\newcommand\chaptername{Chapter} +\newcommand\appendixname{Appendix} +\def\today{\ifcase\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\fi + \space\number\day, \number\year} +\setlength\columnsep{10\p@} +\setlength\columnseprule{0\p@} +\pagestyle{headings} +\pagenumbering{arabic} +\if@twoside +\else + \raggedbottom +\fi +\if@twocolumn + \twocolumn + \sloppy + \flushbottom +\else + \onecolumn +\fi + + +%_%_%_%_% +%_%_%_%_% borrowed from siamltex.cls... +%_%_%_%_% + +\def\@begintheorem#1#2{\vskip-\lastskip\par\vskip12pt\par% +\bgroup\noindent{\bfseries #1\ #2. }\it\ignorespaces} +% +\def\@opargbegintheorem#1#2#3{\vskip-\lastskip\par\vskip12pt\par\bgroup% + \noindent{\bfseries #1\ #2\ ({\upshape #3}). }\it\ignorespaces} +% +\def\@endtheorem{\egroup\vskip12pt} +% + + +%%% create theorems, etc. with upright font, no italic +\def\newtheoremup#1{% + \@ifnextchar[{\@othmup{#1}}{\@nthmup{#1}}} +\def\@nthmup#1#2{% + \@ifnextchar[{\@xnthmup{#1}{#2}}{\@ynthmup{#1}{#2}}} +\def\@xnthmup#1#2[#3]{% + \expandafter\@ifdefinable\csname #1\endcsname + {\@definecounter{#1}\@newctr{#1}[#3]% + \expandafter\xdef\csname the#1\endcsname{% + \expandafter\noexpand\csname the#3\endcsname \@thmcountersep + \@thmcounterup{#1}}% + \global\@namedef{#1}{\@thmup{#1}{#2}}% + \global\@namedef{end#1}{\@endtheoremup}}} +\def\@ynthmup#1#2{% + \expandafter\@ifdefinable\csname #1\endcsname + {\@definecounter{#1}% + \expandafter\xdef\csname the#1\endcsname{\@thmcounterup{#1}}% + \global\@namedef{#1}{\@thmup{#1}{#2}}% + \global\@namedef{end#1}{\@endtheoremup}}} +\def\@othmup#1[#2]#3{% + \@ifundefined{c@#2}{\@nocounterr{#2}}% + {\expandafter\@ifdefinable\csname #1\endcsname + {\global\@namedef{the#1}{\@nameuse{the#2}}% + \global\@namedef{#1}{\@thmup{#2}{#3}}% + \global\@namedef{end#1}{\@endtheoremup}}}} +\def\@thmup#1#2{% + \refstepcounter{#1}% + \@ifnextchar[{\@ythmup{#1}{#2}}{\@xthmup{#1}{#2}}} +\def\@xthmup#1#2{% + \@begintheoremup{#2}{\csname the#1\endcsname}\ignorespaces} +\def\@ythmup#1#2[#3]{% + \@opargbegintheoremup{#2}{\csname the#1\endcsname}{#3}\ignorespaces} +\def\@thmcounterup#1{\noexpand\arabic{#1}} +\def\@thmcountersep{.} +\def\@begintheoremup#1#2{\trivlist + \item[\hskip \labelsep{\bfseries #1\ #2.}]\upshape} +\def\@opargbegintheoremup#1#2#3{\trivlist + \item[\hskip \labelsep{\bfseries #1\ #2\ (#3).}]\upshape} +\def\@endtheoremup{\endtrivlist} + + +\newlength{\proofboxwd} +\setlength{\proofboxwd}{1pt} + +\def\proofbox{\hspace{24\proofboxwd}\vbox{\hrule height0.6\proofboxwd\hbox{% + \vrule height1.3ex width0.6\proofboxwd\hskip0.8ex + \vrule width0.6\proofboxwd}\hrule height0.6\proofboxwd + }} + +\def\examplebox{\hspace{12\proofboxwd}\rule{5.36pt}{7.91pt}} + + +\def\tempproofbox{\hspace{12\proofboxwd}\vbox{\hrule height0.6\proofboxwd\hbox{% + \vrule height1.3ex width0.6\proofboxwd\hskip0.8ex + \vrule width0.6\proofboxwd}\hrule height0.6pt + }} + + +\def\myproofbox{\tempproofbox\global\setlength{\proofboxwd}{0pt}} + +\newenvironment{proof}{% +\vskip-\lastskip\par +\vskip12pt\par\noindent{\bfseries\itshape Proof.} \ignorespaces}% +{\proofbox\vspace{1\baselineskip}\global\setlength{\proofboxwd}{1pt}} + + +\if@mytheorems +\else +\if@onethmnum + \newtheorem{theorem}{Theorem} + \newtheorem{lemma}[theorem]{Lemma} + \newtheorem{corollary}[theorem]{Corollary} + \newtheorem{proposition}[theorem]{Proposition} + \newtheorem{definition}[theorem]{Definition} + \newtheoremup{example}[theorem]{Example} +\else + \newtheorem{theorem}{Theorem}[chapter] + \newtheorem{lemma}[theorem]{Lemma} + \newtheorem{corollary}[theorem]{Corollary} + \newtheorem{proposition}[theorem]{Proposition} + \newtheorem{definition}[theorem]{Definition} + \newtheoremup{example}[theorem]{Example} +\fi +\let\tempendexample\@endtheoremup +\fi + +\newdimen\exboxwd +\exboxwd1pt + +\def\tempexamplebox{\hspace{12\exboxwd}\mbox{\rule{5.36pt}{7.91pt}}} + +\def\myexamplebox{\tempexamplebox\global\exboxwd0pt\relax} + +\def\examplebox{\ifdim\exboxwd=1pt\hspace{12\proofboxwd}\mbox{\rule{5.36pt}{7.91pt}}\else\fi} + +\def\endexample{\examplebox\global\exboxwd1pt\relax\vspace{.9\baselineskip}} + + +\newcounter{rmnum} +\newenvironment{romannum} + {\begin{list}{{\hfill\upshape (\roman{rmnum})}}{\usecounter{rmnum} + \setlength{\leftmargin}{24pt}\labelwidth24pt\labelsep.5em% + \itemsep2pt\parsep0pt + \setlength{\itemindent}{0pt}}}{\end{list}} +\newcounter{muni} +\newenvironment{remunerate} + {\begin{list}{{\hfill\upshape \arabic{muni}.}}{\usecounter{muni} + \setlength{\leftmargin}{24pt}\labelwidth24pt\labelsep.5em% + \itemsep2pt\parsep0pt + \setlength{\itemindent}{0pt}}}{\end{list}} + +\newenvironment{bulletlist} +{\begin{list}{{\hfill\raisebox{1.12pt}{$\bullet$}}}{% + \setlength{\leftmargin}{24pt}\labelwidth24pt\labelsep.5em% + \itemsep2pt\parsep0pt + \setlength{\itemindent}{0pt}}}{\end{list}} + + +\newenvironment{alphlist} + {\begin{list}{{\hfill\upshape (\alph{muni})}}{\usecounter{muni} + \setlength{\leftmargin}{24pt}\labelwidth24pt\labelsep.5em% + \itemsep2pt\parsep0pt + \setlength{\itemindent}{0pt}}}{\end{list}} + + +\newcommand\sameauthor{\leavevmode\vrule height 2pt depth -1.6pt width 23pt} + + +%_%_%_%_% fix eqnarray spacing +\def\@tempb{% + \stepcounter{equation}% + \def\@currentlabel{\p@equation\theequation}% + \global\@eqnswtrue + \m@th + \global\@eqcnt\z@ + \tabskip\@centering + \let\\\@eqncr + $$\everycr{}\halign to\displaywidth\bgroup + \hskip\@centering$\displaystyle\tabskip\z@skip{##}$\@eqnsel + &\global\@eqcnt\@ne\hskip \tw@\arraycolsep \hfil${##}$\hfil + &\global\@eqcnt\tw@ \hskip \tw@\arraycolsep + $\displaystyle{##}$\hfil\tabskip\@centering + &\global\@eqcnt\thr@@ \hb@xt@\z@\bgroup\hss##\egroup + \tabskip\z@skip + \cr +} +\ifx\eqnarray\@tempb % Try the default eqnarray environment + \def\eqnarray{% + \stepcounter{equation}% + \def\@currentlabel{\p@equation\theequation}% + \global\@eqnswtrue + \m@th + \global\@eqcnt\z@ + \tabskip\@centering + \let\\\@eqncr + $$\everycr{}\halign to\displaywidth\bgroup + \hskip\@centering$\displaystyle\tabskip\z@skip{##}$\@eqnsel + &\global\@eqcnt\@ne \hfil$\displaystyle{{}##{}}$\hfil + &\global\@eqcnt\tw@ $\displaystyle{##}$\hfil\tabskip\@centering + &\global\@eqcnt\thr@@ \hb@xt@\z@\bgroup\hss##\egroup + \tabskip\z@skip + \cr +} +\else \typeout{Warning: Unable to fix unknown version of \string\eqnarray.} +\fi + +\def\@tempb{} + + +%_%_%_%_% +%_%_%_%_% for crops and other stuff... +%_%_%_%_% +\setlength{\paperheight}{10in} +\setlength{\paperwidth}{7in} + +\usepackage{ifpdf} +\ifpdf + \pdfpageheight=10in + \pdfpagewidth=7in +\else + \special{papersize=7in,10in} +\fi + +\setlength{\oddsidemargin}{.75in} +\setlength{\evensidemargin}{.766in} + +%_%_%_%_% +%_%_%_%_% Problems/exercises +%_%_%_%_% +\newcounter{prob} +\newenvironment{problems} + {% +\section*{\rule[6pt]{\textwidth}{1pt}\newline\nobreak Problems}% +\addcontentsline{toc}{section}{Problems}% +\markright{Problems} +\begin{list}{{\hfill\upshape \arabic{prob}.}}{\usecounter{prob} + \setlength{\leftmargin}{24pt}\labelwidth24pt\labelsep.5em% + \itemsep2pt\parsep0pt + \setlength{\itemindent}{0pt}}}{\end{list}} + +\newenvironment{exercises} + {% +\section*{\rule[6pt]{\textwidth}{1pt}\newline\nobreak Exercises}% +\addcontentsline{toc}{section}{Exercises}% +\markright{Exercises} +\begin{list}{{\hfill\upshape \arabic{chapter}.\arabic{prob}.}}{\usecounter{prob} + \setlength{\leftmargin}{28pt}\labelwidth28pt\labelsep.5em% + \itemsep2pt\parsep0pt + \setlength{\itemindent}{0pt}}}{\end{list}} + +%_%_%_%_% +%_%_%_%_% front matter, etc. +%_%_%_%_% +\newenvironment{thepreface}{\if@openright\cleardoublepage\else\clearpage\fi +\@makeschapterhead{Preface}% +\addcontentsline{toc}{chapter}{Preface}% + \@mkboth{Preface}% + {Preface}% + \thispagestyle{plain}} + {\clearpage} + +%_%_%_%_% +%_%_%_%_% +%_%_%_%_% + +%_%_%_%_% #1 is the contributor's name, #2 is the affiliation +\newcommand{\contributor}[2]{\small\noindent\vtop{{\bfseries#1}\\#2}\vspace{0.5pc}\par} + +\newenvironment{contributors}{\if@openright\cleardoublepage\else\clearpage\fi +\@makeschapterhead{List of Contributors}% +%\addcontentsline{toc}{chapter}{List of Contributors}% + \@mkboth{List of Contributors}% + {List of Contributors}% + \thispagestyle{plain}% + \hoffset=-20pt% + \begin{multicols}{3}\parindent0pt% +\parskip6pt plus2pt minus1pt% +\widowpenalty10000\clubpenalty10000} + {\end{multicols}\clearpage} + +\setlength{\parskip}{1\parskip} + + +\parskip1\parskip +\hfuzz362pt + + +%_%_%_%_% +%_%_%_%_% GH book formatting +%_%_%_%_% + + +%\setlength{\oddsidemargin}{7.5pc} +\setlength{\oddsidemargin}{2.85pc} +\setlength{\evensidemargin}{1.74pc} +%\setlength{\topmargin}{-3.463pc} +\setlength{\topmargin}{-2.213pc} +\setlength{\textheight}{50pc} +\setlength{\textwidth}{29pc} + +\if@ebookmargins +\setlength{\oddsidemargin}{2.285pc} +\setlength{\evensidemargin}{2.285pc} +\else +\fi + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + + + + + +\def\opendingbat{\rule[.25ex]{.5ex}{.5ex}}%opendingbat + + + + + +%\def\@seccntformat#1{{{\csname the#1\endcsname}\hskip.33em\opendingbat\hskip.33em\relax}}%%%%vertical rule + +\def\@seccntformat#1{{\csname the#1\endcsname\hskip.33em\protect\rule[.25ex]{.5ex}{.5ex}\hskip.33em\relax}}%%%%vertical rule + +\def\ps@headings{% + \let\@oddfoot\@empty\let\@evenfoot\@empty + \def\@evenhead{\hspace*{-3.47pc}{\rule[-5pt]{32.47pc}{0.75pt}}\hspace*{-32.47pc}\hbox to 32.47pc{\fontsize{9.5}{11.5pt}\selectfont\sffamily\thepage\hfill\leftmark}}% + \def\@oddhead{\hspace*{-3.47pc}{\rule[-5pt]{32.47pc}{0.75pt}}\hspace*{-32.47pc}\hbox to 32.47pc{\fontsize{9.5}{11.5pt}\selectfont\sffamily{\rightmark}\hfill\thepage}}% + \let\@mkboth\markboth% + \def\chaptermark##1{% + \markboth {{%%%%%was \MakeUppercase + \ifnum \c@secnumdepth >\m@ne% + \if@mainmatter% + \@chapapp\ \thechapter. \ % + \fi% + \fi% + ##1}}{}}% + \def\sectionmark##1{% + \markright {{%%%%%was \MakeUppercase + \ifnum \c@secnumdepth >\z@% + \thesection. \ % + \fi% + ##1}}}} + + \pagestyle{headings} + +\def\ps@myheadings{% + \let\@oddfoot\@empty\let\@evenfoot\@empty + \def\@evenhead{\hspace*{-3.47pc}{\rule[-5pt]{32.47pc}{0.75pt}}\hspace*{-32.47pc}\hbox to 32.47pc{\fontsize{9.5}{11.5pt}\selectfont\sffamily\thepage\hfill\leftmark}}% + \def\@oddhead{\hspace*{-3.47pc}{\rule[-5pt]{32.47pc}{0.75pt}}\hspace*{-32.47pc}\hbox to 33.55pc{\fontsize{9.5}{11.5pt}\selectfont\sffamily{\rightmark}\hfill\thepage}}% + \let\@mkboth\@gobbletwo + \let\chaptermark\@gobble + \let\sectionmark\@gobble + } + + \usepackage{multicol} + +\def\ps@indexplain{\let\@mkboth\@gobbletwo + \let\@oddhead\@empty\def\@oddfoot{\reset@font\hspace{11pc}\fontsize{9.5}{12pt}\selectfont\sffamily\thepage + \hfil}\let\@evenhead\@empty\let\@evenfoot\@oddfoot} + + + \def\indexcolumns#1{\gdef\@indexcolumns{#1}} + \def\@indexcolumns{3} + +\renewenvironment{theindex} + {\if@twocolumn + \@restonecolfalse + \else + \@restonecoltrue + \fi + \columnseprule \z@ + \columnsep 18\p@%\columnsep 35\p@ + \@makeschapterhead{\hspace*{-6pc}\indexname}% + \addcontentsline{toc}{chapter}{\indexname}% + \@mkboth{\indexname}% + {\indexname}% + \thispagestyle{indexplain}% + \linewidth389.69pt\@totalleftmargin-41.32pt% + \begin{multicols}{\@indexcolumns}\fontsize{9}{11pt}\selectfont\rightskip0pt plus1fil\relax\parindent\z@ + \parskip\z@ \@plus .3\p@\relax + \let\item\@idxitem} + {\end{multicols}\clearpage} + +%%%%%%%%%%%%%%%%%% +% algorithm reference counter bugfix by Jan Blechta (algorithm reference counter is not increased) +\renewenvironment{algorithm}[ +1][\relax]{\refstepcounter{algorithm}% +\addcontentsline{loa}{algorithm}% + {\protect\numberline{Algorithm~\thealgorithm}{\ignorespaces#1}}% +\par\vspace{1\baselineskip}% +\expandafter\ifx#1\relax +\parindent0pt {\scshape\bfseries Algorithm~\thealgorithm.}\\%%% +\else +\parindent0pt {\scshape\bfseries +Algorithm~\thealgorithm.}\enspace{\bfseries#1.}\\%%% +\fi} +{\vspace{1\baselineskip}\par} +%%%%%%%%%%%%%%%%%% + +\def\@sect#1#2#3#4#5#6[#7]#8{% + \ifnum #2>\c@secnumdepth + \let\@svsec\@empty + \else + \refstepcounter{#1}% + \protected@edef\@svsec{\@seccntformat{#1}\relax}% + \fi + \@tempskipa #5\relax + \ifdim \@tempskipa>\z@ + \begingroup\let \\\@centercr \@rightskip \@flushglue \rightskip \@rightskip \leftskip -3.5pc \parindent \z@\relax + #6{% + \@hangfrom{\hskip #3\relax\@svsec}% + \interlinepenalty \@M #8\@@par}% + \endgroup + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7}% + \else + \def\@svsechd{% + #6{\hskip #3\relax + \@svsec #8}% + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7}}% + \fi + \@xsect{#5}} + + +\endinput +%% +%% End of file `book.cls'. + + + diff --git a/Shallow_water.ipynb b/Shallow_water.ipynb index bdc998db..c91ea211 100644 --- a/Shallow_water.ipynb +++ b/Shallow_water.ipynb @@ -2,20 +2,44 @@ "cells": [ { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "# The shallow water equations" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true, + "tags": [ + "hide" + ] }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'svg'\n", + "import matplotlib as mpl\n", + "mpl.rcParams['font.size'] = 8\n", + "figsize =(8,4)\n", + "mpl.rcParams['figure.figsize'] = figsize\n", + "\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from exact_solvers import shallow_water\n", + "from collections import namedtuple\n", + "from utils import riemann_tools\n", + "from ipywidgets import interact\n", + "from ipywidgets import widgets, FloatSlider, Checkbox, RadioButtons\n", + "State = namedtuple('State', shallow_water.conserved_variables)\n", + "Primitive_State = namedtuple('PrimState', shallow_water.primitive_variables)\n", + "g = 1." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ "In this chapter we study a model for shallow water waves in one dimension:\n", "\n", @@ -24,19 +48,14 @@ " (hu)_t + \\left(hu^2 + \\frac{1}{2}gh^2\\right)_x & = 0. \\label{SW_mom}\n", "\\end{align}\n", "\n", - "Here $h$ is the depth, $u$ is the velocity, and $g$ is a constant representing the force of gravity. These equations are a relatively simple but surprisingly effective model for water waves; they are bassed on several important physical assumptions; for instance, it ignores viscosity and compressibility, and assumes the pressure is hydrostatic. Nevertheless, it is a surprisingly effective model for many applications.\n", - "\n", - "Previously we have looked at a *linear hyperbolic system* (acoustics) and *scalar hyperbolic equations* (Burgers', traffic flow). The shallow water system is our first example of a *nonlinear hyperbolic system*; solutions of the Riemann problem will consist of multiple waves, each of which may be a shock or rarefaction.\n", + "Here $h$ is the depth, $u$ is the velocity, and $g$ is a constant representing the force of gravity. These equations are a relatively simple but surprisingly effective model for water waves; they are based on several important physical assumptions. For instance, viscosity and compressibility are neglected, and the pressure is assumed to be hydrostatic. Nevertheless, this is a surprisingly effective model for many applications.\n", "\n", - "The discussion here largely follows that of (Leveque, FVM, Chapter 13)." + "Previously we have looked at a *linear hyperbolic system* (acoustics) and *scalar hyperbolic equations* (advection, Burgers' equation, traffic flow). The shallow water system is our first example of a *nonlinear hyperbolic system*; solutions of the Riemann problem will consist of multiple waves, each of which may be a shock or rarefaction." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Hyperbolic structure\n", "We can write (\\ref{SW_mass})-(\\ref{SW_mom}) in the canonical form $q_t + f(q)_x = 0$ if we define\n", @@ -60,7 +79,7 @@ "\n", "Its eigenvalues are\n", "\n", - "\\begin{align}\n", + "\\begin{align} \\label{SW:char-speeds}\n", " \\lambda_1 & = u - \\sqrt{gh} & \\lambda_2 & = u + \\sqrt{gh},\n", "\\end{align}\n", "\n", @@ -71,42 +90,65 @@ " r_2 & = \\begin{bmatrix} 1 \\\\ u+\\sqrt{gh} \\end{bmatrix}\n", "\\end{align}\n", "\n", - "Notice that -- unlike for acoustics, but similar to the LWR traffic model -- the eigenvalues and eigenvectors depend on $q$. Because of this, the waves appearing in the Riemann problem move at different speeds and may be either jump discontinuities (shocks) or smoothly-varying regions (rarefactions)." + "Notice that -- unlike for acoustics, but similar to the LWR traffic model -- the eigenvalues and eigenvectors depend on $q$. Because of this, the waves appearing in the Riemann problem move at different speeds and may be either jump discontinuities (shocks) or smoothly-varying regions (rarefactions).\n", + "\n", + "Here we define a function for each wave speed, for use later." ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": { - "deletable": true, - "editable": true + "collapsed": true }, + "outputs": [], + "source": [ + "def lambda_1(q, xi, g=1.):\n", + " \"Characteristic speed for shallow water 1-waves.\"\n", + " h, hu = q\n", + " if h > 0:\n", + " u = hu/h\n", + " return u - np.sqrt(g*h)\n", + " else:\n", + " return 0\n", + "\n", + "def lambda_2(q, xi, g=1.):\n", + " \"Characteristic speed for shallow water 2-waves.\"\n", + " h, hu = q\n", + " if h > 0:\n", + " u = hu/h\n", + " return u + np.sqrt(g*h)\n", + " else:\n", + " return 0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ "## The Riemann problem\n", "Consider the Riemann problem with left and right states\n", "\n", "\\begin{align*}\n", - "q_l & = \\begin{bmatrix} h_l \\\\ h_r u_l \\end{bmatrix} &\n", + "q_l & = \\begin{bmatrix} h_l \\\\ h_r u_l \\end{bmatrix}, &\n", "q_r & = \\begin{bmatrix} h_r \\\\ h_r u_r \\end{bmatrix}. \n", "\\end{align*}\n", "\n", - "Typically the Riemann solution will consist of two waves, one related to each of the eigenvectors in \\eqref{SW:fjac-evecs}. Each wave may be a shock or rarefaction. There will be an intermediate state $q_m$ between them. Here we illustrate a typical situation, in which the 1-wave happens to be a rarefaction and the 2-wave is a shock:\n", + "Typically the Riemann solution will consist of two waves, one related to each of the eigenvectors in \\eqref{SW:fjac-evecs}. We refer to the wave related to $r_1$ (the first characteristic family) as a 1-wave and the wave related to $r_2$ (the second characteristic family) as a 2-wave. Each wave may be a shock or rarefaction. There will be an intermediate state $q_m$ between them. In the figure below, we illustrate a typical situation in which the 1-wave happens to be a rarefaction and the 2-wave is a shock:\n", "\n", "![Structure of Riemann solution](./figures/shallow_water_riemann.png)\n", "\n", - "In the sketch above we have one wave going in each direction, but since the wave speeds depend on $q$ and can have either sign, it is possible to have both waves going left, or both going right.\n", + "In the figure we have one wave going in each direction, but since the wave speeds depend on $q$ and can have either sign, it is possible to have both waves going left, or both going right.\n", "\n", "To solve the Riemann problem, we must find $q_m$. To do so we must find a state that can be connected to $q_l$ by a 1-shock or 1-rarefaction and to $q_r$ by a 2-shock or 2-rarefaction. We must also ensure that the resulting waves satisfy the entropy condition." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# Shock waves\n", - "Let us now consider a shock wave connecting a known state $q_*=(h_*, h_* u_*)$ to an unknown state $q=(h,hu)$. In the context of the Riemann problem $q_*$ will be the left or right state and $q$ will be the middle state.\n", + "## Shock waves\n", + "Let us now consider a shock wave connecting a known state $q_*=(h_*, h_* u_*)$ to an unknown state $q=(h,hu)$. In the context of the Riemann problem, $q_*$ will be the initial left or right state and $q$ will be the middle state.\n", "The Rankine-Hugoniot jump conditions $s(q_r - q_l) = f(q_r) - f(q_l)$ for a shock wave moving\n", "at speed $s$ read\n", "\n", @@ -127,42 +169,15 @@ " s & = \\frac{h_* u_* - h u}{h_* - h} = u_* \\mp \\sqrt{gh_* \\left(1+\\frac{\\alpha}{h_*}\\right)\\left(1+\\frac{\\alpha}{2h_*}\\right)} = u_* \\mp \\sqrt{gh \\frac{h_* + h}{2h_*} }\n", "\\end{align}\n", "\n", - "Choosing the plus sign in \\eqref{SW:hugoniot-locus} (which yields the minus sign in \\eqref{SW:shock-speed}) gives a 1-shock. Choosing the minus sign in \\eqref{SW:hugoniot-locus} (which yields the plus sign in \\eqref{SW:shock-speed}) gives a 2-shock. Notice from the last expression in \\eqref{SW:shock-speed} that as $h \\to h^*$ the shock speed approaches the corresponding characteristic speed, while the ratio of the jumps in momentum and depth approaches that suggested by the eigenvectors \\eqref{SW:fjac-evecs}.\n", + "Choosing the plus sign in \\eqref{SW:hugoniot-locus} (which yields the minus sign in \\eqref{SW:shock-speed}) gives a 1-shock. Choosing the minus sign in \\eqref{SW:hugoniot-locus} (which yields the plus sign in \\eqref{SW:shock-speed}) gives a 2-shock. Notice from the last expression in \\eqref{SW:shock-speed} that as $h \\to h^*$ the shock speed approaches the corresponding characteristic speed \\eqref{SW:char-speeds}, while the ratio of the jumps in momentum and depth approaches that suggested by the eigenvectors \\eqref{SW:fjac-evecs}.\n", "\n", - "We can now consider the set of all possible states $(h, h u)$ given by \\eqref{SW:hugoniot-locus}. This curve in the $h - hu$ plane is known as the hugoniot locus; there is a family of hugoniot loci for 1-shocks and another for 2-shocks. Below we plot some members of these two families of curves." + "We can now consider the set of all possible states $(h, h u)$ satisfying \\eqref{SW:hugoniot-locus}. This curve in the $h - hu$ plane is known as the hugoniot locus; there is a family of hugoniot loci for 1-shocks and another for 2-shocks. Below we plot some members of these two families of curves." ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from exact_solvers import shallow_water\n", - "from collections import namedtuple\n", - "from utils import riemann_tools\n", - "from ipywidgets import interact, widgets\n", - "State = namedtuple('State', shallow_water.conserved_variables)\n", - "Primitive_State = namedtuple('PrimState', shallow_water.primitive_variables)\n", - "plt.style.use('seaborn-talk')\n", - "g = 1." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "interact(shallow_water.plot_hugoniot_loci,y_axis=widgets.fixed('hu'));" @@ -170,10 +185,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "The plot above shows the Hugoniot loci in the $h$-$hu$ plane, the natural phase plane in terms of the two conserved quantities. Note that they all approach the origin as $h \\rightarrow 0$. Alternatively, we can plot these same curves in the $h$-$u$ plane:" ] @@ -181,11 +193,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "interact(shallow_water.plot_hugoniot_loci,y_axis=widgets.fixed('u'));" @@ -193,22 +201,16 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "Note that in this plane, the curves in each family are simply vertical translates of one another, and all curves asymptote to $\\pm \\infty$ as $h \\rightarrow 0$." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## All-shock Riemann solutions\n", + "### All-shock Riemann solutions\n", "If we knew *a priori* that both waves in the Riemann solution were shock waves, we could find $q_m$ by finding the intersection of the 1-Hugoniot locus passing through $q_l$ with the 2-Hugoniot locus passing through $q_r$. The Riemann solution would then consist simply of two discontinuities propagating at the speeds given by \\eqref{SW:shock-speed}.\n", "\n", "Here is an example for which this is the correct solution." @@ -217,71 +219,41 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [], - "source": [ - "def c1(q, xi, g=1.):\n", - " \"Characteristic speed for shallow water 1-waves.\"\n", - " h = q[0]\n", - " if h > 0:\n", - " u = q[1]/q[0]\n", - " return u - np.sqrt(g*h)\n", - " else:\n", - " return 0\n", - "\n", - "def c2(q, xi, g=1.):\n", - " \"Characteristic speed for shallow water 2-waves.\"\n", - " h = q[0]\n", - " if h > 0:\n", - " u = q[1]/q[0]\n", - " return u + np.sqrt(g*h)\n", - " else:\n", - " return 0" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "def make_plot_function(q_l,q_r,g=1.,force_waves=None,extra_lines=None):\n", - " states, speeds, reval, wave_types = shallow_water.exact_riemann_solution(q_l,q_r,g,force_waves=force_waves)\n", + " states, speeds, reval, wave_types = \\\n", + " shallow_water.exact_riemann_solution(q_l,q_r,g,\n", + " force_waves=force_waves)\n", " def plot_function(t,plot_1_chars=False,plot_2_chars=False):\n", - " ax = riemann_tools.plot_riemann(states,speeds,reval,wave_types,t=t,t_pointer=0,\n", - " extra_axes=True,variable_names=shallow_water.conserved_variables,\n", + " ax = riemann_tools.plot_riemann(states,speeds,reval,wave_types,\n", + " t=t,t_pointer=0,extra_axes=True,\n", + " variable_names=shallow_water.conserved_variables,\n", " fill=[0]);\n", " if plot_1_chars:\n", - " riemann_tools.plot_characteristics(reval,c1,axes=ax[0],extra_lines=extra_lines)\n", + " riemann_tools.plot_characteristics(reval,lambda_1,axes=ax[0],\n", + " extra_lines=extra_lines)\n", " if plot_2_chars:\n", - " riemann_tools.plot_characteristics(reval,c2,axes=ax[0],extra_lines=extra_lines)\n", - " shallow_water.phase_plane_plot(q_l,q_r,g,ax=ax[3],force_waves=force_waves,y_axis='u')\n", + " riemann_tools.plot_characteristics(reval,lambda_2,axes=ax[0],\n", + " extra_lines=extra_lines)\n", + " shallow_water.phase_plane_plot(q_l,q_r,g,ax=ax[3],\n", + " force_waves=force_waves,y_axis='u')\n", " plt.show()\n", " return plot_function\n", "\n", "def plot_riemann_SW(q_l,q_r,g=1.,force_waves=None,extra_lines=None):\n", " plot_function = make_plot_function(q_l,q_r,g,force_waves,extra_lines)\n", " interact(plot_function, t=widgets.FloatSlider(value=0.,min=0,max=.9),\n", - " plot_1_chars=widgets.Checkbox(description='1-characteristics',value=False),\n", - " plot_2_chars=widgets.Checkbox(description='2-characteristics'))" + " plot_1_chars=Checkbox(description='1-characteristics',\n", + " value=False),\n", + " plot_2_chars=Checkbox(description='2-characteristics'))" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "q_l = State(Depth = 1.,\n", @@ -295,88 +267,72 @@ { "cell_type": "markdown", "metadata": { - "deletable": true, - "editable": true + "tags": [ + "online-instructions" + ] }, "source": [ - "Check the boxes to plot the characteristic families, and notice that the 1-characteristics impinge on the 1-shock; the 2-characteristics impinge on the 2-shock. Thus these shocks satisfy the entropy condition." + "*Check the boxes to plot the characteristic families, and notice that the 1-characteristics impinge on the 1-shock; the 2-characteristics impinge on the 2-shock. Thus these shocks satisfy the entropy condition.*" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "### Dam-break problem: all-shock solution\n", + "#### Dam-break problem: all-shock solution\n", "Here's another example, which you might think of as modeling a dam that suddenly breaks. The water is initially at rest on both sides, but much deeper on the left." ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "q_l = State(Depth = 4.,\n", " Momentum = 0.)\n", "q_r = State(Depth = 1.,\n", " Momentum = 0.)\n", - "plot_riemann_SW(q_l,q_r,force_waves='shock',extra_lines=[[[0,0],[-1.317,1.]]]);" + "plot_riemann_SW(q_l,q_r,force_waves='shock',\n", + " extra_lines=[[[0,0],[-1.317,1.]]]);" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "Check the box to plot the 1-characteristics. Notice that they don't impinge on the 1-shock; instead, characteristics are diverging away from it. This shock does not satisfy the entropy condition and should be replaced with a rarefaction. The corresponding part of the Hugoniot locus is plotted with a dashed line to remind us that it is unphysical.\n", + "*Check the box to plot the 1-characteristics.* Notice that they don't impinge on the 1-shock; instead, characteristics are diverging away from it. This shock does not satisfy the entropy condition and should be replaced with a rarefaction. The corresponding part of the Hugoniot locus is plotted with a dashed line to remind us that it is unphysical.\n", "\n", - "Now check the box to plot the 2-characteristics. Notice that these *do* impinge on the 2-shock; this is an entropy-satisfying shock, and the Hugoniot locus is plotted as a solid line." + "*Now check the box to plot the 2-characteristics.* Notice that these *do* impinge on the 2-shock; this is an entropy-satisfying shock, and the Hugoniot locus is plotted as a solid line." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## The entropy condition\n", + "### The entropy condition\n", "To be physically correct, each of these waves must satisfy the Lax entropy condition. Notice that the shock speed \\eqref{SW:shock-speed} can be written as\n", "\n", "\\begin{align}\n", " s & = u_* \\pm \\sqrt{gh \\frac{h_* + h}{2h_*} }\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "Thus the 1-shock entropy condition reads\n", "\n", "\\begin{align*}\n", "u_l - \\sqrt{gh_l} > u_l - \\sqrt{gh_l \\frac{h_l+h_m}{2h_l}} = u_m - \\sqrt{gh_m \\frac{h_m+h_l}{2h_m}} > u_m - \\sqrt{gh_m}.\n", - "\\end{align*}\n", - "\n", + "\\end{align*} \n", "The second expression for the shock speed is obtained by noticing\n", "that the shock speed is invariant under transposition of the left and right states.\n", - "\n", "The first and second inequalities both simplify to\n", "\n", "\\begin{align} \\label{SW:1-entropy}\n", " h_m > h_l.\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "Similarly, it can be shown that the entropy condition for a 2-shock connecting $q_m$ and $q_r$ is satisfied if and only if\n", "\n", "\\begin{align} \\label{SW:2-entropy}\n", " h_m > h_r.\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "If \\eqref{SW:1-entropy} or \\eqref{SW:2-entropy} is violated, then the\n", "corresponding wave must be a rarefaction rather than a shock.\n", "\n", @@ -385,14 +341,11 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# Rarefaction waves\n", + "## Rarefaction waves\n", "\n", - "## Integral curves\n", + "### Integral curves\n", "In the LWR traffic flow model, we saw that a rarefaction wave\n", "consisted of a smoothly-varying density. For the shallow water\n", "system, both the depth $h$ and the momentum $hu$ will vary smoothly\n", @@ -412,8 +365,7 @@ "\\begin{align}\n", " h'(\\xi) = q_1'(\\xi) & = 1 \\label{SW:dh} \\\\\n", " (hu)'(\\xi) = q_2'(\\xi) & = u \\pm \\sqrt{gh} = \\tilde{q}_2/\\tilde{q}_1 - \\sqrt{g\\tilde{q}_1}, \\label{SW:dhu}\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "where we take the minus sign for 1-waves and the plus sign for 2-waves.\n", "We can think of \\eqref{SW:dh}-\\eqref{SW:dhu} as an initial value ODE;\n", "fixing the value of $\\tilde{q}$ at one point in the rarefaction wave\n", @@ -423,44 +375,33 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "For the shallow water system, these equations can be integrated exactly. If we fix one point $(h_*, h_*u_*)$ on the curve, the whole integral curve is defined by\n", "\n", "\\begin{align}\n", " hu & = hu_* \\pm 2h(\\sqrt{gh_*} - \\sqrt{gh}).\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "where now the plus sign is for 1-waves and the minus sign for 2-waves.\n", "This can be rewritten as\n", "\n", "\\begin{align} \\label{SW:riemann-invariant}\n", "u \\pm 2 \\sqrt{gh} = u_* \\pm 2 \\sqrt{gh_*}.\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "From \\eqref{SW:riemann-invariant} we see that the value $u + 2 \\sqrt{gh}$\n", "is constant along any 1-integral curve, while the value $u-2\\sqrt{gh}$ is constant along any 2-integral curve. We refer to these quantities as *Riemann invariants* for the shallow water system:\n", "\n", "\\begin{align}\n", "w_1(q) & = u + 2 \\sqrt{gh} \\\\\n", "w_2(q) & = u - 2 \\sqrt{gh}.\n", - "\\end{align}\n", - "\n", - "In other words, the trajectories plotted above are just the level curves of $w_1$ and $w_2$. \n", - "This allows us to easily plot the integral curves as a contour plot of $w_1$ or $w_2$:" + "\\end{align} \n", + "In other words, the trajectories plotted above are just the level curves of $w_1$ and $w_2$. This allows us to easily plot the integral curves as a contour plot of $w_1$ or $w_2$:" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "def plot_int_curves(plot_1=True,plot_2=False,y_axis='hu'):\n", @@ -497,10 +438,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "We can also plot the integral curves in the $h$--$u$ plane:" ] @@ -508,11 +446,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "interact(plot_int_curves, y_axis=widgets.fixed('u'),\n", @@ -522,33 +456,23 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "Note that in this plane the integral curves of each family are simply vertical translates of one another due to the form of the functions $w_1$ and $w_2$. Unlike the Hugoniot loci, the integral curves do not asymptote to $\\pm\\infty$ as $h \\rightarrow 0$ and instead approach a finite value. " ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## Comparison of integral curves and Hugoniot loci\n", - "You may have noticed that the integral curves look very similar to the Hugoniot loci, especially when plotted in the $h-hu$ plane. Below we plot the curve from each of these families that passes through a specified point. This divergence is less noticeable in the $h-hu$ plane since all of the curves approach the origin." + "### Comparison of integral curves and Hugoniot loci\n", + "You may have noticed that the integral curves look very similar to the Hugoniot loci, especially when plotted in the $h-hu$ plane. Below we emphasize the differences by plotting the curve from each of these families that passes through a specified point. The difference is less noticeable in the $h-hu$ plane since all of the curves approach the origin." ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "def compare_curves(wave_family=1, h0=1., u0=0., y_axis='u'):\n", @@ -561,35 +485,32 @@ " plt.legend(['Integral curve','Hugoniot locus'])\n", " if y_axis == 'u':\n", " plt.plot(h0,u0,'ok')\n", + " plt.ylabel('velocity (u)')\n", " else:\n", " plt.plot(h0,h0*u0,'ok')\n", + " plt.ylabel('momentum (hu)')\n", + " plt.xlabel('depth h')\n", " plt.show()\n", " \n", "interact(compare_curves,\n", - " wave_family=widgets.RadioButtons(options=[1,2],description='Wave family:'),\n", - " y_axis=widgets.RadioButtons(options=['u','hu'],description='Vertical axis:'),\n", - " h0=widgets.FloatSlider(min=1.e-1,max=3.,value=1.,description='$h_*$'),\n", - " u0=widgets.FloatSlider(min=-3,max=3,description='$u_*$'));" + " wave_family=RadioButtons(options=[1,2],description='Wave family:'),\n", + " y_axis=RadioButtons(options=['u','hu'],description='Vertical axis:'),\n", + " h0=FloatSlider(min=1.e-1,max=3.,value=1.,description='$h_*$'),\n", + " u0=FloatSlider(min=-3,max=3,description='$u_*$'));" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "Near the point of intersection, the curves are very close; indeed, they must be tangent at this point since their direction is parallel to the corresponding eigenvector there. Far from this point they diverge; for small depths they must diverge greatly, since the Hugoniot locus never reaches $h=0$ at any finite velocity." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## The structure of centered rarefaction waves\n", + "### The structure of centered rarefaction waves\n", "Rarefactions appearing in the Riemann solution are also similarity solutions; that is they are constant along any ray $\\xi=x/t$. For a $p$-rarefaction connecting states $q_\\ell$ and $q_r$, the rarefaction thus has the form\n", "\n", "\\begin{align}\n", @@ -608,32 +529,26 @@ "\n", "\\begin{align} \\label{SW:char-sim1}\n", "\\tilde{h} = \\frac{(\\tilde{u}-\\xi)^2}{g}.\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "Meanwhile, the fact that $w_1(\\tilde{q})$ is constant means that\n", "\n", "\\begin{align} \\label{SW:w1-const}\n", " \\tilde{u} + 2 \\sqrt{g\\tilde{h}} = u_\\ell + 2 \\sqrt{gh_\\ell}.\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "Combining \\eqref{SW:char-sim1} with \\eqref{SW:w1-const}, we find\n", "\n", "\\begin{align} \\label{SW:1-raref-struct-h}\n", " \\tilde{h} & = \\frac{(u_\\ell + 2\\sqrt{gh_\\ell} - \\xi)^2}{9g} = \\frac{(w_1(q_l) - \\xi)^2}{9g} \\\\\n", " \\tilde{u} & = \\frac{1}{3}w_1(q_l) + \\frac{2}{3}\\xi. \\label{SW:1-raref-struct-u}\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "We see that $h$ varies quadratically through the rarefaction, while $u$ varies linearly." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "## Connecting states\n", + "### Connecting states\n", "Suppose we know that the middle state $q_m$ is connected to the left and right states by rarefactions. Then we can find $q_m$ by finding the intersection of the corresponding integral curves. Here is an example for which this is the physically correct solution:\n", "\n", "\\begin{align}\n", @@ -645,11 +560,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "q_l = State(Depth = 1.,\n", @@ -661,10 +572,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "Notice that the segment of each integral curve that connects to states with a smaller depth is plotted as a solid line, while the segment connecting to states with greater depth is plotted with a dashed line. This again is to remind us that states connected by a rarefaction through the solid part are physical (entropy-satisfying), while states connected by the dashed part would be unphysical (entropy-violating)." ] @@ -672,32 +580,26 @@ { "cell_type": "markdown", "metadata": { - "deletable": true, - "editable": true + "tags": [ + "online-instructions" + ] }, "source": [ - "Try changing the velocities to $(2, -2)$, and notice that the Riemann solution has a state with almost zero depth in the middle. What happens if you use even larger outflow velocities? We'll discuss this later, in the section on dry states." + "*Try changing the velocities to $(2, -2)$, and notice that the Riemann solution has a state with almost zero depth in the middle. What happens if you use even larger outflow velocities? We'll discuss this later, in the section on dry states.*" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "### Dam-break problem: all-rarefaction solution\n", - "Next let us revisit the problem above where we found that the all-shock solution was incorrect. This time we'll try to find an all-rarefaction solution." + "Next let us revisit the problem from [the section above](Shallow_water.ipynb#Dam-break-problem:-all-shock-solution) where we found that the all-shock solution was incorrect. This time we'll try to find an all-rarefaction solution." ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "q_l = State(Depth = 4.,\n", @@ -709,49 +611,36 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "Plot the 2-characteristics and notice that they cross each other within the 2-rarefaction. This means that the solution we constructed is triple-valued and nonsensical as a solution to this one-dimensional conservation law, and so this portion of the solution is omitted in the plots of depth and momentum. In this case a rarefaction wave is not physical and should be replaced with a shock; the corresponding part of the integral curve is hence shown as a dashed line." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "# The Riemann solution\n", - "To determine $q_m$, we need to know whether each of the two waves is a shock or rarefaction, so that we can use the appopriate Hugoniot locus or integral curve. But to determine the nature of each wave, we need to check \\eqref{SW:1-entropy} or \\eqref{SW:2-entropy}, which requires knowledge of $h_m$. To deal with this is we define a piecewise function $\\phi_l(h)$ that gives:\n", + "## The Riemann solution\n", + "To determine $q_m$, we need to know whether each of the two waves is a shock or rarefaction, so that we can use the appopriate Hugoniot locus or integral curve. But to determine the nature of each wave, we need to check \\eqref{SW:1-entropy} or \\eqref{SW:2-entropy}, which requires knowledge of $h_m$. To deal with this we define a piecewise function $\\phi_l(h)$ that gives:\n", "\n", "- for $h>h_l$, the momentum connected to $q_l$ by a 1-shock;\n", "- for $h(Lighthill, 1955) and (Richards, 1956)). This model and the corresponding Riemann problem are discussed in many places; the discussion here is most closely related to that in Chapter 11 of (LeVeque, 2002)." ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "In this chapter we investigate a conservation law that models the flow of traffic. This model is sometimes referred to as the Lighthill-Whitham-Richards (or LWR) traffic model (see (Lighthill, 1955) and (Richards, 1956)). This model and the corresponding Riemann problem are discussed in many places; the discussion here is most closely related to that in Chapter 11 of (LeVeque, 2002).\n", - "\n", + "## The LWR model\n", "Recall the continuity equation:\n", "\n", "$$\\rho_t + (u\\rho)_x = 0.$$\n", @@ -54,20 +59,14 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ - "![](./figures/LWR-Velocity.png)" + "![Velocity as a function of density in the LWR traffic model.](./figures/LWR-Velocity.png)" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "Combining the two equations above, our conservation law says\n", "\n", @@ -79,11 +78,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "rho = np.linspace(0,1)\n", @@ -95,10 +90,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "This equation is fundamentally different from the advection equation because the flux is **nonlinear**. This fact will have dramatic consequences for both the behavior of solutions and our numerical methods. But we can superficially make this equation look like the advection equation by using the chain rule to write\n", "\n", @@ -113,14 +105,16 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Example: Traffic jam\n", "\n", - "What does our model predict when traffic approaches a totally congested ($\\rho=1$) area? This might be due to construction, an accident or a red light somewhere to the right; upstream of the obstruction, cars will be bumper-to-bumper, so we set $\\rho=1$ for $x>0$ (supposing that traffic has backed up to that point). For $x<0$ we'll assume a lower density $\\rho_l<1$. This is another example of a Riemann problem: two constant states separated by a discontinuity.\n", + "What does our model predict when traffic approaches a totally congested ($\\rho=1$) area? This might be due to construction, an accident or a red light somewhere to the right; upstream of the obstruction, cars will be bumper-to-bumper, so we set $\\rho=1$ for $x>0$ (supposing that traffic has backed up to that point). For $x<0$ we'll assume a lower density $\\rho_l<1$. This is another example of a Riemann problem: two constant states separated by a discontinuity. We have\n", + "\n", + "$$\n", + "\\rho(x,t=0) = \\begin{cases} \\rho_l & x<0 \\\\\n", + " 1 & x>0. \\end{cases}\n", + "$$\n", "\n", "What will happen as time goes forward? Intuitively, we expect traffic to continue backing up to the left, so the region with $\\rho=1$ will extend further and further to the left. This corresponds to the discontinuity (or shock wave) moving to the left. How quickly will it move? The example below shows the solution (on the left) and individual vehicle trajectories in the $x-t$ plane (on the right)." ] @@ -128,44 +122,40 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ - "def jam(rho_l=0.2,t=0.1):\n", + "def jam(rho_l=0.4,t=0.1):\n", " shock_speed = -rho_l\n", " shock_location = t*shock_speed\n", - " fig, axes = plt.subplots(1,2,figsize=(14,4))\n", + " fig, axes = plt.subplots(1,2,figsize=figsize)\n", " \n", " axes[0].plot([-1,shock_location],[rho_l,rho_l],'k',lw=2)\n", " axes[0].plot([shock_location,shock_location],[rho_l,1.],'k',lw=2)\n", " axes[0].plot([shock_location,1.],[1.,1.],'k',lw=2)\n", - " axes[0].set_xlabel('$x$'); axes[0].set_ylabel(r'$\\rho$'); axes[0].set_xlim(-1,1); axes[0].set_ylim(0,1.1)\n", - " traffic_LWR.plot_car_trajectories(rho_l,1.,axes[1]); axes[1].set_ylim(0,1)\n", + " axes[0].set_xlabel('$x$'); axes[0].set_ylabel(r'$\\rho$'); \n", + " axes[0].set_xlim(-0.2,0.2); axes[0].set_ylim(0,1.1)\n", + " traffic_LWR.plot_car_trajectories(rho_l,1.,axes[1]); \n", + " axes[1].set_ylim(0,1); axes[0].set_title(r'$t= $'+str(t))\n", + " plt.xlabel('$x$'); plt.ylabel(r'$t$');\n", " plt.show()\n", " \n", "interact(jam,\n", - " rho_l=widgets.FloatSlider(min=0.,max=0.9,value=0.2,description=r'$\\rho_l$'),\n", - " t=widgets.FloatSlider(min=0.,max=1.));" + " rho_l=FloatSlider(min=0.,max=0.9,value=0.2,description=r'$\\rho_l$'),\n", + " t=FloatSlider(min=0.,max=1.,value=0.2));" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Speed of a shock wave: the Rankine-Hugoniot conditions\n", "\n", - "In the plot above, you should have seen a shock wave (i.e., a discontinuity) that moves to the left as more and more cars pile up behind the traffic jam. How quickly does this discontinuity move to the left?\n", + "In the plot above, you see a shock wave (i.e., a discontinuity) that moves to the left as more and more cars pile up behind the traffic jam. How quickly does this discontinuity move to the left?\n", "\n", "We can figure it out by putting an imaginary line at the location of the shock. Let $\\rho_l$ be the density of cars just to the left of the line, and let $\\rho_r$ be the density of cars just to the right. Imagine for a moment that the line is stationary. Then the rate of cars reaching the line from the left is $f(\\rho_l)$ and the rate of cars departing from the line to the right is $f(\\rho_r)$. If the line really were stationary, we would need to have $f(\\rho_l)-f(\\rho_r)=0$ to avoid cars accumulating at the line.\n", "\n", - "![](./figures/shock_diagram_traffic_a.png)\n", + "![Rate of cars entering and emerging from the shock. If the shock is stationary, these will be unequal.](./figures/shock_diagram_traffic_a.png)\n", "\n", "However, the shock is not stationary, so the line is moving. Let $s$ be the speed of the shock. Then as the line moves to the left, some cars that were to the left are now to the right of the line. The rate of cars removed from the left is $s \\rho_l$ and the rate of cars added on the right is $s \\rho_r$. So in order to avoid an accumulation of cars at the shock, these two effects need to be balanced:\n", "\n", @@ -173,15 +163,12 @@ "\n", "This condition is known as the **Rankine-Hugoniot condition**, and it holds for any shock wave in the solution of any hyperbolic system!\n", "\n", - "![](./figures/shock_diagram_traffic_b.png)" + "![The shock moves at just the necessary rate so that the same number of cars arrive from the left and emerge to the right.](./figures/shock_diagram_traffic_b.png)" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "Returning to our traffic jam scenario, we set $\\rho_r=1$. Then we find that\n", "\n", @@ -197,7 +184,14 @@ "## Example: green light\n", "\n", "What about when a traffic light turns green? At $t=0$, when the light changes, there will be a discontinuity with\n", - "traffic backed up behind the light but little or no traffic after the light. In this case we don't expect the same discontinuity to propagate. Physically, the reason is clear: after the light turns green, the cars in front accelerate and spread out; then the cars behind them accelerate, and so forth. This kind of expansion wave is referred to as a *rarefaction wave* because the drivers experience a decrease in density (a rarefaction) as they pass through this wave. Initially, the solution is discontinuous, but after time zero it becomes continuous." + "traffic backed up behind the light but little or no traffic after the light. With the light at $x=0$, this takes the form of another Riemann problem:\n", + "\n", + "$$\n", + "\\rho(x,t=0) = \\begin{cases} 1 & x<0 \\\\\n", + " \\rho_r & x>0. \\end{cases}\n", + "$$\n", + "\n", + "In this case we don't expect the same discontinuity to propagate. Physically, the reason is clear: after the light turns green, the cars in front accelerate and spread out; then the cars behind them accelerate, and so forth. This kind of expansion wave is referred to as a *rarefaction wave* because the drivers experience a decrease in density (a rarefaction) as they pass through this wave. Initially, the solution is discontinuous, but after time zero it becomes continuous." ] }, { @@ -205,7 +199,7 @@ "metadata": {}, "source": [ "## Similarity solutions\n", - "The exact form of the solution at a green light can be determined if we assume that the solution $\\rho(x,t)$ depends only on $x/t$. This is referred to as a *similarity solution*; in fact, the solution of any Riemann problem is a similarity solution. Writing $\\rho(x,t) = \\tilde{\\rho}(x/t)$ we have (with $\\xi = x/t$):\n", + "The exact form of the solution at a green light can be determined by assuming that the solution $\\rho(x,t)$ depends only on $x/t$. A solution with this property is referred to as a *similarity solution*, because it is remains the same if we rescale both $x$ and $t$ by the same factor. The solution of any Riemann problem is, in fact, a similarity solution. Writing $\\rho(x,t) = \\tilde{\\rho}(x/t)$ we have (with $\\xi = x/t$):\n", "\n", "\\begin{align*}\n", " \\rho_t & = -\\frac{x}{t^2}\\tilde{\\rho}'(\\xi) & \\rho_x & = \\frac{1}{t}\\tilde{\\rho}'(\\xi) f'(\\tilde{\\rho}(\\xi)).\n", @@ -236,10 +230,7 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "The plot below shows the solution density and vehicle trajectories for a green light at $x=0$." ] @@ -247,48 +238,42 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, + "metadata": {}, "outputs": [], "source": [ "def green_light(rho_r=0.,t=0.1):\n", " rho_l = 1.\n", " left_edge = -t\n", " right_edge = -t*(2*rho_r - 1)\n", - " fig, axes = plt.subplots(1,2,figsize=(14,4))\n", + " fig, axes = plt.subplots(1,2,figsize=figsize)\n", " axes[0].plot([-1,left_edge],[rho_l,rho_l],'k',lw=2)\n", " axes[0].plot([left_edge,right_edge],[rho_l,rho_r],'k',lw=2)\n", " axes[0].plot([right_edge,1.],[rho_r,rho_r],'k',lw=2)\n", - " axes[0].set_xlabel('$x$'); axes[0].set_ylabel(r'$\\rho$'); axes[0].set_xlim(-1,1); axes[0].set_ylim(0,1.1)\n", - "\n", - " plt.xlabel('$x$'); plt.ylabel(r'$t$'); plt.xlim(-1,1); plt.ylim(-0.1,1.1)\n", - "\n", - " traffic_LWR.plot_car_trajectories(1.,rho_r,axes[1],t=t,xmax=1.); axes[1].set_ylim(0,1)\n", + " axes[0].set_xlabel('$x$'); axes[0].set_ylabel(r'$\\rho$');\n", + " axes[0].set_xlim(-1,1); axes[0].set_ylim(-0.1,1.1)\n", + " plt.xlabel('$x$'); plt.ylabel(r'$t$');\n", + " \n", + " traffic_LWR.plot_car_trajectories(1.,rho_r,axes[1],t=t,xmax=1.); \n", + " axes[1].set_ylim(0,1)\n", " plt.show() \n", "\n", "interact(green_light,\n", - " rho_r=widgets.FloatSlider(min=0.,max=0.9,value=0.,description=r'$\\rho_r$'),\n", - " t=widgets.FloatSlider(min=0.,max=1.));" + " rho_r=FloatSlider(min=0.,max=0.9,value=0.,description=r'$\\rho_r$'),\n", + " t=FloatSlider(min=0.,max=1.));" ] }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "How can we determine whether an initial discontinuity will lead to a shock or a rarefaction?\n", "- Shocks appear in regions where characteristics overlap:\n", "\n", - "![](./figures/entropy_condition_shock.png)\n", + "![Shocks appear in regions where characteristics overlap.](./figures/entropy_condition_shock.png)\n", "\n", "- Rarefactions appear in regions where characteristics are spreading out:\n", "\n", - "![](./figures/entropy_condition_rarefaction.png)\n", + "![Rarefactions appear in regions where characteristics are spreading out.](./figures/entropy_condition_rarefaction.png)\n", "\n", "More precisely, if the value to the left of a shock is $\\rho_l$ and the value to the right is $\\rho_r$, then it must be that $f'(\\rho_l)>f'(\\rho_r)$. In fact the shock speed must lie between these characteristic speeds:\n", "\n", @@ -301,23 +286,18 @@ }, { "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, + "metadata": {}, "source": [ "## Interactive Riemann solution\n", "\n", - "The cell below generates a plot that shows the Riemann solution for any inputs $(\\rho_l,\\rho_r)$." + "The code in the next cell solves the Riemann problem for any inputs $(\\rho_l,\\rho_r)$. It returns a function `reval(xi)` that gives the value of the Riemann solution along any characteristic $\\xi=x/t$." ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false, - "deletable": true, - "editable": true + "collapsed": false }, "outputs": [], "source": [ @@ -349,8 +329,6 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Interactive Riemann solution\n", - "\n", "The cell below generates a plot that shows the Riemann solution, along with characteristics and vehicle trajectories, for any inputs $(\\rho_l,\\rho_r)$." ] }, @@ -365,18 +343,21 @@ " return 1.-2*rho\n", "\n", "def plot_riemann_traffic(rho_l,rho_r,t):\n", - " states, speeds, reval, wave_types = traffic_LWR.riemann_traffic_exact(rho_l,rho_r)\n", - " ax = riemann_tools.plot_riemann(states,speeds,reval,wave_types,t=t,t_pointer=0,\n", - " extra_axes=True,variable_names=['Density']);\n", - " ax[1].set_ylim(-0.05,1.05)\n", + " states, speeds, reval, wave_types = \\\n", + " traffic_LWR.riemann_traffic_exact(rho_l,rho_r)\n", + " ax = riemann_tools.plot_riemann(states,speeds,reval,\n", + " wave_types,t=t,\n", + " t_pointer=0,extra_axes=True,\n", + " variable_names=['Density']);\n", " riemann_tools.plot_characteristics(reval,c,axes=ax[0])\n", - " traffic_LWR.plot_car_trajectories(rho_l,rho_r,ax[2],t=t,xmax=1.); ax[2].set_ylim(0,1)\n", + " traffic_LWR.plot_car_trajectories(rho_l,rho_r,ax[2],t=t,xmax=1.);\n", + " ax[1].set_ylim(-0.05,1.05); ax[2].set_ylim(0,1)\n", " plt.show() \n", "\n", "interact(plot_riemann_traffic,\n", - " rho_l=widgets.FloatSlider(min=0.,max=1.,value=0.5,description=r'$\\rho_l$'),\n", - " rho_r=widgets.FloatSlider(min=0.,max=1.,description=r'$\\rho_r$'),\n", - " t = widgets.FloatSlider(min=0.,max=1.,value=0.1));" + " rho_l=FloatSlider(min=0.,max=1.,value=0.5,description=r'$\\rho_l$'),\n", + " rho_r=FloatSlider(min=0.,max=1.,description=r'$\\rho_r$'),\n", + " t=FloatSlider(min=0.,max=1.,value=0.1));" ] }, { diff --git a/Traffic_variable_speed.ipynb b/Traffic_variable_speed.ipynb index c10873d6..5a9df801 100644 --- a/Traffic_variable_speed.ipynb +++ b/Traffic_variable_speed.ipynb @@ -7,6 +7,38 @@ "# LWR Traffic flow with varying speed limit" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "hide" + ] + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'svg'\n", + "import matplotlib as mpl\n", + "mpl.rcParams['font.size'] = 8\n", + "figsize =(8,4)\n", + "mpl.rcParams['figure.figsize'] = figsize\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from ipywidgets import interact\n", + "from ipywidgets import widgets, FloatSlider\n", + "from utils import riemann_tools\n", + "from exact_solvers import traffic_variable_speed" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The model" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -15,16 +47,15 @@ "\n", "\\begin{align} \\label{LWR_vc:conslaw}\n", "\\rho_t + (v(x) \\rho(1-\\rho))_x = 0.\n", - "\\end{align}\n", - "\n", - "In the previous chapter, the speed limit was set to unity everywhere. The variable-speed-limit case has been considered, for instance, in (Mochon, 1987) and in Chapter 16 of (LeVeque, 2002). From a physical point of view, we might also imagine that $u_\\text{max}$ varies because of differing road conditions -- for instance, if part of the road is wet or foggy.\n", - "\n", - "Now we consider the Riemann problem with different speed limits to the left and right:\n", + "\\end{align} \n", + "and we consider the Riemann problem with different speed limits to the left and right:\n", "\n", "$$\n", - "v(x) = \\begin{cases} v_l & x<0 \\\\ v_r & x>0 \\end{cases}\n", + "v(x) = \\begin{cases} v_l & x<0 \\\\ v_r & x>0. \\end{cases}\n", "$$\n", "\n", + "In [the earlier LWR chapter](Traffic_flow.ipynb), the speed limit was set to unity everywhere. The variable-speed-limit case has been considered, for instance, in (Mochon, 1987) and in Chapter 16 of (LeVeque, 2002). From a physical point of view, we might also imagine that $u_\\text{max}$ varies because of differing road conditions -- for instance, if part of the road is wet or foggy.\n", + "\n", "\n", "Correspondingly, we have a flux function that is different on either side of $x=0$. Let $f(\\rho,v) = v \\rho (1-\\rho)$ and define\n", "\n", @@ -33,7 +64,7 @@ " f_r & = f(\\rho_r,v_r).\n", "\\end{align}\n", "\n", - "The presence of a discontinuous flux function in the Riemann problem can introduce a host of difficulties, some of which will be illustrated here. For a more detailed discussion, see (Burger et. al., 2008) and other papers in that special issue.\n", + "The presence of a discontinuous flux function in the Riemann problem can introduce new difficulties, some of which will be illustrated here. For a more detailed discussion of other systems with discontinuous flux, see (Burger et. al., 2008) and other papers in that special issue.\n", "\n", "Continuing with the problem at hand, if, say, $v_l=1$ and $v_r=2$ then the two flux functions look like this: " ] @@ -43,36 +74,6 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "%matplotlib inline\n", - "import matplotlib as mpl\n", - "mpl.rcParams['font.size'] = 15\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "from ipywidgets import interact, widgets\n", - "from utils import riemann_tools\n", - "from exact_solvers import traffic_variable_speed" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ipywidgets import interact # for interactive widgets\n", - "#from utils.snapshot_widgets import interact # for static figure that can be viewed online" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], "source": [ "rho = np.linspace(0,1)\n", "f_l = rho*(1-rho); f_r = 2*rho*(1-rho)\n", @@ -86,9 +87,9 @@ "metadata": {}, "source": [ "## Admissible regions\n", - "We can view the solution of the Riemann problem as the problem of finding a physically admissible path connecting the left and right states in the $\\rho-f(\\rho)$ plane. The structure of the Riemann solution can be fairly complicated, but we can simplify things by recognizing a few \"rules\" that must govern the connecting path. Two quick observations will rule out half of the available intermediate states:\n", + "We can view the solution of the Riemann problem as the task of finding a physically admissible path connecting the left and right states in the $\\rho-f(\\rho)$ plane. The structure of the Riemann solution can be fairly complicated, but we can simplify things by recognizing a few \"rules\" that must govern the connecting path. Two quick observations will rule out half of the available intermediate states:\n", "\n", - "1. Since the characteristic speed is positive for $\\rho<1/2$, **we cannot reach any intermediate state with $\\rho<1/2$ on the $f_l$ curve** (since states on the $f_l$ curve must appear to the left of $x=0$.\n", + "1. Since the characteristic speed is positive for $\\rho<1/2$, **we cannot reach any intermediate state with $\\rho<1/2$ on the $f_l$ curve** (since states on the $f_l$ curve must appear to the left of $x=0$).\n", "2. Similarly, since the characteristic speed is negative for $\\rho>1/2$, **we cannot reach any intermediate state with $\\rho>1/2$ on the $f_r$ curve**.\n", "\n", "To remind us of these facts, we'll plot the prohibited parts of the curves with dashed lines. It is important to note that the initial states $\\rho_l$ and $\\rho_r$ **can** inhabit these regions. However, if an initial state is on the inadmissible portion of the curve, then we cannot connect a rarefaction to it, since nearby states are inadmissible. We must jump to it through a rarefaction or (as discussed below) a stationary jump." @@ -97,14 +98,14 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "f_l = rho*(1-rho); f_r = 2*rho*(1-rho)\n", - "plt.plot(rho[26:],f_l[26:],'-c',rho[:26],f_r[:26],'-g'); plt.xlim(0,1); plt.ylim(0,0.6);\n", - "plt.plot(rho[:26],f_l[:26],'--k',rho[26:],f_r[26:],'--k',alpha=0.5); plt.xlim(0,1); plt.ylim(0,0.6);\n", + "plt.plot(rho[26:],f_l[26:],'-c',rho[:26],f_r[:26],'-g');\n", + "plt.xlim(0,1); plt.ylim(0,0.6);\n", + "plt.plot(rho[:26],f_l[:26],'--k',rho[26:],f_r[26:],'--k',alpha=0.5);\n", + "plt.xlim(0,1); plt.ylim(0,0.6);\n", "plt.xlabel(r'$\\rho$'); plt.ylabel(r'$f(\\rho)$')\n", "plt.legend(['$f_l$','$f_r$']);" ] @@ -117,17 +118,15 @@ "We can also determine in advance what kind of waves can be connected to $\\rho_l$ or $\\rho_r$ within the admissible regions:\n", "\n", "1. Any intermediate state on the $f_l$ curve with density greater than $\\rho_l$ must be connected to $\\rho_l$ by a shock. Conversely, any intermediate state with density less than $\\rho_l$ must be connected to $\\rho_l$ by a rarefaction.\n", - "2. Similarly, any intermediate state on the $f_r$ curve with density greater than $\\rho_r$ must be connected to $\\rho_r$ by a rarefaction. Conversely, any intermediate state with density less than $\\rho_r$ must be connected to $\\rho_r$ by a shock.\n", + "2. Similarly, any intermediate state on the $f_r$ curve with density greater than $\\rho_r$ must be connected to $\\rho_r$ by a rarefaction, and any intermediate state with density less than $\\rho_r$ must be connected to $\\rho_r$ by a shock.\n", "\n", - "These conditions follow directly from the Lax entropy condition. To remind us of these conditions, we'll plot the portions of the admissible curves that can be connected to the left or right state by a shock in red, and those that can be connected by a rarefaction in blue. Here's an example of what that looks like." + "These conditions follow directly from the Lax entropy condition. To remind us of these conditions, we'll plot in red the portions of the admissible curves that can be connected to the left or right state by a shock, and in blue those that can be connected by a rarefaction. Here's an example of what that looks like." ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "rho_l = 0.6; rho_r = 0.6\n", @@ -143,7 +142,7 @@ "\n", "So far we've only discussed how to connect the left and right states to other states on the same flux curve, but to solve the Riemann problem we must connect points on the two different flux curves to each other.\n", "\n", - "As discussed at length in the previous chapter, the flux of vehicles must be continuous everywhere -- and in particular, at $x=0$:\n", + "As discussed at length in [the earlier traffic flow chapter](Traffic_flow.ipynb), the flux of vehicles must be continuous everywhere -- and in particular, at $x=0$:\n", "\\begin{align} \\label{LWR_vc:fluxcont}\n", "f(\\rho(0^-,t),v_l)) = f(\\rho(0^+,t),v_r)) \\equiv f^*.\n", "\\end{align}\n", @@ -155,10 +154,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "It may seem strange that the Riemann solution includes two waves when we are dealing with a scalar PDE. One way to understand this is by adding a trivial evolution equation for the speed limit:\n", + "It may seem strange that the Riemann solution includes two waves when we are dealing with a scalar PDE. One way to understand this is by adding a trivial evolution equation for the speed limit (which is now artificially considered a function of $t$):\n", "\n", "\\begin{align} \\label{LWR_vc:2by2}\n", - " \\rho_t + (v(x) \\rho(1-\\rho))_x & = 0 \\\\\n", + " \\rho_t + (v(x,t) \\rho(1-\\rho))_x & = 0 \\\\\n", " v_t & = 0.\n", "\\end{align}\n", "\n", @@ -195,7 +194,7 @@ "\n", "Finally, let us formalize one thing that we observed in the previous notebook:\n", "\n", - ">In the LWR system, shocks always carry a increase in density (from left to right), while rarefactions always carry a decrease in density.\n", + ">In the LWR system, shocks always carry an increase in density (from left to right), while rarefactions always carry a decrease in density.\n", "\n", "Why is this? The Lax entropy condition for a shock moving at speed $s$ tells us\n", "\n", @@ -216,9 +215,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "rho_l = 0.6; rho_r = 0.6\n", @@ -238,19 +235,27 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "def c(rho, xi, v):\n", " return v*(1.-2*rho)\n", " \n", "def make_plot_function(rho_l,rho_r,v_l,v_r,connect=True):\n", - " states, speeds, reval, wave_types = traffic_variable_speed.exact_riemann_solution(rho_l,rho_r,v_l,v_r)\n", + " states, speeds, reval, wave_types = \\\n", + " traffic_variable_speed.exact_riemann_solution(rho_l,rho_r,v_l,v_r)\n", " def plot_function(t):\n", - " ax = riemann_tools.plot_riemann(states,speeds,reval,wave_types,t=t,t_pointer=0,\n", - " extra_axes=True,variable_names=['Density']);\n", - " riemann_tools.plot_characteristics(reval,c,(v_l,v_r),ax[0],extra_lines=[[[0,0],[0,1]]])\n", - " traffic_variable_speed.phase_plane_plot(rho_l,rho_r,v_l,v_r,axes=ax[2],connect=connect)\n", + " ax = riemann_tools.plot_riemann(states,speeds,reval,wave_types,\n", + " t=t,t_pointer=0,\n", + " extra_axes=True,\n", + " variable_names=['Density']);\n", + " riemann_tools.plot_characteristics(reval,c,(v_l,v_r),ax[0],\n", + " extra_lines=[[[0,0],[0,1]]])\n", + " traffic_variable_speed.phase_plane_plot(rho_l,rho_r,v_l,v_r,\n", + " axes=ax[2],\n", + " connect=connect)\n", " plt.show()\n", " return plot_function\n", "\n", @@ -262,9 +267,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "plot_riemann_traffic_vc(rho_l,rho_r,v_l,v_r);" @@ -274,7 +277,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The $\\rho-f$ plane is shown in the rightmost plot above. The Riemann solution is indicated with a thick line; as usual we indicate shocks in red and rarefactions in blue; the stationary jump at $x=0$ is plotted in black. Notice that the jump at the interface corresponds to a horizontal line, since the flux is the same on both sides of the interface. Notice also that the jump does not cross the dashed line at $\\rho=1/2$. The solution indicated satisfies all of the admissibility criteria laid out above; indeed, it is the only solution that does so." + "The $\\rho-f$ plane is shown in the rightmost plot above. The Riemann solution is indicated with a thick line; as usual we indicate shocks in red and rarefactions in blue; the stationary jump at $x=0$ is plotted in black. Notice that the jump at the interface corresponds to a horizontal line, since the flux is the same on both sides of the interface. Notice also that the jump does not cross the dashed line at $\\rho=1/2$. The solution shown satisfies all of the admissibility criteria laid out above; indeed, it is the only solution that does so." ] }, { @@ -288,9 +291,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "rho_l = 0.9; rho_r = 0.6\n", @@ -308,9 +309,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "plot_riemann_traffic_vc(rho_l,rho_r,v_l,v_r);" @@ -328,20 +327,14 @@ "metadata": {}, "source": [ "## Case 3: Transonic rarefaction\n", - "So far we have seen solutions with a single shock or rarefaction; they are similar to solutions of the Riemann problem for the LWR model with fixed speed limit, except that they also include a stationary jump. Let's look now at the third class of solution that appeared in the basic LWR model: a transonic rarefaction. In order to connect rarefactions to both states now, $\\rho_l$ and $\\rho_r$ must lie on the admissible portions of the curve. Thus we must have $\\rho_r \\le 1/2 \\le \\rho_l$; this is the same condition that was required for a transonic rarefaction in the basic LWR model." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, in the variable-speed-limit case there are additional conditions that must be satisfied. Namely, the left and right fluxes cannot be so great as to be impossible to balance with the appropriate flux on the other side; i.e. we require\n", + "So far we have seen solutions with a single shock or rarefaction; they are similar to solutions of the Riemann problem for the LWR model with fixed speed limit (see [this earlier example](Traffic_flow.ipynb#Example:-Traffic-jam) and [this earlier example](Traffic_flow.ipynb#Example:-green-light), except that they also include a stationary jump. More interesting things can happen if we have a rarefaction in which the characteristic speed passes through zero (i.e., a *transonic rarefaction*). In order to connect a rarefaction to both states in the variable-speed-limit setting, the densities $\\rho_l$ and $\\rho_r$ bounding the rarefaction wave must both lie on the admissible portions of the curve. Thus we must have $\\rho_r \\le 1/2 \\le \\rho_l$; this is the same condition that was required for a transonic rarefaction in the basic LWR model.\n", + "\n", + "However, in the variable-speed-limit case there are additional conditions that must be satisfied. Namely, the left and right fluxes must not be so great that we cannot balance them with the appropriate flux on the other side; i.e. we require\n", "\n", "\\begin{align}\n", "f_l & \\le v_r/4 \\label{vcLWR:sufficientA} \\\\\n", "f_r & \\le v_l/4.\\label{vcLWR:sufficientB}\n", - "\\end{align}\n", - "\n", + "\\end{align} \n", "This guarantees that neither the left nor right state lies above the entire (right or left) flux curve in the phase plane." ] }, @@ -356,9 +349,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "rho_l = 0.9; rho_r = 0.2\n", @@ -376,9 +367,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "plot_riemann_traffic_vc(rho_l,rho_r,v_l,v_r);" @@ -388,7 +377,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Because we have a stationary jump in $\\rho$ in order to maintain flux continuity at the interface, it is impossible that the characteristics velocity approach zero on *both* sides of the stationary jump. Thus the transonic rarefaction is broken into two rarefactions, with an intermediate constant state lying either just to the left or just to the right of $x=0$. Where this state lies depends on whether the speed limit increases or decreases at the interface; in the example above this \"shoulder\" appears on the right. Next is an example in which it appears on the left." + "Because we have a stationary jump in $\\rho$ in order to maintain flux continuity at the interface, it is impossible that the characteristic velocity approach zero on *both* sides of the stationary jump. Thus the transonic rarefaction is broken into two rarefactions, with an intermediate constant state lying either just to the left or just to the right of $x=0$. Where this state lies depends on whether the speed limit increases or decreases at the interface; in the example above this \"shoulder\" appears on the right. Next is an example in which it appears on the left." ] }, { @@ -401,9 +390,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "rho_l = 0.9; rho_r = 0.2\n", @@ -424,9 +411,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "rho_l = 0.7; rho_r = 0.6\n", @@ -444,9 +429,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "plot_riemann_traffic_vc(rho_l,rho_r,v_l,v_r);" @@ -499,9 +482,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "states = np.array([[rho_l,0.88,rho_r]])\n", @@ -510,9 +491,12 @@ " rho = np.ones((1,len(xi)))\n", " return rho\n", "wave_types = ['contact','shock']\n", - "fig, ax = plt.subplots(1,2,figsize=(12,4))\n", - "traffic_variable_speed.phase_plane_plot(rho_l,rho_r,v_l,v_r,states,speeds,reval,wave_types,axes=ax[1],show=False)\n", - "riemann_tools.plot_waves(states,speeds,reval,wave_types,ax=ax[0],t_pointer=False,t=0)\n", + "fig, ax = plt.subplots(1,2,figsize=figsize)\n", + "traffic_variable_speed.phase_plane_plot(rho_l,rho_r,v_l,v_r,states,\n", + " speeds,reval,wave_types,\n", + " axes=ax[1],show=False)\n", + "riemann_tools.plot_waves(states,speeds,reval,wave_types,ax=ax[0],\n", + " t_pointer=False,t=0)\n", "riemann_tools.plot_characteristics(reval,c,(v_l,v_r),ax[0])" ] }, @@ -520,7 +504,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "As we can see, the shock is unphysical. The characteristics to the left of the shock are emerging from it, rather than impinging on it; this violates the entropy condition. It's also easy to see why we can't replace that shock with a rarefaction: the rarefaction would be right-going, but all the neighboring characteristics are left-going! Finally, this solution involves connecting to an intermediate inadmissible state, which (according to our reasoning at the beginning of the chapter) is incorrect." + "As we can see, the shock is unphysical. The characteristics to the left of the shock are emerging from it, rather than impinging on it; this violates the entropy condition. It's also easy to see why we can't replace that shock with a rarefaction: the rarefaction would be right-going, but all the neighboring characteristics are left-going! Finally, this solution involves connecting to an intermediate inadmissible state, which (according to our reasoning in [the beginning of the chapter](Traffic_variable_speed.ipynb#Admissible-regions)) is incorrect." ] }, { @@ -534,9 +518,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "rho_l = 0.7; rho_r = 0.1\n", @@ -554,9 +536,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "plot_riemann_traffic_vc(rho_l,rho_r,v_l,v_r);" @@ -576,39 +556,45 @@ "metadata": {}, "source": [ "## Other solutions\n", - "We've now considered all the essential types of solutions. You can continue to experiment with this system using the interactive setup below. See if you can determine the correct path in the $\\rho-f(\\rho)$ plane before revealing the result (using the checkbox)." + "We've now considered all the essential types of solutions. *You can continue to experiment with this system using the interactive setup below. See if you can determine the correct path in the $\\rho-f(\\rho)$ plane before revealing the result (using the checkbox).*" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "def plot_all(rho_l,rho_r,v_l,v_r,connect=False):\n", - " states, speeds, reval, wave_types = traffic_variable_speed.exact_riemann_solution(rho_l,rho_r,v_l,v_r)\n", - " ax = riemann_tools.plot_riemann(states,speeds,reval,wave_types,t=0.5,extra_axes=True,variable_names=[r'$\\rho$']);\n", - " riemann_tools.plot_characteristics(reval,c,(v_l,v_r),ax[0],extra_lines=[[[0,0],[0,1]]])\n", + " states, speeds, reval, wave_types = \\\n", + " traffic_variable_speed.exact_riemann_solution(rho_l,rho_r,v_l,v_r)\n", + " ax = riemann_tools.plot_riemann(states,speeds,reval,wave_types,\n", + " t=0.5,extra_axes=True,\n", + " variable_names=[r'$\\rho$']);\n", + " riemann_tools.plot_characteristics(reval,c,(v_l,v_r),ax[0],\n", + " extra_lines=[[[0,0],[0,1]]])\n", " ax[1].set_ylim(0,1)\n", - " traffic_variable_speed.phase_plane_plot(rho_l,rho_r,v_l,v_r,axes=ax[2],connect=connect)\n", + " traffic_variable_speed.phase_plane_plot(rho_l,rho_r,v_l,v_r,\n", + " axes=ax[2],\n", + " connect=connect)\n", " plt.show()\n", " \n", "interact(plot_all,\n", - " rho_l = widgets.FloatSlider(min=0.,max=1.,step=0.01,value=0.4,description=r'$\\rho_l$'),\n", - " rho_r = widgets.FloatSlider(min=0.,max=1.,step=0.01,value=0.7,description=r'$\\rho_r$'),\n", - " v_l = widgets.FloatSlider(min=0.1,max=2.,value=1.),\n", - " v_r = widgets.FloatSlider(min=0.1,max=2.,value=0.4),\n", - " connect = widgets.Checkbox(description='Connect states')\n", - " );" + " rho_l=FloatSlider(min=0.,max=1.,step=0.01,value=0.4,\n", + " description=r'$\\rho_l$'),\n", + " rho_r=FloatSlider(min=0.,max=1.,step=0.01,value=0.7,\n", + " description=r'$\\rho_r$'),\n", + " v_l=FloatSlider(min=0.1,max=2.,value=1.),\n", + " v_r=FloatSlider(min=0.1,max=2.,value=0.4),\n", + " connect=widgets.Checkbox(description='Connect states')\n", + " );" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "# Approximate solvers" + "## Approximate solvers" ] }, { @@ -634,7 +620,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "from clawpack import pyclaw\n", @@ -644,7 +632,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": false + }, "outputs": [], "source": [ "def test_solver(rho_l, rho_r, v_l, v_r, riemann_solver):\n", @@ -680,21 +670,23 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "rho_l = 0.7; rho_r = 0.5\n", "v_l = 1.0; v_r = 1.5\n", "t = 0.5\n", "\n", - "states, speeds, reval, wave_types = traffic_variable_speed.exact_riemann_solution(rho_l,rho_r,v_l,v_r)\n", + "states, speeds, reval, wave_types = \\\n", + " traffic_variable_speed.exact_riemann_solution(rho_l,rho_r,v_l,v_r)\n", "x, frames = test_solver(rho_l,rho_r,v_l,v_r,riemann.traffic_vc_1D)\n", "\n", "def plot_frame(t):\n", - " ax = riemann_tools.plot_riemann(states, speeds, reval, wave_types, t,layout='horizontal',extra_axes=True);\n", - " riemann_tools.plot_characteristics(reval,c,(v_l,v_r),ax[0],extra_lines=[[[0,0],[0,1]]])\n", + " ax = riemann_tools.plot_riemann(states, speeds, reval, wave_types,\n", + " t,layout='horizontal',\n", + " extra_axes=True);\n", + " riemann_tools.plot_characteristics(reval,c,(v_l,v_r),ax[0],\n", + " extra_lines=[[[0,0],[0,1]]])\n", " rho = frames[int(t*10)].q[0,:]\n", " ax[1].plot(x,rho,'-sg')\n", " ax[1].set_xlim(-0.7, 0.7)\n", @@ -718,42 +710,36 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "rho_l = 0.7; rho_r = 0.2\n", "v_l = 1.0; v_r = 1.0\n", "t = 0.5\n", "\n", - "states, speeds, reval, wave_types = traffic_variable_speed.exact_riemann_solution(rho_l,rho_r,v_l,v_r)\n", + "states, speeds, reval, wave_types = \\\n", + " traffic_variable_speed.exact_riemann_solution(rho_l,rho_r,v_l,v_r)\n", "x, frames = test_solver(rho_l,rho_r,v_l,v_r,riemann.traffic_vc_1D)\n", "x ,fframes = test_solver(rho_l,rho_r,v_l,v_r,riemann.traffic_vc_fwave_1D)\n", "\n", "def plot_frame(t):\n", " rho = frames[int(t*10)].q[0,:]\n", " rho2 = fframes[int(t*10)].q[0,:]\n", - " ax = riemann_tools.plot_riemann(states, speeds, reval, wave_types, t, layout='horizontal', extra_axes=True);\n", + " ax = riemann_tools.plot_riemann(states, speeds, reval, wave_types,\n", + " t, layout='horizontal', \n", + " extra_axes=True);\n", " riemann_tools.plot_characteristics(reval,c,(v_l,v_r),ax[0])\n", " ax[1].plot(x,rho,'-sg')\n", " ax[1].plot(x,rho2,'-or')\n", - " ax[1].legend(['Exact','Approx','$f$-wave'],loc='upper right',fontsize=10);\n", + " ax[1].legend(['Exact','Approx','$f$-wave'],loc='upper right',\n", + " fontsize=10);\n", " ax[1].set_xlim(-0.2,0.2)\n", - " traffic_variable_speed.phase_plane_plot(rho_l,rho_r,v_l,v_r,axes=ax[2])\n", + " traffic_variable_speed.phase_plane_plot(rho_l,rho_r,v_l,v_r,\n", + " axes=ax[2])\n", " plt.show()\n", " \n", "interact(plot_frame,t=widgets.FloatSlider(min=0,max=1,step=0.1,value=0.5));" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [] } ], "metadata": { @@ -772,7 +758,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.12" + "version": "2.7.13" } }, "nbformat": 4, diff --git a/citations.tplx b/citations.tplx deleted file mode 100644 index bc6cedd7..00000000 --- a/citations.tplx +++ /dev/null @@ -1,14 +0,0 @@ -((*- extends 'article.tplx' -*)) - -((* block author *)) -\author{David I. Ketcheson \and Randall J. LeVeque \and Mauricio del Razo Sarmina} -((* endblock author *)) - -((* block title *)) -\title{Riemann Problems and Riemann Solvers} -((* endblock title *)) - -((* block bibliography *)) -\bibliographystyle{unsrt} -\bibliography{riemann} -((* endblock bibliography *)) diff --git a/exact_solvers/nonlinear_elasticity.py b/exact_solvers/nonlinear_elasticity.py index b50bdbb4..1611d4a4 100644 --- a/exact_solvers/nonlinear_elasticity.py +++ b/exact_solvers/nonlinear_elasticity.py @@ -175,7 +175,7 @@ def reval(xi): return states, speeds, reval, wave_types -def phase_plane_plot(q_l, q_r, aux_l, aux_r): +def phase_plane_plot(q_l, q_r, aux_l, aux_r, ax=None): r"""Plot the Hugoniot loci or integral curves in the epsilon-u plane.""" # Solve Riemann problem ex_states, ex_speeds, reval, wave_types, ppc = \ @@ -187,7 +187,8 @@ def phase_plane_plot(q_l, q_r, aux_l, aux_r): u_r = q_r[1]/rho_r # Set plot bounds - fig, ax = plt.subplots() + if ax is None: + fig, ax = plt.subplots() x = (q_l[0], eps_star_l, eps_star_r, q_r[0]) y = (u_l, w1(eps_star_l), w2(eps_star_r), u_r) xmax, xmin = max(x), min(x) diff --git a/make_book.sh b/make_book.sh new file mode 100755 index 00000000..f2d6746f --- /dev/null +++ b/make_book.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# Need to update pandoc to 1.19.x +# Need to install bookbook + +rm 0?-*.ipynb +python make_chapters.py +python3 -m bookbook.latex --output-file riemann --template riemann.tplx +pdflatex riemann +bibtex riemann +pdflatex riemann +pdflatex riemann diff --git a/make_chapters.py b/make_chapters.py new file mode 100644 index 00000000..0e28c265 --- /dev/null +++ b/make_chapters.py @@ -0,0 +1,29 @@ +import re +import subprocess + +chapters = ['Preface', + 'Traffic_flow', + 'Shallow_water', + 'Euler_approximate_solvers', + 'Traffic_variable_speed', + 'Nonlinear_elasticity', + 'Euler_equations_TammannEOS', + 'Pressureless_flow', + 'Kitchen_sink_problem'] + +for i, chapter in enumerate(chapters): + filename = chapter + '.ipynb' + with open(filename, "r") as source: + lines = source.readlines() + output_filename = str(i).zfill(2)+'-'+filename + with open(output_filename, "w") as output: + for line in lines: + line = re.sub(r'from ipywidgets import interact', 'from utils.snapshot_widgets import interact', line) + for j, chapter_name in enumerate(chapters): + line = re.sub(chapter_name+'.ipynb', str(j).zfill(2)+'-'+chapter_name+'.ipynb', line) + output.write(re.sub(r'from ipywidgets import interact', 'from utils.snapshot_widgets import interact', line)) + args = ["jupyter", "nbconvert", "--to", "notebook", "--execute", + "--ExecutePreprocessor.kernel_name=python2", + "--output", output_filename, + "--ExecutePreprocessor.timeout=60", output_filename] + subprocess.check_call(args) diff --git a/riemann.bib b/riemann.bib index 433a0eea..15b27c12 100644 --- a/riemann.bib +++ b/riemann.bib @@ -87,10 +87,10 @@ @article{leveque2002 Volume = {40}, Year = {2002}} -@inproceedings{lighthill1955kinematic, +@article{lighthill1955kinematic, title={On kinematic waves. II. A theory of traffic flow on long crowded roads}, author={Lighthill, Michael J and Whitham, Gerald Beresford}, - booktitle={Proceedings of the Royal Society of London A: Mathematical, Physical and Engineering Sciences}, + journal={Proceedings of the Royal Society of London A: Mathematical, Physical and Engineering Sciences}, volume={229}, number={1178}, pages={317--345}, @@ -136,7 +136,7 @@ @article{osher1984 @article{delrazo2017, Author = {M. J. del Razo and R. J. LeVeque}, - Journal = SIAM Journal on Scientific Computing, + Journal = {SIAM Journal on Scientific Computing}, Pages = {}, Title = {{N}umerical methods for interface coupling of compressible and almost incompressible media}, Volume = {}, diff --git a/riemann.tplx b/riemann.tplx new file mode 100644 index 00000000..4551a57a --- /dev/null +++ b/riemann.tplx @@ -0,0 +1,49 @@ +% Default to the notebook output style +((* if not cell_style is defined *)) + ((* set cell_style = 'style_ipython.tplx' *)) +((* endif *)) + +% Inherit from the specified cell style. +((* extends cell_style *)) + + +%=============================================================================== +% Latex Book +%=============================================================================== + +((* block predoc *)) + ((( super() ))) + ((* block tableofcontents *))\tableofcontents((* endblock tableofcontents *)) +((* endblock predoc *)) + +((* block docclass *)) +\documentclass{SIAMGHbook2016} +((* endblock docclass *)) + +((* block author *)) +\author{David I. Ketcheson \and Randall J. LeVeque \and Mauricio del Razo Sarmina} +((* endblock author *)) + +((* block markdowncell scoped *)) +((( cell.source | citation2latex | strip_files_prefix | convert_pandoc('markdown', 'json',extra_args=[]) | resolve_references | convert_pandoc('json','latex', extra_args=["--chapters"]) ))) +((* endblock markdowncell *)) + +((* block title *)) +\title{The Riemann Problem for Hyperbolic PDEs: Theory and Approximate Solvers} +\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\},fontsize=\small} +((* endblock title *)) + +((* block maketitle *)) +\maketitle +((* endblock maketitle *)) + +((* block bibliography *)) +\bibliographystyle{unsrt} +\bibliography{riemann} +((* endblock bibliography *)) + +((*- block any_cell -*)) +((*- if not 'hide' in cell['metadata'].get('tags', {}) -*)) +((( super() ))) +((*- endif -*)) +((*- endblock any_cell -*)) diff --git a/utils/riemann_tools.py b/utils/riemann_tools.py index 6e7eec2e..479410b1 100644 --- a/utils/riemann_tools.py +++ b/utils/riemann_tools.py @@ -254,12 +254,15 @@ def plot_riemann(states, s, riemann_eval, wave_types=None, t=0.1, ax=None, num_axes = num_vars+1 if extra_axes: num_axes += 1 if layout == 'horizontal': - fig_width = 4*num_axes - fig, ax = plt.subplots(1,num_axes,figsize=(fig_width,4)) + if num_axes == 4: + fig_width = 2.5*num_axes + else: + fig_width = 3*num_axes + fig, ax = plt.subplots(1,num_axes,figsize=(fig_width,3)) plt.subplots_adjust(wspace=0.5) elif layout == 'vertical': fig_width = 9 - fig_height = 4*(num_axes-1) + fig_height = 3*(num_axes-1) fig, ax = plt.subplots(num_axes,1,figsize=(fig_width,fig_height),sharex=True) plt.subplots_adjust(hspace=0) ax[-1].set_xlabel('x') @@ -366,11 +369,11 @@ def make_plot_function(states_list,speeds_list,riemann_eval_list, def plot_function(t,which_char=None): if layout == 'horizontal': - fig_width = 4*num_axes - fig, ax = plt.subplots(1,num_axes,figsize=(fig_width,4)) + fig_width = 3*num_axes + fig, ax = plt.subplots(1,num_axes,figsize=(fig_width,3)) elif layout == 'vertical': fig_width = 9 - fig_height = 4*(num_axes-1) + fig_height = 3*(num_axes-1) fig, ax = plt.subplots(num_axes,1,figsize=(fig_width,fig_height),sharex=True) plt.subplots_adjust(hspace=0) ax[-1].set_xlabel('x') @@ -423,7 +426,7 @@ def JSAnimate_plot_riemann(states,speeds,riemann_eval, wave_types=None, times=No plt.close(ax[0].figure) images = animation_tools.make_images(figs) - anim = animation_tools.JSAnimate_images(images, figsize=(10,5)) + anim = animation_tools.JSAnimate_images(images, figsize=(8,4)) return anim diff --git a/utils/snapshot_widgets.py b/utils/snapshot_widgets.py index 89be5274..9ef63c57 100644 --- a/utils/snapshot_widgets.py +++ b/utils/snapshot_widgets.py @@ -9,12 +9,13 @@ print("Will create static figures with single value of parameters") def interact(f, **kwargs): - print("You must run the notebook in order to use the interactive widgets") fargs = {} for key in kwargs.keys(): try: fargs[key] = kwargs[key].value except: pass # if initial value not set for this parameter - print("Using initial widget values: %s" % fargs) + if ('t' in fargs.keys()): + if fargs['t'] == 0: + fargs['t'] = 0.2 f(**fargs)