Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tleaf ppfd #80

Merged
merged 13 commits into from
Jul 28, 2023
Merged
5 changes: 4 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,12 @@ OBJS :=\
canopy_read_txt.o \
canopy_dxcalc_mod.o \
canopy_profile_mod.o \
canopy_phot_mod.o \
canopy_rad_mod.o \
canopy_ppfd_mod.o \
canopy_tleaf_mod.o \
canopy_wind_mod.o \
canopy_waf_mod.o \
canopy_phot_mod.o \
canopy_eddy_mod.o \
canopy_bioparm_mod.o \
canopy_bioemi_mod.o \
Expand Down
11 changes: 9 additions & 2 deletions src/canopy_alloc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,15 @@ SUBROUTINE canopy_alloc
! Allocate arrays for Internal Canopy Distribution Variables
!-------------------------------------------------------------------------------

if(.not.allocated(zhc)) allocate(zhc(modlays))
if(.not.allocated(fafraczInt)) allocate(fafraczInt(modlays))
if(.not.allocated(zhc)) allocate(zhc(modlays))
if(.not.allocated(fafraczInt)) allocate(fafraczInt(modlays))
if(.not.allocated(fsun)) allocate(fsun(modlays))
if(.not.allocated(tleaf_sun)) allocate(tleaf_sun(modlays))
if(.not.allocated(tleaf_shade)) allocate(tleaf_shade(modlays))
if(.not.allocated(tleaf_ave)) allocate(tleaf_ave(modlays))
if(.not.allocated(ppfd_sun)) allocate(ppfd_sun(modlays))
if(.not.allocated(ppfd_shade)) allocate(ppfd_shade(modlays))
if(.not.allocated(ppfd_ave)) allocate(ppfd_ave(modlays))

!-------------------------------------------------------------------------------
! Allocate arrays for Canopy Wind Outputs
Expand Down
201 changes: 16 additions & 185 deletions src/canopy_bioemi_mod.F90

Large diffs are not rendered by default.

150 changes: 111 additions & 39 deletions src/canopy_calcs.F90

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions src/canopy_canvars_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ MODULE canopy_canvars_mod
real(rk), allocatable :: fainc ( : ) ! incremental foliage shape function
real(rk), allocatable :: fafracz ( : ) ! incremental fractional foliage shape function
real(rk), allocatable :: fafraczInt ( : ) ! integral of incremental fractional foliage shape function
real(rk), allocatable :: fsun ( : ) ! Sunlit/Shaded fraction from photolysis correction factor
real(rk), allocatable :: tleaf_sun ( : ) ! Leaf temp for sunlit leaves (K)
real(rk), allocatable :: tleaf_shade ( : ) ! Leaf temp for shaded leaves (K)
real(rk), allocatable :: tleaf_ave ( : ) ! Average Leaf temp for sunlit and shaded leaves (K)
real(rk), allocatable :: ppfd_sun ( : ) ! PPFD for sunlit leaves (umol phot/m2 s)
real(rk), allocatable :: ppfd_shade ( : ) ! PPFD for shaded leaves (umol phot/m2 s)
real(rk), allocatable :: ppfd_ave ( : ) ! Average PPFD for sunlit and shaded leaves (umol phot/m2 s)
real(rk), allocatable :: canBOT ( : ) ! Canopy bottom wind reduction factors
real(rk), allocatable :: canTOP ( : ) ! Canopy top wind reduction factors
real(rk), allocatable :: canWIND ( : , : ) ! canopy wind speeds (m/s)
Expand Down
17 changes: 12 additions & 5 deletions src/canopy_dealloc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,18 @@ SUBROUTINE canopy_dealloc
! Dellocate arrays for Canopy Distribution
!-------------------------------------------------------------------------------

if(allocated(zk)) deallocate(zk) !allocated in canopy_readnml
if(allocated(zhc)) deallocate(zhc)
if(allocated(fainc)) deallocate(fainc) !allocated in canopy_profile
if(allocated(fafracz)) deallocate(fafracz) !allocated in canopy_profile
if(allocated(fafraczInt)) deallocate(fafraczInt)
if(allocated(zk)) deallocate(zk) !allocated in canopy_readnml
if(allocated(zhc)) deallocate(zhc)
if(allocated(fainc)) deallocate(fainc) !allocated in canopy_profile
if(allocated(fafracz)) deallocate(fafracz) !allocated in canopy_profile
if(allocated(fafraczInt)) deallocate(fafraczInt)
if(allocated(fsun)) deallocate(fsun)
if(allocated(tleaf_sun)) deallocate(tleaf_sun)
if(allocated(tleaf_shade)) deallocate(tleaf_shade)
if(allocated(tleaf_ave)) deallocate(tleaf_ave)
if(allocated(ppfd_sun)) deallocate(ppfd_sun)
if(allocated(ppfd_shade)) deallocate(ppfd_shade)
if(allocated(ppfd_ave)) deallocate(ppfd_ave)

