Skip to content

Commit ba52a24

Browse files
committed
This commit introduces multiple changes in the phenology code aiming at making the code a
bit simpler. This is not intended to be bit-for-bit, because some of the changes impact the logic. However, the results shouldn't be dramatically different. 1. Moved the updates for days since last flushing and abscission events to the cumulative time subroutine. 2. Changed the initialisation of the dates of the last flushing/abscission deciduous events, so they can start at negative values. This change should eliminate the need for a few "if" statements in the main phenology subroutine. 3. Added a fourth case for cold deciduous phenology, which forces leaf flushing if plants remain dormant due to cold for a very long time. This should cause these plants to be vulnerable to frost in climates that are too cold for them to survive. 4. Saved some phenology transition tests to logical variables to make the code a bit more readable. 5. Restructured the cold-deciduous phenology code so the different checks are inside an if/elseif/else block (so only one change can happen at any time). 6. Replaced some additional checks for growing degree days that should be taken care by change 2 plus the definition of a growing season
1 parent 7859acd commit ba52a24

File tree

6 files changed

+401
-373
lines changed

6 files changed

+401
-373
lines changed

biogeochem/EDPhysiologyMod.F90

Lines changed: 273 additions & 239 deletions
Large diffs are not rendered by default.

main/EDInitMod.F90

Lines changed: 81 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module EDInitMod
1111
use FatesConstantsMod , only : primaryland
1212
use FatesConstantsMod , only : nearzero
1313
use FatesConstantsMod , only : rsnbl_math_prec
14+
use FatesConstantsMod , only : ndays_per_year
1415
use EDTypesMod , only : min_patch_area_forced
1516
use FatesConstantsMod , only : n_landuse_cats
1617
use FatesConstantsMod , only : is_crop
@@ -48,11 +49,11 @@ module EDInitMod
4849
use FatesConstantsMod , only : isemi_stress_decid
4950
use PRTGenericMod , only : num_elements
5051
use PRTGenericMod , only : element_list
51-
use EDTypesMod , only : phen_cstat_nevercold
52-
use EDTypesMod , only : phen_cstat_iscold
52+
use EDTypesMod , only : phen_cstat_timeoff
53+
use EDTypesMod , only : phen_cstat_tempoff
5354
use EDTypesMod , only : phen_dstat_timeoff
5455
use EDTypesMod , only : phen_dstat_moistoff
55-
use EDTypesMod , only : phen_cstat_notcold
56+
use EDTypesMod , only : phen_cstat_tempon
5657
use EDTypesMod , only : phen_dstat_moiston
5758
use EDTypesMod , only : phen_estat_evergreen
5859
use FatesInterfaceTypesMod , only : bc_in_type,bc_out_type
@@ -393,11 +394,15 @@ subroutine set_site_properties( nsites, sites,bc_in )
393394
!
394395
! !LOCAL VARIABLES:
395396
integer :: s
396-
real(r8) :: GDD ! First guess for growing degree days
397-
real(r8) :: liqvolmem ! First guess for soil water content memory
398-
real(r8) :: smpmem ! First guess for soil matric potential memory
399-
real(r8) :: tempmem ! First guess for temperature memory
400-
real(r8) :: elong_factor ! Elongation factor (0 - fully off; 1 - fully on)
397+
real(r8) :: gdd_1st ! First guess for growing degree days
398+
real(r8) :: liqvolmem_1st ! First guess for soil water content memory
399+
real(r8) :: smpmem_1st ! First guess for soil matric potential memory
400+
real(r8) :: tempmem_1st ! First guess for temperature memory
401+
real(r8) :: elong_factor_1st ! First guess for elongation factor (fraction of leaves
402+
! flushed relative to the maximum given plant size)
403+
! 0 - completely leafless
404+
! 0.5 - 50% of leaves flushed
405+
! 1.0 - 100% of leaves flushed
401406
integer :: leafon ! DOY for last leaf flushing event, initial guess
402407
integer :: leafoff ! DOY for last leaf abscission event, initial guess
403408
integer :: ndleafon ! Elapsed days since last flushing, initial guess
@@ -422,26 +427,26 @@ subroutine set_site_properties( nsites, sites,bc_in )
422427

