如何在Scipy的solve_ivp中自定义Runge-Kutta每步h后的操作?
在Scipy solve_ivp的步长节点执行自定义操作的实现方法
核心思路
solve_ivp返回的t数组就是求解器自动选择的步长节点(即你提到的[0. 0.11487653 1.26364188 3. ])。如果需要求解过程中实时执行自定义操作,可以利用求解器的events事件机制触发回调;如果仅需求解完成后处理,直接遍历t数组即可。
实时触发的实现示例
下面是用事件函数配合回调,在每个步长节点(除初始点)实时打印hello world的代码:
import numpy as np from scipy.integrate import solve_ivp # 定义指数衰减微分方程 def exponential_decay(t, y): return -0.5 * y # 标记步长是否完成 step_finished = False # 定义事件函数:触发条件为到达非初始步长节点 def step_event(t, y): global step_finished if t == 0: return 1 # 初始点不触发 step_finished = True return 0 # 返回0触发事件 # 配置事件:触发后不终止求解 step_event.terminal = False step_event.direction = 0 # 自定义操作:打印指定内容 def custom_action(t): print(f"hello world at t = {t:.6f}") # 事件回调函数:触发时执行自定义操作 def event_callback(t, y): global step_finished if step_finished: custom_action(t) step_finished = False # 调用solve_ivp求解 sol = solve_ivp( exponential_decay, [0, 3], [1.0], method='DOP853', events=step_event, callback=event_callback ) # 输出求解器的步长节点 print("求解器实际步长节点:", sol.t)
求解后批量处理的示例
如果不需要实时操作,求解完成后直接遍历步长节点即可:
# 跳过初始点0,遍历其余节点执行操作 for t in sol.t[1:]: print(f"hello world at t = {t:.6f}")
关键说明
- 事件函数的作用是让求解器在每个步长结束时触发回调,
terminal=False确保求解过程不会中断。 sol.t存储了求解器自动选择的所有步长节点,完全匹配你需要执行操作的目标节点。
内容的提问来源于stack exchange,提问作者eyesight-2020
相关产品推荐
相关产品推荐

