Advection routine#
Following the notation in [BK19], the quantities of interest that we are advecting are
under the advective fluxes \((P \vec{v})\). Say we are doing the advection for the full time-step update, i.e. the quantities \((P \vec{v})^{n+1/2}\) and \(\Psi^n\) are available, where \(n\) indexes the time-level.
Consider (21) in [BK19] for the cells \(i-1\), \(i\) and \(i+1\),
where, corresponding to the management.variable.Vars
data container,
We see that (1) is a half time-step update,
where \(\mathcal{F}(\cdot,\cdot)\) is the flux across the cell interface for the respective quantity \(\mathcal{U}\). This is from a second-order MUSCL scheme. For a general advection equation,
and discretising the above yields
where the right-hand side is a central difference scheme evaluated at the cell edges. Rewriting this,
we identify the first term in the square bracket on the right with \((P u)^{n+1/2}_{i+1/2} \Psi_{i+1/2}\) and the second with \((P u)^{n+1/2}_{i-1/2} \Psi_{i-1/2}\). Recall that the advective fluxes \((P u)^{n+1/2}\) are available at the onset of the full time-stepping. A cell-to-face averaging is done to obtain these values at \(i+1/2\) and \(i-1/2\). The missing pieces are then \(\Psi^{n+1/2}_{i-1/2}\) and \(\Psi^{n+1/2}_{i+1/2}\).
Todo
Link or insert numerical_fluxes.recompute_advective_fluxes here.
To obtain second-order accuracy in space for the solution, we use a slope limiter to approximate the cell-averages instead of the piecewise constants cell-averages in a first-order Godunov’s method. This sets up a Riemann problem that is solved by a HLLE solver.
Reconstruction#
Let’s get the missing pieces, say \(\Psi^{n+1/2}_{i+1/2}\). First, apply the slope limiter. Fig. 2 shows a simple case where the slope in the \(i\)-th cell is the average of the slopes constructed from the cell averages (dotted-lines) of the adjacent cells. This is done in physics.gas_dynamics.recovery.slopes()
while physics.gas_dynamics.recovery.limiters()
is a switch for the limiter choice specified in the initial coonditions. The limited slope of the \(i\)-th cell is denoted \(S_i\). Now,
by tracing the characteristic of \(\Psi\) backwards in time. Fig. 3 illustrates this.
\(u\) is the velocity at the cell face \(i+1/2\), with
as \(u\) is a constant along the characteristic at \(x_{i+1/2}\).
As we now have the limited slope in the cell, the value for \(\Psi\) anywhere in the cell can be obtained by linear interpolation,
where \(x_{i+1/2} - x_{i} = \Delta x /2\) is used. \(\Psi^-_{i+1/2}\) is the solution of \(\Psi\) from the left for the cell interface at \(i+1/2\). See Fig. 4 for more details.
The Riemann problem#
(5) supposes that the characteristic for \(\Psi^{n+1/2}_{i+1/2}\) is traced from the \(i\)-th cell. Another possibility is from the \((i+1)\)-th cell,
(2), (5) and (6) constitute the Riemann problem. (5) and (6) are computed in physics.gas_dynamics.recovery.recovery()
.
HLLE Solver#
The Riemann problem is solved by selecting the choice of (5) or (6) based on the direction of the flux,
where
(7) and (8) are computed in physics.gas_dynamics.numerical_flux.hll_solver()
. With (7), (2) is updated, yielding the solution to (1).
Strang splitting#
(1) demonstrates the solution of a substep obtained from the Strang splitting in the advection scheme. Writing the advection in the full time-stepping of \(\mathcal{U}^*\) as a general operator,
where \(\mathcal{A}_{\text{full}}^{\Delta t}\) is the advection operator. Splitting the operator dimension-wise,
recalling that the Strang splitting is a second-order operator splitting method. The Strang-splitting is computed in physics.gas_dynamics.explicit.advect()
which calls physics.gas_dynamics.explicit.explicit_step_and_flux()
for each substep.
More details on the methods discussed here can be found in [LeVeque92].
References#
LeVeque, R.J., 1992: Numerical methods for conservation laws. Basel: Birkhäuser.