Skip to content
60 changes: 37 additions & 23 deletions biogeochem/EDPatchDynamicsMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ module EDPatchDynamicsMod
use FatesConstantsMod , only : nocomp_bareground
use FatesInterfaceTypesMod , only : hlm_use_planthydro
use FatesInterfaceTypesMod , only : bc_in_type
use FatesInterfaceTypesMod , only : bc_out_type
use FatesInterfaceTypesMod , only : numpft
use FatesInterfaceTypesMod , only : hlm_stepsize
use FatesInterfaceTypesMod , only : hlm_use_sp
Expand Down Expand Up @@ -482,7 +483,7 @@ end subroutine disturbance_rates

! ============================================================================

subroutine spawn_patches( currentSite, bc_in)
subroutine spawn_patches( currentSite, bc_in, bc_out)
!
! !DESCRIPTION:
! In this subroutine, the following happens,
Expand All @@ -509,6 +510,7 @@ subroutine spawn_patches( currentSite, bc_in)
! !ARGUMENTS:
type (ed_site_type), intent(inout) :: currentSite
type (bc_in_type), intent(in) :: bc_in
type (bc_out_type), intent(inout) :: bc_out
!
! !LOCAL VARIABLES:
type (fates_patch_type) , pointer :: newPatch
Expand Down Expand Up @@ -753,7 +755,9 @@ subroutine spawn_patches( currentSite, bc_in)

call CopyPatchMeansTimers(currentPatch, newPatch)

call TransLitterNewPatch( currentSite, currentPatch, newPatch, patch_site_areadis, i_disturbance_type)

call TransLitterNewPatch( currentSite, currentPatch, newPatch, patch_site_areadis, bc_out, i_disturbance_type)


! Transfer in litter fluxes from plants in various contexts of death and destruction
select case(i_disturbance_type)
Expand All @@ -768,13 +772,13 @@ subroutine spawn_patches( currentSite, bc_in)
end if
case (dtype_ifire)
call fire_litter_fluxes(currentSite, currentPatch, &
newPatch, patch_site_areadis,bc_in)
newPatch, patch_site_areadis,bc_in, bc_out)
case (dtype_ifall)
call mortality_litter_fluxes(currentSite, currentPatch, &
newPatch, patch_site_areadis,bc_in)
case (dtype_ilandusechange)
call landusechange_litter_fluxes(currentSite, currentPatch, &
newPatch, patch_site_areadis,bc_in, &
newPatch, patch_site_areadis,bc_in, bc_out, &
clearing_matrix(i_donorpatch_landuse_type,i_landusechange_receiverpatchlabel))

! if land use change, then may need to change nocomp pft, so tag as having transitioned LU
Expand Down Expand Up @@ -1068,11 +1072,8 @@ subroutine spawn_patches( currentSite, bc_in)
currentSite%mass_balance(el)%burn_flux_to_atm + &
leaf_burn_frac * leaf_m * nc%n

! This diagnostic only tracks
currentSite%flux_diags%elem(el)%burned_liveveg = &
currentSite%flux_diags%elem(el)%burned_liveveg + &
leaf_burn_frac * leaf_m * nc%n * area_inv

bc_out%fire_closs_to_atm_si = bc_out%fire_closs_to_atm_si + &
leaf_burn_frac * leaf_m * nc%n * ha_per_m2 * days_per_sec
end do

! Here the mass is removed from the plant
Expand Down Expand Up @@ -1421,7 +1422,7 @@ subroutine spawn_patches( currentSite, bc_in)

allocate(temp_patch)

call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep, newp_area)
call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep, newp_area, bc_out)
!
temp_patch%nocomp_pft_label = 0

Expand Down Expand Up @@ -1524,7 +1525,7 @@ subroutine spawn_patches( currentSite, bc_in)
! split buffer patch in two, keeping the smaller buffer patch to put into new patches
allocate(temp_patch)

call split_patch(currentSite, buffer_patch, temp_patch, fraction_to_keep, newp_area)
call split_patch(currentSite, buffer_patch, temp_patch, fraction_to_keep, newp_area, bc_out)

! give the new patch the intended nocomp PFT label
temp_patch%nocomp_pft_label = i_pft
Expand Down Expand Up @@ -1633,7 +1634,7 @@ end subroutine spawn_patches

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

subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep, area_to_remove)
subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep, area_to_remove, bc_out)
!
! !DESCRIPTION:
! Split a patch into two patches that are identical except in their areas
Expand All @@ -1644,6 +1645,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep, a
type(fates_patch_type) , intent(inout), pointer :: new_patch ! New Patch
real(r8), intent(in) :: fraction_to_keep ! fraction of currentPatch to keep, the rest goes to newpatch
real(r8), intent(in), optional :: area_to_remove ! area of currentPatch to remove, the rest goes to newpatch
type(bc_out_type) , intent(inout) :: bc_out
!
! !LOCAL VARIABLES:
integer :: el ! element loop index
Expand Down Expand Up @@ -1680,7 +1682,8 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep, a

call CopyPatchMeansTimers(currentPatch, new_patch)

call TransLitterNewPatch( currentSite, currentPatch, new_patch, temp_area, 0)
call TransLitterNewPatch( currentSite, currentPatch, new_patch, temp_area, bc_out, 0)


! Next, we loop through the cohorts in the donor patch, copy them with
! area modified number density into the new-patch, and apply survivorship.
Expand Down Expand Up @@ -1814,8 +1817,7 @@ end subroutine check_patch_area
subroutine TransLitterNewPatch(currentSite, &
currentPatch, &
newPatch, &
patch_site_areadis, &
dist_type)
patch_site_areadis, bc_out, dist_type)

! -----------------------------------------------------------------------------------
!
Expand Down Expand Up @@ -1864,8 +1866,8 @@ subroutine TransLitterNewPatch(currentSite, &
type(fates_patch_type) , intent(inout) :: newPatch ! New patch
real(r8) , intent(in) :: patch_site_areadis ! Area being donated
! by current patch
type(bc_out_type) , intent(inout) :: bc_out
integer, intent(in) :: dist_type ! disturbance type


! locals
type(site_massbal_type), pointer :: site_mass
Expand Down Expand Up @@ -1989,7 +1991,9 @@ subroutine TransLitterNewPatch(currentSite, &
curr_litt%ag_cwd(c) = curr_litt%ag_cwd(c) + donatable_mass*retain_m2

site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass


bc_out%fire_closs_to_atm_si = bc_out%fire_closs_to_atm_si + burned_mass * ha_per_m2 * days_per_sec

! Transfer below ground CWD (none burns)

do sl = 1,currentSite%nlevsoil
Expand Down Expand Up @@ -2018,7 +2022,9 @@ subroutine TransLitterNewPatch(currentSite, &
curr_litt%leaf_fines(dcmpy) = curr_litt%leaf_fines(dcmpy) + donatable_mass*retain_m2

site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass


bc_out%fire_closs_to_atm_si = bc_out%fire_closs_to_atm_si + burned_mass * ha_per_m2 * days_per_sec

! Transfer root fines (none burns)
do sl = 1,currentSite%nlevsoil
donatable_mass = curr_litt%root_fines(dcmpy,sl) * patch_site_areadis
Expand Down Expand Up @@ -2068,7 +2074,7 @@ end subroutine TransLitterNewPatch
! ============================================================================

subroutine fire_litter_fluxes(currentSite, currentPatch, &
newPatch, patch_site_areadis, bc_in)
newPatch, patch_site_areadis, bc_in, bc_out)
!
! !DESCRIPTION:
! CWD pool burned by a fire.
Expand All @@ -2088,6 +2094,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, &
type(fates_patch_type) , intent(inout), target :: newPatch ! New Patch
real(r8) , intent(in) :: patch_site_areadis ! Area being donated
type(bc_in_type) , intent(in) :: bc_in
type(bc_out_type) , intent(inout) :: bc_out

!
! !LOCAL VARIABLES:
Expand Down Expand Up @@ -2229,8 +2236,8 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, &

site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass


bc_out%fire_closs_to_atm_si = bc_out%fire_closs_to_atm_si + burned_mass * ha_per_m2 * days_per_sec

call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, &
bc_in%max_rooting_depth_index_col)

Expand Down Expand Up @@ -2292,6 +2299,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, &
burned_mass = num_dead_trees * SF_val_CWD_frac_adj(c) * bstem * &
currentCohort%fraction_crown_burned
site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass
bc_out%fire_closs_to_atm_si = bc_out%fire_closs_to_atm_si + burned_mass * ha_per_m2 * days_per_sec
endif
new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + donatable_mass * donate_m2
curr_litt%ag_cwd(c) = curr_litt%ag_cwd(c) + donatable_mass * retain_m2
Expand Down Expand Up @@ -2542,7 +2550,7 @@ end subroutine mortality_litter_fluxes
! ============================================================================

subroutine landusechange_litter_fluxes(currentSite, currentPatch, &
newPatch, patch_site_areadis, bc_in, &
newPatch, patch_site_areadis, bc_in, bc_out, &
clearing_matrix_element)
!
! !DESCRIPTION:
Expand All @@ -2559,6 +2567,7 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, &
type(fates_patch_type) , intent(inout), target :: newPatch ! New Patch
real(r8) , intent(in) :: patch_site_areadis ! Area being donated
type(bc_in_type) , intent(in) :: bc_in
type(bc_out_type) , intent(inout) :: bc_out
logical , intent(in) :: clearing_matrix_element ! whether or not to clear vegetation

!
Expand Down Expand Up @@ -2702,7 +2711,9 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, &
end do

site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass


bc_out%fire_closs_to_atm_si = bc_out%fire_closs_to_atm_si + burned_mass * ha_per_m2 * days_per_sec

call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, &
bc_in%max_rooting_depth_index_col)

