#!/usr/bin/env python # coding: utf-8 # # Burgers' equation # In[ ]: get_ipython().run_line_magic('matplotlib', 'inline') get_ipython().run_line_magic('config', "InlineBackend.figure_format = 'svg'") import matplotlib as mpl mpl.rcParams['font.size'] = 8 figsize =(8,4) mpl.rcParams['figure.figsize'] = figsize import matplotlib.pyplot as plt import numpy as np from ipywidgets import interact from ipywidgets import widgets from utils import riemann_tools from exact_solvers import burgers import seaborn as sns sns.set_style('white',{'legend.frameon':'True'}); #sns.set_context('paper') # In this chapter we study another scalar nonlinear conservation law: Burgers' equation. Burgers' equation models momentum transport in a fluid of uniform density and pressure, and it is the simplest equation that captures some key features of gas dynamics. It has been used extensively for developing both theory and numerical methods, and will allow us to further explore the Riemann problem for nonlinear conservation laws. # \begin{align} # q_t + \left(\frac{1}{2}q^2\right)_x = 0. # \label{burgers0} # \end{align} # ## Shock formation # Burgers' equation is a scalar conservation law with the nonlinear flux term $f(q)=q^2/2$. The quasilinear form is obtained by applying the chain rule to differentiate the flux term: # \begin{align*} # q_t + qq_x = 0. # \end{align*} # This equation looks very similar to an advection equation with the exception that the advection speed is given by the value $q$. This is similar to the traffic flow equation but with a different flux. The nonlinearity in the Burgers flux term is essentially the same as in the momentum conservation equation in fluid dynamics, so studying its dynamics provides a guideline to understand more complex fluid dynamics. # # One way to interpret this equation is to imagine that $q$ is the height of a water wave as it approaches the beach. The equation tells us that peak of the wave propagates faster than the trough. In the next figure, we show a solution at two different times for to illustrate this behavior. # ![Fig. 5.1: Wave breaking for Burgers' equation](./figures/burgers_bump.png) # Notice that at first $q$ remains univalued for every $x$. However, after some time the crest of the wave overtakes the leading edge. After this time, we obtain a triple-valued solution. The first time this overtaking happens is referred to as the *breaking time* -- a reference to waves breaking on the beach. It is also the point where the conservation law, in its differential form, breaks down and where the characteristics cross each other for the first time. As we learned in [Traffic_flow.ipynb](Traffic_flow.ipynb), when characteristics cross, a shock wave forms. Mathematically, imposing a shock will avoid the problem of the solution being multivalued. Where should the shock be located? # # If we replace part of the multivalued solution interval with a shock, some mass will be removed (area A1 in the figure below) and some mass will be added (area A2 in the figure below). In order to maintain conservation of the integral of $q$, the shock must be placed so that these two areas are equal: # ![Fig. 5.2: The equal-area rule](./figures/burgers_equal_area.png) # This geometric reasoning provides a nice intuition for the shock location, but is cumbersome in practice. To determine the path of the shock we can again use the Rankine-Hugoniot jump condition, derived in [Traffic_flow.ipynb](Traffic_flow.ipynb). Since the flux for Burgers' equation is $f(q) = q^2/2$, we have # \begin{align*} # s(q_r-q_l) & = f(q_r) - f(q_l)\\ # & = \frac{1}{2} (q_r^2 - q_l^2) \\ # \Rightarrow \ \ \ \ s &= \frac{1}{2}(q_l + q_r). # \end{align*} # Here $q_l, q_r$ denote the solution values just to the left and right of the shock. In general (as in the image above) these states will not be constant and the speed of a shock will change in time. # ### Shock solution # For Burgers' equation, as for the traffic model (or any scalar hyperbolic conservation law with a convex flux function), the solution of the Riemann problem will always consist of one wave, which may be either a shock or a rarefaction. The analysis above already yields the solution to the Riemann problem in the case that the resulting wave is a shock. The entropy condition tells us that a shock will form when $f'(q_l) > f'(q_r)$; i.e. when $q_l>q_r$. In this case the solution is # \begin{align*} # q(x,t) = # \begin{cases} # q_l \quad \text{if} \ \ x/ts. # \end{cases} # \end{align*} # We will now plot the solution of the Burgers' equation when shocks are formed, i.e. when $q_l>q_r$. We first define an interactive plotting function for the exact solver and then we choose the initial conditions and plot the solution. # In[ ]: def plot_riemann_solution(ql, qr): states, speeds, reval, wave_type = burgers.exact_riemann_solution(ql ,qr) plot_function = riemann_tools.make_plot_function(states, speeds, reval, wave_type, layout='horizontal', variable_names=['q'], plot_chars=[burgers.speed]) return interact(plot_function, t=widgets.FloatSlider(value=0.0,min=0,max=1.0), which_char=widgets.Checkbox(value=True,description='Show characteristics')); # In[ ]: ql = 5.0 qr = 1.0 plot_riemann_solution(ql,qr); # ## Rarefaction wave # In the previous figure with the hump as initial condition, we observed that a shock formed on the right side of the hump. However, on the left side, the characteristics spread out and will never cross. This part of the solution is therefore a rarefaction wave. This is the kind of behavior we will observe in the solution of the Riemann problem when $q_lq_r t. # \end{cases} # \end{align*} # # As we will see in the next chapter, the rarefaction solution is always a self-similar solution. This means that it can be expressed as a function of the ratio between position and time $q(x,t) = \tilde{q}(x/t)$, so it remains the same when rescaling both $x$ and $t$ by the same factor. This is a consequence of $q$ being the same along the characteristic in the rarefaction fan. In the Burgers' equation, the form of the rarefaction is particularly simple since the advection speed is simply $q$. # ### Rarefaction solution # In the figure below, we plot solutions of the Riemann problem with $q_ls. # \end{cases} # \end{align*} # # This unphysical solution is also refered to as expansion shock, and it is also a weak solution to the Burgers' equation. In the next figure, we plot this weak solution. # In[ ]: def plot_unphysical_weak_solution(ql, qr): states, speeds, reval, wave_type = burgers.unphysical_riemann_solution(ql ,qr) plot_function = riemann_tools.make_plot_function(states, speeds, reval, wave_type, layout='horizontal', variable_names=['q'], plot_chars=[burgers.speed]) return interact(plot_function, t=widgets.FloatSlider(value=0.0,min=0,max=1.0), which_char=widgets.Checkbox(value=True,description='Show characteristics')); # In[ ]: ql = 1.0 qr = 5.0 plot_unphysical_weak_solution(ql,qr); # Note the solution is given by a shock, even though $q_l