Python:无法使用带信号强度函数的odeint求解微分方程 [英] Python: Unable to solve a differential equation using odeint with signum function

查看:140
本文介绍了Python:无法使用带信号强度函数的odeint求解微分方程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解决此问题:

I am trying to solve this problem:

U在哪里

此处:

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

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

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

其中thetad(所需的theta)= sin(t)-即要跟踪的信号! 和thetad_dot = cos(t),J = 10,c = 0.5,eta = 0.5

where thetad(theta desired)=sin(t)-- i.e signal to be tracked! and thetad_dot=cos(t),J=10,c=0.5,eta=0.5

我首先用odeint尝试-它在t = 0.4之后给出了误差,即theta(上述微分方程的解)平稳降为0,然后保持不变.但是,当我尝试将mxstep增加到5000000时,直到t = 4.3s时,我才能得到一些正确的图形.

I tried first with odeint- it gave error after t=0.4 that is theta(solution of above differential equation) fell flat to 0 and stayed thereafter. However when I tried to increase mxstep to 5000000 I could get somewhat correct graph till t=4.3s.

我想得到一个纯正弦图.那就是我想要theta(上述微分方程的解)跟踪thetad即sin(t).但是它无法在t = 4.3秒后准确跟踪thetad.在这段时间之后,theta(上面的微分方程的解)简单地下降到0并停留在那里.

I want to get a pure sinusoidal graph. That is I want theta(solution of the above differential equation) to track thetad i.e sin(t). But it is not able to accurately track thetad after t=4.3sec. After this time theta(solution of the above differential equation) simply falls off to 0 and stays there.

这是我的代码-

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()

推荐答案

odeint使用的积分器(可能是您发现实施的所有积分器)都是基于您的导数(f)是连续的(并且在每个步骤中都有一个连续的导数).信号函数显然打破了这一要求.无论步长有多小,这都会导致误差估计非常高,进而导致步长过小以及您遇到的问题.

The integrator employed by odeint (and probably all integrators you find implemented) are based on the assumption that your derivative (f) is continuous (and has a continuous derivative) during each step. The signum function obviously breaks this requirement. This causes the error estimates to be very high, no matter how small the step size, which in turn leads to an overly small step size and the problems you have been experiencing.

对此有两种常规解决方案:

There are two general solutions to this:

  1. 选择步长,以使符号翻转恰好落在台阶上. (这可能非常乏味.)

  1. Choose your step size such that the sign flip exactly falls on a step. (This may be horribly tedious.)

用非常陡峭的 Sigmoid 替换信号函数,应该没问题,甚至可以对于大多数应用程序来说更现实.在您的代码中,您可以使用

Replace the signum function with a very steep sigmoid, which should be fine and even more realistic for most applications. In your code, you could use

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

而不是np.sign.此处的系数100控制S型曲线的陡度.选择足够高的值以反映您实际需要的行为.如果选择的值过高,这可能会对您的运行时间产生负面影响,因为积分器会将步长调整得不必要地小.

instead of np.sign. The factor 100 here controls the steepness of the sigmoid. Choose it sufficiently high to reflect the behaviour you actually need. If you choose it excessively high, this may negatively affect your runtime as the integrator will adapt the step size to be unnecessarily small.

在您的情况下,设置较小的绝对公差似乎也可行,但是我不会依赖于此:

In your case, setting a small absolute tolerance also seems to be working, but I would not rely on this:

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

这篇关于Python:无法使用带信号强度函数的odeint求解微分方程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