Я не уверен, что обработка событий в 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)
[ОБНОВЛЕНИЕ]: если я использую необязательный аргумент max_step для solve_ivp и сделаю его достаточно маленьким, тогда я вижу все три корня. Кажется, что функции событий вызываются не на шагах t_eval, а скорее только на внутренних шагах решателя, которые намного меньше шагов t_eval и которые в конечном итоге пропускают некоторые корни. Это не кажется очень полезным, так как вы должны знать, как установить max_steps, чтобы избежать пропущенных корней.