423428
! For now, we impose that deciduous plants start the simulation fully flushed,
424429
! but with the possibility of switching status if needed.
425-
GDD = 30.0_r8 ! Assume sufficiently warm conditions
426-
liqvolmem = 0.5_r8 ! Assume well watered conditions
427-
smpmem = 0._r8 ! Assume well watered conditions
428-
tmpmem = 15.0_r8 ! Assume sufficiently warm conditions
429-
elong_factor = 1._r8 ! Assume leaves fully flushed.
430+
gdd_1st = 30.0_r8 ! Assume sufficiently warm conditions
431+
liqvolmem_1st = 0.5_r8 ! Assume well watered conditions
432+
smpmem_1st = 0._r8 ! Assume well watered conditions
433+
tempmem_1st = 15.0_r8 ! Assume sufficiently warm conditions
434+
elong_factor_1st = 1._r8 ! Assume leaves fully flushed.
430435

431436
! Set the model integration date since the beginning of time.
432437
model_day_int = floor(hlm_model_day)
433438

434439
do s = 1,nsites
435-
436440
! Define the last flushing and abscission dates based on the hemisphere. This
437-
! is to avoid the dates to be too far from optimal in the Southern Hemisphere,
438-
! which could make deciduous plants spend multiple years until synchronising with
439-
! the local climate. For now, both cold- and drought-deciduous default to leaf
440-
! flushing during spring, and to leaf abscission during autumn. This assumes winter
441-
! dry season, which is common in many tropical regions. This is still not ideal
442-
! for some tropical and Mediterranean climates, which peak greenness during autumn
443-
! or spring. In the future, we could consider implementing some map that allows
444-
! assigning the expected dates for each location.
441+
! is to avoid first guess dates that are too far from optimal in the Southern
442+
! Hemisphere, which could make deciduous plants spend multiple years until
443+
! synchronising with the local climate. For now, both cold- and drought-deciduous
444+
! dates default to leaf flushing during spring, and to leaf abscission during
445+
! autumn. This assumes winter dry season, which is common in many tropical
446+
! regions. This is still not ideal for some tropical areas and for Mediterranean
447+
! climates, in which peak greenness occurs during autumn or spring, respectively.
448+
! In the future, we could consider implementing some map that allows assigning
449+
! the expected dates for each location.
445450
if (sites(s)%lat > 0._r8) then
446451
leafon = 100 - hlm_day_of_year
447452
leafoff = 300 - hlm_day_of_year
@@ -450,10 +455,11 @@ subroutine set_site_properties( nsites, sites,bc_in )
450455
leafoff = 120 - hlm_day_of_year
451456
end if
452457

453-
! Make sure the initial dates for last leaf abscission and leaf flushing events
454-
! precede the the beginning of the simulation. This check used to occur inside the
455-
! integrator, but it is better to ensure this during initialisation, so we reduce
456-
! the number of logical tests during time steps.
458+
459+
! Make sure the initial dates for last leaf abscission and leaf flushing
460+
! events precede the the beginning of the simulation. This check used to occur
461+
! inside the integrator, but it is better to ensure this during initialisation,
462+
! so we reduce the number of logical tests during time steps.
457463
if ( leafon > model_day_int ) then
458464
leafon = leafon - ndays_per_year
459465
end if
@@ -469,60 +475,57 @@ subroutine set_site_properties( nsites, sites,bc_in )
469475
ndleafoff = model_day_int - leafoff
470476

471477

