我在scipy中使用odeint来集成一个函数。该函数实际上是一个向量(它是来自 L_total函数的返回值)。我遇到的问题是,对于这个向量的一些条目,集成非常容易,这意味着它不需要很多内部子步骤,但是对于其他一些值,集成应该更加详细。我假设odeint采用一定数量的子步骤,这是应用于向量的每个条目的子步骤。如果这个假设是正确的,有没有办法根据函数向量中的条目以有效的方式在scipy中分配最大数量的内部子步骤?我知道通过使用IF语句,我可能能够改变允许的最大步数,但是我担心它会花费更多的计算时间,而这正是我的目标。我的代码如下所示:
def L_total(self, r, d, u):
tem = self.T(u)
condlist = [numpy.log10(tem) <= 2, numpy.log10(tem) >= 2]
choicelist = [self.L1(r, d, tem), self.L2(r, tem)]
return numpy.select(condlist, choicelist) #This is the returned value for the scipy integration, i.e. the vector I want to integrate
def integrate_function(self, i_0, time_final, r, d):
def f(i, t):
return - self.L_total(r, d, i)
time = numpy.linspace(0., time_final, 2)
result = odeint(f, i_0, time)
return result[-1]
最后一个函数运行正常,直到变量 tem 的值增加,然后我收到一条消息,说“在此调用中完成了超额工作”,建议是增加允许的时间步长:
lsoda-- at current t (=r1), mxstep (=i1) steps ^@^@
taken on this call before reaching tout ^@^@
in above message, i1 = 500
in above message, r1 = 0.3319309749049D+03
此次调用完成的工作量过多(可能是错误的Dfun类型)
增加参数的数量mxstep听起来像解决方案,除了只要log(tem)&lt; 2集成很容易,内部时间步长的数量可以很小,我不想浪费时间在这个简单的集成上,想法是只增加向量的某些值的mxstep值。一种方法是:
def integrate_function(self, i_0, time_final, r, d, tem):
def f(i, t):
return - self.L_total(r, d, i)
time = numpy.linspace(0., time_final, 2)
if numpy.log10(tem)<=2:
result = odeint(f, i_0, time, mxstep=10)
else:
result = odeint(f, i_0, time, mxstep=1000)
return result[-1]
然而,向量函数的长度非常大,因此我将耗费大量的计算时间,因为我必须在另一个循环内执行此循环。我需要的是效率,因为我的代码已经花了很多时间。
答案 0 :(得分:1)
odeint
自动选择的子时间步长对于系统中的所有方程都是相同的。这是因为通常,在求解ODE系统时,不能单独使用这些组件:所有这些组件必须在同一时间点知道,以便在那时找到导数。
对于非耦合系统,其中方程式彼此无关,上面对时间步长构成了可能不必要的约束。在这种情况下,在循环中求解单个方程实际上可能比使用它们作为系统更快。