Skip to article content

DG Methods for Advection-Diffusion in DOLFINx

A mild introduction to suffering | How far does the rabbit hole go?

The Advection-Diffusion Equation

We consider the steady-state advection-diffusion equation for a scalar quantity uu, in this case in m3^{-3}:

(wu)(Du)=fin Ω\nabla \cdot (\mathbf{w} u) - \nabla \cdot (D \nabla u) = f \quad \text{in } \Omega

where w\mathbf{w} is a prescribed advective velocity field in m\,s1^{-1}, DD is the diffusion coefficient in m2^{2}\,s1^{-1}, ff is a source term in m2^{2}\,s1^{-1}, and ΩRd\Omega \subset \mathbb{R}^d is the computational domain.

The relative importance of the two transport mechanisms is captured by the cell Péclet number:

Pe=wh2D\text{Pe} = \frac{|\mathbf{w}| h}{2D}

where hh is a local mesh size. When Pe1\text{Pe} \ll 1 diffusion dominates and the problem is essentially elliptic; when Pe1\text{Pe} \gg 1 advection dominates and the solution can develop sharp internal layers and boundary layers.

Numerical Challenges and the Case for DG

Standard continuous Galerkin (CG) finite element methods work well for the pure diffusion limit, but suffer from spurious non-physical oscillations as Pe\text{Pe} grows. These oscillations arise because CG lacks any intrinsic upwinding mechanism, as the scheme treats upwind and downwind information symmetrically, even though advection is inherently directional.

Several stabilisation strategies have been developed to address this within the CG framework:

These methods can be effective, but all require tuning parameters, add complexity to the formulation, and are fundamentally workarounds for a framework not designed with advection-dominated transport in mind.

Discontinuous Galerkin (DG) methods address the root cause rather than patching the symptom. Because the approximation space allows inter-element discontinuities, information can be passed between elements through numerical fluxes, and the choice of flux naturally encodes upwinding for the advection term. This gives DG several structural advantages:

The trade-off is a larger global system (DG has more degrees of freedom than CG for the same mesh) and the need to select a penalty parameter for the diffusion term carefully. Both are manageable in practice.

Derivation of the DG Weak Form

Notation

Let Th={K}\mathcal{T}_h = \{K\} be a triangulation of Ω\Omega, and let FI\mathcal{F}_I and FB\mathcal{F}_B denote the sets of interior and boundary faces. The DG trial and test space is:

Vh={vL2(Ω):vKPp(K), KTh}V_h = \{v \in L^2(\Omega) : v|_K \in \mathbb{P}_p(K),\ \forall K \in \mathcal{T}_h\}

For an interior face FFIF \in \mathcal{F}_I shared by elements K0K_0 and K1K_1, let n=n0\mathbf{n} = \mathbf{n}_0 be the outward unit normal from K0K_0. We define the average and jump operators for a scalar qq and vector τ\boldsymbol{\tau} as:

q:=q0+q12,q:=q0q1\langle q \rangle := \frac{q_0 + q_1}{2}, \qquad \llbracket q \rrbracket := q_0 - q_1
τ:=τ0+τ12,τ:=τ0n0+τ1n1\langle \boldsymbol{\tau} \rangle := \frac{\boldsymbol{\tau}_0 + \boldsymbol{\tau}_1}{2}, \qquad \llbracket \boldsymbol{\tau} \rrbracket := \boldsymbol{\tau}_0 \cdot \mathbf{n}_0 + \boldsymbol{\tau}_1 \cdot \mathbf{n}_1

Note that τ=(τ0τ1)n\llbracket \boldsymbol{\tau} \rrbracket = (\boldsymbol{\tau}_0 - \boldsymbol{\tau}_1) \cdot \mathbf{n} is the scalar normal jump of a vector, while q=q0q1\llbracket q \rrbracket = q_0 - q_1 is the scalar jump of qq oriented with n\mathbf{n}. On a boundary face there is a single element, so q=q\langle q \rangle = q and q=q\llbracket q \rrbracket = q.

Element-wise Integration by Parts

Multiply the strong form by vVhv \in V_h and integrate over a single element KK:

