{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Approximate solvers for the Euler equations of gas dynamics" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this chapter we discuss approximate solvers for the one-dimensional Euler equations:\n", "\n", "\\begin{align}\n", " \\rho_t + (\\rho u)_x & = 0 \\\\\n", " (\\rho u)_t + (\\rho u^2 + p)_x & = 0 \\\\\n", " E_t + ((E+p)u)_x & = 0.\n", "\\end{align}\n", "\n", "As in [Euler_equations.ipynb](Euler_equations.ipynb), we focus on the case of an ideal gas, for which the total energy is given by\n", "\n", "\\begin{align} \\label{EA:EOS}\n", " E = \\frac{p}{\\gamma-1} + \\frac{1}{2}\\rho u^2.\n", "\\end{align}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Roe solver" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We first derive a Roe solver for the Euler equations, following the same approach as in [shallow_water_approximate_solvers.ipynb](shallow_water_approximate_solvers.ipynb). Namely, we assume that $\\hat{A} = f'(\\hat{q})$ for some average state $\\hat{q}$, and impose the condition of conservation:\n", "\n", "\\begin{align} \\label{EA:cons}\n", " f'(\\hat{q}) (q_r - q_l) & = f(q_r) - f(q_l).\n", "\\end{align}\n", "\n", "We will need the following quantities:\n", "\n", "\\begin{align}\n", "q & = \\begin{pmatrix} \\rho \\\\ \\rho u \\\\ E \\end{pmatrix}, & f(q) & = \\begin{pmatrix} \\rho u \\\\ \\rho u^2 + p \\\\ H u \\rho \\end{pmatrix}, \\\\\n", "f'(\\hat{q}) & = \\begin{pmatrix} \n", " 0 & 1 & 0 \\\\ \n", " \\frac{\\gamma-3}{2}\\hat{u}^2 & (3-\\gamma)\\hat{u} & \\gamma-1 \\\\\n", " \\frac{\\gamma-1}{2}\\hat{u}^3 - \\hat{u}\\hat{H} & \\hat{H} - (\\gamma-1)\\hat{u}^2 & \\gamma \\hat{u} \\end{pmatrix}.\n", "\\end{align}\n", "\n", "Here $H = \\frac{E+p}{\\rho}$ is the enthalpy. We have rewritten most expressions involving $E$ in terms of $H$ because it simplifies the derivation that follows. We now solve \\eqref{EA:cons} to find $\\hat{u}$ and $\\hat{H}$. It turns out that, for the case of a polytropic ideal gas, the average density $\\hat{\\rho}$ plays no role in the Roe solver.\n", "\n", "The first equation of \\eqref{EA:cons} is an identity, satisfied independently of our choice of $\\hat{q}$. The second equation is (using \\eqref{EA:EOS})\n", "\n", "\\begin{align}\n", " \\frac{\\gamma-3}{2}\\hat{u}^2 (\\rho_r - \\rho_l) + (3-\\gamma)\\hat{u}(\\rho_r u_r - \\rho_l u_l) + (\\gamma-1)\\left( \\frac{p_r-p_l}{\\gamma-1} + \\frac{1}{2}(\\rho_r u_r^2 - \\rho_l u_l^2) \\right) & = \\rho_r u_r^2 - \\rho_l u_l^2 + p_r - p_l,\n", "\\end{align}\n", "\n", "which simplifies to a quadratic equation for $\\hat{u}$:\n", "\n", "\\begin{align} \\label{EA:u_quadratic}\n", " (\\rho_r - \\rho_l)\\hat{u}^2 - 2(\\rho_r u_r - \\rho_l u_l) \\hat{u} + (\\rho_r u_r^2 - \\rho_l u_l^2) & = 0,\n", "\\end{align}\n", "\n", "with roots\n", "\n", "\\begin{align}\n", " \\hat{u}_\\pm & = \\frac{\\rho_r u_r - \\rho_l u_l \\mp \\sqrt{\\rho_r \\rho_l} (u_l - u_r)}{\\rho_r - \\rho_l} = \\frac{\\sqrt{\\rho_r} u_r \\pm \\sqrt{\\rho_l} u_l}{\\sqrt{\\rho_r}\\pm\\sqrt{\\rho_l}}\n", "\\end{align}\n", "\n", "Notice that this is identical to the Roe average of the velocity for the shallow water equations, if we replace the density $\\rho$ with depth $h$. As before, we choose the root $u_+$ since it is well defined for all values of $\\rho_r, \\rho_l$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we find $\\hat{H}$ by solving the last equation of \\eqref{EA:cons}, which reads \n", "\\begin{align}\n", " \\left( \\frac{\\gamma-1}{2}\\hat{u}^3 - \\hat{u}\\hat{H} \\right)(\\rho_r - \\rho_l) + \\left( \\hat{H} - (\\gamma-1)\\hat{u}^2 \\right)(\\rho_r u_r - \\rho_l u_l) + \\gamma \\hat{u}(E_r - E_l) & = H_r u_r \\rho_r - H_l u_l \\rho_l.\n", "\\end{align} \n", "We can simplify this using the equality $\\gamma E = \\rho H + \\frac{\\gamma-1}{2}\\rho u^2$ and solve for $\\hat{H}$ to find \n", "\\begin{align}\n", " \\hat{H} & = \\frac{\\rho_r H_r (u_r - \\hat{u}_+) - \\rho_l H_l (u_l - \\hat{u}_+)}{\\rho_r u_r - \\rho_l u_l - \\hat{u}_\\pm(\\rho_r -\\rho_l)} \\\\\n", " & = \\frac{\\rho_r H_r (u_r - \\hat{u}_+) - \\rho_l H_l (u_l - \\hat{u}_+)}{\\pm\\sqrt{\\rho_r \\rho_l}(u_r-u_l)} \\\\\n", " & = \\frac{\\rho_r H_r - \\rho_l H_l \\mp\\sqrt{\\rho_r \\rho_l}(H_r - H_l)}{\\rho_r - \\rho_l} \\\\\n", " & = \\frac{\\sqrt{\\rho_r}H_r \\pm \\sqrt{\\rho_l} H_l}{\\sqrt{\\rho_r}\\pm\\sqrt{\\rho_l}}.\n", "\\end{align} \n", "Once more, we take the plus sign in the final expression for $\\hat{H}$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To implement the Roe solver, we also need the eigenvalues and eigenvectors of the averaged flux Jacobian $f'(\\hat{q})$. These are just the eigenvalues of the true Jacobian, evaluated at the averaged state:\n", "\\begin{align}\n", " \\lambda_1 & = \\hat{u} - \\hat{c}, & \\lambda_2 & = \\hat{u} & \\lambda_3 & = \\hat{u} + \\hat{c},\n", "\\end{align} \n", "\\begin{align}\n", "r_1 & = \\begin{bmatrix} 1 \\\\ \\hat{u}-\\hat{c} \\\\ \\hat{H}-\\hat{u}\\hat{c}\\end{bmatrix} &\n", "r_2 & = \\begin{bmatrix} 1 \\\\ \\hat{u} \\\\ \\frac{1}{2}\\hat{u}^2 \\end{bmatrix} &\n", "r_3 & = \\begin{bmatrix} 1 \\\\ \\hat{u}+\\hat{c} \\\\ \\hat{H}+\\hat{u}\\hat{c}\\end{bmatrix}.\n", "\\end{align}\n", "Here $\\hat{c} = \\sqrt{(\\gamma-1)(\\hat{H}-\\hat{u}^2/2)}$.\n", "\n", "Solving the system of equations\n", "\\begin{align}\n", "q_r - q_l & = \\sum_{p=1}^3 \\wave^p = \\sum_{p=1}^3 \\alpha_p r_p\n", "\\end{align} \n", "for the wave strengths gives\n", "\\begin{align}\n", " \\alpha_2 & = \\delta_1 + (\\gamma-1)\\frac{\\hat{u}\\delta_2 - \\delta_3}{\\hat{c}^2} \\\\\n", " \\alpha_3 & = \\frac{\\delta_2 + (\\hat{c}-\\hat{u})\\delta_1 - \\hat{c}\\alpha_2}{2\\hat{c}} \\\\\n", " \\alpha_1 & = \\delta_1 - \\alpha_2 - \\alpha_3,\n", "\\end{align} \n", "where $\\delta = q_r - q_l$. We now have everything we need to implement the Roe solver." ] }, { "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 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\n", "from ipywidgets import widgets\n", "import matplotlib\n", "Primitive_State = namedtuple('State', Euler.primitive_variables)\n", "Conserved_State = namedtuple('State', Euler.conserved_variables)\n", "gamma = 1.4\n", "problem_data = {}\n", "problem_data['gamma'] = gamma\n", "problem_data['gamma1'] = gamma - 1.0" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def roe_averages(q_l, q_r, gamma=1.4):\n", " rho_sqrt_l = np.sqrt(q_l[0])\n", " rho_sqrt_r = np.sqrt(q_r[0])\n", " p_l = (gamma-1.)*(q_l[2]-0.5*(q_l[1]**2)/q_l[0])\n", " p_r = (gamma-1.)*(q_r[2]-0.5*(q_r[1]**2)/q_r[0])\n", " denom = rho_sqrt_l + rho_sqrt_r\n", " u_hat = (q_l[1]/rho_sqrt_l + q_r[1]/rho_sqrt_r)/denom\n", " H_hat = ((q_l[2]+p_l)/rho_sqrt_l + (q_r[2]+p_r)/rho_sqrt_r)/denom\n", " c_hat = np.sqrt((gamma-1)*(H_hat-0.5*u_hat**2))\n", " \n", " return u_hat, c_hat, H_hat\n", " \n", " \n", "def Euler_roe(q_l, q_r, gamma=1.4):\n", " \"\"\"\n", " Approximate Roe solver for the Euler equations.\n", " \"\"\"\n", " \n", " rho_l = q_l[0]\n", " rhou_l = q_l[1]\n", " u_l = rhou_l/rho_l\n", " rho_r = q_r[0]\n", " rhou_r = q_r[1]\n", " u_r = rhou_r/rho_r\n", " \n", " u_hat, c_hat, H_hat = roe_averages(q_l, q_r, gamma)\n", " \n", " delta = q_r - q_l\n", " \n", " s1 = u_hat - c_hat\n", " s2 = u_hat\n", " s3 = u_hat + c_hat\n", " \n", " alpha2 = (gamma-1.)/c_hat**2 *((H_hat-u_hat**2)*delta[0]+u_hat*delta[1]-delta[2])\n", " alpha3 = (delta[1] + (c_hat - u_hat)*delta[0] - c_hat*alpha2) / (2.*c_hat)\n", " alpha1 = delta[0] - alpha2 - alpha3\n", " \n", " r1 = np.array([1., u_hat-c_hat, H_hat - u_hat*c_hat])\n", " r2 = np.array([1., u_hat, 0.5*u_hat**2])\n", " q_l_star = q_l + alpha1*r1\n", " q_r_star = q_l_star + alpha2*r2\n", " \n", " states = np.column_stack([q_l,q_l_star,q_r_star,q_r])\n", " speeds = [s1, s2, s3]\n", " wave_types = ['contact','contact', 'contact']\n", " \n", " def reval(xi):\n", " rho = (xi