2

from

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

with

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

t_eval is optional for store solution in specify time. Will this override timestep select by RK45?

Aksen P
  • 4,564
  • 3
  • 14
  • 27
M lab
  • 224
  • 1
  • 10

2 Answers2

1

It does not override the timestep. One way to verify this is to use dense_output=True, which saves data at each timestep for interpolating later.

The sol attribute contains additional information about the timesteps in the ts attribute. Here, you can see that using t_eval changes the return of sol3.t but does not affect the timesteps.

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}")

returns

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.  ]

I mildly suggest that instead of using t_eval, you should only use dense_output=True and then construct y_eval after the fact. This is a much more flexible and transparent usage.

sol = solve_ivp(dy, (0, 10), [1], method=method, dense_output=True)
y_eval = sol.sol(t_eval)
Matthew Flamm
  • 448
  • 3
  • 13
0

For short answer

, No! it not override RK45's time step besause the function scipy.integrate.solve_ivp will use interpulated value for each t in t_eval. And RK45 still use its own time step.


For long answer.

After doing some investigate, I found that. According to source code!

At line 156 in function solve_ivp. At line 477.

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

The solver doesn't take t_eval as parameter. At line 511.

t = solver.t

Solver return it own t.

At line 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]

Which t_eval_i_new is new index of t_eval that have t in between using np.searchsorted and t_eval_step is time steps of t_eval between ode solver step.

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

Which means we append t_eval_step to ts and use solver.dense_output() to interpolant over step and give approximate value for each specific time in t_eval_step At line 585 after finish integration then program return output .

 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)
M lab
  • 224
  • 1
  • 10