diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index b1fc9af66d..1d8b824f92 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -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 @@ -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, @@ -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 @@ -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) @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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. @@ -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) ! ----------------------------------------------------------------------------------- ! @@ -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 @@ -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 @@ -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 @@ -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. @@ -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: @@ -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) @@ -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 @@ -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: @@ -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 ! @@ -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) @@ -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)) @@ -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 diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 3b1d61e914..d9fa12f8c2 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -33,6 +33,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 @@ -429,7 +431,7 @@ end subroutine GenerateDamageAndLitterFluxes ! ============================================================================ - subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) + subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in, bc_out ) ! ----------------------------------------------------------------------------------- ! @@ -437,8 +439,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) ! 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) @@ -452,6 +453,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: @@ -470,34 +472,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 @@ -2254,7 +2255,7 @@ subroutine SeedDecay( litt , currentPatch, bc_in ) ! Default seed decay (TRS is off) litt%seed_decay(pft) = litt%seed(pft) * & - EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day + EDPftvarcon_inst%seed_decay_rate(pft)*years_per_day * 0._r8 !THIS IS A HACK end if @@ -2788,7 +2789,7 @@ end subroutine recruitment ! ====================================================================================== - subroutine CWDInput( currentSite, currentPatch, litt, bc_in) + subroutine CWDInput( currentSite, currentPatch, litt, bc_in, bc_out) ! ! !DESCRIPTION: @@ -2808,6 +2809,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: @@ -2955,12 +2957,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 @@ -3232,7 +3238,7 @@ subroutine fragmentation_scaler( currentPatch, bc_in) endif ! scalar endif ! not bare ground - + currentPatch%fragmentation_scaler(:) =0._r8 !this is a hack end subroutine fragmentation_scaler ! ============================================================================ @@ -3272,7 +3278,7 @@ subroutine CWDOut( litt, fragmentation_scaler, nlev_eff_decomp ) do c = 1,ncwd litt%ag_cwd_frag(c) = litt%ag_cwd(c) * SF_val_max_decomp(c) * & - years_per_day * fragmentation_scaler(soil_layer_index) + years_per_day * fragmentation_scaler(soil_layer_index) * 0.0_r8 ! THIS IS A HACK do ilyr = 1,nlev_eff_decomp litt%bg_cwd_frag(c,ilyr) = litt%bg_cwd(c,ilyr) * SF_val_max_decomp(c) * & diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index e0af2a9e0f..d82d4c4a05 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -744,10 +744,10 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) do id = 1,nlev_eff_decomp flux_cel_si(id) = flux_cel_si(id) + & - litt%ag_cwd_frag(ic) * ED_val_cwd_fcel * area_frac * surface_prof(id) + litt%ag_cwd_frag(ic) * ED_val_cwd_fcel * area_frac * surface_prof(id) *0._r8 !THIS IS A HACK flux_lig_si(id) = flux_lig_si(id) + & - litt%ag_cwd_frag(ic) * ED_val_cwd_flig * area_frac * surface_prof(id) + litt%ag_cwd_frag(ic) * ED_val_cwd_flig * area_frac * surface_prof(id) *0._r8 ! this is a hack end do @@ -809,6 +809,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) flux_lig_si(id) = flux_lig_si(id) + & litt%root_fines_frag(ilignin,j) * area_frac enddo + currentPatch => currentPatch%younger end do diff --git a/biogeophys/EDAccumulateFluxesMod.F90 b/biogeophys/EDAccumulateFluxesMod.F90 index b4f93ba5c9..9befde6321 100644 --- a/biogeophys/EDAccumulateFluxesMod.F90 +++ b/biogeophys/EDAccumulateFluxesMod.F90 @@ -41,7 +41,12 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) use FatesPatchMod, only : fates_patch_type use FatesCohortMod, only : fates_cohort_type use FatesInterfaceTypesMod , only : bc_in_type,bc_out_type - + use EDtypesMod , only : AREA_INV + use clm_time_manager , only : get_curr_days_per_year + use FatesConstantsMod , only : sec_per_day + use FatesConstantsMod , only : days_per_year + use FatesConstantsMod , only : g_per_kg + ! ! !ARGUMENTS integer, intent(in) :: nsites @@ -57,8 +62,9 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) integer :: c ! clm/alm column integer :: s ! ed site integer :: ifp ! index fates patch + real :: ind_per_m2 !---------------------------------------------------------------------- - + do s = 1, nsites ! Note: Do not attempt to accumulate or log any @@ -66,6 +72,9 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) ! It is likely this has not been calculated yet (ELM/CLM) cpatch => sites(s)%oldest_patch + bc_out(s)%npp_acc_site = 0._r8 + bc_out(s)%npp_site = 0._r8 + do while (associated(cpatch)) ifp = cpatch%patchno @@ -75,13 +84,35 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) if( bc_in(s)%filter_photo_pa(ifp) == 3 ) then ccohort => cpatch%shortest do while(associated(ccohort)) + ind_per_m2 = ccohort%n * AREA_INV ! Accumulate fluxes from hourly to daily values. ! _tstep fluxes are KgC/indiv/timestep _acc are KgC/indiv/day - ccohort%gpp_acc = ccohort%gpp_acc + ccohort%gpp_tstep ccohort%resp_m_acc = ccohort%resp_m_acc + ccohort%resp_m_tstep + ! Make npp_acc variable for the site level to add to the NBP balance check + ! Convert from kgC/ind to gC/m2 + if(.not.ccohort%isnew)then + bc_out(s)%npp_acc_site = bc_out(s)%npp_acc_site + & + (ccohort%gpp_acc - ccohort%resp_m_acc) & + * ind_per_m2 * g_per_kg & + -(ccohort%resp_g_acc_hold+ccohort%resp_excess_hold) * & + ind_per_m2 * g_per_kg * dt_time/(days_per_year*sec_per_day) + ! gresp is converted from kgC/indiv/year to gC/m2/timestep. + endif + + ! Net Ecosystem Production [kgC/m2/s]. Use yesterday's growth respiration + ! This is taken from the NEP history variable calculation. + ! first add GPP-Rm and convert units from kgC/indiv/timestep to gC/m2/s + ! then smooth out yesterdays's calculated growth respiration and + ! convert units from kgC/indiv/year to gC/m2/s. + if(.not.ccohort%isnew)then + bc_out(s)%npp_site = bc_out(s)%npp_site + (ccohort%gpp_tstep-ccohort%resp_m_tstep) & + * ind_per_m2 * g_per_kg / dt_time - & + (ccohort%resp_g_acc_hold+ccohort%resp_excess_hold) * & + ind_per_m2 * g_per_kg / (days_per_year*sec_per_day) + endif ccohort%sym_nfix_daily = ccohort%sym_nfix_daily + ccohort%sym_nfix_tstep ! weighted mean of D13C by gpp @@ -107,7 +138,8 @@ subroutine AccumulateFluxes_ED(nsites, sites, bc_in, bc_out, dt_time) cpatch => cpatch%younger end do ! while(associated(cpatch)) - end do + + end do return end subroutine AccumulateFluxes_ED diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 979aa2960d..0e83468054 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -294,7 +294,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) ! make new patches from disturbed land if (do_patch_dynamics.eq.itrue ) then - call spawn_patches(currentSite, bc_in) + call spawn_patches(currentSite, bc_in, bc_out) call TotalBalanceCheck(currentSite,3) @@ -320,7 +320,6 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) ! Final instantaneous mass balance check call TotalBalanceCheck(currentSite,5) - end subroutine ed_ecosystem_dynamics !-------------------------------------------------------------------------------! @@ -641,7 +640,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) bc_out%ar_site = bc_out%ar_site + (currentCohort%resp_m_acc_hold + & currentCohort%resp_g_acc_hold + currentCohort%resp_excess_hold) * & AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day - + ! Update the mass balance tracking for the daily nutrient uptake flux ! Then zero out the daily uptakes, they have been used @@ -683,7 +682,11 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%resp_m_acc*currentCohort%n + & (currentCohort%resp_g_acc_hold+currentCohort%resp_excess_hold) * & currentCohort%n/real( hlm_days_per_year,r8) + + write(*,*) 'EDM:acc stgpp',site_cmass%gpp_acc, currentCohort%gpp_acc * currentCohort%n + write(*,*) 'EDM:acc stresp',site_cmass%aresp_acc , + call currentCohort%prt%CheckMassConservation(ft,5) ! Update the leaf biophysical rates based on proportion of leaf @@ -782,7 +785,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) call GenerateDamageAndLitterFluxes( currentSite, currentPatch, bc_in) - call PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in) + call PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in, bc_out) call PreDisturbanceIntegrateLitter(currentPatch ) @@ -828,6 +831,8 @@ subroutine ed_update_site( currentSite, bc_in, bc_out, is_restarting ) ! ! !USES: use EDCanopyStructureMod , only : canopy_spread, canopy_structure + use EDTypesMod , only : AREA ! m2. Area of site + use FatesConstantsMod , only : g_per_kg ! ! !ARGUMENTS: type(ed_site_type) , intent(inout), target :: currentSite @@ -835,6 +840,11 @@ subroutine ed_update_site( currentSite, bc_in, bc_out, is_restarting ) type(bc_out_type) , intent(inout) :: bc_out logical,intent(in) :: is_restarting ! is this called during restart read? ! + real(r8) :: biomass_stock ! total biomass in Kg/site + real(r8) :: litter_stock ! total litter in Kg/site + real(r8) :: seed_stock ! total seed mass in Kg/site + real(r8) :: total_stock ! total ED carbon in Kg/site + ! !LOCAL VARIABLES: type (fates_patch_type) , pointer :: currentPatch !----------------------------------------------------------------------- @@ -856,6 +866,11 @@ subroutine ed_update_site( currentSite, bc_in, bc_out, is_restarting ) call TotalBalanceCheck(currentSite,final_check_id) + call SiteMassStock(currentSite,1,total_stock,biomass_stock,litter_stock,seed_stock) + ! convert from kgC/site to gC/m2 + bc_out%fates_total_carbon_site = total_stock * g_per_kg/AREA + write(*,*) 'total_stock F3, B-L-S',total_stock*g_per_kg/AREA,biomass_stock* g_per_kg/AREA,litter_stock* g_per_kg/AREA,seed_stock* g_per_kg/AREA + ! Update recruit L2FRs based on new canopy position call SetRecruitL2FR(currentSite) @@ -968,7 +983,7 @@ subroutine TotalBalanceCheck (currentSite, call_index ) call SiteMassStock(currentSite,el,total_stock,biomass_stock,litter_stock,seed_stock) change_in_stock = total_stock - site_mass%old_stock - + flux_in = site_mass%seed_in + & site_mass%net_root_uptake + & site_mass%gpp_acc + & @@ -987,7 +1002,9 @@ subroutine TotalBalanceCheck (currentSite, call_index ) net_flux = flux_in - flux_out error = abs(net_flux - change_in_stock) - + write(*,*) 'fatesBALC: netf,chst',net_flux/10._r8,change_in_stock/10._r8 + write(*,*) 'fatesBALC: net npp',(site_mass%gpp_acc - site_mass%aresp_acc)/10._r8 + write(*,*) 'fatesBALC: news, olds', total_stock/10._r8, site_mass%old_stock/10._r8 if(change_in_stock>0.0)then error_frac = error/abs(total_stock) else diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f18dd6de9c..f9125565c8 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -8530,7 +8530,7 @@ subroutine define_history_vars(this, initialize_variables) upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & index = ih_livestem_mr_si) - call this%set_history_var(vname='FATES_NEP', units='kg m-2 s-1', & + call this%set_history_var(vname='FATES_NEP_INT', units='kg m-2 s-1', & long='net ecosystem production in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 025af97745..268a25e6d9 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -371,7 +371,11 @@ subroutine zero_bcs(fates,s) write(fates_log(), *) 'hlm_parteh_mode: ',hlm_parteh_mode call endrun(msg=errMsg(sourcefile, __LINE__)) end select - + + ! carbon loss to atmosphere pathways + fates%bc_out(s)%grazing_closs_to_atm_si = 0.0_r8 + fates%bc_out(s)%fire_closs_to_atm_si = 0.0_r8 + fates%bc_out(s)%rssun_pa(:) = 0.0_r8 fates%bc_out(s)%rssha_pa(:) = 0.0_r8 @@ -408,6 +412,9 @@ subroutine zero_bcs(fates,s) ! Land Use realated fates%bc_out(s)%gpp_site = 0.0_r8 fates%bc_out(s)%ar_site = 0.0_r8 + fates%bc_out(s)%npp_site = 0.0_r8 + fates%bc_out(s)%npp_acc_site = 0.0_r8 + fates%bc_out(s)%fates_total_carbon_site = 0.0_r8 fates%bc_out(s)%hrv_deadstemc_to_prod10c = 0.0_r8 fates%bc_out(s)%hrv_deadstemc_to_prod100c = 0.0_r8 diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 4681845cce..717e596061 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -822,6 +822,14 @@ module FatesInterfaceTypesMod real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] real(r8) :: gpp_site ! Site level GPP, for NBP diagnosis in HLM [Site-Level, gC m-2 s-1] real(r8) :: ar_site ! Site level Autotrophic Resp, for NBP diagnosis in HLM [Site-Level, gC m-2 s-1] + real(r8) :: npp_site ! Site level timestep-specific NPP, for NBP diagnosis in HLM [Site-Level, gC m-2 s-1] + real(r8) :: npp_acc_site ! Sitelevel, timestep-specific accumulated NPP to account for assimilate but not allocated C in HLM balance check. gC/m2 + real(r8) :: gresp_site ! Sitelevel, daily growth respiration flux gC/m2/day to be added to unreleased carbon pool. + real(r8) :: fates_total_carbon_site ! Site level total carbon in FATES (g/m2) for HLM balance check + + ! direct carbon loss to atm pathways + real(r8) :: grazing_closs_to_atm_si ! Loss of carbon to atmosphere via grazing [Site-Level, gC m-2 s-1] + real(r8) :: fire_closs_to_atm_si ! Loss of carbon to atmosphere via burning (includes burning from land use change) [Site-Level, gC m-2 s-1] end type bc_out_type