首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Runge-Kutta四阶法

Runge-Kutta四阶法
EN

Stack Overflow用户
提问于 2016-12-11 08:43:10
回答 1查看 739关注 0票数 0

我正在对两个方程组实现Runge四阶方法。

H是段数,所以T/h是步长。

代码语言:javascript
复制
def cauchy(f1, f2, x10, x20, T, h):
    x1 = [x10]
    x2 = [x20]

    for i in range(1, h):
        k11 = f1((i-1)*T/h, x1[-1], x2[-1])
        k12 = f2((i-1)*T/h, x1[-1], x2[-1])
        k21 = f1((i-1)*T/h + T/h/2, x1[-1] + T/h/2*k11, x2[-1] + T/h/2*k12)
        k22 = f2((i-1)*T/h + T/h/2, x1[-1] + T/h/2*k11, x2[-1] + T/h/2*k12)
        k31 = f1((i-1)*T/h + T/h/2, x1[-1] + T/h/2*k21, x2[-1] + T/h/2*k22)
        k32 = f2((i-1)*T/h + T/h/2, x1[-1] + T/h/2*k21, x2[-1] + T/h/2*k22)
        k41 = f1((i-1)*T/h + T/h, x1[-1] + T/h*k31, x2[-1] + T/h*k32)
        k42 = f2((i-1)*T/h + T/h, x1[-1] + T/h*k31, x2[-1] + T/h*k32)

        x1.append(x1[-1] + T/h/6*(k11 + 2*k21 + 2*k31 + k41))
        x2.append(x2[-1] + T/h/6*(k12 + 2*k22 + 2*k32 + k42))

    return x1, x2

然后我在这个系统上测试:

代码语言:javascript
复制
def f1(t, x1, x2):
    return x2

def f2(t, x1, x2):
    return -x1

def true_x1(t):
    return np.cos(t) + np.sin(t)

def true_x2(t):
    return np.cos(t) - np.sin(t)

它似乎工作得很好(我还用不同的初始值和不同的功能测试了它:所有这些都工作得很好):

代码语言:javascript
复制
x10 = 1
x20 = 1
T = 1
h = 10

x1, x2 = cauchy(f1, f2, x10, x20, T, h)
t = np.linspace(0, T, h)

plt.xlabel('t')
plt.ylabel('x1')
plt.plot(t, true_x1(t), "blue", label="true_x1")
plt.plot(t, x1, "red", label="approximation_x1")
plt.legend(bbox_to_anchor=(0.97, 0.27))
plt.show()

plt.xlabel('t')
plt.ylabel('x2')
plt.plot(t, true_x2(t), "blue", label="true_x2")
plt.plot(t, x2, "red", label="approximation_x2")
plt.legend(bbox_to_anchor=(0.97, 0.97))
plt.show()

然后,我想检查错误是否符合O(step^4)的顺序,所以我减少了步骤并计算错误,如下所示:

代码语言:javascript
复制
step = []
x1_error = []
x2_error = []
for segm in reversed(range(10, 1000)):
    x1, x2 = cauchy(f1, f2, x10, x20, T, segm)
    t = np.linspace(0, T, segm)
    step.append(1/segm)
    x1_error.append(np.linalg.norm(x1 - true_x1(t), np.inf))
    x2_error.append(np.linalg.norm(x2 - true_x2(t), np.inf))

我明白了:

代码语言:javascript
复制
plt.plot(step, x1_error, label="x1_error")
plt.plot(step, x2_error, label="x2_error")
plt.legend()

因此,误差从步长上是线性的。这真的很奇怪,因为它应该是在O(step^4)的顺序上。有人能告诉我我做错了什么吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-11 09:06:23

代码语言:javascript
复制
for i in range(1, h):

这将从1迭代到h-1。由于缺少最后一步,从x[h-1] at time T-T/h到time T的确切解决方案的区别是O(T/h)

因此使用

代码语言:javascript
复制
for i in range(1,h+1):

hi-1i的步骤,或者

代码语言:javascript
复制
for i in range(h):

hii+1的步骤。

此外,np.linspace(0,1,4)将生成4等间距的数字,其中第一个是0,最后一个是1,结果是

代码语言:javascript
复制
array([ 0.        ,  0.33333333,  0.66666667,  1.        ])

这可能不是你所期望的。因此,有了上述更正使用。

代码语言:javascript
复制
t = np.linspace(0, T, segm+1)

在两个计算中使用相同的时间点。

如果使用通常意义上的字母,hdt是步骤的大小,N是步骤的数目,那么遵循代码就更容易了。然后在循环h=T/Ndt=T/N之前定义,以避免在函数调用中重复使用T/N

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41084371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档