Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
NOCSurfaceProcesses
AirSeaFluxCode
Commits
8222efbc
Commit
8222efbc
authored
2 years ago
by
sbiri
Browse files
Options
Download
Email Patches
Plain Diff
add option 5 for gustiness following UA and shift C35 code to option 6
Add all function (unified, not unified) in cs_wl_subs.py
parent
b6038e55
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
277 additions
and
55 deletions
+277
-55
AirSeaFluxCode/src/AirSeaFluxCode.py
AirSeaFluxCode/src/AirSeaFluxCode.py
+9
-8
AirSeaFluxCode/src/AirSeaFluxCode_dev.py
AirSeaFluxCode/src/AirSeaFluxCode_dev.py
+2
-4
AirSeaFluxCode/src/cs_wl_subs.py
AirSeaFluxCode/src/cs_wl_subs.py
+264
-41
AirSeaFluxCode/src/flux_subs.py
AirSeaFluxCode/src/flux_subs.py
+1
-1
AirSeaFluxCode/src/flux_subs_dev.py
AirSeaFluxCode/src/flux_subs_dev.py
+1
-1
No files found.
AirSeaFluxCode/src/AirSeaFluxCode.py
View file @
8222efbc
...
...
@@ -10,14 +10,14 @@ from cs_wl_subs import *
class
S88
:
def
_wind_iterate
(
self
,
ind
):
if
self
.
gust
[
0
]
in
range
(
1
,
6
):
if
self
.
gust
[
0
]
in
range
(
1
,
7
):
self
.
wind
[
ind
]
=
np
.
sqrt
(
np
.
power
(
np
.
copy
(
self
.
spd
[
ind
]),
2
)
+
np
.
power
(
get_gust
(
self
.
gust
[
1
],
self
.
gust
[
2
],
self
.
gust
[
3
],
self
.
theta
[
ind
],
self
.
usr
[
ind
],
self
.
tsrv
[
ind
],
self
.
grav
[
ind
]),
2
))
if
self
.
gust
[
0
]
in
[
3
,
4
]:
if
self
.
gust
[
0
]
in
[
3
,
4
,
5
]:
# self.GustFact[ind] = 1
# option to not remove GustFact
self
.
u10n
[
ind
]
=
self
.
wind
[
ind
]
-
self
.
usr
[
ind
]
/
kappa
*
(
...
...
@@ -92,11 +92,6 @@ class S88:
self
.
SST
[
ind
]),
self
.
rho
[
ind
],
self
.
Rs
[
ind
],
self
.
Rnl
[
ind
],
self
.
cp
[
ind
],
self
.
lv
[
ind
],
np
.
copy
(
self
.
tkt
[
ind
]),
self
.
usr
[
ind
],
self
.
tsr
[
ind
],
self
.
qsr
[
ind
],
self
.
grav
[
ind
])
# self.dter[ind] = cs_C35(np.copy(
# self.skt[ind]), self.rho[ind], self.Rs[ind], self.Rnl[ind],
# self.cp[ind], self.lv[ind], self.usr[ind], self.tsr[ind],
# self.qsr[ind], self.grav[ind])
elif
self
.
skin
==
"ecmwf"
:
self
.
dter
[
ind
]
=
cs_ecmwf
(
self
.
rho
[
ind
],
self
.
Rs
[
ind
],
self
.
Rnl
[
ind
],
self
.
cp
[
ind
],
...
...
@@ -406,6 +401,12 @@ class S88:
self
.
uref
=
self
.
wind
-
self
.
usr
/
kappa
*
(
np
.
log
(
self
.
h_in
[
0
]
/
self
.
h_out
[
0
])
-
self
.
psim
+
psim_calc
(
self
.
h_out
[
0
]
/
self
.
monob
,
self
.
meth
))
elif
self
.
gust
[
0
]
==
5
:
self
.
u10n
=
self
.
spd
-
self
.
usr
/
kappa
*
(
np
.
log
(
self
.
h_in
[
0
]
/
self
.
ref10
)
-
self
.
psim
)
self
.
uref
=
self
.
spd
-
self
.
usr
/
kappa
*
(
np
.
log
(
self
.
h_in
[
0
]
/
self
.
h_out
[
0
])
-
self
.
psim
+
psim_calc
(
self
.
h_out
[
0
]
/
self
.
monob
,
self
.
meth
))
else
:
self
.
u10n
=
self
.
spd
-
self
.
usr
/
kappa
/
self
.
GFo
*
(
np
.
log
(
self
.
h_in
[
0
]
/
self
.
ref10
)
-
self
.
psim
)
# C.4-7
...
...
@@ -527,7 +528,7 @@ class S88:
gust
=
[
0
,
0
,
0
,
0
]
assert
np
.
size
(
gust
)
==
4
,
"gust input must be a 4x1 array"
assert
gust
[
0
]
in
range
(
6
),
"gust at position 0 must be 0 to
5
"
assert
gust
[
0
]
in
range
(
7
),
"gust at position 0 must be 0 to
6
"
self
.
gust
=
gust
def
_class_flag
(
self
):
...
...
This diff is collapsed.
Click to expand it.
AirSeaFluxCode/src/AirSeaFluxCode_dev.py
View file @
8222efbc
...
...
@@ -10,7 +10,7 @@ from cs_wl_subs import *
class
S88
:
def
_wind_iterate
(
self
,
ind
):
if
self
.
gust
[
0
]
in
range
(
1
,
6
):
if
self
.
gust
[
0
]
in
range
(
1
,
7
):
self
.
wind
[
ind
]
=
np
.
sqrt
(
np
.
power
(
np
.
copy
(
self
.
spd
[
ind
]),
2
)
+
np
.
power
(
get_gust
(
self
.
gust
[
1
],
self
.
gust
[
2
],
...
...
@@ -361,8 +361,6 @@ class S88:
self
.
tau
=
self
.
rho
*
np
.
power
(
self
.
usr
,
2
)
*
self
.
spd
/
self
.
wind
self
.
sensible
=
self
.
rho
*
self
.
cp
*
self
.
usr
*
self
.
tsr
self
.
latent
=
self
.
rho
*
self
.
lv
*
self
.
usr
*
self
.
qsr
# Set the new variables (for comparison against "old")
new
=
np
.
array
([
np
.
copy
(
getattr
(
self
,
i
))
for
i
in
new_vars
])
...
...
@@ -582,7 +580,7 @@ class S88:
gust
=
[
0
,
0
,
0
,
0
]
assert
np
.
size
(
gust
)
==
4
,
"gust input must be a 4x1 array"
assert
gust
[
0
]
in
range
(
6
),
"gust at position 0 must be 0 to
5
"
assert
gust
[
0
]
in
range
(
7
),
"gust at position 0 must be 0 to
6
"
self
.
gust
=
gust
def
_class_flag
(
self
):
...
...
This diff is collapsed.
Click to expand it.
AirSeaFluxCode/src/cs_wl_subs.py
View file @
8222efbc
import
numpy
as
np
from
util_subs
import
(
CtoK
,
kappa
)
# def delta(aw, Q, usr, grav, rho, opt):
# """
# Compute the thickness (m) of the viscous skin layer.
def
delta
(
aw
,
Q
,
usr
,
grav
,
rho
,
opt
):
"""
Compute the thickness (m) of the viscous skin layer.
Based on Fairall et al., 1996 and cited in IFS Documentation Cy46r1
eq. 8.155 p. 164
# Based on Fairall et al., 1996 and cited in IFS Documentation Cy46r1
# eq. 8.155 p. 164
Parameters
----------
aw : float
thermal expansion coefficient of sea-water [1/K]
Q : float
part of the net heat flux actually absorbed in the warm layer [W/m^2]
usr : float
friction velocity in the air (u*) [m/s]
grav : float
gravity [ms^-2]
#
Parameters
#
----------
#
aw : float
#
thermal expansion coefficient of sea-water [1/K]
#
Q : float
#
part of the net heat flux actually absorbed in the warm layer [W/m^2]
#
usr : float
#
friction velocity in the air (u*) [m/s]
#
grav : float
#
gravity [ms^-2]
Returns
-------
delta : float
the thickness (m) of the viscous skin layer
#
Returns
#
-------
#
delta : float
#
the thickness (m) of the viscous skin layer
"""
if
opt
==
"C35"
:
rhow
,
cw
,
visw
,
tcw
=
1022
,
4000
,
1e-6
,
0.6
# second term in eq. 14
tmp
=
16
*
grav
*
Q
*
aw
*
rhow
*
cw
*
np
.
power
(
rhow
*
visw
,
3
)
/
(
np
.
power
(
usr
,
4
)
*
np
.
power
(
rho
,
2
)
*
np
.
power
(
tcw
,
2
))
# second term in eq. 14
# lm = 6*np.ones(usr.shape)
lm
=
np
.
where
(
Q
>
0
,
6
/
np
.
power
(
1
+
np
.
power
(
tmp
,
3
/
4
),
1
/
3
),
6
)
# eq. 14 F96
delta
=
np
.
minimum
(
lm
*
visw
/
np
.
sqrt
(
rho
/
rhow
)
/
usr
,
0.01
)
# eq. 12 F96
delta
=
np
.
where
(
Q
>
0
,
lm
*
visw
/
(
np
.
sqrt
(
rho
/
rhow
)
*
usr
),
delta
)
elif
opt
==
"ecmwf"
:
rhow
,
cw
,
visw
,
tcw
=
1025
,
4190
,
1e-6
,
0.6
# u* in the water
usr_w
=
np
.
maximum
(
usr
,
1e-4
)
*
np
.
sqrt
(
rho
/
rhow
)
# rhoa=1.2
rcst_cs
=
16
*
grav
*
np
.
power
(
visw
,
3
)
/
np
.
power
(
tcw
,
2
)
#/(rhow*cw)
# eq. 8.155 Cy46r1
lm
=
6
*
(
1
+
np
.
maximum
(
Q
*
aw
*
rcst_cs
/
np
.
power
(
usr_w
,
4
),
0
)
**
0.75
)
**
(
-
1
/
3
)
ztmp
=
visw
/
usr_w
delta
=
np
.
where
(
Q
>
0
,
np
.
minimum
(
6
*
ztmp
,
0.007
),
lm
*
ztmp
)
return
delta
# """
# if opt == "C35":
# rhow, cw, visw, tcw = 1022, 4000, 1e-6, 0.6
# # second term in eq. 14
# tmp = 16*grav*Q*aw*rhow*cw*np.power(rhow*visw, 3)/(
# np.power(usr, 4)*np.power(rho, 2)*np.power(tcw, 2))
# # second term in eq. 14
# # lm = 6*np.ones(usr.shape)
# lm = np.where(Q > 0, 6/np.power(1+np.power(tmp, 3/4), 1/3), 6) # eq. 14 F96
# delta = np.minimum(lm*visw/np.sqrt(rho/rhow)/usr, 0.01) # eq. 12 F96
# delta = np.where(Q > 0, lm*visw/(np.sqrt(rho/rhow)*usr), delta)
# # bigc = 16*grav*cw*np.power(rhow*visw, 3)/(np.power(tcw, 2)*np.power(
# # rho, 2))
# # lm = np.where(Qb > 0, 6/(1+(bigc*Qb/usr**4)**0.75)**0.333, 6)
# # d = np.minimum(xlamx*visw/(np.sqrt(rho/rhow)*usr), 0.01)
# # d = np.where(Qb > 0, xlamx*visw/(np.sqrt(rho/rhow)*usr), d)
# elif opt == "ecmwf":
# rhow, cw, visw, tcw = 1025, 4190, 1e-6, 0.6
# # u* in the water
# usr_w = np.maximum(usr, 1e-4)*np.sqrt(rho/rhow) # rhoa=1.2
# rcst_cs = 16*grav*np.power(visw, 3)/np.power(tcw, 2)#/(rhow*cw)
# # eq. 8.155 Cy46r1
# # lm = 6/np.power(1+np.power(Q*aw*rcst_cs/np.power(usr_w, 4), 3/4), 1/3)
# lm = 6*(1+np.maximum(Q*aw*rcst_cs/np.power(usr_w, 4), 0)**0.75)**(-1/3)
# ztmp = visw/usr_w
# delta = np.where(Q > 0, np.minimum(6*ztmp, 0.007), lm*ztmp)
# return delta
# ---------------------------------------------------------------------
...
...
@@ -122,6 +127,162 @@ def cs(sst, d, rho, Rs, Rnl, cp, lv, usr, tsr, qsr, grav, opt):
# ---------------------------------------------------------------------
def
cs_C35
(
sst
,
rho
,
Rs
,
Rnl
,
cp
,
lv
,
delta
,
usr
,
tsr
,
qsr
,
grav
):
"""
Compute cool skin.
Based on COARE3.5 (Fairall et al. 1996, Edson et al. 2013)
Parameters
----------
sst : float
sea surface temperature [K]
qsea : float
specific humidity over sea [g/kg]
rho : float
density of air [kg/m^3]
Rs : float
downward shortwave radiation [Wm-2]
Rnl : float
net upwelling IR radiation [Wm-2]
cp : float
specific heat of air at constant pressure [J/K/kg]
lv : float
latent heat of vaporization [J/kg]
delta : float
cool skin thickness [m]
usr : float
friction velocity [m/s]
tsr : float
star temperature [K]
qsr : float
star humidity [g/kg]
grav : float
gravity [ms^-2]
Returns
-------
dter : float
cool skin correction [K]
dqer : float
humidity corrction [g/kg]
delta : float
cool skin thickness [m]
"""
# coded following Saunders (1967) with lambda = 6
if
np
.
nanmin
(
sst
)
>
200
:
# if sst in Kelvin convert to Celsius
sst
=
sst
-
CtoK
# ************ cool skin constants *******
# density of water, specific heat capacity of water, water viscosity,
# thermal conductivity of water
rhow
,
cpw
,
visw
,
tcw
=
1022
,
4000
,
1e-6
,
0.6
for
i
in
range
(
4
):
aw
=
2.1e-5
*
np
.
power
(
np
.
maximum
(
sst
+
3.2
,
0
),
0.79
)
bigc
=
16
*
grav
*
cpw
*
np
.
power
(
rhow
*
visw
,
3
)
/
(
np
.
power
(
tcw
,
2
)
*
np
.
power
(
rho
,
2
))
Rns
=
0.945
*
Rs
# albedo correction
shf
=
rho
*
cp
*
usr
*
tsr
lhf
=
rho
*
lv
*
usr
*
qsr
Qnsol
=
shf
+
lhf
+
Rnl
fs
=
0.065
+
11
*
delta
-
6.6e-5
/
delta
*
(
1
-
np
.
exp
(
-
delta
/
8.0e-4
))
Q
=
Qnsol
+
Rns
*
fs
Qb
=
aw
*
Q
+
0.026
*
np
.
minimum
(
lhf
,
0
)
*
cpw
/
lv
xlamx
=
6
*
np
.
ones
(
sst
.
shape
)
xlamx
=
np
.
where
(
Qb
>
0
,
6
/
(
1
+
(
bigc
*
Qb
/
usr
**
4
)
**
0.75
)
**
0.333
,
6
)
delta
=
np
.
minimum
(
xlamx
*
visw
/
(
np
.
sqrt
(
rho
/
rhow
)
*
usr
),
0.01
)
delta
=
np
.
where
(
Qb
>
0
,
xlamx
*
visw
/
(
np
.
sqrt
(
rho
/
rhow
)
*
usr
),
delta
)
dter
=
Q
*
delta
/
tcw
return
dter
,
delta
# ---------------------------------------------------------------------
def
delta
(
aw
,
Q
,
usr
,
grav
):
"""
Compute the thickness (m) of the viscous skin layer.
Based on Fairall et al., 1996 and cited in IFS Documentation Cy46r1
eq. 8.155 p. 164
Parameters
----------
aw : float
thermal expansion coefficient of sea-water [1/K]
Q : float
part of the net heat flux actually absorbed in the warm layer [W/m^2]
usr : float
friction velocity in the air (u*) [m/s]
grav : float
gravity [ms^-2]
Returns
-------
delta : float
the thickness (m) of the viscous skin layer
"""
rhow
,
visw
,
tcw
=
1025
,
1e-6
,
0.6
# u* in the water
usr_w
=
np
.
maximum
(
usr
,
1e-4
)
*
np
.
sqrt
(
1.2
/
rhow
)
# rhoa=1.2
rcst_cs
=
16
*
grav
*
np
.
power
(
visw
,
3
)
/
np
.
power
(
tcw
,
2
)
lm
=
6
*
(
1
+
np
.
maximum
(
Q
*
aw
*
rcst_cs
/
np
.
power
(
usr_w
,
4
),
0
)
**
0.75
)
**
(
-
1
/
3
)
ztmp
=
visw
/
usr_w
delta
=
np
.
where
(
Q
>
0
,
np
.
minimum
(
6
*
ztmp
,
0.007
),
lm
*
ztmp
)
return
delta
# ---------------------------------------------------------------------
def
cs_ecmwf
(
rho
,
Rs
,
Rnl
,
cp
,
lv
,
usr
,
tsr
,
qsr
,
sst
,
grav
):
"""
cool skin adjustment based on IFS Documentation cy46r1
Parameters
----------
rho : float
density of air [kg/m^3]
Rs : float
downward solar radiation [Wm-2]
Rnl : float
net thermal radiation [Wm-2]
cp : float
specific heat of air at constant pressure [J/K/kg]
lv : float
latent heat of vaporization [J/kg]
usr : float
friction velocity [m/s]
tsr : float
star temperature [K]
qsr : float
star humidity [g/kg]
sst : float
sea surface temperature [K]
grav : float
gravity [ms^-2]
Returns
-------
dtc : float
cool skin temperature correction [K]
"""
if
np
.
nanmin
(
sst
)
<
200
:
# if sst in Celsius convert to Kelvin
sst
=
sst
+
CtoK
aw
=
np
.
maximum
(
1e-5
,
1e-5
*
(
sst
-
CtoK
))
Rns
=
0.945
*
Rs
# (net solar radiation (albedo correction)
shf
=
rho
*
cp
*
usr
*
tsr
lhf
=
rho
*
lv
*
usr
*
qsr
Qnsol
=
shf
+
lhf
+
Rnl
# eq. 8.152
d
=
delta
(
aw
,
Qnsol
,
usr
,
grav
)
for
jc
in
range
(
4
):
# because implicit in terms of delta...
# # fraction of the solar radiation absorbed in layer delta eq. 8.153
# and Eq.(5) Zeng & Beljaars, 2005
fs
=
0.065
+
11
*
d
-
6.6e-5
/
d
*
(
1
-
np
.
exp
(
-
d
/
8e-4
))
Q
=
Qnsol
+
fs
*
Rns
d
=
delta
(
aw
,
Q
,
usr
,
grav
)
dtc
=
Q
*
d
/
0.6
# (rhow*cw*kw)eq. 8.151
return
dtc
# ---------------------------------------------------------------------
def
wl_ecmwf
(
rho
,
Rs
,
Rnl
,
cp
,
lv
,
usr
,
tsr
,
qsr
,
sst
,
skt
,
dtc
,
grav
):
"""
Calculate warm layer correction following IFS Documentation cy46r1.
...
...
@@ -200,6 +361,68 @@ def wl_ecmwf(rho, Rs, Rnl, cp, lv, usr, tsr, qsr, sst, skt, dtc, grav):
# ----------------------------------------------------------------------
def
cs_Beljaars
(
rho
,
Rs
,
Rnl
,
cp
,
lv
,
usr
,
tsr
,
qsr
,
grav
,
Qs
):
"""
cool skin adjustment based on Beljaars (1997)
air-sea interaction in the ECMWF model
Parameters
----------
rho : float
density of air [kg/m^3]
Rs : float
downward solar radiation [Wm-2]
Rnl : float
net thermal radiaion [Wm-2]
cp : float
specific heat of air at constant pressure [J/K/kg]
lv : float
latent heat of vaporization [J/kg]
usr : float
friction velocity [m/s]
tsr : float
star temperature [K]
qsr : float
star humidity [g/kg]
grav : float
gravity [ms^-2]
Qs : float
radiation balance
Returns
-------
Qs : float
radiation balance
dtc : float
cool skin temperature correction [K]
"""
tcw
=
0.6
# thermal conductivity of water (at 20C) [W/m/K]
visw
=
1e-6
# kinetic viscosity of water [m^2/s]
rhow
=
1025
# Density of sea-water [kg/m^3]
cpw
=
4190
# specific heat capacity of water
aw
=
3e-4
# thermal expansion coefficient [K-1]
Rns
=
0.945
*
Rs
# net solar radiation (albedo correction)
shf
=
rho
*
cp
*
usr
*
tsr
lhf
=
rho
*
lv
*
usr
*
qsr
Q
=
Rnl
+
shf
+
lhf
+
Qs
xt
=
16
*
Q
*
grav
*
aw
*
cpw
*
np
.
power
(
rhow
*
visw
,
3
)
/
(
np
.
power
(
usr
,
4
)
*
np
.
power
(
rho
*
tcw
,
2
))
xt1
=
1
+
np
.
power
(
xt
,
3
/
4
)
# Saunders const eq. 22
ls
=
np
.
where
(
Q
>
0
,
6
/
np
.
power
(
xt1
,
1
/
3
),
6
)
delta
=
np
.
where
(
Q
>
0
,
(
ls
*
visw
)
/
(
np
.
sqrt
(
rho
/
rhow
)
*
usr
),
np
.
where
((
ls
*
visw
)
/
(
np
.
sqrt
(
rho
/
rhow
)
*
usr
)
>
0.01
,
0.01
,
(
ls
*
visw
)
/
(
np
.
sqrt
(
rho
/
rhow
)
*
usr
)))
# eq. 21
# fraction of the solar radiation absorbed in layer delta
fc
=
0.065
+
11
*
delta
-
6.6e-5
*
(
1
-
np
.
exp
(
-
delta
/
0.0008
))
/
delta
Qs
=
fc
*
Rns
Q
=
Rnl
+
shf
+
lhf
+
Qs
dtc
=
Q
*
delta
/
tcw
return
Qs
,
dtc
# ----------------------------------------------------------------------
def
get_dqer
(
dter
,
sst
,
qsea
,
lv
):
"""
Calculate humidity correction.
...
...
This diff is collapsed.
Click to expand it.
AirSeaFluxCode/src/flux_subs.py
View file @
8222efbc
...
...
@@ -633,7 +633,7 @@ def apply_GF(gust, spd, wind, step):
GustFact
=
wind
*
0
+
1
if
gust
[
0
]
in
[
1
,
2
]:
GustFact
=
np
.
sqrt
(
wind
/
spd
)
elif
gust
[
0
]
==
5
:
elif
gust
[
0
]
==
6
:
# as in C35 matlab code
GustFact
=
wind
/
spd
elif
step
==
"TSF"
:
...
...
This diff is collapsed.
Click to expand it.
AirSeaFluxCode/src/flux_subs_dev.py
View file @
8222efbc
...
...
@@ -704,7 +704,7 @@ def apply_GF(gust, spd, wind, step):
GustFact
=
wind
*
0
+
1
if
gust
[
0
]
in
[
1
,
2
]:
GustFact
=
np
.
sqrt
(
wind
/
spd
)
elif
gust
[
0
]
==
5
:
elif
gust
[
0
]
==
6
:
# as in C35 matlab code
GustFact
=
wind
/
spd
elif
step
==
"TSF"
:
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment