4.3 Spatial Advection Schemes
Learning Objectives
After completing this lecture, students should be able to:
- understand how different numerical schemes approximate spatial derivatives
- implement upwind, central-difference, and spectral advection schemes
- explain the role of cyclic boundary conditions in numerical advection
- compare numerical diffusion and numerical dispersion
- evaluate the strengths and weaknesses of different advection schemes
- select an appropriate advection scheme for a given application
Concept
Why Different Advection Schemes?
The one-dimensional advection equation is
where
The key numerical challenge is computing the spatial derivative,
Different numerical schemes approximate this derivative in different ways.
The choice of scheme affects:
- accuracy
- stability
- computational cost
- numerical diffusion
- numerical dispersion
Role of Cyclic Boundary Conditions
In this section, we use a cyclic boundary condition so that information leaving one side of the domain re-enters from the opposite side.
This choice is useful because all advection schemes require neighboring information near the boundaries.
The upwind scheme requires information from the upstream side of the flow.
The central-difference scheme requires information from both sides of each grid point.
The spectral scheme assumes a periodic domain because Fourier basis functions are cyclic.
Therefore, cyclic boundaries provide a consistent framework for comparing different advection schemes.
Upwind Scheme
The upwind scheme uses information from the upstream direction of the flow.
For positive velocity (\(u>0\)),
Advantages:
- simple
- stable
- robust
Disadvantages:
- excessive numerical diffusion
- smoothing of sharp gradients
As a result, the bell-shaped tracer gradually broadens and weakens during advection.
Central-Difference Scheme
The central-difference scheme uses information from both sides of a grid point:
Advantages:
- higher accuracy
- reduced numerical diffusion
Disadvantages:
- can generate oscillations
- may become unstable
Because the scheme does not contain built-in numerical damping, small numerical errors may grow with time.
Spectral Scheme
Instead of computing derivatives using neighboring grid points, spectral methods represent the solution as a sum of waves.
For a periodic domain,
The spatial derivative becomes
The derivative is computed exactly in spectral space and then transformed back to physical space.
Advantages:
- very high accuracy
- minimal numerical diffusion
- ideal for smooth solutions
Disadvantages:
- requires periodic boundaries
- more complicated implementation
- less effective for discontinuities
Many global atmospheric and oceanic models use spectral methods because of their excellent accuracy.
Numerical Diffusion and Numerical Dispersion
Numerical schemes introduce errors that can modify the solution.
Numerical diffusion:
- smooths gradients
- broadens peaks
- reduces amplitude
Numerical dispersion:
- distorts wave propagation
- produces oscillatory noise
- shifts phase speeds
Upwind schemes tend to produce numerical diffusion.
Central-difference schemes tend to produce numerical dispersion.
Spectral methods generally minimize both errors for smooth solutions.
Model / Equation
Upwind Scheme with Cyclic Boundary
For positive velocity (\(u>0\)),
At the left boundary,
In Python:
dTdt = np.zeros_like(T)
dTdt[1:] = -U * (T[1:] - T[:-1]) / DX
dTdt[0] = -U * (T[0] - T[-1]) / DX
Central-Difference Scheme with Cyclic Boundary
The central-difference approximation is
This scheme requires information from both sides of each grid point. Therefore, two boundary values must be specified: one for the left side and one for the right side.
For a cyclic boundary, values outside the domain are supplied from the opposite side of the domain:
In Python, the interior points can be computed using array slicing:
dTdt = np.zeros_like(T)
dTdt[1:NX-1] = -U * (T[2:NX] - T[0:NX-2]) / (2.0 * DX)
Then the two boundary points are computed using the cyclic boundary condition:
dTdt[0] = -U * (T[1] - T[-1]) / (2.0 * DX)
dTdt[-1] = -U * (T[0] - T[-2]) / (2.0 * DX)
Here, T[-1] provides the left-side neighbor for T[0], and T[0] provides the right-side neighbor for T[-1].
Combining the interior and boundary calculations gives:
def advection_tendency(T, x, U):
dTdt = np.zeros_like(T)
NX = len(T)
dTdt[1:NX-1] = -U * (T[2:NX] - T[0:NX-2]) / (2.0 * DX)
dTdt[0] = -U * (T[1] - T[-1]) / (2.0 * DX)
dTdt[-1] = -U * (T[0] - T[-2]) / (2.0 * DX)
return dTdt
This implementation avoids np.roll() and explicitly shows how the cyclic boundary condition supplies the missing neighboring values.
Spectral Scheme with Cyclic Boundary
The tracer field is represented as a sum of Fourier waves:
The derivative in spectral space is
The advection tendency becomes
In Python:
Tk = np.fft.fft(T)
k = 2.0 * np.pi * np.fft.fftfreq(len(T), d=DX)
dTdx = np.real(
np.fft.ifft(
1j * k * Tk
)
)
dTdt = -U * dTdx
Because Fourier basis functions are periodic, the cyclic boundary condition is built directly into the spectral derivative.
Sample Code
The template file for this section is
Run the script:
python 4_3-advection3_template.py
The script produces
4_3-advection3_template.mp4
4_3-advection3_template.png
This template uses the one-dimensional advection equation with a cyclic boundary condition. The default numerical scheme is the upwind scheme.
The key part of the template is the advection_tendency() function:
def advection_tendency(T, x, U):
dTdt = np.zeros_like(T)
dTdt[1:] = -U * np.diff(T) / DX
# Cyclic Boundary
dTdt[0] = -U * (T[0] - T[-1]) / DX
return dTdt
In the exercises, you will replace this function with different spatial advection schemes and compare the results.
Exercise
Step 1. Run the Upwind Scheme
First, create a copy of the template script:
cp 4_3-advection3_template.py 4_3-advection3_upwind.py
Run the model:
python 4_3-advection3_upwind.py
Examine the output files:
4_3-advection3_upwind.mp4
4_3-advection3_upwind.png
The default configuration uses
NT = 200
DT = 1.0
DX = 1.0
U = 0.5
The cyclic boundary condition allows the bell-shaped anomaly to leave the right side of the domain and re-enter from the left side.
Questions:
- Does the anomaly propagate toward positive \(x\)?
- What happens when the anomaly reaches the right boundary?
- Does the anomaly re-enter from the left boundary?
- Does the amplitude decrease with time?
- Does the shape become smoother or broader?
This case will be used as the reference simulation.
Step 2. Implement the Central-Difference Scheme
Next, replace the upwind scheme with the central-difference scheme.
Create a new script:
cp 4_3-advection3_upwind.py 4_3-advection3_central.py
Replace the advection_tendency() function with:
def advection_tendency(T, x, U):
dTdt = np.zeros_like(T)
NX = len(T)
# Interior points
dTdt[1:NX-1] = -U * (T[2:NX] - T[0:NX-2]) / (2.0 * DX)
# Cyclic boundary points
dTdt[0] = -U * (T[1] - T[-1]) / (2.0 * DX)
dTdt[-1] = -U * (T[0] - T[-2]) / (2.0 * DX)
return dTdt
Run the model with the default time step:
DT = 1.0
NT = 200
python 4_3-advection3_central.py
Questions:
- Does the central-difference solution remain stable?
- Do oscillations appear?
- Does the amplitude grow with time?
- How does this behavior differ from the upwind scheme?
Step 3. Reduce the Time Step
The central-difference scheme produces less numerical diffusion than the upwind scheme, but it can become numerically unstable when combined with the Forward Euler time integration scheme.
One possible approach is to reduce the time step.
First, use:
DT = 1.0
NT = 200
Run the model and examine the solution.
Next, reduce the time step:
DT = 0.5
NT = 200
Run the model again.
Questions:
- Does the instability become weaker?
- Does the simulation cover the same total physical time interval?
- How does the solution compare with the DT = 1.0 case?
Because the total integration time is now shorter, increase the number of time steps:
DT = 0.5
NT = 400
Run the model again.
Questions:
- Does the instability still appear?
- Is the instability delayed compared with the DT = 1.0 case?
- Does reducing the time step completely eliminate the instability?
Finally, try a smaller time step:
DT = 0.2
NT = 1000
Run the model again.
Questions:
- Does further reducing DT improve the solution?
- Is the solution completely stable?
- What does this suggest about the Forward Euler time integration scheme?
This experiment demonstrates that reducing the time step may improve the solution and delay instability, but it does not fundamentally solve the stability problem associated with the Forward Euler method.
Step 4. Improve Time Integration Using RK4
Although reducing DT improves the numerical solution, it requires substantially more time steps and increases computational cost.
Instead of simply decreasing the time step, we can improve the time integration method.
Create a new script:
cp 4_3-advection3_central.py 4_3-advection3_central_rk4.py
Replace the Forward Euler update:
dTdt = advection_tendency(T, x, U)
T = T + DT * dTdt
with the fourth-order Runge-Kutta (RK4) method:
k1 = advection_tendency(T, x, U)
k2 = advection_tendency( T + 0.5 * DT * k1, x, U)
k3 = advection_tendency( T + 0.5 * DT * k2, x, U)
k4 = advection_tendency( T + DT * k3, x, U)
T = T + DT / 6.0 * ( k1 + 2.0 * k2 + 2.0 * k3 + k4)
Restore the original time step:
DT = 1.0
NT = 200
Run the model:
python 4_3-advection3_central_rk4.py
Questions:
- Does RK4 improve the stability of the central-difference scheme?
- Does RK4 reduce the need for a very small DT?
- How does the RK4 solution compare with the DT = 0.2 Forward Euler solution?
- Does RK4 preserve the shape of the tracer better than the upwind scheme?
This experiment demonstrates that numerical stability depends on both the spatial discretization and the time integration method.
Step 5. Implement the Spectral Scheme
Next, replace the central-difference derivative with a spectral derivative while retaining the RK4 time integration.
Create a new script:
cp 4_3-advection3_central_rk4.py 4_3-advection3_spectral.py
Replace the advection_tendency() function with:
def advection_tendency(T, x, U):
NX = len(x)
L = x[-1] - x[0]
T_hat = np.fft.fft(T)
if NX % 2 == 0:
k = np.asarray( list(range(0, NX // 2)) + [0] + list(range(-NX // 2 + 1, 0)), dtype=np.float64)
else:
k = np.asarray( list(range(0, (NX - 1) // 2)) + [0] + list(range(-(NX - 1) // 2, 0)), dtype=np.float64)
k = k * 2.0 * np.pi / L
dTdx = np.fft.ifft( 1.0j * k * T_hat).real
dTdt = -U * dTdx
return dTdt
Run the model:
python 4_3-advection3_spectral.py
Examine the output files:
4_3-advection3_spectral.mp4
4_3-advection3_spectral.png
Questions:
- How does the spectral solution compare with the upwind solution?
- How does it compare with the central-difference RK4 solution?
- Which scheme best preserves the shape of the bell-shaped anomaly?
- Does the spectral method introduce numerical diffusion?
- Why does the spectral method require a cyclic boundary condition?
Step 6. Compare All Schemes
Compare the output animations and final figures from:
4_3-advection3_upwind.mp4
4_3-advection3_central.mp4
4_3-advection3_central_rk4.mp4
4_3-advection3_spectral.mp4
and
4_3-advection3_upwind.png
4_3-advection3_central.png
4_3-advection3_central_rk4.png
4_3-advection3_spectral.png
Focus on the following comparisons:
| Scheme | Spatial Scheme | Time Scheme |
|---|---|---|
| Upwind | Upwind | Forward Euler |
| Central | Central Difference | Forward Euler |
| Central RK4 | Central Difference | RK4 |
| Spectral | Spectral | RK4 |
Questions:
- Which scheme produces the strongest numerical diffusion?
- Which scheme best preserves the amplitude?
- Which scheme best preserves the shape?
- Which scheme produces oscillatory or unstable behavior?
- How much improvement does RK4 provide relative to Forward Euler?
- Which scheme appears most accurate for this smooth periodic tracer?
This comparison highlights the importance of both spatial discretization and time integration in numerical modeling.
Optional: Summary Code
Students who would like a cleaner implementation may use:
4_3-advection3_summary.py
This script combines:
- upwind, central-difference, and spectral advection schemes,
- Forward Euler and RK4 time integration,
- cyclic boundary conditions,
within a single framework.
The user can switch among schemes by modifying a small number of lines in the code. This summary version will also serve as a useful starting point for later chapters when additional physical processes are introduced.
Key Points
- The advection tendency
can be approximated using several numerical schemes.
-
The upwind scheme uses information from the upstream direction of the flow and is generally stable but introduces numerical diffusion.
-
Numerical diffusion smooths gradients, broadens peaks, and reduces amplitudes.
-
The central-difference scheme is more accurate than the upwind scheme because it uses information from both sides of a grid point.
-
The central-difference scheme contains much less numerical diffusion but can become unstable when combined with Forward Euler time integration.
-
Reducing the time step can delay numerical instability, but it may not completely eliminate the problem.
-
Numerical accuracy depends on both the spatial discretization and the time integration scheme.
-
The RK4 method improves numerical stability and accuracy by evaluating the tendency four times during each time step.
-
Spectral methods compute spatial derivatives using Fourier transforms rather than finite differences.
-
Spectral methods are highly accurate for smooth periodic fields and require cyclic boundary conditions.
-
For smooth advection problems, the combination of spectral derivatives and RK4 time integration often provides the most accurate solution.
-
Numerical models must balance accuracy, stability, and computational cost.
Homework
Complete the following tasks.
1. Central-Difference Scheme with RK4
Use the central-difference spatial derivative together with the RK4 time integration scheme.
Generate and submit:
4_3-advection3_central_rk4.mp4
and
4_3-advection3_central_rk4.png
In a short paragraph, describe:
- how the solution differs from the Forward Euler central-difference solution,
- whether RK4 improves numerical stability,
- whether numerical diffusion is reduced relative to the upwind scheme.
2. Spectral Scheme with RK4
Use the spectral derivative together with the RK4 time integration scheme.
Generate and submit:
4_3-advection3_spectral.mp4
and
4_3-advection3_spectral.png
In a short paragraph, describe:
- how the spectral solution differs from the upwind solution,
- how the spectral solution differs from the central-difference RK4 solution,
- whether the bell-shaped anomaly maintains its original shape,
- why cyclic boundary conditions are required for spectral methods.
Comparison Discussion
Compare the results from:
4_3-advection3_central_rk4.png
4_3-advection3_spectral.png
Discuss:
- Which scheme best preserves the tracer shape?
- Which scheme appears most accurate?
- Which scheme would you choose for a smooth periodic tracer field?
- What trade-offs exist between simplicity, stability, and accuracy?
Optional Further Experiments
Students interested in further exploration may investigate one or more of the following:
- Change the advection velocity \(U\).
- Change the grid spacing \(DX\).
- Change the time step \(DT\).
- Change the initial tracer width \(K\).
- Compare Forward Euler and RK4 for the spectral scheme.
- Compare all four combinations:
- Upwind + Euler
- Central + Euler
- Central + RK4
- Spectral + RK4
- Examine how numerical diffusion and numerical instability depend on spatial and temporal resolution.
Discussion Questions
- Why does the upwind scheme remain stable even though it is less accurate?
- Why can a highly accurate spatial derivative still become unstable?
- Why does improving the time integration method improve the solution?
- What are the advantages and disadvantages of spectral methods?
- Why are cyclic boundary conditions naturally suited for Fourier-based methods?
- How do the lessons learned in this chapter apply to weather and climate models?