K(wu)vdxK(Du)vdx=Kfvdx\int_K \nabla \cdot (\mathbf{w} u)\, v\, \mathrm{d}x - \int_K \nabla \cdot (D\nabla u)\, v\, \mathrm{d}x = \int_K f\, v\, \mathrm{d}x

Applying the divergence theorem to each term separately:

K(wu)vdx+K(wnK)uvds+KDuvdxKD(unK)vds=Kfvdx\begin{split} &-\int_K (\mathbf{w} u) \cdot \nabla v\, \mathrm{d}x + \int_{\partial K} (\mathbf{w} \cdot \mathbf{n}_K)\, u\, v\, \mathrm{d}s \\ &+ \int_K D\nabla u \cdot \nabla v\, \mathrm{d}x - \int_{\partial K} D(\nabla u \cdot \mathbf{n}_K)\, v\, \mathrm{d}s = \int_K f\, v\, \mathrm{d}x \end{split}

Summing over all elements KThK \in \mathcal{T}_h and assembling the K\partial K integrals across shared faces using the average and jump operators yields the global weak form.

Diffusion Term: SIPG

The assembly identity for the diffusion boundary integrals gives:

KKD(unK)vds=FFIF(Dunv+Duv)ds+FFBFD(un)vds\begin{align} \sum_K \int_{\partial K} D(\nabla u \cdot \mathbf{n}_K)\, v\, \mathrm{d}s = &\sum_{F \in \mathcal{F}_I} \int_F \left( \langle D\nabla u \rangle \cdot \mathbf{n}\, \llbracket v \rrbracket + \llbracket D\nabla u \rrbracket\, \langle v \rangle \right) \mathrm{d}s \\ &+ \sum_{F \in \mathcal{F}_B} \int_F D(\nabla u \cdot \mathbf{n})\, v\, \mathrm{d}s \end{align}

In the continuous setting the normal flux of a smooth solution is single-valued, so Du=0\llbracket D\nabla u \rrbracket = 0 and the second interior face term can be dropped from the bilinear form without compromising consistency, since it vanishes exactly when the true solution is substituted. In the discrete setting uhu_h is genuinely discontinuous and Duh\llbracket D\nabla u_h \rrbracket is not zero in general, so omitting this term does modify the discrete system; stability is recovered through the penalty contribution introduced below, rather than by any smoothness of uhu_h. Subtracting the remaining single-valued flux term from the element-wise bulk integrals gives a consistent but non-symmetric form. SIPG adds two further face contributions to restore symmetry and coercivity:

  1. Symmetry: FFIFDvnuds-\displaystyle\sum_{F \in \mathcal{F}_I} \int_F \langle D\nabla v \rangle \cdot \mathbf{n}\, \llbracket u \rrbracket\, \mathrm{d}s, which is zero for the exact solution (consistency preserved) and symmetrises the bilinear form.

  2. Penalty: +FFIFαDhuvds+\displaystyle\sum_{F \in \mathcal{F}_I} \int_F \dfrac{\alpha D}{h}\, \llbracket u \rrbracket \llbracket v \rrbracket\, \mathrm{d}s, which penalises inter-element jumps and restores coercivity.

The interior SIPG bilinear form is therefore:

adiffint(u,v)=KKDuvdxFFIFDunvdsFFIFDvnuds+FFIFαDhuvds\begin{align} a_\text{diff}^\text{int}(u, v) &= \sum_K \int_K D\, \nabla u \cdot \nabla v\, \mathrm{d}x \\ &\quad - \sum_{F \in \mathcal{F}_I} \int_F \langle D\nabla u \rangle \cdot \mathbf{n}\, \llbracket v \rrbracket\, \mathrm{d}s - \sum_{F \in \mathcal{F}_I} \int_F \langle D\nabla v \rangle \cdot \mathbf{n}\, \llbracket u \rrbracket\, \mathrm{d}s \\ &\quad + \sum_{F \in \mathcal{F}_I} \int_F \frac{\alpha D}{h}\, \llbracket u \rrbracket \llbracket v \rrbracket\, \mathrm{d}s \end{align}

The penalty parameter α=Cp2\alpha = Cp^2 (with C10C \sim 10 and pp the polynomial degree) must exceed a threshold that depends on the element geometry.

