【问题标题】:Scipy: Two ways of implementing a differential equation: two different solutions: answeredScipy:实现微分方程的两种方法:两种不同的解决方案:已回答
【发布时间】:2017-09-07 04:34:54
【问题描述】:

我试图为我的化学论文求解一个微分方程,在那里我偶然发现了一个关于 scipy 的微分方程求解器“odeint”的问题。

首先我根据 scipy 网站上的示例通过函数 CIDNP_1 实现了微分(CIDNP 是一种化学现象,它解释了不寻常的变量)。但即使是正确的方向,解决方案也很遥远。

import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate

R0 = 5e+5
kt = 5e5/R0
beta = 3/R0

def CIDNP_1(y, t):
    dP_dt, dQ_dt = y

    def R(t):
        return R0/(1 + kt*R0*t)

    dP_dt = -kt*dP_dt*R(t) - kt*beta*(R(t))**2
    dQ_dt = +kt*dP_dt*R(t) + kt*beta*(R(t))**2
    return [dP_dt, dQ_dt]


def CIDNP_2(y, t):    
    dP_dt, dQ_dt = y

    def R(t):
        return R0/(1 + kt*R0*t)

    return [-kt*dP_dt*R(t) - kt*beta*(R(t))**2, \
            +kt*dP_dt*R(t) + kt*beta*(R(t))**2]

y0 = [-1, +1]
t = np.linspace(1e-9, 100e-6, 1e3)
sol_1 = scipy.integrate.odeint(CIDNP_1, y0, t)
sol_2 = scipy.integrate.odeint(CIDNP_2, y0, t)

然后我更改了对 CIDNP_2 的解决方案,给出了正确的结果,但在我看来,实现没有区别,因为变量 dP_dt 和 dQ_dt 在实现 CIDNP_1 中没有改变。

所以任何人都可以给我一个提示,为什么 CIDNP_1 的实现会给出错误的结果,我会很幸运,因为至少最后两个小时并没有完全丢失。

问候,

雅各布

【问题讨论】:

  • 您确定输入y 在语义上是时间导数,而不仅仅是状态y=[P,Q]resp。 P,Q = y?这种重新标记也将避免发生混淆。
  • 在语义上你是对的。微分方程描述了系统的状态和无导数。但由于我最初只是想在五分钟内编写代码,所以我并没有考虑太多。在下一个版本中,我将对其进行更改。

标签: python numpy scipy differential-equations


【解决方案1】:

在您的第一个版本中,您执行更新时不会同时执行 to 行

dP_dt = -kt*dP_dt*R(t) - kt*beta*(R(t))**2
dQ_dt = +kt*dP_dt*R(t) + kt*beta*(R(t))**2

不是同时的;因此,您使用已经更新的dP_dt 来更新dQ_dt。这是ODE 系统的错误实现。您的第二种方法更好,因为它没有这种错误。您要么必须直接返回更新后的值,要么必须将新计算的 dP_dt 值保存在另一个变量中,然后再计算新的 dQ_dt

new_dP_dt = -kt*dP_dt*R(t) - kt*beta*(R(t))**2
new_dQ_dt = +kt*dP_dt*R(t) + kt*beta*(R(t))**2

return [new_dP_dt, new_dQ_dt]

这会解决你的问题。

【讨论】:

  • 非常感谢。下次我会尽量不在同一行中覆盖我的变量。问候
【解决方案2】:

CIDNP_1 中,在使用新值计算dQ_dt 之前更改dP_dt 的值:

dP_dt = -kt*dP_dt*R(t) - kt*beta*(R(t))**2   # changed dP_dt!
dQ_dt = +kt*dP_dt*R(t) + kt*beta*(R(t))**2   # use the changed value!

CIDNP_2 中,您同时计算它们,即dQ_dt 是用dP_dt 的原始值计算的,而不是更改后的值。你可以这样想

a = -kt*dP_dt*R(t) - kt*beta*(R(t))**2       # no overwriting -
b = +kt*dP_dt*R(t) + kt*beta*(R(t))**2       # uses original value of dP_dt
return [a, b]

你也可以加快速度

def CIDNP_3(y, t):
    dP_dt, dQ_dt = y
    R_t = R0 / (1 + kt * R0 * t)
    res = kt * R_t * (dP_dt + beta * R_t)
    return [-res, res]

【讨论】:

  • 非常感谢。下次我会尽量不在同一行中覆盖我的变量。问候
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 2015-05-11
  • 1970-01-01
  • 2021-06-05
  • 2022-08-18
  • 1970-01-01
  • 2012-02-15
相关资源
最近更新 更多