跳转到内容

并行谱数值方法/时间步长

来自维基教科书,开放的书籍,开放的世界

我们现在简要讨论如何求解初值问题。有关更多信息,请参见 Bradie (Chap. 7)[1]。Boyce 和 DiPrima 中也提供了一个更长但仍然简短的介绍。[2]

向前欧拉

[编辑 | 编辑源代码]

为了有效地计算计算机上的微分方程解,方便地在有限数量的指定点进行计算,然后在这些点之间插值。对于许多计算来说,使用网格很方便,网格上的点彼此相隔等距。

在本节的其余部分 将是我们的步长,假设它是一个常数。在求解 ODE 或 PDE 时,选择 不是随机选择的,而是需要一些直觉和/或理论分析。我们将从最基本的数值方法向前欧拉方法开始。首先用 表示第 时间步的时间,用 表示第 时间步的计算解,其中 。步长 方面的定义为 。首先从具有初始条件的基本 ODE 开始,其中 是某个任意函数, 是我们的解,

 

 

 

 

( 1)

微分方程可以用有限差分来逼近,

现在我们要做的就是用代数方法求解

 

 

 

 

( 2)

如果我们想要计算 在时间 时的值,那么我们可以利用公式 2 生成时间 时的近似值。首先找到 并用它来计算 。然后我们重复这个过程,直到达到最终时间。

一个示例计算

[edit | edit source]

让我们以公式 1 中的 ODE 为例,其初始条件为 ,其中 。使用向前欧拉法,让我们绘制两个示例,其中

公式 1 中的 ODE 的数值解,其中 f(t,y) = y,展示了向前欧拉法在不同时间步长选择下的准确性。

毫无疑问,与 相比,更小的步长,如 ,将更加准确。观察 的曲线,可以发现 仅在 4 个点处计算,然后在每个点之间进行直线插值。这显然不太准确,但可以粗略地了解函数的样子。对于 的解可能需要执行 10 倍的步骤,但它显然更加准确。向前欧拉法是 一阶方法的示例,并使用泰勒展开式中的前两项[脚注 1] 来逼近精确解。

其中,比 O 阶更高的项在逼近解中被省略。将其代入等式 2 ,我们得到:

在消去项并除以 后,我们得到:

由此可以清楚地看出,该方法的精度随步长线性变化,因此它是 一阶精度的。

向后欧拉法

[编辑 | 编辑源代码]

可以通过使用向后差分商来逼近导数,从而获得向前欧拉法的变体。使用等式 1 并应用:

将索引从 步进到 ,我们得到:

注意 不是像向前欧拉方法那样明确地写出来的。相反,这个方程隐式地定义了 ,必须求解才能确定 的值。求解的难易程度完全取决于函数 的复杂程度。例如,如果 仅仅是 ,那么可以使用二次方程,但是许多非线性偏微分方程需要其他方法。这些方法中的一部分将在后面介绍。

Crank-Nicolson 方法

[edit | edit source]

通过对向前欧拉方法和向后欧拉方法进行平均,我们可以找到 Crank-Nicolson 方法

重新排列,我们得到:

再次注意 不是像向前欧拉方法那样明确地写出来的。这个方程隐式地定义了 ,因此必须代数求解才能得到

向前欧拉、向后欧拉和 Crank-Nicolson 方法的稳定性

[edit | edit source]

让我们看一下以下常微分方程

其中 是一个常数,而 ,其中 。我们用前向欧拉法、后向欧拉法和 Crank-Nicolson 时间步进方案对这个 ODE 进行数值求解。结果如下

而精确解由下式给出

方程 2 中 ODE 的数值解,其中 λ = 20,时间步长为 h = 0.1,演示了前向欧拉法的非稳定性以及后向欧拉法和 Crank-Nicolson 法的稳定性。

上图显示了两种方法如何收敛到解,但前向欧拉解对于所选时间步长是非稳定的。下面的清单是一个 Matlab 程序,你可以用它来改变 的值,看看对于固定时间步长,这将如何改变方法的稳定性。

 

 

 

 

( A)
Matlab 程序 代码下载
% A program to demonstrate instability of timestepping methods
% when the timestep is inappropriately choosen.

%Differential equation: y'(t)=-y(t) y(t_0)=y_0
%Initial Condition, y(t_0)=1 where t_0=0
clear all; clc; clf;

%Grid
h=.1;
tmax=4;
Npoints = tmax/h;
lambda=.1;

%Initial Data
y0=1;
t_0=0;
t(1)=t_0;
y_be(1)=y0;
y_fe(1)=y0;
y_imr(1)=y0;

for n=1:Npoints
%Forward Euler
    y_fe(n+1)=y_fe(n)-lambda*h*y_fe(n);
     %Backwards Euler
    y_be(n+1)=y_be(n)/(1+lambda*h);
     %Crank Nicolson
    y_imr(n+1)=y_imr(n)*(2-lambda*h)/(2+lambda*h)
    t(n+1)=t(n)+h;
end

%Exact Solution
tt=[0:.001:tmax];
exact=exp(-lambda*tt);

%Plot
figure(1); clf; plot(tt,exact,'r-',t,y_fe,'b:',t,y_be,'g--',t,y_imr,'k-.');
xlabel time; ylabel y;
legend('Exact','Forward Euler','Backward Euler',...
'Crank Nicolson');

 

 

 

 

( Ap)
一个 Python 程序,用来演示不同时间步进方法的非稳定性。 代码下载
#!/usr/bin/env python
"""
A program to demonstrate instability of timestepping methods#
when the timestep is inappropriately choosen.################
"""

from math import exp
import matplotlib.pyplot as plt
import numpy

#Differential equation: y'(t)=-l*y(t) y(t_0)=y_0
#Initial Condition, y(t_0)=1 where t_0=0

# Definition of the Grid
h = 0.1	# Time step size
t0 = 0	# Initial value
tmax = 4	# Value to be computed y(tmax)
Npoints = int((tmax-t0)/h)	# Number of points in the Grid

t = [t0]

# Initial data
l = 0.1
y0 = 1	# Initial condition y(t0)=y0
y_be = [y0]	# Variables holding the value given by the Backward Euler Iteration
y_fe = [y0]	# Variables holding the value given by the Forward Euler Iteration
y_imr = [y0]	# Variables holding the value given by the Midpoint Rule Iteration

for i in xrange(Npoints):
    y_fe.append(y_fe[-1]*(1-l*h))
    y_be.append(y_be[-1]/(1+l*h))
    y_imr.append(y_imr[-1]*(2-l*h)/(2+l*h))
    t.append(t[-1]+h)


print "Exact Value: y(%d)=%f" % (tmax, exp(-4))
print "Backward Euler Value: y(%d)=%f" % (tmax, y_be[-1])
print "Forward Euler Value: y(%d)=%f" % (tmax, y_fe[-1])
print "Midpoint Rule Value: y(%d)=%f" % (tmax, y_imr[-1])

# Exact Solution
tt=numpy.arange(0,tmax,0.001)
exact = numpy.exp(-l*tt)

# Plot
plt.figure()
plt.plot(tt,exact,'r-',t,y_fe,'b:',t,y_be,'g--',t,y_imr,'k-.');
plt.xlabel('time')
plt.ylabel('y')
plt.legend(('Exact','Forward Euler','Backward Euler',
'Implicit Midpoint Rule'))
plt.show()

前向欧拉法、后向欧拉法和 Crank-Nicolson 时间步进方案对于 的稳定性和精度

[edit | edit source]

我们现在尝试理解这些观察结果,以便我们有一些指导方针来设计稳定的数值方法。如果数值解可以被不依赖步长的函数所限制,那么具有有界解的初值问题的数值解是稳定的。通常使用两种方法来理解稳定性。第一种方法是线性化稳定性,它涉及计算线性系统的特征值,以查看小的扰动是增长还是衰减。第二种方法是计算与微分方程相关的能量类数量,并检查它是否保持有界。

我们假设 ,以便 ODE 的精确解不会无限制地增长。前向欧拉法得到

我们可以对后向欧拉方法进行类似的计算,得到

因此,后向欧拉方法是无条件稳定的,而前向欧拉方法不是。我们留下了Crank-Nicolson方法的分析作为练习。

第二种方法,常用于显示偏微分方程的稳定性,是寻找能量式的量并证明该量可以限制解,并防止解变得过大或过小。通常,该量被选为非负的,那么只需要推导出一个上限。我们概述了如何对常微分方程进行此操作,以便我们可以在观察偏微分方程时使用相同的思想。回想一下,前向欧拉算法由下式给出

乘以该式,我们发现

现在要获得关于 的界限,该界限以 表示,我们使用以下事实

因此,如果

因此,如果 ,那么 ,因此我们得到了稳定性,再次看到该算法在时间步长足够小的情况下是稳定的。在很多情况下,很大,因此时间步长 需要非常小。在这种情况下,前向欧拉方法在计算机上可能非常慢。

稳定性不是数值方法逼近初值问题解的唯一要求。我们还希望证明,随着时间步长的减小,数值逼近会变得更好。对于前向欧拉方法,我们有

现在如果

那么[脚注 2]

所以

我们可以做类似的计算来证明Crank-Nicolson方法是二阶的。在这种情况下,我们使用围绕的泰勒展开式。

所以

因此

因此,这是一个二阶方法。

  1. 确定隐式中点规则对于常微分方程 稳定的实数 和时间步长。在 对应时间步长 的图表中绘制稳定区域。
  2. 证明后向欧拉方法是一阶方法。

备注

[edit | edit source]
  1. 泰勒展开式的推导可以在大多数微积分书籍中找到。
  2. 我们将使用大O符号来表示,如果,那么当 时,我们有,其中 是某个常数。
  1. Bradie (2006)
  2. Boyce and DiPrima (2010)

参考文献

[edit | edit source]

Boyce, W.E.; DiPrima, R.C. (2010). Elementary Differential Equations and Boundary Value Problems. Wiley. {{cite book}}: Cite has empty unknown parameter: |lnguage= (help)

Bradie, B. (2006). A Friendly Introduction to Numerical Analysis. Pearson.

华夏公益教科书