常微分方程(ODE)的数值计算方法

目录

      • 1/ 欧拉法(Euler Method)[^2]
      • 2/ 龙格-库塔法(Runge-Kutta Method)
        • 2.1/ 四阶 Runge-Kutta 方法
        • 2.2/ Runge-Kutta 的一般形式
      • 参考

常微分方程组的求解比较麻烦,通常在计算机上使用数值计算的方式去进行。

假设一阶常微分方程组(ODEs)由下式给出

d x d t = f i ( x ) ,   i = 1 , 2 , … , n \frac{dx}{dt}=f_i(x),~i=1,2,\dots,n dtdx=fi(x), i=1,2,,n
其中 x x x 是一个变量构成的向量 x = [ x 1 , x 2 , … , x n ] x=[x_1,x_2,\dots,x_n] x=[x1,x2,,xn]。任意高阶微分方程都可以通过变量替换变成一阶微分方程组。

求解 ODE 的数值方法有很多种:欧拉法(Euler)、龙格-库塔法(Runge-Kutta)、Adams 线性多步法、Gear 法等 1

1/ 欧拉法(Euler Method)2

在数学和计算科学中,欧拉方法(也叫前向欧拉方法)是一种用于求解给定初值的 ODE 的一阶数值过程,是对常微分方程进行数值积分的最基本的显式方法,也是最简单的 Runge-Kutta 方法。

欧拉方法以列昂哈德·欧拉(Leonhard Euler)的名字命名,在他的《计算积分学》(1768-1870年出版)一书中首次提出。

欧拉方法是一阶方法,它的局部误差(每步误差)与步长的平方成正比,全局误差(给定时间的误差)与步长成正比。 欧拉方法通常作为构造更复杂方法的基础,例如预测器-校正器(Predictor-Corrector)方法。

假设有一个 ODE:
y ′ ( t ) = f ( t , y ( t ) ) , y ( t 0 ) = y 0 , y^{\prime}(t)=f(t,y(t)),\quad y(t_0)=y_0, y(t)=f(t,y(t)),y(t0)=y0,
尽管曲线是未知的,但是起点是已知的。根据微分方程,可以计算出 A 0 A_0 A0 点的斜率,因此可以计算出切线,我们根据该切线走一小步到 A 1 A_1 A1 点。然后再根据 A 1 A_1 A1 点得到该位置的斜率,根据这个斜率走一小步去下一个点 A 2 A_2 A2

如此反复,如果步长取足够的小,那么得到的结果将会很接近确切解。

Euler 方法的迭代公式为:
y n + 1 = y n + h f ( t n , y n ) t n + 1 = t n + h \begin{aligned} y_{n+1}&=y_n+hf(t_n,y_n)\\ t_{n+1}&=t_n+h \end{aligned} yn+1tn+1=yn+hf(tn,yn)=tn+h

2/ 龙格-库塔法(Runge-Kutta Method)

2.1/ 四阶 Runge-Kutta 方法

在数值分析中,Runge-Kutta 方法是一组隐式和显式迭代方法,其中包括欧拉方法,用于时间离散化中的常微分方程的近似解。由国数学家卡尔 • 朗格(Carl Runge)和威廉 • 库塔(Wilhelm Kutta)于 1900 年左右开发。

设一个初值问题如下定义:
d y d t = y ′ ( t ) = f ( t , y ) , y ( t 0 ) = y 0 \frac{dy}{dt}=y^{\prime}(t)=f(t,y),\quad y(t_0)=y_0 dtdy=y(t)=f(t,y),y(t0)=y0
其中 y y y 是一个关于时间 t t t 的未知函数(标量或向量),也是需要近似的函数。已知 y ′ ( t ) y^{\prime}(t) y(t) 是关于 t t t y y y 自身的函数,在时间 t 0 t_0 t0 对应的 y y y 值为 y 0 y_0 y0。 函数 f f f 和初始条件 t 0 , y 0 t_0,y_0 t0,y0 已经给出。选择一个步长 h > 0 h>0 h>0 并且对于 n = 0 , 1 , 2 , 3 , … , n=0,1,2,3,\dots, n=0,1,2,3,, 定义:
y n + 1 = y n + 1 6 h ( k 1 + 2 k 2 + 2 k 3 + k 4 ) t n + 1 = t n + h \begin{aligned} y_{n+1}&=y_{n}+\frac{1}{6} h\left(k_{1}+2 k_{2}+2 k_{3}+k_{4}\right)\\ t_{n+1}&=t_{n}+h \end{aligned} yn+1tn+1=yn+61h(k1+2k2+2k3+k4)=tn+h
其中,
k 1 = f ( t n , y n ) , k 2 = f ( t n + h 2 , y n + h k 1 2 ) , k 3 = f ( t n + h 2 , y n + h k 2 2 ) , k 4 = f ( t n + h , y n + h k 3 ) . \begin{aligned} k_{1}&=f\left(t_{n}, y_{n}\right),\\ k_{2}&=f\left(t_{n}+\frac{h}{2}, y_{n}+h \frac{k_{1}}{2}\right),\\ k_{3}&=f\left(t_{n}+\frac{h}{2}, y_{n}+h \frac{k_{2}}{2}\right),\\ k_{4}&=f\left(t_{n}+h, y_{n}+h k_{3}\right). \end{aligned} k1k2k3k4=f(tn,yn),=f(tn+2h,yn+h2k1),=f(tn+2h,yn+h2k2),=f(tn+h,yn+hk3).

在不同的资料中可能会有不同的但是等价的公式表示。

其中 y n + 1 y_{n+1} yn+1 y ( t n + 1 ) y(t_{n+1}) y(tn+1) 的四阶 Runge-Kutta (RK4)近似,下一个值 ( y n + 1 ) (y_{n+1}) (yn+1) 由当前值 ( y n ) (y_n) (yn) 加上四个增量的加权平均确定,每个增量为间隔大小 h h h 和微分方程右侧的函数 f f f 指定的估计斜率的乘积。

  • k 1 k_1 k1 是间隔开始处的斜率,依赖于 y y y(这第一步是欧拉法);
  • k 2 k_2 k2 是间隔中点处的斜率,依赖于 y y y k 1 k_1 k1
  • k 3 k_3 k3 依旧是间隔中点处的斜率,只是依赖于 y y y k 2 k_2 k2 了;
  • k 4 k_4 k4 是间隔终点处的斜率,依赖于 y y y k 3 k_3 k3.

RK4 是四阶的方法,意味着局部截断误差的阶数为 O ( h 5 ) \mathcal{O}(h^5) O(h5),总积累误差的阶数为 O ( h 4 ) \mathcal{O}(h^4) O(h4).

在实际应用的时候,特别是在物理上,函数 f f f t t t 无关,即所谓的自治系统(Autonomous system)或者时不变系统,它们的增量不会被计算,也不会传递给函数 f f f,而仅仅使用 t n + 1 t_{n+1} tn+1 的最终公式。

2.2/ Runge-Kutta 的一般形式

上面介绍的是 RK4,它只是 Runge-Kutta 的其中一种。实际上,Runge-Kutta 有很多种,如果把它写成一般的形式,有
y n + 1 = y n + h ∑ j = 1 s b z k i y_{n+1}=y_{n}+h \sum_{j=1}^{s} b_{\mathbf{z}} k_{i} yn+1=yn+hj=1sbzki
其中
k 1 = f ( t n , y n ) k 2 = f ( t n + c 2 h , y n + h ( a 21 k 1 ) ) , k 3 = f ( t n + c 3 h , y n + h ( a 31 k 1 + a 32 k 2 ) ) , ⋮ k s = f ( t n + c s h , y n + h ( a s 1 k 1 + a s 2 k 2 + ⋯ + a s , s − 1 k s − 1 ) ) . \begin{aligned} k_{1} &=f\left(t_{n}, y_{n}\right) \\ k_{2} &=f\left(t_{n}+c_{2} h, y_{n}+h\left(a_{21} k_{1}\right)\right), \\ k_{3} &=f\left(t_{n}+c_{3} h, y_{n}+h\left(a_{31} k_{1}+a_{32} k_{2}\right)\right), \\ & \vdots \\ k_{s} &=f\left(t_{n}+c_{s} h, y_{n}+h\left(a_{s 1} k_{1}+a_{s 2} k_{2}+\cdots+a_{s, s-1} k_{s-1}\right)\right) . \end{aligned} k1k2k3ks=f(tn,yn)=f(tn+c2h,yn+h(a21k1)),=f(tn+c3h,yn+h(a31k1+a32k2)),=f(tn+csh,yn+h(as1k1+as2k2++as,s1ks1)).
从公式中可以知道,如果要指定某个特定的方法,就需要提供一个整数 s s s(代表级数的项数),还有系数 a i j ,  for  1 ≤ j < i ≤ s a_{ij},~\text{for }1\le jaij, for 1j<is, b i ,  for  i = 1 , 2 , … , s b_i,~\text{for }i=1,2,\dots,s bi, for i=1,2,,s c i  for  i = 2 , 3 , … , s c_i~\text{for }i=2,3,\dots,s ci for i=2,3,,s.

其中矩阵 [ a i j ] [a_{ij}] [aij] 称为 Runge-Kutta 矩阵,而 b i b_i bi c i c_i ci 是权重和节点。

Taylor 级数展开式表明,Runge-Kutta 方法是一致的,当且仅当
∑ i = 1 s b i = 1 \sum_{i=1}^s b_i=1 i=1sbi=1

参考


  1. 知乎:常微分法数值计算方法 ↩︎

  2. Wikipedia: Euler method ↩︎

你可能感兴趣的:(数学,算法,数值计算,ODE,常微分方程,runge-kutta,methods)