我正在尝试以python可视化振荡器系统。只要其中一个变量没有累积(使用狄拉克-德尔塔函数),系统就可以工作。但是,当我尝试包含它时,系统没有任何变化。您可以在下面找到我所经历的过程以及遇到的一些问题。
我已经在python中编写了一些代码,能够正确可视化常规的振荡器行为。但是,在其中一个变量中包含逐步增量时,系统不会对此做出反应。在下面,您可以找到包含增量的版本。该代码运行,但给出的输出就像没有增量一样。在代码下,您可以找到正确解决方案的问题。
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
a4 = 5.68
aAPD = 9.09
deltaZ = 0.41
gamma = 1.33
negV = 1
n=500
def f(V):
if V<=-60:
return V/20 + 4
elif V>=20:
return V/20 - 1
else:
return -V/80 + 1/4
def alpha(V):
if V<0:
return a4
else:
return -aAPD
def g(q):
return q/(q+1)
def step(V):
global negV
if V>0 and negV == 1:
negV = 0
return deltaZ
elif V<=0 and negV == 0:
negV = 1
return 0
else:
return 0
# function that returns dz/dt
def model(z,t):
V = z[0]
y = z[1]
q = z[2]
dVdt = 25000*(y - f(V))
dydt = alpha(V) - a4*g(q)
dqdt = -gamma*g(q) + step(V)
dzdt = [dVdt,dydt,dqdt]
return dzdt
# initial condition
z0 = [0,0,0]
# time points
t = np.linspace(0,0.5,n)
# solve ODE
z = odeint(model,z0,t)
# plot results
plt.plot(t,z[:,0],label='Voltage')
plt.plot(t,z[:,1],label='y')
plt.plot(t,z[:,2],label='Z')
plt.ylabel('response')
plt.xlabel('time')
plt.legend(loc='best')
plt.show()
问题出在函数step(V)
上。振荡器在某个时刻越过值V = 0。此时,q的值应增加deltaZ。
我不了解或不知道如何获取正确值的python的odesolver中有几点。因此,这里有问题/问题的简短列表:
if V[i]>0 and V[i-1]<0: return deltaZ
那样包含一条语句,那就更好了。由于您最终绘制了V的值,因此该信息应该在某个地方可用,但是我看不到如何访问V的先前值。最好我会解决所有这三个问题,但是如果您能够提供其中一项的答案,那么我也将得到很多帮助。
答案 0 :(得分:0)
我强烈建议您在事件中使用solve_ivp
函数来检测V=0
交叉。参见here。
如果使用终端事件,则解决方案将恰好在V=0
处停止。然后,您可以使用您的瞬时更改在ODE集成器之外更新解决方案,并将其用作第二次调用solve_ivp
的初始条件以完成集成。我假设V=0
的交叉仅发生一次,但是您可以构建逻辑以处理事件的多个交叉。