如何以相同的步长将Euler方法与二阶Runge-Kutta方法进行比较?

问题描述 投票:0回答:1

我有两种求解数值微分方程问题的算法,一种称为Euler方法,另一种称为二阶Runge Kutta(RK2)。本质上,欧拉方法和RK2近似为微分方程的解。唯一的区别是他们使用了不同的公式(Euler使用泰勒级数的一阶导数,而RK2使用泰勒级数的二阶导数)。

我正在尝试更正我编写的一些代码,以使其返回以下解决方案,enter image description here

但是,关于RK2,我的代码没有返回正确的值,但是返回了以下内容,

enter image description here

请注意,在我的解决方案中,我将步长h称为dt。我在下面提供了用于创建此代码的代码,然后提供了一个以数字方式工作的二阶Runge Kutta方法的数字示例。我感兴趣的是,RK2的收敛速度比Euler的方法更快。

import matplotlib.pyplot as plt
import numpy as np
from math import exp  # exponential function

dy = lambda x, y: x * y
f = lambda x: exp(x ** 2 / 2)  # analytical solution function
x_final = 2

# analytical solution
x_a = np.arange(0, x_final, 0.01)
y_a = np.zeros(len(x_a))
for i in range(len(x_a)):
    y_a[i] = f(x_a[i])
plt.plot(x_a, y_a, label="analytical")

# Container for step sizes dt /dt
dt = 0.5

x = 0
y = 1
print("dt = " + str(dt))
print("x \t\t y (Euler) \t y (analytical)")
print("%f \t %f \t %f" % (x, y, f(x)))

n = int((x_final - x) / dt)

x_n = np.zeros(n + 1)
y_n = np.zeros(n + 1)
x_n[0] = x
y_n[0] = y

#Plot Euler's method
for i in range(n):
    y += dy(x, y) * dt
    x += dt
    print("%f \t %f \t %f" % (x, y, f(x)))
    x_n[i + 1] = x
    y_n[i + 1] = y

plt.plot(x_n, y_n, "x-", label="Euler dt=" + str(dt))

###################33
# Runge-Kutta's method 2'nd order (RK2)
x = 0
y = 1
print("dt = " + str(dt))
print("x \t\t y (rk2) \t y (analytical)")
print("%f \t %f \t %f" % (x, y, f(x)))

n = int((x_final - x) / dt)

x_n = np.zeros(n + 1)
y_n = np.zeros(n + 1)
x_n[0] = x
y_n[0] = y

# Plot the RK2
for z in range(n):
    K1 = dt*dy(x,y) # Step 1
    K2 = dt*dy(x+dt/2,y+K1/K2) # Step 2
    y += K2 # Step 3
    x += dt
    print("%f \t %f \t %f" % (x, y, f(x)))
    x_n[i + 1] = x
    y_n[i + 1] = y

plt.plot(x_n, y_n, "x-", label="RK2 dt=" + str(dt))

plt.title("Euler's method ")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.show()

这是适用于RK2的数字代码。我已经在Euler方法所做的更改中添加了步骤1,2和3,这使我们可以创建RK2。

from math import exp
dy = lambda x,y: x*y
f = lambda x: exp(x**2/2)
x = 0
xn = 2
y = 1
dt = 0.5
n = int((xn)/dt)
print ('x \t\t y (RK2) \t y (analytical)')
print ('%f \t %f \t %f'% (x,y,f(x)))
# main loop
for i in range(n):
    K1 = dt*dy(x, y) # step 1
    K2 = dt*dy(x + dt/2, y + K1/2) # step 2
    y += K2  # step 3
    x += dt
    print ('%f \t %f \t %f'% (x,y,f(x)))

对不起,如果我问的很不好。我是python的新手,所以我仍在尝试了解如何解决这些类型的问题。我的问题的摘要是如何解决上述功能,以便计算正确的估算值,然后使用来自python的matplotlib将其绘制在图上。

python matplotlib numeric differential-equations runge-kutta
1个回答
0
投票

有两个小细节:

  1. 在RK-2循环中,您使用的是z,但要使用i来存储值
  2. 在初始代码中,您在更新K2时使用y + K1 / K2,这是错误的。我看到您在第二个代码中对其进行了修复。

因此,固定代码为:

import matplotlib.pyplot as plt
import numpy as np
from math import exp  # exponential function

dy = lambda x, y: x * y
f = lambda x: exp(x ** 2 / 2)  # analytical solution function
x_final = 2

# analytical solution
x_a = np.arange(0, x_final, 0.01)
y_a = np.zeros(len(x_a))
for i in range(len(x_a)):
    y_a[i] = f(x_a[i])

plt.plot(x_a, y_a, label="analytical")

# Container for step sizes dt /dt
dt = 0.5

x = 0
y = 1
print("dt = " + str(dt))
print("x \t\t y (Euler) \t y (analytical)")
print("%f \t %f \t %f" % (x, y, f(x)))

n = int((x_final - x) / dt)

x_e = np.zeros(n + 1)
y_e = np.zeros(n + 1)
x_e[0] = x
y_e[0] = y

#Plot Euler's method
for i in range(n):
    y += dy(x, y) * dt
    x += dt
    print("%f \t %f \t %f" % (x, y, f(x)))
    x_e[i + 1] = x
    y_e[i + 1] = y

plt.plot(x_e, y_e, "x-", label="Euler dt=" + str(dt))

###################33
# Runge-Kutta's method 2'nd order (RK2)
x = 0
y = 1
print("dt = " + str(dt))
print("x \t\t y (rk2) \t y (analytical)")
print("%f \t %f \t %f" % (x, y, f(x)))

n = int((x_final - x) / dt)

x_r = np.zeros(n + 1)
y_r = np.zeros(n + 1)
x_r[0] = x
y_r[0] = y

# Plot the RK2
for i in range(n):
    K1 = dt*dy(x,y) # Step 1
    K2 = dt*dy(x+dt/2,y+K1/2) # Step 2
    y += K2 # Step 3
    x += dt
    print("%f \t %f \t %f" % (x, y, f(x)))
    x_r[i + 1] = x
    y_r[i + 1] = y

plt.plot(x_r, y_r, "s-", label="RK2 dt=" + str(dt))

plt.title("numerical differential equation problem")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.show()
© www.soinside.com 2019 - 2024. All rights reserved.