Python 使用dopri5进行ODE积分和随机模拟

Python 使用dopri5进行ODE积分和随机模拟,python,scipy,Python,Scipy,我仍然是python的初学者,但对运行模拟有一些疑问(如果这是发布我问题的错误区域,我很抱歉,在这种情况下,如果有人能告诉我哪里更适合,我将很乐意移动它)。我的目标是模拟以下微分方程系统: 因为动力系统经历了刚度,我学到的odeint积分方法一直存在问题,所以我尝试用另一种方法来积分,也就是用我听说过的dopri5方法。这似乎有效,但我注意到情节中有一些奇怪的行为。我使用的代码如下: import scipy as sp import pylab as plt import numpy as

我仍然是python的初学者,但对运行模拟有一些疑问(如果这是发布我问题的错误区域,我很抱歉,在这种情况下,如果有人能告诉我哪里更适合,我将很乐意移动它)。我的目标是模拟以下微分方程系统:

因为动力系统经历了刚度,我学到的odeint积分方法一直存在问题,所以我尝试用另一种方法来积分,也就是用我听说过的dopri5方法。这似乎有效,但我注意到情节中有一些奇怪的行为。我使用的代码如下:

import scipy as sp
import pylab as plt
import numpy as np
import scipy.integrate as spi

#Constants
c13 = 6.2
c14 = 1.0
c21 = 7.3
c32 = 2.4
c34 = 12.7
c42 = 5.7
c43 = 5.0

e12 = 1.5
e23 = 2.5
e24 = 2.0
e31 = 3.0
e41 = 4.8

#Time
t_end = 300.
t_start = 0.
t_step = 1.
t_interval = sp.arange(t_start, t_end, t_step)

#Initial Condition
ic = [0.6,0.3,0.2,0.5]

#Noise
sigma1 = 0.1
sigma2 = 0.1
sigma3 = 0.1
sigma4 = 0.1

def model(t,ic):
    Eqs= np.zeros((4))
    Eqs[0] = ic[0]+(ic[0]*(1-ic[0]*ic[0]-ic[1]*ic[1]-ic[2]*ic[2]-ic[3]*ic[3])-c21*((ic[1]*ic[1])*ic[0])+e31*((ic[2]*ic[2])*ic[0])+e41*((ic[3]*ic[3])*ic[0]))
    Eqs[1] = ic[1]+(ic[1]*(1-ic[0]*ic[0]-ic[1]*ic[1]-ic[2]*ic[2]-ic[3]*ic[3])+e12*((ic[0]*ic[0])*ic[1])-c32*((ic[2]*ic[2])*ic[1])-c42*((ic[3]*ic[3])*ic[1]))
    Eqs[2] = ic[2]+(ic[2]*(1-ic[0]*ic[0]-ic[1]*ic[1]-ic[2]*ic[2]-ic[3]*ic[3])-c13*((ic[0]*ic[0])*ic[2])+e23*((ic[1]*ic[1])*ic[2])-c43*((ic[3]*ic[3])*ic[2]))
    Eqs[3] = ic[3]+(ic[3]*(1-ic[0]*ic[0]-ic[1]*ic[1]-ic[2]*ic[2]-ic[3]*ic[3])-c14*((ic[0]*ic[0])*ic[3])+e24*((ic[1]*ic[1])*ic[3])-c34*((ic[2]*ic[2])*ic[3]))
    return Eqs

ode =  spi.ode(model)
ode.set_integrator('dopri5',method='bdf')
ode.set_initial_value(ic,t_start)
ts = []
ys = []

while ode.successful() and ode.t < t_end:
    ode.integrate(ode.t + t_step)
    ts.append(ode.t)
    ys.append(ode.y)

t = np.vstack(ts)
x1,x2,x3,x4 = np.vstack(ys).T

plt.subplot(4, 1, 1)
plt.plot(t, x1, 'b')
plt.xlim([0,t_end])

plt.subplot(4, 1, 2)
plt.plot(t, x2, 'r')
plt.xlim([0,t_end])

plt.subplot(4, 1, 3)
plt.plot(t, x3, 'g')
plt.xlim([0,t_end])

plt.subplot(4, 1, 4)
plt.plot(t, x4, 'purple')
plt.xlim([0,t_end])
plt.xlabel('Time')

plt.show()

代码无法正常运行。看来我写的不是使这些方程随机的合适方法。在这些方程中加入随机扰动的最佳方法是什么?我最近听说了一种叫做PyS3DE的东西,但我对它一无所知。

仅供参考:
dopri5
用于非敌我系统。
set\u integrator
方法毫无怨言地接受参数
method='bdf'
,但在使用
dopri5
时忽略该参数。(是的,我知道,这真的很烦人。)另外,
scipy.integrate.odeint
是Fortran代码LSODA的包装,它会自动检测刚度并在适当的时候切换到刚度解算器,所以如果你真的有刚度问题,你从
odeint
切换到
ode
类的
dopri5
解算器对我来说没有多大意义。“我的另一个问题…”最好一次只问一个问题。为什么你有
Eqs[0]=ic[0]+…
?孤立项
ic[0]
不在上述方程式中。(同样地,对于
模型中的其他方程
)@WarrenWeckesser,“Eqs[0]=ic[0]+…”这个术语是因为我是个白痴,不能从我以前使用的不同方案中翻译我的代码。谢谢你找到那个!当我使用odeint时,问题是变量x1、x2等取负值:()。我以为dopri5适用于僵硬的系统,所以这是我的错误,但在这种情况下,dopri5似乎给出了更准确的结果。我的一位前助教建议我的方程非常有用,所以我正在尝试找到最好的方法来正确地整合它们。你应该用
dopri5
得到一个好的解决方案,但是它可能比一个僵硬的解算器做更多的工作(因此需要更长的时间)。您也可以尝试
'vode'
,它确实接受并实际使用
方法='bdf'
。有关更多选项,请参阅。仅供参考:
dopri5
用于非敌我识别系统。
set\u integrator
方法毫无怨言地接受参数
method='bdf'
,但在使用
dopri5
时忽略该参数。(是的,我知道,这真的很烦人。)另外,
scipy.integrate.odeint
是Fortran代码LSODA的包装,它会自动检测刚度并在适当的时候切换到刚度解算器,所以如果你真的有刚度问题,你从
odeint
切换到
ode
类的
dopri5
解算器对我来说没有多大意义。“我的另一个问题…”最好一次只问一个问题。为什么你有
Eqs[0]=ic[0]+…
?孤立项
ic[0]
不在上述方程式中。(同样地,对于
模型中的其他方程
)@WarrenWeckesser,“Eqs[0]=ic[0]+…”这个术语是因为我是个白痴,不能从我以前使用的不同方案中翻译我的代码。谢谢你找到那个!当我使用odeint时,问题是变量x1、x2等取负值:()。我以为dopri5适用于僵硬的系统,所以这是我的错误,但在这种情况下,dopri5似乎给出了更准确的结果。我的一位前助教建议我的方程非常有用,所以我正在尝试找到最好的方法来正确地整合它们。你应该用
dopri5
得到一个好的解决方案,但是它可能比一个僵硬的解算器做更多的工作(因此需要更长的时间)。您也可以尝试
'vode'
,它确实接受并实际使用
方法='bdf'
。有关更多选项,请参阅。
Eqs[0] = ic[0]+(ic[0]*(1-ic[0]*ic[0]-ic[1]*ic[1]-ic[2]*ic[2]-ic[3]*ic[3])-c21*((ic[1]*ic[1])*ic[0])+e31*((ic[2]*ic[2])*ic[0])+e41*((ic[3]*ic[3])*ic[0]))+sigma1*ic[0]*np.random.normal(0,1)