Python递归微分方程求解系统

Python递归微分方程求解系统,python,recursion,differential-equations,odeint,Python,Recursion,Differential Equations,Odeint,所以我试图用Python来解以下微分方程组 如您所见,对于{0,1,2,3,…}中的每一个n,系统取决于前一个系统的解 我已经尝试过求解n=0的系统,并找到了一个可以插入R(1 | t)中的解决方案R(0 | t),Python可以毫无问题地解决该系统。我已将解决方案R(0 | t)定义为r0(t),并实现了n=1的解决方案,如下所示: def model(z,t): dxdt = -3.273*z[0] + 3.2*z[1] + r0(t) dydt = 3.041*z[0]

所以我试图用Python来解以下微分方程组

如您所见,对于{0,1,2,3,…}中的每一个n,系统取决于前一个系统的解

我已经尝试过求解n=0的系统,并找到了一个可以插入R(1 | t)中的解决方案R(0 | t),Python可以毫无问题地解决该系统。我已将解决方案R(0 | t)定义为r0(t),并实现了n=1的解决方案,如下所示:

def model(z,t):
    dxdt = -3.273*z[0] + 3.2*z[1] + r0(t)
    dydt = 3.041*z[0] - 3.041*z[1]
    dzdt = [dxdt, dydt]
    return dzdt

z0 = [0,0]

t = np.linspace(0,90, 90)

z1 = odeint(model, z0, t)
但是,我想通过在求解n时调用n-1系统的解来推广这个解决方案。由于微分方程在矩阵的右上角只有与零不同的条目,我们只需要上一个解的z解。我试过了

def model0(z,t):
    dxdt = -3.273*z[0] + 3.2*z[1] 
    dydt = 3.041*z[0] - 3.041*z[1]
    dzdt = [dxdt, dydt]
    return dzdt

z0 = [1,1]

t = np.linspace(0,90)

def model1(z,t):
    dxdt = -3.273*z[0] + 3.2*z[1] + 0.071*odeint(model0, z0, t)[t,1]
    dydt = 3.041*z[0] - 3.041*z[1]
    dzdt = [dxdt, dydt]
    return dzdt


z1 = [0,0]


z = odeint(model1, z1, t)

没有任何运气。有没有人有用Python解决这些递归ODE系统的经验

提前谢谢

更新了6x6矩阵和6函数的代码:


A = np.array([[h1h1, h1h2, h1h3, h1a1, h1a2, h1a3], 
              [h2h1, h2h2, h2h3, h2a1, h2a2, h2a3],
              [h3h1, h2h3, h3h3, h3a1, h3a2, h3a3],
              [a1h1, a1h2, a1h3, a1a1, a1a2, a1a3],
              [a2h1, a2h2, a2h3, a2a1, a2a2, a2a3],
              [a3h1, a3h2, a3h3, a3a1, a3a2, a3a3]
              ])


B = np.array([[0, 0, 0, 0, 0,    0], 
              [0, 0, 0, 0, 0,    0],
              [0, 0, 0, 0, h3a0, 0],
              [0, 0, 0, 0, 0,    0],
              [0, 0, 0, 0, 0,    0],
              [0, 0, 0, 0, 0,    0],
              ])


def model0n(u,t):
    Ra = u.reshape([-1,6])
    n = len(Ra) - 1
    dRa = np.zeros(Ra.shape)
    dRa[0] = A @ Ra[0]
    for i in range(1,n+1): 
        dRa[i] = A @ Ra[i] + B @ Ra[i-1]
    return dRa.flatten()

u0 = [1,1,1,1,1,1,0,0,0,0,0,0]
t = np.linspace(0,90,90+1)

u = odeint(model0n,u0,t)
以上结果为u[:,0]的以下曲线图:

对于n=0,它提供矩阵乘积“手动”的结果:


def modeln0manually(z,t):
    d1dt = h1h1*z[0] + h1h2 * z[1] + h1h3*z[2] + h1a1*z[3] + h1a2*z[4] + h1a3*z[5]
    d2dt = h2h1*z[0] + h2h2 * z[1] + h2h3*z[2] + h2a1*z[3] + h2a2*z[4] + h2a3*z[5]
    d3dt = h3h1*z[0] + h3h2 * z[1] + h3h3*z[2] + h3a1*z[3] + h3a2*z[4] + h3a3*z[5]
    d4dt = a1h1*z[0] + a1h2 * z[1] + a1h3*z[2] + a1a1*z[3] + a1a2*z[4] + a1a3*z[5]
    d5dt = a2h1*z[0] + a2h2 * z[1] + a2h3*z[2] + a2a1*z[3] + a2a2*z[4] + a2a3*z[5]
    d6dt = a3h1*z[0] + a3h2 * z[1] + a3h3*z[2] + a3a1*z[3] + a3a2*z[4] + a3a3*z[5]
    drdt = [d1dt, d2dt, d3dt, d4dt, d5dt, d6dt]    
    return drdt    


u0 = [1,1,1,1,1,1]
t = np.linspace(0,90)
z = odeint(modeln0manually, u0, t)
生成u[:,0]的绘图:

您的系统是耦合的,即使是以三角形方式。因此,最简洁的方法是将其作为一个耦合系统来求解

A = np.array([[-3.273, 3.2], [3.041, -3.041]])
B = np.array([[0, 0.071], [0, 0]])

def model0n(u,t):
    Ra = u.reshape([-1,2])
    n = len(Ra) - 1
    dRa = np.zeros(Ra.shape)
    dRa[0] = A @ Ra[0]
    for i in range(1,n+1): 
        dRa[i] = A @ Ra[i] + B @ Ra[i-1]
    return dRa.flatten()

u0 = [1,1,0,0]
t = np.linspace(0,90,90+1)
u = odeint(model0n,u0,t)

谢谢你的回答,不过我的编码技能在这里可能有点欠缺。尝试您的解决方案会在使用odeint语句时出现错误,因为Python无法将u重塑为除n=1之外的n行2列的向量,这导致它只返回问题的初始条件。不过,我可能误解了您的解决方案中的某些内容。
u
需要包含
R(0 | t)
R(n | t)
2*(n+1)
条目,它同时计算所有组件DE的右侧。我使它更加灵活,没有外部维度
n
。注意,这仍然没有被测试,实际上循环索引是错误的。现在它被测试了,它产生了结果。现在增加
n
只意味着向
u0
添加更多条目,始终为偶数。您提供的解决方案非常有用,谢谢!然而,当把模型扩展到一个有六个方程的系统,生成a和b6x6矩阵时,我又遇到了一些麻烦。我用[-1,6]重新塑造了Ra,并提供了新的矩阵,但它不会产生n>0的值和n=0的错误概率。如果我回到我问题的第一个,把六个方程和一个μij*z[j]放在一起,它对n=0有效。在扩展模型时,我是否缺少一些东西?对我来说,这似乎是直截了当的。我已经将我的新代码放入了一个问题中,A和B中的任意值是否为
B
中的尾随逗号?我看代码中没有其他不规则之处。也许我遗漏了一些关于
.flant()
,也可以使用
重塑([-1])
来取消状态数据的结构确切的错误消息是什么?也可以再次检查
np.matmul
(由
@
使用的操作),但这应该只实现通常的矩阵乘法。