【系统建模与仿真】【第二节】常微分方程解法:欧拉法,改进欧拉法,龙格库塔法的推导及MATLAB实现
是因为并不是所有常微分方程都可以写出原表达式,从而算出精确的解析解,所以我们只能用数值分析的方法去近似。如下面这个常微分方程:dydx=x⋅y\frac{d y}{d x}=x \cdot ydxdy=x⋅y我们是可以求出原函数的。先将yyy除到左边来,dxdxdx乘到右边来,构造出两边都有微分项。dyy=xdx\frac{d y}{y}=x d xydy=xdx然后两边同时积分:∫dyy=∫
常系数微分方程的解法
微分方程的类型:
- 常微分方程
- 偏微分方程
常微分方程解法:
- 数值解
- 解析解
1.为什么非要用数值解的解法来解常微分方程呢?
是因为并不是所有常微分方程都可以写出原表达式,从而算出精确的解析解,所以我们只能用数值分析的方法去近似。
如下面这个常微分方程:
d
y
d
x
=
x
⋅
y
\frac{d y}{d x}=x \cdot y
dxdy=x⋅y
我们是可以求出原函数的。
先将
y
y
y除到左边来,
d
x
dx
dx乘到右边来,构造出两边都有微分项。
d
y
y
=
x
d
x
\frac{d y}{y}=x d x
ydy=xdx
然后两边同时积分:
∫
d
y
y
=
∫
x
d
x
\int \frac{d y}{y}=\int{x} d x
∫ydy=∫xdx
ln
∣
y
∣
=
1
2
x
2
+
C
\ln |y|=\frac{1}{2} x^2+C
ln∣y∣=21x2+C
y
=
e
1
2
x
2
+
c
y=e^{\frac{1}{2} x^2+c}
y=e21x2+c
之后我们要求这个微分方程的解就可以用这个解析式进行求解(代入一个初值之后求解)。
2.为什么必须要给出一个初始值才能求解呢?
因为求导会丢失掉函数的常数项部分的信息。
如:对
x
2
x^2
x2求导之后是
2
x
2x
2x,对
x
2
+
C
x^2+C
x2+C求导之后也是
2
x
2x
2x,所以求导之后就已经无法精确的知道原函数是什么了,所以需要一个初值来确定原函数中包含的常数项。
常微分方程数值解解法:
- 欧拉法
- 梯形欧拉法
- 龙格库塔法
欧拉法
y ′ = f ( x , y ) , x ∈ [ x 0 , b ] y ( x 0 ) = y 0 y n + 1 − y n x n + 1 − x n = f ( x n , y n ) \begin{array}{l} \begin{equation} y^{\prime}=f(x, y), x \in\left[x_0, b\right] \quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad \end{equation}\\\\ \begin{equation} y\left(x_0\right)=y_0 \quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad \end{equation}\\\\ \begin{equation} \frac{y_{n+1}-y_n}{x_{n+1}-x_n}=f\left(x_n, y_n\right)\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad \end{equation} \end{array} y′=f(x,y),x∈[x0,b]y(x0)=y0xn+1−xnyn+1−yn=f(xn,yn)
对每个点做斜率,然后延长到下一个点,从而得出一条近似曲线就是上面画出的标P点的折线。即:欧拉法的主要思想就是用上面这条折线近似代替下面这条曲线。两个点之间的距离称作步长 h h h。从而得到下式,就是欧拉法解微分方程的公式。
y n + 1 = y n + h f ( x n , y n ) \begin{equation} y_{n+1}=y_n+h f\left(x_n, y_n\right) \end{equation} yn+1=yn+hf(xn,yn)
梯形欧拉法
梯形欧拉法是基于欧拉法进行改进的。
欧拉法中,
P
1
P_1
P1与
P
2
P_2
P2之间的斜率与
P
2
P_2
P2本身无关,只是从
P
1
P_1
P1处延伸过来的而已,而在梯形欧拉法中,就改进了这一点。
P
2
P_2
P2处的斜率等于
P
2
P_2
P2与
P
1
P_1
P1处的斜率的算术平均。
即:
y
n
+
1
−
y
n
x
n
+
1
−
x
n
=
1
2
(
f
(
x
n
,
y
n
)
+
f
(
x
n
+
1
,
y
n
+
1
)
)
\frac{y_{n+1}-y_n}{x_{n+1}-x_n}=\frac{1}{2}\left(f\left(x_n, y_n\right)+f\left(x_{n+1}, y_{n+1}\right)\right)
xn+1−xnyn+1−yn=21(f(xn,yn)+f(xn+1,yn+1))
然后化简之后可得:
y
n
+
1
=
y
n
+
h
2
(
f
(
x
n
,
y
n
)
+
f
(
x
n
+
1
,
y
n
+
1
)
)
.
y_{n+1}=y_n+\frac{h}{2}\left(f\left(x_n, y_n\right)+f\left(x_{n+1}, y_{n+1}\right)\right) .
yn+1=yn+2h(f(xn,yn)+f(xn+1,yn+1)).
龙格库塔法
从上面的讲解可知,欧拉法是用前一个点或者后一个点的斜率来近似代表两点之间的斜率,梯形法用前后两点的斜率的算术平均值来代替两点之间的斜率,从而达到对曲线的近似。
而龙格库塔其本质其实也和上面的方法没有区别,是用更多的点的斜率来对两点之间的斜率进行近似。
y
n
+
1
=
y
n
+
h
f
(
x
n
+
θ
h
,
y
(
x
n
+
θ
h
)
)
y_{n+1}=y_n+h f\left(x_n+\theta h, y\left(x_n+\theta h\right)\right)
yn+1=yn+hf(xn+θh,y(xn+θh))
平均斜率:
K
ˉ
=
f
(
x
n
+
θ
h
,
y
(
x
n
+
θ
h
)
)
平均斜率:\bar{K}=f\left(x_n+\theta h, y\left(x_n+\theta h\right)\right)
平均斜率:Kˉ=f(xn+θh,y(xn+θh))
通过取不同的
θ
\theta
θ值,可以控制取多少个点。在两点之间取两个点,对其斜率算加权平均值就叫做二阶龙格库塔法;在两点之间取四个点,对其斜率算加权平均值就叫做四阶龙格库塔法。当然取的点数越多,精确度越高。
{
k
1
=
f
(
x
n
,
y
n
)
.
k
2
=
f
(
x
n
+
a
1
h
,
y
n
+
h
b
21
k
1
)
.
⋮
k
r
=
f
(
x
n
+
a
r
h
,
y
n
+
h
⋅
∑
j
=
1
r
−
1
b
r
j
k
j
)
.
\left\{\begin{array}{l} k_1=f\left(x_n, y_n\right) . \\ k_2=f\left(x_n+a_1 h, y_n+h b_{21}k_1\right) . \\ \vdots \\ k_r=f\left(x_n+a_{r h}, y_n+h \cdot \sum_{j=1}^{r-1} b_{r j} k_j\right) . \end{array}\right.
⎩
⎨
⎧k1=f(xn,yn).k2=f(xn+a1h,yn+hb21k1).⋮kr=f(xn+arh,yn+h⋅∑j=1r−1brjkj).
k
ˉ
=
∑
i
=
1
r
c
i
k
i
\bar{k}=\sum_{i=1}^r c_i k_i
kˉ=i=1∑rciki
y
n
+
1
=
y
n
+
h
⋅
∑
i
=
1
l
w
i
k
i
y_{n+1}=y_n+h \cdot \sum_{i=1}^l w_i k_i
yn+1=yn+h⋅i=1∑lwiki
展开来写是这样的:
y
n
+
1
=
y
n
+
h
∑
i
=
1
l
w
i
y
n
′
(
x
n
+
a
i
h
)
y_{n+1}= y_n+h \sum_{i=1}^l w_i y_n^{\prime}\left(x_n+a_i h\right)
yn+1=yn+hi=1∑lwiyn′(xn+aih)
上式就很精准的表达了龙哥库塔法的精髓:就是取很多不同的点,算出其斜率,然后对每个斜率进行加权求和。只不过,加权的权值
w
i
w_i
wi和
k
i
k_i
ki并不是随便取的,取不同的权值会导致最后的精度不同,一般都是采用泰勒级数展开算出的权值,这种方法算出的权值可以使得近似精度最高,误差最小。
下面来证明一下龙格库塔法的系数来源:
我们假设
x
n
x_n
xn与
x
n
+
1
x_{n+1}
xn+1之间取了
i
i
i个点,每个点是
x
n
+
a
i
h
x_n+a_ih
xn+aih,
h
h
h是步长,也就是每个点的间隔。当
a
1
a_1
a1规定为等于0,也就是
x
n
+
a
1
h
x_n+a_1h
xn+a1h等于
x
n
x_n
xn。那么第二个点就是
x
n
+
a
2
h
x_n+a_2h
xn+a2h,第三个点是
x
n
+
a
3
h
x_n+a_3h
xn+a3h,以此类推。
则有:
y
n
′
(
x
n
+
a
1
h
)
=
y
n
′
(
x
n
)
=
f
(
x
n
,
y
n
)
=
k
1
y_n^{\prime}\left(x_n+a_1 h\right)=y_n^{\prime}\left(x_n\right)=f\left(x_n, y_n\right)=k_1
yn′(xn+a1h)=yn′(xn)=f(xn,yn)=k1
所以当我们忽略其他点,让
i
i
i只能取1的时候,会发现式子就变成了欧拉法的样子,所以欧拉法其实是包含在龙哥库塔法中的。
同样的,当
i
i
i取2的时候有:
y
n
′
(
x
n
+
a
2
h
)
=
f
(
x
n
+
a
2
h
,
y
n
(
x
n
+
a
2
h
)
)
=
f
(
x
n
+
a
2
h
,
y
n
+
a
2
h
y
′
(
x
n
)
)
=
f
(
x
n
+
a
2
h
,
y
n
+
a
2
h
f
(
x
n
y
n
)
)
=
f
(
x
n
+
a
2
h
,
y
n
+
a
2
h
k
1
)
=
k
2
\begin{aligned} y_n^{\prime}\left(x_n+a_2 h\right) & =f\left(x_n+a_2 h, y_n\left(x_n+a_2 h\right)\right) \\ & =f\left(x_n+a_2 h, y_n+a_2 h y^{\prime}\left(x_n\right)\right) \\ & =f\left(x_n+a_2 h, y_n+a_2 h f\left(x_n y_n\right)\right) \\ & =f\left(x_n+a_2 h, y_n+a_2 h k_1\right)=k_2 \end{aligned}
yn′(xn+a2h)=f(xn+a2h,yn(xn+a2h))=f(xn+a2h,yn+a2hy′(xn))=f(xn+a2h,yn+a2hf(xnyn))=f(xn+a2h,yn+a2hk1)=k2
上面的推导中,从
y
n
(
x
n
+
a
2
h
)
y_n\left(x_n+a_2 h\right)
yn(xn+a2h)到
y
n
+
a
2
h
y
′
(
x
n
)
y_n+a_2 h y^{\prime}\left(x_n\right)
yn+a2hy′(xn)的变化可以看成是用欧拉法,也可以看作泰勒展开的前两项。
同样的当
i
i
i取3的时候有:
y
n
′
(
x
n
+
a
3
h
)
=
f
(
x
n
+
a
3
h
,
y
n
(
x
n
+
a
3
h
)
)
=
f
(
x
n
+
a
3
h
,
y
n
+
a
3
h
b
31
y
′
(
x
n
)
+
b
32
y
′
(
x
n
+
a
2
h
)
(
b
31
+
b
32
)
)
=
f
(
x
n
+
a
3
h
,
y
n
+
h
(
a
31
k
1
+
a
32
k
2
)
)
=
k
3
\begin{aligned} y_n^{\prime}\left(x_n+a_3 h\right) & =f\left(x_n+a_3 h, y_n\left(x_n+a_3 h\right)\right) \\ & =f\left(x_n+a_3 h, y_n+a_3 h \frac{b_{31} y^{\prime}\left(x_n\right)+b_{32} y^{\prime}\left(x_n+a_2 h\right)}{\left(b_{31}+b_{32}\right)}\right) \\ & =f\left(x_n+a_3 h, y_n+h\left(a_{31} k_1+a_{32} k_2\right)\right)=k_3 \end{aligned}
yn′(xn+a3h)=f(xn+a3h,yn(xn+a3h))=f(xn+a3h,yn+a3h(b31+b32)b31y′(xn)+b32y′(xn+a2h))=f(xn+a3h,yn+h(a31k1+a32k2))=k3
我们最后可以得到:
k
1
=
f
(
x
n
,
y
n
)
k
2
=
f
(
x
n
+
a
2
h
,
y
n
+
a
2
h
k
1
)
k
3
=
f
(
x
n
+
a
3
h
,
y
n
+
h
(
a
31
k
1
+
a
32
k
2
)
)
\begin{aligned} & k_1=f\left(x_n, y_n\right) \\ & k_2=f\left(x_n+a_2 h, y_n+a_2 h k_1\right) \\ & k_3=f\left(x_n+a_3 h, y_n+h\left(a_{31} k_1+a_{32} k_2\right)\right) \end{aligned}
k1=f(xn,yn)k2=f(xn+a2h,yn+a2hk1)k3=f(xn+a3h,yn+h(a31k1+a32k2))
从上面几个式子我们可以找规律,写出通式:
k
i
=
f
(
x
n
+
a
i
h
,
y
n
+
h
∑
j
=
1
j
<
i
ℓ
−
1
a
i
j
k
j
)
,
i
=
1
,
2
,
…
l
k_i=f\left(x_n+a_i h, y_n+h \sum_{\substack{j=1 \\ j<i}}^{\ell-1} a_{i j} k_j\right), i=1,2, \ldots l
ki=f
xn+aih,yn+hj=1j<i∑ℓ−1aijkj
,i=1,2,…l
那么现在问题来了:这些式子中的参数
a
2
a_2
a2,
a
3
a_3
a3等等,如何求?谁决定这些参数?还有就是如何决定我们到底取几个点?算几次中间斜率?
下面我们先固定点数为2个,来解决这个问题:
Step1:
定义常微分方程:
y
n
+
1
=
y
n
+
h
(
w
1
k
1
+
w
2
k
2
)
y_{n+1}=y_n+h\left(w_1 k_1+w_2 k_2\right)
yn+1=yn+h(w1k1+w2k2)
既然取两个点,那么中间的两个斜率分别为(为了方便,把变量替换为
α
\alpha
α和
β
\beta
β):
k
1
=
f
(
x
n
,
y
n
)
k
2
=
f
(
x
n
+
a
2
h
,
y
n
+
h
a
21
k
1
)
=
f
(
x
n
+
α
h
,
y
n
+
β
h
k
1
)
\begin{aligned} k_1 & =f\left(x_n, y_n\right) \\ k_2 & =f\left(x_n+a_2 h, y_n+h a_{21} k_1\right) \\ & =f\left(x_n+\alpha h, y_n+\beta h k_1\right)\\ \end{aligned}
k1k2=f(xn,yn)=f(xn+a2h,yn+ha21k1)=f(xn+αh,yn+βhk1)
所以,目前一共有四个未知量等待解决:
w
1
,
w
2
,
α
,
β
w_1,w_2,\alpha,\beta
w1,w2,α,β。
我们使用泰勒展开来求解这几个未知量:
y
(
x
n
+
1
)
=
y
(
x
n
)
+
h
y
′
(
x
n
)
+
h
2
2
!
y
′
′
(
x
n
)
+
h
3
3
!
y
′
′
′
(
x
n
)
+
⋯
y
′
(
x
n
)
=
f
(
x
n
,
y
n
)
y
′
′
(
x
n
)
=
[
∂
f
∂
x
+
f
(
x
,
y
)
∂
f
∂
y
]
∣
(
x
n
,
y
n
)
\begin{aligned} & y\left(x_{n+1}\right)=y\left(x_n\right)+h y^{\prime}\left(x_n\right)+\frac{h^2}{2 !} y^{\prime \prime}\left(x_n\right)+\frac{h^3}{3 !} y^{\prime \prime \prime}\left(x_n\right)+\cdots \\ & y^{\prime}\left(x_n\right)=f\left(x_n, y_n\right) \\ & y^{\prime \prime}\left(x_n\right)=[\frac{\partial f}{\partial x}+\left.f(x,y) \frac{\partial f}{\partial y}]|_{\left(x_n, y_n\right)}\right. \end{aligned}
y(xn+1)=y(xn)+hy′(xn)+2!h2y′′(xn)+3!h3y′′′(xn)+⋯y′(xn)=f(xn,yn)y′′(xn)=[∂x∂f+f(x,y)∂y∂f]∣(xn,yn)
y
′
′
′
(
x
n
)
=
∂
2
f
∂
x
2
+
2
f
∂
2
f
∂
x
∂
y
+
∂
2
f
∂
y
2
+
∂
f
∂
y
(
∂
f
∂
x
+
f
∂
f
∂
y
)
∣
(
x
n
,
y
n
)
y^{\prime \prime \prime}\left(x_n\right)=\frac{\partial^2 f}{\partial x^2}+2 f \frac{\partial^2 f}{\partial x \partial y}+\frac{\partial^2 f}{\partial y^2}+\left.\frac{\partial f}{\partial y}\left(\frac{\partial f}{\partial x}+f \frac{\partial f}{\partial y}\right)\right|_{\left(x_n, y_n\right)}
y′′′(xn)=∂x2∂2f+2f∂x∂y∂2f+∂y2∂2f+∂y∂f(∂x∂f+f∂y∂f)
(xn,yn)
然后我们将求得的斜率也做泰勒展开;
k
1
=
f
(
x
n
,
y
n
)
k
2
=
f
(
x
n
+
α
h
,
y
n
+
β
h
k
1
)
=
f
(
x
n
,
y
n
)
+
α
h
∂
f
∂
x
+
β
h
k
1
∂
f
∂
y
+
1
2
!
(
α
2
h
2
∂
2
f
∂
x
2
+
2
α
β
h
2
k
1
∂
2
f
∂
x
∂
y
+
β
2
h
2
k
1
2
∂
2
f
∂
y
2
)
+
…
.
\begin{aligned} k_1= & f\left(x_n, y_n\right) \\ k_2= & f\left(x_n+\alpha h, y_n+\beta h k_1\right) \\ = & f\left(x_n, y_n\right)+\alpha h \frac{\partial f}{\partial x}+\beta h k_1 \frac{\partial f}{\partial y} \\ & +\frac{1}{2 !}\left(\alpha^2 h^2 \frac{\partial^2 f}{\partial x^2}+2 \alpha \beta h^2 k_1 \frac{\partial^2 f}{\partial x \partial y}+\beta^2 h^2 k_1^2 \frac{\partial^2 f}{\partial y^2}\right) \\ & +\ldots . \end{aligned}
k1=k2==f(xn,yn)f(xn+αh,yn+βhk1)f(xn,yn)+αh∂x∂f+βhk1∂y∂f+2!1(α2h2∂x2∂2f+2αβh2k1∂x∂y∂2f+β2h2k12∂y2∂2f)+….
再带入原式中得:
y
n
+
1
=
y
n
+
h
w
1
k
1
+
h
w
2
k
2
=
y
n
+
h
ω
1
f
+
h
ω
2
[
f
+
h
(
α
∂
f
∂
x
+
β
f
∂
f
∂
y
)
+
h
2
2
!
(
α
2
∂
2
f
∂
x
2
+
2
α
β
f
∂
2
f
∂
x
∂
y
+
β
2
f
2
∂
2
f
∂
y
2
)
+
⋅
⋅
]
\begin{aligned} y_{n+1}= & y_n+h w_1 k_1+h w_2 k_2 \\ = & y_n+h \omega_1 f+h \omega_2\left[f+h\left(\alpha \frac{\partial f}{\partial x}+\beta f \frac{\partial f}{\partial y}\right)\right. \\ & \left.+\frac{h^2}{2 !}\left(\alpha^2 \frac{\partial^2 f}{\partial x^2}+2 \alpha \beta f \frac{\partial^2 f}{\partial x \partial y}+\beta^2 f^2 \frac{\partial^2 f}{\partial y^2}\right)+\cdot \cdot\right] \end{aligned}
yn+1==yn+hw1k1+hw2k2yn+hω1f+hω2[f+h(α∂x∂f+βf∂y∂f)+2!h2(α2∂x2∂2f+2αβf∂x∂y∂2f+β2f2∂y2∂2f)+⋅⋅]
化简可得原式如下:
y
n
+
1
≃
y
n
+
h
(
w
1
+
w
2
)
f
+
w
2
h
2
(
α
∂
f
∂
x
+
β
f
∂
f
∂
y
)
+
h
3
2
w
2
(
α
2
∂
2
f
∂
x
2
+
2
α
β
f
∂
2
f
∂
x
∂
y
+
β
2
f
2
∂
2
f
∂
y
2
)
+
⋯
\begin{aligned} y_{n+1} \simeq & y_n+h\left(w_1+w_2\right) f+w_2 h^2\left(\alpha \frac{\partial f}{\partial x}+\beta f \frac{\partial f}{\partial y}\right) \\ & +\frac{h^3}{2} w_2\left(\alpha^2 \frac{\partial^2 f}{\partial x^2}+2 \alpha \beta f \frac{\partial^2 f}{\partial x \partial y}+\beta^2 f^2 \frac{\partial^2 f}{\partial y^2}\right)+\cdots \end{aligned}
yn+1≃yn+h(w1+w2)f+w2h2(α∂x∂f+βf∂y∂f)+2h3w2(α2∂x2∂2f+2αβf∂x∂y∂2f+β2f2∂y2∂2f)+⋯
而
y
n
+
1
y_{n+1}
yn+1的泰勒展开如下:
y
(
x
n
+
1
)
=
y
(
x
n
)
+
h
f
+
h
2
2
(
∂
f
∂
x
+
f
∂
f
∂
y
)
+
h
3
6
(
∂
2
f
∂
x
2
+
2
f
∂
2
f
∂
x
∂
y
+
∂
2
f
∂
y
2
+
∂
f
∂
y
(
∂
f
∂
x
+
f
∂
f
∂
y
)
)
\begin{aligned} y\left(x_{n+1}\right)= & y\left(x_n\right)+h f+\frac{h^2}{2}\left(\frac{\partial f}{\partial x}+f \frac{\partial f}{\partial y}\right) \\ & +\frac{h^3}{6}\left(\frac{\partial^2 f}{\partial x^2}+2 f \frac{\partial^2 f}{\partial x \partial y}+\frac{\partial^2 f}{\partial y^2}+\frac{\partial f}{\partial y}\left(\frac{\partial f}{\partial x}+f \frac{\partial f}{\partial y}\right)\right) \end{aligned}
y(xn+1)=y(xn)+hf+2h2(∂x∂f+f∂y∂f)+6h3(∂x2∂2f+2f∂x∂y∂2f+∂y2∂2f+∂y∂f(∂x∂f+f∂y∂f))
将两个式子进行对比可得:
w
1
+
w
2
=
1
α
w
2
=
1
2
β
w
2
=
1
2
}
\left.\begin{array}{rl} w_1+w_2 & =1 \\ \alpha w_2 & =\frac{1}{2} \\ \beta w_2 & =\frac{1}{2} \end{array}\right\}
w1+w2αw2βw2=1=21=21⎭
⎬
⎫
此处共有四个未知数,但只有三个方程,所以我们只能通过一定的假设,获得他们之间的关系:
α
≠
0
,
假设
β
=
α
,
ω
2
=
1
2
α
ω
1
=
1
−
1
2
α
\begin{aligned} \alpha \neq 0, 假设\quad \beta & =\alpha, \\ \omega_2 & =\frac{1}{2 \alpha} \\ \omega_1 & =1-\frac{1}{2 \alpha} \end{aligned}
α=0,假设βω2ω1=α,=2α1=1−2α1
那么原式就是:
y
n
+
1
≃
y
n
+
h
[
(
1
−
1
2
α
)
k
1
+
1
2
α
k
2
]
k
1
=
f
(
x
n
,
y
n
)
k
2
=
f
(
x
n
+
α
h
,
y
n
+
α
h
k
1
)
\begin{aligned} & y_{n+1} \simeq y_n+h\left[\left(1-\frac{1}{2 \alpha}\right) k_1+\frac{1}{2 \alpha} k_2\right] \\ & k_1=f\left(x_n, y_n\right) \\ & k_2=f\left(x_n+\alpha h, y_n+\alpha h k_1\right) \end{aligned}
yn+1≃yn+h[(1−2α1)k1+2α1k2]k1=f(xn,yn)k2=f(xn+αh,yn+αhk1)
那么我们就可以通过给
α
\alpha
α和$\beta $不同取值来探究哪一种取值能更精确的近似。
(i)
if
α
=
1
/
2
=
β
;
w
1
=
0
,
w
2
=
1
y
n
+
1
≃
y
n
+
h
f
(
x
n
+
h
2
,
y
n
+
h
2
f
)
\begin{aligned} \text{if }\alpha=1 / 2 & =\beta ; \quad w_1=0, w_2=1 \\ y_{n+1} & \simeq y_n+h f\left(x_n+\frac{h}{2}, y_n+\frac{h}{2} f\right) \end{aligned}
if α=1/2yn+1=β;w1=0,w2=1≃yn+hf(xn+2h,yn+2hf)
(ii)
α
=
1
;
β
=
1
,
w
1
=
1
2
=
w
2
y
n
+
1
≃
y
n
+
h
2
(
k
1
+
k
2
)
k
1
=
f
k
2
=
f
(
x
n
+
α
h
,
y
n
+
β
h
k
1
)
=
f
(
x
n
+
h
,
y
n
+
h
f
)
\begin{aligned} \alpha=1 ; \quad \beta & =1, \quad w_1=\frac{1}{2}=w_2 \\ y_{n+1} & \simeq y_n+\frac{h}{2}\left(k_1+k_2\right) \\ k_1 & =f \\ k_2 & =f\left(x_n+\alpha h, y_n+\beta h k_1\right) \\ & =f\left(x_n+h, y_n+h f\right) \end{aligned}
α=1;βyn+1k1k2=1,w1=21=w2≃yn+2h(k1+k2)=f=f(xn+αh,yn+βhk1)=f(xn+h,yn+hf)
MATLAB代码实例
实例1:
求解微分方程 d y d t = − y + t + 1 \frac{dy}{dt}=-y+t+1 dtdy=−y+t+1, y 0 = 1 y_0=1 y0=1, t t t的取值是0到2,步长 h = 0.1 h=0.1 h=0.1,用欧拉法求解微分方程并将结果与 y ( t ) = e ( − t ) + t y(t)=e^{(-t)}+t y(t)=e(−t)+t比较。
clear;
clc;
h=0.1;%初始化步长
y0=1;%给定的初值
t=0:h:2;%在0到2的区间内,以h为步长,初始化自变量
y=exp(-t)+t;%这个是解析解
n=length(t);%求一下自变量有多少个,来确定下面欧拉法的循环次数
numy=zeros(1,n);%将欧拉法的y值存储在一个行向量里边
dy=0;%第一个点的导数值是:-y0+t0+1=0
numy(1)=y0;%向量的第一个值就是初值
for i=2:n
numy(i)=y0+h*dy;%计算下一个值
y0=numy(i);
dy=-y0+t(i)+1;%计算当前点的斜率,作为这一点和下一点之间的近似斜率
end
figure;
plot(t,y,'r-',LineWidth=1);
hold on;
plot(t,numy,'b-',LineWidth=1);
xlabel('t');
grid on;
title('EUuler法求系统的输出响应');
ylabel('输出响应y(t)');
legend('解析解','Euler法');
实例2:
取h=0.01,采用欧拉法求解微分方程如下:
{
y
˙
(
t
)
=
y
(
t
)
−
2
t
y
(
t
)
0
≤
t
≤
1
y
(
0
)
=
1
\left\{\begin{array}{c} \dot{y}(t)=y(t)-\frac{2 t}{y(t)} \quad 0 \leq t \leq 1 \\ y(0)=1 \end{array}\right.
{y˙(t)=y(t)−y(t)2t0≤t≤1y(0)=1
微分方程的解析解:
y
(
t
)
=
1
+
2
t
y(t)=\sqrt{1+2 t}
y(t)=1+2t
clear;
clc;
h=0.01;
y0=1;
t=0:h:2;
y=sqrt(1+2*t);
n=length(t);
numy=zeros(1,n);
dy=1;%第一个点的导数值是:-y0+t0+1=0
numy(1)=y0;
for i=2:n
numy(i)=y0+h*dy;
y0=numy(i);
dy=y0-2*t(i)/y0;
end
figure;
plot(t,y,'r-',LineWidth=1);
hold on;
plot(t,numy,'b-',LineWidth=1);
xlabel('t');
grid on;
title('EUuler法求系统的输出响应');
ylabel('输出响应y(t)');
legend('解析解','Euler法');
用梯形法改进后:
clear;
clc;
h=0.01;
y0=1;
t=0:h:2;
y=sqrt(1+2*t);
n=length(t);
numy=zeros(1,n);
dy=1;%第一个点的导数值是:-y0+t0+1=0
numy(1)=y0;
for i=2:n
numy(i)=y0+h*dy;
y1=numy(i);
dy=1/2*(y1-2*t(i)/y1+y0-2*t(i-1)/y0);
y0=y1;
end
figure;
plot(t,y,'r-',LineWidth=1);
hold on;
plot(t,numy,'b-',LineWidth=1);
xlabel('t');
grid on;
title('EUuler法求系统的输出响应');
ylabel('输出响应y(t)');
legend('解析解','Euler法');
实例3:
已知微分方程及初值如下所示,试比较在取不同步长时,其精确解与数值解之间的差异;
{
y
˙
=
−
30
y
y
(
0
)
=
1
3
0
≤
t
≤
1.5
\begin{cases}\dot{y}=-30 y & \\ y(0)=\frac{1}{3} & 0 \leq t \leq 1.5\end{cases}
{y˙=−30yy(0)=310≤t≤1.5
微分方程的解析解为:
y
(
t
)
=
1
3
e
−
30
t
y(t)=\frac{1}{3} e^{-30 t}
y(t)=31e−30t
代码:
%*************************h=0.1时曲线***************************************
clear
t(1)=0; %设置自变量初值
y(1)=1/3;y_euler(1)=1/3;y_rk4(1)=1/3; %设置解析解和数值解初值
h=0.1; %设置计算步长
%求解析解
for k=1:15
t(k+1)=t(k)+h;
y(k+1)=exp(-30*t(k+1))/3;
end
%利用欧拉法求解
for k=1:15
y_euler(k+1)=y_euler(k)+h*(-30*y_euler(k));
end
%利用RK4法求解
for k=1:15
k1=-30*y_rk4(k);
k2=-30*(y_rk4(k)+h*k1/2);
k3=-30*(y_rk4(k)+h*k2/2);
k4=-30*(y_rk4(k)+h*k3);
y_rk4(k+1)=y_rk4(k)+h*(k1+2*k2+2*k3+k4)/6;
end
%绘制解析解的曲线图
plot(t,y);
legend('解析解, h=0.1');
grid on;
%绘制欧拉法的曲线图
plot(t,y_euler);
legend('欧拉法, h=0.1');
grid on;
%绘制RK4法的曲线图
plot(t,y_rk4);
legend('RK4法, h=0.1');
grid on;
%*************************h=0.075时曲线***************************************
clear
t(1)=0; %设置自变量初值
y(1)=1/3;y_euler(1)=1/3;y_rk4(1)=1/3; %设置解析解和数值解初值
h=0.075; %设置计算步长
%求解析解
for k=1:20
t(k+1)=t(k)+h;
y(k+1)=exp(-30*t(k+1))/3;
end
%利用欧拉法求解
for k=1:20
y_euler(k+1)=y_euler(k)+h*(-30*y_euler(k));
end
%利用RK4法求解
for k=1:20
k1=-30*y_rk4(k);
k2=-30*(y_rk4(k)+h*k1/2);
k3=-30*(y_rk4(k)+h*k2/2);
k4=-30*(y_rk4(k)+h*k3);
y_rk4(k+1)=y_rk4(k)+h*(k1+2*k2+2*k3+k4)/6;
end
%绘制欧拉法的曲线图
plot(t,y_euler);
legend('欧拉法, h=0.075');
grid on;
%绘制RK4法的曲线图
plot(t,y_rk4);
legend('RK4法, h=0.075');
grid on;
%*************************h=0.05时曲线***************************************
clear
t(1)=0; %设置自变量初值
y(1)=1/3;y_euler(1)=1/3;y_rk4(1)=1/3; %设置解析解和数值解初值
h=0.05; %设置计算步长
%求解析解
for k=1:30
t(k+1)=t(k)+h;
y(k+1)=exp(-30*t(k+1))/3;
end
%利用欧拉法求解
for k=1:30
y_euler(k+1)=y_euler(k)+h*(-30*y_euler(k));
end
%利用RK4法求解
for k=1:30
k1=-30*y_rk4(k);
k2=-30*(y_rk4(k)+h*k1/2);
k3=-30*(y_rk4(k)+h*k2/2);
k4=-30*(y_rk4(k)+h*k3);
y_rk4(k+1)=y_rk4(k)+h*(k1+2*k2+2*k3+k4)/6;
end
%绘制欧拉法的曲线图
plot(t,y_euler);
legend('欧拉法, h=0.05');
grid on;
%绘制RK4法的曲线图
plot(t,y_rk4);
legend('RK4法, h=0.05');
grid on;
%绘制解析解的曲线图
plot(t,y);
legend('解析解, h=0.05');
grid on;
在MATLAB中可以画出解析解的样子,可以看到,精确解单调下降并迅速收敛到0;
当h=0.1时,欧拉法和RK4法的解曲线均发散,仿真结果是错误的;
当h=0.075时,欧拉法的解曲线仍然发散,仿真结果是错误的;RK4法的解曲线单调下降并收敛到0,仿真结果是正确的
当h=0.05时,欧拉法和RK4法的解均收敛到0(虽然欧拉法的解曲线是振荡收敛的)。如果只要求得到t=1.5处的y(t)值,则两种数值积分算法的解都可以认为是正确的。
为什么会出现这种情况呢?这要涉及到计算稳定性的问题,这一点下一节再讲。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)