Second-Order MUSCL Reconstruction
The first-order finite volume method described in Shallow Water Equations reconstructs left and right states at each face directly from cell-averaged values, introducing \(O(\Delta x)\) numerical diffusion. The MUSCL (Monotone Upstream-centered Schemes for Conservation Laws) scheme reduces this to \(O(\Delta x^2)\) by replacing the piecewise-constant reconstruction with a piecewise-linear one.
Overview
For each interior face shared by cells \(i\) (left) and \(j\) (right), the first-order scheme passes cell-averaged states \(\mathbf{U}_i\), \(\mathbf{U}_j\) directly to the Roe solver. MUSCL replaces these with reconstructed face states:
where \(\Delta\vec{x}_i = \vec{x}_f - \vec{x}_i\) is the displacement from cell \(i\)'s centroid to the face midpoint \(\vec{x}_f\). These reconstructed states are then passed to the Roe solver in place of the cell-averaged values.
Step 1 — Weighted Least-Squares Gradient
For each cell \(i\), the gradient \(\nabla q_i\) (computed independently for each of \(h\), \(hu\), \(hv\)) is found by minimizing over the set of neighbors \(\mathcal{N}(i)\):
where \(d_{ij} = \|\vec{x}_j - \vec{x}_i\|\) and \((\Delta x_{ij}, \Delta y_{ij}) = \vec{x}_j - \vec{x}_i\). The inverse-distance weighting gives more influence to nearby neighbors.
The normal equations form the \(2\times 2\) symmetric system \(\mathbf{M}_i \,\nabla q_i = \mathbf{b}_i\), where
Since \(\mathbf{M}_i\) is symmetric positive definite (for non-degenerate meshes), its inverse is computed analytically:
Cells where \(|\det\mathbf{M}_i| < 10^{-15}\) (degenerate, e.g. isolated or 1D cells) are
assigned zero gradients. The per-cell coefficients of \(\mathbf{M}_i^{-1}\) are combined with
per-edge weights once at startup to produce four scalars per edge that are reused every
timestep (see PrecomputeLSGradCoeffs).
Code: PrecomputeLSGradCoeffs + ComputeLeastSquaresGradients
in src/operator_fluxes_ceed.c.
Step 2 — Linear Reconstruction to Face Midpoints
Given cell-centered gradients, the state at face midpoint \(\vec{x}_f\) is approximated by linear extrapolation from each neighboring centroid:
Ghost cells (owned by another MPI rank) have incomplete gradients because only edges local to this process contribute to their least-squares sum. To avoid error, reconstruction falls back to first-order (zero extrapolation) on the ghost side.
Code: ReconstructFaceValues in src/operator_fluxes_ceed.c.
Step 3 — Minmod Slope Limiter
Pure linear reconstruction can produce values outside the range of surrounding cell averages, causing spurious oscillations near discontinuities. The minmod limiter clips the extrapolated increment so the face value cannot overshoot the adjacent cell-average difference:
where
The limiter reduces the scheme to first-order accuracy locally wherever the solution
is non-smooth, preventing oscillations while preserving second-order convergence in
smooth regions. It is enabled by default when second_order is active. Disable via
no_limiter: true in the YAML configuration or the -no_limiter command-line flag.
Code: Minmod + ReconstructFaceValues in src/operator_fluxes_ceed.c.
Step 4 — Roe Solver on Reconstructed States
The reconstructed states \(\mathbf{U}_{i \to f}\) and \(\mathbf{U}_{j \to f}\) replace the cell-averaged states in the Roe flux computation described in Shallow Water Equations. Water depth is clamped to zero from below after reconstruction to prevent unphysical negative values that can arise from linear extrapolation.
Code: SWEFlux_Roe_MUSCL Q-function in src/swe/swe_muscl_fluxes_ceed.h,
applied via the CEED operator created by CreateCeedFluxOperatorReconstructed
in src/operator_fluxes_ceed.c.
MPI Parallelism
Partition-boundary edges are treated at first-order accuracy because ghost-cell gradients are incomplete. This does not affect the global convergence rate but can introduce small MPI-count-dependent variations in \(L_\infty\) norms.
Enabling Second-Order Reconstruction
MUSCL reconstruction requires the CEED backend. Enable via YAML:
numerics:
spatial : fv
temporal : euler
riemann : roe
second_order : true # enable MUSCL reconstruction (CEED backend required)
no_limiter : true # optional: disable the minmod limiter
Or via command-line flags: -second_order and optionally -no_limiter.
If the CEED backend is not active, a warning is printed and the solver falls
back to first-order.