Advection Term: Upwind Flux

After summing over elements, the advection face integrals over an interior face FF (with normal n=n0\mathbf{n} = \mathbf{n}_0) yield:

F(wn)(u0v0u1v1)ds\int_F (\mathbf{w} \cdot \mathbf{n})\bigl(u_0\, v_0 - u_1\, v_1\bigr)\, \mathrm{d}s

Since uu is multi-valued on FF, we replace it with the upwind value:

uup={u0if wn>0u1if wn0u_\text{up} = \begin{cases} u_0 & \text{if } \mathbf{w} \cdot \mathbf{n} > 0 \\ u_1 & \text{if } \mathbf{w} \cdot \mathbf{n} \leq 0 \end{cases}

which can be written compactly as:

(wn)uup=wun+12wnu(\mathbf{w} \cdot \mathbf{n})\, u_\text{up} = \langle \mathbf{w} u \rangle \cdot \mathbf{n} + \tfrac{1}{2}|\mathbf{w} \cdot \mathbf{n}|\, \llbracket u \rrbracket

The face integral then becomes (wn)uupv(\mathbf{w}\cdot\mathbf{n})\, u_\text{up}\, \llbracket v \rrbracket, where v=v0v1\llbracket v \rrbracket = v_0 - v_1 is the oriented scalar jump of the test function.

The compact identity above assumes that wn\mathbf{w}\cdot\mathbf{n} is single-valued on FF, i.e. wn=0\llbracket \mathbf{w}\cdot\mathbf{n} \rrbracket = 0. This holds whenever w\mathbf{w} is prescribed analytically or is represented in a continuous finite element space, but it fails in general for a velocity field interpolated from an external solver into a DG space. The practical consequences, and how to handle them, are discussed in the section on coupling with an external velocity field.

The interior advection contribution is:

aadvint(u,v)=KK(wu)vdx+FFIF(wn)uupvdsa_\text{adv}^\text{int}(u, v) = -\sum_K \int_K (\mathbf{w} u) \cdot \nabla v\, \mathrm{d}x + \sum_{F \in \mathcal{F}_I} \int_F (\mathbf{w} \cdot \mathbf{n})\, u_\text{up}\, \llbracket v \rrbracket\, \mathrm{d}s

Boundary contributions depend on the flow direction and are treated in the next section.

Boundary Conditions

Each boundary condition modifies the face integrals that arise during integration by parts on FB\mathcal{F}_B.

Diffusion

Dirichlet (u=gDu = g_D on ΓD\Gamma_D):

Imposed weakly by treating ΓD\Gamma_D faces as one-sided SIPG faces, mirroring the interior treatment:

adiffD(u,v)=ΓDD(un)vdsΓDD(vn)uds+ΓDαDhuvdsdiffD(v)=ΓDD(vn)gDds+ΓDαDhgDvds\begin{align} a_\text{diff}^D(u, v) &= - \int_{\Gamma_D} D(\nabla u \cdot \mathbf{n})\, v\, \mathrm{d}s - \int_{\Gamma_D} D(\nabla v \cdot \mathbf{n})\, u\, \mathrm{d}s + \int_{\Gamma_D} \frac{\alpha D}{h}\, u\, v\, \mathrm{d}s \\ \ell_\text{diff}^D(v) &= - \int_{\Gamma_D} D(\nabla v \cdot \mathbf{n})\, g_D\, \mathrm{d}s + \int_{\Gamma_D} \frac{\alpha D}{h}\, g_D\, v\, \mathrm{d}s \end{align}

Neumann (Dun=gND\nabla u \cdot \mathbf{n} = g_N on ΓN\Gamma_N):

The boundary flux integral is replaced directly by the prescribed value. No penalty is needed:

ΓND(un)vdsΓNgNvds-\int_{\Gamma_N} D(\nabla u \cdot \mathbf{n})\, v\, \mathrm{d}s \longrightarrow -\int_{\Gamma_N} g_N\, v\, \mathrm{d}s

The homogeneous case gN=0g_N = 0 is the natural condition and requires no modification.

Robin (Dun=gRβuD\nabla u \cdot \mathbf{n} = g_R - \beta u on ΓR\Gamma_R, β0\beta \geq 0):

Substituting the Robin condition into the boundary face integral:

ΓRD(un)vds=ΓRβuvdsΓRgRvds-\int_{\Gamma_R} D(\nabla u \cdot \mathbf{n})\, v\, \mathrm{d}s = \int_{\Gamma_R} \beta\, u\, v\, \mathrm{d}s - \int_{\Gamma_R} g_R\, v\, \mathrm{d}s

The βuv\beta u v term enters the bilinear form; gRvg_R v moves to the right-hand side.

Advection

Inflow (wn<0\mathbf{w} \cdot \mathbf{n} < 0 on Γin\Gamma_\text{in}, u=ginu = g_\text{in}):

The upwind value is the prescribed inflow data; information enters from outside the domain:

Γin(wn)ginvds(RHS only)\int_{\Gamma_\text{in}} (\mathbf{w} \cdot \mathbf{n})\, g_\text{in}\, v\, \mathrm{d}s \quad \text{(RHS only)}

Since wn<0\mathbf{w} \cdot \mathbf{n} < 0 on Γin\Gamma_\text{in}, this contributes positively for positive inflow data.

Outflow (wn>0\mathbf{w} \cdot \mathbf{n} > 0 on Γout\Gamma_\text{out}):

The upwind value is the interior trace uu; no data needs to be prescribed:

Γout(wn)uvds(bilinear form)\int_{\Gamma_\text{out}} (\mathbf{w} \cdot \mathbf{n})\, u\, v\, \mathrm{d}s \quad \text{(bilinear form)}

This is the natural outflow condition for DG upwinding.

Wall / Symmetry (wn=0\mathbf{w} \cdot \mathbf{n} = 0 on Γw\Gamma_w):

No advective flux crosses the boundary. The face integral vanishes, so no term is added for either walls or symmetry planes.

The Complete Weak Formulation

Find uVhu \in V_h such that a(u,v)=(v)a(u, v) = \ell(v) for all vVhv \in V_h, where:

Bilinear form:

a(u,v)=KKDuvdxFFIΓDFDunvdsFFIΓDFDvnuds+FFIΓDFαDhuvds+ΓRβuvdsKK(wu)vdx+FFIF(wn)uupvds+Γout(wn)uvds\begin{split} a(u, v) &= \sum_K \int_K D\, \nabla u \cdot \nabla v\, \mathrm{d}x \\ &\quad - \sum_{F \in \mathcal{F}_I \cup \Gamma_D} \int_F \langle D\nabla u \rangle \cdot \mathbf{n}\, \llbracket v \rrbracket\, \mathrm{d}s - \sum_{F \in \mathcal{F}_I \cup \Gamma_D} \int_F \langle D\nabla v \rangle \cdot \mathbf{n}\, \llbracket u \rrbracket\, \mathrm{d}s + \sum_{F \in \mathcal{F}_I \cup \Gamma_D} \int_F \frac{\alpha D}{h}\, \llbracket u \rrbracket \llbracket v \rrbracket\, \mathrm{d}s \\ &\quad + \int_{\Gamma_R} \beta\, u\, v\, \mathrm{d}s \\ &\quad - \sum_K \int_K (\mathbf{w} u) \cdot \nabla v\, \mathrm{d}x + \sum_{F \in \mathcal{F}_I} \int_F (\mathbf{w} \cdot \mathbf{n})\, u_\text{up}\, \llbracket v \rrbracket\, \mathrm{d}s + \int_{\Gamma_\text{out}} (\mathbf{w} \cdot \mathbf{n})\, u\, v\, \mathrm{d}s \end{split}

Linear form:

(v)=ΩfvdxΓNgNvdsΓRgRvdsΓDD(vn)gDds+ΓDαDhgDvdsΓin(wn)ginvds\begin{split} \ell(v) &= \int_\Omega f\, v\, \mathrm{d}x \\ &\quad - \int_{\Gamma_N} g_N\, v\, \mathrm{d}s - \int_{\Gamma_R} g_R\, v\, \mathrm{d}s \\ &\quad - \int_{\Gamma_D} D(\nabla v \cdot \mathbf{n})\, g_D\, \mathrm{d}s + \int_{\Gamma_D} \frac{\alpha D}{h}\, g_D\, v\, \mathrm{d}s \\ &\quad - \int_{\Gamma_\text{in}} (\mathbf{w} \cdot \mathbf{n})\, g_\text{in}\, v\, \mathrm{d}s \end{split}

Coupling with an External Velocity Field

The formulation above assumes a velocity field that is either prescribed analytically or represented continuously, divergence-free in the discrete sense, and exactly tangential on walls. When w\mathbf{w} is instead supplied by an external solver such as OpenFOAM, each of these assumptions relaxes, and the face integrals need care. The issues divide into three groups.

Single-valued face flux

OpenFOAM stores its velocity as cell-centred values together with a set of face-normal mass fluxes ϕF=F(ρw)nds\phi_F = \int_F (\rho \mathbf{w}) \cdot \mathbf{n}\,\mathrm{d}s that are, by construction, single-valued per face and conservative at the discrete level. Interpolating the cell-centred velocity into a DG space on the transport mesh and reconstructing wn\mathbf{w}\cdot\mathbf{n} from it loses both properties: the two sides of an interior face disagree, and wn0\llbracket \mathbf{w}\cdot\mathbf{n} \rrbracket \ne 0.

The compact identity used for the interior advection integral then no longer collapses to an upwind flux. Two equivalent fixes are available:

  1. Replace the compact form by an explicit upwind flux that does not rely on single-valuedness of wn\mathbf{w}\cdot\mathbf{n}: $$ \hat{f}_\text{adv} = \tfrac{1}{2} \bigl( \mathbf{w}_0\cdot\mathbf{n}, u_0 + \mathbf{w}_1\cdot\mathbf{n}, u_1 \bigr)

    • \tfrac{1}{2} \bigl| \langle \mathbf{w}\rangle\cdot\mathbf{n} \bigr|, \llbracket u \rrbracket. $$

  2. Transfer the face-flux field ϕF\phi_F directly from OpenFOAM and use it as the advective transport coefficient on each face, replacing wn\mathbf{w}\cdot\mathbf{n} by ϕF/(ρF)\phi_F / (\rho\, |F|) (or by ϕF/F\phi_F / |F| if a volumetric flux is used). The upwind branch is then selected on the sign of ϕF\phi_F. This is the option that preserves OpenFOAM’s flux conservation and is generally preferred.

In either case the boundary face integrals Γin/out\int_{\Gamma_\text{in/out}} must use the same face flux, not the reconstructed wn\mathbf{w}\cdot\mathbf{n}, so that the inflow and outflow splits remain consistent.

Discrete divergence

The physical field is divergence-free, but the interpolant wh\mathbf{w}_h on the transport mesh is not, in general. The two forms

(wu)andwu\nabla\cdot(\mathbf{w} u) \quad\text{and}\quad \mathbf{w}\cdot\nabla u

differ by (w)u(\nabla\cdot\mathbf{w})\, u, which is zero at the continuum level but acts as a spurious source when wh0\nabla\cdot\mathbf{w}_h \ne 0. Two options are available:

When the face-flux form (option 2 above) is used, conservation is enforced through ϕF\phi_F directly and this divergence mismatch does not arise in the same way.

Wall boundary flux

On no-slip or symmetry walls the physical condition is wn=0\mathbf{w}\cdot\mathbf{n} = 0, and the corresponding face integral vanishes. An interpolated velocity field rarely satisfies this exactly: a small residual normal component acts as a spurious inflow or outflow, with the sign and magnitude depending on the interpolation. The safest treatment is to enforce wn=0\mathbf{w}\cdot\mathbf{n} = 0 explicitly on wall facets, either by masking the integrand or by using the face-flux field ϕF\phi_F, which is identically zero on OpenFOAM wall patches and therefore introduces no leak.

Mesh transfer

All of the above assumes that values defined on the OpenFOAM mesh have been transferred to the transport mesh. Mesh-to-mesh interpolation is itself a source of error, particularly at boundaries and in regions with large velocity gradients, and its treatment is outside the scope of this note. For the purposes of this formulation, we assume that either a face-flux field ϕF\phi_F or a cell-centred velocity has been made available on the transport mesh by a method appropriate to the coupling.

Further Reading