Example #1
0
def Es(T, method=None):
    """Computes saturated pressure in Pa given T in K, using the method:
    1: Hyland-Wexler formulation, polynomial coeff (absolute norm)
    2: Wexler formulation
    3: Hyland-Wexler formulation, polynomial coeff (relative error norm)
    4: classic Goff Gratch equation
    5: 6.112*numpy.ma.exp(17.67*tempc/(tempc+243.5))

    Default is method 1
    
    Note: 1 and 2 use method 3 where T is not : 173.15 < T < 473.15
    ref for 1, 2 and 3:
    Piotr Flatau and al., Journal of Applied Met., Vol 31, Dec 1992 ( http://ams.allenpress.com/perlserv/?request=get-document&doi=10.1175%2F1520-0450(1992)031%3C1507%3APFTSVP%3E2.0.CO%3B2&ct=1 )
    """
    if method is None:
        method = 1

    if method == 1:
        ## Put in C
        x = T - 273.15
        ## Water vapor
        c0 = 0.611220713E03
        c1 = 0.443944344E02
        c2 = 0.143195336E01
        c3 = 0.263350515E-01
        c4 = 0.310636053E-03
        c5 = 0.185218710E-05
        c6 = 0.103440324E-07
        c7 = -0.468258100E-10
        c8 = 0.466533033E-13
        eswat = c0 + x * (c1 + x * (c2 + x * (c3 + x * (c4 + x *
                                                        (c5 + x *
                                                         (c6 + x *
                                                          (c7 + x * c8)))))))
        ## ice
        c0 = .611153246E03
        c1 = .503261230E02
        c2 = .188595709E01
        c3 = .422115970E-01
        c4 = .620376691E-03
        c5 = .616082536E-05
        c6 = .405172828E-07
        c7 = .161492905E-09
        c8 = .297886454E-12
        esice = c0 + x * (c1 + x * (c2 + x * (c3 + x * (c4 + x *
                                                        (c5 + x *
                                                         (c6 + x *
                                                          (c7 + x * c8)))))))
        ## Combine
        es = MV2.where(MV2.less(T, 273.15), esice, eswat)
        ## Overwrite values outside valid range with method 2
        mn, mx = genutil.minmax(T)
        if mn < 173.16 or mx > 473.15:
            es2 = Es(T, method=2)
            es = MV2.where(MV2.less(T, 173.16), es2, es)
            es = MV2.where(MV2.greater(T, 473.15), es2, es)
    elif method == 2:
        # over water
        g0 = -0.29912729E4
        g1 = -0.60170128E4
        g2 = 0.1887643854E2
        g3 = -0.28354721E-1
        g4 = 0.17838301E-4
        g5 = -0.84150417E-9
        g6 = 0.44412543E-12
        g7 = 0.2858487E1
        # over ice
        k0 = -0.58653696e4
        k1 = 0.2224103300E2
        k2 = 0.13749042E-1
        k3 = -0.34031775E-4
        k4 = 0.26967687E-7
        k5 = 0.6918651
        esice = (k0 + (k1 + k5 * MV2.log(T) +
                       (k2 + (k3 + k4 * T) * T) * T) * T) / T  # over ice
        eswat = (g0 + (g1 + (g2 + g7 * MV2.log(T) +
                             (g3 + (g4 + (g5 + g6 * T) * T) * T) * T) * T) *
                 T) / T**2  # over water
        es = MV2.where(MV2.less(T, 273.15), esice, eswat)
        es = MV2.exp(es)
    elif method == 3:
        ## Put in C
        x = T - 273.15
        ## Water vapor
        c0 = 0.611213476E03
        c1 = 0.444007856E02
        c2 = 0.143064234E01
        c3 = 0.264461437E-01
        c4 = 0.305930558E-03
        c5 = 0.196237241E-05
        c6 = 0.892344772E-08
        c7 = -0.373208410E-10
        c8 = 0.209339997E-13
        eswat = c0 + x * (c1 + x * (c2 + x * (c3 + x * (c4 + x *
                                                        (c5 + x *
                                                         (c6 + x *
                                                          (c7 + x * c8)))))))
        ## ice
        c0 = .611123516E03
        c1 = .503109514E02
        c2 = .1888369801E01
        c3 = .420547422E-01
        c4 = .614396778E-03
        c5 = .602780717E-05
        c6 = .387940929E-07
        c7 = .149436277E-09
        c8 = .262655803E-12
        esice = c0 + x * (c1 + x * (c2 + x * (c3 + x * (c4 + x *
                                                        (c5 + x *
                                                         (c6 + x *
                                                          (c7 + x * c8)))))))
        ## Combine
        es = MV2.where(MV2.less(T, 273.15), esice, eswat)
        ## Overwrite values outside valid range with method 2
        mn, mx = genutil.minmax(T)
        if mn < 173.16 or mx > 473.15:
            es2 = Es(T, method=2)
            es = MV2.where(MV2.less(T, 173.16), es2, es)
            es = MV2.where(MV2.greater(T, 473.15), es2, es)
    elif method == 4:
        est = 101324.6  #Pa
        Ts = 373.16 / T
        a = -7.90298
        b = 5.02808
        c = -1.3816E-7
        d = 11.344
        f = 8.1328E-3
        h = -3.49149
        maxexp = int(numpy.log10(numpy.finfo(numpy.float).max))
        minexp = 1 - a
        es = a * (Ts - 1.)
        es = es + b * numpy.ma.log10(Ts)
        A = d * (1. - Ts)
        A = numpy.ma.masked_greater(A, maxexp)
        A = numpy.ma.masked_less(A, minexp)
        es = es + c * (numpy.ma.power(10, A) - 1.)
        A = h * (Ts - 1.)
        A = numpy.ma.masked_greater(A, maxexp)
        A = numpy.ma.masked_less(A, minexp)
        es = es + f * (numpy.ma.power(10, A) - 1.)
        es = est * numpy.ma.power(10, es)
    elif method == 5:
        tempc = T - 273.15
        es = 611.2 * numpy.ma.exp(17.67 * tempc / (tempc + 243.5))
    return es
Example #2
0
def logLinearInterpolation(A,
                           P,
                           levels=[
                               100000, 92500, 85000, 70000, 60000, 50000,
                               40000, 30000, 25000, 20000, 15000, 10000, 7000,
                               5000, 3000, 2000, 1000
                           ],
                           status=None):
    """
    Log-linear interpolation
    to convert a field from sigma levels to pressure levels
    Value below surface are masked
    
    Input
    A :    array on sigma levels
    P :    pressure field from TOP (level 0) to BOTTOM (last level)
    levels : pressure levels to interplate to (same units as P), default levels are:[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000]

    P and levels must have same units

    Output
    array on pressure levels (levels)
    
    Examples:
    A=logLinearInterpolation(A,P),levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000])
    """

    try:
        nlev = len(levels)  # Number of pressure levels
    except:
        nlev = 1  # if only one level len(levels) would breaks
        levels = [
            levels,
        ]
    order = A.getOrder()
    A = A(order='z...')
    P = P(order='z...')
    sh = list(P.shape)
    nsigma = sh[0]  #number of sigma levels
    sh[0] = nlev
    t = MV2.zeros(sh, typecode=MV2.float32)
    sh2 = P[0].shape
    prev = -1
    for ilev in range(nlev):  # loop through pressure levels
        if status is not None:
            prev = genutil.statusbar(ilev, nlev - 1., prev)
        lev = levels[ilev]  # get value for the level
        Pabv = MV2.ones(sh2, MV2.float)
        Aabv = -1 * Pabv  # Array on sigma level Above
        Abel = -1 * Pabv  # Array on sigma level Below
        Pbel = -1 * Pabv  # Pressure on sigma level Below
        Pabv = -1 * Pabv  # Pressure on sigma level Above
        Peq = MV2.masked_equal(Pabv, -1)  # Area where Pressure == levels
        for i in range(1, nsigma):  # loop from second sigma level to last one
            a = MV2.greater_equal(
                P[i], lev)  # Where is the pressure greater than lev
            b = MV2.less_equal(P[i - 1],
                               lev)  # Where is the pressure less than lev
            # Now looks if the pressure level is in between the 2 sigma levels
            # If yes, sets Pabv, Pbel and Aabv, Abel
            a = MV2.logical_and(a, b)
            Pabv = MV2.where(a, P[i], Pabv)  # Pressure on sigma level Above
            Aabv = MV2.where(a, A[i], Aabv)  # Array on sigma level Above
            Pbel = MV2.where(a, P[i - 1],
                             Pbel)  # Pressure on sigma level Below
            Abel = MV2.where(a, A[i - 1], Abel)  # Array on sigma level Below
            Peq = MV2.where(MV2.equal(P[i], lev), A[i], Peq)

        val = MV2.masked_where(
            MV2.equal(Pbel, -1),
            numpy.ones(Pbel.shape) *
            lev)  # set to missing value if no data below lev if there is

        tl = MV2.log(val / Pbel) / MV2.log(
            Pabv / Pbel) * (Aabv - Abel) + Abel  # Interpolation
        if ((Peq.mask is None) or (Peq.mask is MV2.nomask)):
            tl = Peq
        else:
            tl = MV2.where(1 - Peq.mask, Peq, tl)
        t[ilev] = tl.astype(MV2.float32)

    ax = A.getAxisList()
    autobnds = cdms2.getAutoBounds()
    cdms2.setAutoBounds('off')
    lvl = cdms2.createAxis(MV2.array(levels).filled())
    cdms2.setAutoBounds(autobnds)
    try:
        lvl.units = P.units
    except:
        pass
    lvl.id = 'plev'

    try:
        t.units = P.units
    except:
        pass

    ax[0] = lvl
    t.setAxisList(ax)
    t.id = A.id
    for att in A.listattributes():
        setattr(t, att, getattr(A, att))
    return t(order=order)
Example #3
0
def logLinearInterpolation(A,P,levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000],status=None):
    """
    Log-linear interpolation
    to convert a field from sigma levels to pressure levels
    Value below surface are masked
    
    Input
    A :    array on sigma levels
    P :    pressure field from TOP (level 0) to BOTTOM (last level)
    levels : pressure levels to interplate to (same units as P), default levels are:[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000]

    P and levels must have same units

    Output
    array on pressure levels (levels)
    
    Examples:
    A=logLinearInterpolation(A,P),levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000])
    """
    
    try:
        nlev=len(levels)  # Number of pressure levels
    except:
        nlev=1  # if only one level len(levels) would breaks
        levels=[levels,]
    order=A.getOrder()
    A=A(order='z...')
    P=P(order='z...')
    sh=list(P.shape)
    nsigma=sh[0] #number of sigma levels
    sh[0]=nlev
    t=MV2.zeros(sh,typecode=MV2.float32)
    sh2=P[0].shape
    prev=-1
    for ilev in range(nlev): # loop through pressure levels
        if status is not None:
            prev=genutil.statusbar(ilev,nlev-1.,prev)
        lev=levels[ilev] # get value for the level
        Pabv=MV2.ones(sh2,MV2.float)
        Aabv=-1*Pabv # Array on sigma level Above
        Abel=-1*Pabv # Array on sigma level Below
        Pbel=-1*Pabv # Pressure on sigma level Below
        Pabv=-1*Pabv # Pressure on sigma level Above
        Peq=MV2.masked_equal(Pabv,-1) # Area where Pressure == levels
        for i in range(1,nsigma): # loop from second sigma level to last one
            a=MV2.greater_equal(P[i],  lev) # Where is the pressure greater than lev
            b=   MV2.less_equal(P[i-1],lev) # Where is the pressure less than lev
            # Now looks if the pressure level is in between the 2 sigma levels
            # If yes, sets Pabv, Pbel and Aabv, Abel
            a=MV2.logical_and(a,b)
            Pabv=MV2.where(a,P[i],Pabv) # Pressure on sigma level Above
            Aabv=MV2.where(a,A[i],Aabv) # Array on sigma level Above
            Pbel=MV2.where(a,P[i-1],Pbel) # Pressure on sigma level Below
            Abel=MV2.where(a,A[i-1],Abel) # Array on sigma level Below
            Peq= MV2.where(MV2.equal(P[i],lev),A[i],Peq)

        val=MV2.masked_where(MV2.equal(Pbel,-1),numpy.ones(Pbel.shape)*lev) # set to missing value if no data below lev if there is
        
        tl=MV2.log(val/Pbel)/MV2.log(Pabv/Pbel)*(Aabv-Abel)+Abel # Interpolation
        if ((Peq.mask is None) or (Peq.mask is MV2.nomask)):
            tl=Peq
        else:
            tl=MV2.where(1-Peq.mask,Peq,tl)
        t[ilev]=tl.astype(MV2.float32)
        
    ax=A.getAxisList()
    autobnds=cdms2.getAutoBounds()
    cdms2.setAutoBounds('off')
    lvl=cdms2.createAxis(MV2.array(levels).filled())
    cdms2.setAutoBounds(autobnds)
    try:
        lvl.units=P.units
    except:
        pass
    lvl.id='plev'
    
    try:
      t.units=P.units
    except:
      pass
  
    ax[0]=lvl
    t.setAxisList(ax)
    t.id=A.id
    for att in A.listattributes():
        setattr(t,att,getattr(A,att))
    return t(order=order)