!-------------------------------------------------------------------------------
! Deallocate arrays for Canopy Wind
Expand Down
11 changes: 9 additions & 2 deletions src/canopy_init.F90
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@ SUBROUTINE canopy_init
! Initialize arrays for Canopy Distribution
!-------------------------------------------------------------------------------

if(allocated(zhc)) zhc(:) = fillreal
if(allocated(fafraczInt)) fafraczInt(:) = fillreal
if(allocated(zhc)) zhc(:) = fillreal
if(allocated(fafraczInt)) fafraczInt(:) = fillreal
if(allocated(fsun)) fsun(:) = fillreal
if(allocated(tleaf_sun)) tleaf_sun(:) = fillreal
if(allocated(tleaf_shade)) tleaf_shade(:) = fillreal
if(allocated(tleaf_ave)) tleaf_ave(:) = fillreal
if(allocated(ppfd_sun)) ppfd_sun(:) = fillreal
if(allocated(ppfd_shade)) ppfd_shade(:) = fillreal
if(allocated(ppfd_ave)) ppfd_ave(:) = fillreal

!-------------------------------------------------------------------------------
! Initialize arrays for Canopy Wind
Expand Down
130 changes: 130 additions & 0 deletions src/canopy_ppfd_mod.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
module canopy_ppfd_mod

implicit none

contains

!:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SUBROUTINE CANOPY_PPFD_EXP( ZK, FCH, SFCRAD, LAI, FSUN, &
PPFD_SUN, PPFD_SHADE, PPFD_AVE)

!-----------------------------------------------------------------------

! Description:
! computes linear interpolation method for PPFD sun/shade in canopy.

! Preconditions:
! in-canopy height, and model LAI, clumping index, and solar zenith angle

! Subroutines and Functions Called:

! Revision History:
! Prototype 06/23 by PCC
! Jun 2023 P.C. Campbell: Initial standalone PPFD linear subroutine based on
! Silva et al. (2020) exponential curve algorithms
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------
use canopy_const_mod, ONLY: RK !constants for canopy models
use canopy_utils_mod, ONLY: interp_linear1_internal

! Arguments:
! IN/OUT
REAL(RK), INTENT( IN ) :: ZK(:) ! Input model heights (m)
REAL(RK), INTENT( IN ) :: FCH ! Model input canopy height (m)
REAL(RK), INTENT( IN ) :: SFCRAD ! Model input Instantaneous surface downward shortwave flux (W/m2)
REAL(RK), INTENT( IN ) :: LAI ! Model input total Leaf Area Index
REAL(RK), INTENT( IN ) :: FSUN(:) ! Sunlit/Shaded fraction from photolysis correction factor
REAL(RK), INTENT( OUT ) :: PPFD_SUN(SIZE(ZK)) ! PPFD for sunlit leaves (umol phot/m2 s)
REAL(RK), INTENT( OUT ) :: PPFD_SHADE(SIZE(ZK)) ! PPFD for shaded leaves (umol phot/m2 s)
REAL(RK), INTENT( OUT ) :: PPFD_AVE(SIZE(ZK)) ! Average PPFD for sunlit and shaded leaves (umol phot/m2 s)

