如何在Python SciPy的solve_ivp ODE求解器中获取/记录步长?
追踪scipy.integrate.solve_ivp的动态步长
要获取solve_ivp使用的自适应步长,最高效且几乎不增加积分时间的方法是利用回调函数(callback)——它会在每一步成功积分后触发,我们可以在回调中记录时间点并计算步长。
方法1:使用闭包追踪步长(推荐,无全局变量)
通过闭包封装步长列表和上一次时间点,避免全局变量污染:
import numpy as np from scipy.integrate import solve_ivp def create_step_tracker(): step_sizes = [] last_t = None def tracker(t, y): nonlocal last_t if last_t is not None: # 计算当前步长并存储 step_sizes.append(t - last_t) last_t = t # 返回False表示不终止积分 return False # 返回追踪函数和步长列表 return tracker, step_sizes # 定义你的微分方程 def ode(t, y): return -y # 示例:一阶线性ODE # 创建追踪器 tracker, step_sizes = create_step_tracker() # 调用solve_ivp并传入回调 sol = solve_ivp(ode, t_span=[0, 10], y0=[1.0], callback=tracker) # 查看结果 print("积分使用的步长:") print(np.round(step_sizes, 6))
方法2:使用全局变量(简单直接)
如果不需要考虑代码封装,全局变量的方式更简洁:
import numpy as np from scipy.integrate import solve_ivp step_sizes = [] last_t = None def track_step(t, y): global last_t if last_t is not None: step_sizes.append(t - last_t) last_t = t return False def ode(t, y): return -y sol = solve_ivp(ode, [0, 10], [1.0], callback=track_step) print("步长列表:", step_sizes)
原理说明
solve_ivp的callback参数接受一个函数,该函数会在每一步成功完成积分后被调用,传入当前的时间t和状态y。- 我们通过记录相邻两次回调的时间差,直接得到积分器实际使用的步长——这完全是积分过程的副产品,几乎不会增加额外计算量,不会显著影响积分速度。
- 此方法适用于所有
solve_ivp支持的自适应步长算法(如RK45、RK23、Radau等),也兼容固定步长方法。
内容的提问来源于stack exchange,提问作者valade aurélien
相关产品推荐
相关产品推荐

