在python中使用broyden函数时的Nan或Inf

时间:2014-09-29 23:07:16

标签: python idl nonlinear-functions

我有一个代码,我试图从IDL复制到Python。我有大部分复制并且它有效,除了当我尝试通过broyden1非线性解算器运行我编写的函数(称为broyfunc)时,我收到错误消息,我不能使用infs数组或NaNs。我也不知道怎么去检查这个。我已经包含了我的错误消息和我的代码。谢谢!

import numpy as np
import scipy
import sympy
import sympy.mpmath as mpmath

# Inputs needed for AN_RC_MOD
p0 = 1.5 # reference pressure (surface pressure) [bar]
T0 = 94 # temperature at reference pressure [K]                                
Ttoa = 175 # temperature at top of atmosphere (assumed as stratopause) [K]      
F1 = 1.5 # flux absorbed in channel '1' (assumed to be "stratosphere") [W/m**2]  
F2 = 1.1 # flux absorbed in channel '2' (assumed to be "troposphere") [W/m**2]  
F20 = 0.75 # flux absorbed in channel '2' down to reference level p0  [W/m**2]     
Fi = 0 # internal heat flux [W/m**2]                                           
gam = 1.4 # ratio of specific heats, cp/cv (see Eq. 8 of RC12)                    
alpha = 0.77 # empirical adjustment to dry adiabatic lapse rate (see Eq. 10 of RC12)
n = 4/3 # scaling parameter that relates tau ~ p^n, where tau is gray thermal optical depth (see Eq.6 of RC12)
beta = alpha*((gam-1)/gam)


# Outputs:                                                                             
# taurc - gray thermal optical depth of radiative-convective boundary           
# tau0  - gray thermal optical depth down to reference pressure p0              
# k1    - attenuation parameter for channel '1' [dimensionless]                 
# k2    - attenuation parameter for channel '2' [dimensionless] 


# Important constants
sigma = 5.67e-8 # Stefan-Boltzmann constant [J/s/m**2/K**4]
D = 1.66 # diffusivity factory, (see, e.g., Rodgers & Walshaw 1966)

# Need inputs for: (numbers are for Titan, from Example_w_fluxes.pro)
  #F1C     = F1   ;flux absorbed in channel '1' (assumed to be "stratosphere") [W/m**2] 
  #F20C    = F20  ;flux absorbed in channel '2' down to reference level p0  [W/m**2]
  #F2C     = F2   ;flux absorbed in channel '2' (assumed to be "troposphere") [W/m**2]
  #FiC     = Fi   ;internal heat flux [W/m**2]
  #T0C     = T0   ;temperature at reference pressure [K] 
  #p0C     = p0   ;reference pressure (e.g., surface pressure) [bar] 
  #TtoaC   = Ttoa ;temperature at top of atmosphere [K] 
  #nC      = n    ;scaling power between gray optical depth and pressure
  #betaC   = alpha*(gam - 1.)/gam ;beta defined in Eq. 11 of RC12

# Need inputs for: (numbers are for Titan, from Example_w_fluxes.pro)
  #F1C     = F1   ;flux absorbed in channel '1' (assumed to be "stratosphere") [W/m**2] 
  #F20C    = F20  ;flux absorbed in channel '2' down to reference level p0  [W/m**2]
  #F2C     = F2   ;flux absorbed in channel '2' (assumed to be "troposphere") [W/m**2]
  #FiC     = Fi   ;internal heat flux [W/m**2]
  #T0C     = T0   ;temperature at reference pressure [K] 
  #p0C     = p0   ;reference pressure (e.g., surface pressure) [bar] 
  #TtoaC   = Ttoa ;temperature at top of atmosphere [K] 
  #nC      = n    ;scaling power between gray optical depth and pressure
  #betaC   = alpha*(gam - 1.)/gam ;beta defined in Eq. 11 of RC12

# x[0] = optical depth of Radiative-Convective boundary, taurc
# x[1] = total thermal optical depth down to reference pressure p0 (tau0)

# initial guess that R-C boundary is at D*taurc~1, and tau0~10*p0^n
x = [1/D, 10*p0**n] # initial guesses of taurc and tau0, respectively
print x

# Define function F for Broyden optimization

def broyfunc(x): 

    # Variables
    taurc = x[0] # current value of optical depth of r-c boundary
    tau0  = x[1] # current value of total thermal optical depth down to reference pressure p0

# Compute fluxes and temperatures at r-c boundary ;;;
# first check if solver is attempting to use negative values for the 
# optical depths (which is unphysical), and, if so, return large numbers
# to the solver to prevent it from trying such values as solutions

    if x[0] < 0 or x[1] < 0: 
        x = [1.e3,1.e3]
        print x
    else:
        x = x

# Shortwave optical depth in channel "2" is given by
# LOG( F2/(F2-F20) ), and k2 is defined as the ratio of 
# this to the thermal optical depth at p0 (i.e., tau0)
    if F2 > 0:
          k2 = math.log(F2/(F2-F20))/tau0
    else:
          # if the flux in channel "2" is zero, 
          # then no attenuation in this channel
          k2 = 0
