2017-05-08 284 views
2

我试图解决这个问题:的Python:无法解决使用odeint与符号函数微分方程

enter image description here

其中U是

enter image description here

这里:

s=c*e(t)+e_dot(t) 

and

e(t)=theta(t)-thetad(t) 

e_dot(t)=theta_dot(t)-thetad_dot(t) 

其中thetad(希塔需要的话)= SIN(T) - 待跟踪即信号!我试着第一次使用odeint,它在t = 0.4后给出的误差是θ(上面的微分方程的解)平稳地下降到了0, 0并留下。然而,当我试图将mxstep提高到5000000时,我可以得到一些正确的图,直到t = 4.3s。

我想得到一个纯正弦曲线图。那就是我希望theta(上述微分方程的解)跟踪时间即sin(t)。但在t = 4.3秒后无法准确地追踪该点。在这段时间之后,θ(上述微分方程的解)简单地下降到0并停留在那里。

这里是我的代码 -

from scipy.integrate import odeint 
import numpy as np 
import matplotlib.pyplot as plt 

c=0.5 
eta=0.5 
def f(Y,t): 
    x=Y[0] 
    y=Y[1] 
    e=x-np.sin(t) 
    de=y-np.cos(t) 
    s=c*e+de 
    return [y,-c*(de)-np.sin(t)-eta*np.sign(s)] 

t=np.linspace(0,10,1000) 
y0=[0.5,1.0] 
sol=odeint(f,y0,t,mxstep=5000000) 
#sol=odeint(f,y0,t) 
print(sol) 
angle=sol[:,0] 
omega=sol[:,1] 
error=angle-np.sin(t) 
derror=omega-np.cos(t) 
plt.subplot(4,2,1) 
plt.plot(t,angle) 
plt.plot(t,error,'r--') 
plt.grid() 
plt.subplot(4,2,2) 
plt.plot(t,omega) 
plt.plot(t,derror,'g--') 
plt.grid() 
plt.subplot(4,2,3) 
plt.plot(angle,omega) 
plt.grid() 
plt.subplot(4,2,4) 
plt.plot(error,derror,'b--') 
plt.savefig('signum_graph.eps') 
plt.show() 

回答

1

odeint(你发现实现,可能是所有集成商)采用积分是基于这样的假设,你的衍生物(f)是连续的(并具有连续衍生物)在每个步骤中。 signum函数显然打破了这个要求。这会导致误差估计值非常高,无论步长有多小,反过来导致步长过小以及遇到的问题。

达到这一目的有两种常用的解决方案:

  1. 选择你的步长,使得标志翻转正好落在了一步。 (这可能会非常乏味)

  2. 用非常陡峭的sigmoid代替signum函数,这对大多数应用程序来说应该是很好的,甚至更现实。在代码中,你可以使用

    sign = lambda x: np.tanh(100*x) 
    

    ,而不是np.sign。这里的因子100控制了S形的陡度。选择它足够高,以反映你实际需要的行为。如果选择过高,这可能会对运行时间产生负面影响,因为积分器会将步长调整到不必要的小。

在你的情况,设定绝对值小的公差也似乎是工作,但我不会依靠这样的:

sol = odeint(f,y0,t,mxstep=50000,atol=1e-5) 
+0

的ODE功能应具有中等规模的连续导数最多的顺序的方法。什么“中等大小”取决于步长算法的内部。即使是阶梯函数的一阶导数,也是一个狄拉克三角洲峰值,较高的一个更差...... – LutzL

+0

非常感谢! Wrzlprmft你救了我很多麻烦!我正在查看integrate.ode中的Vode选项。然而,tanh在这里帮助了我很多! –

+0

另一个变体是'def sign(s):s * = 1e3;返回s /(1 + np.abs(s));'。同时尝试移动sigmoid函数以使其不对称,使其不对称,或者其他小的偏移量。只有在这种变化下解的相似性,你才能希望在给定的时间间隔内存在某种广义的解。 – LutzL