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
de93be2b
Commit
de93be2b
authored
4 years ago
by
sbiri
Browse files
Options
Download
Email Patches
Plain Diff
changed to contain only subroutines related to fluxes
parent
723b94fb
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
11 additions
and
343 deletions
+11
-343
flux_subs.py
flux_subs.py
+11
-343
No files found.
flux_subs.py
View file @
de93be2b
import
numpy
as
np
import
sys
from
VaporPressure
import
VaporPressure
from
util_subs
import
(
CtoK
,
kappa
,
gc
,
visc_air
)
CtoK
=
273.16
# 273.15
""" Conversion factor for $^\circ\,$C to K """
kappa
=
0.4
# NOTE: 0.41
""" von Karman's constant """
# ---------------------------------------------------------------------
...
...
@@ -500,7 +494,8 @@ def psiu_26(zol, meth):
f
=
np
.
power
(
zol
,
2
)
/
(
1
+
np
.
power
(
zol
,
2
))
psi
=
np
.
where
(
zol
<
0
,
(
1
-
f
)
*
psik
+
f
*
psic
,
psi
)
return
psi
# ---------------------------------------------------------------------
#------------------------------------------------------------------------------
def
psim_conv
(
zol
,
meth
):
...
...
@@ -547,137 +542,6 @@ def psim_stab(zol, meth):
# ---------------------------------------------------------------------
def
get_init
(
spd
,
T
,
SST
,
lat
,
P
,
Rl
,
Rs
,
cskin
,
gust
,
L
,
tol
,
meth
,
qmeth
):
"""
Checks initial input values and sets defaults if needed
Parameters
----------
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
SST : float
sea surface temperature in K
lat : float
latitude (deg), default 45deg
P : float
air pressure (hPa), default 1013hPa
Rl : float
downward longwave radiation (W/m^2)
Rs : float
downward shortwave radiation (W/m^2)
cskin : int
0 switch cool skin adjustment off, else 1
default is 1
gust : int
3x1 [x, beta, zi] x=1 to include the effect of gustiness, else 0
beta gustiness parameter, beta=1 for UA, beta=1.2 for COARE
zi PBL height (m) 600 for COARE, 1000 for UA and ERA5, 800 default
default for COARE [1, 1.2, 600]
default for UA, ERA5 [1, 1, 1000]
default else [1, 1.2, 800]
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
tol : float
4x1 or 7x1 [option, lim1-3 or lim1-6]
option : 'flux' to set tolerance limits for fluxes only lim1-3
option : 'ref' to set tolerance limits for height adjustment lim-1-3
option : 'all' to set tolerance limits for both fluxes and height
adjustment lim1-6 ['all', 0.01, 0.01, 5e-05, 0.01, 1, 1]
meth : str
"S80","S88","LP82","YT96","UA","LY04","C30","C35","C40","ERA5"
qmeth : str
is the saturation evaporation method to use amongst
"HylandWexler","Hardy","Preining","Wexler","GoffGratch","CIMO",
"MagnusTetens","Buck","Buck2","WMO","WMO2000","Sonntag","Bolton",
"IAPWS","MurphyKoop"]
default is Buck2
Returns
-------
lat : float
latitude
P : float
air pressure (hPa)
Rl : float
downward longwave radiation (W/m^2)
Rs : float
downward shortwave radiation (W/m^2)
cskin : int
cool skin adjustment switch
gust : int
gustiness switch
tol : float
tolerance limits
L : int
MO length switch
"""
if
((
type
(
spd
)
!=
np
.
ndarray
)
or
(
type
(
T
)
!=
np
.
ndarray
)
or
(
type
(
SST
)
!=
np
.
ndarray
)):
sys
.
exit
(
"input type of spd, T and SST should be numpy.ndarray"
)
# if input values are nan break
if
meth
not
in
[
"S80"
,
"S88"
,
"LP82"
,
"YT96"
,
"UA"
,
"LY04"
,
"C30"
,
"C35"
,
"C40"
,
"ERA5"
]:
sys
.
exit
(
"unknown method"
)
if
qmeth
not
in
[
"HylandWexler"
,
"Hardy"
,
"Preining"
,
"Wexler"
,
"CIMO"
,
"GoffGratch"
,
"MagnusTetens"
,
"Buck"
,
"Buck2"
,
"WMO"
,
"WMO2000"
,
"Sonntag"
,
"Bolton"
,
"IAPWS"
,
"MurphyKoop"
]:
sys
.
exit
(
"unknown q-method"
)
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"
)
if
(
np
.
all
(
lat
==
None
)):
# set latitude to 45deg if empty
lat
=
45
*
np
.
ones
(
spd
.
shape
)
elif
((
np
.
all
(
lat
!=
None
))
and
(
np
.
size
(
lat
)
==
1
)):
lat
=
np
.
ones
(
spd
.
shape
)
*
np
.
copy
(
lat
)
if
((
np
.
all
(
P
==
None
))
or
np
.
all
(
np
.
isnan
(
P
))):
P
=
np
.
ones
(
spd
.
shape
)
*
1013
elif
(((
np
.
all
(
P
!=
None
))
or
np
.
all
(
~
np
.
isnan
(
P
)))
and
np
.
size
(
P
)
==
1
):
P
=
np
.
ones
(
spd
.
shape
)
*
np
.
copy
(
P
)
if
(
np
.
all
(
Rl
==
None
)
or
np
.
all
(
np
.
isnan
(
Rl
))):
Rl
=
np
.
ones
(
spd
.
shape
)
*
370
# set to default for COARE3.5
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"
)):
cskin
=
0
elif
((
cskin
==
None
)
and
(
meth
==
"UA"
or
meth
==
"LY04"
or
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
]
elif
((
gust
==
None
)
and
(
meth
==
"UA"
or
meth
==
"ERA5"
)):
gust
=
[
1
,
1
,
1000
]
elif
(
gust
==
None
):
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
]):
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
elif
((
L
==
None
)
and
(
meth
==
"ERA5"
)):
L
=
2
elif
((
L
==
None
)
and
(
meth
==
"C30"
or
meth
==
"C35"
or
meth
==
"C40"
)):
L
=
3
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
# ---------------------------------------------------------------------
def
get_skin
(
sst
,
qsea
,
rho
,
Rl
,
Rs
,
Rnl
,
cp
,
lv
,
tkt
,
usr
,
tsr
,
qsr
,
lat
):
""" Computes cool skin
...
...
@@ -779,7 +643,7 @@ def get_gust(beta, Ta, usr, tsrv, zi, lat):
def
get_L
(
L
,
lat
,
usr
,
tsr
,
qsr
,
t10n
,
tv10n
,
qair
,
h_in
,
T
,
Ta
,
th
,
tv
,
sst
,
dt
,
d
q
,
wind
,
monob
,
meth
):
dt
,
d
tv
,
dq
,
zo
,
wind
,
monob
,
meth
):
"""
calculates Monin-Obukhov length and virtual star temperature
...
...
@@ -843,8 +707,13 @@ def get_L(L, lat, usr, tsr, qsr, t10n, tv10n, qair, h_in, T, Ta, th, tv, sst,
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
))
#
monob = ((tv*np.power(usr, 2))/(kappa*g*tsrv))
elif
(
L
==
2
):
tsrv
=
tsr
+
0.61
*
t10n
*
qsr
Rb
=
((
g
*
h_in
[
0
]
*
((
2
*
dt
)
/
(
Ta
+
sst
-
g
*
h_in
[
0
])
+
0.61
*
dq
))
/
...
...
@@ -867,64 +736,6 @@ def get_L(L, lat, usr, tsr, qsr, t10n, tv10n, qair, h_in, T, Ta, th, tv, sst,
#------------------------------------------------------------------------------
def
get_hum
(
hum
,
T
,
sst
,
P
,
qmeth
):
"""
Get specific humidity output
Parameters
----------
hum : array
humidity input switch 2x1 [x, values] default is relative humidity
x='rh' : relative humidity in %
x='q' : specific humidity (g/kg)
x='Td' : dew point temperature (K)
T : float
air temperature in K
sst : float
sea surface temperature in K
P : float
air pressure at sea level in hPa
qmeth : str
method to calculate specific humidity from vapor pressure
Returns
-------
qair : float
specific humidity of air
qsea : float
specific humidity over sea surface
"""
if
(
hum
==
None
):
RH
=
np
.
ones
(
sst
.
shape
)
*
80
qsea
=
qsat_sea
(
sst
,
P
,
qmeth
)
/
1000
# surface water q (g/kg)
qair
=
qsat_air
(
T
,
P
,
RH
,
qmeth
)
/
1000
# q of air (g/kg)
elif
(
hum
[
0
]
not
in
[
'rh'
,
'q'
,
'Td'
]):
sys
.
exit
(
"unknown humidity input"
)
qair
,
qsea
=
np
.
nan
,
np
.
nan
elif
(
hum
[
0
]
==
'rh'
):
RH
=
hum
[
1
]
if
(
np
.
all
(
RH
<
1
)):
sys
.
exit
(
"input relative humidity units should be \%"
)
qair
,
qsea
=
np
.
nan
,
np
.
nan
qsea
=
qsat_sea
(
sst
,
P
,
qmeth
)
/
1000
# surface water q (g/kg)
qair
=
qsat_air
(
T
,
P
,
RH
,
qmeth
)
/
1000
# q of air (g/kg)
elif
(
hum
[
0
]
==
'q'
):
qair
=
hum
[
1
]
qsea
=
qsat_sea
(
sst
,
P
,
qmeth
)
/
1000
# surface water q (g/kg)
elif
(
hum
[
0
]
==
'Td'
):
Td
=
hum
[
1
]
# dew point temperature (K)
Td
=
np
.
where
(
Td
<
200
,
np
.
copy
(
Td
)
+
CtoK
,
np
.
copy
(
Td
))
T
=
np
.
where
(
T
<
200
,
np
.
copy
(
T
)
+
CtoK
,
np
.
copy
(
T
))
esd
=
611.21
*
np
.
exp
(
17.502
*
((
Td
-
273.16
)
/
(
Td
-
32.19
)))
es
=
611.21
*
np
.
exp
(
17.502
*
((
T
-
273.16
)
/
(
T
-
32.19
)))
RH
=
100
*
esd
/
es
qair
=
qsat_air
(
T
,
P
,
RH
,
qmeth
)
/
1000
# q of air (g/kg)
qsea
=
qsat_sea
(
sst
,
P
,
qmeth
)
/
1000
# surface water q (g/kg)
return
qair
,
qsea
#-------------------------------------------------------------------------
def
get_strs
(
h_in
,
monob
,
wind
,
zo
,
zot
,
zoq
,
dt
,
dq
,
dter
,
dqer
,
ct
,
cq
,
cskin
,
meth
):
"""
...
...
@@ -951,7 +762,7 @@ def get_strs(h_in, monob, wind, zo, zot, zoq, dt, dq, dter, dqer, ct, cq,
dter : float
cskin temperature adjustment (K)
dqer : float
cskin q adjustment (
q
/kg)
cskin q adjustment (
g
/kg)
ct : float
temperature exchange coefficient
cq : float
...
...
@@ -1033,147 +844,4 @@ def get_strs(h_in, monob, wind, zo, zot, zoq, dt, dq, dter, dqer, ct, cq,
tsr
=
ct
*
wind
*
(
dt
+
dter
*
cskin
)
/
usr
qsr
=
cq
*
wind
*
(
dq
+
dqer
*
cskin
)
/
usr
return
usr
,
tsr
,
qsr
#------------------------------------------------------------------------------
def
get_heights
(
h
,
dim_len
):
""" Reads input heights for velocity, temperature and humidity
Parameters
----------
h : float
input heights (m)
dim_len : int
length dimension
Returns
-------
hh : array
"""
hh
=
np
.
zeros
((
3
,
dim_len
))
if
(
type
(
h
)
==
float
or
type
(
h
)
==
int
):
hh
[
0
,
:],
hh
[
1
,
:],
hh
[
2
,
:]
=
h
,
h
,
h
elif
(
len
(
h
)
==
2
and
np
.
ndim
(
h
)
==
1
):
hh
[
0
,
:],
hh
[
1
,
:],
hh
[
2
,
:]
=
h
[
0
],
h
[
1
],
h
[
1
]
elif
(
len
(
h
)
==
3
and
np
.
ndim
(
h
)
==
1
):
hh
[
0
,
:],
hh
[
1
,
:],
hh
[
2
,
:]
=
h
[
0
],
h
[
1
],
h
[
2
]
elif
(
len
(
h
)
==
1
and
np
.
ndim
(
h
)
==
2
):
hh
=
np
.
zeros
((
3
,
h
.
shape
[
1
]))
hh
[
0
,
:],
hh
[
1
,
:],
hh
[
2
,
:]
=
h
[
0
,
:],
h
[
0
,
:],
h
[
0
,
:]
elif
(
len
(
h
)
==
2
and
np
.
ndim
(
h
)
==
2
):
hh
=
np
.
zeros
((
3
,
h
.
shape
[
1
]))
hh
[
0
,
:],
hh
[
1
,
:],
hh
[
2
,
:]
=
h
[
0
,
:],
h
[
1
,
:],
h
[
1
,
:]
elif
(
len
(
h
)
==
3
and
np
.
ndim
(
h
)
==
2
):
hh
=
np
.
zeros
((
3
,
h
.
shape
[
1
]))
hh
=
np
.
copy
(
h
)
return
hh
# ---------------------------------------------------------------------
def
qsat_sea
(
T
,
P
,
qmeth
):
""" Computes surface saturation specific humidity (g/kg)
Parameters
----------
T : float
temperature ($^
\\
circ$
\\
,C)
P : float
pressure (mb)
qmeth : str
method to calculate vapor pressure
Returns
-------
qs : float
"""
T
=
np
.
asarray
(
T
)
if
(
np
.
nanmin
(
T
)
>
200
):
# if Ta in Kelvin convert to Celsius
T
=
T
-
CtoK
ex
=
VaporPressure
(
T
,
P
,
'liquid'
,
qmeth
)
es
=
0.98
*
ex
# reduction at sea surface
qs
=
622
*
es
/
(
P
-
0.378
*
es
)
return
qs
# ------------------------------------------------------------------------------
def
qsat_air
(
T
,
P
,
rh
,
qmeth
):
""" Computes saturation specific humidity (g/kg) as in C35
Parameters
----------
T : float
temperature ($^\circ$\,C)
P : float
pressure (mb)
rh : float
relative humidity (%)
qmeth : str
method to calculate vapor pressure
Returns
-------
q : float
em : float
"""
T
=
np
.
asarray
(
T
)
if
(
np
.
nanmin
(
T
)
>
200
):
# if Ta in Kelvin convert to Celsius
T
=
T
-
CtoK
es
=
VaporPressure
(
T
,
P
,
'liquid'
,
qmeth
)
em
=
0.01
*
rh
*
es
q
=
622
*
em
/
(
P
-
0.378
*
em
)
return
q
# ---------------------------------------------------------------------
def
gc
(
lat
,
lon
=
None
):
""" Computes gravity relative to latitude
Parameters
----------
lat : float
latitude ($^\circ$)
lon : float
longitude ($^\circ$, optional)
Returns
-------
gc : float
gravity constant (m/s^2)
"""
gamma
=
9.7803267715
c1
=
0.0052790414
c2
=
0.0000232718
c3
=
0.0000001262
c4
=
0.0000000007
if
lon
is
not
None
:
lon_m
,
lat_m
=
np
.
meshgrid
(
lon
,
lat
)
else
:
lat_m
=
lat
phi
=
lat_m
*
np
.
pi
/
180.
xx
=
np
.
sin
(
phi
)
gc
=
(
gamma
*
(
1
+
c1
*
np
.
power
(
xx
,
2
)
+
c2
*
np
.
power
(
xx
,
4
)
+
c3
*
np
.
power
(
xx
,
6
)
+
c4
*
np
.
power
(
xx
,
8
)))
return
gc
# ---------------------------------------------------------------------
def
visc_air
(
T
):
""" Computes the kinematic viscosity of dry air as a function of air temp.
following Andreas (1989), CRREL Report 89-11.
Parameters
----------
Ta : float
air temperature ($^\circ$\,C)
Returns
-------
visa : float
kinematic viscosity (m^2/s)
"""
T
=
np
.
asarray
(
T
)
if
(
np
.
nanmin
(
T
)
>
200
):
# if Ta in Kelvin convert to Celsius
T
=
T
-
273.16
visa
=
1.326e-5
*
(
1
+
6.542e-3
*
T
+
8.301e-6
*
np
.
power
(
T
,
2
)
-
4.84e-9
*
np
.
power
(
T
,
3
))
return
visa
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