This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

Notebooks · posts/crank-nicolson-is-second-order-in-time

Crank-Nicolson is second order in time, backward Euler first

The heat equation from , stepped to with six time steps from 0.02 down to 0.000625. Each halving cuts the Crank-Nicolson error by a factor of 4.0 to 4.7 (measured order 2.09 to 2.23, then 2.000) and the backward Euler error by 1.9 to 2.0 (order 0.94 to 0.996). The errors are measured against the exact solution of the space-discretized equation, a discrete sine series. Against the exact Fourier series of the PDE, the Crank-Nicolson error stops falling at the space error, .

The rod is with both ends held at . The PDE's solution is the Fourier sine series

since has sine coefficients for odd and zero for even , and each mode decays at its own rate .

The second derivative is replaced by the centered difference on 199 interior points, . The time steps are then the only error left to measure. The Python reference, posts/refs/crank-nicolson-is-second-order-in-time.py, steps the same equations with scipy's banded solver and computes the exact space-discretized solution with a matrix exponential (output beside it).

Look inside this program

  • Atlas

    The program’s map: every function and which calls which.

  • There’s no recorded run of this program yet.

Shift+Enter in a cell runs it and moves to the next. Running a cell runs every cell above it too, as one program.

[1]lines 28–48

Two schemes, one family

Both schemes average the space difference between the old and the new time level, with weight on the new one:

is backward Euler; is Crank-Nicolson, which is the trapezoidal rule in time. The left side is a tridiagonal system, with on the diagonal and beside it, . The Thomas algorithm solves it in one sweep down and one back up.

Why the order differs: backward Euler evaluates the right side at the end of the step, which makes a local error of order per step and after the steps. The trapezoidal rule evaluates it at both ends, the first-order error terms of the two ends cancel, and what remains is per step and in total.

[2]lines 70–112

The exact answers

The error of a time-stepping scheme is measured against the exact solution of the equations it steps, , which differs from the PDE's solution by the space error. That solution is also a sine series. The grid vectors are eigenvectors of , with eigenvalues , , which tend to as . The second difference of a quadratic is exact, so at every grid point. Expanding the constant 2 in the eigenvectors then gives the coefficients of in closed form:

which tends to as . At the sum returns to rounding (tested below). The Python reference computes the same vector as with scipy's expm and agrees to .

[3]lines 133–180

Halving the time step

The cell runs both schemes at (5 to 160 steps) and takes the largest error over the grid at . The measured order between two runs is of the ratio of their errors.

Backward Euler's order climbs from 0.94 to 0.996, toward 1. Crank-Nicolson's is 2.14, 2.09, 2.11, 2.23 and then 2.000. The excess over 2 comes from the fast modes. For a mode with , Crank-Nicolson's factor per step, , is negative and close to , so the scheme barely damps a mode the equation kills at once. Backward Euler's factor goes to 0 instead. At that is every mode from up, and it adds 47% (fast_share) to the error of the slowest mode alone. As shrinks those modes have decayed before they matter; at the error is the slowest mode's to 1%, and its order is 2.000.

Against the PDE's own Fourier series the Crank-Nicolson error falls with the rest until it meets the space error, (the horizontal line). The two errors have opposite signs, so at they partly cancel and the total dips below both. After that the total is the space error. Refining further buys nothing unless is refined with it.

[4]lines 207–313