# k1 is computed by requiring the radiative temperature profile
# to equal the top-of-atmosphere temperature (Ttoa, set by user), 
# which is accomplished by evaluating Eq. 18 in RC12 at tau=0
    if F1 > 0: 
          k1 = D*( 2/F1*( sigma*Ttoa**4 - Fi/2 - F2/2*(1 + k2/D) ) - 1 )
    else:
      # if the flux in channel "1" is zero, 
      # then no attenuation in this channel
          k1 = 0
# return values of k1, k2 to user
    k1C = k1 # attenuation parameter for channel '1' (assumed as "stratosphere")
    k2C = k2 # attenuation parameter for channel '2' (assumed as "troposphere")
    print 'k1C', k1C
    print 'k2C', k2C

# four cases: (1) both k1, k2 are greater than zero
#             (2) k1 greater than zero, k2 equal to (or less than) zero
#             (3) k2 greater than zero, k1 equal to (or less than) zero
#             (4) both k1, k2, are equal to (or less than) zero

# case 1: both k1, k2 are greater than zero #
    if k1 > 0 and k2 > 0:
        # upwelling thermal flux at R-C boundary from radiative equilibrium (RC12 Eq. 19)
        Fup_r = (F1/2)*(1 + (D/k1) + (1 - D/k1)*math.exp(-k1*taurc)) + (F2/2)*(1 + (D/k2) + (1 - D/k2)*math.exp(-k2*taurc)) + (Fi/2)*(2 + D*taurc)
        # temperature at R-C boundary from radiative equilibrium (RC12 Eq. 18)
        sigmaT_r = F1/2*(1 + D/k1 + (k1/D - D/k1)*math.exp(-k1*taurc)) + F2/2*(1 + D/k2 + (k2/D - D/k2)*math.exp(-k2*taurc)) + Fi/2*(1 + D*taurc)
        T_r = (sigmaT_r/sigma)**0.25
# case 2: k1 greater than zero, k2 equal to (or less than) zero #
    if  k1 > 0 and k2 < 0:     
        k2C = 0
        # upwelling thermal flux at R-C boundary from radiative equilibrium (RC12 Eq. 19)
        Fup_r = F1/2*(1 + D/k1 + (1 - D/k1)*math.exp(-k1*taurc)) + F2/2*(2 + D*taurc) + Fi/2*(2 + D*taurc)
        # temperature at R-C boundary from radiative equilibrium (RC12 Eq. 18)
        sigmaT_r = F1/2*(1 + D/k1 + (k1/D - D/k1)*math.exp(-k1*taurc)) + F2/2*(1 + D*taurc) + Fi/2*(1 + D*taurc)
        T_r = (sigmaT_r/sigma)**0.25
# case 3: k2 greater than zero, k1 equal to (or less than) zero #
    if k1 < 0 and k2 > 0:      
        k1C = 0
        # upwelling thermal flux at R-C boundary from radiative equilibrium (RC12 Eq. 19)
        Fup_r = F1/2*(2 + D*taurc) + F2/2*(1 + D/k2 + (1 - D/k2)*math.exp(-k2*taurc)) + Fi/2*(2 + D*taurc)
        # temperature at R-C boundary from radiative equilibrium (RC12 Eq. 18)
        sigmaT_r = F1/2*(1 + D*taurc) + F2/2*(1 + D/k2 + (k2/D - D/k2)*math.exp(-k2*taurc)) + Fi/2*(1 + D*taurc)
        T_r = (sigmaT_r/sigma)**0.25
# case 4: both k1, k2, are equal to (or less than) zero
    if k1 < 0 and k2 < 0: 
        k1C = 0  
        k2C = 0
        # upwelling thermal flux at R-C boundary from radiative equilibrium (RC12 Eq. 19)
        Fup_r = F1/2*(2 + D*taurc) + F2/2*(2 + D*taurc) + Fi/2*(2 + D*taurc)
        # temperature at R-C boundary from radiative equilibrium (RC12 Eq. 18)
        sigmaT_r = F1/2*(1 + D*taurc) + F2/2*(1 + D*taurc) + Fi/2*(1 + D*taurc)
        T_r = (sigmaT_r/sigma)**0.25

