简体   繁体   English

使用dopri5进行Python绘图

[英]Python plotting using dopri5

My goal is to plot the following set of coupled ODEs: 我的目标是绘制以下一组耦合的ODE:

在此处输入图片说明

The odeint method was giving me problems (such as some of the x_i's taking on negative values which analytically does not happen), so I decided to use a fourth-order Runge-Kutta solver. odeint方法给我带来了问题(例如某些x_i呈现负值,而解析上不会发生),因此我决定使用四阶Runge-Kutta求解器。 I was following the examples here to use the dopri5 method ( Using adaptive step sizes with scipy.integrate.ode ): 我在下面的示例中使用dopri5方法(对scipy.integrate.ode 使用自适应步长 ):

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

#Constants
c13 = 6.2
c14 = 1.0
c21 = 7.3
c32 = 2.4
c34 = 12.7
c42 = 5.7
c43 = 5.0

e12 = 1.5
e23 = 2.5
e24 = 2.0
e31 = 3.0
e41 = 4.8

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

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

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

ode =  spi.ode(model)

ode.set_integrator('dopri5')
ode.set_initial_value(ic,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.3])

plt.show()

which produces the following plot: 生成以下图:

在此处输入图片说明

However, my plots have something odd about them -- the x1 value seems to randomly spike above 1. Because (1,0,0,0) is a fixed point of the dynamical system, it doesn't make much sense to me that it spikes above one (there might've been a reason if the spikes had shown some sort of repetitive pattern, but they look random in the plot, so I'm wondering if that has more to do with just the numerical integration rather than the actual dynamics). 但是,我的图有一些奇怪的地方– x1值似乎随机上升到1以上。因为(1,0,0,0)是动力系统的固定点,所以对我而言,这没有多大意义峰值超过一个(可能是峰值显示某种重复模式的原因,但在图中它们看起来是随机的,所以我想知道这是否与数字积分有关而不是与实际动态)。 Changing parameters also changes that spike (some parameter values I tried still have that spiking but it's substantially less). 更改参数也会更改尖峰(我尝试过的某些参数值仍然有尖峰,但要小得多)。 I therefore have 2 questions: 因此,我有两个问题:

1) What is causing these spikes to appear? 1)是什么导致这些尖峰出现? My original thought was that it was the "t_step" being large, so I tried playing around with it (which leads me to my second question) 我最初的想法是“ t_step”很大,所以我尝试使用它(这使我想到了第二个问题)

2) I tried changing the step size from 1 to 0.1. 2)我尝试将步长从1更改为0.1。 However it produced this plot, which actually looks much different than if step size was 1 (which I thought lower step size would produce more accurate plots?) In this plot, it appears that the time each x_i spends near 1 is longer than if the step size was 1 instead of 0.1, and the heights of the spikes are all equal -- how do I know which plot is more accurate of the true system considering the plots have some substantial differences? 但是,它生成了该图,实际上看起来与步长为1时有很大不同(我认为较低的步长会生成更精确的图?)在此图中,似乎每个x_i花费接近1的时间比如果步长是1而不是0.1,并且尖峰的高度都相等-考虑到这些图之间存在实质性差异,我如何知道哪个图对真实系统更准确?

在此处输入图片说明

The real crux of the problem I'm working on is looking up the interaction between x3 and x4, but I want to make sure the simulations are set up correctly so that I can get accurate results about x3 and x4! 我正在研究的问题的真正症结在于查找x3和x4之间的交互,但是我想确保正确设置了仿真,以便可以得到关于x3和x4的准确结果!

By the Gronwall lemma, the error propagation of "nice" ODE is controlled by an exponential with the Lipschitz constant L as factor. 通过Gronwall引理,“好” ODE的误差传播由以Lipschitz常数L为因子的指数控制。 Which means that any local error contribution incurred at time t gets (potentially) magnified by a factor of exp(L(Tt)) at time T . 这意味着在时刻发生的任何地方误差贡献t得到(可能)通过的因子放大exp(L(Tt))在时间T

Being generous one may use L=10 for your system. 慷慨的可以为您的系统使用L=10 Over a time interval of 10 this gives an error magnification of exp(100)=2.688e+43 , or a total decoupling of the numerical value from the initial value and the exact solution. 10的时间间隔内,这会得出exp(100)=2.688e+43的误差放大倍率,或者数值与初始值和精确解的总解耦。

Thus it is more astonishing how far, up to t=80 , the similarity of both solutions is preserved. 因此,令人惊讶的是,直到t=80为止,两个解决方案的相似性都得以保留。


Notes on the theory, spikes: There is nothing limiting the variables to stay inside the interval [0,1] or to have some conserved quantity that has the same effect. 关于理论的注释,尖峰:没有限制变量保持在区间[0,1]内或具有某些守恒量的相同效果的任何限制。 The best you can do is to use a Ljapunov function like V(x)=sum(x*x) which then gives bounds that limit the solution to be between two spheres. 最好的办法是使用Ljapunov函数,例如V(x)=sum(x*x) ,该V(x)=sum(x*x)然后给出将解限制在两个球体之间的界限。

The fixed points are all hyperbolic, the Jacobian there is rank-deficient and traceless which excludes stable fixed points. 这些不动点都是双曲的,雅可比行列是秩不足且无迹的,不包括稳定的不动点。 The spikes are then just a result of the direction of the stable and unstable manifolds/axis of these hyperbolic points. 然后,尖峰只是这些双曲线点的稳定和不稳定歧管/轴方向的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM