diff --git a/AirSeaFluxCode.py b/AirSeaFluxCode.py index 8d6b89347c4233f84fad9be47285f550dc422c82..d1af461cd5bb8a1320e93db41c1a54b4992a1dec 100644 --- a/AirSeaFluxCode.py +++ b/AirSeaFluxCode.py @@ -1,7 +1,6 @@ import numpy as np import sys import logging -#import metpy.constants as mpcon from flux_subs import (kappa, CtoK, get_heights, cdn_calc, cd_calc, get_skin, psim_calc, psit_calc, ctcq_calc, ctcqn_calc, get_gust, gc, q_calc, qsea_calc, qsat26sea, qsat26air, @@ -40,8 +39,8 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, downward longwave radiation (W/m^2) Rs : float downward shortwave radiation (W/m^2) - jcool : bool - 0 if sst is true ocean skin temperature called in COARE + jcool : int + 0 if sst is true ocean skin temperature called in COARE, else 1 n : int number of iterations @@ -124,12 +123,12 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, meth == "C40")): lat=45*np.ones(np.shape(spd)) #### - th = np.where(np.nanmax(T) < 200, (np.copy(T)+CtoK) * + th = np.where(T < 200, (np.copy(T)+CtoK) * np.power(1000/P,287.1/1004.67), np.copy(T)*np.power(1000/P,287.1/1004.67)) # potential T - Ta = np.where(np.nanmax(T) < 200, np.copy(T)+CtoK+tlapse*hh_in[1], + Ta = np.where(T < 200, np.copy(T)+CtoK+tlapse*hh_in[1], np.copy(T)+tlapse*hh_in[1]) # convert to Kelvin if needed - sst = np.where(np.nanmax(SST) < 200, np.copy(SST)+CtoK, np.copy(SST)) + sst = np.where(SST < 200, np.copy(SST)+CtoK, np.copy(SST)) if (meth == "C30" or meth == "C35" or meth == "C40" or meth == "UA" or meth == "ERA5"): qsea = qsat26sea(sst, P)/1000 # surface water specific humidity (g/kg) @@ -161,12 +160,11 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, tv=th*(1.+0.61*qair) # virtual potential T dtv=dt*(1.+0.61*qair)+0.61*th*dq # ------------ -# rho = P*100/(287.1*tv10n) - rho = P*100/(287.1*(T+CtoK)*(1+0.61*qair)) - # rho=P*100/(287.1*sst*(1+0.61*qsea)) # Zeng et al. 1998 + rho = P*100/(287.1*tv10n) +# rho=P*100/(287.1*sst*(1+0.61*qsea)) # Zeng et al. 1998 lv = (2.501-0.00237*SST)*1e6 cp = 1004.67*(1 + 0.00084*qsea) -# cp = 1004.67 # Zeng et al. 1998, C3.0, C3.5 +# cp = 1004.67*np.ones(Ta.shape) # Zeng et al. 1998, C3.0, C3.5 u10n = np.copy(spd) monob = -100*np.ones(u10n.shape) # Monin-Obukhov length cdn = cdn_calc(u10n, Ta, None, lat, meth) @@ -175,9 +173,14 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, cd = cd_calc(cdn, hh_in[0], ref_ht, psim) tsr, tsrv = np.zeros(u10n.shape), np.zeros(u10n.shape) qsr = np.zeros(u10n.shape) + # if jcool == 1: + tkt = 0.001*np.ones(T.shape) + Rnl = 0.97*(5.67e-8*np.power(sst-0.3*jcool+CtoK, 4)-Rl) + dter = np.ones(T.shape)*0.3 + dqer = dter*0.622*lv*qsea/(287.1*np.power(sst, 2)) if (meth == "UA"): - wind = np.where(dtv >= 0,np.where(spd > 0.1, spd, 0.1), - np.sqrt(np.power(np.copy(spd),2)+np.power(0.5,2))) + wind = np.where(dtv >= 0, np.where(spd > 0.1, spd, 0.1), + np.sqrt(np.power(np.copy(spd), 2)+np.power(0.5, 2))) usr = 0.06 for i in range(5): zo = 0.013*np.power(usr,2)/g+0.11*visc_air(Ta)/usr @@ -190,7 +193,7 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, zo = 0.013*np.power(usr, 2)/g + 0.11*visc_air(Ta)/usr zot = zo/np.exp(2.67*np.power(usr*zo/visc_air(Ta), 0.25)-2.57) zoq = zot - logging.info('method %s | wind:%s, usr:%s,' + logging.info('method %s | wind:%s, usr:%s, ' 'zo:%s, zot:%s, zoq:%s, Rb:%s, monob:%s', meth, np.ma.median(wind[~np.isnan(wind)]), np.ma.median(usr[~np.isnan(usr)]), @@ -201,7 +204,7 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, np.ma.median(monob[~np.isnan(monob)])) elif (meth == "ERA5"): wind = np.sqrt(np.power(np.copy(spd), 2)+np.power(0.5, 2)) - usr = np.sqrt(cd*wind**2) + usr = np.sqrt(cd*np.power(wind, 2)) Rb = ((g*hh_in[0]*((2*dt)/(Ta+sst-g*hh_in[0]) + 0.61*dq))/np.power(wind, 2)) zo = 0.11*visc_air(Ta)/usr+0.018*np.power(usr, 2)/g @@ -212,8 +215,8 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, psit_calc((hh_in[0]+zo)/monob, meth) + psit_calc(zot/monob, meth)))) monob = hh_in[0]/zol - logging.info('method %s | wind:%s, usr:%s,' - 'zo:%s, zot:%s, zoq:%s, Rb:%s, monob:%s', meth, + logging.info('method %s | wind:%s, usr:%s, ' + 'zo:%s, zot:%s, Rb:%s, monob:%s', meth, np.ma.median(wind[~np.isnan(wind)]), np.ma.median(usr[~np.isnan(usr)]), np.ma.median(zo[~np.isnan(zo)]), @@ -222,14 +225,14 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, np.ma.median(monob[~np.isnan(monob)])) elif (meth == "C30" or meth == "C35" or meth == "C40"): wind = np.sqrt(np.power(np.copy(spd), 2)+np.power(0.5, 2)) - usr = 0.035*wind*np.log(10/1e-4)/np.log(hh_in[0]/1e-4) + usr = np.sqrt(cd*np.power(wind, 2)) a = 0.011*np.ones(T.shape) a = np.where(wind > 10, 0.011+(wind-10)/(18-10)*(0.018-0.011), np.where(wind > 18, 0.018, a)) zo = a*np.power(usr, 2)/g+0.11*visc_air(T)/usr rr = zo*usr/visc_air(T) zoq = np.minimum(5e-5/np.power(rr, 0.6), 1.15e-4) - zot=zoq + zot = zoq Rb = g*hh_in[0]*dtv/((T+CtoK)*np.power(wind, 2)) zol = (Rb*((np.log((hh_in[0]+zo)/zo)-psim_calc((hh_in[0]+zo) / monob, meth)+psim_calc(zo/monob, meth)) / @@ -237,12 +240,8 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, psit_calc((hh_in[0]+zo)/monob, meth) + psit_calc(zot/monob, meth)))) monob = hh_in[0]/zol -# wetc = 0.622*lv*qsea/(287.1*np.power(sst, 2)) - tkt = 0.001*np.ones(T.shape) - Rnl = 0.97*(5.67e-8*np.power(sst-0.3*jcool+CtoK, 4)-Rl) - dter, dqer = np.ones(T.shape)*0.3, np.zeros(T.shape)*np.nan - logging.info('method %s | wind:%s, usr:%s,' - 'zo:%s, zot:%s, zoq:%s, Rb:%s, monob:%s', meth, + logging.info('method %s | wind:%s, usr:%s, ' + 'zo:%s, zot:%s, Rb:%s, monob:%s', meth, np.ma.median(wind[~np.isnan(wind)]), np.ma.median(usr[~np.isnan(usr)]), np.ma.median(zo[~np.isnan(zo)]), @@ -252,27 +251,31 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, else: wind = np.copy(spd) zo, zot = 0.0001*np.ones(u10n.shape), 0.0001*np.ones(u10n.shape) - usr = np.sqrt(cd * wind**2) - logging.info('method %s | wind:%s, usr:%s,' - 'zo:%s, zot:%s, zoq:%s, Rb:%s, monob:%s', meth, + usr = np.sqrt(cd*np.power(wind, 2)) + logging.info('method %s | wind:%s, usr:%s, ' + 'zo:%s, zot:%s, Rb:%s, monob:%s', meth, np.ma.median(wind[~np.isnan(wind)]), np.ma.median(usr[~np.isnan(usr)]), np.ma.median(zo[~np.isnan(zo)]), np.ma.median(zot[~np.isnan(zot)]), np.ma.median(monob[~np.isnan(monob)])) + tsr = (dt+dter*jcool)*kappa/(np.log(hin[1]/zot) - + psit_calc(hh_in[1]/monob, meth)) + qsr = (dq+dqer*jcool)*kappa/(np.log(hin[2]/zot) - + psit_calc(hh_in[2]/monob, meth)) # tolerance for u,t,q,usr,tsr,qsr - tol = np.array([1e-06, 0.01, 5e-05, 1e-06, 0.001, 5e-07]) - it, ind, ii, itera = 0, np.where(spd > 0), True, np.zeros(spd.shape)*np.nan + tol = np.array([1e-06, 0.01, 5e-07, 1e-06, 0.001, 5e-07]) + it, ind = 0, np.where(spd > 0) + ii, itera = True, np.zeros(spd.shape)*np.nan while np.any(ii): it += 1 if it > n: break - old = np.array([np.copy(u10n[ind]), np.copy(t10n[ind]), - np.copy(q10n[ind]), np.copy(usr[ind]), - np.copy(tsr[ind]), np.copy(qsr[ind])]) + old = np.array([np.copy(u10n), np.copy(t10n), np.copy(q10n), + np.copy(usr), np.copy(tsr), np.copy(qsr)]) cdn[ind] = cdn_calc(u10n[ind], Ta[ind], None, lat[ind], meth) if (np.all(np.isnan(cdn))): - break # sys.exit("cdn cannot be nan") + break logging.info('break %s at iteration %s cdn<0', meth, it) zo[ind] = ref_ht/np.exp(kappa/np.sqrt(cdn[ind])) psim[ind] = psim_calc(hh_in[0]/monob[ind], meth) @@ -289,8 +292,8 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, (np.log(-1.574*monob[ind]/zo[ind]) - psim_calc(-1.574, meth) + psim_calc(zo[ind]/monob[ind], meth) + - 1.14*(np.power(-hh_in[0]/monob[ind],1/3) - - np.power(1.574,1/3))), + 1.14*(np.power(-hh_in[0]/monob[ind], 1/3) - + np.power(1.574, 1/3))), np.where((hh_in[0]/monob[ind] > -1.574) & (hh_in[0]/monob[ind] < 0), kappa*wind[ind]/(np.log(hh_in[0]/zo[ind]) - @@ -305,54 +308,55 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, 5*np.log(hh_in[0]/monob[ind]) + hh_in[0]/monob[ind]-1)))) # Zeng et al. 1998 (7-10) - tsr[ind] = np.where(hh_in[1]/monob[ind] < -0.465, kappa*dt[ind] / + tsr[ind] = np.where(hh_in[1]/monob[ind] < -0.465, kappa*(dt[ind] + + dter[ind]*jcool) / (np.log((-0.465*monob[ind])/zot[ind]) - psit_calc(-0.465, meth)+0.8 * - (np.power(0.465,-1/3) - - np.power(-hh_in[1]/monob[ind],-1/3))), - np.where((hh_in[1]/monob[ind]>-0.465) & - (hh_in[1]/monob[ind]<0), - kappa*dt[ind]/(np.log(hh_in[1]/zot[ind]) - + (np.power(0.465, -1/3) - + np.power(-hh_in[1]/monob[ind], -1/3))), + np.where((hh_in[1]/monob[ind] > -0.465) & + (hh_in[1]/monob[ind] < 0), + kappa*(dt[ind]+dter[ind]*jcool) / + (np.log(hh_in[1]/zot[ind]) - psit_calc(hh_in[1]/monob[ind], meth) + psit_calc(zot[ind]/monob[ind], meth)), - np.where((hh_in[1]/monob[ind]>0) & - (hh_in[1]/monob[ind]<1), - kappa*dt[ind]/(np.log(hh_in[1]/zot[ind]) + + np.where((hh_in[1]/monob[ind] > 0) & + (hh_in[1]/monob[ind] < 1), + kappa*(dt[ind]+dter[ind]*jcool) / + (np.log(hh_in[1]/zot[ind]) + 5*hh_in[1]/monob[ind]-5*zot[ind]/monob[ind]), - kappa*dt[ind]/(np.log(monob[ind]/zot[ind])+5 - - 5**zot[ind]/monob[ind] + + kappa*(dt[ind]+dter[ind]*jcool) / + (np.log(monob[ind]/zot[ind])+5 - + 5*zot[ind]/monob[ind] + 5*np.log(hh_in[1]/monob[ind]) + hh_in[1]/monob[ind]-1)))) # Zeng et al. 1998 (11-14) - qsr[ind] = np.where(hh_in[2]/monob[ind] < -0.465, kappa*dq[ind] / + qsr[ind] = np.where(hh_in[2]/monob[ind] < -0.465, kappa*(dq[ind] + + dqer[ind]*jcool) / (np.log((-0.465*monob[ind])/zoq[ind]) - psit_calc(-0.465, meth) + psit_calc(zoq[ind]/monob[ind], meth) + - 0.8*(np.power(0.465,-1/3) - - np.power(-hh_in[2]/monob[ind],-1/3))), - np.where((hh_in[2]/monob[ind]>-0.465) & - (hh_in[2]/monob[ind]<0), - kappa*dq[ind]/(np.log(hh_in[1]/zot[ind]) - + 0.8*(np.power(0.465, -1/3) - + np.power(-hh_in[2]/monob[ind], -1/3))), + np.where((hh_in[2]/monob[ind] > -0.465) & + (hh_in[2]/monob[ind] < 0), + kappa*(dq[ind]+dqer[ind]*jcool) / + (np.log(hh_in[1]/zot[ind]) - psit_calc(hh_in[2]/monob[ind], meth) + psit_calc(zoq[ind]/monob[ind], meth)), - np.where((hh_in[2]/monob[ind]>0) & - (hh_in[2]/monob[ind]<1), kappa*dq[ind] / + np.where((hh_in[2]/monob[ind] > 0) & + (hh_in[2]/monob[ind]<1), kappa*(dq[ind] + + dqer[ind]*jcool) / (np.log(hh_in[1]/zoq[ind]) + 5*hh_in[2]/monob[ind]-5*zoq[ind]/monob[ind]), - kappa*dq[ind]/(np.log(monob[ind]/zoq[ind])+5 - + kappa*(dq[ind]+dqer[ind]*jcool) / + (np.log(monob[ind]/zoq[ind])+5 - 5*zoq[ind]/monob[ind] + 5*np.log(hh_in[2]/monob[ind]) + hh_in[2]/monob[ind]-1)))) elif (meth == "C30" or meth == "C35" or meth == "C40"): usr[ind] = (wind[ind]*kappa/(np.log(hh_in[0]/zo[ind]) - psiu_26(hh_in[0]/monob[ind], meth))) - dter[ind], dqer[ind], tkt[ind] = get_skin(sst[ind], qsea[ind], - rho[ind], Rl[ind], - Rs[ind], Rnl[ind], - cp[ind], lv[ind], - np.copy(tkt[ind]), - usr[ind], tsr[ind], - qsr[ind], lat[ind]) logging.info('method %s | dter = %s | Rnl = %s ' '| usr = %s | tsr = %s | qsr = %s', meth, np.ma.median(dter[~np.isnan(dter)]), @@ -364,16 +368,24 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, (np.log(hin[2]/zoq[ind])-psit_26(hin[2]/monob[ind])))) tsr[ind] = ((dt[ind]+dter[ind]*jcool)*(kappa / (np.log(hin[1]/zot[ind])-psit_26(hin[1]/monob[ind])))) - Rnl[ind] = 0.97*(5.67e-8*np.power(SST[ind] - - dter[ind]*jcool+CtoK, 4)-Rl[ind]) else: - usr[ind] = np.sqrt(cd[ind]*wind[ind]**2) - tsr[ind] = ct[ind]*wind[ind]*dt[ind]/usr[ind] - qsr[ind] = cq[ind]*wind[ind]*dq[ind]/usr[ind] - fact = (np.log(hh_in[1]/ref_ht)-psit[ind])/kappa - t10n[ind] = Ta[ind] - (tsr[ind]*fact) - fact = (np.log(hh_in[2]/ref_ht)-psiq[ind])/kappa - q10n[ind] = qair[ind] - (qsr[ind]*fact) + usr[ind] = (wind[ind]*kappa/(np.log(hh_in[0]/zo[ind]) - + psim_calc(hh_in[0]/monob[ind], meth)))#np.sqrt(cd[ind]*wind[ind]**2) + tsr[ind] = ct[ind]*wind[ind]*(dt[ind]+dter[ind]*jcool)/usr[ind] + qsr[ind] = cq[ind]*wind[ind]*(dq[ind]+dqer[ind]*jcool)/usr[ind] + dter[ind], dqer[ind], tkt[ind] = get_skin(sst[ind], qsea[ind], + rho[ind], Rl[ind], + Rs[ind], Rnl[ind], + cp[ind], lv[ind], + np.copy(tkt[ind]), + usr[ind], tsr[ind], + qsr[ind], lat[ind]) + Rnl[ind] = 0.97*(5.67e-8*np.power(SST[ind] - + dter[ind]*jcool+CtoK, 4)-Rl[ind]) + t10n[ind] = (Ta[ind] - + (tsr[ind]*(np.log(hh_in[1]/ref_ht)-psit[ind])/kappa)) + q10n[ind] = (qair[ind] - + (qsr[ind]*(np.log(hh_in[2]/ref_ht)-psiq[ind])/kappa)) tv10n[ind] = t10n[ind]*(1+0.61*q10n[ind]) if (meth == "UA"): tsrv[ind] = tsr[ind]*(1.+0.61*qair[ind])+0.61*th[ind]*qsr[ind] @@ -407,7 +419,7 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, wind[ind] = np.where(dtv[ind] >= 0, np.where(spd[ind] > 0.1, spd[ind], 0.1), np.sqrt(np.power(np.copy(spd[ind]), 2) + - np.power(get_gust(1,tv[ind], usr[ind], + np.power(get_gust(1, tv[ind], usr[ind], tsrv[ind], zi, lat[ind]), 2))) # Zeng et al. 1998 (20) u10n[ind] = (wind[ind]-(usr[ind]/kappa)*(np.log(hh_in[0]/10) - @@ -434,29 +446,36 @@ def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, u10n[ind] = (wind[ind]-(usr[ind]/kappa)*(np.log(hh_in[0]/10) - psim[ind])) u10n[u10n < 0] = np.nan - new = np.array([np.copy(u10n[ind]), np.copy(t10n[ind]), - np.copy(q10n[ind]), np.copy(usr[ind]), - np.copy(tsr[ind]), np.copy(qsr[ind])]) - d = np.abs(new-old) - ind = np.where((d[0, :] > tol[0])+(d[1, :] > tol[1]) + - (d[2, :] > tol[2])+(d[3, :] > tol[3]) + - (d[4, :] > tol[4])+(d[5, :] > tol[5])) itera[ind] = np.ones(1)*it - if np.shape(ind)[0] == 0: - break + new = np.array([np.copy(u10n), np.copy(t10n), np.copy(q10n), + np.copy(usr), np.copy(tsr), np.copy(qsr)]) + d = np.abs(new-old) +# ind = np.where((d[0, :] > tol[0])+(d[1, :] > tol[1]) + +# (d[2, :] > tol[2])+(d[3, :] > tol[3]) + +# (d[4, :] > tol[4])+(d[5, :] > tol[5])) + if (ind[0].size == 0): + ii = False else: - ii = ((d[0, ind] > tol[0])+(d[1, ind] > tol[1]) + - (d[2, ind] > tol[2])+(d[3, ind] > tol[3]) + - (d[4, ind] > tol[4])+(d[5, ind] > tol[5])) - logging.info('method %s | # of iterations:%s', meth, np.ma.median(it)) + ii = True + if ((it == 3) or (it == 6) or (it == 10)): + print('Method {}, # {} tol u10n: {} | t10n: {} | q10n: {} | ' + 'u*: {} | t*: {} | q*: {}'.format(meth, it, + np.ma.max(d[0, ~np.isnan(d[0,:])]), + np.ma.max(d[1, ~np.isnan(d[1,:])]), + np.ma.max(d[2, ~np.isnan(d[2,:])]), + np.ma.max(d[3, ~np.isnan(d[3,:])]), + np.ma.max(d[4, ~np.isnan(d[4,:])]), + np.ma.max(d[5, ~np.isnan(d[5,:])])), + file=open('tol_mid.txt','a')) + logging.info('method %s | # of iterations:%s', meth, it) logging.info('method %s | # of points that did not converge :%s', meth, - np.shape(ind)) + ind[0].size) # calculate output parameters -# rho = (0.34838*P)/(tv10n) - rho = P*100./(287.1*(T+CtoK)*(1+0.61*qair)) # C35 + rho = (0.34838*P)/(tv10n) +# rho = P*100./(287.1*(T+CtoK)*(1+0.61*qair)) # C35 t10n = t10n-(273.16+tlapse*ref_ht) - sensible = -1*tsr*usr*cp*rho - latent = -1*qsr*usr*lv*rho + sensible = -rho*cp*usr*tsr + latent = -rho*lv*usr*qsr if (meth == "C30" or meth == "C35" or meth == "C40" or meth == "UA" or meth == "ERA5"): tau = rho*np.power(usr, 2)*(spd/wind) diff --git a/flux_subs.py b/flux_subs.py index e59dd282a35056df45fcd4c033a3d356781c6394..566259ce481297678510d8f9f2ed19af689e58c5 100755 --- a/flux_subs.py +++ b/flux_subs.py @@ -75,11 +75,11 @@ def cdn_from_roughness(u10n, Ta, Tp, lat, meth="S88"): cdn = np.copy(cdnn) usr = np.sqrt(cdn*u10n**2) if (meth == "S88"): - # .....Charnock roughness length (equn 4 in Smith 88) + # Charnock roughness length (eq. 4 in Smith 88) zc = 0.011*np.power(usr, 2)/g - # .....smooth surface roughness length (equn 6 in Smith 88) + # smooth surface roughness length (eq. 6 in Smith 88) zs = 0.11*visc_air(Ta)/usr - zo = zc + zs # .....equns 7 & 8 in Smith 88 to calculate new CDN + zo = zc + zs # eq. 7 & 8 in Smith 88 elif (meth == "UA"): # valid for 0<u<18m/s # Zeng et al. 1998 (24) zo = 0.013*np.power(usr, 2)/g+0.11*visc_air(Ta)/usr @@ -90,11 +90,10 @@ def cdn_from_roughness(u10n, Ta, Tp, lat, meth="S88"): zo = a*np.power(usr, 2)/g+0.11*visc_air(Ta)/usr elif (meth == "C35"): a = 0.011*np.ones(Ta.shape) - a = np.where(u10n > 18, 0.0017*19-0.0050, - np.where((u10n > 7) & (u10n <= 18), - 0.0017*u10n-0.0050, a)) -# charn = np.where(wind > 10, 0.011+(wind-10)/(18-10)*(0.018-0.011), -# np.where(wind > 18, 0.018, 0.011*np.ones(np.shape(wind)))) +# a = np.where(u10n > 19, 0.0017*19-0.0050, +# np.where((u10n > 7) & (u10n <= 18), +# 0.0017*u10n-0.0050, a)) + a = np.where(u10n > 19, 0.0017*19-0.0050, 0.0017*u10n-0.0050) zo = 0.11*visc_air(Ta)/usr+a*np.power(usr, 2)/g elif (meth == "C40"): a = 0.011*np.ones(Ta.shape) @@ -140,7 +139,7 @@ def ctcqn_calc(zol, cdn, u10n, zo, Ta, meth="S80"): ctn = np.ones(Ta.shape)*1.00*0.001 elif (meth == "LP82"): cqn = np.where((zol <= 0) & (u10n > 4) & (u10n < 14), 1.15*0.001, - np.nan) + 1*0.001) ctn = np.where((zol <= 0) & (u10n > 4) & (u10n < 25), 1.13*0.001, 0.66*0.001) elif (meth == "LY04"): @@ -377,13 +376,13 @@ def psit_26(zol): b, d = 2/3, 0.35 dzol = np.where(d*zol > 50, 50, d*zol) # stable psi = -((1+b*zol)**1.5+b*(zol-14.28)*np.exp(-dzol)+8.525) - psi = np.where(zol < 0, (1-(np.power(zol, 2)/(1+np.power(zol, 2))))*2 * - np.log((1+np.sqrt(1-15*zol))/2)+(np.power(zol, 2) / - (1+np.power(zol, 2))) * - (1.5*np.log((1+np.power(1-34.15*zol, 1/3) + - np.power(1-34.15*zol, 2/3))/3) - - np.sqrt(3)*np.arctan((1+2*np.power(1-34.15*zol, 1/3)) / - np.sqrt(3))+4*np.arctan(1)/np.sqrt(3)), psi) + psik = 2*np.log((1+np.sqrt(1-15*zol))/2) + psic = (1.5*np.log((1+np.power(1-34.15*zol, 1/3) + + np.power(1-34.15*zol, 2/3))/3)-np.sqrt(3) * + np.arctan(1+2*np.power(1-34.15*zol, 1/3))/np.sqrt(3) + + 4*np.arctan(1)/np.sqrt(3)) + f = np.power(zol, 2)/(1+np.power(zol, 2)) + psi = np.where(zol < 0, (1-f)*psik+f*psic, psi) return psi # --------------------------------------------------------------------- @@ -646,7 +645,7 @@ def get_gust(beta, Ta, usr, tsrv, zi, lat): ------- ug : float """ - if (np.max(Ta) < 200): # convert to K if in Celsius + if (np.nanmax(Ta) < 200): # convert to K if in Celsius Ta = Ta+273.16 g = gc(lat, None) Bf = (-g/Ta)*usr*tsrv