为什么Python RK23解算器会爆炸并给出不现实的结果?

为什么Python RK23解算器会爆炸并给出不现实的结果?,python,scipy,ode,integrate,Python,Scipy,Ode,Integrate,我正在试验python scipy模块中的RK45/RK23解算器。用它来解简单的常微分方程,却不能给出正确的结果。当我手动为Runge Kutta 4阶编写代码时,模块中的odeint解算器也能完美工作,但RK23/RK45不能。如果有人能帮助我解决这个问题,那将是非常有帮助的。到目前为止,我只实现了简单的ODE dydt=-K*(y^2) 代码: 将numpy导入为np 来自scipy.integrate import solve_ivp、RK45、odeint 将matplotlib.py

我正在试验python scipy模块中的RK45/RK23解算器。用它来解简单的常微分方程,却不能给出正确的结果。当我手动为Runge Kutta 4阶编写代码时,模块中的odeint解算器也能完美工作,但RK23/RK45不能。如果有人能帮助我解决这个问题,那将是非常有帮助的。到目前为止,我只实现了简单的ODE

dydt=-K*(y^2)

代码:

将numpy导入为np
来自scipy.integrate import solve_ivp、RK45、odeint
将matplotlib.pyplot作为plt导入
#功能模型乐趣(y,t)
def型号(y,t):
k=0.3
dydt=-k*(y**2)
回程差
#初始条件
y0=np.数组([0.5])
y=np.零(100)
t=np.linspace(0,20)
t_span=[0,20]
#RK45执行
yr=求解ivp(fun=模型,t_span=t_span,y0=y,t_eval=t,方法=RK45)
##odeint解算器
yy=odeint(func=model,y0=y0,t=t)
##手动执行
t1=0
h=0.05
y=np.零(21)
y[0]=y0;
i=0
k=0.3
##龙格库塔四阶实现

(t1好的,我已经找到了解决方案。RK45要求函数定义像fun(t,y)一样,而odeint要求函数定义像func(y,t)因此,赋予它们相同的函数将导致不同的结果。

FYI:如果您想对
odeint
solve_ivp
使用相同的函数定义,请以
func(t,y)
的形式定义它,并将参数
tfirst=True
添加到
odeint
函数调用中。感谢专业提示:)
import numpy as np
from scipy.integrate import solve_ivp,RK45,odeint
import matplotlib.pyplot as plt


# function model fun(y,t)

def model(y,t):
    k = 0.3
    dydt = -k*(y**2)
    return dydt

# intial condition
y0 = np.array([0.5])
y = np.zeros(100)    
t = np.linspace(0,20)
t_span = [0,20]

#RK45 implementation
yr = solve_ivp(fun=model,t_span=t_span,y0=y,t_eval=t,method=RK45)

##odeint solver
yy = odeint(func=model,y0=y0,t=t)

##manual implementation
t1 = 0
h = 0.05
y = np.zeros(21)
y[0]=y0;
i=0
k=0.3
##Runge Kutta 4th order implementation
while (t1<1.):    
    m1 = -k*(y[i]**2)
    y1 = y[i]+ m1*h/2
    m2 = -k*(y1**2)
    y2 = y1 + m2*h/2
    m3 = -k*(y2**2)
    y3 = y2 + m3*h/2
    m4 = -k*(y3**2)
    i=i+1
    y[i] = y[i-1] + (m1 + 2*m2 + 2*m3 + m4)/6
    t1 = t1 + h

#plotting
t2 = np.linspace(0,20,num=21)
plt.plot(t2,y,'r-',label='RK4')
plt.plot(t,yy,'b--',label='odeint')
#plt.plot(t2,yr.y[0],'g:',label='RK45')
plt.xlabel('time')
plt.ylabel('y(t)')
plt.legend()
plt.show()