From d62cf3e1e03875fb0c2105a667ed2013cbcfedb7 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 11 Jun 2024 09:12:37 -0400 Subject: [PATCH 01/26] incremental progress towards more flux diagnostics --- biogeochem/FatesSoilBGCFluxMod.F90 | 22 +++++++- main/EDInitMod.F90 | 21 +++++-- main/EDMainMod.F90 | 3 +- main/EDTypesMod.F90 | 88 +++++++++++++++++++++++++----- main/FatesHistoryInterfaceMod.F90 | 47 ---------------- 5 files changed, 113 insertions(+), 68 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 9d813c32b3..eb878639ce 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -218,13 +218,33 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) ccohort%daily_p_demand = fnrt_c * EDPftvarcon_inst%vmax_p(pft) * sec_per_day ! P Uptake: Convert g/m2/day -> kg/plant/day ccohort%daily_p_gain = bc_in(s)%plant_p_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n + + ! Track flux diagnostics for history writing + sites(s)%flux_diags%p_uptake = sites(s)%flux_diags%p_uptake + bc_in(s)%plant_p_uptake_flux(icomp,1)/sec_per_day + ccohort => ccohort%shorter end do cpatch => cpatch%younger end do end if - + + ! Update diagnostic arrays + cpatch => sites(s)%oldest_patch + do while (associated(cpatch)) + ccohort => cpatch%tallest + do while (associated(ccohort)) + pft = ccohort%pft + + + + + ccohort => ccohort%shorter + end do + cpatch => cpatch%younger + end do + + ! These can now be zero'd bc_in(s)%plant_nh4_uptake_flux(:,:) = 0._r8 bc_in(s)%plant_no3_uptake_flux(:,:) = 0._r8 diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index e33ee5e7ec..94a2b73945 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -145,7 +145,8 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%fmort_rate_crown(1:nlevsclass,1:numpft)) allocate(site_in%growthflux_fusion(1:nlevsclass,1:numpft)) allocate(site_in%mass_balance(1:num_elements)) - allocate(site_in%flux_diags(1:num_elements)) + + if (hlm_use_tree_damage .eq. itrue) then allocate(site_in%term_nindivs_canopy_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) @@ -206,10 +207,21 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%sp_tsai(1:numpft)) allocate(site_in%sp_htop(1:numpft)) + ! Allocate site-level flux diagnostics + ! ----------------------------------------------------------------------- + allocate(site_in%flux_diags%elem_diag(1:num_elements)) do el=1,num_elements - allocate(site_in%flux_diags(el)%leaf_litter_input(1:numpft)) - allocate(site_in%flux_diags(el)%root_litter_input(1:numpft)) + allocate(site_in%flux_diags%elem_diag(el)%leaf_litter_input(1:numpft)) + allocate(site_in%flux_diags%elem_diag(el)%root_litter_input(1:numpft)) end do + allocate(site_in%flux_diags%nh4_uptake_scpf(numpft*nlevsclass)) + allocate(site_in%flux_diags%no3_uptake_scpf(numpft*nlevsclass)) + allocate(site_in%flux_diags%sym_nfix_scpf(numpft*nlevsclass)) + allocate(site_in%flux_diags%n_efflux_scpf(numpft*nlevsclass)) + allocate(site_in%flux_diags%p_uptake_scpf(numpft*nlevsclass)) + allocate(site_in%flux_diags%p_efflux_scpf(numpft*nlevsclass)) + + ! Initialize the static soil ! arrays from the boundary (initial) condition @@ -282,9 +294,10 @@ subroutine zero_site( site_in ) ! Zero the state variables used for checking mass conservation call site_in%mass_balance(el)%ZeroMassBalState() call site_in%mass_balance(el)%ZeroMassBalFlux() - call site_in%flux_diags(el)%ZeroFluxDiags() end do + call site_in%flux_diags%ZeroFluxDiags() + ! This will be initialized in FatesSoilBGCFluxMod:PrepCH4BCs() ! It checks to see if the value is below -9000. If it is, ! it will assume the first value of the smoother is set diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 06e4b74c80..328ab437a6 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -163,9 +163,10 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) do el = 1,num_elements call currentSite%mass_balance(el)%ZeroMassBalFlux() - call currentSite%flux_diags(el)%ZeroFluxDiags() end do + call currentSite%flux_diags%ZeroFluxDiags() + ! Call a routine that simply identifies if logging should occur ! This is limited to a global event until more structured event handling is enabled call IsItLoggingTime(hlm_masterproc,currentSite) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index b482370058..eafa98aae1 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -147,7 +147,7 @@ module EDTypesMod ! ===================================================================================== - type, public :: site_fluxdiags_type + type, public :: elem_diag_type ! ---------------------------------------------------------------------------------- ! Diagnostics of fluxes @@ -161,19 +161,54 @@ module EDTypesMod ! (2) mass transfer from non-disturbance inducing mortality events ! (3) mass transfer from disturbance inducing mortality events ! [kg / ha / day] + ! + ! + ! ! --------------------------------------------------------------------------------- - + real(r8) :: cwd_ag_input(1:ncwd) real(r8) :: cwd_bg_input(1:ncwd) real(r8),allocatable :: leaf_litter_input(:) real(r8),allocatable :: root_litter_input(:) + + end type elem_diag_type + + + type, public :: site_fluxdiags_type + + + ! This is for all diagnostics that are uniform over all elements (C,N,P) + + type(elem_diag_type), pointer :: elem_diag(:) ! This variable is slated as to-do, but the fluxdiags type needs ! to be refactored first. Currently this type is allocated ! by chemical species (ie C, N or P). GPP is C, but not N or P (RGK 0524) ! Previous day GPP [kgC/m2/year], partitioned by size x pft !real(r8),allocatable :: gpp_prev_scpf(:) + + ! Nutrient Flux Diagnostics + + real(r8) :: resp_excess + real(r8) :: nh4_uptake ! plant nh4 uptake, kg m-2 s-1 + real(r8) :: no3_uptake ! plant no3 uptake, kg m-2 s-1 + real(r8) :: sym_nfix ! plant N uptake via symbiotic fixation kg m-2 s-1 + real(r8) :: n_efflux ! efflux of unusable N from plant to soil labile pool kg m-2 s-1 + real(r8) :: p_uptake ! po4 uptake, kg m-2 s-1 + real(r8) :: p_efflux ! efflux of unusable P from plant to soil labile pool kg m-2 s-1 + + ! Size by PFT delineated nutrient flux diagnostics (same units as above) + ! These are only allocated if both complex history diagnostics, and the + ! species of interest (N or P) is requested + real(r8),allocatable :: nh4_uptake_scpf(:) + real(r8),allocatable :: no3_uptake_scpf(:) + real(r8),allocatable :: sym_nfix_scpf(:) + real(r8),allocatable :: n_efflux_scpf(:) + real(r8),allocatable :: p_uptake_scpf(:) + real(r8),allocatable :: p_efflux_scpf(:) + + contains @@ -305,9 +340,14 @@ module EDTypesMod type(site_massbal_type), pointer :: mass_balance(:) - ! Flux diagnostics (allocation for each element) + ! Flux diagnostics + ! These are used to write history output based on fluxes + ! that are calculated before mortality and cohort/patch restructuring + ! but are written after patch structure. This structure also allows for + ! accurate restarting of the history - type(site_fluxdiags_type), pointer :: flux_diags(:) + type(site_fluxdiags_type) :: flux_diags + ! PHENOLOGY real(r8) :: grow_deg_days ! Phenology growing degree days @@ -471,19 +511,37 @@ module EDTypesMod subroutine ZeroFluxDiags(this) class(site_fluxdiags_type) :: this + integer :: el - this%cwd_ag_input(:) = 0._r8 - this%cwd_bg_input(:) = 0._r8 - this%leaf_litter_input(:) = 0._r8 - this%root_litter_input(:) = 0._r8 - - ! We don't zero gpp_prev_scpf because this is not - ! incremented like others, it is assigned at the end - ! of the daily history write process - + do el = 1,num_elements + this%elem_diag(el)%cwd_ag_input(:) = 0._r8 + this%elem_diag(el)%cwd_bg_input(:) = 0._r8 + this%elem_diag(el)%leaf_litter_input(:) = 0._r8 + this%elem_diag(el)%root_litter_input(:) = 0._r8 + end do + + this%resp_excess = 0._r8 + this%nh4_uptake = 0._r8 + this%no3_uptake = 0._r8 + this%sym_nfix = 0._r8 + this%n_efflux = 0._r8 + this%p_uptake = 0._r8 + this%p_efflux = 0._r8 + + this%nh4_uptake_scpf(:) = 0._r8 + this%no3_uptake_scpf(:) = 0._r8 + this%sym_nfix_scpf(:) = 0._r8 + this%n_efflux_scpf(:) = 0._r8 + this%p_uptake_scpf(:) = 0._r8 + this%p_efflux_scpf(:) = 0._r8 - return - end subroutine ZeroFluxDiags + ! We don't zero gpp_prev_scpf because this is not + ! incremented like others, it is assigned at the end + ! of the daily history write process + + + return + end subroutine ZeroFluxDiags ! ===================================================================================== diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 6c34f48292..2d174851ac 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -279,10 +279,6 @@ module FatesHistoryInterfaceMod integer :: ih_pefflux_si integer :: ih_nefflux_scpf integer :: ih_pefflux_scpf - integer :: ih_ndemand_si - integer :: ih_ndemand_scpf - integer :: ih_pdemand_si - integer :: ih_pdemand_scpf integer :: ih_nfix_si integer :: ih_nfix_scpf @@ -2178,11 +2174,6 @@ subroutine update_history_nutrflux(this,csite) this%hvars(ih_nefflux_si)%r81d(io_si) + & ccohort%daily_n_efflux*uconv - ! Demand - this%hvars(ih_ndemand_si)%r81d(io_si) = & - this%hvars(ih_ndemand_si)%r81d(io_si) + & - ccohort%daily_n_demand*uconv - case (phosphorus_element) ! Mineralized uptake of PO4 @@ -2195,11 +2186,6 @@ subroutine update_history_nutrflux(this,csite) this%hvars(ih_pefflux_si)%r81d(io_si) + & ccohort%daily_p_efflux*uconv - ! Demand - this%hvars(ih_pdemand_si)%r81d(io_si) = & - this%hvars(ih_pdemand_si)%r81d(io_si) + & - ccohort%daily_p_demand*uconv - end select end do @@ -2268,11 +2254,6 @@ subroutine update_history_nutrflux(this,csite) this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) + & ccohort%daily_n_efflux*uconv - ! Demand - this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_n_demand*uconv - case (phosphorus_element) ! Mineralized uptake of PO4 @@ -2285,11 +2266,6 @@ subroutine update_history_nutrflux(this,csite) this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) + & ccohort%daily_p_efflux*uconv - ! Demand - this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_p_demand*uconv - end select end do @@ -6433,12 +6409,6 @@ subroutine define_history_vars(this, initialize_variables) upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_nefflux_si) - call this%set_history_var(vname='FATES_NDEMAND', units='kg m-2 s-1', & - long='plant nitrogen need (algorithm dependent) in kg N per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & - index = ih_ndemand_si) - call this%set_history_var(vname='FATES_NFIX_SYM', units='kg m-2 s-1', & long='symbiotic dinitrogen fixation in kg N per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -6536,11 +6506,6 @@ subroutine define_history_vars(this, initialize_variables) upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_pefflux_si) - call this%set_history_var(vname='FATES_PDEMAND', units='kg m-2 s-1', & - long='plant phosphorus need (algorithm dependent) in kg P per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & - index = ih_pdemand_si) end if phosphorus_active_if0 call this%set_history_var(vname='FATES_STRUCTC', units='kg m-2', & @@ -7170,12 +7135,6 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & initialize=initialize_variables, index = ih_nefflux_scpf) - call this%set_history_var(vname='FATES_NDEMAND_SZPF', units='kg m-2 s-1', & - long='plant N need (algorithm dependent), by size-class x pft in kg N per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & - initialize=initialize_variables, index = ih_ndemand_scpf) - call this%set_history_var(vname='FATES_NFIX_SYM_SZPF', units='kg m-2 s-1', & long='symbiotic dinitrogen fixation, by size-class x pft in kg N per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & @@ -7301,12 +7260,6 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & initialize=initialize_variables, index = ih_pefflux_scpf) - call this%set_history_var(vname='FATES_PDEMAND_SZPF', units='kg m-2 s-1', & - long='plant P need (algorithm dependent), by size-class x pft in kg P per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & - initialize=initialize_variables, index = ih_pdemand_scpf) - end if phosphorus_active_if1 call this%set_history_var(vname='FATES_CROWNAREA_CLLL', units='m2 m-2', & From e2afc630e05bd1d790a08f1e479a772f73e668af Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 11 Jun 2024 10:33:57 -0400 Subject: [PATCH 02/26] Started up the integrated flux balance tracking --- main/EDInitMod.F90 | 18 +++++++++++--- main/EDTypesMod.F90 | 41 +++++++++++++++++++++++++++++-- main/FatesHistoryInterfaceMod.F90 | 30 ++++++++++++++++++++++ 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 94a2b73945..c582a906ef 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -33,7 +33,7 @@ module EDInitMod use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : numWaterMem use EDTypesMod , only : num_vegtemp_mem - use EDTypesMod , only : AREA + use EDTypesMod , only : area, area_inv use EDTypesMod , only : init_spread_near_bare_ground use EDTypesMod , only : init_spread_inventory use FatesConstantsMod , only : leaves_on @@ -145,8 +145,7 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%fmort_rate_crown(1:nlevsclass,1:numpft)) allocate(site_in%growthflux_fusion(1:nlevsclass,1:numpft)) allocate(site_in%mass_balance(1:num_elements)) - - + allocate(site_in%iflux_balance(1:num_elements)) if (hlm_use_tree_damage .eq. itrue) then allocate(site_in%term_nindivs_canopy_damage(1:nlevdamage, 1:nlevsclass, 1:numpft)) @@ -485,7 +484,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) write(fates_log(),*) 'negative area',s,ft,sites(s)%area_pft(ft) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - sites(s)%area_pft(ft)= sites(s)%area_pft(ft) * AREA ! rescale units to m2. + sites(s)%area_pft(ft)= sites(s)%area_pft(ft) * area ! rescale units to m2. end do ! re-normalize PFT area to ensure it sums to one. @@ -814,6 +813,13 @@ subroutine init_patches( nsites, sites, bc_in) do el=1,num_elements call SiteMassStock(sites(s),el,sites(s)%mass_balance(el)%old_stock, & biomass_stock,litter_stock,seed_stock) + + ! Initialize the integrated flux balance diagnostics + ! No need to initialize the instantaneous states, those are re-calculated + sites(s)%iflux_balance(el)%iflux_liveveg = & + (biomass_stock + seed_stock)*area_inv + sites(s)%iflux_balance(el)%iflux_litter = litter_stock * area_inv + end do call set_patchno(sites(s)) @@ -860,6 +866,10 @@ subroutine init_patches( nsites, sites, bc_in) end do end if + + + + return end subroutine init_patches diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index eafa98aae1..b9fa7cef6e 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -170,9 +170,37 @@ module EDTypesMod real(r8) :: cwd_bg_input(1:ncwd) real(r8),allocatable :: leaf_litter_input(:) real(r8),allocatable :: root_litter_input(:) + + real(r8) :: netflux_liveveg ! Net change in live vegetation [kg/m2/s] + real(r8) :: netflux_litter ! Net change in litter [kg/m2/s] end type elem_diag_type + ! ------------------------------------------------------------------------- + + type, public :: site_ifluxbal_type + + ! The combination of living vegetation and litter accounts + ! for all of the mass that is tracked by FATES + + ! Mass in living vegetation, this includes: + ! All organs on living plants, including non respiring tissues + ! and heartwood. + ! The live seed pool + + real(r8) :: state_liveveg ! Assessed instanteously [kg/m2] + real(r8) :: iflux_liveveg ! Integrated daily [kg/m2] + + ! Mass in all litter tracked by FATES + ! This includes only the unfragmented litter, litter that + ! has fragmented is tracked by the host models + + real(r8) :: state_litter ! Assessed instantaneously [kg/m2] + real(r8) :: iflux_litter ! Integrated daily [kg/m2] + + end type site_iflux_type + + ! ------------------------------------------------------------------------- type, public :: site_fluxdiags_type @@ -336,10 +364,17 @@ module EDTypesMod real(r8), allocatable :: sp_tsai(:) ! target TSAI per FATES pft real(r8), allocatable :: sp_htop(:) ! target HTOP per FATES pft - ! Mass Balance (allocation for each element) + ! Instantaneous Mass Balance (allocation for each element) type(site_massbal_type), pointer :: mass_balance(:) + ! Integrated Mass Balance checks, i.e. do the integrated + ! fluxes match the state? One is for live vegetation, + ! one if for litter + + type(site_ifluxbal_type), pointer :: iflux_balance(:) + + ! Flux diagnostics ! These are used to write history output based on fluxes ! that are calculated before mortality and cohort/patch restructuring @@ -518,6 +553,8 @@ subroutine ZeroFluxDiags(this) this%elem_diag(el)%cwd_bg_input(:) = 0._r8 this%elem_diag(el)%leaf_litter_input(:) = 0._r8 this%elem_diag(el)%root_litter_input(:) = 0._r8 + this%elem_diag(el)%netflux_liveveg = 0._r8 + this%elem_diag(el)%netflux_litter = 0._r8 end do this%resp_excess = 0._r8 @@ -537,7 +574,7 @@ subroutine ZeroFluxDiags(this) ! We don't zero gpp_prev_scpf because this is not ! incremented like others, it is assigned at the end - ! of the daily history write process + ! of the daily history write process return diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 2d174851ac..3874660eeb 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2313,6 +2313,36 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) call update_history_dyn2(this,nc,nsites,sites,bc_in) end if end if + + if(check_iflux_bal) then + + ! For carbon balance checks, we need to initialize the + ! total carbon stock + do el=1,num_elements + call SiteMassStock(sites(s),el,sites(s)%mass_balance(el)%old_stock, & + biomass_stock,litter_stock,seed_stock) + + ! Initialize the integrated flux balance diagnostics + ! No need to initialize the instantaneous states, those are re-calculated + sites(s)%iflux_balance(el)%state_liveveg = & + (biomass_stock + seed_stock)*area_inv + sites(s)%iflux_balance(el)%state_litter = litter_stock * area_inv + + sites(s)%iflux_balance(el)%iflux_liveveg = & + sites(s)%iflux_balance(el)%iflux_liveveg + & + sites(s)%flux_diags%elem_diags(el)%netflux_liveveg + + sites(s)%iflux_balance(el)%iflux_litter = & + sites(s)%iflux_balance(el)%iflux_litter + & + sites(s)%flux_diags%elem_diags(el)%netflux_litter + + + end do + + + end if + + return end subroutine update_history_dyn From 0d58b8915662d2d11365eb24635a71c288a8b223 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 11 Jun 2024 11:21:50 -0400 Subject: [PATCH 03/26] Updates to integrated flux diagnostics --- main/ChecksBalancesMod.F90 | 62 +++++++++++++++++++++++++++++++ main/FatesHistoryInterfaceMod.F90 | 29 --------------- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index df671a52ac..af447addfb 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -240,8 +240,70 @@ subroutine CheckLitterPools(currentSite,bc_in) return end subroutine CheckLitterPools + ! ================================================================== + subroutine CheckIntegratedMassPools(sites) + + type(ed_site_type) , intent(inout), target :: sites(:) + + integer :: nsites + integer :: el + integer :: s + + logical,parameter :: check_iflux_bal = .true. + + + if(check_iflux_bal) then + + nsites = ubound(sites,dim=1) + + do s = 1,nsites + + ! For carbon balance checks, we need to initialize the + ! total carbon stock + do el=1,num_elements + call SiteMassStock(sites(s),el,sites(s)%mass_balance(el)%old_stock, & + biomass_stock,litter_stock,seed_stock) + + associate(ibal => sites(s)%iflux_balance(el), & + diag => sites(s)%flux_diags%elem_diags(el)) + + + + ! Initialize the integrated flux balance diagnostics + ! No need to initialize the instantaneous states, those are re-calculated + + ibal%state_liveveg = (biomass_stock + seed_stock)*area_inv + ibal%state_litter = litter_stock * area_inv + + ibal%iflux_liveveg = ibal%iflux_liveveg + & + diag%netflux_liveveg * sec_per_day + + ibal%iflux_litter = ibal%iflux_litter + & + diag%netflux_litter * sec_per_day + + ! Perform the comparison between integrated flux and state + if(abs(ibal%state_liveveg - ibal%iflux_liveveg) > iflux_tol(el) ) then + write(fates_log(),*) 'The fluxes in to an out of live vegetation are integrated' + write(fates_log(),*) 'in time over the length of the FATES simulation.' + write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' + write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' + write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' + write(fates_log(),*) 'state_liveveg: ',ibal%state_liveveg + write(fates_log(),*) 'iflux_liveveg: ',ibal%iflux_liveveg + write(fates_log(),*) 'state - iflux: ',ibal%state_liveveg - & + ibal%iflux_liveveg + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + end do + end do + end if + + return + end subroutine CheckIntegratedMassPools + end module ChecksBalancesMod diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 3874660eeb..e5da84f07b 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2313,35 +2313,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) call update_history_dyn2(this,nc,nsites,sites,bc_in) end if end if - - if(check_iflux_bal) then - - ! For carbon balance checks, we need to initialize the - ! total carbon stock - do el=1,num_elements - call SiteMassStock(sites(s),el,sites(s)%mass_balance(el)%old_stock, & - biomass_stock,litter_stock,seed_stock) - - ! Initialize the integrated flux balance diagnostics - ! No need to initialize the instantaneous states, those are re-calculated - sites(s)%iflux_balance(el)%state_liveveg = & - (biomass_stock + seed_stock)*area_inv - sites(s)%iflux_balance(el)%state_litter = litter_stock * area_inv - - sites(s)%iflux_balance(el)%iflux_liveveg = & - sites(s)%iflux_balance(el)%iflux_liveveg + & - sites(s)%flux_diags%elem_diags(el)%netflux_liveveg - - sites(s)%iflux_balance(el)%iflux_litter = & - sites(s)%iflux_balance(el)%iflux_litter + & - sites(s)%flux_diags%elem_diags(el)%netflux_litter - - - end do - - - end if - return end subroutine update_history_dyn From 50e675df2c9d516ba8d14ee633f768e67fd4ca3f Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 11 Jun 2024 12:23:31 -0400 Subject: [PATCH 04/26] More work towards tracking integrated mass checks --- biogeochem/EDPhysiologyMod.F90 | 7 ++ main/ChecksBalancesMod.F90 | 121 +++++++++++++++++++++--------- main/EDMainMod.F90 | 4 + main/EDTypesMod.F90 | 4 + main/FatesHistoryInterfaceMod.F90 | 3 + 5 files changed, 105 insertions(+), 34 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index e25a722f7a..16de218d1b 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2689,6 +2689,12 @@ subroutine recruitment(currentSite, currentPatch, bc_in) m_repro = 0._r8 end select + ! Diagnose the recruit flux [kg/m2] + currentSite%flux_diags%elem_diags(el)%recruit_flux = & + currentSite%flux_diags%elem_diags(el)%recruit_flux + & + (m_struct+m_leaf+m_fnrt+m_sapw+m_store+m_repro)*currentCohort%n*area_inv + + select case(hlm_parteh_mode) case (prt_carbon_allom_hyp, prt_cnp_flex_allom_hyp) @@ -2731,6 +2737,7 @@ subroutine recruitment(currentSite, currentPatch, bc_in) currentPatch%litter(el)%seed_germ(ft) - cohort_n / currentPatch%area * & (m_struct + m_leaf + m_fnrt + m_sapw + m_store + m_repro) end if + end do ! cycle through the initial conditions, and makes sure that they are all initialized diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index af447addfb..e7e43ccd72 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -31,7 +31,8 @@ module ChecksBalancesMod private public :: SiteMassStock public :: PatchMassStock - + public :: CheckIntegratedMassPools + character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -245,14 +246,18 @@ end subroutine CheckLitterPools subroutine CheckIntegratedMassPools(sites) - type(ed_site_type) , intent(inout), target :: sites(:) - - integer :: nsites - integer :: el - integer :: s - - logical,parameter :: check_iflux_bal = .true. + type(ed_site_type), intent(inout), target :: sites(:) + + integer :: nsites + integer :: el + integer :: s + real(r8) :: tot_veg_turnover + real(r8) :: net_uptake + real(r8) :: biomass_stock + real(r8) :: seed_stock + real(r8) :: litter_stock + logical,parameter :: check_iflux_bal = .true. if(check_iflux_bal) then @@ -267,36 +272,84 @@ subroutine CheckIntegratedMassPools(sites) biomass_stock,litter_stock,seed_stock) associate(ibal => sites(s)%iflux_balance(el), & - diag => sites(s)%flux_diags%elem_diags(el)) + ediag => sites(s)%flux_diags%elem_diags(el), & + diag => sites(s)%flux_diags) + + ! Initialize the integrated flux balance diagnostics + ! No need to initialize the instantaneous states, those are re-calculated + + ibal%state_liveveg = (biomass_stock + seed_stock)*area_inv + ibal%state_litter = litter_stock * area_inv + ! Flux for live veg: NPP + + ! net spatial seed flux + + ! veg turnover - + ! seed turnover - ! Initialize the integrated flux balance diagnostics - ! No need to initialize the instantaneous states, those are re-calculated + tot_litter_input = sum(ediag%leaf_litter_input(:)) + & + sum(ediag%root_litter_input(:)) + & + sum(ediag%cwd_ag_input(:)) + & + sum(ediag%cwd_bg_input(:)) + + tot_veg_turnover = tot_litter_input - ediag%seed_turnover - ediag%fire_atm_flux - ibal%state_liveveg = (biomass_stock + seed_stock)*area_inv - ibal%state_litter = litter_stock * area_inv - - ibal%iflux_liveveg = ibal%iflux_liveveg + & - diag%netflux_liveveg * sec_per_day - - ibal%iflux_litter = ibal%iflux_litter + & - diag%netflux_litter * sec_per_day - - ! Perform the comparison between integrated flux and state - if(abs(ibal%state_liveveg - ibal%iflux_liveveg) > iflux_tol(el) ) then - write(fates_log(),*) 'The fluxes in to an out of live vegetation are integrated' - write(fates_log(),*) 'in time over the length of the FATES simulation.' - write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' - write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' - write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' - write(fates_log(),*) 'state_liveveg: ',ibal%state_liveveg - write(fates_log(),*) 'iflux_liveveg: ',ibal%iflux_liveveg - write(fates_log(),*) 'state - iflux: ',ibal%state_liveveg - & - ibal%iflux_liveveg - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - + select case(element_list(el)) + case(carbon12_element) + net_uptake = diag%npp + case(nitrogen_element) + net_uptake = diag%n_uptake + diag%sym_nfix - diag%n_efflux + case(phosphorus_element) + net_uptake = diag%p_uptake - diag%p_efflux + case default + write(fates_log(),*) 'FATES: Invalid choice for cohort_fusion_conservation_method' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + ! Fluxes are in [kg/m2/s] integrate to [kg/m2] + ibal%iflux_liveveg = ibal%iflux_liveveg + & + ( net_uptake & + - tot_veg_turnover & + + ediag%net_seed_transport & + - ediag%seed_turnover) * sec_per_day + + ! Flux for litter: veg turnover + + ! seed turnover - + ! fragmentation - + ! burned + + ibal%iflux_litter = ibal%iflux_litter + & + ediag%netflux_litter * sec_per_day + + ! Perform the comparison between integrated flux and state + if(abs(ibal%state_liveveg - ibal%iflux_liveveg) > iflux_tol(el) ) then + write(fates_log(),*) 'The fluxes in to an out of live vegetation are integrated' + write(fates_log(),*) 'in time over the length of the FATES simulation.' + write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' + write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' + write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' + write(fates_log(),*) 'state_liveveg: ',ibal%state_liveveg + write(fates_log(),*) 'iflux_liveveg: ',ibal%iflux_liveveg + write(fates_log(),*) 'state - iflux: ',ibal%state_liveveg - & + ibal%iflux_liveveg + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + if(abs(ibal%state_litter - ibal%iflux_litter) > iflux_tol(el) ) then + write(fates_log(),*) 'The fluxes in to an out of litter are integrated' + write(fates_log(),*) 'in time over the length of the FATES simulation.' + write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' + write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' + write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' + write(fates_log(),*) 'state_litter: ',ibal%state_litter + write(fates_log(),*) 'iflux_litter: ',ibal%iflux_litter + write(fates_log(),*) 'state - iflux: ',ibal%state_litter - & + ibal%iflux_litter + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + + end associate end do end do end if diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 328ab437a6..625fee2d73 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -513,6 +513,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%gpp_acc_hold = currentCohort%gpp_acc * real(hlm_days_per_year,r8) currentCohort%resp_acc_hold = currentCohort%resp_acc * real(hlm_days_per_year,r8) + ! Save NPP diagnostic for flux accounting [kg/m2/s] + currentSite%flux_diags%npp = currentSite%flux_diags%npp + & + currentCohort%npp_acc * currentCohort%n * area_inv * day_per_sec + ! Passing gpp_acc_hold to HLM bc_out%gpp_site = bc_out%gpp_site + currentCohort%gpp_acc_hold * & AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index b9fa7cef6e..a495e27738 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -171,6 +171,10 @@ module EDTypesMod real(r8),allocatable :: leaf_litter_input(:) real(r8),allocatable :: root_litter_input(:) + real(r8) :: net_seed_transport + real(r8) :: seed_turnover + + real(r8) :: netflux_liveveg ! Net change in live vegetation [kg/m2/s] real(r8) :: netflux_litter ! Net change in litter [kg/m2/s] diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index e5da84f07b..230d8512b8 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -14,6 +14,7 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : i_term_mort_type_cstarv use FatesConstantsMod , only : i_term_mort_type_canlev use FatesConstantsMod , only : i_term_mort_type_numdens + use ChecksBalancesMod , only : CheckIntegratedMassPools use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun use EDParamsMod , only : nclmax, maxpft @@ -2313,6 +2314,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) call update_history_dyn2(this,nc,nsites,sites,bc_in) end if end if + + call CheckIntegratedMassPools(sites) return end subroutine update_history_dyn From 7dd60f402dc562af2cf5a354fade101e62e8f994 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 12 Jun 2024 10:12:49 -0400 Subject: [PATCH 05/26] more updates to checks and balances --- biogeochem/EDPatchDynamicsMod.F90 | 7 +++++-- biogeochem/EDPhysiologyMod.F90 | 7 ++++++- main/ChecksBalancesMod.F90 | 12 ++++++------ main/EDTypesMod.F90 | 5 +++-- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 140c108d66..2e16c0d9d7 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1755,7 +1755,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & element_id = element_list(el) site_mass => currentSite%mass_balance(el) - flux_diags => currentSite%flux_diags(el) + flux_diags => currentSite%flux_diags curr_litt => currentPatch%litter(el) ! Litter pool of "current" patch new_litt => newPatch%litter(el) ! Litter pool of "new" patch @@ -1815,6 +1815,9 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass + flux_diags%elem_diags(el)%burned_liveveg = & + flux_diags%elem_diags(el)%burned_liveveg + burned_mass*area_inv*sec_per_day + call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) @@ -2290,7 +2293,7 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & end do site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass - + call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 16de218d1b..1ff449a307 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -487,13 +487,18 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) call CWDOut(litt,currentPatch%fragmentation_scaler,nlev_eff_decomp) site_mass => currentSite%mass_balance(el) - + diag => currentSite%flux_diags%elem_diags(el) + ! 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/s] + diag%tot_seed_turnover = diag%tot_seed_turnover + & + (sum(litt%seed_decay) + sum(litt%seed_germ_decay))*currentPatch%area*area_inv*day_per_sec + end do diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index e7e43ccd72..a08b2f58c9 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -282,8 +282,9 @@ subroutine CheckIntegratedMassPools(sites) ibal%state_litter = litter_stock * area_inv ! Flux for live veg: NPP + - ! net spatial seed flux + - ! veg turnover - + ! net spatial seed flux - + ! veg turnover to litter - + ! veg loss to fire (SEEDS DONT BURN) - ! seed turnover @@ -292,8 +293,6 @@ subroutine CheckIntegratedMassPools(sites) sum(ediag%cwd_ag_input(:)) + & sum(ediag%cwd_bg_input(:)) - tot_veg_turnover = tot_litter_input - ediag%seed_turnover - ediag%fire_atm_flux - select case(element_list(el)) case(carbon12_element) net_uptake = diag%npp @@ -309,9 +308,10 @@ subroutine CheckIntegratedMassPools(sites) ! Fluxes are in [kg/m2/s] integrate to [kg/m2] ibal%iflux_liveveg = ibal%iflux_liveveg + & ( net_uptake & - - tot_veg_turnover & + - tot_litter_input & + - ediag%burned_liveveg & + ediag%net_seed_transport & - - ediag%seed_turnover) * sec_per_day + - ediag%tot_seed_turnover) * sec_per_day ! Flux for litter: veg turnover + ! seed turnover - diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index a495e27738..ec427ac1aa 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -171,8 +171,9 @@ module EDTypesMod real(r8),allocatable :: leaf_litter_input(:) real(r8),allocatable :: root_litter_input(:) - real(r8) :: net_seed_transport - real(r8) :: seed_turnover + real(r8) :: net_seed_transport + real(r8) :: tot_seed_turnover ! decay of living seed bank to + ! fragmented litter [kg/m2/s] real(r8) :: netflux_liveveg ! Net change in live vegetation [kg/m2/s] From 2bdc4428b202fc2303c1e8b9127557bfb9a9c025 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 12 Jun 2024 10:13:51 -0400 Subject: [PATCH 06/26] updates to checks and balances --- biogeochem/EDPatchDynamicsMod.F90 | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 2e16c0d9d7..ac5abed4ad 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1005,6 +1005,12 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%mass_balance(el)%burn_flux_to_atm = & currentSite%mass_balance(el)%burn_flux_to_atm + & leaf_burn_frac * leaf_m * nc%n + + ! This diagnostic only tracks + currentSite%flux_diags%elem_diag(el)%burned_liveveg = & + currentSite%flux_diags%elem_diag(el)%burned_liveveg + & + leaf_burn_frac * leaf_m * nc%n + end do ! Here the mass is removed from the plant @@ -1815,8 +1821,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass - flux_diags%elem_diags(el)%burned_liveveg = & - flux_diags%elem_diags(el)%burned_liveveg + burned_mass*area_inv*sec_per_day + call set_root_fraction(currentSite%rootfrac_scr, pft, currentSite%zi_soil, & bc_in%max_rooting_depth_index_col) From d55ed92dc84ec4bb27f0286e35ca3bd137d43144 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 13 Jun 2024 15:47:56 -0400 Subject: [PATCH 07/26] updates to checks --- biogeochem/EDCohortDynamicsMod.F90 | 5 +++-- biogeochem/EDLoggingMortalityMod.F90 | 9 +++++---- biogeochem/EDPatchDynamicsMod.F90 | 4 ++-- biogeochem/EDPhysiologyMod.F90 | 6 +++--- main/ChecksBalancesMod.F90 | 30 +++++++++++++++------------- main/EDInitMod.F90 | 6 +++--- main/EDMainMod.F90 | 4 ++-- main/EDTypesMod.F90 | 18 +++++++++-------- 8 files changed, 44 insertions(+), 38 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index ef87851ec1..e63e732759 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -45,6 +45,7 @@ Module EDCohortDynamicsMod use PRTGenericMod , only : max_nleafage use FatesConstantsMod , only : ican_upper use EDTypesMod , only : site_fluxdiags_type + use EDTypesMod , only : elem_diag_type use PRTGenericMod , only : num_elements use FatesConstantsMod , only : leaves_on use FatesConstantsMod , only : leaves_off @@ -602,7 +603,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) type(bc_in_type), intent(in) :: bc_in type(litter_type), pointer :: litt ! Litter object for each element - type(site_fluxdiags_type),pointer :: flux_diags + type(elem_diag_type),pointer :: flux_diags real(r8) :: leaf_m ! leaf mass [kg] real(r8) :: store_m ! storage mass [kg] @@ -646,7 +647,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) endif litt => cpatch%litter(el) - flux_diags => csite%flux_diags(el) + flux_diags => csite%flux_diags%elem(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) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index bf6ab7443c..11de3c471c 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -19,6 +19,7 @@ module EDLoggingMortalityMod use FatesPatchMod , only : fates_patch_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type + use EDTypesMod , only : elem_diag_type use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type @@ -733,7 +734,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site !LOCAL VARIABLES: type(fates_cohort_type), pointer :: currentCohort type(site_massbal_type), pointer :: site_mass - type(site_fluxdiags_type), pointer :: flux_diags + type(elem_diag_type), pointer :: flux_diags type(litter_type),pointer :: new_litt type(litter_type),pointer :: cur_litt @@ -791,12 +792,12 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site do el = 1,num_elements - + element_id = element_list(el) site_mass => currentSite%mass_balance(el) - flux_diags=> currentSite%flux_diags(el) + flux_diags=> currentSite%flux_diags%elem(el) cur_litt => currentPatch%litter(el) ! Litter pool of "current" patch - new_litt => newPatch%litter(el) ! Litter pool of "new" patch + new_litt => newPatch%litter(el) ! Litter pool of "new" patch ! Zero some site level accumulator diagnsotics trunk_product_site = 0.0_r8 diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ac5abed4ad..7d11d07554 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1007,8 +1007,8 @@ subroutine spawn_patches( currentSite, bc_in) leaf_burn_frac * leaf_m * nc%n ! This diagnostic only tracks - currentSite%flux_diags%elem_diag(el)%burned_liveveg = & - currentSite%flux_diags%elem_diag(el)%burned_liveveg + & + currentSite%flux_diags%elem(el)%burned_liveveg = & + currentSite%flux_diags%elem(el)%burned_liveveg + & leaf_burn_frac * leaf_m * nc%n end do diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 1ff449a307..309c0a8607 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -487,7 +487,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) call CWDOut(litt,currentPatch%fragmentation_scaler,nlev_eff_decomp) site_mass => currentSite%mass_balance(el) - diag => currentSite%flux_diags%elem_diags(el) + diag => currentSite%flux_diags%elem(el) ! Fragmentation flux to soil decomposition model [kg/site/day] site_mass%frag_out = site_mass%frag_out + currentPatch%area * & @@ -2695,8 +2695,8 @@ subroutine recruitment(currentSite, currentPatch, bc_in) end select ! Diagnose the recruit flux [kg/m2] - currentSite%flux_diags%elem_diags(el)%recruit_flux = & - currentSite%flux_diags%elem_diags(el)%recruit_flux + & + currentSite%flux_diags%elem(el)%recruit_flux = & + currentSite%flux_diags%elem(el)%recruit_flux + & (m_struct+m_leaf+m_fnrt+m_sapw+m_store+m_repro)*currentCohort%n*area_inv diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index a08b2f58c9..680217a8da 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -16,6 +16,8 @@ module ChecksBalancesMod use FatesLitterMod, only : ncwd use FatesLitterMod, only : ndcmpy use PRTGenericMod, only : carbon12_element + use PRTGenericMod, only : nitrogen_element + use PRTGenericMod, only : phosphorus_element use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : fnrt_organ use PRTGenericMod, only : sapw_organ @@ -272,7 +274,7 @@ subroutine CheckIntegratedMassPools(sites) biomass_stock,litter_stock,seed_stock) associate(ibal => sites(s)%iflux_balance(el), & - ediag => sites(s)%flux_diags%elem_diags(el), & + ediag => sites(s)%flux_diags%elem(el), & diag => sites(s)%flux_diags) ! Initialize the integrated flux balance diagnostics @@ -297,7 +299,7 @@ subroutine CheckIntegratedMassPools(sites) case(carbon12_element) net_uptake = diag%npp case(nitrogen_element) - net_uptake = diag%n_uptake + diag%sym_nfix - diag%n_efflux + net_uptake = diag%nh4_uptake + diag%no3_uptake + diag%sym_nfix - diag%n_efflux case(phosphorus_element) net_uptake = diag%p_uptake - diag%p_efflux case default @@ -335,18 +337,18 @@ subroutine CheckIntegratedMassPools(sites) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(abs(ibal%state_litter - ibal%iflux_litter) > iflux_tol(el) ) then - write(fates_log(),*) 'The fluxes in to an out of litter are integrated' - write(fates_log(),*) 'in time over the length of the FATES simulation.' - write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' - write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' - write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' - write(fates_log(),*) 'state_litter: ',ibal%state_litter - write(fates_log(),*) 'iflux_litter: ',ibal%iflux_litter - write(fates_log(),*) 'state - iflux: ',ibal%state_litter - & - ibal%iflux_litter - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + !if(abs(ibal%state_litter - ibal%iflux_litter) > iflux_tol(el) ) then + ! write(fates_log(),*) 'The fluxes in to an out of litter are integrated' + ! write(fates_log(),*) 'in time over the length of the FATES simulation.' + ! write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' + ! write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' + ! write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' + ! write(fates_log(),*) 'state_litter: ',ibal%state_litter + ! write(fates_log(),*) 'iflux_litter: ',ibal%iflux_litter + ! write(fates_log(),*) 'state - iflux: ',ibal%state_litter - & + ! ibal%iflux_litter + ! call endrun(msg=errMsg(sourcefile, __LINE__)) + !end if end associate diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index c582a906ef..1f14604d9a 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -208,10 +208,10 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) ! Allocate site-level flux diagnostics ! ----------------------------------------------------------------------- - allocate(site_in%flux_diags%elem_diag(1:num_elements)) + allocate(site_in%flux_diags%elem(1:num_elements)) do el=1,num_elements - allocate(site_in%flux_diags%elem_diag(el)%leaf_litter_input(1:numpft)) - allocate(site_in%flux_diags%elem_diag(el)%root_litter_input(1:numpft)) + allocate(site_in%flux_diags%elem(el)%leaf_litter_input(1:numpft)) + allocate(site_in%flux_diags%elem(el)%root_litter_input(1:numpft)) end do allocate(site_in%flux_diags%nh4_uptake_scpf(numpft*nlevsclass)) allocate(site_in%flux_diags%no3_uptake_scpf(numpft*nlevsclass)) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 625fee2d73..604923ce0e 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -513,9 +513,9 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%gpp_acc_hold = currentCohort%gpp_acc * real(hlm_days_per_year,r8) currentCohort%resp_acc_hold = currentCohort%resp_acc * real(hlm_days_per_year,r8) - ! Save NPP diagnostic for flux accounting [kg/m2/s] + ! Save NPP diagnostic for flux accounting [kg/m2/day] currentSite%flux_diags%npp = currentSite%flux_diags%npp + & - currentCohort%npp_acc * currentCohort%n * area_inv * day_per_sec + currentCohort%npp_acc * currentCohort%n * area_inv ! Passing gpp_acc_hold to HLM bc_out%gpp_site = bc_out%gpp_site + currentCohort%gpp_acc_hold * & diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index ec427ac1aa..2185927ffe 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -203,7 +203,7 @@ module EDTypesMod real(r8) :: state_litter ! Assessed instantaneously [kg/m2] real(r8) :: iflux_litter ! Integrated daily [kg/m2] - end type site_iflux_type + end type site_ifluxbal_type ! ------------------------------------------------------------------------- @@ -212,7 +212,7 @@ module EDTypesMod ! This is for all diagnostics that are uniform over all elements (C,N,P) - type(elem_diag_type), pointer :: elem_diag(:) + type(elem_diag_type), pointer :: elem(:) ! This variable is slated as to-do, but the fluxdiags type needs ! to be refactored first. Currently this type is allocated @@ -220,6 +220,8 @@ module EDTypesMod ! Previous day GPP [kgC/m2/year], partitioned by size x pft !real(r8),allocatable :: gpp_prev_scpf(:) + real(r8) :: npp ! kg m-2 day-1 + ! Nutrient Flux Diagnostics real(r8) :: resp_excess @@ -554,12 +556,12 @@ subroutine ZeroFluxDiags(this) integer :: el do el = 1,num_elements - this%elem_diag(el)%cwd_ag_input(:) = 0._r8 - this%elem_diag(el)%cwd_bg_input(:) = 0._r8 - this%elem_diag(el)%leaf_litter_input(:) = 0._r8 - this%elem_diag(el)%root_litter_input(:) = 0._r8 - this%elem_diag(el)%netflux_liveveg = 0._r8 - this%elem_diag(el)%netflux_litter = 0._r8 + this%elem(el)%cwd_ag_input(:) = 0._r8 + this%elem(el)%cwd_bg_input(:) = 0._r8 + this%elem(el)%leaf_litter_input(:) = 0._r8 + this%elem(el)%root_litter_input(:) = 0._r8 + this%elem(el)%netflux_liveveg = 0._r8 + this%elem(el)%netflux_litter = 0._r8 end do this%resp_excess = 0._r8 From b74171700d64a9c976b87c694fc1329a9539035f Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 13 Jun 2024 15:50:29 -0400 Subject: [PATCH 08/26] updates to integration tests --- biogeochem/EDPhysiologyMod.F90 | 71 +++++++++++++++--------------- biogeochem/FatesSoilBGCFluxMod.F90 | 11 +++-- main/ChecksBalancesMod.F90 | 54 +++++++++++++---------- main/EDMainMod.F90 | 7 +-- main/EDTypesMod.F90 | 16 ++++--- 5 files changed, 86 insertions(+), 73 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 1ff449a307..a30b7e9cb0 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -451,9 +451,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) ! ! !LOCAL VARIABLES: - type(site_massbal_type), pointer :: site_mass - type(litter_type), pointer :: litt ! Points to the litter object for - ! the different element types + integer :: el ! Litter element loop index integer :: nlev_eff_decomp ! Number of active layers over which ! fragmentation fluxes are transfered @@ -464,41 +462,42 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) do el = 1, num_elements - litt => currentPatch%litter(el) - - ! Calculate loss rate of viable seeds to litter - call SeedDecay(litt, currentPatch, bc_in) + associate( litt => currentPatch%litter(el), & + site_mass => currentSite%mass_balance(el), & + diag => currentSite%flux_diags%elem_diags(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 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) - - site_mass => currentSite%mass_balance(el) - diag => currentSite%flux_diags%elem_diags(el) - - ! 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/s] - diag%tot_seed_turnover = diag%tot_seed_turnover + & - (sum(litt%seed_decay) + sum(litt%seed_germ_decay))*currentPatch%area*area_inv*day_per_sec - + end associate end do diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index eb878639ce..bc938b9bc7 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -219,9 +219,6 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) ! P Uptake: Convert g/m2/day -> kg/plant/day ccohort%daily_p_gain = bc_in(s)%plant_p_uptake_flux(icomp,1)*kg_per_g*AREA/ccohort%n - ! Track flux diagnostics for history writing - sites(s)%flux_diags%p_uptake = sites(s)%flux_diags%p_uptake + bc_in(s)%plant_p_uptake_flux(icomp,1)/sec_per_day - ccohort => ccohort%shorter end do cpatch => cpatch%younger @@ -236,8 +233,12 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) do while (associated(ccohort)) pft = ccohort%pft + ! Track flux diagnostics for history writing and tracking [kg/plant/day] -> [kg/m2/day] + sites(s)%flux_diags%p_uptake = sites(s)%flux_diags%p_uptake + & + ccohort%daily_p_gain*ccohort%n*area_inv - + sites(s)%flux_diags%n_uptake = sites(s)%flux_diags%n_uptake + & + (ccohort%daily_nh4_uptake+ccohort%daily_no3_uptake)*ccohort%n*area_inv ccohort => ccohort%shorter end do @@ -582,6 +583,8 @@ subroutine EffluxIntoLitterPools(csite, cpatch, ccohort, bc_in ) end select + sites(s)%flux_diag + litt => cpatch%litter(el) do j = 1,csite%nlevsoil diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index a08b2f58c9..36ebd12827 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -252,6 +252,7 @@ subroutine CheckIntegratedMassPools(sites) integer :: el integer :: s real(r8) :: tot_veg_turnover + real(r8) :: tot_litter_input real(r8) :: net_uptake real(r8) :: biomass_stock real(r8) :: seed_stock @@ -273,7 +274,8 @@ subroutine CheckIntegratedMassPools(sites) associate(ibal => sites(s)%iflux_balance(el), & ediag => sites(s)%flux_diags%elem_diags(el), & - diag => sites(s)%flux_diags) + diag => sites(s)%flux_diags, & + site_mass => sites(s)%mass_balance(el)) ! Initialize the integrated flux balance diagnostics ! No need to initialize the instantaneous states, those are re-calculated @@ -281,12 +283,12 @@ subroutine CheckIntegratedMassPools(sites) ibal%state_liveveg = (biomass_stock + seed_stock)*area_inv ibal%state_litter = litter_stock * area_inv - ! Flux for live veg: NPP + + ! Flux for live veg: net uptake (either NPP or net nutrient uptake) + ! net spatial seed flux - ! veg turnover to litter - - ! veg loss to fire (SEEDS DONT BURN) - + ! veg loss to fire (SEEDS DONT BURN) - + ! veg loss from exported harvest - ! seed turnover - tot_litter_input = sum(ediag%leaf_litter_input(:)) + & sum(ediag%root_litter_input(:)) + & @@ -297,32 +299,36 @@ subroutine CheckIntegratedMassPools(sites) case(carbon12_element) net_uptake = diag%npp case(nitrogen_element) - net_uptake = diag%n_uptake + diag%sym_nfix - diag%n_efflux + net_uptake = site_mass%net_root_uptake*area_inv case(phosphorus_element) - net_uptake = diag%p_uptake - diag%p_efflux + net_uptake = site_mass%net_root_uptake*area_inv case default write(fates_log(),*) 'FATES: Invalid choice for cohort_fusion_conservation_method' call endrun(msg=errMsg(sourcefile, __LINE__)) end select - ! Fluxes are in [kg/m2/s] integrate to [kg/m2] + ! Fluxes are in [kg/m2/day] so they can be added, + ! the frequency is /day so no conversion necessary + ! to integrate to [kg/m2] ibal%iflux_liveveg = ibal%iflux_liveveg + & ( net_uptake & - tot_litter_input & - ediag%burned_liveveg & - + ediag%net_seed_transport & - - ediag%tot_seed_turnover) * sec_per_day + + site_mass%seed_in*area_inv & + - ediag%tot_seed_turnover) ! Flux for litter: veg turnover + ! seed turnover - ! fragmentation - ! burned - ibal%iflux_litter = ibal%iflux_litter + & - ediag%netflux_litter * sec_per_day + !ibal%iflux_litter = ibal%iflux_litter + & + ! ediag%netflux_litter * sec_per_day + + ediag%err_liveveg = ibal%state_liveveg - ibal%iflux_liveveg ! Perform the comparison between integrated flux and state - if(abs(ibal%state_liveveg - ibal%iflux_liveveg) > iflux_tol(el) ) then + if(abs(ediag%err_liveveg) > iflux_tol(el) ) then write(fates_log(),*) 'The fluxes in to an out of live vegetation are integrated' write(fates_log(),*) 'in time over the length of the FATES simulation.' write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' @@ -335,18 +341,18 @@ subroutine CheckIntegratedMassPools(sites) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(abs(ibal%state_litter - ibal%iflux_litter) > iflux_tol(el) ) then - write(fates_log(),*) 'The fluxes in to an out of litter are integrated' - write(fates_log(),*) 'in time over the length of the FATES simulation.' - write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' - write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' - write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' - write(fates_log(),*) 'state_litter: ',ibal%state_litter - write(fates_log(),*) 'iflux_litter: ',ibal%iflux_litter - write(fates_log(),*) 'state - iflux: ',ibal%state_litter - & - ibal%iflux_litter - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + !if(abs(ibal%state_litter - ibal%iflux_litter) > iflux_tol(el) ) then + ! write(fates_log(),*) 'The fluxes in to an out of litter are integrated' + ! write(fates_log(),*) 'in time over the length of the FATES simulation.' + ! write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' + ! write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' + ! write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' + ! write(fates_log(),*) 'state_litter: ',ibal%state_litter + ! write(fates_log(),*) 'iflux_litter: ',ibal%iflux_litter + ! write(fates_log(),*) 'state - iflux: ',ibal%state_litter - & + ! ibal%iflux_litter + ! call endrun(msg=errMsg(sourcefile, __LINE__)) + !end if end associate diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 625fee2d73..d84d190e92 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -513,9 +513,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%gpp_acc_hold = currentCohort%gpp_acc * real(hlm_days_per_year,r8) currentCohort%resp_acc_hold = currentCohort%resp_acc * real(hlm_days_per_year,r8) - ! Save NPP diagnostic for flux accounting [kg/m2/s] - currentSite%flux_diags%npp = currentSite%flux_diags%npp + & - currentCohort%npp_acc * currentCohort%n * area_inv * day_per_sec ! Passing gpp_acc_hold to HLM bc_out%gpp_site = bc_out%gpp_site + currentCohort%gpp_acc_hold * & @@ -623,6 +620,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentSite%mass_balance(element_pos(carbon12_element))%net_root_uptake = & currentSite%mass_balance(element_pos(carbon12_element))%net_root_uptake - & currentCohort%daily_c_efflux*currentCohort%n + + ! Save NPP diagnostic for flux accounting [kg/m2/day] + currentSite%flux_diags%npp = currentSite%flux_diags%npp + & + (currentCohort%npp_acc - currentCohort%resp_excess) * currentCohort%n * area_inv ! And simultaneously add the input fluxes to mass balance accounting site_cmass%gpp_acc = site_cmass%gpp_acc + & diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index ec427ac1aa..4d516cccaf 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -171,13 +171,13 @@ module EDTypesMod real(r8),allocatable :: leaf_litter_input(:) real(r8),allocatable :: root_litter_input(:) - real(r8) :: net_seed_transport real(r8) :: tot_seed_turnover ! decay of living seed bank to - ! fragmented litter [kg/m2/s] + ! fragmented litter [kg/m2/day] + real(r8) :: exported_harvest ! mass of harvested vegetation exported and not sent to litter [kg/m2/day] - - real(r8) :: netflux_liveveg ! Net change in live vegetation [kg/m2/s] - real(r8) :: netflux_litter ! Net change in litter [kg/m2/s] + real(r8) :: err_liveveg ! Error from comparing [state-integrated flux] + ! in live vegetation [kg/m2] + real(r8) :: err_litter ! Net change in litter [kg/m2/s] end type elem_diag_type @@ -186,7 +186,11 @@ module EDTypesMod type, public :: site_ifluxbal_type ! The combination of living vegetation and litter accounts - ! for all of the mass that is tracked by FATES + ! for all of the mass that is tracked by FATES. We use these + ! data structures to ensure that an instantaneous assessment + ! of the mass of live vegetation and litter, is the same + ! as the initial condition plus the integrated fluxes in and + ! out of those pools over the duration of the simulation. ! Mass in living vegetation, this includes: ! All organs on living plants, including non respiring tissues From 362d6b2c7589dbf1e44b01217e2dc2e7b1d1ec94 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 14 Jun 2024 15:12:56 -0400 Subject: [PATCH 09/26] integrated flux balance changes --- biogeochem/EDCohortDynamicsMod.F90 | 16 ++++---- biogeochem/EDLoggingMortalityMod.F90 | 20 +++++----- biogeochem/EDPatchDynamicsMod.F90 | 55 ++++++++++++++-------------- biogeochem/EDPhysiologyMod.F90 | 50 ++++++++++++------------- biogeochem/FatesSoilBGCFluxMod.F90 | 22 ----------- main/ChecksBalancesMod.F90 | 26 ++++++------- main/EDTypesMod.F90 | 13 +++++-- main/FatesHistoryInterfaceMod.F90 | 49 ++++++++++++++++--------- main/FatesRestartInterfaceMod.F90 | 16 ++++---- 9 files changed, 132 insertions(+), 135 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index e63e732759..c77b495731 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -603,7 +603,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) type(bc_in_type), intent(in) :: bc_in type(litter_type), pointer :: litt ! Litter object for each element - type(elem_diag_type),pointer :: flux_diags + type(elem_diag_type),pointer :: elflux_diags real(r8) :: leaf_m ! leaf mass [kg] real(r8) :: store_m ! storage mass [kg] @@ -647,7 +647,7 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) endif litt => cpatch%litter(el) - flux_diags => csite%flux_diags%elem(el) + elflux_diags => csite%flux_diags%elem(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) @@ -668,12 +668,12 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) enddo ! above ground - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + elflux_diags%cwd_ag_input(c) = elflux_diags%cwd_ag_input(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) + & + elflux_diags%cwd_bg_input(c) = elflux_diags%cwd_bg_input(c) + & (struct_m + sapw_m) * SF_val_CWD_frac_adj(c) * & (1.0_r8 - prt_params%allom_agb_frac(pft)) * nplant @@ -693,11 +693,11 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) end do - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & + elflux_diags%leaf_litter_input(pft) = & + elflux_diags%leaf_litter_input(pft) + & (leaf_m+repro_m) * nplant - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & + elflux_diags%root_litter_input(pft) = & + elflux_diags%root_litter_input(pft) + & (fnrt_m+store_m) * nplant diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 11de3c471c..92c252baa4 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -732,9 +732,9 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site !LOCAL VARIABLES: - type(fates_cohort_type), pointer :: currentCohort + type(fates_cohort_type), pointer :: currentCohort type(site_massbal_type), pointer :: site_mass - type(elem_diag_type), pointer :: flux_diags + type(elem_diag_type), pointer :: elflux_diags type(litter_type),pointer :: new_litt type(litter_type),pointer :: cur_litt @@ -795,7 +795,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site element_id = element_list(el) site_mass => currentSite%mass_balance(el) - flux_diags=> currentSite%flux_diags%elem(el) + elflux_diags=> currentSite%flux_diags%elem(el) cur_litt => currentPatch%litter(el) ! Litter pool of "current" patch new_litt => newPatch%litter(el) ! Litter pool of "new" patch @@ -895,10 +895,10 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ! Diagnostics on fluxes into the AG and BG CWD pools - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + elflux_diags%cwd_ag_input(c) = elflux_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) + & + elflux_diags%cwd_bg_input(c) = elflux_diags%cwd_bg_input(c) + & SF_val_CWD_frac_adj(c) * bg_wood ! Diagnostic specific to resource management code @@ -936,10 +936,10 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site end do - flux_diags%cwd_ag_input(ncwd) = flux_diags%cwd_ag_input(ncwd) + & + elflux_diags%cwd_ag_input(ncwd) = elflux_diags%cwd_ag_input(ncwd) + & SF_val_CWD_frac_adj(ncwd) * ag_wood - flux_diags%cwd_bg_input(ncwd) = flux_diags%cwd_bg_input(ncwd) + & + elflux_diags%cwd_bg_input(ncwd) = elflux_diags%cwd_bg_input(ncwd) + & SF_val_CWD_frac_adj(ncwd) * bg_wood if( element_id .eq. carbon12_element) then @@ -964,7 +964,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site retain_m2 end do - flux_diags%cwd_bg_input(ncwd) = flux_diags%cwd_bg_input(ncwd) + & + elflux_diags%cwd_bg_input(ncwd) = elflux_diags%cwd_bg_input(ncwd) + & bg_wood ! ---------------------------------------------------------------------------------------- @@ -1025,10 +1025,10 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site end do ! track as diagnostic fluxes - flux_diags%leaf_litter_input(pft) = flux_diags%leaf_litter_input(pft) + & + elflux_diags%leaf_litter_input(pft) = elflux_diags%leaf_litter_input(pft) + & leaf_litter - flux_diags%root_litter_input(pft) = flux_diags%root_litter_input(pft) + & + elflux_diags%root_litter_input(pft) = elflux_diags%root_litter_input(pft) + & root_litter ! Logging specific diagnostics diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 7d11d07554..3771898754 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -27,6 +27,7 @@ module EDPatchDynamicsMod use FatesCohortMod , only : fates_cohort_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type + use EDTypesMod , only : elem_diag_type use EDTypesMod , only : min_patch_area use EDTypesMod , only : min_patch_area_forced use EDParamsMod , only : nclmax @@ -1688,7 +1689,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & type(litter_type), pointer :: new_litt type(litter_type), pointer :: curr_litt type(site_massbal_type), pointer :: site_mass - type(site_fluxdiags_type), pointer :: flux_diags + type(elem_diag_type), pointer :: elflux_diags real(r8) :: donatable_mass ! non-burned litter mass provided by the donor [kg] ! some may or may not be retained by the donor @@ -1761,7 +1762,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & element_id = element_list(el) site_mass => currentSite%mass_balance(el) - flux_diags => currentSite%flux_diags + elflux_diags => currentSite%flux_diags%elem(el) curr_litt => currentPatch%litter(el) ! Litter pool of "current" patch new_litt => newPatch%litter(el) ! Litter pool of "new" patch @@ -1839,12 +1840,12 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & end do ! Track as diagnostic fluxes - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & + elflux_diags%leaf_litter_input(pft) = & + elflux_diags%leaf_litter_input(pft) + & num_dead_trees * (leaf_m+repro_m) * (1.0_r8-currentCohort%fraction_crown_burned) - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & + elflux_diags%root_litter_input(pft) = & + elflux_diags%root_litter_input(pft) + & (fnrt_m + store_m) * num_dead_trees ! coarse root biomass per tree @@ -1866,9 +1867,9 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & donatable_mass * retain_m2 ! track diagnostics - flux_diags%cwd_bg_input(c) = & - flux_diags%cwd_bg_input(c) + & - donatable_mass + elflux_diags%cwd_bg_input(c) = & + elflux_diags%cwd_bg_input(c) + & + donatable_mass enddo end do @@ -1887,7 +1888,7 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & 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 - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + donatable_mass + elflux_diags%cwd_ag_input(c) = elflux_diags%cwd_ag_input(c) + donatable_mass enddo @@ -1930,7 +1931,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & type(litter_type), pointer :: new_litt type(litter_type), pointer :: curr_litt type(site_massbal_type), pointer :: site_mass - type(site_fluxdiags_type), pointer :: flux_diags + type(elem_diag_type), pointer :: elflux_diags real(r8) :: remainder_area ! amount of area remaining in patch after donation real(r8) :: num_dead @@ -1977,7 +1978,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & element_id = element_list(el) site_mass => currentSite%mass_balance(el) - flux_diags => currentSite%flux_diags(el) + elflux_diags => currentSite%flux_diags%elem(el) curr_litt => currentPatch%litter(el) ! Litter pool of "current" patch new_litt => newPatch%litter(el) ! Litter pool of "new" patch @@ -2107,17 +2108,17 @@ 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_adj(c) * ag_wood + elflux_diags%cwd_ag_input(c) = & + elflux_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_adj(c) * bg_wood + elflux_diags%cwd_bg_input(c) = & + elflux_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) + & + elflux_diags%leaf_litter_input(pft) = elflux_diags%leaf_litter_input(pft) + & num_dead*(leaf_m + repro_m) - flux_diags%root_litter_input(pft) = flux_diags%root_litter_input(pft) + & + elflux_diags%root_litter_input(pft) = elflux_diags%root_litter_input(pft) + & num_dead * (fnrt_m + store_m*(1.0_r8-EDPftvarcon_inst%allom_frbstor_repro(pft))) @@ -2160,7 +2161,7 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & type(litter_type), pointer :: new_litt type(litter_type), pointer :: curr_litt type(site_massbal_type), pointer :: site_mass - type(site_fluxdiags_type), pointer :: flux_diags + type(elem_diag_type), pointer :: elflux_diags real(r8) :: donatable_mass ! non-burned litter mass provided by the donor [kg] ! some may or may not be retained by the donor @@ -2241,7 +2242,7 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & element_id = element_list(el) site_mass => currentSite%mass_balance(el) - flux_diags => currentSite%flux_diags(el) + elflux_diags => currentSite%flux_diags%elem(el) curr_litt => currentPatch%litter(el) ! Litter pool of "current" patch new_litt => newPatch%litter(el) ! Litter pool of "new" patch @@ -2315,12 +2316,12 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & end do ! Track as diagnostic fluxes - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & + elflux_diags%leaf_litter_input(pft) = & + elflux_diags%leaf_litter_input(pft) + & num_dead_trees * (leaf_m+repro_m) * (1.0_r8-burn_frac_landusetransition) - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & + elflux_diags%root_litter_input(pft) = & + elflux_diags%root_litter_input(pft) + & (fnrt_m + store_m) * num_dead_trees ! coarse root biomass per tree @@ -2338,8 +2339,8 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & donatable_mass * retain_m2 ! track diagnostics - flux_diags%cwd_bg_input(c) = & - flux_diags%cwd_bg_input(c) + & + elflux_diags%cwd_bg_input(c) = & + elflux_diags%cwd_bg_input(c) + & donatable_mass enddo end do @@ -2372,7 +2373,7 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & 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 - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + donatable_mass + elflux_diags%cwd_ag_input(c) = elflux_diags%cwd_ag_input(c) + donatable_mass enddo currentCohort => currentCohort%taller diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 791dd64370..f585bd7ba7 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -50,6 +50,7 @@ module EDPhysiologyMod use EDTypesMod , only : site_massbal_type use EDTypesMod , only : numlevsoil_max use EDTypesMod , only : numWaterMem + use EDTypesMod , only : elem_diag_type use FatesLitterMod , only : dl_sf use EDParamsMod , only : dinc_vai, dlower_vai use EDTypesMod , only : area_inv @@ -265,7 +266,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) type(fates_cohort_type), pointer :: ccohort ! Current cohort type(fates_cohort_type), pointer :: ndcohort ! New damage-class cohort type(litter_type), pointer :: litt ! Points to the litter object - type(site_fluxdiags_type), pointer :: flux_diags ! pointer to site level flux diagnostics object + type(elem_diag_type), pointer :: elflux_diags ! pointer to site level flux diagnostics object integer :: cd ! Damage class index integer :: el ! Element index integer :: dcmpy ! Decomposition pool index @@ -342,7 +343,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) do_element: do el = 1, num_elements litt => cpatch%litter(el) - flux_diags => csite%flux_diags(el) + elflux_diags => csite%flux_diags%elem(el) ! Reduce the mass of the newly damaged cohort ! Fine-roots are not damaged as of yet @@ -368,8 +369,8 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) ndcohort%n * dcmpy_frac / cpatch%area end do - flux_diags%leaf_litter_input(ipft) = & - flux_diags%leaf_litter_input(ipft) + & + elflux_diags%leaf_litter_input(ipft) = & + elflux_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) @@ -380,7 +381,7 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) SF_val_CWD_frac_adj(c) * ndcohort%n / & cpatch%area - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + elflux_diags%cwd_ag_input(c) = elflux_diags%cwd_ag_input(c) + & (struct_loss + sapw_loss) * & SF_val_CWD_frac_adj(c) * ndcohort%n end do @@ -464,7 +465,7 @@ subroutine PreDisturbanceLitterFluxes( currentSite, currentPatch, bc_in ) associate( litt => currentPatch%litter(el), & site_mass => currentSite%mass_balance(el), & - diag => currentSite%flux_diags%elem_diags(el)) + diag => currentSite%flux_diags%elem(el)) ! Calculate loss rate of viable seeds to litter call SeedDecay(litt, currentPatch, bc_in) @@ -2691,11 +2692,6 @@ subroutine recruitment(currentSite, currentPatch, bc_in) m_repro = 0._r8 end select - ! Diagnose the recruit flux [kg/m2] - currentSite%flux_diags%elem(el)%recruit_flux = & - currentSite%flux_diags%elem(el)%recruit_flux + & - (m_struct+m_leaf+m_fnrt+m_sapw+m_store+m_repro)*currentCohort%n*area_inv - select case(hlm_parteh_mode) case (prt_carbon_allom_hyp, prt_cnp_flex_allom_hyp) @@ -2786,7 +2782,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! ! !LOCAL VARIABLES: type(fates_cohort_type), pointer :: currentCohort - type(site_fluxdiags_type), pointer :: flux_diags + type(elem_diag_type), pointer :: elflux_diags type(site_massbal_type), pointer :: site_mass integer :: c real(r8) :: dead_n ! total understorey dead tree density @@ -2833,7 +2829,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) element_id = litt%element_id ! Object tracking flux diagnostics for each element - flux_diags => currentSite%flux_diags(element_pos(element_id)) + elflux_diags => currentSite%flux_diags%elem(element_pos(element_id)) ! Object tracking site level mass balance for each element site_mass => currentSite%mass_balance(element_pos(element_id)) @@ -2887,8 +2883,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! about double counting. ! --------------------------------------------------------------------------------- - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & + elflux_diags%leaf_litter_input(pft) = & + elflux_diags%leaf_litter_input(pft) + & leaf_m_turnover * currentCohort%n root_fines_tot = (fnrt_m_turnover + store_m_turnover ) * & @@ -2906,8 +2902,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) end do end do - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & + elflux_diags%root_litter_input(pft) = & + elflux_diags%root_litter_input(pft) + & (fnrt_m_turnover + store_m_turnover ) * currentCohort%n @@ -2923,7 +2919,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) 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) + & + elflux_diags%cwd_ag_input(c) = elflux_diags%cwd_ag_input(c) + & (struct_m_turnover + sapw_m_turnover) * SF_val_CWD_frac_adj(c) * & prt_params%allom_agb_frac(pft) * currentCohort%n @@ -2936,7 +2932,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) bg_cwd_tot * currentSite%rootfrac_scr(ilyr) end do - flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & + elflux_diags%cwd_bg_input(c) = elflux_diags%cwd_bg_input(c) + & bg_cwd_tot*currentPatch%area enddo @@ -2973,8 +2969,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) dead_n_natural = dead_n - dead_n_dlogging - dead_n_ilogging - flux_diags%leaf_litter_input(pft) = & - flux_diags%leaf_litter_input(pft) + & + elflux_diags%leaf_litter_input(pft) = & + elflux_diags%leaf_litter_input(pft) + & leaf_m * dead_n*currentPatch%area @@ -2998,8 +2994,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) end do end do - flux_diags%root_litter_input(pft) = & - flux_diags%root_litter_input(pft) + & + elflux_diags%root_litter_input(pft) = & + elflux_diags%root_litter_input(pft) + & root_fines_tot*currentPatch%area ! Track CWD inputs from dead plants @@ -3017,7 +3013,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) currentSite%rootfrac_scr(ilyr) * bg_cwd_tot end do - flux_diags%cwd_bg_input(c) = flux_diags%cwd_bg_input(c) + & + elflux_diags%cwd_bg_input(c) = elflux_diags%cwd_bg_input(c) + & bg_cwd_tot * currentPatch%area ! Send AGB component of boles from logging activities into the litter. @@ -3040,7 +3036,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) litt%ag_cwd_in(c) = litt%ag_cwd_in(c) + & trunk_wood * (1._r8-logging_export_frac) - flux_diags%cwd_ag_input(c) = flux_diags%cwd_ag_input(c) + & + elflux_diags%cwd_ag_input(c) = elflux_diags%cwd_ag_input(c) + & trunk_wood * (1._r8-logging_export_frac) * currentPatch%area ! Add AG wood to litter from indirect anthro sources @@ -3049,7 +3045,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) 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) + & + elflux_diags%cwd_ag_input(c) = elflux_diags%cwd_ag_input(c) + & SF_val_CWD_frac_adj(c) * (dead_n_natural+dead_n_ilogging) * & currentPatch%area * prt_params%allom_agb_frac(pft) @@ -3059,7 +3055,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) 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) + & + elflux_diags%cwd_ag_input(c) = elflux_diags%cwd_ag_input(c) + & SF_val_CWD_frac_adj(c) * dead_n * (struct_m + sapw_m) * & currentPatch%area * prt_params%allom_agb_frac(pft) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index bc938b9bc7..7605e0a336 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -226,26 +226,6 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) end if - ! Update diagnostic arrays - cpatch => sites(s)%oldest_patch - do while (associated(cpatch)) - ccohort => cpatch%tallest - do while (associated(ccohort)) - pft = ccohort%pft - - ! Track flux diagnostics for history writing and tracking [kg/plant/day] -> [kg/m2/day] - sites(s)%flux_diags%p_uptake = sites(s)%flux_diags%p_uptake + & - ccohort%daily_p_gain*ccohort%n*area_inv - - sites(s)%flux_diags%n_uptake = sites(s)%flux_diags%n_uptake + & - (ccohort%daily_nh4_uptake+ccohort%daily_no3_uptake)*ccohort%n*area_inv - - ccohort => ccohort%shorter - end do - cpatch => cpatch%younger - end do - - ! These can now be zero'd bc_in(s)%plant_nh4_uptake_flux(:,:) = 0._r8 bc_in(s)%plant_no3_uptake_flux(:,:) = 0._r8 @@ -583,8 +563,6 @@ subroutine EffluxIntoLitterPools(csite, cpatch, ccohort, bc_in ) end select - sites(s)%flux_diag - litt => cpatch%litter(el) do j = 1,csite%nlevsoil diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 1eca9ae2bb..4709f2d9e0 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -5,7 +5,7 @@ module ChecksBalancesMod use EDtypesMod, only : ed_site_type use FatesPatchMod, only : fates_patch_type use FatesCohortMod, only : fates_cohort_type - use EDTypesMod, only : AREA + use EDTypesMod, only : AREA, area_inv use EDTypesMod, only : site_massbal_type use PRTGenericMod, only : num_elements use PRTGenericMod, only : element_list @@ -330,18 +330,18 @@ subroutine CheckIntegratedMassPools(sites) ediag%err_liveveg = ibal%state_liveveg - ibal%iflux_liveveg ! Perform the comparison between integrated flux and state - if(abs(ediag%err_liveveg) > iflux_tol(el) ) then - write(fates_log(),*) 'The fluxes in to an out of live vegetation are integrated' - write(fates_log(),*) 'in time over the length of the FATES simulation.' - write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' - write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' - write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' - write(fates_log(),*) 'state_liveveg: ',ibal%state_liveveg - write(fates_log(),*) 'iflux_liveveg: ',ibal%iflux_liveveg - write(fates_log(),*) 'state - iflux: ',ibal%state_liveveg - & - ibal%iflux_liveveg - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + !if(abs(ediag%err_liveveg) > iflux_tol(el) ) then + ! write(fates_log(),*) 'The fluxes in to an out of live vegetation are integrated' + ! write(fates_log(),*) 'in time over the length of the FATES simulation.' + ! write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' + ! write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' + ! write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' + ! write(fates_log(),*) 'state_liveveg: ',ibal%state_liveveg + ! write(fates_log(),*) 'iflux_liveveg: ',ibal%iflux_liveveg + ! write(fates_log(),*) 'state - iflux: ',ibal%state_liveveg - & + ! ibal%iflux_liveveg + ! call endrun(msg=errMsg(sourcefile, __LINE__)) + !end if !if(abs(ibal%state_litter - ibal%iflux_litter) > iflux_tol(el) ) then ! write(fates_log(),*) 'The fluxes in to an out of litter are integrated' diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index a05aa1b783..8907bb5ffb 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -177,7 +177,9 @@ module EDTypesMod real(r8) :: err_liveveg ! Error from comparing [state-integrated flux] ! in live vegetation [kg/m2] - real(r8) :: err_litter ! Net change in litter [kg/m2/s] + + real(r8) :: err_litter ! Net change in litter [kg/m2] + real(r8) :: burned_liveveg ! Amount of mass burned from living plants [kg/m2/day] end type elem_diag_type @@ -564,10 +566,15 @@ subroutine ZeroFluxDiags(this) this%elem(el)%cwd_bg_input(:) = 0._r8 this%elem(el)%leaf_litter_input(:) = 0._r8 this%elem(el)%root_litter_input(:) = 0._r8 - this%elem(el)%netflux_liveveg = 0._r8 - this%elem(el)%netflux_litter = 0._r8 + this%elem(el)%burned_liveveg = 0._r8 + this%elem(el)%tot_seed_turnover = 0._r8 + this%elem(el)%exported_harvest = 0._r8 + this%elem(el)%err_liveveg = 0._r8 + this%elem(el)%err_litter = 0._r8 + this%elem(el)%burned_liveveg = 0._r8 end do + this%npp = 0._r8 this%resp_excess = 0._r8 this%nh4_uptake = 0._r8 this%no3_uptake = 0._r8 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 230d8512b8..71f0137157 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -23,6 +23,7 @@ module FatesHistoryInterfaceMod use PRTGenericMod , only : num_elements use PRTGenericMod , only : prt_cnp_flex_allom_hyp use EDTypesMod , only : site_fluxdiags_type + use EDTypesMod , only : elem_diag_type use EDtypesMod , only : ed_site_type use FatesCohortMod , only : fates_cohort_type use FatesPatchMod , only : fates_patch_type @@ -395,7 +396,7 @@ module FatesHistoryInterfaceMod integer :: ih_vis_rad_err_si integer :: ih_nir_rad_err_si integer :: ih_fire_c_to_atm_si - + integer :: ih_interr_liveveg_elem integer :: ih_cbal_err_fates_si integer :: ih_err_fates_elem @@ -2335,7 +2336,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) type(fates_cohort_type), pointer :: ccohort type(fates_patch_type), pointer :: cpatch - type(site_fluxdiags_type), pointer :: flux_diags_c ! Pointer to site level carbon fluxes + type(elem_diag_type), pointer :: elflux_diags_c ! Pointer to site level carbon fluxes type(litter_type), pointer :: litt ! Generic pointer to any litter pool integer :: s ! site counter @@ -2465,6 +2466,8 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_cbal_err_fates_si(io_si) = & sites(s)%mass_balance(element_pos(carbon12_element))%err_fates / sec_per_day + + ! Total carbon lost to atmosphere from burning (kgC/site/day -> kgC/m2/s) hio_fire_c_to_atm_si(io_si) = & sites(s)%mass_balance(element_pos(carbon12_element))%burn_flux_to_atm * & @@ -2582,12 +2585,12 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) sites(s)%term_crownarea_ustory * days_per_year + & sites(s)%imort_crownarea - flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) + elflux_diags_c => sites(s)%flux_diags%elem(element_pos(carbon12_element)) - hio_litter_in_si(io_si) = (sum(flux_diags_c%cwd_ag_input(:)) + & - sum(flux_diags_c%cwd_bg_input(:)) + & - sum(flux_diags_c%leaf_litter_input(:)) + & - sum(flux_diags_c%root_litter_input(:))) * & + hio_litter_in_si(io_si) = (sum(elflux_diags_c%cwd_ag_input(:)) + & + sum(elflux_diags_c%cwd_bg_input(:)) + & + sum(elflux_diags_c%leaf_litter_input(:)) + & + sum(elflux_diags_c%root_litter_input(:))) * & AREA_INV * days_per_sec ! Loop through patches to sum up diagonistics @@ -3061,8 +3064,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) integer :: i_dist, j_dist - type(site_fluxdiags_type), pointer :: flux_diags - type(site_fluxdiags_type), pointer :: flux_diags_c + type(elem_diag_type), pointer :: elflux_diags + type(elem_diag_type), pointer :: elflux_diags_c real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) @@ -3280,7 +3283,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_nplant_canopy_si_scag => this%hvars(ih_nplant_canopy_si_scag)%r82d, & hio_nplant_understory_si_scag => this%hvars(ih_nplant_understory_si_scag)%r82d, & hio_disturbance_rate_si_lulu => this%hvars(ih_disturbance_rate_si_lulu)%r82d, & - hio_cstarvmortality_continuous_carbonflux_si_pft => this%hvars(ih_cstarvmortality_continuous_carbonflux_si_pft)%r82d) + hio_cstarvmortality_continuous_carbonflux_si_pft => this%hvars(ih_cstarvmortality_continuous_carbonflux_si_pft)%r82d, & + hio_interr_liveveg_elem => this%hvars(ih_interr_liveveg_elem)%r82d) model_day_int = nint(hlm_model_day) @@ -3323,6 +3327,9 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! Total model error [kg/day -> kg/s] (all elements) hio_err_fates_elem(io_si,el) = sites(s)%mass_balance(el)%err_fates / sec_per_day + hio_interr_liveveg_elem(io_si,el) = sites(s)%flux_diags%elem(el)%err_liveveg + + ! Total element lost to atmosphere from burning (kg/site/day -> kg/m2/s) hio_burn_flux_elem(io_si,el) = & sites(s)%mass_balance(el)%burn_flux_to_atm * ha_per_m2 * & @@ -4547,7 +4554,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! Some carbon only litter diagnostics (legacy) ! ------------------------------------------------------------------------------ - flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) + elflux_diags_c => sites(s)%flux_diags%elem(element_pos(carbon12_element)) ! ------------------------------------------------------------------------------ ! Diagnostics discretized by element type @@ -4555,12 +4562,12 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) do el = 1, num_elements - flux_diags => sites(s)%flux_diags(el) + elflux_diags => sites(s)%flux_diags%elem(el) ! Sum up all input litter fluxes (above below, fines, cwd) [kg/ha/day] - hio_litter_in_elem(io_si, el) = (sum(flux_diags%cwd_ag_input(:)) + & - sum(flux_diags%cwd_bg_input(:)) + sum(flux_diags%leaf_litter_input(:)) + & - sum(flux_diags%root_litter_input(:))) / m2_per_ha / sec_per_day + hio_litter_in_elem(io_si, el) = (sum(elflux_diags%cwd_ag_input(:)) + & + sum(elflux_diags%cwd_bg_input(:)) + sum(elflux_diags%leaf_litter_input(:)) + & + sum(elflux_diags%root_litter_input(:))) / m2_per_ha / sec_per_day ! Plant multi-element states and fluxes @@ -4808,10 +4815,10 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) do i_cwd = 1, ncwd hio_cwd_ag_in_si_cwdsc(io_si, i_cwd) = hio_cwd_ag_in_si_cwdsc(io_si, i_cwd) + & - flux_diags_c%cwd_ag_input(i_cwd) / days_per_year / sec_per_day + elflux_diags_c%cwd_ag_input(i_cwd) / days_per_year / sec_per_day hio_cwd_bg_in_si_cwdsc(io_si, i_cwd) = hio_cwd_bg_in_si_cwdsc(io_si, i_cwd) + & - flux_diags_c%cwd_bg_input(i_cwd) / days_per_year / sec_per_day + elflux_diags_c%cwd_bg_input(i_cwd) / days_per_year / sec_per_day end do @@ -6670,6 +6677,8 @@ subroutine define_history_vars(this, initialize_variables) upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_cbal_err_fates_si) + + call this%set_history_var(vname='FATES_LEAF_ALLOC', units='kg m-2 s-1', & long='allocation to leaves in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -8376,6 +8385,12 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & index = ih_err_fates_elem) + call this%set_history_var(vname='FATES_INTERR_LIVEVEG_EL',units='kg m-2', & + long='Bias error between integrated flux and (minus) state in live vegetation ', & + use_default='active', avgflag='A', vtype=site_elem_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_interr_liveveg_elem) + call this%set_history_var(vname='FATES_LITTER_AG_FINE_EL', units='kg m-2', & long='mass of aboveground litter in fines (leaves, nonviable seed) by element', & use_default='active', avgflag='A', vtype=site_elem_r8, & diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index ffef39eb6f..f139706734 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2254,14 +2254,14 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_scpf = io_idx_co_1st do i_cwd=1,ncwd - this%rvars(ir_cwdagin_flxdg+el-1)%r81d(io_idx_si_cwd) = sites(s)%flux_diags(el)%cwd_ag_input(i_cwd) - this%rvars(ir_cwdbgin_flxdg+el-1)%r81d(io_idx_si_cwd) = sites(s)%flux_diags(el)%cwd_bg_input(i_cwd) + this%rvars(ir_cwdagin_flxdg+el-1)%r81d(io_idx_si_cwd) = sites(s)%flux_diags%elem(el)%cwd_ag_input(i_cwd) + this%rvars(ir_cwdbgin_flxdg+el-1)%r81d(io_idx_si_cwd) = sites(s)%flux_diags%elem(el)%cwd_bg_input(i_cwd) io_idx_si_cwd = io_idx_si_cwd + 1 end do do i_pft=1,numpft - this%rvars(ir_leaflittin_flxdg+el-1)%r81d(io_idx_si_pft) = sites(s)%flux_diags(el)%leaf_litter_input(i_pft) - this%rvars(ir_rootlittin_flxdg+el-1)%r81d(io_idx_si_pft) = sites(s)%flux_diags(el)%root_litter_input(i_pft) + this%rvars(ir_leaflittin_flxdg+el-1)%r81d(io_idx_si_pft) = sites(s)%flux_diags%elem(el)%leaf_litter_input(i_pft) + this%rvars(ir_rootlittin_flxdg+el-1)%r81d(io_idx_si_pft) = sites(s)%flux_diags%elem(el)%root_litter_input(i_pft) io_idx_si_pft = io_idx_si_pft + 1 end do @@ -3220,14 +3220,14 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_scpf = io_idx_co_1st do i_cwd=1,ncwd - sites(s)%flux_diags(el)%cwd_ag_input(i_cwd) = this%rvars(ir_cwdagin_flxdg+el-1)%r81d(io_idx_si_cwd) - sites(s)%flux_diags(el)%cwd_bg_input(i_cwd) = this%rvars(ir_cwdbgin_flxdg+el-1)%r81d(io_idx_si_cwd) + sites(s)%flux_diags%elem(el)%cwd_ag_input(i_cwd) = this%rvars(ir_cwdagin_flxdg+el-1)%r81d(io_idx_si_cwd) + sites(s)%flux_diags%elem(el)%cwd_bg_input(i_cwd) = this%rvars(ir_cwdbgin_flxdg+el-1)%r81d(io_idx_si_cwd) io_idx_si_cwd = io_idx_si_cwd + 1 end do do i_pft=1,numpft - sites(s)%flux_diags(el)%leaf_litter_input(i_pft) = this%rvars(ir_leaflittin_flxdg+el-1)%r81d(io_idx_si_pft) - sites(s)%flux_diags(el)%root_litter_input(i_pft) = this%rvars(ir_rootlittin_flxdg+el-1)%r81d(io_idx_si_pft) + sites(s)%flux_diags%elem(el)%leaf_litter_input(i_pft) = this%rvars(ir_leaflittin_flxdg+el-1)%r81d(io_idx_si_pft) + sites(s)%flux_diags%elem(el)%root_litter_input(i_pft) = this%rvars(ir_rootlittin_flxdg+el-1)%r81d(io_idx_si_pft) io_idx_si_pft = io_idx_si_pft + 1 end do From df281a062d2c8f1e4b184773f70dfbfa0bbacfe5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 17 Jun 2024 10:26:44 -0400 Subject: [PATCH 10/26] flux diagnostics --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- main/ChecksBalancesMod.F90 | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3771898754..db54482d35 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1010,7 +1010,7 @@ subroutine spawn_patches( currentSite, bc_in) ! 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 + leaf_burn_frac * leaf_m * nc%n * area_inv end do diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 4709f2d9e0..8a63158738 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -292,10 +292,10 @@ subroutine CheckIntegratedMassPools(sites) ! veg loss from exported harvest - ! seed turnover - tot_litter_input = sum(ediag%leaf_litter_input(:)) + & - sum(ediag%root_litter_input(:)) + & - sum(ediag%cwd_ag_input(:)) + & - sum(ediag%cwd_bg_input(:)) + tot_litter_input = (sum(ediag%leaf_litter_input(:)) + & + sum(ediag%root_litter_input(:)) + & + sum(ediag%cwd_ag_input(:)) + & + sum(ediag%cwd_bg_input(:)))*area_inv select case(element_list(el)) case(carbon12_element) @@ -327,7 +327,10 @@ subroutine CheckIntegratedMassPools(sites) !ibal%iflux_litter = ibal%iflux_litter + & ! ediag%netflux_litter * sec_per_day - ediag%err_liveveg = ibal%state_liveveg - ibal%iflux_liveveg + ediag%err_liveveg = ibal%iflux_liveveg - ibal%state_liveveg + + print*, ediag%err_liveveg, diag%npp, site_mass%net_root_uptake*area_inv, tot_litter_input, & + ediag%burned_liveveg, site_mass%seed_in*area_inv, ediag%tot_seed_turnover ! Perform the comparison between integrated flux and state !if(abs(ediag%err_liveveg) > iflux_tol(el) ) then From 3eccbd122ea828bcfea32d97f6e6a757497b93d5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 17 Jun 2024 11:04:22 -0400 Subject: [PATCH 11/26] updating integrated fluxes --- main/EDMainMod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index ef884bbb22..cbbf209c5d 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -621,8 +621,9 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%daily_c_efflux*currentCohort%n ! Save NPP diagnostic for flux accounting [kg/m2/day] + currentSite%flux_diags%npp = currentSite%flux_diags%npp + & - (currentCohort%npp_acc - currentCohort%resp_excess) * currentCohort%n * area_inv + (currentCohort%npp_acc_hold/hlm_days_per_year - currentCohort%resp_excess) * currentCohort%n * area_inv ! And simultaneously add the input fluxes to mass balance accounting site_cmass%gpp_acc = site_cmass%gpp_acc + & From 170a0e91ca6b7b8570799366c0c63f69d07bef63 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 17 Jun 2024 13:49:23 -0400 Subject: [PATCH 12/26] moved integrated flux calculation to before history write call --- main/FatesHistoryInterfaceMod.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 71f0137157..2e213e94a1 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2309,6 +2309,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) if (hlm_use_ed_st3.eq.itrue) return + call CheckIntegratedMassPools(sites) + if(hlm_hist_level_dynam>0) then call update_history_dyn1(this,nc,nsites,sites,bc_in) if(hlm_hist_level_dynam>1) then @@ -2316,7 +2318,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end if end if - call CheckIntegratedMassPools(sites) + return end subroutine update_history_dyn From 319c1fb924e13cf01f075e4e0161e2a000fbe82a Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 17 Jun 2024 11:41:52 -0700 Subject: [PATCH 13/26] fix units on seed production in history --- main/FatesHistoryInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 6c34f48292..a83931f875 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -4037,7 +4037,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_bdead_md_canopy_si_scls(io_si,scls) = hio_bdead_md_canopy_si_scls(io_si,scls) + & struct_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day hio_seed_prod_canopy_si_scls(io_si,scls) = hio_seed_prod_canopy_si_scls(io_si,scls) + & - ccohort%seed_prod * ccohort%n / m2_per_ha / days_per_year / sec_per_day + ccohort%seed_prod * ccohort%n / m2_per_ha / sec_per_day hio_npp_leaf_canopy_si_scls(io_si,scls) = hio_npp_leaf_canopy_si_scls(io_si,scls) + & leaf_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day @@ -4174,7 +4174,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_bdead_md_understory_si_scls(io_si,scls) = hio_bdead_md_understory_si_scls(io_si,scls) + & struct_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day hio_seed_prod_understory_si_scls(io_si,scls) = hio_seed_prod_understory_si_scls(io_si,scls) + & - ccohort%seed_prod * ccohort%n / m2_per_ha / days_per_year / sec_per_day + ccohort%seed_prod * ccohort%n / m2_per_ha / sec_per_day hio_npp_leaf_understory_si_scls(io_si,scls) = hio_npp_leaf_understory_si_scls(io_si,scls) + & leaf_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day From bbe260745f87e5b94896dfa8f72b224585b51014 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 18 Jun 2024 10:29:58 -0400 Subject: [PATCH 14/26] integrated flux work --- main/ChecksBalancesMod.F90 | 26 +++++++++++++------------- main/EDMainMod.F90 | 6 ++++++ main/FatesHistoryInterfaceMod.F90 | 3 --- main/FatesRestartInterfaceMod.F90 | 24 ++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 8a63158738..2d858d1942 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -245,12 +245,12 @@ end subroutine CheckLitterPools ! ================================================================== - subroutine CheckIntegratedMassPools(sites) + subroutine CheckIntegratedMassPools(site) - type(ed_site_type), intent(inout), target :: sites(:) + type(ed_site_type), intent(inout) :: site - integer :: nsites + !integer :: nsites integer :: el integer :: s real(r8) :: tot_veg_turnover @@ -259,25 +259,26 @@ subroutine CheckIntegratedMassPools(sites) real(r8) :: biomass_stock real(r8) :: seed_stock real(r8) :: litter_stock + real(r8) :: total_stock logical,parameter :: check_iflux_bal = .true. if(check_iflux_bal) then - nsites = ubound(sites,dim=1) + !nsites = ubound(sites,dim=1) - do s = 1,nsites + !do s = 1,nsites ! For carbon balance checks, we need to initialize the ! total carbon stock do el=1,num_elements - call SiteMassStock(sites(s),el,sites(s)%mass_balance(el)%old_stock, & + call SiteMassStock(site,el,total_stock, & biomass_stock,litter_stock,seed_stock) - associate(ibal => sites(s)%iflux_balance(el), & - ediag => sites(s)%flux_diags%elem(el), & - diag => sites(s)%flux_diags, & - site_mass => sites(s)%mass_balance(el)) + associate(ibal => site%iflux_balance(el), & + ediag => site%flux_diags%elem(el), & + diag => site%flux_diags, & + site_mass => site%mass_balance(el)) ! Initialize the integrated flux balance diagnostics ! No need to initialize the instantaneous states, those are re-calculated @@ -329,8 +330,7 @@ subroutine CheckIntegratedMassPools(sites) ediag%err_liveveg = ibal%iflux_liveveg - ibal%state_liveveg - print*, ediag%err_liveveg, diag%npp, site_mass%net_root_uptake*area_inv, tot_litter_input, & - ediag%burned_liveveg, site_mass%seed_in*area_inv, ediag%tot_seed_turnover + !print*, ediag%err_liveveg, ediag%err_liveveg/ibal%state_liveveg, ibal%state_liveveg, net_uptake, tot_litter_input ! Perform the comparison between integrated flux and state !if(abs(ediag%err_liveveg) > iflux_tol(el) ) then @@ -362,7 +362,7 @@ subroutine CheckIntegratedMassPools(sites) end associate end do - end do + !end do end if return diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index cbbf209c5d..1283492a63 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -91,6 +91,7 @@ module EDMainMod use EDPatchDynamicsMod , only : get_frac_site_primary use FatesGlobals , only : endrun => fates_endrun use ChecksBalancesMod , only : SiteMassStock + use ChecksBalancesMod , only : CheckIntegratedMassPools use EDMortalityFunctionsMod , only : Mortality_Derivative use EDTypesMod , only : AREA_INV use PRTGenericMod, only : carbon12_element @@ -307,7 +308,12 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) call terminate_patches(currentSite) end if + ! Final instantaneous mass balance check call TotalBalanceCheck(currentSite,5) + + ! Check to see if the time integrated fluxes match the state + call CheckIntegratedMassPools(currentSite) + end subroutine ed_ecosystem_dynamics diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 2e213e94a1..6d7a950b3f 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -14,7 +14,6 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : i_term_mort_type_cstarv use FatesConstantsMod , only : i_term_mort_type_canlev use FatesConstantsMod , only : i_term_mort_type_numdens - use ChecksBalancesMod , only : CheckIntegratedMassPools use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun use EDParamsMod , only : nclmax, maxpft @@ -2309,8 +2308,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) if (hlm_use_ed_st3.eq.itrue) return - call CheckIntegratedMassPools(sites) - if(hlm_hist_level_dynam>0) then call update_history_dyn1(this,nc,nsites,sites,bc_in) if(hlm_hist_level_dynam>1) then diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index f139706734..8fcf0414a3 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -268,6 +268,8 @@ module FatesRestartInterfaceMod integer :: ir_oldstock_mbal integer :: ir_errfates_mbal integer :: ir_woodprod_mbal + integer :: ir_liveveg_intflux_el + integer :: ir_liveveg_err_el integer :: ir_prt_base ! Base index for all PRT variables ! site-level input seed from dispersal @@ -1036,6 +1038,7 @@ subroutine define_restart_vars(this, initialize_variables) ! Patch Level Litter Pools are potentially multi-element if(hlm_use_sp.eq.ifalse)then + call this%RegisterCohortVector(symbol_base='fates_ag_cwd', vtype=cohort_r8, & long_name_base='above ground CWD', & units='kg/m2', veclength=num_elements, flushval = flushzero, & @@ -1132,6 +1135,20 @@ subroutine define_restart_vars(this, initialize_variables) units='kg/ha', veclength=num_elements, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_errfates_mbal) + + ! Time integrated mass balance accounting [kg/m2] + call this%RegisterCohortVector(symbol_base='fates_liveveg_intflux', vtype=site_r8, & + long_name_base='total mass of live vegetation of each chemical species, integrated from fluxes', & + units='kg/m2', veclength=num_elements, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_liveveg_intflux_el) + + + call this%RegisterCohortVector(symbol_base='fates_liveveg_err', vtype=site_r8, & + long_name_base='total mass error of live vegetation of each chemical species, from integrated fluxes', & + units='kg/m2', veclength=num_elements, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_liveveg_err_el) + + end if call this%RegisterCohortVector(symbol_base='fates_woodproduct', vtype=site_r8, & @@ -2269,6 +2286,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) this%rvars(ir_errfates_mbal+el-1)%r81d(io_idx_si) = sites(s)%mass_balance(el)%err_fates this%rvars(ir_woodprod_mbal+el-1)%r81d(io_idx_si) = sites(s)%mass_balance(el)%wood_product + this%rvars(ir_liveveg_intflux_el+el-1)%r81d(io_idx_si) = sites(s)%iflux_balance(el)%iflux_liveveg + this%rvars(ir_liveveg_err_el+el-1)%r81d(io_idx_si) = sites(s)%flux_diags%elem(el)%err_liveveg + end do end if @@ -3234,6 +3254,10 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%mass_balance(el)%old_stock = this%rvars(ir_oldstock_mbal+el-1)%r81d(io_idx_si) sites(s)%mass_balance(el)%err_fates = this%rvars(ir_errfates_mbal+el-1)%r81d(io_idx_si) sites(s)%mass_balance(el)%wood_product = this%rvars(ir_woodprod_mbal+el-1)%r81d(io_idx_si) + + sites(s)%iflux_balance(el)%iflux_liveveg = this%rvars(ir_liveveg_intflux_el+el-1)%r81d(io_idx_si) + sites(s)%flux_diags%elem(el)%err_liveveg = this%rvars(ir_liveveg_err_el+el-1)%r81d(io_idx_si) + end do end if From 1113228e044de456f6ae422c1922369a98b75f3f Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 19 Jun 2024 15:15:47 -0400 Subject: [PATCH 15/26] bug fix to litter flux tracking --- biogeochem/EDPhysiologyMod.F90 | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index f585bd7ba7..6f6eb626ac 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1751,6 +1751,7 @@ subroutine phenology_leafonoff(currentSite) call PRTDeciduousTurnover(currentCohort%prt,ipft,sapw_organ , eff_sapw_drop_fraction ) call PRTDeciduousTurnover(currentCohort%prt,ipft,struct_organ, eff_struct_drop_fraction) end if + end if shed_block if(debug) call currentCohort%prt%CheckMassConservation(ipft,1) @@ -2834,6 +2835,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! Object tracking site level mass balance for each element site_mass => currentSite%mass_balance(element_pos(element_id)) + ! Transfer litter from turnover of living plants + currentCohort => currentPatch%shortest do while(associated(currentCohort)) @@ -2844,7 +2847,9 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) store_m_turnover = currentCohort%prt%GetTurnover(store_organ,element_id) fnrt_m_turnover = currentCohort%prt%GetTurnover(fnrt_organ,element_id) repro_m_turnover = currentCohort%prt%GetTurnover(repro_organ,element_id) + + store_m = currentCohort%prt%GetState(store_organ,element_id) fnrt_m = currentCohort%prt%GetState(fnrt_organ,element_id) repro_m = currentCohort%prt%GetState(repro_organ,element_id) @@ -2885,7 +2890,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) elflux_diags%leaf_litter_input(pft) = & elflux_diags%leaf_litter_input(pft) + & - leaf_m_turnover * currentCohort%n + (leaf_m_turnover+repro_m_turnover) * currentCohort%n root_fines_tot = (fnrt_m_turnover + store_m_turnover ) * & plant_dens @@ -2968,12 +2973,6 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) dead_n_natural = dead_n - dead_n_dlogging - dead_n_ilogging - - elflux_diags%leaf_litter_input(pft) = & - elflux_diags%leaf_litter_input(pft) + & - leaf_m * dead_n*currentPatch%area - - ! %n has not been updated due to mortality yet, thus ! the litter flux has already been counted since it captured ! the losses of live trees and those flagged for death @@ -2994,6 +2993,10 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) end do end do + elflux_diags%leaf_litter_input(pft) = & + elflux_diags%leaf_litter_input(pft) + & + (leaf_m+repro_m) * dead_n*currentPatch%area + elflux_diags%root_litter_input(pft) = & elflux_diags%root_litter_input(pft) + & root_fines_tot*currentPatch%area @@ -3046,7 +3049,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) prt_params%allom_agb_frac(pft) elflux_diags%cwd_ag_input(c) = elflux_diags%cwd_ag_input(c) + & - SF_val_CWD_frac_adj(c) * (dead_n_natural+dead_n_ilogging) * & + (struct_m + sapw_m) * SF_val_CWD_frac_adj(c) * (dead_n_natural+dead_n_ilogging) * & currentPatch%area * prt_params%allom_agb_frac(pft) else From e0d46ea064b2f44f319e3999d566a71a651428f7 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 1 Jul 2024 11:04:56 -0400 Subject: [PATCH 16/26] Subtle syntax updates for flux diagnostics --- main/ChecksBalancesMod.F90 | 2 +- main/EDMainMod.F90 | 1 - parameter_files/patch_default_bciopt224.xml | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 2d858d1942..dfd8f3b927 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -330,7 +330,7 @@ subroutine CheckIntegratedMassPools(site) ediag%err_liveveg = ibal%iflux_liveveg - ibal%state_liveveg - !print*, ediag%err_liveveg, ediag%err_liveveg/ibal%state_liveveg, ibal%state_liveveg, net_uptake, tot_litter_input + !print*, ediag%err_liveveg!, ediag%err_liveveg/ibal%state_liveveg, ibal%state_liveveg, net_uptake, tot_litter_input ! Perform the comparison between integrated flux and state !if(abs(ediag%err_liveveg) > iflux_tol(el) ) then diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 1283492a63..46d4d93a4f 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -102,7 +102,6 @@ module EDMainMod use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ use PRTLossFluxesMod, only : PRTMaintTurnover - use PRTLossFluxesMod, only : PRTReproRelease use EDPftvarcon, only : EDPftvarcon_inst use FatesHistoryInterfaceMod, only : fates_hist diff --git a/parameter_files/patch_default_bciopt224.xml b/parameter_files/patch_default_bciopt224.xml index b1ec419f64..73ab594ff8 100644 --- a/parameter_files/patch_default_bciopt224.xml +++ b/parameter_files/patch_default_bciopt224.xml @@ -2,7 +2,7 @@ This parameter dataset was created by Ryan Knox rgknox@lbl.gov. Please contact if using in published work. The calibration uses the following datasets: [1] Ely et al. 2019. Leaf mass area, Panama. NGEE-Tropics data collection.http://dx.doi.org/10.15486/ngt/1411973 and [2] Condit et al. 2019. Complete data from the Barro Colorado 50-ha plot. https://doi.org/10.15146/5xcp-0d46. [3] Koven et al. 2019. Benchmarking and parameter sensitivity of physiological and vegetation dynamics using the functionally assembled terrestrial ecosystem simulator. Biogeosciences. The ECA nutrient aquisition parmeters are unconstrained, the file output naming convention vmn6phi is shorthand for vmax for nitrogen uptake is order e-6 and for phosphorus is excessively high. These parameters were calibrated with the special fates modification in main/EDTypesMod.F90: nclmax = 3 fates_params_default.cdl - fates_params_opt224_092023_api26.cdl + fates_params_opt224_0424_api34.cdl 1 From 373428140a1e0668ebb13971cef9dc8d9be45c31 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 1 Jul 2024 13:26:34 -0400 Subject: [PATCH 17/26] Added integrated litter fluxes to diagnostics, and added harvest term to live-veg diagnostic --- biogeochem/EDLoggingMortalityMod.F90 | 5 + biogeochem/EDPatchDynamicsMod.F90 | 4 + main/ChecksBalancesMod.F90 | 205 ++++++++++++++------------- main/EDTypesMod.F90 | 7 +- main/FatesHistoryInterfaceMod.F90 | 13 +- main/FatesRestartInterfaceMod.F90 | 18 ++- 6 files changed, 144 insertions(+), 108 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 92c252baa4..711c89f3ca 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -29,6 +29,7 @@ module EDLoggingMortalityMod use FatesConstantsMod , only : dtype_ilog use FatesConstantsMod , only : dtype_ifall use FatesConstantsMod , only : dtype_ifire + use EDTypesMod , only : area_inv use EDPftvarcon , only : EDPftvarcon_inst use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params @@ -1053,6 +1054,10 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site currentCohort => currentCohort%taller end do + ! Amount of trunk mass exported off site [kg/m2] + elflux_diags%exported_harvest = elflux_diags%exported_harvest + & + trunk_product_site * area_inv + ! Update the amount of carbon exported from the site through logging ! operations. Currently we assume only above-ground portion ! of the tree bole that experienced "direct" logging is exported diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index db54482d35..982388e3cd 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2368,6 +2368,10 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & trunk_product_site = trunk_product_site + & woodproduct_mass + ! Amount of trunk mass exported off site [kg/m2] + elflux_diags%exported_harvest = elflux_diags%exported_harvest + & + woodproduct_mass * area_inv + site_mass%wood_product = site_mass%wood_product + & woodproduct_mass endif diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index dfd8f3b927..981073b40e 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -247,7 +247,7 @@ end subroutine CheckLitterPools subroutine CheckIntegratedMassPools(site) - + type(ed_site_type), intent(inout) :: site !integer :: nsites @@ -260,114 +260,117 @@ subroutine CheckIntegratedMassPools(site) real(r8) :: seed_stock real(r8) :: litter_stock real(r8) :: total_stock - + logical,parameter :: check_iflux_bal = .true. if(check_iflux_bal) then - - !nsites = ubound(sites,dim=1) - !do s = 1,nsites - - ! For carbon balance checks, we need to initialize the - ! total carbon stock - do el=1,num_elements - call SiteMassStock(site,el,total_stock, & - biomass_stock,litter_stock,seed_stock) - - associate(ibal => site%iflux_balance(el), & - ediag => site%flux_diags%elem(el), & - diag => site%flux_diags, & - site_mass => site%mass_balance(el)) - - ! Initialize the integrated flux balance diagnostics - ! No need to initialize the instantaneous states, those are re-calculated - - ibal%state_liveveg = (biomass_stock + seed_stock)*area_inv - ibal%state_litter = litter_stock * area_inv - - ! Flux for live veg: net uptake (either NPP or net nutrient uptake) + - ! net spatial seed flux - - ! veg turnover to litter - - ! veg loss to fire (SEEDS DONT BURN) - - ! veg loss from exported harvest - - ! seed turnover - - tot_litter_input = (sum(ediag%leaf_litter_input(:)) + & - sum(ediag%root_litter_input(:)) + & - sum(ediag%cwd_ag_input(:)) + & - sum(ediag%cwd_bg_input(:)))*area_inv - - select case(element_list(el)) - case(carbon12_element) - net_uptake = diag%npp + site_mass%net_root_uptake*area_inv - case(nitrogen_element) - net_uptake = site_mass%net_root_uptake*area_inv - case(phosphorus_element) - net_uptake = site_mass%net_root_uptake*area_inv - case default - write(fates_log(),*) 'FATES: Invalid choice for cohort_fusion_conservation_method' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - ! Fluxes are in [kg/m2/day] so they can be added, - ! the frequency is /day so no conversion necessary - ! to integrate to [kg/m2] - ibal%iflux_liveveg = ibal%iflux_liveveg + & - ( net_uptake & - - tot_litter_input & - - ediag%burned_liveveg & - + site_mass%seed_in*area_inv & - - ediag%tot_seed_turnover) - - ! Flux for litter: veg turnover + - ! seed turnover - - ! fragmentation - - ! burned - - !ibal%iflux_litter = ibal%iflux_litter + & - ! ediag%netflux_litter * sec_per_day - - ediag%err_liveveg = ibal%iflux_liveveg - ibal%state_liveveg - - !print*, ediag%err_liveveg!, ediag%err_liveveg/ibal%state_liveveg, ibal%state_liveveg, net_uptake, tot_litter_input - - ! Perform the comparison between integrated flux and state - !if(abs(ediag%err_liveveg) > iflux_tol(el) ) then - ! write(fates_log(),*) 'The fluxes in to an out of live vegetation are integrated' - ! write(fates_log(),*) 'in time over the length of the FATES simulation.' - ! write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' - ! write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' - ! write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' - ! write(fates_log(),*) 'state_liveveg: ',ibal%state_liveveg - ! write(fates_log(),*) 'iflux_liveveg: ',ibal%iflux_liveveg - ! write(fates_log(),*) 'state - iflux: ',ibal%state_liveveg - & - ! ibal%iflux_liveveg - ! call endrun(msg=errMsg(sourcefile, __LINE__)) - !end if - - !if(abs(ibal%state_litter - ibal%iflux_litter) > iflux_tol(el) ) then - ! write(fates_log(),*) 'The fluxes in to an out of litter are integrated' - ! write(fates_log(),*) 'in time over the length of the FATES simulation.' - ! write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' - ! write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' - ! write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' - ! write(fates_log(),*) 'state_litter: ',ibal%state_litter - ! write(fates_log(),*) 'iflux_litter: ',ibal%iflux_litter - ! write(fates_log(),*) 'state - iflux: ',ibal%state_litter - & - ! ibal%iflux_litter - ! call endrun(msg=errMsg(sourcefile, __LINE__)) - !end if - - - end associate - end do - !end do + ! For carbon balance checks, we need to initialize the + ! total carbon stock + do el=1,num_elements + call SiteMassStock(site,el,total_stock, & + biomass_stock,litter_stock,seed_stock) + + associate(ibal => site%iflux_balance(el), & + ediag => site%flux_diags%elem(el), & + diag => site%flux_diags, & + site_mass => site%mass_balance(el)) + + ! Initialize the integrated flux balance diagnostics + ! No need to initialize the instantaneous states, those are re-calculated + + ibal%state_liveveg = (biomass_stock + seed_stock)*area_inv + ibal%state_litter = litter_stock * area_inv + + ! Flux for live veg: net uptake (either NPP or net nutrient uptake) + + ! net spatial seed flux - + ! veg turnover to litter - + ! veg loss to fire (SEEDS DONT BURN) - + ! veg loss from exported harvest - + ! seed turnover + + tot_litter_input = (sum(ediag%leaf_litter_input(:)) + & + sum(ediag%root_litter_input(:)) + & + sum(ediag%cwd_ag_input(:)) + & + sum(ediag%cwd_bg_input(:)))*area_inv + + select case(element_list(el)) + case(carbon12_element) + net_uptake = diag%npp + site_mass%net_root_uptake*area_inv + case(nitrogen_element) + net_uptake = site_mass%net_root_uptake*area_inv + case(phosphorus_element) + net_uptake = site_mass%net_root_uptake*area_inv + case default + write(fates_log(),*) 'FATES: Invalid choice for cohort_fusion_conservation_method' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + ! Fluxes are in [kg/m2/day] so they can be added, + ! the frequency is /day so no conversion necessary + ! to integrate to [kg/m2] + ibal%iflux_liveveg = ibal%iflux_liveveg + & + ( net_uptake & + - tot_litter_input & + - ediag%burned_liveveg & + - ediag%exported_harvest & + + site_mass%seed_in*area_inv & + - ediag%tot_seed_turnover) + + ! Flux for litter: veg turnover + seed turnover - "these are tot_litter_input" + ! fragmentation - + ! burned litter + + ibal%iflux_litter = ibal%iflux_litter + & + tot_litter_input - & + site_mass%frag_out*area_inv - & + (site_mass%burn_flux_to_atm*area_inv - ediag%burned_liveveg) + + + ediag%err_liveveg = ibal%iflux_liveveg - ibal%state_liveveg + + ediag%err_litter = ibal%iflux_litter - ibal%state_litter + + + + !print*, ediag%err_liveveg!, ediag%err_liveveg/ibal%state_liveveg, ibal%state_liveveg, net_uptake, tot_litter_input + + ! Perform the comparison between integrated flux and state + !if(abs(ediag%err_liveveg) > iflux_tol(el) ) then + ! write(fates_log(),*) 'The fluxes in to an out of live vegetation are integrated' + ! write(fates_log(),*) 'in time over the length of the FATES simulation.' + ! write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' + ! write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' + ! write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' + ! write(fates_log(),*) 'state_liveveg: ',ibal%state_liveveg + ! write(fates_log(),*) 'iflux_liveveg: ',ibal%iflux_liveveg + ! write(fates_log(),*) 'state - iflux: ',ibal%state_liveveg - & + ! ibal%iflux_liveveg + ! call endrun(msg=errMsg(sourcefile, __LINE__)) + !end if + + !if(abs(ibal%state_litter - ibal%iflux_litter) > iflux_tol(el) ) then + ! write(fates_log(),*) 'The fluxes in to an out of litter are integrated' + ! write(fates_log(),*) 'in time over the length of the FATES simulation.' + ! write(fates_log(),*) 'This integrated quantity is compared with the instantaneous' + ! write(fates_log(),*) 'assessment of the total mass, they should be the same quanitity' + ! write(fates_log(),*) 'within a tolerance, but there is a discrepancy.' + ! write(fates_log(),*) 'state_litter: ',ibal%state_litter + ! write(fates_log(),*) 'iflux_litter: ',ibal%iflux_litter + ! write(fates_log(),*) 'state - iflux: ',ibal%state_litter - & + ! ibal%iflux_litter + ! call endrun(msg=errMsg(sourcefile, __LINE__)) + !end if + + + end associate + end do + end if return end subroutine CheckIntegratedMassPools - + end module ChecksBalancesMod diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 8907bb5ffb..a199be0c45 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -174,12 +174,11 @@ module EDTypesMod real(r8) :: tot_seed_turnover ! decay of living seed bank to ! fragmented litter [kg/m2/day] real(r8) :: exported_harvest ! mass of harvested vegetation exported and not sent to litter [kg/m2/day] - + real(r8) :: burned_liveveg ! Amount of mass burned from living plants [kg/m2/day] real(r8) :: err_liveveg ! Error from comparing [state-integrated flux] ! in live vegetation [kg/m2] - real(r8) :: err_litter ! Net change in litter [kg/m2] - real(r8) :: burned_liveveg ! Amount of mass burned from living plants [kg/m2/day] + end type elem_diag_type @@ -571,7 +570,7 @@ subroutine ZeroFluxDiags(this) this%elem(el)%exported_harvest = 0._r8 this%elem(el)%err_liveveg = 0._r8 this%elem(el)%err_litter = 0._r8 - this%elem(el)%burned_liveveg = 0._r8 + end do this%npp = 0._r8 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 8421db4e94..801f3ae15c 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -396,6 +396,7 @@ module FatesHistoryInterfaceMod integer :: ih_nir_rad_err_si integer :: ih_fire_c_to_atm_si integer :: ih_interr_liveveg_elem + integer :: ih_interr_litter_elem integer :: ih_cbal_err_fates_si integer :: ih_err_fates_elem @@ -3283,7 +3284,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_nplant_understory_si_scag => this%hvars(ih_nplant_understory_si_scag)%r82d, & hio_disturbance_rate_si_lulu => this%hvars(ih_disturbance_rate_si_lulu)%r82d, & hio_cstarvmortality_continuous_carbonflux_si_pft => this%hvars(ih_cstarvmortality_continuous_carbonflux_si_pft)%r82d, & - hio_interr_liveveg_elem => this%hvars(ih_interr_liveveg_elem)%r82d) + hio_interr_liveveg_elem => this%hvars(ih_interr_liveveg_elem)%r82d, & + hio_interr_litter_elem => this%hvars(ih_interr_litter_elem)%r82d) model_day_int = nint(hlm_model_day) @@ -3327,7 +3329,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_err_fates_elem(io_si,el) = sites(s)%mass_balance(el)%err_fates / sec_per_day hio_interr_liveveg_elem(io_si,el) = sites(s)%flux_diags%elem(el)%err_liveveg - + + hio_interr_litter_elem(io_si,el) = sites(s)%flux_diags%elem(el)%err_litter ! Total element lost to atmosphere from burning (kg/site/day -> kg/m2/s) hio_burn_flux_elem(io_si,el) = & @@ -8390,6 +8393,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & index = ih_interr_liveveg_elem) + call this%set_history_var(vname='FATES_INTERR_LITTER_EL',units='kg m-2', & + long='Bias error between integrated flux and (minus) state in litter ', & + use_default='active', avgflag='A', vtype=site_elem_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_interr_litter_elem) + call this%set_history_var(vname='FATES_LITTER_AG_FINE_EL', units='kg m-2', & long='mass of aboveground litter in fines (leaves, nonviable seed) by element', & use_default='active', avgflag='A', vtype=site_elem_r8, & diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 8fcf0414a3..7f8daefe86 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -270,6 +270,8 @@ module FatesRestartInterfaceMod integer :: ir_woodprod_mbal integer :: ir_liveveg_intflux_el integer :: ir_liveveg_err_el + integer :: ir_litter_intflux_el + integer :: ir_litter_err_el integer :: ir_prt_base ! Base index for all PRT variables ! site-level input seed from dispersal @@ -1141,13 +1143,21 @@ subroutine define_restart_vars(this, initialize_variables) long_name_base='total mass of live vegetation of each chemical species, integrated from fluxes', & units='kg/m2', veclength=num_elements, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_liveveg_intflux_el) - call this%RegisterCohortVector(symbol_base='fates_liveveg_err', vtype=site_r8, & long_name_base='total mass error of live vegetation of each chemical species, from integrated fluxes', & units='kg/m2', veclength=num_elements, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_liveveg_err_el) + call this%RegisterCohortVector(symbol_base='fates_litter_intflux', vtype=site_r8, & + long_name_base='total mass of litter of each chemical species, integrated from fluxes', & + units='kg/m2', veclength=num_elements, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_litter_intflux_el) + + call this%RegisterCohortVector(symbol_base='fates_litter_err', vtype=site_r8, & + long_name_base='total mass error of litter of each chemical species, from integrated fluxes', & + units='kg/m2', veclength=num_elements, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_litter_err_el) end if @@ -2288,6 +2298,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) this%rvars(ir_liveveg_intflux_el+el-1)%r81d(io_idx_si) = sites(s)%iflux_balance(el)%iflux_liveveg this%rvars(ir_liveveg_err_el+el-1)%r81d(io_idx_si) = sites(s)%flux_diags%elem(el)%err_liveveg + + this%rvars(ir_litter_intflux_el+el-1)%r81d(io_idx_si) = sites(s)%iflux_balance(el)%iflux_litter + this%rvars(ir_litter_err_el+el-1)%r81d(io_idx_si) = sites(s)%flux_diags%elem(el)%err_litter end do end if @@ -3257,6 +3270,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%iflux_balance(el)%iflux_liveveg = this%rvars(ir_liveveg_intflux_el+el-1)%r81d(io_idx_si) sites(s)%flux_diags%elem(el)%err_liveveg = this%rvars(ir_liveveg_err_el+el-1)%r81d(io_idx_si) + + sites(s)%iflux_balance(el)%iflux_litter = this%rvars(ir_litter_intflux_el+el-1)%r81d(io_idx_si) + sites(s)%flux_diags%elem(el)%err_litter = this%rvars(ir_litter_err_el+el-1)%r81d(io_idx_si) end do end if From c75423da5d3d2aadf8722706f3076ac06b98d3aa Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 1 Jul 2024 18:50:26 -0400 Subject: [PATCH 18/26] minor comment updates --- main/EDTypesMod.F90 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index a199be0c45..e4be2193fb 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -155,15 +155,11 @@ module EDTypesMod ! file after number densities of plants have changed. They also ! allow the history flux diagnostics to be rebuilt during restart ! - ! ! Litter fluxes are the total from ! (1) turnover from living plants ! (2) mass transfer from non-disturbance inducing mortality events ! (3) mass transfer from disturbance inducing mortality events ! [kg / ha / day] - ! - ! - ! ! --------------------------------------------------------------------------------- real(r8) :: cwd_ag_input(1:ncwd) @@ -175,6 +171,9 @@ module EDTypesMod ! fragmented litter [kg/m2/day] real(r8) :: exported_harvest ! mass of harvested vegetation exported and not sent to litter [kg/m2/day] real(r8) :: burned_liveveg ! Amount of mass burned from living plants [kg/m2/day] + + ! Integrated Error Terms ( Int. Flux - State ) + real(r8) :: err_liveveg ! Error from comparing [state-integrated flux] ! in live vegetation [kg/m2] real(r8) :: err_litter ! Net change in litter [kg/m2] @@ -229,7 +228,9 @@ module EDTypesMod ! Nutrient Flux Diagnostics - real(r8) :: resp_excess + real(r8) :: resp_excess ! plant carbon respired due to carbon overflow + ! this happens when nutrients are limiting construction + ! of new tissues kg m-2 s-1 real(r8) :: nh4_uptake ! plant nh4 uptake, kg m-2 s-1 real(r8) :: no3_uptake ! plant no3 uptake, kg m-2 s-1 real(r8) :: sym_nfix ! plant N uptake via symbiotic fixation kg m-2 s-1 From 84cc2060f80f71ef3c57509b9144ac83697afab5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 2 Jul 2024 10:36:41 -0400 Subject: [PATCH 19/26] updated some time integrated flux terms --- biogeochem/EDPhysiologyMod.F90 | 2 +- main/ChecksBalancesMod.F90 | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 6f6eb626ac..4c24c91ab9 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2143,7 +2143,7 @@ subroutine SeedUpdate( currentSite ) ! Seed input from local sources (within site). Note that a fraction of the ! internal seed rain is sent out to neighboring gridcells. - litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1-site_disp_frac(pft))/area ![kg/m2/day] + litt%seed_in_local(pft) = litt%seed_in_local(pft) + site_seed_rain(pft)*(1.0_r8-site_disp_frac(pft))/area ![kg/m2/day] ! If we are using the Tree Recruitment Scheme (TRS) with or w/o seedling dynamics if ( any(regeneration_model == [TRS_regeneration, TRS_no_seedling_dyn]) .and. & diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 981073b40e..7db2cd9ae3 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -314,7 +314,8 @@ subroutine CheckIntegratedMassPools(site) - tot_litter_input & - ediag%burned_liveveg & - ediag%exported_harvest & - + site_mass%seed_in*area_inv & + + site_mass%seed_in*area_inv & + - site_mass%seed_out*area_inv & - ediag%tot_seed_turnover) ! Flux for litter: veg turnover + seed turnover - "these are tot_litter_input" @@ -323,7 +324,7 @@ subroutine CheckIntegratedMassPools(site) ibal%iflux_litter = ibal%iflux_litter + & tot_litter_input - & - site_mass%frag_out*area_inv - & + (site_mass%frag_out*area_inv - ediag%tot_seed_turnover) - & (site_mass%burn_flux_to_atm*area_inv - ediag%burned_liveveg) From ea654d6f59e0522dc837f5820359049a95164054 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 3 Jul 2024 12:48:19 -0400 Subject: [PATCH 20/26] moved itegrated flux check later in call sequence so that termination fluxes are accounted for --- main/EDMainMod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 46d4d93a4f..ffddb14f5f 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -310,8 +310,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) ! Final instantaneous mass balance check call TotalBalanceCheck(currentSite,5) - ! Check to see if the time integrated fluxes match the state - call CheckIntegratedMassPools(currentSite) + end subroutine ed_ecosystem_dynamics @@ -827,6 +826,9 @@ subroutine ed_update_site( currentSite, bc_in, bc_out, is_restarting ) currentPatch => currentPatch%younger enddo + + ! Check to see if the time integrated fluxes match the state + call CheckIntegratedMassPools(currentSite) ! The HLMs need to know about nutrient demand, and/or ! root mass and affinities From 9f85668ec75781c82f7787da4316b56f9fa5c24b Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 17 Oct 2024 10:54:49 -0400 Subject: [PATCH 21/26] renamed flux diagnostic --- biogeochem/EDCohortDynamicsMod.F90 | 4 ++-- biogeochem/EDLoggingMortalityMod.F90 | 2 +- biogeochem/EDPatchDynamicsMod.F90 | 10 +++++----- biogeochem/EDPhysiologyMod.F90 | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index c77b495731..39929612e3 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -693,8 +693,8 @@ subroutine SendCohortToLitter(csite,cpatch,ccohort,nplant,bc_in) end do - elflux_diags%leaf_litter_input(pft) = & - elflux_diags%leaf_litter_input(pft) + & + elflux_diags%surf_fine_litter_input(pft) = & + elflux_diags%surf_fine_litter_input(pft) + & (leaf_m+repro_m) * nplant elflux_diags%root_litter_input(pft) = & elflux_diags%root_litter_input(pft) + & diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 711c89f3ca..6161b9fcd1 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -1026,7 +1026,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site end do ! track as diagnostic fluxes - elflux_diags%leaf_litter_input(pft) = elflux_diags%leaf_litter_input(pft) + & + elflux_diags%surf_fine_litter_input(pft) = elflux_diags%surf_fine_litter_input(pft) + & leaf_litter elflux_diags%root_litter_input(pft) = elflux_diags%root_litter_input(pft) + & diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 982388e3cd..fe25b5c9fa 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1840,8 +1840,8 @@ subroutine fire_litter_fluxes(currentSite, currentPatch, & end do ! Track as diagnostic fluxes - elflux_diags%leaf_litter_input(pft) = & - elflux_diags%leaf_litter_input(pft) + & + elflux_diags%surf_fine_litter_input(pft) = & + elflux_diags%surf_fine_litter_input(pft) + & num_dead_trees * (leaf_m+repro_m) * (1.0_r8-currentCohort%fraction_crown_burned) elflux_diags%root_litter_input(pft) = & @@ -2115,7 +2115,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & elflux_diags%cwd_bg_input(c) + SF_val_CWD_frac_adj(c) * bg_wood end do - elflux_diags%leaf_litter_input(pft) = elflux_diags%leaf_litter_input(pft) + & + elflux_diags%surf_fine_litter_input(pft) = elflux_diags%surf_fine_litter_input(pft) + & num_dead*(leaf_m + repro_m) elflux_diags%root_litter_input(pft) = elflux_diags%root_litter_input(pft) + & @@ -2316,8 +2316,8 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & end do ! Track as diagnostic fluxes - elflux_diags%leaf_litter_input(pft) = & - elflux_diags%leaf_litter_input(pft) + & + elflux_diags%surf_fine_litter_input(pft) = & + elflux_diags%surf_fine_litter_input(pft) + & num_dead_trees * (leaf_m+repro_m) * (1.0_r8-burn_frac_landusetransition) elflux_diags%root_litter_input(pft) = & diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 4c24c91ab9..b8d33d33cb 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -369,8 +369,8 @@ subroutine GenerateDamageAndLitterFluxes( csite, cpatch, bc_in ) ndcohort%n * dcmpy_frac / cpatch%area end do - elflux_diags%leaf_litter_input(ipft) = & - elflux_diags%leaf_litter_input(ipft) + & + elflux_diags%surf_fine_litter_input(ipft) = & + elflux_diags%surf_fine_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) @@ -2888,8 +2888,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) ! about double counting. ! --------------------------------------------------------------------------------- - elflux_diags%leaf_litter_input(pft) = & - elflux_diags%leaf_litter_input(pft) + & + elflux_diags%surf_fine_litter_input(pft) = & + elflux_diags%surf_fine_litter_input(pft) + & (leaf_m_turnover+repro_m_turnover) * currentCohort%n root_fines_tot = (fnrt_m_turnover + store_m_turnover ) * & @@ -2993,8 +2993,8 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) end do end do - elflux_diags%leaf_litter_input(pft) = & - elflux_diags%leaf_litter_input(pft) + & + elflux_diags%surf_fine_litter_input(pft) = & + elflux_diags%surf_fine_litter_input(pft) + & (leaf_m+repro_m) * dead_n*currentPatch%area elflux_diags%root_litter_input(pft) = & From ebfe5a70a5f373a6145e883803074013913bff85 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 17 Oct 2024 10:58:54 -0400 Subject: [PATCH 22/26] Add descriptive comment --- main/ChecksBalancesMod.F90 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 7db2cd9ae3..2807076df4 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -247,7 +247,13 @@ end subroutine CheckLitterPools subroutine CheckIntegratedMassPools(site) - + ! ----------------------------------------------------------------------------------- + ! + ! This subroutine checks that the time integrated net fluxes in and out of + ! the vegetation and the litter actually match the quantity in those pools. + ! + ! ----------------------------------------------------------------------------------- + type(ed_site_type), intent(inout) :: site !integer :: nsites From b1255b9cb7fb09fe5f8ba4b051e35c89d794785d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 17 Oct 2024 11:06:04 -0400 Subject: [PATCH 23/26] added back in p and n demand diagnostics --- main/FatesHistoryInterfaceMod.F90 | 54 +++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 801f3ae15c..deb604ed55 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -282,7 +282,11 @@ module FatesHistoryInterfaceMod integer :: ih_pefflux_scpf integer :: ih_nfix_si integer :: ih_nfix_scpf - + integer :: ih_ndemand_si + integer :: ih_ndemand_scpf + integer :: ih_pdemand_si + integer :: ih_pdemand_scpf + integer :: ih_trimming_si integer :: ih_area_plant_si integer :: ih_area_trees_si @@ -2176,6 +2180,11 @@ subroutine update_history_nutrflux(this,csite) this%hvars(ih_nefflux_si)%r81d(io_si) + & ccohort%daily_n_efflux*uconv + ! Demand + this%hvars(ih_ndemand_si)%r81d(io_si) = & + this%hvars(ih_ndemand_si)%r81d(io_si) + & + ccohort%daily_n_demand*uconv + case (phosphorus_element) ! Mineralized uptake of PO4 @@ -2188,6 +2197,11 @@ subroutine update_history_nutrflux(this,csite) this%hvars(ih_pefflux_si)%r81d(io_si) + & ccohort%daily_p_efflux*uconv + ! Demand + this%hvars(ih_pdemand_si)%r81d(io_si) = & + this%hvars(ih_pdemand_si)%r81d(io_si) + & + ccohort%daily_p_demand*uconv + end select end do @@ -2256,6 +2270,11 @@ subroutine update_history_nutrflux(this,csite) this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) + & ccohort%daily_n_efflux*uconv + ! Demand + this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_ndemand_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_n_demand*uconv + case (phosphorus_element) ! Mineralized uptake of PO4 @@ -2267,7 +2286,12 @@ subroutine update_history_nutrflux(this,csite) this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) = & this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) + & ccohort%daily_p_efflux*uconv - + + ! Demand + this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) = & + this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_p_demand*uconv + end select end do @@ -6422,6 +6446,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_nefflux_si) + call this%set_history_var(vname='FATES_NDEMAND', units='kg m-2 s-1', & + long='plant nitrogen need (algorithm dependent) in kg N per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_ndemand_si) + call this%set_history_var(vname='FATES_NFIX_SYM', units='kg m-2 s-1', & long='symbiotic dinitrogen fixation in kg N per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -6519,6 +6549,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_pefflux_si) + call this%set_history_var(vname='FATES_PDEMAND', units='kg m-2 s-1', & + long='plant phosphorus need (algorithm dependent) in kg P per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_pdemand_si) + end if phosphorus_active_if0 call this%set_history_var(vname='FATES_STRUCTC', units='kg m-2', & @@ -7150,6 +7186,12 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & initialize=initialize_variables, index = ih_nefflux_scpf) + call this%set_history_var(vname='FATES_NDEMAND_SZPF', units='kg m-2 s-1', & + long='plant N need (algorithm dependent), by size-class x pft in kg N per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ndemand_scpf) + call this%set_history_var(vname='FATES_NFIX_SYM_SZPF', units='kg m-2 s-1', & long='symbiotic dinitrogen fixation, by size-class x pft in kg N per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & @@ -7274,7 +7316,13 @@ subroutine define_history_vars(this, initialize_variables) use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & initialize=initialize_variables, index = ih_pefflux_scpf) - + + call this%set_history_var(vname='FATES_PDEMAND_SZPF', units='kg m-2 s-1', & + long='plant P need (algorithm dependent), by size-class x pft in kg P per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_pdemand_scpf) + end if phosphorus_active_if1 call this%set_history_var(vname='FATES_CROWNAREA_CLLL', units='m2 m-2', & From b4390fe7944ec10f8a05f863043fbd2028fe68b5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 17 Oct 2024 11:14:16 -0400 Subject: [PATCH 24/26] fixed comment --- main/ChecksBalancesMod.F90 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 2807076df4..2c4f1ac97a 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -308,7 +308,7 @@ subroutine CheckIntegratedMassPools(site) case(phosphorus_element) net_uptake = site_mass%net_root_uptake*area_inv case default - write(fates_log(),*) 'FATES: Invalid choice for cohort_fusion_conservation_method' + write(fates_log(),*) 'FATES: an invalid chemical species was detected' call endrun(msg=errMsg(sourcefile, __LINE__)) end select @@ -339,9 +339,6 @@ subroutine CheckIntegratedMassPools(site) ediag%err_litter = ibal%iflux_litter - ibal%state_litter - - !print*, ediag%err_liveveg!, ediag%err_liveveg/ibal%state_liveveg, ibal%state_liveveg, net_uptake, tot_litter_input - ! Perform the comparison between integrated flux and state !if(abs(ediag%err_liveveg) > iflux_tol(el) ) then ! write(fates_log(),*) 'The fluxes in to an out of live vegetation are integrated' From 28680e589a556a8c99bed32c3294a6a5ddf6df8d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 17 Oct 2024 11:50:12 -0400 Subject: [PATCH 25/26] converted leaf_litter_input to surf_fine_litter_input --- main/ChecksBalancesMod.F90 | 2 +- main/EDInitMod.F90 | 2 +- main/EDTypesMod.F90 | 4 ++-- main/FatesHistoryInterfaceMod.F90 | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/main/ChecksBalancesMod.F90 b/main/ChecksBalancesMod.F90 index 2c4f1ac97a..325a1089e8 100644 --- a/main/ChecksBalancesMod.F90 +++ b/main/ChecksBalancesMod.F90 @@ -295,7 +295,7 @@ subroutine CheckIntegratedMassPools(site) ! veg loss from exported harvest - ! seed turnover - tot_litter_input = (sum(ediag%leaf_litter_input(:)) + & + tot_litter_input = (sum(ediag%surf_fine_litter_input(:)) + & sum(ediag%root_litter_input(:)) + & sum(ediag%cwd_ag_input(:)) + & sum(ediag%cwd_bg_input(:)))*area_inv diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 0184c1a3b8..d529a0e123 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -214,7 +214,7 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) ! ----------------------------------------------------------------------- allocate(site_in%flux_diags%elem(1:num_elements)) do el=1,num_elements - allocate(site_in%flux_diags%elem(el)%leaf_litter_input(1:numpft)) + allocate(site_in%flux_diags%elem(el)%surf_fine_litter_input(1:numpft)) allocate(site_in%flux_diags%elem(el)%root_litter_input(1:numpft)) end do allocate(site_in%flux_diags%nh4_uptake_scpf(numpft*nlevsclass)) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index a5adc91987..61878db1ef 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -168,7 +168,7 @@ module EDTypesMod real(r8) :: cwd_ag_input(1:ncwd) real(r8) :: cwd_bg_input(1:ncwd) - real(r8),allocatable :: leaf_litter_input(:) + real(r8),allocatable :: surf_fine_litter_input(:) real(r8),allocatable :: root_litter_input(:) real(r8) :: tot_seed_turnover ! decay of living seed bank to @@ -583,7 +583,7 @@ subroutine ZeroFluxDiags(this) do el = 1,num_elements this%elem(el)%cwd_ag_input(:) = 0._r8 this%elem(el)%cwd_bg_input(:) = 0._r8 - this%elem(el)%leaf_litter_input(:) = 0._r8 + this%elem(el)%surf_fine_litter_input(:) = 0._r8 this%elem(el)%root_litter_input(:) = 0._r8 this%elem(el)%burned_liveveg = 0._r8 this%elem(el)%tot_seed_turnover = 0._r8 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c6d0efbc72..0751b06b90 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2621,7 +2621,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_litter_in_si(io_si) = (sum(elflux_diags_c%cwd_ag_input(:)) + & sum(elflux_diags_c%cwd_bg_input(:)) + & - sum(elflux_diags_c%leaf_litter_input(:)) + & + sum(elflux_diags_c%surf_fine_litter_input(:)) + & sum(elflux_diags_c%root_litter_input(:))) * & AREA_INV * days_per_sec @@ -4609,7 +4609,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! Sum up all input litter fluxes (above below, fines, cwd) [kg/ha/day] hio_litter_in_elem(io_si, el) = (sum(elflux_diags%cwd_ag_input(:)) + & - sum(elflux_diags%cwd_bg_input(:)) + sum(elflux_diags%leaf_litter_input(:)) + & + sum(elflux_diags%cwd_bg_input(:)) + sum(elflux_diags%surf_fine_litter_input(:)) + & sum(elflux_diags%root_litter_input(:))) / m2_per_ha / sec_per_day From c83473d7745afc57949c803ef431130f66315258 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 17 Oct 2024 18:34:39 -0600 Subject: [PATCH 26/26] fixed typo in history interface --- main/FatesHistoryInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 0751b06b90..739ea30503 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3316,7 +3316,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_disturbance_rate_si_lulu => this%hvars(ih_disturbance_rate_si_lulu)%r82d, & hio_cstarvmortality_continuous_carbonflux_si_pft => this%hvars(ih_cstarvmortality_continuous_carbonflux_si_pft)%r82d, & hio_interr_liveveg_elem => this%hvars(ih_interr_liveveg_elem)%r82d, & - hio_interr_litter_elem => this%hvars(ih_interr_litter_elem)%r82d) + hio_interr_litter_elem => this%hvars(ih_interr_litter_elem)%r82d, & hio_transition_matrix_si_lulu => this%hvars(ih_transition_matrix_si_lulu)%r82d)