13Week 13 – Finite Differences for Linear Advection
Topic: Finite Difference Methods and Conservation Viewpoint for Linear Advection
13.1 Learning Objectives
By the end of this notebook, you should be able to:
Derive first-order finite difference schemes for the linear advection equation \[u_t + c\,u_x = 0.\]
Implement explicit finite difference schemes in Python using NumPy.
Interpret the Courant number \(\lambda = c \Delta t / \Delta x\) and its role in stability.
Recognize numerical diffusion and dispersion in approximate solutions.
Connect finite difference schemes to a discrete conservation principle.
13.2 1. The Linear Advection Equation
We consider the linear advection equation on a 1D domain \(x \in [0,L]\): \[u_t + c\,u_x = 0,\] where \(c\) is a constant wave speed.
Physically: a profile \(u(x,t)\) is transported (advected) to the right if \(c>0\) or to the left if \(c<0\), without changing shape (for smooth solutions and periodic/compatible boundary conditions).
Mathematically: the exact solution is a simple translation of the initial condition: \[u(x,t) = u_0(x - ct).\]
We will study how different finite difference schemes approximate this simple behavior.
13.3 2. Spatial and Temporal Grids
We discretize the domain \(x \in [0,L]\) into \(N\) grid points with spacing \(\Delta x = L/N\), and we advance in time using time step \(\Delta t\).
Spatial grid: \(x_j = j\,\Delta x\), for \(j = 0,1,\dots,N-1\)
Time levels: \(t^n = n\,\Delta t\), for \(n = 0,1,\dots\)
For simplicity, we will use periodic boundary conditions, so that \[u_0^n = u_N^n, \quad \text{or equivalently } u_{j+N}^n = u_j^n.\]
This allows us to focus on the behavior of the numerical schemes without dealing with boundaries.
import numpy as npimport matplotlib.pyplot as plt# Basic grid setupL =1.0# domain lengthN =200# number of grid pointsdx = L / Nx = np.linspace(0, L, N, endpoint=False)c =1.0# advection speedTfinal =0.5# final time# Courant numberlambda_target =0.8dt = lambda_target * dx / cnt =int(Tfinal / dt)print(f"dx = {dx:.4f}, dt = {dt:.4f}, number of time steps = {nt}")
dx = 0.0050, dt = 0.0040, number of time steps = 125
13.4 3. Initial Condition and Periodicity
We will use a smooth Gaussian bump as an initial condition: \[u_0(x) = \exp\big(-100(x - 0.3)^2\big).\]
With periodic boundary conditions, this bump will wrap around the domain as it moves.
It turns out this scheme is unconditionally unstable for pure advection (no diffusion).
13.6.1 Task
Implement the FTCS scheme with periodic boundary conditions.
Use the same grid and time step as for FTBS.
Observe what happens to the numerical solution as time advances.
Hint: Use np.roll(u, -1) for \(u_{j+1}\) and np.roll(u, 1) for \(u_{j-1}\).
# TRY IT 1: Implement FTCS for linear advectiondef ftcs_advection(u0, c, dx, dt, nt):'''TODO: Implement the Forward-Time, Central-Space scheme for u_t + c u_x = 0 with periodic BCs. ''' N =len(u0) u = u0.copy() lambda_c = c * dt / dx history = [u.copy()]for n inrange(nt):# TODO: add the line below with the FTCS update:# u_new = u_new = u.copy() # placeholder history.append(u_new.copy()) u = u_newreturn np.array(history)# After you implement ftcs_advection, uncomment these lines to test:# history_ftcs = ftcs_advection(u0, c, dx, dt, nt)# plt.figure(figsize=(6, 3))# plt.plot(x, u0, label="t=0")# plt.plot(x, history_ftcs[nt//2], label=f"t={dt*(nt//2):.3f}")# plt.plot(x, history_ftcs[-1], label=f"t={dt*nt:.3f}")# plt.xlabel("x")# plt.ylabel("u")# plt.title("FTCS Scheme for Linear Advection (Expected to be Unstable)")# plt.legend()# plt.grid(True)# plt.show()
Observation:
As \(n\) increases, the FTCS solution exhibits oscillations that grow in time.
This is consistent with a Von Neumann stability analysis, which shows that the amplification factor has magnitude greater than 1 for some modes, regardless of \(\Delta t\) and \(\Delta x\).
This provides a nice contrast with FTBS, which is stable for \(0 < \lambda \le 1\) when \(c>0\).
13.7 6. Conservation Viewpoint
For the linear advection equation, \[u_t + c\,u_x = 0,\] we can rewrite it in conservation form: \[u_t + \partial_x F(u) = 0, \quad F(u) = c\,u.\]
Integrating over a cell \([x_{j-1/2}, x_{j+1/2}]\): \[
\frac{d}{dt}\int_{x_{j-1/2}}^{x_{j+1/2}} u(x,t)\,dx
= F\big(u(x_{j-1/2},t)\big) - F\big(u(x_{j+1/2},t)\big).
\]
The change in cell average is governed by the fluxes through the cell boundaries.
FTBS can be understood as approximating these fluxes in a one-sided way for \(c>0\).
We will return to this idea in Week 14 when we formally introduce finite volume methods.
13.8 7. Exercise 2 - Courant Number and Stability
The Courant number is \[\lambda = \frac{c\,\Delta t}{\Delta x}.\]
For FTBS with \(c>0\), stability requires \(0 < \lambda \leq 1\).
13.8.1 Task
Write a small function that runs FTBS for a given \(\lambda\).
Try \(\lambda = 0.4\), \(0.8\), \(1.0\), and \(1.2\), keeping \(\Delta x\) fixed and adjusting \(\Delta t\).
Compare the solutions at a fixed final time \(T\) and comment on:
Stability vs instability
Amount of numerical diffusion (smoothing)
# TRY IT 2: Explore the effect of lambda on FTBS stabilitydef run_ftbs_with_lambda(lambda_val): dt_local = lambda_val * dx / c nt_local =int(Tfinal / dt_local) u0_local = initial_condition(x) history_local = ftbs_advection(u0_local, c, dx, dt_local, nt_local)return history_local, dt_local, nt_local# TODO:# 1. Call run_ftbs_with_lambda for lambda_val in [0.4, 0.8, 1.0, 1.2].# 2. Plot the solutions at the final time on the same figure.# 3. Observe which values of lambda lead to stability or instability,# and which lead to more/less numerical diffusion.
13.9 8. Summary and Looking Ahead
In this notebook we:
Derived and implemented FTBS (stable) and FTCS (unstable) schemes for the linear advection equation.
Explored the role of the Courant number \(\lambda\) in stability and numerical diffusion.
Introduced the conservation viewpoint, writing the PDE in flux form \(u_t + (F(u))_x = 0\).
Next: We will build directly on the conservation form and derive finite volume methods, which are designed to enforce conservation at the discrete level by approximating fluxes across cell boundaries.