From 01d7c95dbf6e22d6f13e5b75b73604d02836a435 Mon Sep 17 00:00:00 2001
From: sbiri <sbiri@noc.ac.uk>
Date: Wed, 24 Mar 2021 15:11:32 +0000
Subject: [PATCH] LY04 updated to aerobulk's version

---
 AirSeaFluxCode.py | 24 +++++++++++++++++-------
 flux_subs.py      | 16 ++++++++++------
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/AirSeaFluxCode.py b/AirSeaFluxCode.py
index fae10df..e5d77a2 100644
--- a/AirSeaFluxCode.py
+++ b/AirSeaFluxCode.py
@@ -189,8 +189,6 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None, hin=18, hout=10,
     u10n = np.copy(spd)
     usr = 0.035*u10n
     cd10n = cdn_calc(u10n, usr, Ta, lat, meth)
-    ct10n, ct, cq10n, 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)
     psim, psit, psiq = (np.zeros(spd.shape), np.zeros(spd.shape),
                         np.zeros(spd.shape))
     cd = cd_calc(cd10n, h_in[0], ref_ht, psim)
@@ -214,8 +212,14 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None, hin=18, hout=10,
         wind = np.copy(spd)
     # stars and roughness lengths
     usr = np.sqrt(cd*np.power(wind, 2))
-    zo = 0.0001*np.ones(spd.shape)
-    zot, zoq = 0.0001*np.ones(spd.shape), 0.0001*np.ones(spd.shape)
+    zo = 1e-4*np.ones(spd.shape)
+    zot, zoq = 1e-4*np.ones(spd.shape), 1e-4*np.ones(spd.shape)
+    ct10n = np.power(kappa, 2)/(np.log(h_in[0]/zo)*np.log(h_in[1]/zot))
+    cq10n = np.power(kappa, 2)/(np.log(h_in[0]/zo)*np.log(h_in[2]/zoq))
+    ct = np.power(kappa, 2)/((np.log(h_in[0]/zo)-psim) *
+                             (np.log(h_in[1]/zot)-psit))
+    cq = np.power(kappa, 2)/((np.log(h_in[0]/zo)-psim) *
+                             (np.log(h_in[2]/zoq)-psiq))
     monob = -100*np.ones(spd.shape)  # Monin-Obukhov length
     tsr = (dt+dter*cskin-dtwl*wl)*kappa/(np.log(h_in[1]/zot) -
                                          psit_calc(h_in[1]/monob, meth))
@@ -223,7 +227,7 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None, hin=18, hout=10,
                                  psit_calc(h_in[2]/monob, meth))
     # set-up to feed into iteration loop
     it, ind = 0, np.where(spd > 0)
-    ii, itera = True, np.zeros(spd.shape)*np.nan
+    ii, itera = True, -1*np.ones(spd.shape)
     tau = 0.05*np.ones(spd.shape)
     sensible = 5*np.ones(spd.shape)
     latent = 65*np.ones(spd.shape)
@@ -258,6 +262,11 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None, hin=18, hout=10,
         ct[ind], cq[ind] = ctcq_calc(cd10n[ind], cd[ind], ct10n[ind], cq10n[ind],
                                       h_in[:, ind], [ref_ht, ref_ht, ref_ht],
                                       psit[ind], psiq[ind])
+        if (meth == "LY04"):
+            cd = np.maximum(np.copy(cd), 1e-4)
+            ct = np.maximum(np.copy(ct), 1e-4)
+            cq = np.maximum(np.copy(cq), 1e-4)
+            zo = np.minimum(np.copy(zo), 0.0025)
         usr[ind], tsr[ind], qsr[ind] = get_strs(h_in[:, ind], monob[ind],
                                                 wind[ind], zo[ind], zot[ind],
                                                 zoq[ind], dt[ind], dq[ind],
@@ -358,7 +367,7 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None, hin=18, hout=10,
                                   np.power(get_gust(gust[1], tv[ind], usr[ind],
                                   tsrv[ind], gust[2], lat[ind]), 2)))
                                   # Zeng et al. 1998 (20)
