试图改变odeint的容差,但得到“检测到非法输入”和“无限循环”

时间:2015-02-28 02:13:25

标签: python odeint

我给出了以下微分方程y''+ ay' - y + by ^ 3 = c cos(kx),初始条件为y(0)= y'(0)= 0且参数值a = 0.05 ,b = k = 1且c = 0.5。

现在,我要做的是减少求解器的相对容差,直到上一次迭代的数值解y(t)的变化在x = x_max时小于10 ^ -8。

这是我的代码:

from scipy.integrate import odeint
from scipy.optimize import brent
import numpy as np

def de( Y, t ): # de as an array
    a = 0.05    # parameters
    b = 1.0
    c = 0.5
    k = 1.0
    return np.array([Y[1], Y[0] - a*Y[1] - b*(Y[0])**3 - c*np.cos(k*t)])

def Ydiff(h, *args): # calculates difference between the solution Y1
    de = args[0]     # (with default relative error) and Y2 (with new 
    t  = args[1]     # relative error)
    y0 = args[2]
    Y1 = args[3]
    Y2 = odeint( de, y0, t, full_output=0, rtol=h)
    return np.linalg.norm(Y1[-1,0] - Y2[-1,0])    # linalg.norm isn't 
                                                  # necessary here
t  = np.linspace( 0, 100, 10000 )
y0 = np.array([ 0., 0. ])         # initial conditions [y(0),y'(0)]
Y1  = odeint( de, y0, t, full_output=0)
hmin = brent(Ydiff, args=(de,t,y0,Y1), brack=(0,1),full_output=False)

print Ydiff(hmin,de,t,y0,Y1)

我得到了输出:

lsoda--  rtol(i1) is r1 .lt. 0.0        
     In above message,  I1 =         1
     In above message,  R1 = -0.1618034000000E+01
Illegal input detected (internal error).
Run with full_output = 1 to get quantitative information.

使用不同的R1值重复...

lsoda--  run aborted.. apparent infinite loop

我不明白为什么我会“检测到非法输入”和“明显的无限循环”。后者是新的,我不确定为什么会发生这种情况。

任何帮助将不胜感激。

P.S。我对这种格式感到抱歉。我是新手,我不知道如何更改它以使问题看起来不错。

- 编辑 -

我尝试了建议的“full_output = 1”并将Ydiff的第5行更改为

    Y2,p = odeint( de, y0, t, full_output=1,rtol=h)
    print p
    print

我会得到像

这样的东西
{'nfe': array([0, 0, 0, ..., 0, 0, 0]), 'nje': array([0, 0, 0, ..., 0, 0, 0]), 'tolsf': array([ 0.,  0.,  0., ...,  0.,  0.,  0.]), 'nqu': array([0, 0, 0, ..., 0, 0, 0]), 'lenrw': 52, 'tcur': array([ 0.,  0.,  0., ...,  0.,  0.,  0.]), 'hu': array([ -4.10454254e+77,   0.00000000e+00,   0.00000000e+00, ...,
     0.00000000e+00,   0.00000000e+00,   0.00000000e+00]), 'imxer': -1, 'leniw': 22, 'tsw': array([ 0.,  0.,  0., ...,  0.,  0.,  0.]), 'message': 'Illegal input detected (internal error).', 'nst': array([          0, -1217644544,   166928456, ...,        2133,
          2133,        2133]), 'mused': array([0, 0, 0, ..., 0, 0, 0])}

{'nfe': array([   7,    9,   11, ..., 4547, 4547, 4547]), 'nje': array([ 0,  0,  0, ..., 12, 12, 12]), 'tolsf': array([ 0.,  0.,  0., ...,  0.,  0.,  0.]), 'nqu': array([2, 2, 2, ..., 7, 7, 7]), 'lenrw': 52, 'tcur': array([  1.37153782e-02,   2.74214740e-02,   4.11275699e-02, ...,
     1.00011148e+02,   1.00011148e+02,   1.00011148e+02]), 'hu': array([ 0.0137061 ,  0.0137061 ,  0.0137061 , ...,  0.07718142,
    0.07718142,  0.07718142]), 'imxer': -1, 'leniw': 22, 'tsw': array([  0.        ,   0.        ,   0.        , ...,  76.44146089,
    76.44146089,  76.44146089]), 'message': 'Integration successful.', 'nst': array([   3,    4,    5, ..., 2185, 2185, 2185]), 'mused': array([1, 1, 1, ..., 1, 1, 1])}

这很奇怪。今天我没有得到无限循环错误,但我仍然得到这些消息。为了看看发生了什么,我再次编辑了同一行:

    if p['message'] != 'Integration successful.':
    print '=======================\nkey \t 2-norm\n'
    for k in p.keys():
        if type(p[k]) == np.ndarray:
            if np.linalg.norm(p[k]) == 0.:
                print k,'\t ',np.linalg.norm(p[k],2)
            if np.linalg.norm(p[k]) == np.inf:
                print k,'\t ',np.linalg.norm(p[k],2)
            if np.linalg.norm(p[k]) == np.nan:
                print k,'\t ',np.linalg.norm(p[k],2)
    print '\n'

我得到了输出(除了'nje'出现0次之外):

lsoda--  rtol(i1) is r1 .lt. 0.0        
    In above message,  I1 =         1
    In above message,  R1 = -0.7482574658091E-07
Illegal input detected (internal error).
Run with full_output = 1 to get quantitative information.
=======================
key      2-norm

tolsf     0.0
tcur      0.0
hu        0.0
tsw       0.0

我想知道如果可能的话可以解决这个问题。

1 个答案:

答案 0 :(得分:0)

如果您按照建议在full_output中将1设置为Y2 = odeint( de, y0, t, full_output=1, rtol=h),则会看到确切的错误:

 line 55, in Ydiff
return np.linalg.norm(Y1[-1,0] - Y2[-1,0])    # linalg.norm isn't
TypeError: tuple indices must be integers, not tuple

如果你print( type(Y2)),你会发现它是一个元组而不是一个数组。它实际上是一个数组元组:

(array([[  0.00000000e+00,   0.00000000e+00],
       [ -2.50008335e-05,  -4.99925000e-03],
       [ -9.99866688e-05,  -9.99600058e-03],
       ..., 
       [ -1.34944031e+00,  -1.27522994e+00],
       [ -1.36215569e+00,  -1.26750159e+00],
       [ -1.37479105e+00,  -1.25922413e+00]]), {'nfe': array([  29,   29,   31, ..., 4801, 4803, 4803], dtype=int32), 'nje': array([0, 0, 0, ..., 0, 0, 0], dtype=int32), 'tolsf': array([  1.27797787e-316,   1.27797787e-316,   1.27797787e-316, ...,
         1.27797787e-316,   1.27797787e-316,   1.27797787e-316]), 'nqu': array([3, 3, 3, ..., 7, 7, 7], dtype=int32), 'lenrw': 52, 'tcur': array([  2.15045290e-02,   2.15045290e-02,   3.64071805e-02, ...,
         9.99873247e+01,   1.00033487e+02,   1.00033487e+02]), 'hu': array([ 0.01490265,  0.01490265,  0.01490265, ...,  0.04616208,
        0.04616208,  0.04616208]), 'imxer': -1, 'leniw': 22, 'tsw': array([ 0.,  0.,  0., ...,  0.,  0.,  0.]), 'message': 'Integration successful.', 'nst': array([  14,   14,   15, ..., 2293, 2294, 2294], dtype=int32), 'mused': array([1, 1, 1, ..., 1, 1, 1], dtype=int32)})