使用dopri5绘制矩阵形式的ODE系统

时间:2015-12-10 22:23:21

标签: python matrix ode

对绘图感兴趣的等式系统如下:

enter image description here

我能够通过执行以下操作来修改他们发布的示例:

import scipy as sp
import pylab as plt
import numpy as np
import scipy.integrate as spi

#Constants
c13 = 4.2
c14 = 4.2
c21 = 4.3
c32 = 4.4
c34 = 4.4
c42 = 4.4
c43 = 4.4

e12 = 1.9
e23 = 2.5
e24 = 2.2
e31 = 2.0
e41 = 2.0

#Time
t_end = 700
t_start = 0
t_step = 1
t_interval = sp.arange(t_start, t_end, t_step)

#Initial Condition
r = [0.2,0.3,0.3,0.5]

def model(t,r):
    Eqs= np.zeros((4))
    Eqs[0] = (r[0]*(1-r[0]*r[0]-r[1]*r[1]-r[2]*r[2]-r[3]*r[3])-c21*((r[1]*r[1])*r[0])+e31*((r[2]*r[2])*r[0])+e41*((r[3]*r[3])*r[0]))
    Eqs[1] = (r[1]*(1-r[0]*r[0]-r[1]*r[1]-r[2]*r[2]-r[3]*r[3])+e12*((r[0]*r[0])*r[1])-c32*((r[2]*r[2])*r[1])-c42*((r[3]*r[3])*r[1]))
    Eqs[2] = (r[2]*(1-r[0]*r[0]-r[1]*r[1]-r[2]*r[2]-r[3]*r[3])-c13*((r[0]*r[0])*r[2])+e23*((r[1]*r[1])*r[2])-c43*((r[3]*r[3])*r[2]))
    Eqs[3] = (r[3]*(1-r[0]*r[0]-r[1]*r[1]-r[2]*r[2]-r[3]*r[3])-c14*((r[0]*r[0])*r[3])+e24*((r[1]*r[1])*r[3])-c34*((r[2]*r[2])*r[3]))
    return Eqs

ode =  spi.ode(model)

ode.set_integrator('dopri5')
ode.set_initial_value(r,t_start)
ts = []
ys = []

while ode.successful() and ode.t < t_end:
    ode.integrate(ode.t + t_step)
    ts.append(ode.t)
    ys.append(ode.y)

t = np.vstack(ts)
x1,x2,x3,x4 = np.vstack(ys).T

plt.subplot(1, 1, 1)
plt.plot(t, x1, 'r', label = 'x1')
plt.plot(t, x2, 'b', label = 'x2')
plt.plot(t, x3, 'g', label = 'x3')
plt.plot(t, x4, 'purple', label = 'x4')
plt.xlim([0,t_end])
plt.legend()
plt.ylim([-0.2,1.5])

plt.show()

这肯定会给我一些我想要的情节。但是,我想最终使用这组ODE进行随机分析,因此,如果以矩阵形式编写ODE系统,那么对此进行建模要容易得多(这样,我可以轻松地改变噪音,看看它如何影响ODE)。我理解以矩阵形式编写方程式的数学方法,但我不理解如何修改我的代码,以便在&#34; def模型(t,r):&#34;部分,它被读作数组/矩阵。要将方程转换为矩阵形式,我可以定义:

b = np.array([1, 1, 1, 1]) 
A = np.array([[1, 1+c21, 1-e31, 1-e41], 
              [1-e12, 1, 1+c32, 1+c42],
              [c13+1, 1-e23, 1, 1+c43],
              [c14+1, 1-e24, 1+c34, 1]])

然后方程组将是(其中x是向量(x1,x2,x3,x4)):

x(t)= diag(x)[b ^ {T} -Adiag(x)x]

所以我的问题是:如何修改我定义我的ODE的位置,以便我可以将它们作为矩阵输入而不是单独写出每个方程? (如果我稍后查看一个超过4维的系统,这也会更容易)

1 个答案:

答案 0 :(得分:0)

使用已实现的numpy.array操作首选项以元素方式执行(与以矩阵方式操作的numpy.matrix操作相比),方程组的公式只是

def model(t,x):
    return x*(b-A.dot(x*x))

x*x生成元素方块的向量,x**2将是另一个选项,A.dot(x2)执行numpy.array个对象的矩阵向量积,{{1}同样是两个操作数向量的向量值元素乘积。

使用x*(b-...)作为变量会将系统缩小为

u=x*x
因此,它在dotu = 2*u*(b-A.dot(u)) 中具有一个度并且是二次的,这可以帮助检查静止点。我怀疑它们都是双曲线的,因此没有渐近稳定的解决方案。

使用替换u,因此

u=log(x)

将静止点隐藏在负无穷大处,因此该替换的分析值可能受到限制。然而,dotu = b-A.dot(exp(2*u)) 的积极性是内置的,这可能允许更积极的数值方法或使用与以前相同的谨慎提供更多的准确性。