import numpy as np import sys import logging 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, visc_air, psit_26, psiu_26) def AirSeaFluxCode(spd, T, SST, lat, RH, P, hin, hout, zi=600, Rl=None, Rs=None, jcool=1, meth="S88", n=10): """ Calculates momentum and heat fluxes using different parameterizations Parameters ---------- meth : str "S80","S88","LP82","YT96","UA","LY04","C30","C35","C40","ERA5" spd : float relative wind speed in m/s (is assumed as magnitude difference between wind and surface current vectors) T : float air temperature in K (will convert if < 200) SST : float sea surface temperature in K (will convert if < 200) lat : float latitude (deg) RH : float relative humidity in % P : float air pressure hin : float sensor heights in m (array of 1->3 values: 1 -> u=t=q; / 2 -> u,t=q; 3 -> u,t,q ) default 10m hout : float output height, default is 10m zi : int PBL height (m) called in C35 Rl : float downward longwave radiation (W/m^2) Rs : float downward shortwave radiation (W/m^2) jcool : int 0 if sst is true ocean skin temperature called in COARE, else 1 n : int number of iterations Returns ------- res : array that contains 1. momentum flux (W/m^2) 2. sensible heat (W/m^2) 3. latent heat (W/m^2) 4. Monin-Obhukov length (mb) 5. drag coefficient (cd) 6. neutral drag coefficient (cdn) 7. heat exhange coefficient (ct) 8. neutral heat exhange coefficient (ctn) 9. moisture exhange coefficient (cq) 10. neutral moisture exhange coefficient (cqn) 11. star virtual temperature (tsrv) 12. star temperature (tsr) 13. star humidity (qsr) 14. star velocity (usr) 15. momentum stability function (psim) 16. heat stability funciton (psit) 17. 10m neutral velocity (u10n) 18. 10m neutral temperature (t10n) 19. 10m neutral virtual temperature (tv10n) 20. 10m neutral specific humidity (q10n) 21. surface roughness length (zo) 22. heat roughness length (zot) 23. moisture roughness length (zoq) 24. velocity at reference height (urefs) 25. temperature at reference height (trefs) 26. specific humidity at reference height (qrefs) 27. number of iterations until convergence ind : int the indices in the matrix for the points that did not converge after the maximum number of iterations The code is based on bform.f and flux_calc.R modified by S. Biri """ logging.basicConfig(filename='flux_calc.log', format='%(asctime)s %(message)s',level=logging.INFO) ref_ht, tlapse = 10, 0.0098 # reference height, lapse rate hh_in = get_heights(hin) # heights of input measurements/fields hh_out = get_heights(hout) # desired height of output variables if np.all(np.isnan(lat)): # set latitude to 45deg if empty lat=45*np.ones(spd.shape) g = gc(lat, None) # acceleration due to gravity ctn, ct, cqn, cq = (np.zeros(spd.shape)*np.nan, np.zeros(spd.shape)*np.nan, np.zeros(spd.shape)*np.nan, np.zeros(spd.shape)*np.nan) # if input values are nan break if (np.all(np.isnan(spd)) or np.all(np.isnan(T)) or np.all(np.isnan(SST))): sys.exit("input wind, T or SST is empty") logging.debug('all input is nan') if (np.all(np.isnan(RH)) and meth == "C35"): RH = np.ones(spd.shape)*80 # if empty set to default for COARE3.5 elif (np.all(np.isnan(RH))): sys.exit("input RH is empty") logging.debug('input RH is empty') if (np.all(np.isnan(P)) and (meth == "C30" or meth == "C40")): P = np.ones(spd.shape)*1015 # if empty set to default for COARE3.0 elif ((np.all(np.isnan(P))) and meth == "C35"): P = np.ones(spd.shape)*1013 # if empty set to default for COARE3.5 elif (np.all(np.isnan(P))): sys.exit("input P is empty") logging.debug('input P is empty') if (np.all(np.isnan(Rl)) and meth == "C30"): Rl = np.ones(spd.shape)*150 # set to default for COARE3.0 elif ((np.all(np.isnan(Rl)) and meth == "C35") or (np.all(np.isnan(Rl)) and meth == "C40")): Rl = np.ones(spd.shape)*370 # set to default for COARE3.5 if (np.all(np.isnan(Rs)) and meth == "C30"): Rs = np.ones(spd.shape)*370 # set to default for COARE3.0 elif ((np.all(np.isnan(Rs))) and (meth == "C35" or meth == "C40")): Rs = np.ones(spd.shape)*150 # set to default for COARE3.5 if ((np.all(np.isnan(zi))) and (meth == "C30" or meth == "C35" or meth == "C40")): zi = 600 # set to default for COARE3.5 elif ((np.all(np.isnan(zi))) and (meth == "ERA5" or meth == "UA")): zi = 1000 if (np.all(np.isnan(lat)) and (meth == "C30" or meth == "C35" or meth == "C40")): lat=45*np.ones(np.shape(spd)) #### 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(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(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) Q, _ = qsat26air(T, P, RH) # specific humidity of air (g/kg) qair = Q/1000 del Q logging.info('method %s | qsea:%s, qair:%s', meth, np.ma.median(qsea[~np.isnan(qsea)]), np.ma.median(qair[~np.isnan(qair)])) else: qsea = qsea_calc(sst, P) qair = q_calc(Ta, RH, P) logging.info('method %s | qsea:%s, qair:%s', meth, np.ma.median(qsea[~np.isnan(qsea)]), np.ma.median(qair[~np.isnan(qair)])) if (np.all(np.isnan(qsea)) or np.all(np.isnan(qair))): print("qsea and qair cannot be nan") logging.info('method %s qsea and qair cannot be nan | sst:%s, Ta:%s,' 'P:%s, RH:%s', meth, np.ma.median(sst[~np.isnan(sst)]), np.ma.median(Ta[~np.isnan(Ta)]), np.ma.median(P[~np.isnan(P)]), np.ma.median(RH[~np.isnan(RH)])) # first guesses dt = Ta - sst dq = qair - qsea t10n, q10n = np.copy(Ta), np.copy(qair) tv10n = t10n*(1 + 0.61*q10n) # Zeng et al. 1998 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*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*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) psim, psit, psiq = (np.zeros(u10n.shape), np.zeros(u10n.shape), np.zeros(u10n.shape)) 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))) usr = 0.06 for i in range(5): zo = 0.013*np.power(usr,2)/g+0.11*visc_air(Ta)/usr usr=kappa*wind/np.log(hh_in[0]/zo) Rb = g*hh_in[0]*dtv/(tv*wind**2) zol = np.where(Rb >= 0, Rb*np.log(hh_in[0]/zo) / (1-5*np.where(Rb < 0.19, Rb, 0.19)), Rb*np.log(hh_in[0]/zo)) monob = hh_in[0]/zol 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, ' '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)]), np.ma.median(zo[~np.isnan(zo)]), np.ma.median(zot[~np.isnan(zot)]), np.ma.median(zoq[~np.isnan(zoq)]), np.ma.median(Rb[~np.isnan(Rb)]), 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*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 zot = 0.40*visc_air(Ta)/usr zol = (Rb*((np.log((hh_in[0]+zo)/zo)-psim_calc((hh_in[0]+zo) / monob, meth)+psim_calc(zo/monob, meth)) / (np.log((hh_in[0]+zo)/zot) - 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, 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(Rb[~np.isnan(Rb)]), 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 = 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 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)) / (np.log((hh_in[0]+zo)/zot) - 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, 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(Rb[~np.isnan(Rb)]), np.ma.median(monob[~np.isnan(monob)])) else: wind = np.copy(spd) zo, zot = 0.0001*np.ones(u10n.shape), 0.0001*np.ones(u10n.shape) 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-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), 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 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) cd[ind] = cd_calc(cdn[ind], hh_in[0], ref_ht, psim[ind]) ctn[ind], cqn[ind] = ctcqn_calc(hh_in[1]/monob[ind], cdn[ind], u10n[ind], zo[ind], Ta[ind], meth) psit[ind] = psit_calc(hh_in[1]/monob[ind], meth) psiq[ind] = psit_calc(hh_in[2]/monob[ind], meth) ct[ind], cq[ind] = ctcq_calc(cdn[ind], cd[ind], ctn[ind], cqn[ind], hh_in[1], hh_in[2], ref_ht, psit[ind], psiq[ind]) if (meth == "UA"): usr[ind] = np.where(hh_in[0]/monob[ind] < -1.574, kappa*wind[ind] / (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))), 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]) - psim_calc(hh_in[0]/monob[ind], meth) + psim_calc(zo[ind]/monob[ind], meth)), np.where((hh_in[0]/monob[ind] > 0) & (hh_in[0]/monob[ind] < 1), kappa*wind[ind]/(np.log(hh_in[0]/zo[ind]) + 5*hh_in[0]/monob[ind]-5*zo[ind]/monob[ind]), kappa*wind[ind]/(np.log(monob[ind]/zo[ind]) + 5-5*zo[ind]/monob[ind] + 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] + 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]+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]+dter[ind]*jcool) / (np.log(hh_in[1]/zot[ind]) + 5*hh_in[1]/monob[ind]-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] + 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]+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] + dqer[ind]*jcool) / (np.log(hh_in[1]/zoq[ind]) + 5*hh_in[2]/monob[ind]-5*zoq[ind]/monob[ind]), 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))) logging.info('method %s | dter = %s | Rnl = %s ' '| usr = %s | tsr = %s | qsr = %s', meth, np.ma.median(dter[~np.isnan(dter)]), np.ma.median(Rnl[~np.isnan(Rnl)]), np.ma.median(usr[~np.isnan(usr)]), np.ma.median(tsr[~np.isnan(tsr)]), np.ma.median(qsr[~np.isnan(qsr)])) qsr[ind] = ((dq[ind]+dqer[ind]*jcool)*(kappa / (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])))) else: 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] monob[ind] = (tv[ind]*np.power(usr[ind], 2))/(kappa*g[ind]*tsrv[ind]) elif (meth == "C30" or meth == "C35" or meth == "C40"): tsrv[ind] = tsr[ind]+0.61*(T[ind]+CtoK)*qsr[ind] zol[ind] = (kappa*g[ind]*hh_in[0]/(T[ind]+CtoK)*(tsr[ind] + 0.61*(T[ind]+CtoK)*qsr[ind])/np.power(usr[ind], 2)) monob[ind] = hh_in[0]/zol[ind] elif (meth == "ERA5"): tsrv[ind] = tsr[ind]+0.61*t10n[ind]*qsr[ind] Rb[ind] = ((g[ind]*hh_in[0]*((2*dt[ind])/(Ta[ind]+sst[ind]-g[ind] * hh_in[0])+0.61*dq[ind]))/np.power(wind[ind], 2)) zo[ind] = (0.11*visc_air(Ta[ind])/usr[ind]+0.018 * np.power(usr[ind], 2)/g[ind]) zot[ind] = 0.40*visc_air(Ta[ind])/usr[ind] zol[ind] = (Rb[ind]*((np.log((hh_in[0]+zo[ind])/zo[ind]) - psim_calc((hh_in[0]+zo[ind])/monob[ind], meth) + psim_calc(zo[ind]/monob[ind], meth)) / (np.log((hh_in[0]+zo[ind])/zot[ind]) - psit_calc((hh_in[0]+zo[ind])/monob[ind], meth) + psit_calc(zot[ind]/monob[ind], meth)))) monob[ind] = hh_in[0]/zol[ind] else: tsrv[ind] = tsr[ind]+0.61*t10n[ind]*qsr[ind] monob[ind] = (tv10n[ind]*usr[ind]**2)/(g[ind]*kappa*tsrv[ind]) psim[ind] = psim_calc(hh_in[0]/monob[ind], meth) psit[ind] = psit_calc(hh_in[1]/monob[ind], meth) psiq[ind] = psit_calc(hh_in[2]/monob[ind], meth) if (meth == "UA"): 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], tsrv[ind], zi, lat[ind]), 2))) # Zeng et al. 1998 (20) u10n[ind] = (wind[ind]-(usr[ind]/kappa)*(np.log(hh_in[0]/10) - psim[ind])) u10n[u10n < 0] = np.nan elif (meth == "C30" or meth == "C35" or meth == "C40"): wind[ind] = np.sqrt(np.power(np.copy(spd[ind]), 2) + np.power(get_gust(1.2, Ta[ind], usr[ind], tsrv[ind], zi, lat[ind]), 2)) u10n[ind] = ((wind[ind] + usr[ind]/kappa*(np.log(10/hh_in[0])- psiu_26(10/monob[ind], meth) + psiu_26(hh_in[0]/monob[ind], meth)) + psiu_26(10/monob[ind], meth)*usr[ind]/kappa / (wind[ind]/spd[ind]))) u10n[u10n < 0] = np.nan elif (meth == "ERA5"): wind[ind] = np.sqrt(np.power(np.copy(spd[ind]), 2) + np.power(get_gust(1, Ta[ind], usr[ind], tsrv[ind], zi, lat[ind]), 2)) u10n[ind] = (spd[ind]+(usr[ind]/kappa)*(np.log(hh_in[0] / ref_ht)-psim[ind])) u10n[u10n < 0] = np.nan else: u10n[ind] = (wind[ind]-(usr[ind]/kappa)*(np.log(hh_in[0]/10) - psim[ind])) u10n[u10n < 0] = np.nan itera[ind] = np.ones(1)*it 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 = 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, ind[0].size) # calculate output parameters 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 = -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) else: tau = rho*np.power(usr, 2) zo = ref_ht/np.exp(kappa/cdn**0.5) zot = ref_ht/(np.exp(kappa**2/(ctn*np.log(ref_ht/zo)))) zoq = ref_ht/(np.exp(kappa**2/(cqn*np.log(ref_ht/zo)))) urefs = (spd-(usr/kappa)*(np.log(hh_in[0]/hh_out[0])-psim + psim_calc(hh_out[0]/monob, meth))) trefs = (Ta-(tsr/kappa)*(np.log(hh_in[1]/hh_out[1])-psit + psit_calc(hh_out[0]/monob, meth))) trefs = trefs-(273.16+tlapse*hh_out[1]) qrefs = (qair-(qsr/kappa)*(np.log(hh_in[2]/hh_out[2]) - psit+psit_calc(hh_out[2]/monob, meth))) res = np.zeros((27, len(spd))) res[0][:] = tau res[1][:] = sensible res[2][:] = latent res[3][:] = monob res[4][:] = cd res[5][:] = cdn res[6][:] = ct res[7][:] = ctn res[8][:] = cq res[9][:] = cqn res[10][:] = tsrv res[11][:] = tsr res[12][:] = qsr res[13][:] = usr res[14][:] = psim res[15][:] = psit res[16][:] = u10n res[17][:] = t10n res[18][:] = tv10n res[19][:] = q10n res[20][:] = zo res[21][:] = zot res[22][:] = zoq res[23][:] = urefs res[24][:] = trefs res[25][:] = qrefs res[26][:] = itera return res, ind