Expand Down Expand Up @@ -2762,6 +2773,7 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, &
EDPftvarcon_inst%landusechange_frac_burned(pft)

site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass
bc_out%fire_closs_to_atm_si = bc_out%fire_closs_to_atm_si + burned_mass * ha_per_m2 * days_per_sec
else ! all other pools can end up as timber products or burn or go to litter
donatable_mass = donatable_mass * (1.0_r8-EDPftvarcon_inst%landusechange_frac_exported(pft)) * &
(1.0_r8-EDPftvarcon_inst%landusechange_frac_burned(pft))
Expand All @@ -2775,6 +2787,8 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, &

site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass

bc_out%fire_closs_to_atm_si = bc_out%fire_closs_to_atm_si + burned_mass * ha_per_m2 * days_per_sec

trunk_product_site = trunk_product_site + &
woodproduct_mass

Expand Down
72 changes: 39 additions & 33 deletions biogeochem/EDPhysiologyMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ module EDPhysiologyMod
use FatesConstantsMod, only : megajoules_per_joule
use FatesConstantsMod, only : mpa_per_mm_suction
use FatesConstantsMod, only : g_per_kg
use FatesConstantsMod, only : ha_per_m2
use FatesConstantsMod, only : days_per_sec
use FatesConstantsMod, only : ndays_per_year
use FatesConstantsMod, only : nocomp_bareground
use FatesConstantsMod, only : nocomp_bareground_land
Expand Down Expand Up @@ -432,16 +434,15 @@ end subroutine GenerateDamageAndLitterFluxes

! ============================================================================

subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in )
subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in, bc_out )

! -----------------------------------------------------------------------------------
!
! This subroutine calculates all of the different litter input and output fluxes
! associated with seed turnover, seed influx, litterfall from live and
! dead plants, germination, and fragmentation.
!
! At this time we do not have explicit herbivory, and burning losses to litter
! are handled elsewhere.
! Herbivory is handled here. burning losses to litter are handled elsewhere.
!
! Note: The processes conducted here DO NOT handle litter fluxes associated
! with disturbance. Those fluxes are handled elsewhere (EDPatchDynamcisMod)
Expand All @@ -455,6 +456,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in )
type(ed_site_type), intent(inout) :: currentSite
type(fates_patch_type), intent(inout) :: currentPatch
type(bc_in_type), intent(in) :: bc_in
type(bc_out_type), intent(inout) :: bc_out

!
! !LOCAL VARIABLES:
Expand All @@ -473,34 +475,33 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in )
site_mass => currentSite%mass_balance(el), &
diag => currentSite%flux_diags%elem(el))

! Calculate loss rate of viable seeds to litter
call SeedDecay(litt, currentPatch, bc_in)