# Upwelling thermal flux at R-C boundary from convective region (RC12 Eq. 13)
    #Fup_c = sigma*T0**4*math.exp(D*taurc)*((math.exp(-D*tau0)) + (1/((D*tau0)**(4*beta/n)))*(mpmath.gammainc(1+(4*beta/n),D*tau0) - mpmath.gammainc(1+(4*beta/n),D*taurc)))
    #Fup_c = (sigma*T0**4)*math.exp(D*taurc)*(math.exp((-D*tau0) + 1/(D*tau0)**(4*beta/n)*mpmath.gammainc(1+4*beta/n)*(mpmath.gammainc(1+4*beta/n, D*tau0) - mpmath.gammainc(1+4*beta/n,D*taurc))))

    a1 = D*taurc
    a2 = -D*tau0
    a3 = D*taurc
    a4 = D*tau0
    b1 = (4*beta)/n
    b2 = b1 + 1
    Fup_c1 = (sigma*T0**4)*(math.exp(a1))
    Fup_c2 = math.exp(a2)
    Fup_c3 = 1/(a4**b1)
    Fup_c4 = mpmath.gammainc(b2, a3)
    Fup_c5 = mpmath.gammainc(b2, a4)


    Fup_c = Fup_c1*(Fup_c2 + (Fup_c3*(Fup_c4 - Fup_c5))) 

# temperature at R-C boundary from convective region (RC12 Eq. 11)
    T_c = T0*(taurc/tau0)**(beta/n)

    print 'D*taurc', D*taurc
    print 'Fup_r', Fup_r
    print 'Fup_c', Fup_c
    print 'T_r', T_r
    print 'T_c', T_c

# system is solved when the temperatures and upwelling fluxes are continuous 
# at the R-C boundary, so the solver attempts to minimize the difference
# between these quantities as computed from the radiative expressions and the 
# convective expressions

    #result = np.dtype('f8')
    result = [T_r - T_c, Fup_r - Fup_c] 
    print result



# essentially we solve simultaneous equations:
# T_r - T_c = 0 and Fup_r - Fup_c = 0

broyfunc(x)
#y = np.dtype('f8')
y = scipy.optimize.broyden1(broyfunc, x)

ValueError Traceback(最近一次调用最后一次)  in()     183 y = np.dtype(&#39; f8&#39;)     184打印x - &GT; 185 y = scipy.optimize.broyden1(broyfunc,x,iter = 10)     186

// anaconda / lib / python2.7 / site-packages / scipy / optimize / nonlin.pyc in broyden1(F,xin,iter,alpha,reduction_method,max_rank,verbose,maxiter,f_tol,f_rtol,x_tol,x_rtol ,tol_norm,line_search,callback,** kw)

// anaconda / lib / python2.7 / site-packages / scipy / optimize / nonlin.pyc in nonlin_solve(F,x0,jacobian,iter,verbose,maxiter,f_tol,f_rtol,x_tol,x_rtol,tol_norm,line_search ,callback,full_output,raise_exception)     279 dx = np.inf     280 Fx = func(x) - &GT; 281 Fx_norm = norm(Fx)     282     283 jacobian = asjacobian(jacobian)

// anaconda / lib / python2.7 / site-packages / scipy / linalg / misc.pyc in norm(a,ord)     115#与numpy的区别仅在于非限制性处理和使用     116#blas - &GT; 117 a = np.asarray_chkfinite(a)     118如果ord in(None,2)和(a.ndim == 1)和(a.dtype.char in&#39; fdFD&#39;):     119#使用blas来获得快速稳定的欧几里德范数

asarray_chkfinite中的

// anaconda / lib / python2.7 / site-packages / numpy / lib / function_base.pyc(a,dtype,order)     588如果apectype中的a.dtype.char [&#39; AllFloat&#39;]而不是np.isfinite(a).all():     589引发ValueError( - &GT; 590&#34;数组不得包含infs或NaNs&#34;)     591返回a     592

ValueError:数组不能包含infs或NaNs

1 个答案:

答案 0 :(得分:0)

最直接的问题是你没有从broyfunc返回任何内容:

#result = np.dtype('f8')
result = [T_r - T_c, Fup_r - Fup_c] 
print result

因此所有的broyden集成商都看到了有效的

>>> scipy.optimize.broyden1(lambda x: None, 0)
Traceback (most recent call last):
[...]
ValueError: array must not contain infs or NaNs

(可怕的错误信息,诚然。)

添加return result后,我得到类似

的内容
[...]
k1C 114.773687493
k2C 0.0688650670293
D*taurc 23.3390821136
Fup_r 9.7427665389
Fup_c 3.96039873101838
T_r 113.899157512
T_c 90.592872808
[23.306284704464417, mpf('5.782367807885139')]

[1000.0, 1000.0]
k1C 114.8261008
k2C -0.00260762458087
Traceback (most recent call last):
[...]
OverflowError: math range error

但这是一个单独的问题,需要实际考虑你的代码应该做什么。 ; - )


还有一个值得警告的问题是:你写了

n = 4/3 # scaling parameter that relates tau ~ p^n, where tau is gray thermal optical depth (see Eq.6 of RC12)

但你使用的是Python 2,所以你有整数除法:

>>> n = 4/3
>>> n
1

升级到Python 3(最好),通过添加小数点(4./3)确保所有内容都是浮点数,或者 - 如果你遇到Python 2并且这是我的建议正在处理数字代码 - 将from __future__ import division添加到程序的开头,以便获得

>>> from __future__ import division
>>> 4/3
1.3333333333333333