Interactive explainer

The fallback scheme, hands-on

A high-order scheme is at its best where the flow is smooth and at its worst at a shock. Instead of limiting the solution everywhere in advance, a Spectral Difference scheme can let each update go ahead, inspect the result, and fall back to a robust second-order scheme only in the cells where it failed. This page takes that repair apart, one move at a time.

Why a repair is needed

A polynomial cannot follow a jump. It overshoots on both sides, and the overshoots do not shrink when the mesh is refined. For the Euler equations an overshoot can mean a negative density or pressure, and the simulation stops. The advection demo of the Spectral Difference page shows it at any order above one.

The classical cure acts a priori: before each update, slopes or high modes are reduced wherever a sensor judges the solution too rough. The sensor has to guess where trouble will appear, and what it removes from smooth flow by mistake is lost. The alternative, introduced by Clain, Diot & Loubère (2011) under the name MOOD, acts a posteriori: take the unlimited step, look at what came out, and redo only what is not acceptable.

That needs two ingredients: a robust scheme to fall back on that can be mixed with the high-order one cell by cell, and a test that tells an acceptable value from a bad one.

The finite volumes inside an element

The first ingredient comes for free. A Spectral Difference (SD) element of degree \(p\) evaluates its flux at \(p+2\) flux points, and the \(p+1\) intervals between them are control volumes. Integrating the SD update over one of them gives, exactly,

\[ \frac{\mathrm{d} \bar u_i}{\mathrm{d} t} = - \frac{f_h(x_{i+1/2}) - f_h(x_{i-1/2})}{\Delta x_i} , \]

with \(\bar u_i\) the average of the solution over the control volume and \(f_h\) the flux polynomial (how it is built). So the SD scheme is already a finite-volume scheme on these control volumes, with an unusually accurate flux at their faces. The fallback is a second finite-volume scheme on the same control volumes. Both are differences of fluxes at the same faces, so the flux at any one face can be taken from either scheme and the result is still conservative.

One stage, move by move

Every stage of the time integrator goes through the same five moves. The figure shows them for a square pulse advected to the right, \(f = u\), on eight fourth-order elements.

Anatomy of a limited stage

Bars: averages over the control volumes. Dashed: exact solution. The picture shows the first stage of the next time step; the other stages are treated the same way.

time step 0 outside their bounds 0 accepted as smooth extrema 0 rejected 0 fluxes replaced 0

Things to try

The checks

The candidate value of a control volume is rejected if it fails the first test without being excused by the second, or if it fails the third.

The repair

The fallback is a second-order Godunov scheme, MUSCL–Hancock, applied to the control volumes: a slope is built in each one from its neighbours and limited (minmod in the demos), and a Riemann problem is solved at every face. It is diffusive and it does not overshoot, which is what is wanted in the few places where it is used.

At a face of a rejected volume the flux is taken from the fallback; elsewhere it is the SD flux. In general the two are mixed with a weight \(\theta\) defined at the faces,

\[ F = \theta\, F^{\,\mathrm{fallback}} + (1 - \theta)\, F^{\,\mathrm{SD}} , \]

with \(\theta = 1\) at the faces of a rejected volume. The figure above uses \(\theta = 0\) everywhere else; the production codes let \(\theta\) fall to ¾ and ¼ over the next two faces, so that the scheme does not change abruptly from one volume to the next. The update is then repeated with the mixed fluxes. Because each face still carries a single flux, what leaves one volume enters its neighbour, at every order and with any \(\theta\).

All of this happens at every stage of the time integrator, on the control volumes of every element at once. In two and three dimensions the control volumes are tensor products of the one-dimensional ones and the same moves are applied face by face, direction by direction.

A shock that forms on its own

In a gas, shocks are not put in by hand: they form. The simplest model is Burgers' equation, \(f = u^2/2\), in which each value travels at a speed equal to itself, so the crest of a wave catches up with the trough ahead of it. A sine wave stays smooth until \(t = 1/\pi \approx 0.32\) and carries a shock from then on. A limiter that acts after the fact has nothing to do before that time and a great deal to do after it.

Burgers' equation, from a sine wave

Green: the polynomial inside each element. Dashed: a reference solution on a fine mesh. Red: control volumes that fell back to second order in the last step. The strip below records their fraction over time.

time 0.00 cells at second order – first fallback at –

Things to try

In real simulations

The same construction runs in the production codes for the Euler and Navier–Stokes equations, and the share of the flow that is repaired stays small. In the two runs below, the control volumes that fell back are marked in red.

Double Mach reflection of a Mach 10 shock, fourth order, 800×200 elements. Top: density. Bottom: the control volumes that fell back (red, drawn enlarged). They trace the shocks and stay under half a per cent of the cells.
Kelvin–Helmholtz instability, fourth order, 800×800 elements, with the control volumes that fell back marked in red (drawn enlarged). They follow the mixing layers and never exceed 0.5% of the cells; everywhere else the scheme stays fourth order.

The demos solve linear advection and Burgers' equation with a third-order strong-stability-preserving Runge–Kutta integrator and apply the checks at every stage. The detection (the relaxed maximum principle with the smooth-extremum test) and the fallback (MUSCL with a minmod slope on the unequal control volumes) follow the reference implementation. The codes of the papers integrate in time with ADER, correct each of its time slices in the same way, and add the flux blending and the positivity checks described above.

From this page to the papers

The codes are public: spd in Python, which runs on CPUs and GPUs, and spd_K in C++ with Kokkos.