如何在scipy.integrate.solve_ivp

时间:2018-09-04 23:53:40

标签: python scipy

我不确定scipy.integrate.solve_ivp中的事件处理是否正常工作。在下面的示例中,我对一个导数进行了积分,该导数将导致三次多项式具有x = -6,x = -2和x = 2的三个根。我设置了一个事件函数,该函数返回y,在这些x值处将为零。我希望在解决方案的t_events属性中看到三个条目,但是即使解决方案跨过x轴三遍,我也只能看到一个条目。

我在这里做错什么了吗?

再现代码示例:

def fprime(x, y):
    return 3 * x**2 + 12 * x - 4

def event(x, y):
    return y

import numpy as np
from scipy.integrate import solve_ivp
sol = solve_ivp(fprime, (-8, 4), np.array([-120]), t_eval=np.linspace(-8, 4, 10), events=[event])

上面的代码导致:

message: 'The solver successfully reached the interval end.'
      nfev: 26
      njev: 0
       nlu: 0
       sol: None
    status: 0
   success: True
         t: array([-8.        , -6.66666667, -5.33333333, -4.        , -2.66666667,
        -1.33333333,  0.        ,  1.33333333,  2.66666667,  4.        ])
  t_events: [array([-6.])]
         y: array([[-120.        ,  -26.96296296,   16.2962963 ,   24.        ,
           10.37037037,  -10.37037037,  -24.        ,  -16.2962963 ,
           26.96296296,  120.        ]])

```

问题是,您可以从sol.y数组中看到三个零(三个符号变化),但是只记录了一个事件。

Scipy / Numpy / Python版本信息:

1.0.0 1.13.3 sys.version_info(major=3, minor=6, micro=0, releaselevel='final', serial=0)

[更新]:如果我对resolve_ivp使用可选的max_step参数,并使其足够小,则可以看到所有三个根。似乎事件函数不是在t_eval步骤中调用的,而是仅在内部求解器步骤中调用的,内部求解器步骤比t_eval步骤少得多,并且最终会跳过一些根。这似乎不太有用,因为您必须知道如何设置max_steps以避免丢失根。

1 个答案:

答案 0 :(得分:2)

  

事件函数不是在t_eval步骤中调用,而是仅在内部求解器步骤中调用

这是正确的。在一对新的(t, y)is found之后,从事件and passedfind_active_events计算事件,这会将事件功能的符号与上一步进行比较。

t_eval完全不被事件计算使用,它由later处理。因此,事件看到的符号更改就是您在输出中看到的带有t_eval=None的符号更改,其中只有一个。

y: array([[-120.        , -110.49687882,  -35.93785936,   94.46893375,
     120.        ]]) 

似乎值得在SciPy追踪器上提出问题;有a few open issues regarding solve_ivp,仍然很新。