将指定时间评估会覆盖通过RK45方法选择的时间步长吗? (scipy.integrate.solve_ivp)

时间:2019-07-15 08:44:53

标签: python scipy runge-kutta

来自

https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.solve_ivp.html

使用

sol = scipy.integrate.solve_ivp(fun, t_span, y0, method='RK45', t_eval=None, dense_output=False, events=None, vectorized=False, **options)

t_eval对于指定时间的商店解决方案是可选的。 覆盖时间步长会由RK45选择吗?

2 个答案:

答案 0 :(得分:1)

它不会覆盖时间步。验证这一点的一种方法是使用dense_output=True,它会保存每个时间步的数据以供以后插值。

sol属性在ts属性中包含有关时间步长的其他信息。在这里,您可以看到使用t_eval会更改sol3.t的返回值,但不会影响时间步长。

import numpy as np
from scipy.integrate import solve_ivp

# To make readable
np.set_printoptions(precision=2)

method = 'RK45'

def dy(t, y):
    return y

sol = solve_ivp(dy, (0, 10), [1], method=method)
print(f"No options    : {sol.t}")
sol2 = solve_ivp(dy, (0, 10), [1], method=method, dense_output=True)
print(f"Dense output  : {sol2.t}")
print(f"  Interpolants: {sol2.sol.ts}")
t_eval = [5]
sol3 = solve_ivp(dy, (0, 10), [1], method=method, t_eval=t_eval, dense_output=True)
print(f"t_eval return : {sol3.t}")
print(f"  Interpolants: {sol3.sol.ts}")

返回

No options    : [ 0.    0.1   1.07  2.3   3.65  5.03  6.43  7.83  9.24 10.  ]
Dense output  : [ 0.    0.1   1.07  2.3   3.65  5.03  6.43  7.83  9.24 10.  ]
  Interpolants: [ 0.    0.1   1.07  2.3   3.65  5.03  6.43  7.83  9.24 10.  ]
t_eval return : [5]
  Interpolants: [ 0.    0.1   1.07  2.3   3.65  5.03  6.43  7.83  9.24 10.  ]

我建议不要使用t_eval,而应该只使用dense_output=True,然后在事实之后构造y_eval。这是一种更加灵活和透明的用法。

sol = solve_ivp(dy, (0, 10), [1], method=method, dense_output=True)
y_eval = sol.sol(t_eval)

答案 1 :(得分:0)

简短回答

,不!它不会覆盖RK45的时间步长,因为函数scipy.integrate.solve_ivp将对t中的每个t_eval使用插值。 RK45仍然使用自己的时间步长。


较长的答案。

经过一些调查,我发现了。 根据{{​​3}}!

在函数solve_ivp中的第156行。在第477行。

solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)

求解器不使用t_eval作为参数。 在第511行。

t = solver.t

求解器返回自己的t

在第545行。

if solver.direction > 0:
            t_eval_i_new = np.searchsorted(t_eval, t, side='right')
            t_eval_step = t_eval[t_eval_i:t_eval_i_new]

t_eval_i_newt_eval的新索引,在使用t之间有np.searchsorted,而t_eval_step是ode之间t_eval的时间步长求解器步骤。

if t_eval_step.size > 0:
            if sol is None:
                sol = solver.dense_output()
            ts.append(t_eval_step)
            ys.append(sol(t_eval_step))
            t_eval_i = t_eval_i_new

这意味着我们将t_eval_step附加到ts上,并使用solver.dense_output()对步进行插值,并为t_eval_step中的每个特定时间提供近似值 完成集成后,在第585行,然后返回程序输出。

 return OdeResult(t=ts, y=ys, sol=sol, t_events=t_events, nfev=solver.nfev,
                 njev=solver.njev, nlu=solver.nlu, status=status,
                 message=message, success=status >= 0)