[英]Using dopri5 to plot a system of ODEs in matrix form
我對繪圖感興趣的方程組如下:
通過執行以下操作,我能夠繪制出他們修改的示例的圖:
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的維數。噪聲,並查看如何影響ODE)。 我了解數學上如何以矩陣形式編寫方程式,但是我不了解如何修改代碼,因此在“ def model(t,r):”部分中,將其讀取為數組/矩陣。 要將等式轉換為矩陣形式,我可以定義:
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個以上維度的系統,這也將變得更加容易)
使用實現的numpy.array
操作首選項以元素方式起作用(與以矩陣方式操作的numpy.matrix
操作相反),方程組的公式很簡單
def model(t,x):
return x*(b-A.dot(x*x))
x*x
產生元素方平方的向量, x**2
是另一個選擇, A.dot(x2)
對numpy.array
對象執行矩陣向量乘積, x*(b-...)
為再次是兩個操作數向量的向量值逐元素積。
使用u=x*x
作為變量將系統簡化為
dotu = 2*u*(b-A.dot(u))
因此,它的度數小1,並且平方度u
,這可能有助於檢查靜止點。 我懷疑它們都是雙曲線的,因此沒有漸近穩定的解決方案。
使用替換u=log(x)
並因此
dotu = b-A.dot(exp(2*u))
在負無窮大處隱藏靜止點,因此此替換的分析值可能會受到限制。 但是, x=exp(u)
是內置的,這可以允許使用更積極的數值方法,或者使用與以前相同的謹慎性提供更高的精度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.