微分方程数值解
核心思想:用差分代替微分
常微分方程
eg1:$$\begin{equation}
\begin{cases}
y’=y-\frac{2x}{y}, 0<x<1 \\
y\left( 0 \right) =1 \
\end{cases}
\end{equation}$$
欧拉法
迭代方程:
yn+1=yn+hf(xn,yn)
将例题1微分方程转化为迭代方程:
yn+1=yn+h(yn−yn2xn)
function yn1=myfun(xn,yn,h)
yn1=yn+h*(yn-2*xn/yn);
end
直接一个循环就出来了:
clc;clear;
yn=1;%设置初值
xn=0;%设置起点
Xs=1;%设置终点
h=0.1;%设置步长
x(1)=xn;y(1)=yn;%用于存储变量与函数值
i=1;
while xn<Xs %当xn达到研究区间上限结束
yn=myfun(xn,yn,h);
xn=xn+h;
i=i+1;
x(i)=xn;y(i)=yn;
end
plot(x,y,x,sqrt(1+2*x));
xlabel('自变量x')
ylabel('函数值y')
legend('欧拉法','实际值');
figure;
plot(x,y-sqrt(1+2*x))
legend('误差值')
结果如下:


改进欧拉法
改进欧拉法实则首先用欧拉法进行预测估计:
yˉn+1=yn+hf(xn,yn)
再利用梯形公式估计:
yn+1=yn+2h[f(xn,yn)+f(xn+1,yˉn+1)]
转化为平均化形式:
⎩⎪⎪⎨⎪⎪⎧yp=yn+hf(xn,yn)yc=yn+hf(xn+1,yp)yn+1=21(yp+yc)
相比于欧拉法只是迭代方程产生区别:
function yn1=myfun(xn,yn,h)
yp=yn+h*(yn-2*xn/yn);
yc=yn+h*(yn-2*(xn+h)/yp);
yn1=1/2*(yp+yc);
end


可以看出确实改善了求解精度
显式R-K方法
R-K方法是对欧拉方法的推广,只是将:
Δy=yn+1−yn=∫xnxn+1f(x,y(x))dx≈hi=1∑rcif(xn+λih,y(xn+λih))
积分的精度调高了,为了保证精度和减少计算,一般采用四阶龙格库塔法,通过待定系数可以求出四阶R-K方程模型:
⎩⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎧yn+1=yn+6h(K1+2K2+2K3+K4)K1=f(xn,yn)K2=f(xn+2h,yn+2hK1)K3=f(xn+2h,yn+2hK2)K4=f(xn+h,yn+hK3)
注意:R-K法是基于泰勒展开的方法,要求解具有较好的光滑性质,如果解得光滑性差,使用四阶龙格库塔求得的结果效果反而不如改进的欧拉方法,建模时需要对不同问题进行判断使用
结果:


其截断误差是:
o(h5)
刚性方程组
eg2:
⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧u′=−1000.25u+999.75v+0.5v′=999.75u−1000.25v+0.5u(0)=1v(0)=−1
利用龙格库塔求出结果:




我针对特殊情况总结了一下流程:
首先对方程组进行降阶处理转化为一阶n元微分方程组:
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧y1′=f1(x,y1,y2⋯yN)y2′=f2(x,y1,y2⋯yN)⋮yN′=fN(x,y1,y2⋯yN)y1(x0)=a1y2(x0)=a2⋮yN(x0)=aN
其次根据R-K公式得到:
⎩⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎧yn+11=yn1+6h(K11+2K21+2K31+K41)yn+12=yn2+6h(K12+2K22+2K32+K42)⋮yn+1N=ynN+6h(K1N+2K2N+2K3N+K4N)
其中:
⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧K1i=fi(x,y1,y2⋯yN)K2i=fi(x+2h,y1+2hK11,y2+2hK12,⋯,yN+2hK1N)K3i=fi(x+2h,y1+2hK21,y2+2hK22,⋯,yN+2hK2N)K4i=fi(x+h,y1+hK31,y2+hK32,⋯,yN+hK3N)
即可