综述:
我们知道欧拉方法用到了一个点的函数值,是一阶方法,改进的欧拉方法用到了两个点的函数值,变成了二阶的方法,为了提高精度,用更多的节点的线性组合来计算的近似值。
构造时要求近似公式在处的Taylor展开式与解在处的taylor展开式的前几项重合,从而使近似公式达到所需要的阶数。
本文将以一具体微分方程为例,使用C++采用4阶RK方法对其求解。
目录
题目:
用4阶R-K方法求初值问题
的数值解,取步长h=0.2
4阶R-K公式:
代码实现:
高阶RK推导起来比欧拉和改进欧拉难不少,主要是选择合适的权值使得截断误差的阶变高,有一点需要注意当RK方法大于4阶后,会多偏导数的项改变权值不会使他为0。
但是这个代码实现起来更加简单~
#include <iostream>
#include <iomanip>
using namespace std;
class RK
{
public:
RK(double x0,double y0,int n,double h)
{
this->m_h = h;
this->m_n = n;
this->m_x = x0;
this->m_y = y0;
}
double fun(double x,double y)//函数y'=y-2x/y
{
return (y - (x * 2.0) / y);
}
void RKfun()
{
double K1, K2, K3, K4;
K1 = K2 = K3 = K4 = 0.0;
double yn_next = 0.0;
int n = this->m_n;
double sh = this->m_h / 2.0;
while (n)
{
K1 = fun(this->m_x,this->m_y);
K2 = fun(this->m_x + sh, this->m_y + K1 * sh);
K3 = fun(this->m_x + sh, this->m_y + K2 * sh);
K4 = fun(this->m_x + this->m_h, this->m_y + this->m_h * K3);
yn_next = this->m_y + sh/3.0 * (K1 + 2.0 * K2 + 2.0 * K3 + K4);
cout << "n = " << this->m_n - n + 1 << "时: " << "yn = " << setprecision(5)<<yn_next << endl;
this->m_x += this->m_h;
this->m_y = yn_next;
n--;
}
}
int m_n;
double m_h;
double m_x;
double m_y;
};
int main()
{
RK rk4(0, 1.0, 5, 0.2);
rk4.RKfun();
return 0;
}
运行结果:
数值解与真实解比较:
0.2 | 1.1832 | 1.1832 |
0.4 | 1.3417 | 1.3416 |
0.6 | 1.4833 | 1.4832 |
0.8 | 1.6125 | 1.6125 |
1.0 | 1.7321 | 1.7321 |
由上表可以看出4阶RK方法的精度很高,在等于0.2 0.8 1.0处相等
总结:
RK方法的导出基于Taylor展开,故它要求所求问题的解具有较高的光滑度。当解充分光滑时,4阶RK方法确实优于改进Euler方法。对于大量实际问题来说,四阶RK方法一般可以达到精度要求。但是如果解的光滑性差,4阶RK求解的效果不如改进Euler。