! LOCAL
REAL(RK), PARAMETER :: CTEMP_1_SUN = 1.083_rk !Exponential 2-m PPFD --> PPFD parameters (Level 1 =
!top of canopy
REAL(RK), PARAMETER :: CTEMP_2_SUN = 1.096_rk !Based on Table 1 in Silva et al. (2022)
REAL(RK), PARAMETER :: CTEMP_3_SUN = 1.104_rk !
REAL(RK), PARAMETER :: CTEMP_4_SUN = 1.098_rk !
REAL(RK), PARAMETER :: CTEMP_5_SUN = 1.090_rk !...
REAL(RK), PARAMETER :: DTEMP_1_SUN = 0.002_rk !...
REAL(RK), PARAMETER :: DTEMP_2_SUN = -0.128_rk !...
REAL(RK), PARAMETER :: DTEMP_3_SUN = -0.298_rk !...
REAL(RK), PARAMETER :: DTEMP_4_SUN = -0.445_rk !...
REAL(RK), PARAMETER :: DTEMP_5_SUN = -0.535_rk !...
REAL(RK), PARAMETER :: CTEMP_1_SHADE = 0.871_rk !...
REAL(RK), PARAMETER :: CTEMP_2_SHADE = 0.890_rk !...
REAL(RK), PARAMETER :: CTEMP_3_SHADE = 0.916_rk !...
REAL(RK), PARAMETER :: CTEMP_4_SHADE = 0.941_rk !...
REAL(RK), PARAMETER :: CTEMP_5_SHADE = 0.956_rk !...
REAL(RK), PARAMETER :: DTEMP_1_SHADE = 0.015_rk !...
REAL(RK), PARAMETER :: DTEMP_2_SHADE = -0.141_rk !...
REAL(RK), PARAMETER :: DTEMP_3_SHADE = -0.368_rk !...
REAL(RK), PARAMETER :: DTEMP_4_SHADE = -0.592_rk !...
REAL(RK), PARAMETER :: DTEMP_5_SHADE = -0.743_rk !...

REAL(RK), PARAMETER :: FRAC_PAR = 0.5_rk !Fraction of incoming solar irradiance that is PAR
drnimbusrain marked this conversation as resolved.
Show resolved Hide resolved

REAL(RK) :: CTEMP_SUN(SIZE(ZK)) ! Regression coefficient C for sun leaves
REAL(RK) :: DTEMP_SUN(SIZE(ZK)) ! Regression coefficient D for sun leaves
REAL(RK) :: CTEMP_SHADE(SIZE(ZK)) ! Regression coefficient C for shade leaves
REAL(RK) :: DTEMP_SHADE(SIZE(ZK)) ! Regression coefficient D for shade leaves

integer i

! Use exponential PPFD model based on Silva et al. (2020) to get approx. sun/shade PPFD
! through canopy
!Citation:
!Silva, S. J., Heald, C. L., and Guenther, A. B.: Development of a reduced-complexity plant canopy
!physics surrogate model for use in chemical transport models: a case study with GEOS-Chem v12.3.0,
!Geosci. Model Dev., 13, 2569–2585, https://doi.org/10.5194/gmd-13-2569-2020, 2020.
do i=1, SIZE(ZK) !calculate linear change in parameters interpolated to Silva et al. 5 layer canopy regions
if (ZK(i) .gt. FCH) then ! above canopy, PPFD_leaf = PPFD_toc (toc=top of canopy)
CTEMP_SUN(i) = 0.0
DTEMP_SUN(i) = 0.0
CTEMP_SHADE(i) = 0.0
DTEMP_SHADE(i) = 0.0
else if (ZK(i) .le. FCH .and. ZK(i) .gt. FCH*(4.0_rk/5.0_rk)) then !Level 1 - 2
CTEMP_SUN(i) = interp_linear1_internal((/ FCH*(4.0_rk/5.0_rk),FCH /), &
(/ CTEMP_2_SUN,CTEMP_1_SUN /),ZK(i))
DTEMP_SUN(i) = interp_linear1_internal((/ FCH*(4.0_rk/5.0_rk),FCH /), &
(/ DTEMP_2_SUN,DTEMP_1_SUN /),ZK(i))
CTEMP_SHADE(i) = interp_linear1_internal((/ FCH*(4.0_rk/5.0_rk),FCH /), &
(/ CTEMP_2_SHADE,CTEMP_1_SHADE /),ZK(i))
DTEMP_SHADE(i) = interp_linear1_internal((/ FCH*(4.0_rk/5.0_rk),FCH /), &
(/ DTEMP_2_SHADE,DTEMP_1_SHADE /),ZK(i))
else if (ZK(i) .le. FCH*(4.0_rk/5.0_rk) .and. ZK(i) .gt. FCH*(3.0_rk/5.0_rk)) then !Level 2 - 3
CTEMP_SUN(i) = interp_linear1_internal((/ FCH*(3.0_rk/5.0_rk),FCH*(4.0_rk/5.0_rk) /), &
(/ CTEMP_3_SUN,CTEMP_2_SUN /),ZK(i))
DTEMP_SUN(i) = interp_linear1_internal((/ FCH*(3.0_rk/5.0_rk),FCH*(4.0_rk/5.0_rk) /), &
(/ DTEMP_3_SUN,DTEMP_2_SUN /),ZK(i))
CTEMP_SHADE(i) = interp_linear1_internal((/ FCH*(3.0_rk/5.0_rk),FCH*(4.0_rk/5.0_rk) /), &
(/ CTEMP_3_SHADE,CTEMP_2_SHADE /),ZK(i))
DTEMP_SHADE(i) = interp_linear1_internal((/ FCH*(3.0_rk/5.0_rk),FCH*(4.0_rk/5.0_rk) /), &
(/ DTEMP_3_SHADE,DTEMP_2_SHADE /),ZK(i))
else if (ZK(i) .le. FCH*(3.0_rk/5.0_rk) .and. ZK(i) .gt. FCH*(2.0_rk/5.0_rk)) then !Level 3 - 4
CTEMP_SUN(i) = interp_linear1_internal((/ FCH*(2.0_rk/5.0_rk),FCH*(3.0_rk/5.0_rk) /), &
(/ CTEMP_4_SUN,CTEMP_3_SUN /),ZK(i))
DTEMP_SUN(i) = interp_linear1_internal((/ FCH*(2.0_rk/5.0_rk),FCH*(3.0_rk/5.0_rk) /), &
(/ DTEMP_4_SUN,DTEMP_3_SUN /),ZK(i))
CTEMP_SHADE(i) = interp_linear1_internal((/ FCH*(2.0_rk/5.0_rk),FCH*(3.0_rk/5.0_rk) /), &
(/ CTEMP_4_SHADE,CTEMP_3_SHADE /),ZK(i))
DTEMP_SHADE(i) = interp_linear1_internal((/ FCH*(2.0_rk/5.0_rk),FCH*(3.0_rk/5.0_rk) /), &
(/ DTEMP_4_SHADE,DTEMP_3_SHADE /),ZK(i))
else if (ZK(i) .le. FCH*(2.0_rk/5.0_rk) ) then !Level 4 - Bottom
CTEMP_SUN(i) = interp_linear1_internal((/ ZK(1),FCH*(2.0_rk/5.0_rk) /), &
(/ CTEMP_5_SUN,CTEMP_4_SUN /),ZK(i))
DTEMP_SUN(i) = interp_linear1_internal((/ ZK(1),FCH*(2.0_rk/5.0_rk) /), &
(/ DTEMP_5_SUN,DTEMP_4_SUN /),ZK(i))
CTEMP_SHADE(i) = interp_linear1_internal((/ ZK(1),FCH*(2.0_rk/5.0_rk) /), &
(/ CTEMP_5_SHADE,CTEMP_4_SHADE /),ZK(i))
DTEMP_SHADE(i) = interp_linear1_internal((/ ZK(1),FCH*(2.0_rk/5.0_rk) /), &
(/ DTEMP_5_SHADE,DTEMP_4_SHADE /),ZK(i))
end if
end do

PPFD_SUN = FRAC_PAR * SFCRAD * EXP(CTEMP_SUN + DTEMP_SUN * LAI) !Silva et al. W/m2 --> umol m-2 s-1
PPFD_SHADE = FRAC_PAR * SFCRAD * EXP(CTEMP_SHADE + DTEMP_SHADE * LAI)
PPFD_AVE = (PPFD_SUN*FSUN) + (PPFD_SHADE*(1.0-FSUN)) ! average = sum sun and shade weighted by sunlit fraction

END SUBROUTINE CANOPY_PPFD_EXP

end module canopy_ppfd_mod
47 changes: 47 additions & 0 deletions src/canopy_rad_mod.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module canopy_rad_mod

implicit none

contains

!:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SUBROUTINE CANOPY_FSUN_CLU( FCLAI, LAI, CLU, COSZEN, FSUN)

!-----------------------------------------------------------------------

! Description:
! computes linear interpolation method for PPFD sun/shade in canopy.

! Preconditions:
! in-canopy height, and model LAI, clumping index, and solar zenith angle

! Subroutines and Functions Called:

! Revision History:
! Prototype 06/23 by PCC
! Jun 2023 P.C. Campbell: Initial standalone PPFD linear subroutine based on
! Silva et al. (2020) exponential curve algorithms
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------
use canopy_const_mod, ONLY: RK !constants for canopy models
use canopy_phot_mod

! Arguments:
! IN/OUT
REAL(RK), INTENT( IN ) :: FCLAI(:) ! Input Fractional (z) shapes of the
! plant surface distribution (nondimensional), i.e., a Fractional Culmulative LAI
REAL(RK), INTENT( IN ) :: LAI ! Model input total Leaf Area Index
REAL(RK), INTENT( IN ) :: CLU ! Model input Clumping Index
REAL(RK), INTENT( IN ) :: COSZEN ! Model input Cosine Solar Zenith Angle
REAL(RK), INTENT( OUT ) :: FSUN(SIZE(FCLAI)) ! Sunlit/Shaded fraction from photolysis correction factor

!Calculate photolyis shading/correction factor through canopy, i.e., the fraction of sunlit leaves downward through canopy
! `canopy_phot` gives relative direct beam irradiance,
! which, multiplied by clumping index, gives sunlit fraction (e.g., Bonan 2019, eq. 14.18)

call canopy_phot(FCLAI, LAI, CLU, COSZEN, FSUN)
FSUN = FSUN * CLU

END SUBROUTINE CANOPY_FSUN_CLU

end module canopy_rad_mod
Loading