可以通过在小时间间隔内将一些系数/参数设为常数来减少解决非线性 ODE 所需的工作量吗?

计算科学 非线性方程 scipy
2021-12-25 00:45:00

到目前为止,我一直将scipy.integrate.odeint其用作我的“主力”ODE 求解器。我当前的问题需要我解决一个大型系统(最多约 5000 个)ODE。

odeint这是我注意到的程序的一般工作流程:

  1. 获取初始值和函数以计算t=t0
  2. 估计,使用标准数值求积方法(需要 1 次调用 Jacobian 函数)tn=tn1+δt
  3. 处“收敛”解决方案来解决非线性问题(可能需要多次调用,比如到 Jacobian 函数t1Nn

所以,要在每一步继续,我们至少需要雅可比调用。如果计算雅可比行列式需要一些努力,那么这在计算上可能会很昂贵。δtNn+1

上保持不变(几乎就像在一些小时间尺度上的“准平衡”假设?)这样,当 ODE 系统通过求解时,对 Jacobian 函数的重复调用不会那么昂贵,因为它不必计算某些东西,直到下一个时间步。δtδt

我对这种简化的幼稚实现使用了一种类似于此处描述的方法:scipy.integrate.odeint:odeint 如何访问独立于它发展的参数集?

基本上,为了在区间上求解 ODE 系统(例如),我会:[0,10]

  1. 首先考虑区间,并预先计算要用于此时间步的系数/参数[0,1]
  2. 将步骤 1. 中预先计算的值作为常量参数传递给 Jacobian 函数,用于在上求解 ODE 系统,[0,1]
  3. 上求解 ODE 系统获得的数据之外的所有结果[0,1]t=1
  4. 使用为获得的数据预先计算要在时间步t=1[1,2]
  5. 与步骤 2-3 类似,odeint再次调用
  6. 冲洗并重复

当我的主管发现我在做什么时,类似于我上面链接的问题的答案,他警告说这种实现可能既低效(因为我打破了 的内部流程odeint)又不准确(因为我有点人为地引入不连续性不断)。

如果可能的话,我怎样才能正确地实现“准平衡”简化?

1个回答

我建议您查看 Rosenbrock 或 Rosenbrock-W 方法。这些是多阶段(如 Runge-Kutta)方法,每一步仅计算一次雅可比行列式。这些方法比对角隐式 Runge-Kutta 方法具有更多的顺序条件(由于滞后和/或不精确的雅可比行列式),但在其他方面相似。在 Hairer 和 Wanner 的第二卷中有一章解释了订单条件并讨论了一些方法类。

您可以通过 petsc4py 访问PETSc 实现,它实现了许多 Rosenbrock 和 Rosenbrock-W 方法。有关用法,请参见Oregonator 示例