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