指定时间评估是否会通过 RK45 方法覆盖时间步长 select? (scipy.integrate.solve_ivp)
will specifying time evaluate will override timestep select by RK45 method? (scipy.integrate.solve_ivp)
来自
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
覆盖时间步长 select 吗?
它不会覆盖时间步长。验证这一点的一种方法是使用 dense_output=True
,它在每个时间步保存数据以供稍后插值。
sol
属性包含有关 ts
属性中时间步长的附加信息。在这里,您可以看到使用 t_eval
会更改 sol3.t
的 return 但不会影响时间步长。
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. ]
我温和地建议您不要使用 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)
简答
,不!它不会覆盖 RK45 的时间步长,因为函数 scipy.integrate.solve_ivp
将为 t_eval
中的每个 t
使用内插值。而RK45依旧使用自己的时间步
长答案。
经过一番调查,我发现了这一点。
根据 source code!
在函数 solve_ivp
的第 156 行。在第 477 行。
solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
求解器不将t_eval
作为参数。
在第 511 行。
t = solver.t
求解器 return 它拥有 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_new
是 t_eval
的新索引,在使用 np.searchsorted
和 t_eval_step
之间有 t
是 t_eval
的时间步长在 ode 求解器步骤之间。
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 输出 .
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)
来自
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
覆盖时间步长 select 吗?
它不会覆盖时间步长。验证这一点的一种方法是使用 dense_output=True
,它在每个时间步保存数据以供稍后插值。
sol
属性包含有关 ts
属性中时间步长的附加信息。在这里,您可以看到使用 t_eval
会更改 sol3.t
的 return 但不会影响时间步长。
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. ]
我温和地建议您不要使用 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)
简答
,不!它不会覆盖 RK45 的时间步长,因为函数 scipy.integrate.solve_ivp
将为 t_eval
中的每个 t
使用内插值。而RK45依旧使用自己的时间步
长答案。
经过一番调查,我发现了这一点。 根据 source code!
在函数 solve_ivp
的第 156 行。在第 477 行。
solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
求解器不将t_eval
作为参数。
在第 511 行。
t = solver.t
求解器 return 它拥有 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_new
是 t_eval
的新索引,在使用 np.searchsorted
和 t_eval_step
之间有 t
是 t_eval
的时间步长在 ode 求解器步骤之间。
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 输出 .
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)