-        elif (gust[0] == 1 and (meth == "C30" or meth == "C35")): # or meth == "C40"
+        elif (gust[0] == 1 and (meth == "C30" or meth == "C35")):
             wind[ind] = np.sqrt(np.power(np.copy(spd[ind]), 2) +
                                 np.power(get_gust(gust[1], Ta[ind], usr[ind],
                                 tsrv[ind], gust[2], lat[ind]), 2))
@@ -370,6 +379,7 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None, hin=18, hout=10,
             wind[ind] = np.copy(spd[ind])
         u10n[ind] = wind[ind]-usr[ind]/kappa*(np.log(h_in[0, ind]/10) -
                                               psim[ind])
+        #  usr[ind]/np.sqrt(cd10n[ind])
         if (it < 4): # make sure you allow small negative values convergence
             u10n = np.where(u10n < 0, 0.5, u10n)
         flag = np.where((u10n < 0) & (flag == "n"), "u",
@@ -406,7 +416,7 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None, hin=18, hout=10,
         else:
             ii = True
     itera[ind] = -1
-    # itera = np.where(itera > n, -1, itera)
+    itera = np.where(itera > n, -1, itera)
     logging.info('method %s | # of iterations:%s', meth, it)
     logging.info('method %s | # of points that did not converge :%s \n', meth,
                   ind[0].size)
diff --git a/flux_subs.py b/flux_subs.py
index 454a0d4..6d71760 100755
--- a/flux_subs.py
+++ b/flux_subs.py
@@ -39,9 +39,12 @@ def cdn_calc(u10n, usr, Ta, lat, meth="S80"):
         cdn = np.power((0.10038+u10n*2.17e-3+np.power(u10n, 2)*2.78e-3 -
                         np.power(u10n, 3)*4.4e-5)/u10n, 2)
     elif (meth == "LY04"):
-        cdn = np.where(u10n >= 0.5,
-                       (0.142+(2.7/u10n)+(u10n/13.09))*0.001,
-                       (0.142+(2.7/0.5)+(0.5/13.09))*0.001)
+        cdn = np.where(u10n > 0.25, (0.142+2.7/u10n+u10n/13.09 -
+                                    3.14807e-10*np.power(u10n, 6))*1e-3,
+                       (0.142+2.7/0.25+0.25/13.09 -
+                        3.14807e-10*np.power(0.25, 6))*1e-3)
+        cdn = np.where(u10n > 33, 2.34e-3, np.copy(cdn))
+        cdn = np.maximum(np.copy(cdn), 0.1e-3)
     else:
         print("unknown method cdn: "+meth)
     return cdn
@@ -156,8 +159,9 @@ def ctcqn_calc(zol, cdn, usr, zo, Ta, meth="S80"):
         cqn = np.where((zol <= 0), 1.15*0.001, 1*0.001)
         ctn = np.where((zol <= 0), 1.13*0.001, 0.66*0.001)
     elif (meth == "LY04"):
-        cqn = 34.6*0.001*np.sqrt(cdn)
-        ctn = np.where(zol <= 0, 32.7*0.001*np.sqrt(cdn), 18*0.001*np.sqrt(cdn))
+        cqn = np.maximum(34.6*0.001*np.sqrt(cdn), 0.1e-3)
+        ctn = np.maximum(np.where(zol <= 0, 32.7*0.001*np.sqrt(cdn),
+                                  18*0.001*np.sqrt(cdn)), 0.1e-3)
     elif (meth == "UA"):
         # Zeng et al. 1998 (25)
         rr = usr*zo/visc_air(Ta)
@@ -274,7 +278,7 @@ def psim_calc(zol, meth="S80"):
     """
     if (meth == "ecmwf"):
         psim = psim_ecmwf(zol)
-    elif (meth == "C30" or meth == "C35"):  # or meth == "C40"
+    elif (meth == "C30" or meth == "C35"):
         psim = psiu_26(zol, meth)
     elif (meth == "Beljaars"): # Beljaars (1997) eq. 16, 17
         psim = np.where(zol < 0, psim_conv(zol, meth), psi_Bel(zol))
-- 
GitLab