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

Initial commit of historical leaf temp/par averaging approach. #111

Merged
merged 8 commits into from
Mar 19, 2024
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ You can also [generate global inputs using Python (see python/global_data_proces
| `co2_set` | user-set real value of atmospheric co2 concentration (ppmv) (only used if `co2_opt=0` or `co2_opt=1`) |
| `leafage_opt` | user-set options for applying leaf-age response to biogenic VOC emissions based on [Guenther et al. 2006](https://doi.org/10.5194/acp-6-3181-2006) (default is off i.e., `leafage_opt=1`, the corresponding $\gamma$ is set to 1). If turned on (`leafage_opt=0`), leafage $\gamma$ is calculated and the lai_tstep option needs to be set to ensure correct interpolation in this leafage_opt calculation. |
| `lai_tstep` | user-defined options for the number of seconds in the interval at which LAI (Leaf Area Index) data is provided to the model. For instance, if LAI data is given on a daily basis, lai_tstep would be set to the number of seconds in a day (86,400 seconds). If LAI data is provided monthly, then lai_tstep would represent the total number of seconds in that month (e.g., 2,592,000 seconds for a 30-day month). This parameter helps in determining the frequency of LAI input and is crucial for interpolating LAI values to the model's hourly timesteps when the model's timestep (time_intvl) is smaller than the LAI input interval. |
| `hist_opt` | user-set option to use historically averaged short-term (24-hr) and long-term (240-hr) rolling averages for leaf temperature and PAR for biogenic emissions (default is off i.e., `hist_opt=0`) Note: If simulation is </= 24 hours, instantaneous values for leaf temperature and PAR will be used even if historical averaging is turned on (i.e., `hist_opt=1`). Recommend turning on `hist_opt=1` and running at least for 25 hours to create a model spin-up, and use subsequent simulation hours for analysis. Overall a 10-day (240 hr) spinup is optimal for best analysis of biogenic emissions. |
| `soim_opt` | user-set options for applying soil moisture response to biogenic VOC emissions based on [Guenther et al. 2006](https://doi.org/10.5194/acp-6-3181-2006), which depends on input soil moisture at depth and the wilting point. This includes additional PFT dependent approach for cumulative root fraction within each soil layer from [Zeng (2001)](https://doi.org/10.1175/1525-7541(2001)002<0525:GVRDFL>2.0.CO;2). (default is off i.e., `soim_opt=1`, the corresponding $\gamma$ is set to 1). If turned on (`soim_opt=0`), which is recommended, soim $\gamma$ is calculated and the prescribed 4-layer soil depths (`soild[1-4]` below) are used. Four layers are assumed, and are based on GFS Noah and Noah-MP LSM. |
| `soild[1-4]` | user-set real values of four level soil depths at centerpoint (cm). Four layers are based on the GFS Noah and Noah-MP LSM, default values are `soild1=5.0`, `soild2=25.0`, `soild3=70.0`, and `soild4=150.0`. |

Expand Down
1 change: 1 addition & 0 deletions input/namelist.canopy
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,5 @@
soild2 = 25.0
soild3 = 70.0
soild4 = 150.0
hist_opt = 1
/
68 changes: 55 additions & 13 deletions src/canopy_alloc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ SUBROUTINE canopy_alloc
if(.not.allocated(variables_3d)) allocate(variables_3d(nlon,nlat,var3d_set))
if(.not.allocated(variables_1d)) allocate(variables_1d(var3d_set))
if(.not.allocated(variables_can)) allocate(variables_can(nlat*nlon))
if(.not.allocated(pavdref)) allocate(pavdref(var3d_set))
if(.not.allocated(levref)) allocate(levref(var3d_set))
if(.not.allocated(pavdref)) allocate(pavdref(var3d_set))
if(.not.allocated(levref)) allocate(levref(var3d_set))
if(.not.allocated(pavd_arr)) allocate(pavd_arr(var3d_set))
if(.not.allocated(lev_arr)) allocate(lev_arr(var3d_set))
end if
Expand All @@ -34,17 +34,59 @@ 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(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))
if(.not.allocated(lad)) allocate(lad(nlat*nlon,modlays))
if(.not.allocated(lad_3d)) allocate(lad_3d(nlon,nlat,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))
if(.not.allocated(lad)) allocate(lad(nlat*nlon,modlays))
if(.not.allocated(lad_3d)) allocate(lad_3d(nlon,nlat,modlays))

if(.not.allocated(tleaf_sun24_tmp)) allocate(tleaf_sun24_tmp(nlat*nlon,modlays))
if(.not.allocated(tleaf_shade24_tmp)) allocate(tleaf_shade24_tmp(nlat*nlon,modlays))
if(.not.allocated(tleaf_ave24_tmp)) allocate(tleaf_ave24_tmp(nlat*nlon,modlays))
if(.not.allocated(ppfd_sun24_tmp)) allocate(ppfd_sun24_tmp(nlat*nlon,modlays))
if(.not.allocated(ppfd_shade24_tmp)) allocate(ppfd_shade24_tmp(nlat*nlon,modlays))
if(.not.allocated(tleaf_sun240_tmp)) allocate(tleaf_sun240_tmp(nlat*nlon,modlays))
if(.not.allocated(tleaf_shade240_tmp)) allocate(tleaf_shade240_tmp(nlat*nlon,modlays))
if(.not.allocated(tleaf_ave240_tmp)) allocate(tleaf_ave240_tmp(nlat*nlon,modlays))
if(.not.allocated(ppfd_sun240_tmp)) allocate(ppfd_sun240_tmp(nlat*nlon,modlays))
if(.not.allocated(ppfd_shade240_tmp)) allocate(ppfd_shade240_tmp(nlat*nlon,modlays))
if(.not.allocated(tleaf_sun24)) allocate(tleaf_sun24(nlat*nlon,modlays))
if(.not.allocated(tleaf_shade24)) allocate(tleaf_shade24(nlat*nlon,modlays))
if(.not.allocated(tleaf_ave24)) allocate(tleaf_ave24(nlat*nlon,modlays))
if(.not.allocated(ppfd_sun24)) allocate(ppfd_sun24(nlat*nlon,modlays))
if(.not.allocated(ppfd_shade24)) allocate(ppfd_shade24(nlat*nlon,modlays))
if(.not.allocated(tleaf_sun240)) allocate(tleaf_sun240(nlat*nlon,modlays))
if(.not.allocated(tleaf_shade240)) allocate(tleaf_shade240(nlat*nlon,modlays))
if(.not.allocated(tleaf_ave240)) allocate(tleaf_ave240(nlat*nlon,modlays))
if(.not.allocated(ppfd_sun240)) allocate(ppfd_sun240(nlat*nlon,modlays))
if(.not.allocated(ppfd_shade240)) allocate(ppfd_shade240(nlat*nlon,modlays))

if(.not.allocated(tleaf_sun24_tmp_3d)) allocate(tleaf_sun24_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(tleaf_shade24_tmp_3d)) allocate(tleaf_shade24_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(tleaf_ave24_tmp_3d)) allocate(tleaf_ave24_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(ppfd_sun24_tmp_3d)) allocate(ppfd_sun24_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(ppfd_shade24_tmp_3d)) allocate(ppfd_shade24_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(tleaf_sun240_tmp_3d)) allocate(tleaf_sun240_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(tleaf_shade240_tmp_3d)) allocate(tleaf_shade240_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(tleaf_ave240_tmp_3d)) allocate(tleaf_ave240_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(ppfd_sun240_tmp_3d)) allocate(ppfd_sun240_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(ppfd_shade240_tmp_3d)) allocate(ppfd_shade240_tmp_3d(ntime,nlon,nlat,modlays))
if(.not.allocated(tleaf_sun24_3d)) allocate(tleaf_sun24_3d(nlon,nlat,modlays))
if(.not.allocated(tleaf_shade24_3d)) allocate(tleaf_shade24_3d(nlon,nlat,modlays))
if(.not.allocated(tleaf_ave24_3d)) allocate(tleaf_ave24_3d(nlon,nlat,modlays))
if(.not.allocated(ppfd_sun24_3d)) allocate(ppfd_sun24_3d(nlon,nlat,modlays))
if(.not.allocated(ppfd_shade24_3d)) allocate(ppfd_shade24_3d(nlon,nlat,modlays))
if(.not.allocated(tleaf_sun240_3d)) allocate(tleaf_sun240_3d(nlon,nlat,modlays))
if(.not.allocated(tleaf_shade240_3d)) allocate(tleaf_shade240_3d(nlon,nlat,modlays))
if(.not.allocated(tleaf_ave240_3d)) allocate(tleaf_ave240_3d(nlon,nlat,modlays))
if(.not.allocated(ppfd_sun240_3d)) allocate(ppfd_sun240_3d(nlon,nlat,modlays))
if(.not.allocated(ppfd_shade240_3d)) allocate(ppfd_shade240_3d(nlon,nlat,modlays))

!-------------------------------------------------------------------------------
! Allocate arrays for Canopy Wind Outputs
Expand Down
60 changes: 30 additions & 30 deletions src/canopy_bioemi_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ module canopy_bioemi_mod
contains

!:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SUBROUTINE CANOPY_BIO( ZK, FCLAI, FCH, LAI, FSUN, PPFD_SUN, &
PPFD_SHADE, TLEAF_SUN, TLEAF_SHADE, TLEAF_AVE, TEMP2, LU_OPT, &
SUBROUTINE CANOPY_BIO( ZK, FCLAI, FCH, LAI, FSUN, &
PPFD_SUN, PPFD_SHADE, TLEAF_SUN, TLEAF_SHADE, PPFD24_SUN, &
PPFD24_SHADE, TLEAF24_AVE, &
PPFD240_SUN, PPFD240_SHADE, &
TLEAF240_AVE, TEMP2, LU_OPT, &
VTYPE, MODRES, CCE, VERT, CO2OPT, CO2SET, &
LEAFAGEOPT, PASTLAI, CURRENTLAI, TSTEPLAI, &
SOIMOPT, SOIM1, SOIM2, SOIM3, SOIM4, SOID1, SOID2, SOID3, &
Expand Down Expand Up @@ -49,17 +52,23 @@ SUBROUTINE CANOPY_BIO( ZK, FCLAI, FCH, LAI, FSUN, PPFD_SUN, &

! Arguments:
! IN/OUT
REAL(RK), INTENT( IN ) :: ZK(:) ! Model heights (m)
REAL(RK), INTENT( IN ) :: FCLAI(:) ! Fractional (z) shapes of the
REAL(RK), INTENT( IN ) :: ZK(:) ! Model heights (m)
REAL(RK), INTENT( IN ) :: FCLAI(:) ! Fractional (z) shapes of the
! plant surface distribution (nondimensional), i.e., a Fractional Culmulative LAI
REAL(RK), INTENT( IN ) :: FCH ! Canopy height (m)
REAL(RK), INTENT( IN ) :: LAI ! Total Leaf Area Index
REAL(RK), INTENT( IN ) :: FSUN(:) ! Sunlit/Shaded fraction from photolysis correction factor
REAL(RK), INTENT( IN ) :: PPFD_SUN(:) ! PPFD for sunlit leaves (umol phot/m2 s)
REAL(RK), INTENT( IN ) :: PPFD_SHADE(:) ! PPFD for shaded leaves (umol phot/m2 s)
REAL(RK), INTENT( IN ) :: TLEAF_SUN(:) ! Leaf temp for sunlit leaves (K)
REAL(RK), INTENT( IN ) :: TLEAF_SHADE(:) ! Leaf temp for shaded leaves (K)
REAL(RK), INTENT( IN ) :: TLEAF_AVE(:) ! Average Leaf temp (K)
REAL(RK), INTENT( IN ) :: FCH ! Canopy height (m)
REAL(RK), INTENT( IN ) :: LAI ! Total Leaf Area Index
REAL(RK), INTENT( IN ) :: FSUN(:) ! Sunlit/Shaded fraction from photolysis correction factor
REAL(RK), INTENT( IN ) :: TLEAF_SUN(:) ! Leaf temp for sunlit leaves (K)
REAL(RK), INTENT( IN ) :: TLEAF_SHADE(:) ! Leaf temp for shaded leaves (K)
REAL(RK), INTENT( IN ) :: PPFD_SUN(:) ! PPFD for sunlit leaves (umol phot/m2 s)
REAL(RK), INTENT( IN ) :: PPFD_SHADE(:) ! PPFD for shaded leaves (umol phot/m2 s)
REAL(RK), INTENT( IN ) :: PPFD24_SUN(:) ! PPFD for sunlit leaves (umol phot/m2 s) --24 hr ave
REAL(RK), INTENT( IN ) :: PPFD24_SHADE(:) ! PPFD for shaded leaves (umol phot/m2 s)
REAL(RK), INTENT( IN ) :: TLEAF24_AVE(:) ! Average Leaf temp (K)
REAL(RK), INTENT( IN ) :: PPFD240_SUN(:) ! PPFD for sunlit leaves (umol phot/m2 s) -- 240 hr ave
REAL(RK), INTENT( IN ) :: PPFD240_SHADE(:) ! PPFD for shaded leaves (umol phot/m2 s)
REAL(RK), INTENT( IN ) :: TLEAF240_AVE(:) ! Average Leaf temp (K)

REAL(RK), INTENT( IN ) :: TEMP2 ! Model input 2-m Temperature (K)
INTEGER, INTENT( IN ) :: LU_OPT ! integer for LU type from model mapped to Massman et al. (default = 0/VIIRS)
INTEGER, INTENT( IN ) :: VTYPE ! Grid cell dominant vegetation type
Expand All @@ -79,29 +88,23 @@ SUBROUTINE CANOPY_BIO( ZK, FCLAI, FCH, LAI, FSUN, PPFD_SUN, &
REAL(RK), INTENT( IN ) :: SOID4 ! Soil depth layer 4 [cm]
REAL(RK), INTENT( IN ) :: WILT ! Wilting point [proportion]

INTEGER, INTENT( IN ) :: LEAFAGEOPT ! leafage_opt (0= ON, 1= off i.e. GAMMALEAFAGE =1, in canopy_readnml.F90)
REAL(RK), INTENT( IN ) :: PASTLAI ! Past LAI [cm2/cm2]
REAL(RK), INTENT( IN ) :: CURRENTLAI ! Current LAI [cm2/cm2]
REAL(RK), INTENT( IN ) :: TSTEPLAI !Number of days between the past and current LAI
INTEGER, INTENT( IN ) :: LEAFAGEOPT ! leafage_opt (0= ON, 1= off i.e. GAMMALEAFAGE =1, in canopy_readnml.F90)
REAL(RK), INTENT( IN ) :: PASTLAI ! Past LAI [cm2/cm2]
REAL(RK), INTENT( IN ) :: CURRENTLAI ! Current LAI [cm2/cm2]
REAL(RK), INTENT( IN ) :: TSTEPLAI !Number of days between the past and current LAI

INTEGER, INTENT( IN ) :: MODLAYS ! Input total model layers
INTEGER, INTENT( IN ) :: EMI_IND ! Input biogenic emissions index
REAL(RK), INTENT( OUT ) :: EMI_OUT(:) ! Output canopy layer volume emissions (kg m-3 s-1)

! Local Variables
REAL(RK) :: TLEAF24_AVE(SIZE(ZK)) ! Average Leaf temp over the past 24 hours (K)
REAL(RK) :: TLEAF240_AVE(SIZE(ZK)) ! Average Leaf temp over the past 240 hours (K)
REAL(RK) :: GammaTLEAF_SUN_NUM(SIZE(ZK)) ! Numerator in Tleaf sun activity factor
REAL(RK) :: GammaTLEAF_SHADE_NUM(SIZE(ZK)) ! Numerator in Tleaf shade activity factor
REAL(RK) :: GammaTLEAF_SUN_DEN(SIZE(ZK)) ! Denominator in Tleaf sun activity factor
REAL(RK) :: GammaTLEAF_SHADE_DEN(SIZE(ZK)) ! Denominator in Tleaf sun activity factor
REAL(RK) :: GammaTLEAF_SUN(SIZE(ZK)) ! Tleaf sun activity factor
REAL(RK) :: GammaTLEAF_SHADE(SIZE(ZK)) ! Tleaf shade activity factor
REAL(RK) :: GammaTLEAF_AVE(SIZE(ZK)) ! Average Tleaf activity factor
REAL(RK) :: PPFD24_SUN(SIZE(ZK)) ! Average PPFD sun over the past 24 hours
REAL(RK) :: PPFD24_SHADE(SIZE(ZK)) ! Average PPFD shade over the past 24 hours
REAL(RK) :: PPFD240_SUN(SIZE(ZK)) ! Average PPFD sun over the past 240 hours
REAL(RK) :: PPFD240_SHADE(SIZE(ZK)) ! Average PPFD shade over the past 240 hours
REAL(RK) :: CP_SUN(SIZE(ZK)) ! Normalized emission capacity sun at PPFD = 1000 umol phot/m2 s
REAL(RK) :: CP_SHADE(SIZE(ZK)) ! Normalized emission capacity shade at PPFD = 1000 umol phot/m2 s
REAL(RK) :: ALPHA_P_SUN(SIZE(ZK)) ! Quantum yield of isoprene sunlit (mol/mol)
Expand Down Expand Up @@ -144,16 +147,14 @@ SUBROUTINE CANOPY_BIO( ZK, FCLAI, FCH, LAI, FSUN, PPFD_SUN, &
REAL(RK), PARAMETER :: CT2 = 230.0_rk !Deactivation energy (kJ/mol) (Guenther et al., 2012)

! Calculate maximum normalized emission capacity (E_OPT) and Tleaf at E_OPT
TLEAF240_AVE = TLEAF_AVE !Assume instantaneous TLEAF estimate for TLEAF240 and TLEAF24 (could improve...)
TLEAF24_AVE = TLEAF_AVE
TLEAF_OPT = 313.0_rk + (0.6_rk * (TLEAF240_AVE-297.0_rk)) !Guenther et al. (2012)

! Calculate emission species/plant-dependent mapped emission factors and other important coefficients for gamma terms
call canopy_biop(EMI_IND, LU_OPT, VTYPE, EF, CT1, CEO, ANEW, AGRO, AMAT, AOLD, ROOTA, ROOTB)

E_OPT = CEO * EXP(0.05_rk * (TLEAF24_AVE-297.0_rk)) * EXP(0.05_rk * (TLEAF240_AVE-297.0_rk))

! Calculate gamma (activity) values for average Tleaf (Clifton et al., 2022)
! Calculate gamma (activity) values for average Tleaf (Clifton et al., 2022; based on Guenther et al. 2012)
GammaTLEAF_SUN_NUM = CT2*exp((CT1/(rgasuniv/1000.0))*((1.0/TLEAF_OPT)-(1.0/TLEAF_SUN)))
GammaTLEAF_SUN_DEN = (CT2-CT1)*(1.0-exp((CT2/(rgasuniv/1000.0))*((1.0/TLEAF_OPT)-(1.0/TLEAF_SUN))))
GammaTLEAF_SUN = E_OPT*(GammaTLEAF_SUN_NUM/GammaTLEAF_SUN_DEN)
Expand All @@ -164,12 +165,9 @@ SUBROUTINE CANOPY_BIO( ZK, FCLAI, FCH, LAI, FSUN, PPFD_SUN, &

GammaTLEAF_AVE = (GammaTLEAF_SUN*FSUN) + (GammaTLEAF_SHADE*(1.0-FSUN)) ! average = sum sun and shade weighted by sunlit fraction

! Calculate gamma (activity) values for average PPFD (Clifton et al., 2022)
PPFD240_SUN = PPFD_SUN/2.0 !Clifton et al...halve the instantaneous PPFD estimate to get PPFD240 and PPFD24
PPFD240_SHADE = PPFD_SHADE/2.0
PPFD24_SUN = PPFD_SUN/2.0
PPFD24_SHADE = PPFD_SHADE/2.0
GammaTLEAF_AVE = MAX( GammaTLEAF_AVE, 0.0_rk )

! Calculate gamma (activity) values for average PPFD (Clifton et al., 2022; based on Guenther et al. 2012)
ALPHA_P_SUN = 0.004 - 0.0005*log(PPFD240_SUN)
ALPHA_P_SHADE = 0.004 - 0.0005*log(PPFD240_SHADE)
CP_SUN = 0.0468*(PPFD240_SUN**(0.6))*exp(0.005*(PPFD24_SUN-PPFD0_SUN))
Expand All @@ -179,6 +177,8 @@ SUBROUTINE CANOPY_BIO( ZK, FCLAI, FCH, LAI, FSUN, PPFD_SUN, &

GammaPPFD_AVE = (GammaPPFD_SUN*FSUN) + (GammaPPFD_SHADE*(1.0-FSUN)) ! average = sum sun and shade weighted by sunlit fraction

GammaPPFD_AVE = MAX( GammaPPFD_AVE, 0.0_rk )

! Get CO2 inhibition factor for isoprene only

if (EMI_IND .eq. 1) then !Isoprene
Expand Down
Loading
Loading