四种有限差分方法的数学推导
简介
本文默认读者对有限差分方法有一定了解,因此不做过多的前置知识介绍。考虑如下初值问题:
将 划分为 个等距区间,,我们有以下几种有限差分格式用于求其数值解:
向前欧拉格式:
向后欧拉格式:
跃点(Leap frog)格式:
梯形格式:
接下来,对以上四种有限差分格式,我们将进行其准确性(Accuracy)与稳定性(Stability)的数学推导。
准确性推导
首先定义局部截断误差(Local Truncation Error),其定义为:其他点处的精确解在 处按照差分格式计算得到的结果与 处的精确解的差值。
警告:上述局部截断误差与通常定义的局部截断误差相差一个 ,参考时请注意。
向前欧拉格式
向前欧拉格式的局部截断误差 可表示为如下等式
对 进行 Taylor 展开有
于是有
误差 可表示为如下形式:
令 ,对误差 有如下估计:
向后欧拉格式
向后欧拉格式的局部截断误差 可表示为如下等式
对 进行 Taylor 展开有
于是有
误差 可表示为如下形式:
令 ,假定 ,对误差 有如下估计:
跃点格式
跃点格式的局部截断误差 可表示为如下等式
对 和 进行 Taylor 展开有
于是有
误差 可表示为如下形式:
令 ,对误差 有如下估计:
令 ,,则 ,且 。于是上式可改写为如下形式:
不妨假定上式中的 是由向前欧拉格式得到的,注意到 时 ,于是有
梯形格式
梯形格式的局部截断误差 可表示为如下等式
对 和 进行 Taylor 展开有
于是有
误差 可表示为如下形式:
令 ,假定 ,对误差 有如下估计:
稳定性推导
考虑模型问题
其中 为常数。定义 为舍入误差,。我们称差分格式的绝对稳定区域(Absolute Stability Region)为复平面上所有使差分格式的解稳定的 的集合。
向前欧拉格式
将格式代入模型问题可得
考虑到舍入误差,我们有 而非 :
误差 满足
假设 ,若 ,则有
其中 为常数,所以本格式的绝对稳定区域为 。
向后欧拉格式
将格式代入模型问题可得
考虑到舍入误差,我们有 而非 :
误差 满足
假设 ,若 ,则有
其中 为常数,所以本格式的绝对稳定区域为 。
跃点格式
将格式代入模型问题可得
考虑到舍入误差,我们有 而非 :
误差 满足
其中 ,多值函数 取将正数映射到正数的解析分支。随后我们有
假设 ,若 ,则有
上式同时出现 与 ,所以仅 时跃点格式稳定。令 有
其中
注意到仅 且 时上式成立,所以跃点格式的绝对稳定区域为 。
梯形格式
将格式代入模型问题可得
考虑到舍入误差,我们有 而非 :
误差 满足
假设 ,令 ,若 ,则有
其中 为常数,所以本格式的绝对稳定区域为 。
计算复杂性
记 。
对于递推式中不含 的差分格式,其求解全部 只需进行 次计算,即计算复杂度为 。
反之对于递推式中含有 的差分格式,其计算每一个 时都需要求解隐函数零点,这一过程是 的,因此整个求解过程的计算复杂度为 。
数值实验
以下面的例子对四种差分格式进行数值实验。
其中 。
上述初值问题的解析解为
网格宽度 时,使用差分格式求解上述初值问题,可得如下图表:
图 1 数值实验结果结论
由上述数值实验的实验结果,可以看出虽然向前 Euler 格式、向后 Euler 格式和跃点格式的准确性都是 的,但是跃点格式的实际准确性明显优于向前 Euler 格式和向后 Euler 格式。
而准确性为 的梯形格式则明显优于所有准确性为 的差分格式。
附录
向前欧拉格式:
function [x, result] = forward_euler(T, step, u0, f)
x = linspace(0, T, step + 1);
result = zeros(1, step + 1);
result(k) = result(k - 1) + h * f(x(k - 1), result(k - 1));
向后欧拉格式:
function [x, result] = backward_euler(T, step, u0, f)
x = linspace(0, T, step + 1);
result = zeros(1, step + 1);
temp_func = @(uk) result(k - 1) + h * f(x(k), uk) - uk;
result(k) = fzero(temp_func, result(k - 1));
跃点格式:
function [x, result] = leap_frog(T, step, u0, u1, f)
x = linspace(0, T, step + 1);
result = zeros(1, step + 1);
result(k) = result(k - 2) + 2 * h * f(x(k - 1), result(k - 1));
梯形格式:
function [x, result] = trapezoidal(T, step, u0, f)
x = linspace(0, T, step + 1);
result = zeros(1, step + 1);
temp_func = @(uk) result(k - 1) - uk + ...
h * (f(x(k), uk) + f(x(k - 1), result(k - 1))) / 2;
result(k) = fzero(temp_func, result(k - 1));