是的,你可以这样做,但不能直接在odeint 中,因为它没有事件机制,而你提出的需要一个事件-动作机制。
但是您可以将问题分成多个步骤,在每个步骤中使用odeint 和现在的常量A 参数,然后最后加入这些步骤。
T = [[0]]
N = [[n0]]
for k in range(len(A)):
t = np.linspan(k,k+1,11);
n = odeint(lambda u,t: A[k]*u, [n0],t)
n0 = n[-1]
T.append(t[1:])
N.append(n[1:])
T = np.concatenate(T)
N = np.concatenate(N)
如果您对低效率感到满意,无论是在 ODE 的评估上还是在内部步数上,您也可以将参数实现为分段常数函数。
tA = np.arange(len(A));
A_func = interp1d(tA, A, kind="zero", fill_value="extrapolate")
T = np.linspace(0,len(A)+1, 10*len(A)+11);
N = odeint(lambda u,t: A_func(t)*u, [n0], T)
内部步长控制器的工作假设 ODE 函数可以很好地微分到 5 阶或更高阶。然后通过步进误差计算中固有的隐式数值微分将跳跃视为高度振荡的事件,需要非常小的步长。代码内部有一些缓解措施,通常允许求解器最终跨过这种跳转,但与上面的第一个变体相比,它需要更多的内部步骤,因此需要更多的函数评估。