.. |br| raw:: html
.. _hard_method:
Numerical Schemes
*****************
MUSCL Scheme
~~~~~~~~~~~~
The MUSCL scheme (*Monotonic Upstream-centered Scheme for Conservation
Laws*) is a second-order in space finite volume method that is *total
variation diminishing (TVD)* and can provide accurate simulations of
shock dynamics. A succinct, semi-discrete representation of the scheme
can be written
.. math::
\frac{du_i}{dt} + \frac{1}{\Delta x_i}
\left[
F^{*}_{i+1/2} - F^{*}_{i-1/2}
\right] = 0,\label{semi}\tag{1}
where :math:`F^{*}_{i\pm 1/2}` are numerical fluxes that are a
non-linear mix of first and second-order slope reconstructions depending
on the gradients close to the current cell, and can be written in the
form
.. math::
F^{*}_{i\pm 1/2} = f^{low}_{i\pm 1/2} -
\phi(r_i)
\left(
f^{low}_{i\pm 1/2} - f^{high}_{i\pm 1/2}
\right)
where :math:`r_i` is the ratio of successive gradient approximations and
:math:`\phi: r_i \rightarrow [0,1]` is a limiter function that selects a
realistic spatial derivative value. One example of such a limiter
function is the *minmod* limiter
.. math::
\phi_{mm}(r_i) = max[0, min(1,r_i)];
\;\;\lim_{r_i \rightarrow \infty}\phi_{mm}(r_i) = 1.
In smooth areas of the flow, :math:`\phi_{mm}(r_i)` will be close to
one, which will select the higher-order approximation. Near a shock,
:math:`r_i` will approach infinity and :math:`\phi_{mm}(r_i)` will be
close to zero and the low-order approximation will be selected.
Runge-Kutta Time Evolution for Explicit Update
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To fully discretize (:math:`\ref{semi}`), we can use `Heun's method
`__ to approximate the
time derivative. This method is second-order accurate in time. Heun's
method is a Runge-Kutta method with the following Butcher tableau:
.. note::
The method documented here is second-order accurate in space and
time.
+-----+-----+-----+
| 0 | | |
+-----+-----+-----+
| 1 | 1 | |
+-----+-----+-----+
| | 1/2 | 1/2 |
+-----+-----+-----+
Each step is preceded by a reconstruction of primitive variables and a
flux calculation given by a *Riemann* solver.
The quantity reconstruction to faces uses the rule
.. math::
q^n_{i\pm 1/2} = q^n_i \pm
\frac{\Delta x_i}{2}
\left(\frac{\partial q^n_i}{\partial s}\right),\label{recon}\tag{2}
where :math:`\partial q^n_i/\partial s` is the flux limited slope.
The calculation of a RK slope :math:`K` is then
.. math::
K_i = \frac{F_{i-1/2} - F_{i+1/2}}{\Delta x},
where the :math:`F_i\pm1/2` are obtained from a Riemann solver. The code
in this specialization example uses the HLL approximate Riemann sovler.
.. math::
F^{hll} =
\frac
{S_R F_L - S_L F_R + S_R S_L\left(U_R - U_L\right)}
{S_R - S_L}
where :math:`S_T` and :math:`S_H` are the min and max characteristic
speeds taken at the tail and head of the cell interfaces respectively,
:math:`U_L` and :math:`U_R` are the respective intermediate quantities,
and :math:`F_L` and :math:`F_R` are the flux functions evaluated at the
respective intermediate quantities.
The RK slope is then used to advance the conserved variables, with which
we can calculate the primitive variables and the next RK slope.
Geometric Multigrid Solver for Implicit Update
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A geometric multigrid solver is a linear solver that uses the fact that
relaxation methods such as the Jacobi or the Gauss-Seidel method
converge faster in coarser domains or grids, and then the solutions in
those coarser grids can be used as initial guesses of the relaxation
methods applied in finer grids.
The method begins by applying a relaxation method to the system
.. math::
Ax = b.
After a few iterations of the relaxation method we obtain the
approximate solution :math:`x'`. The residual :math:`r` is then computed
with :math:`r = b - Ax'`. This gives raise to the equation :math:`Ay =
r`, such that :math:`y` is a correction to the unkown array :math:`x`
and the improved approximation :math:`x''` is given by
.. math::
x'' = x' + y \implies Ax'' = A(x' + y) = Ax' + r = b,\label{residual}\tag{3}
which only works if the operator :math:`A` is linear.
To solve :math:`Ay = r`, the equation can be transported to a coarser
grid where relaxation methods are more effective. This is done by
applying a restriction operator on :math:`r \rightarrow r_c`. In the
coarser grid, the system :math:`Ay_c = r_c` is solved by applying the
method described above, with an initial solution of :math:`y_{c0} = 0`.
Once obtained, the solution :math:`y_c` is extended with a prolongation
operator to the finer grid, where the correction
(:math:`\ref{residual}`) is applied. In the coarsest level an exact
solution to the system is ideally calculated, but an approximated
solution can be used as well.
The algorithm described above is named `v-cycle` due to its diagram:
.. image:: ../../../doc/v-cycle.svg
A full multigrid (`FMG`) is the chaining of successive such `v-cycles`
where a finer grid is added after each `v-cycle` is completed:
.. image:: ../../../doc/fmg.svg
.. vim: set tabstop=2 shiftwidth=2 expandtab fo=cqt tw=72 :