Lecture 8

Discontinuous Galerkin Methods

Unstructured grids

  • Most problems have complex domains.
  • Use unstructured grids.
  • Use Finite Elements.
  • How to recapture spectral (like) convergence?

An unstructured grid representing parts of the UK

Communication

A sketch of a communication pattern on CPUs
  • Parallel computing splits tasks across cores.
  • Communicate information as needed - ghost points.
  • Exascale - millions of GPUs: communication limit.
  • Bigger “numerical stencils” hit limit earlier.
  • Simple spectral method couples every point.

Basis functions

  • Standard FE function basis continuous at nodes - couples neighbouring elements.
  • Discontinuous Galerkin basis functions only inside elements:
    • only couples to direct neighbour;
    • solution multi-valued at element boundary.

Admissible solutions using linear basis functions for Galerkin finite elements (top) and Discontinuous Galerkin (bottom)

Basis functions and weak form

For eg advection \(\partial_t \psi + u \partial_x \psi = 0\), basis

\[ \psi = \sum_a \hat{\psi}_a(t) N_a(x) \]

gives mass-stiffness discrete form

\[ \hat{M}_{ab} \partial_t \hat{\psi}_a + \hat{K}_{ab} \hat{\psi}_a = \hat{F}_b \]

within one single element. \(\hat{\mathbf{F}}\) is inter-element boundary flux.

Legendre polynomials

Mass matrix \(\hat{M}_{ab} = \int N_a N_b\). Choose \(N_a\) orthonormal \(\implies \hat{M}\) identity.

In 1d, map \(x \to \xi \in [-1, 1]\): use Legendre polynomials \(P_a(\xi)\).

Need boundary flux. Have \(P_a(1) = 1, P_a(-1) = (-1)^a\). Use upwind:

\[ \hat{\psi}_a(x; \hat{\psi}_a^{-}, \hat{\psi}_a^{+}) = \begin{cases} \hat{\psi}_a^{-} & u < 0 \\ \hat{\psi}_a^{+} & u > 0 \end{cases} \]

Nodal DG

Count: \(\sum_{n=1}^{N_\text{modes}} \hat{\psi}_n N_n \leftrightarrow \{ \psi( \xi_n ) \equiv \psi_n \}\).

If nodes \(\{ \xi_n \}\) chosen well, solve \(\psi_n\) directly.

Gauss-Lobatto points:

  • nodes \(\xi = \{ \pm 1 \}\): communicate one number;
  • natural for Gauss quadrature.

Vandermonde matrix \(\hat{V}_{in} = P_n(\xi_n)\):

\[ \hat{V}_{in} \hat{\psi}_n = \psi_i \, . \]

Nodal DG equations

Nodal values \(\psi_i\) also give

\[ M_{ab} \partial_t \psi_a + K_{ab} \psi_a = F_b \, . \]

Use Vandermonde matrix to map to nodes:

\[ \begin{aligned} M &= \left( \hat{V} \hat{V}^T \right)^{-1} \, , \\ K^T &= M \left( \partial_x \hat{V} \right) \hat{V}^{-1} \, . \end{aligned} \]

Force vector is flux on boundary nodes only. Map to reference scales \(M\) by \(\det(J)\), not \(K\).

Implementation

from numpy.polynomial import legendre
from scipy.integrate import ode
import quadpy
m = 4 # modes
Ne = 10 # Number of elements
GL = quadpy.c1.gauss_lobatto(m+1)
nodes = GL.points
weights = GL.weights
V_hat = legendre.legvander(nodes, m)
c = np.eye(m+1)
for p in range(m+1):
    V_hat[:, p] /= np.sqrt(2/(2*p+1))
    c[p, p] /= np.sqrt(2/(2*p+1))
V_hat_inv = np.linalg.inv(V_hat)
d_V_hat = legendre.legval(nodes, legendre.legder(c)).T
M = np.linalg.inv(V_hat @ V_hat.T)
M_inv = V_hat @ V_hat.T
K = (M @ (d_V_hat @ np.linalg.inv(V_hat))).T

def dpsidt(t, psi):
    rhs = np.zeros_like(psi)
    dpdt = np.zeros_like(psi)
    for e in range(1, Ne+1):
        lo = e*(m+1)
        hi = (e+1)*(m+1)
        rhs[lo:hi] += u * Ks @ psi[lo:hi]
        rhs[lo] += u * psi[lo-1]
        rhs[hi-1] -= u * psi[hi-1]
        dpdt[lo:hi] = (M_inv / dx_e * 2) @ rhs[lo:hi]
    dpdt[:m+1] = dpdt[-2*(m+1):-(m+1)]
    dpdt[-(m+1):] = dpdt[(m+1):2*(m+1)]
    return dpdt

cfl = 0.5/(2*m+1)
r = ode(dpsidt).set_integrator('dopri5', max_step=cfl*dx_e)
r.set_initial_value(psi0)
r.integrate(t_end)

Summary

  • Discontinuous Galerkin methods work on unstructured grids and give spectral convergence.
  • DG methods are efficient on exascale machines.
  • Setting up a DG scheme is more work.
  • Making DG methods work with discontinuous data is hard.