Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
CryoGrid.jl
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
CryoGrid
CryoGrid.jl
Commits
e3208bb3
Commit
e3208bb3
authored
2 years ago
by
Jan Nitzbon
Committed by
Brian Groenke
2 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Add new surface energy balance parameterizations
parent
dbd55040
No related branches found
No related tags found
1 merge request
!34
Add new surface energy balance parameterizations
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
examples/heat_vgfc_seb_samoylov_custom.jl
+12
-19
12 additions, 19 deletions
examples/heat_vgfc_seb_samoylov_custom.jl
src/Physics/SEB/SEB.jl
+64
-16
64 additions, 16 deletions
src/Physics/SEB/SEB.jl
src/Physics/SEB/seb_heat.jl
+128
-36
128 additions, 36 deletions
src/Physics/SEB/seb_heat.jl
with
204 additions
and
71 deletions
examples/heat_vgfc_seb_samoylov_custom.jl
+
12
−
19
View file @
e3208bb3
...
...
@@ -12,17 +12,9 @@ soilprofile = SoilProfile(
0.4
u
"m"
=>
soilparameters
(
xic
=
0.30
,
por
=
0.55
,
sat
=
1.0
,
org
=
0.25
),
#(θwi=0.80,θm=0.15,θo=0.05,ϕ=0.55),
3.0
u
"m"
=>
soilparameters
(
xic
=
0.0
,
por
=
0.50
,
sat
=
1.0
,
org
=
0.0
),
#(θwi=0.50,θm=0.50,θo=0.0,ϕ=0.50),
10.0
u
"m"
=>
soilparameters
(
xic
=
0.0
,
por
=
0.30
,
sat
=
1.0
,
org
=
0.0
),
#(θwi=0.30,θm=0.70,θo=0.0,ϕ=0.30),
)
,
)
;
# mid-winter temperature profile
tempprofile
=
TemperatureProfile
(
0.01
u
"m"
=>
-
15.9
u
"°C"
,
0.05
u
"m"
=>
-
15.49
u
"°C"
,
0.10
u
"m"
=>
-
15.32
u
"°C"
,
0.20
u
"m"
=>
-
14.44
u
"°C"
,
0.30
u
"m"
=>
-
14.18
u
"°C"
,
0.40
u
"m"
=>
-
13.50
u
"°C"
,
1000.0
u
"m"
=>
10.2
u
"°C"
,
)
tempprofile
=
CryoGrid
.
Presets
.
SamoylovDefault
.
tempprofile
forcings
=
loadforcings
(
CryoGrid
.
Presets
.
Forcings
.
Samoylov_ERA_obs_fitted_1979_2014_spinup_extended_2044
,
:
Tair
=>
u
"°C"
);
Tair
=
TimeSeriesForcing
(
ustrip
.
(
forcings
.
data
.
Tair
),
forcings
.
timestamps
,
:
Tair
);
# assume other forcings don't (yet) have units
...
...
@@ -36,22 +28,23 @@ tspan = (DateTime(2010,1,1), DateTime(2011,1,1))
soilprofile
,
tempprofile
=
CryoGrid
.
Presets
.
SamoylovDefault
initT
=
initializer
(
:
T
,
tempprofile
)
strat
=
Stratigraphy
(
-
2.0
u
"m"
=>
top
(
SurfaceEnergyBalance
(
Tair
,
pr
,
q
,
wind
,
Lin
,
Sin
,
z
)),
Tuple
(
z
=>
subsurface
(
:
soil
1
,
Soil
(
para
=
para
),
Heat
(
:
H
,
freezecurve
=
SFCC
(
DallAmico
())))
for
(
z
,
para
)
in
soilprofile
),
-
z
*
u
"m"
=>
top
(
SurfaceEnergyBalance
(
Tair
,
pr
,
q
,
wind
,
Lin
,
Sin
,
z
,
solscheme
=
Analytical
(),
stabfun
=
Businger
()
)),
Tuple
(
knot
.
depth
=>
subsurface
(
Symbol
(
:
soil
,
i
)
,
Soil
(
para
=
knot
.
value
),
Heat
(
:
H
,
freezecurve
=
SFCC
(
DallAmico
())))
for
(
i
,
knot
)
in
enumerate
(
soilprofile
)
)
,
1000.0
u
"m"
=>
bottom
(
GeothermalHeatFlux
(
0.053
u
"J/s/m^2"
)),
);
grid
=
Grid
(
gridvals
);
model
=
Tile
(
strat
,
grid
,
initT
);
tile
=
Tile
(
strat
,
grid
,
initT
);
# define time span
tspan
=
(
DateTime
(
2010
,
10
,
30
),
DateTime
(
2011
,
10
,
30
))
p
=
parameters
(
model
)
u0
,
du0
=
initialcondition!
(
model
,
tspan
,
p
)
p
=
parameters
(
tile
)
u0
,
du0
=
initialcondition!
(
tile
,
tspan
,
p
)
# CryoGrid front-end for ODEProblem
prob
=
CryoGridProblem
(
model
,
u0
,
tspan
,
p
,
savevars
=
(
:
T
,))
prob
=
CryoGridProblem
(
tile
,
u0
,
tspan
,
p
,
step_limiter
=
nothing
,
savevars
=
(
:
T
,))
# solve with forward Euler (w/ CFL) and construct CryoGridOutput from solution
out
=
@time
solve
(
prob
,
Euler
(),
dt
=
2
*
60.0
,
saveat
=
24
*
3600.0
,
progress
=
true
)
|>
CryoGridOutput
;
# Plot it!
zs
=
[
1
:
10.
..
,
20
:
10
:
100.
..
]
zs
=
[
1
,
5
,
10
,
15
,
20
:
10
:
100.
..
]
cg
=
Plots
.
cgrad
(
:
copper
,
rev
=
true
);
plot
(
out
.
H
[
Z
(
zs
)],
color
=
cg
[
LinRange
(
0.0
,
1.0
,
length
(
zs
))]
'
,
ylabel
=
"Enthalpy"
,
leg
=
false
,
dpi
=
150
)
plot
(
out
.
T
[
Z
(
zs
)],
color
=
cg
[
LinRange
(
0.0
,
1.0
,
length
(
zs
))]
'
,
ylabel
=
"Temperature"
,
leg
=
false
,
size
=
(
800
,
500
),
dpi
=
150
)
plot
(
ustrip
.
(
out
.
H
[
Z
(
zs
)]),
color
=
cg
[
LinRange
(
0.0
,
1.0
,
length
(
zs
))]
'
,
ylabel
=
"Enthalpy"
,
leg
=
false
,
dpi
=
150
)
plot
(
ustrip
.
(
out
.
T
[
Z
(
zs
)]),
color
=
cg
[
LinRange
(
0.0
,
1.0
,
length
(
zs
))]
'
,
ylabel
=
"Temperature"
,
leg
=
false
,
size
=
(
800
,
500
),
dpi
=
150
)
This diff is collapsed.
Click to expand it.
src/Physics/SEB/SEB.jl
+
64
−
16
View file @
e3208bb3
module
SEB
using
..
HeatConduction
:
Heat
using
..
Physics
using
..
Boundaries
using
CryoGrid
.
InputOutput
:
Forcing
using
CryoGrid
.
Physics
using
CryoGrid
.
Physics
.
Boundaries
using
CryoGrid
.
Physics
.
HeatConduction
using
CryoGrid
.
Physics
.
Soils
using
CryoGrid
.
Numerics
using
CryoGrid
.
Utils
import
CryoGrid
:
BoundaryProcess
,
BoundaryStyle
,
Neumann
,
Top
import
CryoGrid
:
initialcondition!
,
variables
import
CryoGrid
:
initialcondition!
,
variables
,
boundaryvalue
using
Unitful
Base
.
@kwdef
struct
SEBParams
<:
IterableStruct
export
SurfaceEnergyBalance
,
SEBParams
export
Businger
,
HøgstrømSHEBA
,
Iterative
,
Analytical
,
Numerical
abstract type
SolutionScheme
end
"""
Byun 1990
"""
struct
Analytical
<:
SolutionScheme
end
"""
equation by Westermann2016, but use Newton solver
- not implemented yet
"""
struct
Numerical
<:
SolutionScheme
end
"""
Westermann2016, use info from last time step
"""
struct
Iterative
<:
SolutionScheme
end
abstract type
StabilityFunctions
end
"""
Businger 1971
"""
struct
Businger
<:
StabilityFunctions
end
"""
Høgstrøm 1988 (unstable conditions)
SHEBA, Uttal et al., 2002, Grachev et al. 2007 (stable conditions)
"""
struct
HøgstrømSHEBA
<:
StabilityFunctions
end
Base
.
@kwdef
struct
SEBParams
{
TSolution
,
TStabFun
}
# surface properties --> should be associated with the Stratigraphy and maybe made state variables
α
::
Float
"1"
=
0.2
xu
"1"
# surface albedo [-]
ϵ
::
Float
"1"
=
0.97
xu
"1"
# surface emissivity [-]
...
...
@@ -30,28 +63,43 @@ Base.@kwdef struct SEBParams <: IterableStruct
# material properties (assumed to be constant)
ρₐ
::
Float
"kg/m^3"
=
1.293
xu
"kg/m^3"
# density of air at standard pressure and 0°C [kg/m^3]
cₐ
::
Float
"J/(m^3*K)"
=
1005.7
xu
"J/(kg*K)"
*
ρₐ
# volumetric heat capacity of dry air at standard pressure and 0°C [J/(m^3*K)]
Pr₀
::
Float64
=
0.74
# turbulent Prandtl number
βₘ
::
Float64
=
4.7
βₕ
::
Float64
=
βₘ
/
Pr₀
γₘ
::
Float64
=
15.0
γₕ
::
Float64
=
9.0
# type-dependent parameters
solscheme
::
TSolution
=
Iterative
()
stabfun
::
TStabFun
=
HøgstrømSHEBA
()
end
struct
SurfaceEnergyBalance
{
F
}
<:
BoundaryProcess
{
Heat
}
forcing
::
F
sebparams
::
SEBParams
"""
SurfaceEnergyBalance{TSolution,TStabFun,F} <: BoundaryProcess{Heat}
Surface energy balance upper boundary condition.
"""
struct
SurfaceEnergyBalance
{
TSolution
,
TStabFun
,
F
}
<:
BoundaryProcess
{
Heat
}
forcings
::
F
sebparams
::
SEBParams
{
TSolution
,
TStabFun
}
SurfaceEnergyBalance
(
forcings
::
NamedTuple
,
sebparams
::
SEBParams
)
=
new
{
typeof
(
sebparams
.
solscheme
),
typeof
(
sebparams
.
stabfun
),
typeof
(
forcings
)}(
forcings
,
sebparams
)
function
SurfaceEnergyBalance
(
Tair
::
Forcing
,
Tair
::
Forcing
{
Float
"°C"
}
,
p
::
Forcing
,
q
::
Forcing
,
wind
::
Forcing
,
Lin
::
Forcing
,
Sin
::
Forcing
,
z
::
Float
"m"
,
params
::
SEBParams
=
SEBParams
()
z
::
Float
"m"
;
kwargs
...
)
forcing
=
(
Tair
=
Tair
,
p
=
p
,
q
=
q
,
wind
=
wind
,
Lin
=
Lin
,
Sin
=
Sin
,
z
=
z
);
new
{
typeof
(
forcing
)}(
forcing
,
params
)
forcings
=
(
Tair
=
Tair
,
p
=
p
,
q
=
q
,
wind
=
wind
,
Lin
=
Lin
,
Sin
=
Sin
,
z
=
z
);
sebparams
=
SEBParams
(;
kwargs
...
);
new
{
typeof
(
sebparams
.
solscheme
),
typeof
(
sebparams
.
stabfun
),
typeof
(
forcings
)}(
forcings
,
sebparams
)
end
end
BoundaryStyle
(
::
Type
{
<:
SurfaceEnergyBalance
})
=
Neumann
()
include
(
"seb_heat.jl"
)
end
\ No newline at end of file
end
This diff is collapsed.
Click to expand it.
src/Physics/SEB/seb_heat.jl
+
128
−
36
View file @
e3208bb3
...
...
@@ -20,33 +20,35 @@ function initialcondition!(top::Top, seb::SurfaceEnergyBalance, state)
@setscalar
state
.
ustar
=
10.
;
end
BoundaryStyle
(
::
Type
{
<:
SurfaceEnergyBalance
})
=
Neumann
()
"""
Top interaction, ground heat flux from surface energy balance. (no snow, no water body, no infiltration)
"""
function
(
seb
::
SurfaceEnergyBalance
)(
top
::
Top
,
soil
::
Soil
,
heat
::
Heat
,
stop
,
ssoil
)
function
boundaryvalue
(
seb
::
SurfaceEnergyBalance
,
::
Top
,
::
Heat
,
::
Soil
,
stop
,
ssoil
)
# TODO (optimize): pre-compute all forcings at time t here, then pass to functions
# 1. calculate radiation budget
# outgoing shortwave radiation as reflected
@setscalar
stop
.
Sout
=
let
α
=
seb
.
sebparams
.
α
,
Sin
=
seb
.
forcing
.
Sin
(
stop
.
t
);
-
α
*
Sin
# Eq. (2) in Westermann et al. (2016)
@setscalar
stop
.
Sout
=
let
α
=
seb
.
sebparams
.
α
,
Sin
=
seb
.
forcing
s
.
Sin
(
stop
.
t
);
-
α
*
Sin
# Eq. (2) in Westermann et al. (2016)
end
# outgoing longwave radiation composed of emitted and reflected radiation
@setscalar
stop
.
Lout
=
let
ϵ
=
seb
.
sebparams
.
ϵ
,
σ
=
seb
.
sebparams
.
σ
,
T₀
=
ssoil
.
T
[
1
],
Lin
=
seb
.
forcing
.
Lin
(
stop
.
t
);
-
ϵ
*
σ
*
T₀
^
4
-
(
1
-
ϵ
)
*
Lin
# Eq. (3) in Westermann et al. (2016)
@setscalar
stop
.
Lout
=
let
ϵ
=
seb
.
sebparams
.
ϵ
,
σ
=
seb
.
sebparams
.
σ
,
T₀
=
ssoil
.
T
[
1
],
Lin
=
seb
.
forcing
s
.
Lin
(
stop
.
t
);
-
ϵ
*
σ
*
normalize_temperature
(
T₀
)
^
4
-
(
1
-
ϵ
)
*
Lin
# Eq. (3) in Westermann et al. (2016)
end
# net radiation budget
@setscalar
stop
.
Qnet
=
let
Sin
=
seb
.
forcing
.
Sin
(
stop
.
t
),
Lin
=
seb
.
forcing
.
Lin
(
stop
.
t
),
Sout
=
getscalar
(
stop
.
Sout
),
Lout
=
getscalar
(
stop
.
Lout
);
@setscalar
stop
.
Qnet
=
let
Sin
=
seb
.
forcing
s
.
Sin
(
stop
.
t
),
Lin
=
seb
.
forcing
s
.
Lin
(
stop
.
t
),
Sout
=
getscalar
(
stop
.
Sout
),
Lout
=
getscalar
(
stop
.
Lout
);
Sin
+
Sout
+
Lin
+
Lout
end
# 2. calcuate turbulent heat flux budget
# determine atmospheric stability conditions
@setscalar
stop
.
ustar
=
ustar
(
seb
,
stop
);
@setscalar
stop
.
Lstar
=
Lstar
(
seb
,
stop
,
ssoil
);
@setscalar
stop
.
ustar
=
ustar
(
seb
,
stop
);
# sensible heat flux
@setscalar
stop
.
Qh
=
Q_H
(
seb
,
stop
,
ssoil
);
...
...
@@ -66,15 +68,12 @@ end
"""
Density of air at given tempeature and pressure
"""
density_air
(
seb
::
SurfaceEnergyBalance
,
T
::
Real
"°C"
,
p
::
Real
"Pa"
)
=
p
/
(
T
*
seb
.
sebparams
.
Rₐ
);
density_air
(
seb
::
SurfaceEnergyBalance
,
T
::
Real
"°C"
,
p
::
Real
"Pa"
)
=
p
/
(
normalize_temperature
(
T
)
*
seb
.
sebparams
.
Rₐ
);
"""
Saturation pressure of water/ice according to the empirical August-Roche-Magnus formula
Note: T is passed [K] and converted to [°C]
"""
estar
(
T
::
Real
"°C"
)
=
(
(
T
>
0
)
?
611.2
*
exp
(
17.62
*
T
/
(
243.12
+
T
))
# Eq. (B3) in Westermann et al. (2016)
:
611.2
*
exp
(
22.46
*
T
/
(
272.62
+
T
))
;
)
estar
(
T
::
Real
"°C"
)
=
(
T
>
0
)
?
611.2
*
exp
(
17.62
*
T
/
(
243.12
+
T
))
:
611.2
*
exp
(
22.46
*
T
/
(
272.62
+
T
));
# Eq. (B3) in Westermann et al. (2016)
"""
Latent heat of evaporation/condensation of water in [J/kg]
...
...
@@ -93,30 +92,88 @@ Friction velocity according to Monin-Obukhov theory
"""
function
ustar
(
seb
::
SurfaceEnergyBalance
,
stop
)
let
κ
=
seb
.
sebparams
.
κ
,
uz
=
seb
.
forcing
.
wind
(
stop
.
t
),
# wind speed at height z
z
=
seb
.
forcing
.
z
,
# height z of wind forcing
uz
=
seb
.
forcing
s
.
wind
(
stop
.
t
),
# wind speed at height z
z
=
seb
.
forcing
s
.
z
,
# height z of wind forcing
z₀
=
seb
.
sebparams
.
z₀
,
# aerodynamic roughness length [m]
Lstar
=
stop
.
Lstar
|>
getscalar
;
κ
*
uz
./
(
log
(
z
/
z₀
)
-
Ψ_M
(
z
/
Lstar
,
z₀
/
Lstar
))
# Eq. (7) in Westermann et al. (2016)
κ
*
uz
./
(
log
(
z
/
z₀
)
-
Ψ_M
(
seb
,
z
/
Lstar
,
z₀
/
Lstar
))
# Eq. (7) in Westermann et al. (2016)
end
end
"""
Obukhov length according to Monin-Obukhov theory
Obukhov length according to Monin-Obukhov theory, iterative determination as in CryoGrid3 / Westermann et al. 2016
- uses the turubulent fluxes Qe and Qh as well as the friction velocity of the previous time step
"""
function
Lstar
(
seb
::
SurfaceEnergyBalance
,
stop
,
ssoil
)
function
Lstar
(
seb
::
SurfaceEnergyBalance
{
Iterative
}
,
stop
,
ssoil
)
res
=
let
κ
=
seb
.
sebparams
.
κ
,
g
=
seb
.
sebparams
.
g
,
Rₐ
=
seb
.
sebparams
.
Rₐ
,
cₚ
=
seb
.
sebparams
.
cₐ
/
seb
.
sebparams
.
ρₐ
,
# specific heat capacity of air at constant pressure
Tₕ
=
seb
.
forcing
.
Tair
(
stop
.
t
),
# air temperature at height z over surface
p
=
seb
.
forcing
.
p
(
stop
.
t
),
# atmospheric pressure at surface
Tair
=
seb
.
forcings
.
Tair
(
stop
.
t
),
Tₕ
=
normalize_temperature
(
Tair
),
# air temperature at height z over surface
p
=
seb
.
forcings
.
p
(
stop
.
t
),
# atmospheric pressure at surface
ustar
=
stop
.
ustar
|>
getscalar
,
Qₑ
=
stop
.
Qe
|>
getscalar
,
Qₕ
=
stop
.
Qh
|>
getscalar
,
Llg
=
L_lg
(
ssoil
.
T
[
1
]),
ρₐ
=
density_air
(
seb
,
Tₕ
,
p
);
# density of air at surface air temperature and surface pressure [kg/m^3]
-
ρₐ
*
cₚ
*
Tₕ
/
(
κ
*
g
)
*
ustar
^
3
/
(
Qₕ
+
0.61
*
cₚ
/
Llg
*
Tₕ
*
Qₑ
)
# Eq. (8) in Westermann et al. (2016)
ρₐ
=
density_air
(
seb
,
Tair
,
p
);
# density of air at surface air temperature and surface pressure [kg/m^3]
-
ρₐ
*
cₚ
*
Tₕ
/
(
κ
*
g
)
*
ustar
^
3
/
(
Qₕ
+
0.61
*
cₚ
/
Llg
*
Tₕ
*
Qₑ
)
# Eq. (8) in Westermann et al. (2016)
end
# upper and lower limits for Lstar
res
=
(
abs
(
res
)
<
1e-7
)
?
sign
(
res
)
*
1e-7
:
res
res
=
(
abs
(
res
)
>
1e+7
)
?
sign
(
res
)
*
1e+7
:
res
end
"""
Obukhov length, analytical solution of Monin-Obukhov theory according to Byun 1990
- implicitly assumes the Businger 1971 stability functions
- only uses the current surface temperature as input
"""
function
Lstar
(
seb
::
SurfaceEnergyBalance
{
Analytical
},
stop
,
ssoil
)
res
=
let
g
=
seb
.
sebparams
.
g
,
Rₐ
=
seb
.
sebparams
.
Rₐ
,
cₚ
=
seb
.
sebparams
.
cₐ
/
seb
.
sebparams
.
ρₐ
,
# specific heat capacity of air at constant pressure
Tₕ
=
normalize_temperature
(
seb
.
forcings
.
Tair
(
stop
.
t
)),
# air temperature at height z over surface
T₀
=
normalize_temperature
(
ssoil
.
T
[
1
]),
# surface temperature
p
=
seb
.
forcings
.
p
(
stop
.
t
),
# atmospheric pressure at surface (height z)
p₀
=
seb
.
forcings
.
p
(
stop
.
t
),
# normal pressure (for now assumed to be equal to p)
uz
=
seb
.
forcings
.
wind
(
stop
.
t
),
# wind speed at height z
z
=
seb
.
forcings
.
z
,
# height z of wind forcing
z₀
=
seb
.
sebparams
.
z₀
,
# aerodynamic roughness length [m]
Pr₀
=
seb
.
sebparams
.
Pr₀
,
# turbulent Prandtl number
γₕ
=
seb
.
sebparams
.
γₕ
,
γₘ
=
seb
.
sebparams
.
γₘ
,
βₕ
=
seb
.
sebparams
.
βₕ
,
βₘ
=
seb
.
sebparams
.
βₘ
;
Θₕ
=
Tₕ
*
(
p₀
/
p
)
^
(
Rₐ
/
cₚ
);
# potential temperature (for now identical to actual temperature)
Θ₀
=
T₀
*
(
p₀
/
p
)
^
(
Rₐ
/
cₚ
);
# calcuate bulk Richardson number
Ri_b
=
g
/
Θ₀
*
(
Θₕ
-
Θ₀
)
*
(
z
-
z₀
)
/
uz
^
2
;
# bulk Richardson number, eq. (9) in Byun 1990
# calulate ζ
a
=
(
z
/
(
z
-
z₀
))
*
log
(
z
/
z₀
);
if
Ri_b
>
0
# stable conditions
b
=
2
*
βₕ
*
(
βₘ
*
Ri_b
-
1
);
c
=
-
(
2
*
βₕ
*
Ri_b
-
1
)
-
(
1
+
(
4
*
(
βₕ
-
βₘ
)
*
Ri_b
)
/
Pr₀
)
^
0.5
ζ
=
a
/
b
*
c
;
# eq. (19) in Byun 1990
else
# unstable conditions
s_b
=
Ri_b
/
Pr₀
;
# eq. (30) in Byun 1990
Q_b
=
1
/
9
*
(
1
/
γₘ
^
2
+
3
*
γₕ
/
γₘ
*
s_b
^
2
);
# eq. (31) in Byun 1990
P_b
=
1
/
54
*
(
-
2
/
γₘ
^
3
+
9
/
γₘ
*
(
3
-
γₕ
/
γₘ
)
*
s_b
^
2
);
# eq. (32) in Byun 1990
θ_b
=
acos
(
P_b
/
Q_b
^
(
3
/
2
)
);
# eq. (33) in Byun 1990
T_b
=
(
(
P_b
^
2
-
Q_b
^
3
)
^
0.5
+
abs
(
P_b
)
)
^
(
1
/
3
);
# eq. (34) in Byun 1990
if
Q_b
^
3
-
P_b
^
2
>=
0
ζ
=
a
*
(
-
2
*
Q_b
^
0.5
*
cos
(
θ_b
/
3
)
+
1
/
(
3
*
γₘ
)
)
# eq. (28) in Byun 1990
else
ζ
=
a
*
(
-
(
T_b
+
Q_b
/
T_b
)
+
1
/
(
3
*
γₘ
)
);
# eq. (29) in Byun 1990
end
end
# calculate Lstar
z
/
ζ
;
end
# upper and lower limits for Lstar
res
=
(
abs
(
res
)
<
1e-7
)
?
sign
(
res
)
*
1e-7
:
res
...
...
@@ -129,17 +186,17 @@ Sensible heat flux, defined as positive if it is a flux towards the surface
function
Q_H
(
seb
::
SurfaceEnergyBalance
,
stop
,
ssoil
)
let
κ
=
seb
.
sebparams
.
κ
,
Rₐ
=
seb
.
sebparams
.
Rₐ
,
Tₕ
=
seb
.
forcing
.
Tair
(
stop
.
t
),
# air temperature
Tₕ
=
seb
.
forcing
s
.
Tair
(
stop
.
t
),
# air temperature
T₀
=
ssoil
.
T
[
1
],
# surface temperature
cₚ
=
seb
.
sebparams
.
cₐ
/
seb
.
sebparams
.
ρₐ
,
# specific heat capacity of air at constant pressure
z
=
seb
.
forcing
.
z
,
# height at which forcing data are provided
z
=
seb
.
forcing
s
.
z
,
# height at which forcing data are provided
Lstar
=
stop
.
Lstar
|>
getscalar
,
ustar
=
stop
.
ustar
|>
getscalar
,
p
=
seb
.
forcing
.
p
(
stop
.
t
),
p
=
seb
.
forcing
s
.
p
(
stop
.
t
),
z₀
=
seb
.
sebparams
.
z₀
,
ρₐ
=
density_air
(
seb
,
Tₕ
,
p
);
# density of air at surface air temperature and surface pressure [kg/m^3]
rₐᴴ
=
(
κ
*
ustar
)
^-
1
*
(
log
(
z
/
z₀
)
-
Ψ_HW
(
z
/
Lstar
,
z₀
/
Lstar
))
# Eq. (6) in Westermann et al. (2016)
rₐᴴ
=
(
κ
*
ustar
)
^-
1
*
(
log
(
z
/
z₀
)
-
Ψ_HW
(
seb
,
z
/
Lstar
,
z₀
/
Lstar
))
# Eq. (6) in Westermann et al. (2016)
# calculate Q_H
-
ρₐ
*
cₚ
*
(
Tₕ
-
T₀
)
/
rₐᴴ
# Eq. (4) in Westermann et al. (2016)
...
...
@@ -155,28 +212,28 @@ function Q_E(seb::SurfaceEnergyBalance, stop, ssoil)
let
κ
=
seb
.
sebparams
.
κ
,
γ
=
seb
.
sebparams
.
γ
,
Rₐ
=
seb
.
sebparams
.
Rₐ
,
Tₕ
=
seb
.
forcing
.
Tair
(
stop
.
t
),
# air temperature at height z over surface
Tₕ
=
seb
.
forcing
s
.
Tair
(
stop
.
t
),
# air temperature at height z over surface
T₀
=
ssoil
.
T
[
1
],
# surface temperature
p
=
seb
.
forcing
.
p
(
stop
.
t
),
# atmospheric pressure at surface
qₕ
=
seb
.
forcing
.
q
(
stop
.
t
),
# specific humidity at height h over surface
z
=
seb
.
forcing
.
z
,
# height at which forcing data are provided
p
=
seb
.
forcing
s
.
p
(
stop
.
t
),
# atmospheric pressure at surface
qₕ
=
seb
.
forcing
s
.
q
(
stop
.
t
),
# specific humidity at height h over surface
z
=
seb
.
forcing
s
.
z
,
# height at which forcing data are provided
rₛ
=
seb
.
sebparams
.
rₛ
,
# surface resistance against evapotranspiration / sublimation [1/m]
Lstar
=
stop
.
Lstar
|>
getscalar
,
ustar
=
stop
.
ustar
|>
getscalar
,
Llg
=
L_lg
(
ssoil
.
T
[
1
]),
Lsg
=
L_sg
(
ssoil
.
T
[
1
]),
z₀
=
seb
.
sebparams
.
z₀
,
# aerodynamic roughness length [m]
ρₐ
=
density_air
(
seb
,
seb
.
forcing
.
Tair
(
stop
.
t
)
,
seb
.
forcing
.
p
(
stop
.
t
));
# density of air at surface air temperature and surface pressure [kg/m^3]
ρₐ
=
density_air
(
seb
,
Tₕ
,
seb
.
forcing
s
.
p
(
stop
.
t
));
# density of air at surface air temperature and surface pressure [kg/m^3]
q₀
=
γ
*
estar
(
T₀
)
/
p
# saturation pressure of water/ice at the surface; Eq. (B1) in Westermann et al (2016)
rₐᵂ
=
(
κ
*
ustar
)
^-
1
*
(
log
(
z
/
z₀
)
-
Ψ_HW
(
z
/
Lstar
,
z₀
/
Lstar
))
# aerodynamic resistance Eq. (6) in Westermann et al. (2016)
L
=
(
T₀
<=
0.0
)
?
Lsg
:
Llg
# latent heat of sublimation/resublimation or evaporation/condensation [J/kg]
rₐᵂ
=
(
κ
*
ustar
)
^-
1
*
(
log
(
z
/
z₀
)
-
Ψ_HW
(
seb
,
z
/
Lstar
,
z₀
/
Lstar
))
# aerodynamic resistance Eq. (6) in Westermann et al. (2016)
L
=
(
T₀
<=
0.0
)
?
Lsg
:
Llg
# latent heat of sublimation/resublimation or evaporation/condensation [J/kg]
# calculate Q_E
res
=
(
qₕ
>
q₀
)
?
-
ρₐ
*
L
*
(
qₕ
-
q₀
)
/
(
rₐᵂ
)
:
# Eq. (5) in Westermann et al. (2016) # condensation / deposition (no aerodynamics resistance)
-
ρₐ
*
L
*
(
qₕ
-
q₀
)
/
(
rₐᵂ
+
rₛ
)
;
# evaporation / sublimation (account for surface resistance against evapotranspiration/sublimation)
res
=
(
T₀
<=
0.0
)
?
0
:
res
;
# for now: set sublimation and deposition to zero.
res
=
(
T₀
<=
0.0
)
?
0
:
res
;
# for now: set sublimation and deposition to zero.
end
end
...
...
@@ -185,7 +242,7 @@ Integrated stability function for heat/water transport
Högström, 1988
SHEBA, Uttal et al., 2002, Grachev et al. 2007
"""
function
Ψ_HW
(
ζ₁
::
Real
,
ζ₂
::
Real
)
function
Ψ_HW
(
seb
::
SurfaceEnergyBalance
{
T
,
HøgstrømSHEBA
},
ζ₁
::
Float64
,
ζ₂
::
Float64
)
where
T
if
ζ₁
<=
0
# neutral and unstable conditions (according to Høgstrøm, 1988)
# computed using WolframAlpha command "Integrate[ (1-(0.95*(1-11.6x)^(-1/2)))/x ] assuming x<0"
res
=
real
(
log
(
Complex
(
ζ₁
))
+
1.9
*
atanh
(
Complex
((
1
-
11.6
*
ζ₁
)
^
0.5
))
-
...
...
@@ -205,8 +262,10 @@ end
"""
Integrated stability function for momentum transport
Högström, 1988
SHEBA, Uttal et al., 2002, Grachev et al. 2007
"""
function
Ψ_M
(
ζ₁
::
Real
,
ζ₂
::
Real
)
function
Ψ_M
(
seb
::
SurfaceEnergyBalance
{
T
,
HøgstrømSHEBA
},
ζ₁
::
Float64
,
ζ₂
::
Float64
)
where
T
if
ζ₁
<=
0
# neutral and unstable conditions (according to Høgstrøm, 1988)
# computed using WolframAlpha command "Integrate[ (1-(1-19.3x)^(-1/4))/x ] assuming x<0"
# log(ζ₁) - 2*atan((1-19.3*ζ₁)^(1/4)) + 2*atanh((1-19.3*ζ₁)^(1/4)) -
...
...
@@ -230,4 +289,37 @@ function Ψ_M(ζ₁::Real, ζ₂::Real)
end
end
export
SurfaceEnergyBalance
"""
Integrated stability function for heat/water transport
Businger 1971
"""
function
Ψ_HW
(
seb
::
SurfaceEnergyBalance
{
T
,
Businger
},
ζ₁
::
Float64
,
ζ₂
::
Float64
)
where
T
let
γₕ
=
seb
.
sebparams
.
γₕ
,
βₕ
=
seb
.
sebparams
.
βₕ
;
if
ζ₁
<=
0
# neutral and unstable conditions (according to Businger, 1971)
return
2
*
log
(
(
(
1
-
γₕ
*
ζ₁
)
^
0.5
+
1
)
/
(
(
1
-
γₕ
*
ζ₂
)
^
0.5
+
1
)
);
# eq. (15) in Byun 1990
else
# stable stratification (according to Busigner, 1971)
return
-
βₕ
*
(
ζ₁
-
ζ₂
);
# eq. (13) in Byun 1990
end
end
end
"""
Integrated stability function for momentum transport
Busigner 1971
"""
function
Ψ_M
(
seb
::
SurfaceEnergyBalance
{
T
,
Businger
},
ζ₁
::
Float64
,
ζ₂
::
Float64
)
where
T
let
γₘ
=
seb
.
sebparams
.
γₘ
,
βₘ
=
seb
.
sebparams
.
βₘ
;
if
ζ₁
<=
0
# neutral and unstable conditions (according to Businger, 1971)
x
=
(
1
-
γₘ
*
ζ₁
)
^
0.25
;
x₀
=
(
1
-
γₘ
*
ζ₂
)
^
0.25
;
return
2
*
log
(
(
1
+
x
)
/
(
1
+
x₀
)
)
+
log
(
(
1
+
x
^
2
)
/
(
1
+
x₀
^
2
)
)
-
2
*
atan
(
x
)
+
2
*
atan
(
x
)
;
# eq. (14) in Byun 1990
else
# stable stratification (according to Busigner, 1971)
return
-
βₘ
*
(
ζ₁
-
ζ₂
);
# eq. (12) in Byun 1990
end
end
end
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment