Python SciPy ODE 求解器不收敛
Python SciPy ODE solver not converging
我正在尝试使用 scipy 的 ode 求解器绘制二维方程组之间的相互作用。我试图通过以下代码块更改传递给求解器的参数:
# define maximum number of iteration steps for ode solver iteration
m = 1 #power of iteration
N = 2**m #number of steps
# setup a try-catch formulation to increase the number of steps as needed for solution to converge
while True:
try:
z = ode(stateEq).set_integrator("vode",nsteps=N,method='bdf',max_step=5e5)
z.set_initial_value(x0, t0)
for i in range(1, t.size):
if i%1e3 == 0:
print 'still integrating...'
x[i, :] = z.integrate(t[i]) # get one more value, add it to the array
if not z.successful():
raise RuntimeError("Could not integrate")
break
except:
m += 1
N = 2**m
if m%2 == 0:
print 'increasing nsteps...'
print 'nsteps = ', N
运行 这永远不会中断 while 循环。它不断地增加 nsteps 并且系统永远不会得到解决。如果我不把它放在 while 循环中,系统就会解决,我想,因为解决方案被绘制出来了。 while循环是必要的吗?我是否错误地制定了求解器?
参数 nsteps
规定了在一个采样步骤中最多可以执行多少个积分步骤(即调用 z.integrate
)。如果您的采样步长足够小以捕获动态,则它的默认值是可以的。如果你想在一个大的采样步骤中整合一个很大的时间跨度(例如,为了摆脱瞬态动力学),这个值很容易太小。
此参数的作用是避免由于意外的超长集成而引起的问题。例如,如果您想在一个循环中对一个控制参数的 100 个值执行一个给定的积分过夜,您不希望在第二天早上看到第 14 号是病态的并且仍然是 运行。
如果这与您无关,只需将 nsteps
设置为非常高的值即可,无需担心。相继增加nsteps
当然没有意义,你只是在重复相同的计算。
Running this never breaks the while loop. It keeps increasing the nsteps forever and the system never gets solved.
这表明您遇到的问题与超出 nsteps
不同,很可能是问题没有很好地解决。仔细阅读集成商生成的错误消息。我还建议您检查微分方程。查看解决方案可能会有所帮助,直到集成无法看到出了什么问题,即在 运行 之后绘制 x
this:
z = ode(stateEq)
z.set_integrator("vode",nsteps=1e10,method='bdf',max_step=5e5)
z.set_initial_value(x0, t0)
for i,time in enumerate(t):
x[i,:] = z.integrate(time)
if not z.successful():
break
你对max_step
的评价很高(这应该不会高于你动态的时间尺度)。根据您的应用程序,这可能非常合理,但它表明您正在处理大量数据。这反过来可能意味着参数 atol
和 first_step
的默认值不适合您的情况,您需要调整它们。
我正在尝试使用 scipy 的 ode 求解器绘制二维方程组之间的相互作用。我试图通过以下代码块更改传递给求解器的参数:
# define maximum number of iteration steps for ode solver iteration
m = 1 #power of iteration
N = 2**m #number of steps
# setup a try-catch formulation to increase the number of steps as needed for solution to converge
while True:
try:
z = ode(stateEq).set_integrator("vode",nsteps=N,method='bdf',max_step=5e5)
z.set_initial_value(x0, t0)
for i in range(1, t.size):
if i%1e3 == 0:
print 'still integrating...'
x[i, :] = z.integrate(t[i]) # get one more value, add it to the array
if not z.successful():
raise RuntimeError("Could not integrate")
break
except:
m += 1
N = 2**m
if m%2 == 0:
print 'increasing nsteps...'
print 'nsteps = ', N
运行 这永远不会中断 while 循环。它不断地增加 nsteps 并且系统永远不会得到解决。如果我不把它放在 while 循环中,系统就会解决,我想,因为解决方案被绘制出来了。 while循环是必要的吗?我是否错误地制定了求解器?
参数 nsteps
规定了在一个采样步骤中最多可以执行多少个积分步骤(即调用 z.integrate
)。如果您的采样步长足够小以捕获动态,则它的默认值是可以的。如果你想在一个大的采样步骤中整合一个很大的时间跨度(例如,为了摆脱瞬态动力学),这个值很容易太小。
此参数的作用是避免由于意外的超长集成而引起的问题。例如,如果您想在一个循环中对一个控制参数的 100 个值执行一个给定的积分过夜,您不希望在第二天早上看到第 14 号是病态的并且仍然是 运行。
如果这与您无关,只需将 nsteps
设置为非常高的值即可,无需担心。相继增加nsteps
当然没有意义,你只是在重复相同的计算。
Running this never breaks the while loop. It keeps increasing the nsteps forever and the system never gets solved.
这表明您遇到的问题与超出 nsteps
不同,很可能是问题没有很好地解决。仔细阅读集成商生成的错误消息。我还建议您检查微分方程。查看解决方案可能会有所帮助,直到集成无法看到出了什么问题,即在 运行 之后绘制 x
this:
z = ode(stateEq)
z.set_integrator("vode",nsteps=1e10,method='bdf',max_step=5e5)
z.set_initial_value(x0, t0)
for i,time in enumerate(t):
x[i,:] = z.integrate(time)
if not z.successful():
break
你对max_step
的评价很高(这应该不会高于你动态的时间尺度)。根据您的应用程序,这可能非常合理,但它表明您正在处理大量数据。这反过来可能意味着参数 atol
和 first_step
的默认值不适合您的情况,您需要调整它们。