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

查看:20
本文介绍了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 desired)=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) 在每一步中都是连续的(并且有一个连续的导数).signum 函数显然打破了这个要求.这会导致误差估计非常高,无论步长有多小,进而导致步长过小以及您遇到的问题.

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 替换 signum 函数,这应该没问题,甚至对于大多数应用程序更现实.在您的代码中,您可以使用

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 控制 sigmoid 的陡度.选择足够高的值以反映您实际需要的行为.如果您选择过高,这可能会对您的运行时间产生负面影响,因为积分器会将步长调整为不必要的小.

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天全站免登陆