472-
estat = phen_estat_evergreen
473-
cstat = phen_cstat_notcold ! Leaves are on
474-
dstat = phen_dstat_moiston ! Leaves are on
475-
476-
477-
! We set the number of chilling days and cold days to zero. This will be
478-
sites(s)%nchilldays(1:numpft) = 0
479-
sites(s)%ncolddays(1:numpft) = 0 ! recalculated in phenology
480-
! immediately, so yes this
481-
! is memory-less, but needed
482-
! for first value in history file
483-
sites(s)%phen_model_date = model_day_int
484-
sites(s)%grow_deg_days(1:numpft) = GDD
485-
486-
sites(s)%liqvol_memory(1:numWaterMem,1:numpft) = liqvolmem
487-
sites(s)%smp_memory(1:numWaterMem,1:numpft) = smpmem
488-
sites(s)%vegtemp_memory(1:num_vegtemp_mem) = tempmem
489-
490-
do ft = 1, numpft
491-
! These must be updated once the new parameter is integrated to FATES.
492-
select case (prt_params%evergreen(ft))
493-
case (itrue)
478+
!---~---
479+
! Initialise site-level variables that are not PFT specific or that can be
480+
! set for all PFTs without considering the leaf phenological habit. Some of
481+
! the memory and cumulative variables are currently used only for leaf
482+
! phenology, but they may be useful for other modules, so they are set for
483+
! all PFTs.
484+
! Some variables such as ncolddays are recalculated every day (memoryless)
485+
! but they need an initial value so they are defined for the first history
486+
! file.
487+
!---~---
488+
sites(s)%phen_model_date = model_day_int
489+
sites(s)%vegtemp_memory(1:num_vegtemp_mem) = tempmem_1st
490+
sites(s)%liqvol_memory (1:numWaterMem,1:numpft) = liqvolmem_1st
491+
sites(s)%smp_memory (1:numWaterMem,1:numpft) = smpmem_1st
492+
sites(s)%grow_deg_days (1:numpft) = gdd_1st
493+
sites(s)%nchilldays (1:numpft) = 0
494+
sites(s)%ncolddays (1:numpft) = 0
495+
sites(s)%elong_factor (1:numpft) = elong_factor_1st
496+
497+
498+
499+
!---~---
500+
! Fill in variables that do require checks for leaf phenology habit.
501+
!---~---
502+
do_phen_pft_init: do ft = 1, numpft
503+
case_leaf_habit: select case (prt_params%phen_leaf_habit(ft))
504+
case (ievergreen)
494505
! Evergreens. Phenological status is not used, set it accordingly.
495-
! Assign dummy values to other values.
496-
sites(s)%phen_status (ft) = estat
497-
sites(s)%leafondate (ft) = cleafon - hlm_day_of_year
498-
sites(s)%leafoffdate (ft) = cleafoff - hlm_day_of_year
499-
sites(s)%ndaysleafon (ft) = 0
500-
sites(s)%ndaysleafoff(ft) = 0
501-
end select
502-
503-
select case (prt_params%season_decid(ft))
504-
case (itrue)
505-
! Cold deciduous
506-
sites(s)%phen_status (ft) = cstat
507-
sites(s)%leafondate (ft) = cleafon - hlm_day_of_year
508-
sites(s)%leafoffdate (ft) = cleafoff - hlm_day_of_year
509-
sites(s)%ndaysleafon (ft) = cndleafon
510-
sites(s)%ndaysleafoff(ft) = cndleafoff
511-
end select
512-
513-
514-
select case (prt_params%stress_decid(ft))
506+
sites(s)%phen_status (ft) = phen_estat_evergreen
507+
case (ihard_season_decid)
508+
! Cold deciduous. Initialise both status and time since last flushing
509+
! and abscission days. We assume the initial status to be with leaves
510+
! fully flushed.
511+
sites(s)%phen_status (ft) = phen_cstat_tempon
512+
sites(s)%leafondate (ft) = leafon
513+
sites(s)%leafoffdate (ft) = leafoff
514+
sites(s)%ndaysleafon (ft) = ndleafon
515+
sites(s)%ndaysleafoff(ft) = ndleafoff
515516
case (ihard_stress_decid,isemi_stress_decid)
516-
! Drought deciduous
517-
sites(s)%phen_status (ft) = dstat
518-
sites(s)%leafondate (ft) = dleafon - hlm_day_of_year
519-
sites(s)%leafoffdate (ft) = dleafoff - hlm_day_of_year
520-
sites(s)%ndaysleafon (ft) = dndleafon
521-
sites(s)%ndaysleafoff(ft) = dndleafoff
522-
end select
523-
end do
517+
! Drought deciduous. Initialise both status and time since last flushing
518+
! and abscission days. We assume the initial status to be with leaves
519+
! fully flushed.
520+
sites(s)%phen_status (ft) = phen_dstat_moiston
521+
sites(s)%leafondate (ft) = leafon
522+
sites(s)%leafoffdate (ft) = leafoff
523+
sites(s)%ndaysleafon (ft) = ndleafon
524+
sites(s)%ndaysleafoff(ft) = ndleafoff
525+
end select case_leaf_habit
526+
end do do_phen_pft_init
527+
!---~---
524528

525-
sites(s)%elong_factor(1:numpft) = elong_factor
526529