Example #4
0
def Es(T, method=None):
    """Computes saturated pressure in Pa given T in K, using the method:
    1: Hyland-Wexler formulation, polynomial coeff (absolute norm)
    2: Wexler formulation
    3: Hyland-Wexler formulation, polynomial coeff (relative error norm)
    4: classic Goff Gratch equation
    5: 6.112*numpy.ma.exp(17.67*tempc/(tempc+243.5))

    Default is method 1

    Note: 1 and 2 use method 3 where T is not : 173.15 < T < 473.15
    ref for 1, 2 and 3:
    Piotr Flatau and al., Journal of Applied Met., Vol 31, Dec 1992
    ( http://ams.allenpress.com/perlserv/?request=get-document&\
doi=10.1175%2F1520-0450(1992)031%3C1507%3APFTSVP%3E2.0.CO%3B2&ct=1 )
    """
    if method is None:
        method = 1

    if method == 1:
        # Put in C
        x = T - 273.15
        # Water vapor
        c0 = 0.611220713e03
        c1 = 0.443944344e02
        c2 = 0.143195336e01
        c3 = 0.263350515e-01
        c4 = 0.310636053e-03
        c5 = 0.185218710e-05
        c6 = 0.103440324e-07
        c7 = -0.468258100e-10
        c8 = 0.466533033e-13
        eswat = c0 + x * (c1 + x * (c2 + x * (c3 + x * (c4 + x * (c5 + x * (c6 + x * (c7 + x * c8)))))))
        # ice
        c0 = 0.611153246e03
        c1 = 0.503261230e02
        c2 = 0.188595709e01
        c3 = 0.422115970e-01
        c4 = 0.620376691e-03
        c5 = 0.616082536e-05
        c6 = 0.405172828e-07
        c7 = 0.161492905e-09
        c8 = 0.297886454e-12
        esice = c0 + x * (c1 + x * (c2 + x * (c3 + x * (c4 + x * (c5 + x * (c6 + x * (c7 + x * c8)))))))
        # Combine
        es = MV2.where(MV2.less(T, 273.15), esice, eswat)
        # Overwrite values outside valid range with method 2
        mn, mx = genutil.minmax(T)
        if mn < 173.16 or mx > 473.15:
            es2 = Es(T, method=2)
            es = MV2.where(MV2.less(T, 173.16), es2, es)
            es = MV2.where(MV2.greater(T, 473.15), es2, es)
    elif method == 2:
        # over water
        g0 = -0.29912729e4
        g1 = -0.60170128e4
        g2 = 0.1887643854e2
        g3 = -0.28354721e-1
        g4 = 0.17838301e-4
        g5 = -0.84150417e-9
        g6 = 0.44412543e-12
        g7 = 0.2858487e1
        # over ice
        k0 = -0.58653696e4
        k1 = 0.2224103300e2
        k2 = 0.13749042e-1
        k3 = -0.34031775e-4
        k4 = 0.26967687e-7
        k5 = 0.6918651
        esice = (k0 + (k1 + k5 * MV2.log(T) + (k2 + (k3 + k4 * T) * T) * T) * T) / T  # over ice
        eswat = (
            g0 + (g1 + (g2 + g7 * MV2.log(T) + (g3 + (g4 + (g5 + g6 * T) * T) * T) * T) * T) * T
        ) / T ** 2  # over water
        es = MV2.where(MV2.less(T, 273.15), esice, eswat)
        es = MV2.exp(es)
    elif method == 3:
        # Put in C
        x = T - 273.15
        # Water vapor
        c0 = 0.611213476e03
        c1 = 0.444007856e02
        c2 = 0.143064234e01
        c3 = 0.264461437e-01
        c4 = 0.305930558e-03
        c5 = 0.196237241e-05
        c6 = 0.892344772e-08
        c7 = -0.373208410e-10
        c8 = 0.209339997e-13
        eswat = c0 + x * (c1 + x * (c2 + x * (c3 + x * (c4 + x * (c5 + x * (c6 + x * (c7 + x * c8)))))))
        # ice
        c0 = 0.611123516e03
        c1 = 0.503109514e02
        c2 = 0.1888369801e01
        c3 = 0.420547422e-01
        c4 = 0.614396778e-03
        c5 = 0.602780717e-05
        c6 = 0.387940929e-07
        c7 = 0.149436277e-09
        c8 = 0.262655803e-12
        esice = c0 + x * (c1 + x * (c2 + x * (c3 + x * (c4 + x * (c5 + x * (c6 + x * (c7 + x * c8)))))))
        # Combine
        es = MV2.where(MV2.less(T, 273.15), esice, eswat)
        # Overwrite values outside valid range with method 2
        mn, mx = genutil.minmax(T)
        if mn < 173.16 or mx > 473.15:
            es2 = Es(T, method=2)
            es = MV2.where(MV2.less(T, 173.16), es2, es)
            es = MV2.where(MV2.greater(T, 473.15), es2, es)
    elif method == 4:
        est = 101324.6  # Pa
        Ts = 373.16 / T
        a = -7.90298
        b = 5.02808
        c = -1.3816e-7
        d = 11.344
        f = 8.1328e-3
        h = -3.49149
        maxexp = int(numpy.log10(numpy.finfo(numpy.float).max))
        minexp = 1 - a
        es = a * (Ts - 1.0)
        es = es + b * numpy.ma.log10(Ts)
        A = d * (1.0 - Ts)
        A = numpy.ma.masked_greater(A, maxexp)
        A = numpy.ma.masked_less(A, minexp)
        es = es + c * (numpy.ma.power(10, A) - 1.0)
        A = h * (Ts - 1.0)
        A = numpy.ma.masked_greater(A, maxexp)
        A = numpy.ma.masked_less(A, minexp)
        es = es + f * (numpy.ma.power(10, A) - 1.0)
        es = est * numpy.ma.power(10, es)
    elif method == 5:
        tempc = T - 273.15
        es = 611.2 * numpy.ma.exp(17.67 * tempc / (tempc + 243.5))
    return es