Skip to content

Commit 31ed3b3

Browse files
Merge branch 'mpaiao-pr-elm_outvars' into next (PR #7328)
This pull request expands the list of variables in the ELM output, and most changes were taken from CLM5. This adds aerodynamic resistances, friction velocity, and canopy air properties to the ELM output (temperature, humidity, wind speed) to the history file. These are helpful for assessing the model representation of turbulent fluxes. All new variables are set as "inactive" by default. The pull request has two very minor additional edits: Also borrowed from CLM5, this replaces the indices 1 and 2 for the resistances with local variables "above_canopy" and "below_canopy". This change is simply to improve code readability. Revised the comments and variable output names for variable obu. I simply replaced "Monin-Obukhov length" with "Obukhov length", which is the correct name of the variable according to the American Meteorological Society. [BFB]
2 parents 04947fc + ef056b4 commit 31ed3b3

File tree

7 files changed

+156
-37
lines changed

7 files changed

+156
-37
lines changed

components/elm/src/biogeophys/BareGroundFluxesMod.F90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ subroutine BareGroundFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
8787
real(r8) :: dth(bounds%begp:bounds%endp) ! diff of virtual temp. between ref. height and surface
8888
real(r8) :: dthv ! diff of vir. poten. temp. between ref. height and surface
8989
real(r8) :: dqh(bounds%begp:bounds%endp) ! diff of humidity between ref. height and surface
90-
real(r8) :: obu(bounds%begp:bounds%endp) ! Monin-Obukhov length (m)
90+
real(r8) :: obu(bounds%begp:bounds%endp) ! Obukhov length scale (m)
9191
real(r8) :: ur(bounds%begp:bounds%endp) ! wind speed at reference height [m/s]
9292
real(r8) :: um(bounds%begp:bounds%endp) ! wind speed including the stablity effect [m/s]
9393
real(r8) :: temp1(bounds%begp:bounds%endp) ! relation for potential temperature profile
@@ -250,7 +250,7 @@ subroutine BareGroundFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
250250
z0hg_patch(p) = z0hg_col(c)
251251
z0qg_patch(p) = z0qg_col(c)
252252

253-
! Initialize Monin-Obukhov length and wind speed
253+
! Initialize Obukhov length scale and wind speed
254254

255255
call MoninObukIni(ur(p), thv(c), dthv, zldis(p), z0mg_patch(p), um(p), obu(p))
256256
num_iter(p) = 0._r8

components/elm/src/biogeophys/CanopyFluxesMod.F90

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ module CanopyFluxesMod
1717
use elm_varctl , only : use_hydrstress
1818
use elm_varpar , only : nlevgrnd, nlevsno
1919
use elm_varcon , only : namep
20+
use elm_varcon , only : mm_epsilon
21+
use elm_varcon , only : pa_to_kpa
2022
use pftvarcon , only : crop, nfixer
2123
use decompMod , only : bounds_type
2224
use PhotosynthesisMod , only : Photosynthesis, PhotosynthesisTotal, Fractionation, PhotoSynthesisHydraulicStress
@@ -168,21 +170,16 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
168170
real(r8), parameter :: ria = 0.5_r8 ! free parameter for stable formulation (currently = 0.5, "gamma" in Sakaguchi&Zeng,2008)
169171

170172
real(r8) :: zldis(bounds%begp:bounds%endp) ! reference height "minus" zero displacement height [m]
171-
real(r8) :: zeta ! dimensionless height used in Monin-Obukhov theory
172173
real(r8) :: wc ! convective velocity [m/s]
173174
real(r8) :: ugust_total(bounds%begp:bounds%endp) ! gustiness including convective velocity [m/s]
174175
real(r8) :: dth(bounds%begp:bounds%endp) ! diff of virtual temp. between ref. height and surface
175176
real(r8) :: dthv(bounds%begp:bounds%endp) ! diff of vir. poten. temp. between ref. height and surface
176177
real(r8) :: dqh(bounds%begp:bounds%endp) ! diff of humidity between ref. height and surface
177-
real(r8) :: obu(bounds%begp:bounds%endp) ! Monin-Obukhov length (m)
178-
real(r8) :: um(bounds%begp:bounds%endp) ! wind speed including the stablity effect [m/s]
179178
real(r8) :: ur(bounds%begp:bounds%endp) ! wind speed at reference height [m/s]
180-
real(r8) :: uaf(bounds%begp:bounds%endp) ! velocity of air within foliage [m/s]
181179
real(r8) :: temp1(bounds%begp:bounds%endp) ! relation for potential temperature profile
182180
real(r8) :: temp12m(bounds%begp:bounds%endp) ! relation for potential temperature profile applied at 2-m
183181
real(r8) :: temp2(bounds%begp:bounds%endp) ! relation for specific humidity profile
184182
real(r8) :: temp22m(bounds%begp:bounds%endp) ! relation for specific humidity profile applied at 2-m
185-
real(r8) :: ustar(bounds%begp:bounds%endp) ! friction velocity [m/s]
186183
real(r8) :: tstar ! temperature scaling parameter
187184
real(r8) :: qstar ! moisture scaling parameter
188185
real(r8) :: thvstar ! virtual potential temperature scaling parameter
@@ -235,7 +232,7 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
235232
real(r8) :: efpot ! potential latent energy flux [kg/m2/s]
236233
real(r8) :: efe(bounds%begp:bounds%endp) ! water flux from leaf [mm/s]
237234
real(r8) :: efsh ! sensible heat from leaf [mm/s]
238-
real(r8) :: obuold(bounds%begp:bounds%endp) ! monin-obukhov length from previous iteration
235+
real(r8) :: obuold(bounds%begp:bounds%endp) ! Obukhov length scale from previous iteration
239236
real(r8) :: tlbef(bounds%begp:bounds%endp) ! leaf temperature from previous iteration [K]
240237
real(r8) :: ecidif ! excess energies [W/m2]
241238
real(r8) :: err(bounds%begp:bounds%endp) ! balance error
@@ -319,6 +316,13 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
319316
real(r8) :: prev_tau_diff(bounds%begp:bounds%endp) ! Previous difference in iteration tau
320317

321318
character(len=64) :: event !! timing event
319+
320+
! Indices for raw and rah
321+
integer, parameter :: above_canopy = 1 ! Above canopy
322+
integer, parameter :: below_canopy = 2 ! Below canopy
323+
324+
! Lower bound for VPD (based on CLM)
325+
real(r8), parameter :: vpd_min = 50._r8
322326
!------------------------------------------------------------------------------
323327

324328
associate( &
@@ -444,6 +448,18 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
444448
eflx_sh_soil => veg_ef%eflx_sh_soil , & ! Output: [real(r8) (:) ] sensible heat flux from soil (W/m**2) [+ to atm]
445449
eflx_sh_veg => veg_ef%eflx_sh_veg , & ! Output: [real(r8) (:) ] sensible heat flux from leaves (W/m**2) [+ to atm]
446450
eflx_sh_grnd => veg_ef%eflx_sh_grnd , & ! Output: [real(r8) (:) ] sensible heat flux from ground (W/m**2) [+ to atm]
451+
rah_above => frictionvel_vars%rah_above_patch , & ! Output: [real(r8) (:) ] above-canopy sensible heat flux resistance [s/m]
452+
rah_below => frictionvel_vars%rah_above_patch , & ! Output: [real(r8) (:) ] below-canopy sensible heat flux resistance [s/m]
453+
raw_above => frictionvel_vars%raw_below_patch , & ! Output: [real(r8) (:) ] above-canopy water vapour flux resistance [s/m]
454+
raw_below => frictionvel_vars%raw_below_patch , & ! Output: [real(r8) (:) ] below-canopy water vapour flux resistance [s/m]
455+
ustar => frictionvel_vars%ustar_patch , & ! Output: [real(r8) (:) ] friction velocity [m/s]
456+
um => frictionvel_vars%um_patch , & ! Output: [real(r8) (:) ] wind speed including the stablity effect [m/s]
457+
uaf => frictionvel_vars%uaf_patch , & ! Output: [real(r8) (:) ] canopy air wind speed [m/s]
458+
taf => frictionvel_vars%taf_patch , & ! Output: [real(r8) (:) ] canopy air temperature [K]
459+
qaf => frictionvel_vars%qaf_patch , & ! Output: [real(r8) (:) ] canopy air specific humidity [kg/kg]
460+
obu => frictionvel_vars%obu_patch , & ! Output: [real(r8) (:) ] Obukhov length scale [m]
461+
zeta => frictionvel_vars%zeta_patch , & ! Output: [real(r8) (:) ] dimensionless stability parameter
462+
vpd => frictionvel_vars%vpd_patch , & ! Output: [real(r8) (:) ] vapour pressure deficit [kPa]
447463
begp => bounds%begp , &
448464
endp => bounds%endp &
449465
)
@@ -747,7 +763,7 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
747763
p = filterp(f)
748764
c = veg_pp%column(p)
749765

750-
! Initialize Monin-Obukhov length and wind speed
766+
! Initialize Obukhov length scale and wind speed
751767

752768
call MoninObukIni(ur(p), thv(c), dthv(p), zldis(p), z0mv(p), um(p), obu(p))
753769
num_iter(p) = 0._r8
@@ -784,8 +800,8 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
784800

785801
! Determine aerodynamic resistances
786802
ram1(p) = 1._r8/(ustar(p)*ustar(p)/um(p))
787-
rah(p,1) = 1._r8/(temp1(p)*ustar(p))
788-
raw(p,1) = 1._r8/(temp2(p)*ustar(p))
803+
rah(p,above_canopy) = 1._r8/(temp1(p)*ustar(p))
804+
raw(p,above_canopy) = 1._r8/(temp2(p)*ustar(p))
789805

790806
! Forbid removing more than 99% of wind speed in a time step.
791807
! This is mainly to avoid convergence issues since this is such a
@@ -842,18 +858,25 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
842858

843859
!! Sakaguchi changes for stability formulation ends here
844860

845-
rah(p,2) = 1._r8/(csoilcn*uaf(p))
846-
raw(p,2) = rah(p,2)
861+
rah(p,below_canopy) = 1._r8/(csoilcn*uaf(p))
862+
raw(p,below_canopy) = rah(p,below_canopy)
847863
if (use_lch4) then
848-
grnd_ch4_cond(p) = 1._r8/(raw(p,1)+raw(p,2))
864+
grnd_ch4_cond(p) = 1._r8/(raw(p,above_canopy)+raw(p,below_canopy))
849865
end if
850866

851867
! Stomatal resistances for sunlit and shaded fractions of canopy.
852868
! Done each iteration to account for differences in eah, tv.
853869

854-
svpts(p) = el(p) ! pa
855-
eah(p) = forc_pbot(t) * qaf(p) / 0.622_r8 ! pa
870+
svpts(p) = el(p) ! Pa
871+
eah(p) = forc_pbot(t) * qaf(p) / mm_epsilon ! Pa
856872
rhaf(p) = eah(p)/svpts(p)
873+
874+
! variables for history fields
875+
rah_above(p) = rah(p,above_canopy)
876+
raw_above(p) = raw(p,above_canopy)
877+
rah_below(p) = rah(p,below_canopy)
878+
raw_below(p) = raw(p,below_canopy)
879+
vpd(p) = max((svpts(p) - eah(p)), vpd_min) * pa_to_kpa ! kPa
857880
end do
858881

859882
! Modification for shrubs proposed by X.D.Z
@@ -941,9 +964,9 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
941964
! Sensible heat conductance for air, leaf and ground
942965
! Moved the original subroutine in-line...
943966

944-
wta = 1._r8/rah(p,1) ! air
967+
wta = 1._r8/rah(p,above_canopy) ! air
945968
wtl = (elai(p)+esai(p))/rb(p) ! leaf
946-
wtg(p) = 1._r8/rah(p,2) ! ground
969+
wtg(p) = 1._r8/rah(p,below_canopy) ! ground
947970
wtshi = 1._r8/(wta+wtl+wtg(p))
948971
wtl0(p) = wtl*wtshi ! leaf
949972
wtg0 = wtg(p)*wtshi ! ground
@@ -1005,7 +1028,7 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
10051028
! Air has same conductance for both sensible and latent heat.
10061029
! Moved the original subroutine in-line...
10071030

1008-
wtaq = frac_veg_nosno(p)/raw(p,1) ! air
1031+
wtaq = frac_veg_nosno(p)/raw(p,above_canopy) ! air
10091032
wtlq = frac_veg_nosno(p)*(elai(p)+esai(p))/rb(p) * rpp ! leaf
10101033

10111034
!Litter layer resistance. Added by K.Sakaguchi
@@ -1016,10 +1039,10 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
10161039

10171040
! add litter resistance and Lee and Pielke 1992 beta
10181041
if (delq(p) < 0._r8) then !dew. Do not apply beta for negative flux (follow old rsoil)
1019-
wtgq(p) = frac_veg_nosno(p)/(raw(p,2)+rdl)
1042+
wtgq(p) = frac_veg_nosno(p)/(raw(p,below_canopy)+rdl)
10201043
else
10211044
if (do_soilevap_beta()) then
1022-
wtgq(p) = soilbeta(c)*frac_veg_nosno(p)/(raw(p,2)+rdl)
1045+
wtgq(p) = soilbeta(c)*frac_veg_nosno(p)/(raw(p,below_canopy)+rdl)
10231046
endif
10241047
end if
10251048

@@ -1112,7 +1135,7 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
11121135
taf(p) = wtg0*t_grnd(c) + wta0(p)*thm(p) + wtl0(p)*t_veg(p)
11131136
qaf(p) = wtlq0(p)*qsatl(p) + wtgq0*qg(c) + forc_q(t)*wtaq0(p)
11141137

1115-
! Update Monin-Obukhov length and wind speed including the
1138+
! Update Obukhov length scale and wind speed including the
11161139
! stability effect
11171140

11181141
dth(p) = thm(p)-taf(p)
@@ -1123,13 +1146,13 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
11231146
qstar = temp2(p)*dqh(p)
11241147

11251148
thvstar = tstar*(1._r8+0.61_r8*forc_q(t)) + 0.61_r8*forc_th(t)*qstar
1126-
zeta = zldis(p)*vkc*grav*thvstar/(ustar(p)**2*thv(c))
1149+
zeta(p) = zldis(p)*vkc*grav*thvstar/(ustar(p)**2*thv(c))
11271150

1128-
if (zeta >= 0._r8) then !stable
1129-
zeta = min(2._r8,max(zeta,0.01_r8))
1151+
if (zeta(p) >= 0._r8) then !stable
1152+
zeta(p) = min(2._r8,max(zeta(p),0.01_r8))
11301153
um(p) = max(ur(p),0.1_r8)
11311154
else !unstable
1132-
zeta = max(-100._r8,min(zeta,-0.01_r8))
1155+
zeta(p) = max(-100._r8,min(zeta(p),-0.01_r8))
11331156
if ((.not. atm_gustiness) .or. force_land_gustiness) then
11341157
wc = beta*(-grav*ustar(p)*thvstar*zii/thv(c))**0.333_r8
11351158
ugust_total(p) = sqrt(ugust(t)**2 + wc**2)
@@ -1138,7 +1161,7 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, &
11381161
um(p) = max(ur(p),0.1_r8)
11391162
end if
11401163
end if
1141-
obu(p) = zldis(p)/zeta
1164+
obu(p) = zldis(p)/zeta(p)
11421165

11431166
if (obuold(p)*obu(p) < 0._r8) nmozsgn(p) = nmozsgn(p)+1
11441167
if (nmozsgn(p) >= 4) obu(p) = zldis(p)/(-0.01_r8)

components/elm/src/biogeophys/FrictionVelocityMod.F90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module FrictionVelocityMod
2424
!
2525
! !PUBLIC MEMBER FUNCTIONS:
2626
public :: FrictionVelocity ! Calculate friction velocity
27-
public :: MoninObukIni ! Initialization of the Monin-Obukhov length
27+
public :: MoninObukIni ! Initialization of the Obukhov length scale
2828
!
2929
! !PRIVATE MEMBER FUNCTIONS:
3030
private :: StabilityFunc1 ! Stability function for rib < 0.
@@ -62,7 +62,7 @@ subroutine FrictionVelocity(lbn, ubn, fn, filtern, &
6262
real(r8) , intent(in) :: z0m ( lbn: ) ! roughness length over vegetation, momentum [m] [lbn:ubn]
6363
real(r8) , intent(in) :: z0h ( lbn: ) ! roughness length over vegetation, sensible heat [m] [lbn:ubn]
6464
real(r8) , intent(in) :: z0q ( lbn: ) ! roughness length over vegetation, latent heat [m] [lbn:ubn]
65-
real(r8) , intent(in) :: obu ( lbn: ) ! monin-obukhov length (m) [lbn:ubn]
65+
real(r8) , intent(in) :: obu ( lbn: ) ! Obukhov length scale (m) [lbn:ubn]
6666
integer , intent(in) :: iter ! iteration number
6767
real(r8) , intent(in) :: ur ( lbn: ) ! wind speed at reference height [m/s] [lbn:ubn]
6868
real(r8) , intent(in) :: um ( lbn: ) ! wind speed including the stablity effect [m/s] [lbn:ubn]
@@ -445,7 +445,7 @@ end function StabilityFunc2
445445
subroutine MoninObukIni (ur, thv, dthv, zldis, z0m, um, obu)
446446
!$acc routine seq
447447
! !DESCRIPTION:
448-
! Initialization of the Monin-Obukhov length.
448+
! Initialization of the Obukhov length scale.
449449
! The scheme is based on the work of Zeng et al. (1998):
450450
! Intercomparison of bulk aerodynamic algorithms for the computation
451451
! of sea surface fluxes using TOGA CORE and TAO data. J. Climate,
@@ -462,7 +462,7 @@ subroutine MoninObukIni (ur, thv, dthv, zldis, z0m, um, obu)
462462
real(r8), intent(in) :: zldis ! reference height "minus" zero displacement heght [m]
463463
real(r8), intent(in) :: z0m ! roughness length, momentum [m]
464464
real(r8), intent(out) :: um ! wind speed including the stability effect [m/s]
465-
real(r8), intent(out) :: obu ! monin-obukhov length (m)
465+
real(r8), intent(out) :: obu ! Obukhov length scale (m)
466466
!
467467
! !LOCAL VARIABLES:
468468
real(r8) :: wc ! convective velocity [m/s]

0 commit comments

Comments
 (0)