我需要一个高效的Python ODE求解器来解决类似于Matlab的ode15s的僵化问题。
摘要: -我已经将方程函数的ODE系统从Matlab转换为Python。 -我已经在Matlab中解决了该系统。 -在Python中,我可以使用SciPy vode集成器解决系统。 -SciPy解算器比Matlab ODE解算器花费的时间长约16倍,因为在相同的持续时间内,它需要花费约162x的步数。
如何通过减少所需的步骤数来提高求解器的速度?
我有一个包含23个变量的方程组dY / dt。
我的Matlab ODE解算器实现是:
const
当我运行上面的代码时,它需要约0.5秒,并以507个步骤完成。
我将duration = [0 .5]
options = odeset('MaxStep',1e-3,'InitialStep',2e-5);
[t,Yc] = ode15s(@funct, duration, Y, options);
转换为Python,并使用具有相同设置的SciPy vode集成器:
funct
此实现大约需要82秒和81,222个步骤-对于我需要运行的仿真类型来说,这太长了。
我发现了一条recommends calculating the Jacobian to decrease the number of steps made by the solver的帖子。
因为我无法直接计算雅可比行列式,所以我使用以下方法对它进行数值估算:
solver = ode(funct)
solver.set_integrator('vode', method='bdf', max_step=1e-3, first_step=2e-5)
solver.set_initial_value(Y0, t0)
while solver.successful() and solver.t < t1:
solver.integrate(t1, step=True)
csv_writer.writerow([solver.t, solver.y])
我知道上面的实现有点笨拙,但是我只想减少步骤数。
我将此雅可比行列式传递给积分器:
def jacobian(time, Y):
dY_dt = funct(time, Y)
Y_step = Y + Y * .001
n=len(Y)
jac=np.zeros((n, n))
for column in range(n): #through columns
Y_step_current = np.copy(Y)
Y_step_current[column] = Y_step[column]
dY_dY = funct(time, Y_step_current)
if (Y_step[column] - Y[column]) != 0:
jac[column, :] = (dY_dY - dY_dt) / (Y_step[column] - Y[column])
return jac
此实现比第一个实现还要慢,并且要求我将最小步长减小到1e-8。
简而言之,如何实现与Matlab的ode15相同的可变步长Python集成器?