527530
sites(s)%NF = 0.0_r8
528531
sites(s)%NF_successful = 0.0_r8
@@ -1206,7 +1209,7 @@ subroutine init_cohorts(site_in, patch_in, bc_in)
12061209
phen_select: select case (prt_params%phen_leaf_habit(pft))
12071210
case (ihard_season_decid)
12081211
select case (site_in%phen_status(pft))
1209-
case (phen_cstat_nevercold, phen_cstat_iscold)
1212+
case (phen_cstat_tempoff, phen_cstat_timeoff)
12101213
! Cold deciduous, off season, assume complete abscission
12111214
efleaf_coh = 0.0_r8
12121215
effnrt_coh = 1.0_r8 - fnrt_drop_fraction

main/EDTypesMod.F90

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,19 @@ module EDTypesMod
9898
! The default phen_estat_evergreen is a dummy value reserved for evergreen PFTs.
9999

100100
integer, parameter, public :: phen_estat_evergreen = 0 ! This PFT is evergreen.
101-
integer, parameter, public :: phen_cstat_nevercold = 1 ! This (location/plant) has not experienced a cold period over a large number
102-
! of days, leaves are dropped and flagged as non-cold region
103-
integer, parameter, public :: phen_cstat_iscold = 2 ! This (location/plant) is in a cold-state where leaves should have fallen
104-
integer, parameter, public :: phen_cstat_notcold = 3 ! This site is in a warm-state where leaves are allowed to flush
105-
106-
integer, parameter, public :: phen_dstat_timeoff = 4 ! Leaves off due to time exceedance (drought phenology)
107-
integer, parameter, public :: phen_dstat_moistoff = 5 ! Leaves off due to moisture avail (drought phenology)
108-
integer, parameter, public :: phen_dstat_moiston = 6 ! Leaves on due to moisture avail (drought phenology)
109-
integer, parameter, public :: phen_dstat_timeon = 7 ! Leaves on due to time exceedance (drought phenology)
110-
integer, parameter, public :: phen_dstat_pshed = 8 ! Leaves partially abscissing (drought phenology)
101+
102+
! Season (cold) deciduous flags
103+
integer, parameter, public :: phen_cstat_timeoff = 1 ! - Leaves off due to time, leaves exceeded life span without cold days
104+
integer, parameter, public :: phen_cstat_tempoff = 2 ! - Leaves off after reaching multiple cold days
105+
integer, parameter, public :: phen_cstat_tempon = 3 ! - Leaves on after exceeding the growing degree day threshold
106+
integer, parameter, public :: phen_cstat_timeon = 4 ! - Leaves on after extended cold period, forced flushing
107+
108+
! Stress (drought) deciduous flags
109+
integer, parameter, public :: phen_dstat_timeoff = 5 ! Leaves off due to time, leaves exceeded life span without desiccation
110+
integer, parameter, public :: phen_dstat_moistoff = 6 ! Leaves off after moisture availability fell below the threshold
111+
integer, parameter, public :: phen_dstat_moiston = 7 ! Leaves on after moisture availability increased above the threshold
112+
integer, parameter, public :: phen_dstat_timeon = 8 ! Leaves on after extended dry period, forced flushing
113+
integer, parameter, public :: phen_dstat_pshed = 9 ! Leaves partially abscissing due to drying conditions
111114

112115
! PATCH FUSION
113116
real(r8), parameter, public :: force_patchfuse_min_biomass = 0.005_r8 ! min biomass (kg / m2 patch area) below which to force-fuse patches

main/FatesCumulativeMemoryMod.F90

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,20 @@ module FatesCumulativeMemoryMod
1414
use EDTypesMod , only : ed_site_type
1515
use EDTypesMod , only : num_vegtemp_mem
1616
use EDTypesMod , only : numWaterMem
17-
use EDTypesMod , only : phen_cstat_iscold
1817
use FatesAllometryMod , only : set_root_fraction
18+
use FatesConstantsMod , only : ievergreen
19+
use FatesConstantsMod , only : ihard_season_decid
20+
use FatesConstantsMod , only : ihard_stress_decid
21+
use FatesConstantsMod , only : isemi_stress_decid
1922
use FatesConstantsMod , only : ndays_per_year
2023
use FatesConstantsMod , only : nearzero
2124
use FatesConstantsMod , only : r8 => fates_r8
2225
use FatesConstantsMod , only : tfrz => t_water_freeze_k_1atm
2326
use FatesInterfaceTypesMod, only : bc_in_type
24-
use FatesInterfaceTypesMod, only : hlm_day_of_year
27+
use FatesInterfaceTypesMod, only : hlm_model_day
2528
use FatesInterfaceTypesMod, only : numpft
2629
use FatesPatchMod , only : fates_patch_type
30+
use PRTParametersMod , only : prt_params
2731

