【发布时间】:2017-08-04 16:17:20
【问题描述】:
我需要一个 ODE 求解器来解决类似于 MATLAB ode15s 的棘手问题。
对于我的问题,我需要检查不同初始值需要多少步(计算),并将其与我自己的 ODE 求解器进行比较。
我尝试过使用
solver = scipy.integrate.ode(f)
solver.set_integrator('vode', method='bdf', order=15, nsteps=3000)
solver.set_initial_value(u0, t0)
然后与:
i = 0
while solver.successful() and solver.t<tf:
solver.integrate(tf, step=True)
i += 1
print(i)
tf 是我的时间间隔的结束。
使用的函数定义为:
def func(self, t, u):
u1 = u[1]
u2 = mu * (1-numpy.dot(u[0], u[0]))*u[1] - u[0]
return numpy.array([u1, u2])
初始值u0 = [ 2, 0] 是一个棘手的问题。
这意味着步数不应该取决于我的常量mu。
但确实如此。
我认为odeint-方法可以解决这个棘手的问题-但是我必须发送整个t-vector,因此需要设置已完成的步数,这会破坏重点我的任务。
是否可以在两个t0 和tf 之间使用具有自适应步长的odeint?
或者你能看到我在使用vode-integrator 时遗漏了什么吗?
【问题讨论】:
-
我不明白你为什么说步数不应该取决于常量
mu。vode是一个自适应求解器。任何改变方程组的东西都可能改变所需的步数。 -
对于僵硬问题,步数可以少得多,因为可以采取更长的步数。说它不依赖可能有点苛刻。我可以在 MATLAB 中使用
ode15s进行相同的计算,mu > 10000 需要 40-100 步。而在我的 python 示例中计算 mu = 1000 需要 120 万步。 -
我看到了类似的东西;在 'adams' 和 'bdf' 之间改变方法并不会改变步数。 (顺便说一句,使用
order=15没有意义;'vode'求解器的'bdf'方法的最大阶数是5(而'adams'求解器的最大阶数是12)。如果你离开参数,默认情况下应该使用最大值。) -
odeint是 LSODA 的封装。ode还提供了 LSODA 的包装:将'vode'更改为'lsoda'。不幸的是,'lsoda'求解器忽略了integrate方法的step=True参数。 -
'lsoda'求解器做得好多。您可以通过初始化tvals = []和在func中执行tvals.append(t)来获得所使用步数的上限。最后,设置tvals = np.unique(tvals)。tvals的长度告诉您评估函数的时间值的数量。这并不完全是您想要的,但它确实显示了使用'lsoda'求解器和使用'bdf'方法的'vode'求解器之间的巨大 差异。'lsoda'求解器使用的步数与您为 matlab 引用的顺序相同。 (我用过mu=10000,tf = 10。)