使用scipy.integrate.odeint解决一个颂歌系统(改变常数!)?

时间:2015-10-07 08:23:54

标签: python scipy ode

我目前有一个具有时间相关常数的颂歌系统。 E.g。

def fun(u, t, a, b, c):
    x = u[0]
    y = u[1]
    z = u[2]
    dx_dt = a * x + y * z
    dy_dt = b * (y-z)
    dz_dt = -x*y+c*y-z
    return [dx_dt, dy_dt, dz_dt]

常数是" a"," b"和" c"。我目前有一个" a" s用于每个时间步骤,我希望在每个时间步骤插入,当使用scipy ode求解器时...这可能吗?

谢谢!

2 个答案:

答案 0 :(得分:8)

是的,这是可能的。在a不变的情况下,我猜您调用scipy.integrate.odeint(fun, u0, t, args),其中fun定义为您的问题,u0 = [x0, y0, z0]是初始条件,t是要为ODE求解的一系列时间点,args = (a, b, c)是要传递给fun的额外参数。

如果a取决于时间,您只需重新考虑a作为函数,例如(给定常量a0):

def a(t):
    return a0 * t

然后你必须修改fun来计算每个时间步的衍生物,以考虑先前的变化:

def fun(u, t, a, b, c):
    x = u[0]
    y = u[1]
    z = u[2]
    dx_dt = a(t) * x + y * z # A change on this line: a -> a(t)
    dy_dt = b * (y - z)
    dz_dt = - x * y + c * y - z
    return [dx_dt, dy_dt, dz_dt]

最后,请注意u0targs保持不变,您可以再次致电scipy.integrate.odeint(fun, u0, t, args)

关于这种方法的正确性的一句话。数值积分近似的表现受到影响,我不知道如何(没有理论上的保证),但这是一个有效的简单例子:

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

tmax = 10.0

def a(t):
    if t < tmax / 2.0:
        return ((tmax / 2.0) - t) / (tmax / 2.0)
    else:
        return 1.0

def func(x, t, a):
    return - (x - a(t))

x0 = 0.8
t = np.linspace(0.0, tmax, 1000)
args = (a,)
y = sp.integrate.odeint(func, x0, t, args)

fig = plt.figure()
ax = fig.add_subplot(111)
h1, = ax.plot(t, y)
h2, = ax.plot(t, [a(s) for s in t])
ax.legend([h1, h2], ["y", "a"])
ax.set_xlabel("t")
ax.grid()
plt.show()

enter image description here

我希望这会对你有所帮助。

答案 1 :(得分:1)

不,这是不可能的,因为求解器将使用您无法控制的内部时间步长,并且每个时间步都使用该函数的多个评估。

如果参数是分段常数,那么您可以从跳转点到跳转点进行积分。

如果是分段线性,则可以使用插值函数。

对于其他任何事情,你必须实现自己的逻辑,从t时间到这些参数的正确值。

注意,数值积分的近似顺序不仅受RK方法的阶数限制,而且受微分方程(部分)的微分阶数的限制。

相关问题