! Calculate seed germination rate, the status flags prevent
! germination from occuring when the site is in a drought
! (for drought deciduous) or too cold (for cold deciduous)
call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus(1:numpft), bc_in, currentPatch)

! Send fluxes from newly created litter into the litter pools
! This litter flux is from non-disturbance inducing mortality, as well
! as litter fluxes from live trees
call CWDInput(currentSite, currentPatch, litt,bc_in)

! Only calculate fragmentation flux over layers that are active
! (RGK-Mar2019) SHOULD WE MAX THIS AT 1? DONT HAVE TO

nlev_eff_decomp = max(bc_in%max_rooting_depth_index_col, 1)
call CWDOut(litt,currentPatch%fragmentation_scaler,nlev_eff_decomp)

! Fragmentation flux to soil decomposition model [kg/site/day]
site_mass%frag_out = site_mass%frag_out + currentPatch%area * &
( sum(litt%ag_cwd_frag) + sum(litt%bg_cwd_frag) + &
sum(litt%leaf_fines_frag) + sum(litt%root_fines_frag) + &
sum(litt%seed_decay) + sum(litt%seed_germ_decay))

! Track total seed decay diagnostic in [kg/m2/day]
diag%tot_seed_turnover = diag%tot_seed_turnover + &
(sum(litt%seed_decay) + sum(litt%seed_germ_decay))*currentPatch%area*area_inv
! Calculate loss rate of viable seeds to litter
call SeedDecay(litt, currentPatch, bc_in)


! Calculate seed germination rate, the status flags prevent
! germination from occuring when the site is in a drought
! (for drought deciduous) or too cold (for cold deciduous)
call SeedGermination(litt, currentSite%cstatus, currentSite%dstatus(1:numpft), bc_in, currentPatch)

! Send fluxes from newly created litter into the litter pools
! This litter flux is from non-disturbance inducing mortality, as well
! as litter fluxes from live trees
call CWDInput(currentSite, currentPatch, litt,bc_in, bc_out)

! Only calculate fragmentation flux over layers that are active
! (RGK-Mar2019) SHOULD WE MAX THIS AT 1? DONT HAVE TO

nlev_eff_decomp = max(bc_in%max_rooting_depth_index_col, 1)
call CWDOut(litt,currentPatch%fragmentation_scaler,nlev_eff_decomp)


! Fragmentation flux to soil decomposition model [kg/site/day]
site_mass%frag_out = site_mass%frag_out + currentPatch%area * &
( sum(litt%ag_cwd_frag) + sum(litt%bg_cwd_frag) + &
sum(litt%leaf_fines_frag) + sum(litt%root_fines_frag) + &
sum(litt%seed_decay) + sum(litt%seed_germ_decay))


end associate
end do
Expand Down Expand Up @@ -2785,7 +2786,7 @@ end subroutine recruitment

! ======================================================================================

subroutine CWDInput( currentSite, currentPatch, litt, bc_in)
subroutine CWDInput( currentSite, currentPatch, litt, bc_in, bc_out)

!
! !DESCRIPTION:
Expand All @@ -2805,6 +2806,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in)
type(fates_patch_type),intent(inout), target :: currentPatch
type(litter_type),intent(inout),target :: litt
type(bc_in_type),intent(in) :: bc_in
type(bc_out_type),intent(inout) :: bc_out

!
! !LOCAL VARIABLES:
Expand Down Expand Up @@ -2952,12 +2954,16 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in)
elflux_diags%root_litter_input(pft) + &
(fnrt_m_turnover + store_m_turnover ) * currentCohort%n

! send the part of the herbivory flux that doesn't go to litter to the atmosphere
! send the part of the herbivory flux that doesn't go to litter to the atmosphere (and also for tracking)

site_mass%herbivory_flux_out = &
site_mass%herbivory_flux_out + &
leaf_herbivory * (1._r8 - herbivory_element_use_efficiency) * currentCohort%n

bc_out%grazing_closs_to_atm_si = bc_out%grazing_closs_to_atm_si + &
leaf_herbivory * (1._r8 - herbivory_element_use_efficiency) * currentCohort%n * &
ha_per_m2 * days_per_sec

! Assumption: turnover from deadwood and sapwood are lumped together in CWD pool

!update partitioning of stem wood (struct + sapw) to cwd based on cohort dbh
Expand Down
Loading