用“跳跃”系数求解 ODE

计算科学 matlab Python 一体化
2021-12-21 01:14:16

我正在数值求解以下形式的线性耦合 ODE

y(t)=M^(t)y(t)=[0A(t)B(t)0]y(t),
我遇到的困难是A(t)B(t)不要长时间改变并突然迅速改变。这是我正在处理的一个例子的情节:

元素的情节......它是“跳跃的”

蓝线在左轴,橙线在右轴。我在 python 中使用 scipy 的 Runge-Kutta 45 实现来解决 ODE 并有一个数组A(t)B(t)在我开始之前(即它不是一个函数,而是从任意采样数据派生的)。

只要我施加足够小的max_step参数来捕捉快速变化,我就可以获得准确的解决方案,但这需要很长时间,而且我处于对性能敏感的应用程序中。例如,我需要对这个函数进行大约 100k 的函数评估才能获得良好的收敛性(1E-4 精度)。当然,求解器在系数不变的区域浪费了大量时间/函数调用。我手头也有系数数组,并且在某种意义上已经知道问题点在哪里,并且应该能够事先告诉求解器它们。

我的问题是:如何有效地求解具有脉冲系数的 ODE? 或者,有没有比使用 RK45 更好的方法来解决采样数据的 ODE? 我只是对系数进行插值并将其像连续函数一样传递给求解器,但我不确定其他人会推荐什么。

编辑:另一个想法,有没有办法以正交方式解决这个ODE,就像解决方案一样y(x)=f(x)y(x)只是ef(x)dx? 即使通过对角化我也看不到简单的方法M因为它取决于t,但谁知道呢?实际上,该等式是否适用于带有矩阵求幂的矩阵?事情没有那么简单,不是吗?

2个回答

我会推荐 3 件事来追求:

  1. 使用 ode15s(一个刚性求解器)。这将允许在跳跃附近获得更好的分辨率

  2. 重新调整问题。您的系数非常大,如果它们发生了几个数量级的变化,这可能会导致您的求解器出现过度的调节问题,因此重新缩放然后在 ode 求解后撤消缩放可能是最好的

  3. 如果您在跳转时仍然遇到严重错误,请尝试在 ode15s 选项中指定事件。您可以在系数跳跃时指定事件,这将迫使求解器在这些点附近以高精度求解以解决不连续性。

您在这里处理的现象称为“僵硬系统”。在这里查看完整的解释:http ://www.scholarpedia.org/article/Stiff_systems

Matlab 的 ode45 是一个非刚性求解器,因此不适合您的问题。您应该尝试使用一种刚性求解器。Matlab 有 4 个刚性求解器,但 Scipy 的 solve_ivp 等其他工具也具有非刚性求解器:https ://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.solve_ivp.html

Julia 也有解决棘手问题的方法,有关更多详细信息,请参阅 Chris Rackauckas 对上述问题的评论,因为他是该主题的专家。