diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index bbadcb320d..b45ad0e257 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -33,6 +33,7 @@ Module EDCohortDynamicsMod use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type + use FatesLitterMod , only : adjust_SF_CWD_frac use EDParamsMod , only : max_cohort_per_patch use EDTypesMod , only : AREA use EDTypesMod , only : min_npm2, min_nppatch @@ -1022,7 +1023,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) integer :: crowndamage ! the crown damage class of the cohort integer :: sl ! loop index for soil layers integer :: dcmpy ! loop index for decomposability - + real(r8) :: SF_val_CWD_frac_adj(4) !Updated wood partitioning to CWD based on dbh !---------------------------------------------------------------------- pft = ccohort%pft @@ -1052,29 +1053,32 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) litt => cpatch%litter(el) flux_diags => csite%flux_diags(el) + !adjust how wood is partitioned between the cwd classes based on cohort dbh + call adjust_SF_CWD_frac(ccohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + do c=1,ncwd ! above ground CWD litt%ag_cwd(c) = litt%ag_cwd(c) + plant_dens * & - (struct_m+sapw_m) * SF_val_CWD_frac(c) * & + (struct_m+sapw_m) * SF_val_CWD_frac_adj(c) * & prt_params%allom_agb_frac(pft) ! below ground CWD do sl=1,csite%nlevsoil litt%bg_cwd(c,sl) = litt%bg_cwd(c,sl) + plant_dens * & - (struct_m+sapw_m) * SF_val_CWD_frac(c) * & + (struct_m+sapw_m) * SF_val_CWD_frac_adj(c) * & (1.0_r8 - prt_params%allom_agb_frac(pft)) * & csite%rootfrac_scr(sl) enddo ! above ground flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - (struct_m+sapw_m) * SF_val_CWD_frac(c) * & + (struct_m+sapw_m) * SF_val_CWD_frac_adj(c) * & prt_params%allom_agb_frac(pft) * nplant ! below ground flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & - (struct_m + sapw_m) * SF_val_CWD_frac(c) * & + (struct_m + sapw_m) * SF_val_CWD_frac_adj(c) * & (1.0_r8 - prt_params%allom_agb_frac(pft)) * nplant enddo diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index a98dd055cf..537d62642c 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -22,6 +22,7 @@ module EDLoggingMortalityMod use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type + use FatesLitterMod , only : adjust_SF_CWD_frac use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_resources_management_type use EDTypesMod , only : dtype_ilog @@ -766,7 +767,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site integer :: nlevsoil ! number of soil layers integer :: ilyr ! soil layer loop index integer :: el ! elemend loop index - + real(r8) :: SF_val_CWD_frac_adj(4) !Updated wood partitioning to CWD based on dbh nlevsoil = currentSite%nlevsoil @@ -870,37 +871,40 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site prt_params%allom_agb_frac(currentCohort%pft) bg_wood = (direct_dead+indirect_dead) * (struct_m + sapw_m ) * & (1._r8 - prt_params%allom_agb_frac(currentCohort%pft)) - - do c = 1,ncwd-1 + + !adjust how wood is partitioned between the cwd classes based on cohort dbh + call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + + do c = 1,ncwd-1 new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + & - ag_wood * SF_val_CWD_frac(c) * donate_m2 + ag_wood * SF_val_CWD_frac_adj(c) * donate_m2 cur_litt%ag_cwd(c) = cur_litt%ag_cwd(c) + & - ag_wood * SF_val_CWD_frac(c) * retain_m2 + ag_wood * SF_val_CWD_frac_adj(c) * retain_m2 do ilyr = 1,nlevsoil new_litt%bg_cwd(c,ilyr) = new_litt%bg_cwd(c,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(c) * donate_m2 + SF_val_CWD_frac_adj(c) * donate_m2 cur_litt%bg_cwd(c,ilyr) = cur_litt%bg_cwd(c,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(c) * retain_m2 + SF_val_CWD_frac_adj(c) * retain_m2 end do ! Diagnostics on fluxes into the AG and BG CWD pools flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * ag_wood + SF_val_CWD_frac_adj(c) * ag_wood flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & - SF_val_CWD_frac(c) * bg_wood + SF_val_CWD_frac_adj(c) * bg_wood ! Diagnostic specific to resource management code if( element_id .eq. carbon12_element) then delta_litter_stock = delta_litter_stock + & - (ag_wood + bg_wood) * SF_val_CWD_frac(c) + (ag_wood + bg_wood) * SF_val_CWD_frac_adj(c) end if enddo @@ -915,39 +919,39 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site (1._r8 - prt_params%allom_agb_frac(currentCohort%pft)) new_litt%ag_cwd(ncwd) = new_litt%ag_cwd(ncwd) + ag_wood * & - SF_val_CWD_frac(ncwd) * donate_m2 + SF_val_CWD_frac_adj(ncwd) * donate_m2 cur_litt%ag_cwd(ncwd) = cur_litt%ag_cwd(ncwd) + ag_wood * & - SF_val_CWD_frac(ncwd) * retain_m2 + SF_val_CWD_frac_adj(ncwd) * retain_m2 do ilyr = 1,nlevsoil new_litt%bg_cwd(ncwd,ilyr) = new_litt%bg_cwd(ncwd,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(ncwd) * donate_m2 + SF_val_CWD_frac_adj(ncwd) * donate_m2 cur_litt%bg_cwd(ncwd,ilyr) = cur_litt%bg_cwd(ncwd,ilyr) + & bg_wood * currentSite%rootfrac_scr(ilyr) * & - SF_val_CWD_frac(ncwd) * retain_m2 + SF_val_CWD_frac_adj(ncwd) * retain_m2 end do flux_diags%cwd_ag_input(ncwd) = flux_diags%cwd_ag_input(ncwd) + & - SF_val_CWD_frac(ncwd) * ag_wood + SF_val_CWD_frac_adj(ncwd) * ag_wood flux_diags%cwd_bg_input(ncwd) = flux_diags%cwd_bg_input(ncwd) + & - SF_val_CWD_frac(ncwd) * bg_wood + SF_val_CWD_frac_adj(ncwd) * bg_wood if( element_id .eq. carbon12_element) then delta_litter_stock = delta_litter_stock + & - (ag_wood+bg_wood) * SF_val_CWD_frac(ncwd) + (ag_wood+bg_wood) * SF_val_CWD_frac_adj(ncwd) end if ! --------------------------------------------------------------------------------------- ! Handle below-ground trunk flux for directly logged trees (c = ncwd) ! ---------------------------------------------------------------------------------------- - bg_wood = direct_dead * (struct_m + sapw_m ) * SF_val_CWD_frac(ncwd) * & + bg_wood = direct_dead * (struct_m + sapw_m ) * SF_val_CWD_frac_adj(ncwd) * & (1._r8 - prt_params%allom_agb_frac(currentCohort%pft)) do ilyr = 1,nlevsoil @@ -974,7 +978,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ag_wood = direct_dead * (struct_m + sapw_m ) * & prt_params%allom_agb_frac(currentCohort%pft) * & - SF_val_CWD_frac(ncwd) + SF_val_CWD_frac_adj(ncwd) trunk_product_site = trunk_product_site + & ag_wood * logging_export_frac diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 4c4efca18f..2e454267ae 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -16,6 +16,7 @@ module EDPatchDynamicsMod use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type + use FatesLitterMod , only : adjust_SF_CWD_frac use EDTypesMod , only : homogenize_seed_pfts use EDTypesMod , only : n_dbh_bins, area, patchfusion_dbhbin_loweredges use EDtypesMod , only : force_patchfuse_min_biomass @@ -760,14 +761,13 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%imort_carbonflux(currentCohort%pft) = & currentSite%imort_carbonflux(currentCohort%pft) + & (nc%n * ED_val_understorey_death / hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + total_c * days_per_sec * years_per_day * ha_per_m2 currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) = & currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) + & (nc%n * ED_val_understorey_death / hlm_freq_day ) * & ( (sapw_c + struct_c + store_c) * prt_params%allom_agb_frac(currentCohort%pft) + & - leaf_c ) * & - g_per_kg * days_per_sec * years_per_day * ha_per_m2 + leaf_c ) * days_per_sec * years_per_day * ha_per_m2 ! Step 2: Apply survivor ship function based on the understory death fraction @@ -1020,7 +1020,14 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%imort_carbonflux(currentCohort%pft) + & (nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac/ hlm_freq_day ) * & - total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 + total_c * days_per_sec * years_per_day * ha_per_m2 + + currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) = & + currentSite%imort_abg_flux(currentCohort%size_class, currentCohort%pft) + & + (nc%n * currentPatch%fract_ldist_not_harvested * & + logging_coll_under_frac/ hlm_freq_day ) * & + ( ( sapw_c + struct_c + store_c) * prt_params%allom_agb_frac(currentCohort%pft) + & + leaf_c ) * days_per_sec * years_per_day * ha_per_m2 ! Step 2: Apply survivor ship function based on the understory death fraction @@ -1659,7 +1666,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & integer :: pft ! loop index for plant functional types integer :: dcmpy ! loop index for decomposability pool integer :: element_id ! parteh compatible global element index - + real(r8) :: SF_val_CWD_frac_adj(4) !Updated wood partitioning to CWD based on dbh !--------------------------------------------------------------------- ! Only do this if there was a fire in this actual patch. @@ -1792,9 +1799,13 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & bcroot = (sapw_m + struct_m) * (1.0_r8 - prt_params%allom_agb_frac(pft) ) ! below ground coarse woody debris from burned trees + + !adjust the how wood is partitioned between the cwd classes based on cohort dbh + call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + do c = 1,ncwd do sl = 1,currentSite%nlevsoil - donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * & + donatable_mass = num_dead_trees * SF_val_CWD_frac_adj(c) * & bcroot * currentSite%rootfrac_scr(sl) new_litt%bg_cwd(c,sl) = new_litt%bg_cwd(c,sl) + & @@ -1815,10 +1826,10 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & ! Above ground coarse woody debris from twigs and small branches ! a portion of this pool may burn do c = 1,ncwd - donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem + donatable_mass = num_dead_trees * SF_val_CWD_frac_adj(c) * bstem if (c == 1 .or. c == 2) then donatable_mass = donatable_mass * (1.0_r8-currentCohort%fraction_crown_burned) - burned_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem * & + 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 endif @@ -1891,7 +1902,8 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & integer :: el ! element loop index integer :: sl ! soil layer index integer :: element_id ! parteh compatible global element index - real(r8) :: dcmpy_frac ! decomposability fraction + real(r8) :: dcmpy_frac ! decomposability fraction + real(r8) :: SF_val_CWD_frac_adj(4) !Updated wood partitioning to CWD based on dbh !--------------------------------------------------------------------- remainder_area = currentPatch%area - patch_site_areadis @@ -1989,24 +2001,26 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) + ! Adjust how wood is partitioned between the cwd classes based on cohort dbh + call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) do c=1,ncwd - + ! Transfer wood of dying trees to AG CWD pools new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + ag_wood * & - SF_val_CWD_frac(c) * donate_m2 + SF_val_CWD_frac_adj(c) * donate_m2 curr_litt%ag_cwd(c) = curr_litt%ag_cwd(c) + ag_wood * & - SF_val_CWD_frac(c) * retain_m2 + SF_val_CWD_frac_adj(c) * retain_m2 ! Transfer wood of dying trees to BG CWD pools do sl = 1,currentSite%nlevsoil new_litt%bg_cwd(c,sl) = new_litt%bg_cwd(c,sl) + bg_wood * & - currentSite%rootfrac_scr(sl) * SF_val_CWD_frac(c) * & + currentSite%rootfrac_scr(sl) * SF_val_CWD_frac_adj(c) * & donate_m2 curr_litt%bg_cwd(c,sl) = curr_litt%bg_cwd(c,sl) + bg_wood * & - currentSite%rootfrac_scr(sl) * SF_val_CWD_frac(c) * & + currentSite%rootfrac_scr(sl) * SF_val_CWD_frac_adj(c) * & retain_m2 end do end do @@ -2042,10 +2056,10 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & ! track diagnostic fluxes do c=1,ncwd flux_diags%cwd_ag_input(c) = & - flux_diags%cwd_ag_input(c) + SF_val_CWD_frac(c) * ag_wood + flux_diags%cwd_ag_input(c) + SF_val_CWD_frac_adj(c) * ag_wood flux_diags%cwd_bg_input(c) = & - flux_diags%cwd_bg_input(c) + SF_val_CWD_frac(c) * bg_wood + flux_diags%cwd_bg_input(c) + SF_val_CWD_frac_adj(c) * bg_wood end do flux_diags%leaf_litter_input(pft) = flux_diags%leaf_litter_input(pft) + & diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b92c330d2b..9040343100 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -51,6 +51,7 @@ module EDPhysiologyMod use FatesLitterMod , only : ilabile use FatesLitterMod , only : ilignin use FatesLitterMod , only : icellulose + use FatesLitterMod , only : adjust_SF_CWD_frac use EDTypesMod , only : nclmax use EDTypesMod , only : AREA,AREA_INV use EDTypesMod , only : nlevleaf @@ -152,6 +153,7 @@ module EDPhysiologyMod integer :: istat ! return status code character(len=255) :: smsg ! Message string for deallocation errors + integer, parameter :: dleafon_drycheck = 100 ! Drought deciduous leaves max days on check parameter real(r8), parameter :: decid_leaf_long_max = 1.0_r8 ! Maximum leaf lifespan for @@ -176,6 +178,9 @@ module EDPhysiologyMod ! computational problems. The current threshold ! is the same used in ED-2.2. + real(r8), parameter :: smp_lwr_bound = -1000000._r8 ! Imposed soil matric potential lower bound for + ! frozen or excessively dry soils, used when + ! computing water stress. ! ============================================================================ contains @@ -262,7 +267,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) real(r8) :: store_loss ! "" [kg] real(r8) :: struct_loss ! "" [kg] real(r8) :: dcmpy_frac ! fraction of mass going to each decomposition pool - + real(r8) :: SF_val_CWD_frac_adj(4) !SF_val_CWD_frac adjusted based on cohort dbh if(hlm_use_tree_damage .ne. itrue) return @@ -352,16 +357,18 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) flux_diags%leaf_litter_input(ipft) = & flux_diags%leaf_litter_input(ipft) + & (store_loss+leaf_loss+repro_loss) * ndcohort%n + + call adjust_SF_CWD_frac(ndcohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) do c = 1,ncwd litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & (sapw_loss + struct_loss) * & - SF_val_CWD_frac(c) * ndcohort%n / & + SF_val_CWD_frac_adj(c) * ndcohort%n / & cpatch%area flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & (struct_loss + sapw_loss) * & - SF_val_CWD_frac(c) * ndcohort%n + SF_val_CWD_frac_adj(c) * ndcohort%n end do end do do_element @@ -898,7 +905,7 @@ subroutine phenology( currentSite, bc_in ) use EDParamsMod, only : ED_val_phen_mindayson use EDParamsMod, only : ED_val_phen_ncolddayslim use EDParamsMod, only : ED_val_phen_coldtemp - + use EDBtranMod, only : check_layer_water ! ! !ARGUMENTS: type(ed_site_type), intent(inout), target :: currentSite @@ -913,6 +920,7 @@ subroutine phenology( currentSite, bc_in ) integer :: i_wmem ! Loop counter for water mem days integer :: i_tmem ! Loop counter for veg temp mem days integer :: ipft ! plant functional type index + integer :: j ! Soil layer index real(r8) :: mean_10day_liqvol ! mean soil liquid volume over last 10 days [m3/m3] real(r8) :: mean_10day_smp ! mean soil matric potential over last 10 days [mm] real(r8) :: leaf_c ! leaf carbon [kg] @@ -1183,12 +1191,25 @@ subroutine phenology( currentSite, bc_in ) ! Set the memory to be the weighted average of the soil properties, using the ! root fraction of each layer (except the topmost one) as the weighting factor. + currentSite%liqvol_memory(1,ipft) = sum( bc_in%h2o_liqvol_sl (2:nlevroot) * & currentSite%rootfrac_scr(2:nlevroot) ) / & - rootfrac_notop - currentSite%smp_memory (1,ipft) = sum( bc_in%smp_sl (2:nlevroot) * & - currentSite%rootfrac_scr(2:nlevroot) ) / & - rootfrac_notop + rootfrac_notop + currentSite%smp_memory (1,ipft) = 0._r8 + do j = 2,nlevroot + if(check_layer_water(bc_in%h2o_liqvol_sl(j),bc_in%tempk_sl(j)) ) then + currentSite%smp_memory (1,ipft) = currentSite%smp_memory (1,ipft) + & + bc_in%smp_sl (j) * & + currentSite%rootfrac_scr(j) / & + rootfrac_notop + else + ! Nominal extreme suction for frozen or unreasonably dry soil + currentSite%smp_memory (1,ipft) = currentSite%smp_memory (1,ipft) + & + smp_lwr_bound * & + currentSite%rootfrac_scr(j) / & + rootfrac_notop + end if + end do ! Calculate the mean soil moisture ( liquid volume (m3/m3) and matric potential (mm)) ! over the last 10 days @@ -2597,6 +2618,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) integer :: pft integer :: dcmpy ! decomposability pool index integer :: numlevsoil ! Actual number of soil layers + + real(r8) :: SF_val_CWD_frac_adj(4) !SF_val_CWD_frac adjusted based on cohort dbh !---------------------------------------------------------------------- ! ----------------------------------------------------------------------------------- @@ -2615,6 +2638,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) currentCohort => currentPatch%shortest do while(associated(currentCohort)) + pft = currentCohort%pft call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) @@ -2687,18 +2711,22 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! 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 + call adjust_SF_CWD_frac(currentCohort%dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + + do c = 1,ncwd litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & (sapw_m_turnover + struct_m_turnover) * & - SF_val_CWD_frac(c) * plant_dens * & + SF_val_CWD_frac_adj(c) * plant_dens * & prt_params%allom_agb_frac(pft) flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - (struct_m_turnover + sapw_m_turnover) * SF_val_CWD_frac(c) * & + (struct_m_turnover + sapw_m_turnover) * SF_val_CWD_frac_adj(c) * & prt_params%allom_agb_frac(pft) * currentCohort%n bg_cwd_tot = (sapw_m_turnover + struct_m_turnover) * & - SF_val_CWD_frac(c) * plant_dens * & + SF_val_CWD_frac_adj(c) * plant_dens * & (1.0_r8-prt_params%allom_agb_frac(pft)) do ilyr = 1, numlevsoil @@ -2779,7 +2807,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! Below-ground bg_cwd_tot = (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * & + SF_val_CWD_frac_adj(c) * dead_n * & (1.0_r8-prt_params%allom_agb_frac(pft)) do ilyr = 1, numlevsoil @@ -2798,7 +2826,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) trunk_wood = (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n_dlogging * & + SF_val_CWD_frac_adj(c) * dead_n_dlogging * & prt_params%allom_agb_frac(pft) site_mass%wood_product = site_mass%wood_product + & @@ -2816,21 +2844,21 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! Add AG wood to litter from indirect anthro sources litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + SF_val_CWD_frac_adj(c) * (dead_n_natural+dead_n_ilogging) * & prt_params%allom_agb_frac(pft) flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + SF_val_CWD_frac_adj(c) * (dead_n_natural+dead_n_ilogging) * & currentPatch%area * prt_params%allom_agb_frac(pft) else litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * & + SF_val_CWD_frac_adj(c) * dead_n * & prt_params%allom_agb_frac(pft) flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac(c) * dead_n * (struct_m + sapw_m) * & + SF_val_CWD_frac_adj(c) * dead_n * (struct_m + sapw_m) * & currentPatch%area * prt_params%allom_agb_frac(pft) end if @@ -2860,13 +2888,13 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) currentSite%resources_management%delta_litter_stock = & currentSite%resources_management%delta_litter_stock + & (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * (dead_n_natural+dead_n_ilogging) * & + SF_val_CWD_frac_adj(c) * (dead_n_natural+dead_n_ilogging) * & currentPatch%area currentSite%resources_management%delta_biomass_stock = & currentSite%resources_management%delta_biomass_stock + & (struct_m + sapw_m) * & - SF_val_CWD_frac(c) * dead_n * currentPatch%area + SF_val_CWD_frac_adj(c) * dead_n * currentPatch%area end do ! Update diagnostics that track resource management @@ -3168,5 +3196,5 @@ subroutine SetRecruitL2FR(csite) return end subroutine SetRecruitL2FR - + end module EDPhysiologyMod diff --git a/biogeochem/FatesLitterMod.F90 b/biogeochem/FatesLitterMod.F90 index be5ec48aa9..e0ef9c80aa 100644 --- a/biogeochem/FatesLitterMod.F90 +++ b/biogeochem/FatesLitterMod.F90 @@ -44,6 +44,7 @@ module FatesLitterMod implicit none private + public :: adjust_SF_CWD_frac integer, public, parameter :: ncwd = 4 ! number of coarse woody debris pools ! (twig,s branch,l branch, trunk) @@ -57,7 +58,6 @@ module FatesLitterMod type, public :: litter_type - ! This object is allocated for each element (C, N, P, etc) that we wish to track. @@ -424,6 +424,73 @@ function GetTotalLitterMass(this) result(total_mass) return end function GetTotalLitterMass - + + ! ===================================================== + + subroutine adjust_SF_CWD_frac(dbh,ncwd,SF_val_CWD_frac,SF_val_CWD_frac_adj) + + !DESCRIPTION + !Adjust the partitioning of struct + sawp into cwd pools based on + !cohort dbh. This avoids struct and sapw from small cohorts going to + !fuel classes that are larger than their dbh. Here, struct + sapw are sent to the cwd + !class consistent with fuel class diameter thresholds (Fosberg et al., 1971; + !Rothermel, 1983) + + !ARGUMENTS + real(r8), intent(in) :: dbh !dbh of cohort [cm] + type(integer), intent(in) :: ncwd !number of cwd pools + real(r8), intent(in) :: SF_val_CWD_frac(:) !fates parameter specifying the + !fraction of struct + sapw going + !to each CWD class + real(r8), intent(out) :: SF_val_CWD_frac_adj(:) !Updated cwd paritions + ! + !LOCAL VARIABLES + !These diameter ranges are based on work by Fosberg et al., 1971 + + real(r8), parameter :: lb_max_diam = 7.6 !max diameter [cm] for large branch (100 hr fuel) + real(r8), parameter :: sb_max_diam = 2.5 !max diameter [cm] for small branch (10 hr fuel) + real(r8), parameter :: twig_max_diam = 0.6 !max diameter [cm] for twig (1 hr fuel) + !------------------------------------------------------------------------------------ + + + SF_val_CWD_frac_adj = SF_val_CWD_frac + + !If dbh is > 7.6 cm diameter then the main stem is 1,000 hr fuel and we don't change + !how biomass is partitioned among cwd classes. + if (dbh > lb_max_diam) then + return + + !When dbh is greater than the max size of a small branch (10 hr fuel) but less than or + !equal to the max size of a large branch (e.g. saplings where dbh > 2.5 cm and < 7.5 cm) + !we redistribute the biomass that would have gone to 1,000 hr fuel among the smaller cwd classes. + !This keeps the biomass proportions among the combustible classes the same as the scenario + !where a fraction of struct + sawp goes to 1,000 hr fuel. + else if (dbh > sb_max_diam .and. dbh .le. lb_max_diam) then + SF_val_CWD_frac_adj(ncwd) = 0.0 + SF_val_CWD_frac_adj(ncwd-1) = SF_val_CWD_frac(ncwd-1) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) + SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) + SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r8 - SF_val_CWD_frac(ncwd) ) + + !When dbh is greater than the max size of a twig (1 hr fuel) but less than or + !equal to the max size of a small branch (10 hr fuel) we redistribute the biomass among the smaller + !pools. + else if (dbh > twig_max_diam .and. dbh .le. sb_max_diam) then + SF_val_CWD_frac_adj(ncwd) = 0.0 + SF_val_CWD_frac_adj(ncwd-1) = 0.0 + SF_val_CWD_frac_adj(ncwd-2) = SF_val_CWD_frac(ncwd-2) / (1.0_r8 - (SF_val_CWD_frac(ncwd) + & + SF_val_CWD_frac(ncwd-1))) + SF_val_CWD_frac_adj(ncwd-3) = SF_val_CWD_frac(ncwd-3) / (1.0_r8 - (SF_val_CWD_frac(ncwd) + & + SF_val_CWD_frac(ncwd-1))) + + !If dbh is less than or equal to the max size of a twig we send all + !biomass to twigs. + else if (dbh .le. twig_max_diam) then + SF_val_CWD_frac_adj(ncwd) = 0.0 + SF_val_CWD_frac_adj(ncwd-1) = 0.0 + SF_val_CWD_frac_adj(ncwd-2) = 0.0 + SF_val_CWD_frac_adj(ncwd-3) = sum(SF_val_CWD_frac) + + endif + end subroutine adjust_SF_CWD_frac end module FatesLitterMod diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 48b9d1e448..18d29c0109 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -265,7 +265,6 @@ subroutine PatchNormanRadiation (currentPatch, & integer :: fp,iv,s ! array indices integer :: ib ! waveband number real(r8) :: cosz ! 0.001 <= coszen <= 1.000 - real(r8) :: chil real(r8) :: gdir @@ -363,11 +362,7 @@ subroutine PatchNormanRadiation (currentPatch, & cosz = max(0.001_r8, currentPatch%solar_zenith_angle ) !copied from previous radiation code... do ft = 1,numpft sb = (90._r8 - (acos(cosz)*180._r8/pi_const)) * (pi_const / 180._r8) - chil = xl(ft) !min(max(xl(ft), -0.4_r8), 0.6_r8 ) - if ( abs(chil) <= 0.01_r8) then - chil = 0.01_r8 - end if - phi1b(ft) = 0.5_r8 - 0.633_r8*chil - 0.330_r8*chil*chil + phi1b(ft) = 0.5_r8 - 0.633_r8*xl(ft) - 0.330_r8*xl(ft)*xl(ft) phi2b(ft) = 0.877_r8 * (1._r8 - 2._r8*phi1b(ft)) !0 = horiz leaves, 1 - vert leaves. gdir = phi1b(ft) + phi2b(ft) * sin(sb) !how much direct light penetrates a singleunit of lai? diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 148df49e78..da5a064ca7 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1835,8 +1835,6 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - - ! logging parameters, make sure they make sense if ( (logging_mechanical_frac + logging_collateral_frac + logging_direct_frac) .gt. 1._r8) then write(fates_log(),*) 'the sum of logging_mechanical_frac + logging_collateral_frac + logging_direct_frac' @@ -1868,6 +1866,13 @@ subroutine FatesCheckParams(is_master) do ipft = 1,npft + ! xl must be between -0.4 and 0.6 according to Bonan (2019) doi:10.1017/9781107339217 pg. 238 + !----------------------------------------------------------------------------------- + if (EDPftvarcon_inst%xl(ipft) < -0.4 .or. EDPftvarcon_inst%xl(ipft) > 0.6) then + write(fates_log(),*) 'fates_rad_leaf_xl for pft ', ipft, ' is outside the allowed range of -0.6 to 0.4' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Check that parameter ranges for age-dependent mortality make sense !----------------------------------------------------------------------------------- diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index c384edbc26..2e13027097 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -877,15 +877,15 @@ module EDTypesMod ! were terminated this timestep, on size x pft real(r8), allocatable :: term_carbonflux_canopy(:) ! carbon flux from live to dead pools associated - ! with termination mortality, per canopy level + ! with termination mortality, per canopy level. [kgC/ha/day] real(r8), allocatable :: term_carbonflux_ustory(:) ! carbon flux from live to dead pools associated - ! with termination mortality, per canopy level - real(r8), allocatable :: imort_carbonflux(:) ! biomass of individuals killed due to impact mortality per year. [kgC/ha/day] + ! with termination mortality, per canopy level. [kgC/ha/day] + real(r8), allocatable :: imort_carbonflux(:) ! biomass of individuals killed due to impact mortality per year. [kgC/m2/sec] real(r8), allocatable :: fmort_carbonflux_canopy(:) ! biomass of canopy indivs killed due to fire per year. [gC/m2/sec] real(r8), allocatable :: fmort_carbonflux_ustory(:) ! biomass of understory indivs killed due to fire per year [gC/m2/sec] real(r8), allocatable :: term_abg_flux(:,:) ! aboveground biomass lost due to termination mortality x size x pft - real(r8), allocatable :: imort_abg_flux(:,:) ! aboveground biomass lost due to impact mortality x size x pft + real(r8), allocatable :: imort_abg_flux(:,:) ! aboveground biomass lost due to impact mortality x size x pft [kgC/m2/sec] real(r8), allocatable :: fmort_abg_flux(:,:) ! aboveground biomass lost due to fire mortality x size x pft @@ -914,7 +914,7 @@ module EDTypesMod real(r8), allocatable :: fmort_rate_ustory_damage(:,:,:) ! number of individuals per damage class that die from fire - ustory real(r8), allocatable :: fmort_cflux_canopy_damage(:,:) ! cflux per damage class that die from fire - canopy real(r8), allocatable :: fmort_cflux_ustory_damage(:,:) ! cflux per damage class that die from fire - ustory - real(r8), allocatable :: imort_cflux_damage(:,:) ! carbon flux from impact mortality by damage class + real(r8), allocatable :: imort_cflux_damage(:,:) ! carbon flux from impact mortality by damage class [kgC/m2/sec] real(r8), allocatable :: term_cflux_canopy_damage(:,:) ! carbon flux from termination mortality by damage class real(r8), allocatable :: term_cflux_ustory_damage(:,:) ! carbon flux from termination mortality by damage class diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index bbd8103ab9..a4cd255ef6 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3865,13 +3865,15 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! treat carbon flux from imort the same way hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sum(sites(s)%imort_carbonflux(:)) / g_per_kg + sum(sites(s)%imort_carbonflux(:)) do i_pft = 1, numpft hio_mortality_carbonflux_si_pft(io_si,i_pft) = hio_mortality_carbonflux_si_pft(io_si,i_pft) + & (sites(s)%fmort_carbonflux_canopy(i_pft) + & - sites(s)%fmort_carbonflux_ustory(i_pft) + & - sites(s)%imort_carbonflux(i_pft) ) / g_per_kg ! cdk + sites(s)%fmort_carbonflux_ustory(i_pft) ) / g_per_kg + & + sites(s)%imort_carbonflux(i_pft) + & + sites(s)%term_carbonflux_ustory(i_pft) * days_per_sec * ha_per_m2 + & + sites(s)%term_carbonflux_canopy(i_pft) * days_per_sec * ha_per_m2 hio_firemortality_carbonflux_si_pft(io_si,i_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) / g_per_kg end do @@ -3882,8 +3884,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) i_scpf = (i_pft-1)*nlevsclass + i_scls hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) = hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) + & (sites(s)%fmort_abg_flux(i_scls,i_pft) / g_per_kg ) + & - (sites(s)%imort_abg_flux(i_scls,i_pft) / g_per_kg) + & - (sites(s)%term_abg_flux(i_scls,i_pft) * days_per_sec * ha_per_m2 ) ! jfn + sites(s)%imort_abg_flux(i_scls,i_pft) + & + (sites(s)%term_abg_flux(i_scls,i_pft) * days_per_sec * ha_per_m2 ) end do end do @@ -6753,7 +6755,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_firemortality_carbonflux_si_pft) - call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_CFLUX_PF', units='kg m-2 s-1', & + call this%set_history_var(vname='FATES_MORTALITY_HYDRO_CFLUX_PF', units='kg m-2 s-1', & long='PFT-level flux of biomass carbon from live to dead pool from hydraulic failure mortality', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 82b4357ea7..47fb444d38 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -822,6 +822,7 @@ subroutine SetFatesGlobalElements2(use_fates) nleafage = size(prt_params%leaf_long,dim=2) end if + nlevsclass = size(ED_val_history_sizeclass_bin_edges,dim=1) ! These values are used to define the restart file allocations and general structure ! of memory for the cohort arrays @@ -885,7 +886,6 @@ subroutine SetFatesGlobalElements2(use_fates) ! Identify number of size and age class bins for history output ! assume these arrays are 1-indexed - nlevsclass = size(ED_val_history_sizeclass_bin_edges,dim=1) nlevage = size(ED_val_history_ageclass_bin_edges,dim=1) nlevheight = size(ED_val_history_height_bin_edges,dim=1) nlevcoage = size(ED_val_history_coageclass_bin_edges,dim=1) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 6efceb3191..ec0e4ffc1f 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2087,6 +2087,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_cacls= io_idx_co_1st io_idx_si_cdsc = io_idx_co_1st io_idx_si_cdpf = io_idx_co_1st + io_idx_si_scpf = io_idx_co_1st + io_idx_si_pft = io_idx_co_1st ! recruitment rate do i_pft = 1,numpft @@ -2101,6 +2103,37 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_area_pft_sift(io_idx_co_1st+i_pft-1) = sites(s)%area_pft(i_pft) end do + do i_scls = 1, nlevsclass + do i_pft = 1, numpft + rio_fmortrate_cano_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_canopy(i_scls, i_pft) + rio_fmortrate_usto_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_ustory(i_scls, i_pft) + rio_imortrate_siscpf(io_idx_si_scpf) = sites(s)%imort_rate(i_scls, i_pft) + rio_fmortrate_crown_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_crown(i_scls, i_pft) + rio_fmortrate_cambi_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_cambial(i_scls, i_pft) + rio_termnindiv_cano_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_canopy(i_scls,i_pft) + rio_termnindiv_usto_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_ustory(i_scls,i_pft) + rio_growflx_fusion_siscpf(io_idx_si_scpf) = sites(s)%growthflux_fusion(i_scls, i_pft) + rio_abg_term_flux_siscpf(io_idx_si_scpf) = sites(s)%term_abg_flux(i_scls, i_pft) + rio_abg_imort_flux_siscpf(io_idx_si_scpf) = sites(s)%imort_abg_flux(i_scls, i_pft) + rio_abg_fmort_flux_siscpf(io_idx_si_scpf) = sites(s)%fmort_abg_flux(i_scls, i_pft) + io_idx_si_scpf = io_idx_si_scpf + 1 + end do + end do + + do i_pft = 1, numpft + rio_termcflux_cano_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_canopy(i_pft) + rio_termcflux_usto_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_ustory(i_pft) + rio_fmortcflux_cano_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) + rio_fmortcflux_usto_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_ustory(i_pft) + rio_imortcflux_sipft(io_idx_si_pft) = sites(s)%imort_carbonflux(i_pft) + rio_dd_status_sift(io_idx_si_pft) = sites(s)%dstatus(i_pft) + rio_dleafondate_sift(io_idx_si_pft) = sites(s)%dleafondate(i_pft) + rio_dleafoffdate_sift(io_idx_si_pft) = sites(s)%dleafoffdate(i_pft) + rio_dndaysleafon_sift(io_idx_si_pft) = sites(s)%dndaysleafon(i_pft) + rio_dndaysleafoff_sift(io_idx_si_pft) = sites(s)%dndaysleafoff(i_pft) + rio_elong_factor_sift(io_idx_si_pft) = sites(s)%elong_factor(i_pft) + io_idx_si_pft = io_idx_si_pft + 1 + end do if(hlm_use_sp.eq.ifalse)then do el = 1, num_elements @@ -2128,6 +2161,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) end do end if + + ! canopy spread term rio_spread_si(io_idx_si) = sites(s)%spread @@ -2136,7 +2171,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! new column, reset num patches patchespersite = 0 - do while(associated(cpatch)) + do_patch: do while(associated(cpatch)) ! found patch, increment patchespersite = patchespersite + 1 @@ -2414,31 +2449,12 @@ subroutine set_restart_vectors(this,nc,nsites,sites) cpatch => cpatch%younger - enddo ! cpatch do while - - io_idx_si_scpf = io_idx_co_1st + enddo do_patch ! cpatch do while ! Fill the site level diagnostics arrays do i_scls = 1, nlevsclass - do i_pft = 1, numpft - - rio_fmortrate_cano_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_canopy(i_scls, i_pft) - rio_fmortrate_usto_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_ustory(i_scls, i_pft) - rio_imortrate_siscpf(io_idx_si_scpf) = sites(s)%imort_rate(i_scls, i_pft) - rio_fmortrate_crown_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_crown(i_scls, i_pft) - rio_fmortrate_cambi_siscpf(io_idx_si_scpf) = sites(s)%fmort_rate_cambial(i_scls, i_pft) - rio_termnindiv_cano_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_canopy(i_scls,i_pft) - rio_termnindiv_usto_siscpf(io_idx_si_scpf) = sites(s)%term_nindivs_ustory(i_scls,i_pft) - rio_growflx_fusion_siscpf(io_idx_si_scpf) = sites(s)%growthflux_fusion(i_scls, i_pft) - rio_abg_term_flux_siscpf(io_idx_si_scpf) = sites(s)%term_abg_flux(i_scls, i_pft) - rio_abg_imort_flux_siscpf(io_idx_si_scpf) = sites(s)%imort_abg_flux(i_scls, i_pft) - rio_abg_fmort_flux_siscpf(io_idx_si_scpf) = sites(s)%fmort_abg_flux(i_scls, i_pft) - - io_idx_si_scpf = io_idx_si_scpf + 1 - end do - - rio_demorate_sisc(io_idx_si_sc) = sites(s)%demotion_rate(i_scls) + rio_demorate_sisc(io_idx_si_sc) = sites(s)%demotion_rate(i_scls) rio_promrate_sisc(io_idx_si_sc) = sites(s)%promotion_rate(i_scls) io_idx_si_sc = io_idx_si_sc + 1 @@ -2479,16 +2495,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_democflux_si(io_idx_si) = sites(s)%demotion_carbonflux rio_promcflux_si(io_idx_si) = sites(s)%promotion_carbonflux - io_idx_si_pft = io_idx_co_1st - do i_pft = 1, numpft - rio_termcflux_cano_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_canopy(i_pft) - rio_termcflux_usto_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_ustory(i_pft) - rio_fmortcflux_cano_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) - rio_fmortcflux_usto_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_ustory(i_pft) - rio_imortcflux_sipft(io_idx_si_pft) = sites(s)%imort_carbonflux(i_pft) - io_idx_si_pft = io_idx_si_pft + 1 - end do - rio_imortcarea_si(io_idx_si) = sites(s)%imort_crownarea rio_fmortcarea_cano_si(io_idx_si) = sites(s)%fmort_crownarea_canopy rio_fmortcarea_usto_si(io_idx_si) = sites(s)%fmort_crownarea_ustory @@ -2503,18 +2509,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_gdd_si(io_idx_si) = sites(s)%grow_deg_days rio_phenmodeldate_si(io_idx_si) = sites(s)%phen_model_date - ! Drought-deciduous phenology are now PFT dependent - io_idx_si_pft = io_idx_co_1st - do i_pft = 1,numpft - rio_dd_status_sift(io_idx_si_pft) = sites(s)%dstatus(i_pft) - rio_dleafondate_sift(io_idx_si_pft) = sites(s)%dleafondate(i_pft) - rio_dleafoffdate_sift(io_idx_si_pft) = sites(s)%dleafoffdate(i_pft) - rio_dndaysleafon_sift(io_idx_si_pft) = sites(s)%dndaysleafon(i_pft) - rio_dndaysleafoff_sift(io_idx_si_pft) = sites(s)%dndaysleafoff(i_pft) - rio_elong_factor_sift(io_idx_si_pft) = sites(s)%elong_factor(i_pft) - - io_idx_si_pft = io_idx_si_pft + 1 - end do + rio_acc_ni_si(io_idx_si) = sites(s)%acc_NI @@ -3008,6 +3003,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_cacls= io_idx_co_1st io_idx_si_cdsc = io_idx_co_1st io_idx_si_cdpf = io_idx_co_1st + io_idx_si_scpf = io_idx_co_1st + io_idx_si_pft = io_idx_co_1st ! read seed_bank info(site-level, but PFT-resolved) do i_pft = 1,numpft @@ -3029,6 +3026,38 @@ subroutine get_restart_vectors(this, nc, nsites, sites) endif endif + do i_scls = 1,nlevsclass + do i_pft = 1, numpft + sites(s)%fmort_rate_canopy(i_scls, i_pft) = rio_fmortrate_cano_siscpf(io_idx_si_scpf) + sites(s)%fmort_rate_ustory(i_scls, i_pft) = rio_fmortrate_usto_siscpf(io_idx_si_scpf) + sites(s)%imort_rate(i_scls, i_pft) = rio_imortrate_siscpf(io_idx_si_scpf) + sites(s)%fmort_rate_crown(i_scls, i_pft) = rio_fmortrate_crown_siscpf(io_idx_si_scpf) + sites(s)%fmort_rate_cambial(i_scls, i_pft) = rio_fmortrate_cambi_siscpf(io_idx_si_scpf) + sites(s)%term_nindivs_canopy(i_scls,i_pft) = rio_termnindiv_cano_siscpf(io_idx_si_scpf) + sites(s)%term_nindivs_ustory(i_scls,i_pft) = rio_termnindiv_usto_siscpf(io_idx_si_scpf) + sites(s)%growthflux_fusion(i_scls, i_pft) = rio_growflx_fusion_siscpf(io_idx_si_scpf) + sites(s)%term_abg_flux(i_scls,i_pft) = rio_abg_term_flux_siscpf(io_idx_si_scpf) + sites(s)%imort_abg_flux(i_scls,i_pft) = rio_abg_imort_flux_siscpf(io_idx_si_scpf) + sites(s)%fmort_abg_flux(i_scls,i_pft) = rio_abg_fmort_flux_siscpf(io_idx_si_scpf) + io_idx_si_scpf = io_idx_si_scpf + 1 + end do + end do + + do i_pft = 1, numpft + sites(s)%term_carbonflux_canopy(i_pft) = rio_termcflux_cano_sipft(io_idx_si_pft) + sites(s)%term_carbonflux_ustory(i_pft) = rio_termcflux_usto_sipft(io_idx_si_pft) + sites(s)%fmort_carbonflux_canopy(i_pft) = rio_fmortcflux_cano_sipft(io_idx_si_pft) + sites(s)%fmort_carbonflux_ustory(i_pft) = rio_fmortcflux_usto_sipft(io_idx_si_pft) + sites(s)%imort_carbonflux(i_pft) = rio_imortcflux_sipft(io_idx_si_pft) + sites(s)%dstatus(i_pft) = rio_dd_status_sift(io_idx_si_pft) + sites(s)%dleafondate(i_pft) = rio_dleafondate_sift(io_idx_si_pft) + sites(s)%dleafoffdate(i_pft) = rio_dleafoffdate_sift(io_idx_si_pft) + sites(s)%dndaysleafon(i_pft) = rio_dndaysleafon_sift(io_idx_si_pft) + sites(s)%dndaysleafoff(i_pft) = rio_dndaysleafoff_sift(io_idx_si_pft) + sites(s)%elong_factor(i_pft) = rio_elong_factor_sift(io_idx_si_pft) + io_idx_si_pft = io_idx_si_pft + 1 + end do + ! Mass balance and diagnostics across elements at the site level if(hlm_use_sp.eq.ifalse)then do el = 1, num_elements @@ -3061,7 +3090,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) patchespersite = 0 cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) + do_patch: do while(associated(cpatch)) patchespersite = patchespersite + 1 @@ -3333,8 +3362,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) end if cpatch => cpatch%younger - - enddo ! patch do while + enddo do_patch if(patchespersite .ne. rio_npatch_si(io_idx_si)) then write(fates_log(),*) 'Number of patches per site during retrieval does not match allocation' @@ -3391,30 +3419,11 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! Fill the site level diagnostics arrays ! ----------------------------------------------------------------------------- - - io_idx_si_scpf = io_idx_co_1st - do i_scls = 1,nlevsclass - do i_pft = 1, numpft - sites(s)%fmort_rate_canopy(i_scls, i_pft) = rio_fmortrate_cano_siscpf(io_idx_si_scpf) - sites(s)%fmort_rate_ustory(i_scls, i_pft) = rio_fmortrate_usto_siscpf(io_idx_si_scpf) - sites(s)%imort_rate(i_scls, i_pft) = rio_imortrate_siscpf(io_idx_si_scpf) - sites(s)%fmort_rate_crown(i_scls, i_pft) = rio_fmortrate_crown_siscpf(io_idx_si_scpf) - sites(s)%fmort_rate_cambial(i_scls, i_pft) = rio_fmortrate_cambi_siscpf(io_idx_si_scpf) - sites(s)%term_nindivs_canopy(i_scls,i_pft) = rio_termnindiv_cano_siscpf(io_idx_si_scpf) - sites(s)%term_nindivs_ustory(i_scls,i_pft) = rio_termnindiv_usto_siscpf(io_idx_si_scpf) - sites(s)%growthflux_fusion(i_scls, i_pft) = rio_growflx_fusion_siscpf(io_idx_si_scpf) - - sites(s)%term_abg_flux(i_scls,i_pft) = rio_abg_term_flux_siscpf(io_idx_si_scpf) - sites(s)%imort_abg_flux(i_scls,i_pft) = rio_abg_imort_flux_siscpf(io_idx_si_scpf) - sites(s)%fmort_abg_flux(i_scls,i_pft) = rio_abg_fmort_flux_siscpf(io_idx_si_scpf) - - io_idx_si_scpf = io_idx_si_scpf + 1 - end do sites(s)%demotion_rate(i_scls) = rio_demorate_sisc(io_idx_si_sc) sites(s)%promotion_rate(i_scls) = rio_promrate_sisc(io_idx_si_sc) - + io_idx_si_sc = io_idx_si_sc + 1 end do @@ -3452,16 +3461,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%demotion_carbonflux = rio_democflux_si(io_idx_si) sites(s)%promotion_carbonflux = rio_promcflux_si(io_idx_si) - io_idx_si_pft = io_idx_co_1st - do i_pft = 1, numpft - sites(s)%term_carbonflux_canopy(i_pft) = rio_termcflux_cano_sipft(io_idx_si_pft) - sites(s)%term_carbonflux_ustory(i_pft) = rio_termcflux_usto_sipft(io_idx_si_pft) - sites(s)%fmort_carbonflux_canopy(i_pft) = rio_fmortcflux_cano_sipft(io_idx_si_pft) - sites(s)%fmort_carbonflux_ustory(i_pft) = rio_fmortcflux_usto_sipft(io_idx_si_pft) - sites(s)%imort_carbonflux(i_pft) = rio_imortcflux_sipft(io_idx_si_pft) - io_idx_si_pft = io_idx_si_pft + 1 - end do - ! Site level phenology status flags sites(s)%cstatus = rio_cd_status_si(io_idx_si) @@ -3474,17 +3473,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%grow_deg_days = rio_gdd_si(io_idx_si) sites(s)%phen_model_date= rio_phenmodeldate_si(io_idx_si) - ! Fill drought-deciduous variables, which are now PFT variables. - io_idx_si_pft = io_idx_co_1st - do i_pft = 1,numpft - sites(s)%dstatus(i_pft) = rio_dd_status_sift(io_idx_si_pft) - sites(s)%dleafondate(i_pft) = rio_dleafondate_sift(io_idx_si_pft) - sites(s)%dleafoffdate(i_pft) = rio_dleafoffdate_sift(io_idx_si_pft) - sites(s)%dndaysleafon(i_pft) = rio_dndaysleafon_sift(io_idx_si_pft) - sites(s)%dndaysleafoff(i_pft) = rio_dndaysleafoff_sift(io_idx_si_pft) - sites(s)%elong_factor(i_pft) = rio_elong_factor_sift(io_idx_si_pft) - io_idx_si_pft = io_idx_si_pft + 1 - end do + sites(s)%acc_NI = rio_acc_ni_si(io_idx_si) sites(s)%snow_depth = rio_snow_depth_si(io_idx_si) diff --git a/parameter_files/archive/api25.4.0_041023_pr958.xml b/parameter_files/archive/api25.4.0_041023_pr958.xml index 16b3af5890..fb424d93e0 100644 --- a/parameter_files/archive/api25.4.0_041023_pr958.xml +++ b/parameter_files/archive/api25.4.0_041023_pr958.xml @@ -26,6 +26,20 @@ fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12 + + fates_maintresp_reduction_upthresh + fates_pft + unitless (0-1) + upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + + + fates_mort_upthresh_cstarvation + fates_pft + unitless + threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + fates_phen_fnrt_drop_fraction fraction of fine roots to drop during drought/cold @@ -53,7 +67,6 @@ day threshold compared against days since leaves abscised (shed) - fates_pft 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index d1b219a36a..6a48bdaa41 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -365,7 +365,7 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_pft) ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; double fates_leaf_vcmaxha(fates_pft) ; @@ -1271,7 +1271,8 @@ data: fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, 4.7, 2.2, 5.3, 1.6 ; - fates_leaf_vcmax25top = 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; + fates_leaf_vcmax25top = + 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330 ;