Commit b4c11efd authored by sbiri's avatar sbiri
Browse files

Update AirSeaFluxCode.py, flux_subs.py, get_init.py, hum_subs.py files

parent 3d302aa5
......@@ -71,10 +71,8 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None,
set 1 to keep points
L : int
Monin-Obukhov length definition options
0 : default for S80, S88, LP82, YT96 and LY04
1 : following UA (Zeng et al., 1998), default for UA
2 : following ERA5 (IFS Documentation cy46r1), default for ERA5
3 : COARE3.5 (Edson et al., 2013), default for C30, C35 and C40
"S80" : default for S80, S88, LP82, YT96 and LY04
"ERA5" : following ERA5 (IFS Documentation cy46r1), default for ERA5
Returns
-------
res : array that contains
......@@ -113,6 +111,8 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None,
"""
logging.basicConfig(filename='flux_calc.log',
format='%(asctime)s %(message)s',level=logging.INFO)
logging.captureWarnings(True)
# check input values and set defaults where appropriate
lat, P, Rl, Rs, cskin, gust, tol, L = get_init(spd, T, SST, lat, P, Rl, Rs,
cskin, gust, L, tol, meth,
qmeth)
......@@ -123,7 +123,7 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None,
' Rs: %s | gust: %s | cskin: %s | L : %s', meth,
np.nanmedian(lat), np.nanmedian(P), np.nanmedian(Rl),
np.nanmedian(Rs), gust, cskin, L)
####
# set up/calculate temperatures and specific humidities
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
......@@ -135,9 +135,9 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None,
np.nanmedian(qsea), np.nanmedian(qair))
if (np.all(np.isnan(qsea)) or np.all(np.isnan(qair))):
print("qsea and qair cannot be nan")
# first guesses
dt = Ta - sst
dq = qair - qsea
# first guesses
t10n, q10n = np.copy(Ta), np.copy(qair)
tv10n = t10n*(1 + 0.61*q10n)
# Zeng et al. 1998
......@@ -162,6 +162,7 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None,
Rnl = 0.97*(5.67e-8*np.power(sst-0.3*cskin+CtoK, 4)-Rl)
dter = np.ones(T.shape)*0.3
dqer = dter*0.622*lv*qsea/(287.1*np.power(sst, 2))
# gustiness adjustment
if (gust[0] == 1 and 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)))
......@@ -169,6 +170,7 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None,
wind = np.sqrt(np.power(np.copy(spd), 2)+np.power(0.5, 2))
elif (gust[0] == 0):
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)
......@@ -177,11 +179,13 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None,
psit_calc(h_in[1]/monob, meth))
qsr = (dq+dqer*cskin)*kappa/(np.log(h_in[2]/zoq) -
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
tau = 0.05*np.ones(spd.shape)
sensible = 5*np.ones(spd.shape)
latent = 65*np.ones(spd.shape)
# iteration loop
while np.any(ii):
it += 1
if it > n:
......@@ -288,14 +292,14 @@ def AirSeaFluxCode(spd, T, SST, lat=None, hum=None, P=None,
d = np.fabs(new-old)
if (tol[0] == 'flux'):
ind = np.where((d[0, :] > tol[1])+(d[1, :] > tol[2]) +
(d[2, :] > tol[3]))
(d[2, :] > tol[3]))
elif (tol[0] == 'ref'):
ind = np.where((d[0, :] > tol[1])+(d[1, :] > tol[2]) +
(d[2, :] > tol[3]))
(d[2, :] > tol[3]))
elif (tol[0] == 'all'):
ind = np.where((d[0, :] > tol[1])+(d[1, :] > tol[2]) +
(d[2, :] > tol[3])+(d[3, :] > tol[4]) +
(d[4, :] > tol[5])+(d[5, :] > tol[6]))
(d[2, :] > tol[3])+(d[3, :] > tol[4]) +
(d[4, :] > tol[5])+(d[5, :] > tol[6]))
if (ind[0].size == 0):
ii = False
else:
......
......@@ -651,10 +651,8 @@ def get_L(L, lat, usr, tsr, qsr, t10n, tv10n, qair, h_in, T, Ta, th, tv, sst,
----------
L : int
Monin-Obukhov length definition options
0 : default for S80, S88, LP82, YT96 and LY04
1 : following UA (Zeng et al., 1998), default for UA
2 : following ERA5 (IFS Documentation cy46r1), default for ERA5
3 : COARE3.5 (Edson et al., 2013), default for C30, C35 and C40
"S80" : default for S80, S88, LP82, YT96 and LY04
"ERA5" : following ERA5 (IFS Documentation cy46r1), default for ERA5
lat : float
latitude
usr : float
......@@ -702,19 +700,11 @@ def get_L(L, lat, usr, tsr, qsr, t10n, tv10n, qair, h_in, T, Ta, th, tv, sst,
"""
g = gc(lat)
if (L == 0):
if (L == "S80"):
tsrv = tsr+0.61*t10n*qsr
monob = ((tv10n*np.power(usr, 2))/(g*kappa*tsrv))
monob = np.where(np.fabs(monob) < 1, np.where(monob < 0, -1, 1), monob)
elif (L == 1):
Rb = g*h_in[0]*dtv/(tv*np.power(wind, 2))
zol = np.where(Rb >= 0, Rb*np.log(h_in[0]/zo) /
(1-5*np.where(Rb < 0.19, Rb, 0.19)),
Rb*np.log(h_in[0]/zo))
monob = h_in[0]/zol
tsrv = tsr*(1.+0.61*qair)+0.61*th*qsr
# monob = ((tv*np.power(usr, 2))/(kappa*g*tsrv))
elif (L == 2):
elif (L == "ERA5"):
tsrv = tsr+0.61*t10n*qsr
Rb = ((g*h_in[0]*((2*dt)/(Ta+sst-g*h_in[0])+0.61*dq)) /
np.power(wind, 2))
......@@ -727,11 +717,6 @@ def get_L(L, lat, usr, tsr, qsr, t10n, tv10n, qair, h_in, T, Ta, th, tv, sst,
psit_calc((h_in[0]+zo)/monob, meth) +
psit_calc(zot/monob, meth))))
monob = h_in[0]/zol
elif (L == 3):
tsrv = tsr+0.61*(T+CtoK)*qsr
zol = (kappa*g*h_in[0]/(T+CtoK)*(tsr+0.61*(T+CtoK)*qsr) /
np.power(usr, 2))
monob = h_in[0]/zol
return tsrv, monob
#------------------------------------------------------------------------------
......@@ -784,48 +769,50 @@ def get_strs(h_in, monob, wind, zo, zot, zoq, dt, dq, dter, dqer, ct, cq,
"""
if (meth == "UA"):
usr = np.where(h_in[0]/monob < -1.574, kappa*wind /
usr = np.where(h_in[0]/monob <= -1.574, kappa*wind /
(np.log(-1.574*monob/zo)-psim_calc(-1.574, meth) +
psim_calc(zo/monob, meth) +
1.14*(np.power(-h_in[0]/monob, 1/3) -
np.power(1.574, 1/3))),
np.where((h_in[0]/monob > -1.574) & (h_in[0]/monob < 0),
kappa*wind/(np.log(h_in[0]/zo) -
psim_calc(h_in[0]/monob, meth) +
psim_calc(zo/monob, meth)),
np.where((h_in[0]/monob > 0) &
(h_in[0]/monob < 1),
kappa*wind/(np.log(h_in[0]/zo) +
5*h_in[0]/monob-5*zo/monob),
kappa*wind/(np.log(monob/zo)+5-5*zo/monob +
5*np.log(h_in[0]/monob)+h_in[0]/monob-1))))
np.where(h_in[0]/monob < 0, kappa*wind /
(np.log(h_in[0]/zo) -
psim_calc(h_in[0]/monob, meth) +
psim_calc(zo/monob, meth)),
np.where(h_in[0]/monob <= 1, kappa*wind /
(np.log(h_in[0]/zo) +
5*h_in[0]/monob-5*zo/monob),
kappa*wind/(np.log(monob/zo)+5 -
5*zo/monob +
5*np.log(h_in[0]/monob) +
h_in[0]/monob-1))))
# Zeng et al. 1998 (7-10)
tsr = np.where(h_in[1]/monob < -0.465, kappa*(dt+dter*cskin) /
(np.log((-0.465*monob)/zot) -
psit_calc(-0.465, meth)+0.8*(np.power(0.465, -1/3) -
np.power(-h_in[1]/monob, -1/3))),
np.where((h_in[1]/monob > -0.465) & (h_in[1]/monob < 0),
kappa*(dt+dter*cskin)/(np.log(h_in[1]/zot) -
psit_calc(h_in[1]/monob, meth) +
psit_calc(zot/monob, meth)),
np.where((h_in[1]/monob > 0) & (h_in[1]/monob < 1),
kappa*(dt+dter*cskin)/(np.log(h_in[1]/zot) +
5*h_in[1]/monob-5*zot/monob),
kappa*(dt+dter*cskin)/(np.log(monob/zot)+5 -
5*zot/monob+5*np.log(h_in[1]/monob) +
h_in[1]/monob-1))))
np.where(h_in[1]/monob < 0, kappa*(dt+dter*cskin) /
(np.log(h_in[1]/zot) -
psit_calc(h_in[1]/monob, meth) +
psit_calc(zot/monob, meth)),
np.where(h_in[1]/monob <= 1,
kappa*(dt+dter*cskin) /
(np.log(h_in[1]/zot) +
5*h_in[1]/monob-5*zot/monob),
kappa*(dt+dter*cskin) /
(np.log(monob/zot)+5 -
5*zot/monob+5*np.log(h_in[1]/monob) +
h_in[1]/monob-1))))
# Zeng et al. 1998 (11-14)
qsr = np.where(h_in[2]/monob < -0.465, kappa*(dq+dqer*cskin) /
(np.log((-0.465*monob)/zoq) -
psit_calc(-0.465, meth)+psit_calc(zoq/monob, meth) +
0.8*(np.power(0.465, -1/3) -
np.power(-h_in[2]/monob, -1/3))),
np.where((h_in[2]/monob > -0.465) & (h_in[2]/monob < 0),
np.where(h_in[2]/monob < 0,
kappa*(dq+dqer*cskin)/(np.log(h_in[1]/zot) -
psit_calc(h_in[2]/monob, meth) +
psit_calc(zoq/monob, meth)),
np.where((h_in[2]/monob > 0) &
(h_in[2]/monob<1),
np.where(h_in[2]/monob <= 1,
kappa*(dq+dqer*cskin) /
(np.log(h_in[1]/zoq)+5*h_in[2]/monob -
5*zoq/monob),
......
......@@ -99,11 +99,11 @@ def get_init(spd, T, SST, lat, P, Rl, Rs, cskin, gust, L, tol, meth, qmeth):
if (np.all(Rs == None) or np.all(np.isnan(Rs))):
Rs = np.ones(spd.shape)*150 # set to default for COARE3.5
if ((cskin == None) and (meth == "S80" or meth == "S88" or meth == "LP82"
or meth == "YT96" or meth == "LY04")):
or meth == "YT96" or meth == "UA" or
meth == "LY04")):
cskin = 0
elif ((cskin == None) and (meth == "UA" or meth == "C30"
or meth == "C35" or meth == "C40"
or meth == "ERA5")):
elif ((cskin == None) and (meth == "C30" or meth == "C35" or meth == "C40"
or meth == "ERA5")):
cskin = 1
if ((gust == None) and (meth == "C30" or meth == "C35" or meth == "C40")):
gust = [1, 1.2, 600]
......@@ -113,19 +113,17 @@ def get_init(spd, T, SST, lat, P, Rl, Rs, cskin, gust, L, tol, meth, qmeth):
gust = [1, 1.2, 800]
elif (np.size(gust) < 3):
sys.exit("gust input must be a 3x1 array")
if (L not in [None, 0, 1, 2, 3]):
if (L not in [None, "S80", "ERA5"]):
sys.exit("L input must be either None, 0, 1, 2 or 3")
if ((L == None) and (meth == "S80" or meth == "S88" or meth == "LP82"
or meth == "YT96" or meth == "LY04")):
L = 0
elif ((L == None) and (meth == "UA")):
L = 1
or meth == "YT96" or meth == "LY04" or
meth == "UA" or meth == "C30" or meth == "C35"
or meth == "C40")):
L = "S80"
elif ((L == None) and (meth == "ERA5")):
L = 2
elif ((L == None) and (meth == "C30" or meth == "C35" or meth == "C40")):
L = 3
L = "ERA5"
if (tol == None):
tol = ['flux', 0.01, 1, 1]
elif (tol[0] not in ['flux', 'ref', 'all']):
sys.exit("unknown tolerance input")
return lat, P, Rl, Rs, cskin, gust, tol, L
\ No newline at end of file
return lat, P, Rl, Rs, cskin, gust, tol, L
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment