将刚性 ODE 与 Python 集成

发布于 2024-08-18 03:11:56 字数 436 浏览 3 评论 0原文

我正在寻找一个能够在 Python 中集成严格 ODE 的优秀库。问题是,scipy 的 odeint 有时会给我很好的解决方案,但是初始条件的最轻微的变化都会导致它崩溃并放弃。 MATLAB 的刚性求解器(ode15s 和 ode23s)很好地解决了同样的问题,但我无法使用它(即使是在 Python 中,因为 MATLAB C API 的 Python 绑定都没有实现回调,并且我需要传递一个函数到 ODE 求解器)。我正在尝试 PyGSL,但它非常复杂。任何建议将不胜感激。

编辑:我在使用 PyGSL 时遇到的具体问题是选择正确的阶跃函数。其中有几个,但没有与 ode15s 或 ode23s 直接类似的东西(bdf 公式和修改后的 Rosenbrock,如果有意义的话)。那么对于刚性系统来说,选择什么好的阶跃函数呢?我必须对这个系统求解很长时间才能确保它达到稳态,而 GSL 求解器要么选择很小的时间步长,要么选择太大的时间步长。

I'm looking for a good library that will integrate stiff ODEs in Python. The issue is, scipy's odeint gives me good solutions sometimes, but the slightest change in the initial conditions causes it to fall down and give up. The same problem is solved quite happily by MATLAB's stiff solvers (ode15s and ode23s), but I can't use it (even from Python, because none of the Python bindings for the MATLAB C API implement callbacks, and I need to pass a function to the ODE solver). I'm trying PyGSL, but it's horrendously complex. Any suggestions would be greatly appreciated.

EDIT: The specific problem I'm having with PyGSL is choosing the right step function. There are several of them, but no direct analogues to ode15s or ode23s (bdf formula and modified Rosenbrock if that makes sense). So what is a good step function to choose for a stiff system? I have to solve this system for a really long time to ensure that it reaches steady-state, and the GSL solvers either choose a miniscule time-step or one that's too large.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风和你 2024-08-25 03:11:56

如果您可以使用Matlab的ode15s解决您的问题,那么您应该也可以使用scipy的vode求解器解决它。为了模拟 ode15s,我使用了以下设置:

ode15s = scipy.integrate.ode(f)
ode15s.set_integrator('vode', method='bdf', order=15, nsteps=3000)
ode15s.set_initial_value(u0, t0)

然后您就可以愉快地使用 ode15s.integrate(t_final) 解决您的问题。它应该可以很好地解决棘手的问题。

(另请参阅链接

If you can solve your problem with Matlab's ode15s, you should be able to solve it with the vode solver of scipy. To simulate ode15s, I use the following settings:

ode15s = scipy.integrate.ode(f)
ode15s.set_integrator('vode', method='bdf', order=15, nsteps=3000)
ode15s.set_initial_value(u0, t0)

and then you can happily solve your problem with ode15s.integrate(t_final). It should work pretty well on a stiff problem.

(See also Link)

夜深人未静 2024-08-25 03:11:56

Python可以调用C。行业标准是ODEPACK中的LSODE。它是公共领域的。您可以下载C 版本。这些求解器非常棘手,因此最好使用一些经过良好测试的代码。

补充:确保您确实拥有一个刚性系统,即速率(特征值)是否相差超过 2 或 3 个数量级。此外,如果系统是刚性的,但您只想寻找稳态解,这些求解器可以让您选择以代数方式求解某些方程。否则,像 DVERK 这样的优秀 Runge-Kutta 求解器将是一个很好且更简单的解决方案。

添加到此处是因为它不适合注释:这是来自 DLSODE 标题文档:

C     T     :INOUT  Value of the independent variable.  On return it
C                   will be the current value of t (normally TOUT).
C
C     TOUT  :IN     Next point where output is desired (.NE. T).

此外,是的 Michaelis-Menten 动力学是非线性的。不过,艾特肯加速可以与之配合。 (如果您想要简短的解释,请首先考虑 Y 为标量的简单情况。运行系统以获取 3 个 Y(T) 点。通过它们拟合指数曲线(简单代数)。然后将 Y 设置为渐近线并重复。现在假设 3 个点在一个平面上,也没关系。)此外,除非有强制函数(如恒定的 IV 滴注),否则 MM 消除将会衰减。远离,系统将接近线性。希望有帮助。

Python can call C. The industry standard is LSODE in ODEPACK. It is public-domain. You can download the C version. These solvers are extremely tricky, so it's best to use some well-tested code.

Added: Be sure you really have a stiff system, i.e. if the rates (eigenvalues) differ by more than 2 or 3 orders of magnitude. Also, if the system is stiff, but you are only looking for a steady-state solution, these solvers give you the option of solving some of the equations algebraically. Otherwise, a good Runge-Kutta solver like DVERK will be a good, and much simpler, solution.

Added here because it would not fit in a comment: This is from the DLSODE header doc:

C     T     :INOUT  Value of the independent variable.  On return it
C                   will be the current value of t (normally TOUT).
C
C     TOUT  :IN     Next point where output is desired (.NE. T).

Also, yes Michaelis-Menten kinetics is nonlinear. The Aitken acceleration works with it, though. (If you want a short explanation, first consider the simple case of Y being a scalar. You run the system to get 3 Y(T) points. Fit an exponential curve through them (simple algebra). Then set Y to the asymptote and repeat. Now just generalize to Y being a vector. Assume the 3 points are in a plane - it's OK if they're not.) Besides, unless you have a forcing function (like a constant IV drip), the MM elimination will decay away and the system will approach linearity. Hope that helps.

余厌 2024-08-25 03:11:56

PyDSTool 封装了 Radau 求解器,它是一个优秀的隐式刚性积分器。它比 odeint 有更多的设置,但比 PyGSL 少很多。最大的好处是,您的 RHS 函数被指定为字符串(通常,尽管您可以使用符号操作构建系统)并转换为 C,因此没有缓慢的 python 回调,整个过程将非常快。

PyDSTool wraps the Radau solver, which is an excellent implicit stiff integrator. This has more setup than odeint, but a lot less than PyGSL. The greatest benefit is that your RHS function is specified as a string (typically, although you can build a system using symbolic manipulations) and is converted into C, so there are no slow python callbacks and the whole thing will be very fast.

执笏见 2024-08-25 03:11:56

我目前正在研究一些 ODE 及其求解器,所以你的问题对我来说非常有趣......

根据我所听到和读到的,对于刚性问题,正确的方法是选择隐式方法作为阶跃函数(如果我错了请纠正我,我仍在学习 ODE 求解器的奥秘)。我无法引用您在哪里读到此内容,因为我不记得了,但这里有一个 线程 提出了类似的问题。

因此,简而言之,bsimp 方法似乎值得一试,尽管它需要雅可比函数。如果您无法计算雅可比行列式,我将尝试使用 rk2imprk4imp 或任何 gear 方法。

I am currently studying a bit of ODE and its solvers, so your question is very interesting to me...

From what I have heard and read, for stiff problems the right way to go is to choose an implicit method as a step function (correct me if I am wrong, I am still learning the misteries of ODE solvers). I cannot cite you where I read this, because I don't remember, but here is a thread from gsl-help where a similar question was asked.

So, in short, seems like the bsimp method is worth taking a shot, although it requires a jacobian function. If you cannot calculate the Jacobian, I will try with rk2imp, rk4imp, or any of the gear methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文