2832
implicit none
2933
private
@@ -66,7 +70,6 @@ subroutine UpdateCumulativeMemoryVars(currentSite,bc_in)
6670
! Update moisture-related memory variables.
6771
call UpdateMemoryMoisture(currentSite,bc_in)
6872

69-
return
7073
end subroutine UpdateCumulativeMemoryVars
7174

7275

@@ -84,53 +87,37 @@ subroutine UpdatePhenologyDate(currentSite)
8487
! Arguments
8588
type(ed_site_type), intent(inout), target :: currentSite
8689
! Local variables
87-
integer :: ipft
88-
integer :: date_offset_off
89-
integer :: date_offset_on
90+
integer :: ipft ! PFT index
9091

9192
!---~---
92-
! Advance elapsed time. The only reason this is a site variable instead of a
93-
! global variable is that we need to save this information to the restart file,
94-
! and we do not have global scalars in the restart file.
93+
! Advance elapsed time, by using the host land model variable. The only reason
94+
! this is a site variable instead of a global variable is that we need to save this
95+
! information to the restart file, and we do not have global scalars in the restart
96+
! file. This value starts at zero and increases indefinitely.
9597
!---~---
96-
currentSite%phen_model_date = currentSite%phen_model_date + 1
98+
currentSite%phen_model_date = floor(hlm_model_day)
9799

98100

99-
!---~---
100-
! Update the number of days since last flushing and abscission events.
101-
!---~---
101+
! Update the number of days since last flushing and abscission events. This is
102+
! done for deciduous PFTs only.
102103
do ipft = 1, numpft
103-
104-
! If this is the beginning of the simulation, the last leaf abscission and/or
105-
! the last flushing events may have occurred before
106-
! might not had occured yet, so set it to last year to get things rolling.
107-
if ( model_day_int < currentSite%leafoffdate(ipft) ) then
108-
date_offset = ndays_per_year
109-
else
110-
date_offset = 0
111-
end if
112-
113-
114-
! Calculate the number of days since the last leaf flushing and leaf
115-
! abscission events.
116-
104+
select case (prt_params%phen_leaf_habit(ipft))
105+
case (ihard_season_decid,ihard_stress_decid,isemi_stress_decid)
106+
!---~---
107+
! Update the number of days since last flushing and abscission events, by
108+
! using the current date and the dates of the last events. Note that we no
109+
! longer need to check whether this is the beginning of the simulation,
110+
! because the cold start initialisation already fixes the dates of the last
111+
! event to be prior to the beginning of the simulation.
112+
!---~---
117113
currentSite%ndaysleafoff(ipft) = &
118-
currentSite%phen_model_date - (currentSite%leafoffdate(ipft) - ndays_per_year)
119-
else
120-
currentSite%ndaysleafoff(ipft) =
121-
model_day_int - currentSite%leafoffdate(ipft)
122-
end if
123-
124-
if (model_day_int < currentSite%leafondate(ipft)) then
125-
currentSite%ndaysleafon(ipft) = model_day_int - (currentSite%leafondate(ipft) - ndays_per_year)
126-
else
127-
currentSite%ndaysleafon(ipft) = model_day_int - currentSite%leafondate(ipft)
128-
end if
114+
currentSite%phen_model_date - currentSite%leafoffdate(ipft)
115+
currentSite%ndaysleafon (ipft) = &
116+
currentSite%phen_model_date - currentSite%leafondate (ipft)
117+
end select
129118
end do
130119
!---~---
131120

132-
133-
return
134121
end subroutine UpdatePhenologyDate
135122

136123

@@ -181,7 +168,6 @@ subroutine UpdateCumulativeThermal(currentSite,bc_in)
181168
currentSite%vegtemp_memory(1) = temp_in_C
182169

183170

184-
return
185171
end subroutine UpdateCumulativeThermal
186172

187173

@@ -262,6 +248,5 @@ subroutine UpdateMemoryMoisture(currentSite,bc_in)
262248
end do pft_memory_loop
263249

264250

265-
return
266251
end subroutine UpdateMemoryMoisture
267252
end module FatesCumulativeMemoryMod

0 commit comments

Comments
 (0)